diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..59d79bd --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,37 @@ +## The Basics + +Thanks for making a pull request! Before making a pull request, we have some +things for you to read through first: + +- We generally do not accept patches for formatting fixes, unless the formatting + fixes are part of a functional patch (for example, when fixing a bug in a + function you can fix up the lines surrounding it if needed). +- Patches that break compatibility with the original game data or save data will + not be accepted. +- New features and user interface changes will most likely not be accepted + unless they are for improving user accessibility. +- New platforms are acceptable if they use FNA and don't mess with the game + source too much. + - (No homebrew console targets, sorry! Maybe do the work in SDL instead?) +- Translations and localizations of the game are not a community effort. If you + want to translate the game, you should contact Cellar Door Games. +- Pull requests that do not fill out the Legal Stuff will be closed + automatically. + +If you understand these notes, you can delete the text in this section. Pull +requests that still have this text will be closed automatically. + + +## Changes: + +Describe your patch here! + + +## Legal Stuff: + +By submitting this pull request, I confirm that... + +- [ ] My changes may be used in a future commercial release of Rogue Legacy +- [ ] I will be credited in a `CONTRIBUTORS` file and the "GitHub Friends" + section of the credits for all of said releases, but will NOT be compensated + for these changes unless there is a prior written agreement diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..841c196 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,25 @@ +name: CI + +on: [push, pull_request] + +jobs: + linux: + name: Linux + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: true + + - name: Clone FNA + run: | + git clone --recursive https://github.com/FNA-XNA/FNA.git + mv FNA ../FNA + + - name: dotnet build (Debug) + run: | + dotnet build -c Debug + + - name: dotnet build (Release) + run: | + dotnet build -c Release diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..59bee9d --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +bin/ +obj/ +obj_core/ +*.pidb +*.user +*.userprefs +*.suo +*.vs diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..9c753c8 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch", + "type": "mono", + "request": "launch", + "program": "${workspaceRoot}/RogueCastle/bin/x64/Debug/net40/RogueLegacy.exe", + "cwd": "${workspaceRoot}/RogueCastle/bin/x64/Debug/net40/", + "env": { + "LD_LIBRARY_PATH": "${workspaceRoot}/fnalibs3/lib64/" + } + }, + { + "name": "Attach", + "type": "mono", + "request": "attach", + "address": "localhost", + "port": 55555 + } + ] +} diff --git a/DS2DEngine/DS2DEngine.csproj b/DS2DEngine/DS2DEngine.csproj new file mode 100644 index 0000000..3f54192 --- /dev/null +++ b/DS2DEngine/DS2DEngine.csproj @@ -0,0 +1,26 @@ + + + + Library + net40 + + + + + {4EFA1C2F-A065-4520-A8AC-A71EA1751C54} + InputSystem + + + {92C40872-2B5C-4894-AABB-602547E1DFC3} + SpriteSystem + + + {D9583122-AC6D-41EB-8292-04BDD0519D7C} + Tweener + + + {35253CE1-C864-4CD3-8249-4D1319748E8F} + FNA + + + diff --git a/DS2DEngine/src/AI Logic/Actions/ChangePropertyLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/ChangePropertyLogicAction.cs new file mode 100644 index 0000000..f238ccd --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/ChangePropertyLogicAction.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; + +namespace DS2DEngine +{ + public class ChangePropertyLogicAction : LogicAction + { + private string m_propertyName; + private object m_propertyArg; + private object m_object; + + public ChangePropertyLogicAction(object propertyObject, string propertyName, object propertyArg) + { + m_object = propertyObject; + m_propertyName = propertyName; + m_propertyArg = propertyArg; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive) + { + PropertyInfo propertyInfo = m_object.GetType().GetProperty(m_propertyName); + propertyInfo.SetValue(m_object, m_propertyArg, null); + base.Execute(); + } + } + + public override object Clone() + { + return new ChangePropertyLogicAction(m_object, m_propertyName, m_propertyArg); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + m_propertyArg = null; + m_object = null; + base.Dispose(); + } + } + } +} diff --git a/DS2DEngine/src/AI Logic/Actions/ChangeSpriteLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/ChangeSpriteLogicAction.cs new file mode 100644 index 0000000..a67e6f4 --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/ChangeSpriteLogicAction.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Tweener; +using Tweener.Ease; + +namespace DS2DEngine +{ + public class ChangeSpriteLogicAction : LogicAction + { + private string m_spriteName; + private bool m_playAnimation; + private bool m_loopAnimation; + + //private TweenObject m_tweenDelay; + //private BlankObj m_blankObj; // Storing the blank object so that we can dispose it properly later. + private IAnimateableObj m_animateableObj; + + public ChangeSpriteLogicAction(string spriteName, bool playAnimation = true, bool loopAnimation = true) + { + m_spriteName = spriteName; + m_playAnimation = playAnimation; + m_loopAnimation = loopAnimation; + //m_blankObj = new BlankObj(1, 1); + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + m_animateableObj = this.ParentLogicSet.ParentGameObj as IAnimateableObj; + if (m_animateableObj != null && (m_animateableObj.SpriteName != m_spriteName || m_animateableObj.IsAnimating == false)) + { + this.ParentLogicSet.ParentGameObj.ChangeSprite(m_spriteName); + if (m_playAnimation == true) + { + m_animateableObj.PlayAnimation(m_loopAnimation); + //if (SequenceType == Types.Sequence.Serial && animateableObj.IsLooping == false) + //{ + // m_tweenDelay = Tween.To(m_blankObj, animateableObj.TotalFrames, Linear.EaseNone, "X", "1"); + // m_tweenDelay.UseTicks = true; + //} + } + } + base.Execute(); + } + } + + public override void Update(Microsoft.Xna.Framework.GameTime gameTime) + { + this.ExecuteNext(); + base.Update(gameTime); + } + + public override void ExecuteNext() + { + if (m_playAnimation == false || m_loopAnimation == true || (m_animateableObj != null && SequenceType == Types.Sequence.Serial && m_animateableObj.IsLooping == false && m_animateableObj.IsAnimating == false)) + { + base.ExecuteNext(); + } + } + + //public override void ExecuteNext() + //{ + // if (m_tweenDelay != null) + // { + // if (NextLogicAction != null) + // m_tweenDelay.EndHandler(NextLogicAction, "Execute"); + // else + // m_tweenDelay.EndHandler(ParentLogicSet, "ExecuteComplete"); + // } + // else + // base.ExecuteNext(); + //} + + public override void Stop() + { + // Okay. Big problem with delay tweens. Because logic actions are never disposed in-level (due to garbage collection concerns) the reference to the delay tween in this logic action will exist until it is + // disposed, EVEN if the tween completes. If the tween completes, it goes back into the pool, and then something else will call it, but this logic action's delay tween reference will still be pointing to it. + // This becomes a HUGE problem if this logic action's Stop() method is called, because it will then stop the tween that this tween reference is pointing to. + // The solution is to comment out the code below. This means that this tween reference will always call it's endhandler, which in this case is either Execute() or ExecuteComplete(). This turns out + // to not be a problem, because when a logic set is called to stop, its IsActive flag is set to false, and all Execute() methods in logic actions have to have their parent logic set's IsActive flag to true + // in order to run. Therefore, when the tween calls Execute() or ExecuteComplete() nothing will happen. + // - This bug kept you confused for almost 5 hours. DO NOT FORGET IT. That is what this long explanation is for. + // TL;DR - DO NOT UNCOMMENT THE CODE BELOW OR LOGIC SETS BREAK. + + //if (m_tweenDelay != null) + // m_tweenDelay.StopTween(false); + + IAnimateableObj obj = this.ParentLogicSet.ParentGameObj as IAnimateableObj; + if (obj != null) + obj.StopAnimation(); + base.Stop(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // See above for explanation. + //if (m_tweenDelay != null) + // m_tweenDelay.StopTween(false); + + //m_tweenDelay = null; + //m_blankObj.Dispose(); + //m_blankObj = null; + m_animateableObj = null; + + base.Dispose(); + } + } + + public override object Clone() + { + return new ChangeSpriteLogicAction(m_spriteName, m_playAnimation, m_loopAnimation); + } + } +} diff --git a/DS2DEngine/src/AI Logic/Actions/ChangeStateLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/ChangeStateLogicAction.cs new file mode 100644 index 0000000..4cf4ab2 --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/ChangeStateLogicAction.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public class ChangeStateLogicAction : LogicAction + { + private int m_state; + + public ChangeStateLogicAction(int state) + { + m_state = state; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + if (ParentLogicSet.ParentGameObj is IStateObj) + (ParentLogicSet.ParentGameObj as IStateObj).State = m_state; + base.Execute(); + } + } + + public override object Clone() + { + return new ChangeStateLogicAction(m_state); + } + + public override void Dispose() + { + if (IsDisposed == false) + base.Dispose(); + } + } +} diff --git a/DS2DEngine/src/AI Logic/Actions/ChangeWeightLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/ChangeWeightLogicAction.cs new file mode 100644 index 0000000..a5193a7 --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/ChangeWeightLogicAction.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public class ChangeWeightLogicAction : LogicAction + { + private bool m_isWeighted = false; + + public ChangeWeightLogicAction(bool isWeighted) + { + m_isWeighted = isWeighted; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + IPhysicsObj physicsObj = ParentLogicSet.ParentGameObj as IPhysicsObj; + if (physicsObj != null) + physicsObj.IsWeighted = m_isWeighted; + base.Execute(); + } + } + + public override object Clone() + { + return new ChangeWeightLogicAction(m_isWeighted); + } + } +} diff --git a/DS2DEngine/src/AI Logic/Actions/ChaseLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/ChaseLogicAction.cs new file mode 100644 index 0000000..fe1e886 --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/ChaseLogicAction.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public class ChaseLogicAction : LogicAction + { + private bool m_moveTowards; + private GameObj m_target; + private float m_speed; + private float m_duration; + private float m_durationCounter; + private Vector2 m_minRelativePos = Vector2.Zero; + private Vector2 m_maxRelativePos = Vector2.Zero; + private Vector2 m_storedRelativePos; + + //To stop an object from moving, call this method and set overrideSpeed to 0. + public ChaseLogicAction(GameObj target, bool moveTowards, float duration, float overrideSpeed = -1) + { + m_moveTowards = moveTowards; + m_target = target; + m_speed = overrideSpeed; + m_duration = duration; + } + + public ChaseLogicAction(GameObj target, Vector2 minRelativePos, Vector2 maxRelativePos, bool moveTowards, float duration, float overrideSpeed = -1) + { + m_minRelativePos = minRelativePos; + m_maxRelativePos = maxRelativePos; + m_moveTowards = moveTowards; + m_target = target; + m_speed = overrideSpeed; + m_duration = duration; + } + + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + if (m_speed == -1) + m_speed = this.ParentLogicSet.ParentGameObj.Speed; + + this.ParentLogicSet.ParentGameObj.CurrentSpeed = m_speed; + + if (m_target != null) + { + m_durationCounter = m_duration; + + m_storedRelativePos = new Vector2(CDGMath.RandomInt((int)m_minRelativePos.X, (int)m_maxRelativePos.X), CDGMath.RandomInt((int)m_minRelativePos.Y, (int)m_maxRelativePos.Y)); + + Vector2 seekPosition; + + if (m_moveTowards == true) + seekPosition = m_target.Position + m_storedRelativePos; + else + seekPosition = 1000 * this.ParentLogicSet.ParentGameObj.Position - m_target.Position; + + TurnToFace(seekPosition, this.ParentLogicSet.ParentGameObj.TurnSpeed, 1/60f); + + this.ParentLogicSet.ParentGameObj.HeadingX = (float)Math.Cos(this.ParentLogicSet.ParentGameObj.Orientation); + this.ParentLogicSet.ParentGameObj.HeadingY = (float)Math.Sin(this.ParentLogicSet.ParentGameObj.Orientation); + + if (ParentLogicSet.ParentGameObj.LockFlip == false) + { + if (ParentLogicSet.ParentGameObj.X > m_target.X) + ParentLogicSet.ParentGameObj.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + else + ParentLogicSet.ParentGameObj.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.None; + } + } + base.Execute(); + } + } + + public override void Update(Microsoft.Xna.Framework.GameTime gameTime) + { + float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds; + m_durationCounter -= elapsedSeconds; + if (m_target != null && m_durationCounter > 0) + { + Vector2 seekPosition; + if (m_moveTowards == true) + seekPosition = m_target.Position + m_storedRelativePos; + else + seekPosition = 2 * this.ParentLogicSet.ParentGameObj.Position - m_target.Position; + + TurnToFace(seekPosition, this.ParentLogicSet.ParentGameObj.TurnSpeed, elapsedSeconds); + + this.ParentLogicSet.ParentGameObj.HeadingX = (float)Math.Cos(this.ParentLogicSet.ParentGameObj.Orientation); + this.ParentLogicSet.ParentGameObj.HeadingY = (float)Math.Sin(this.ParentLogicSet.ParentGameObj.Orientation); + + if (ParentLogicSet.ParentGameObj.LockFlip == false) + { + if (ParentLogicSet.ParentGameObj.X > m_target.X) + ParentLogicSet.ParentGameObj.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + else + ParentLogicSet.ParentGameObj.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.None; + } + } + this.ExecuteNext(); + base.Update(gameTime); + } + + public override void ExecuteNext() + { + if (m_durationCounter <= 0) + base.ExecuteNext(); + } + + + public override void Stop() + { + this.ParentLogicSet.ParentGameObj.CurrentSpeed = 0; + base.Stop(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + m_target = null; // This class is not the class that should be disposing the target. + base.Dispose(); + } + } + + public override object Clone() + { + return new ChaseLogicAction(m_target, m_minRelativePos, m_maxRelativePos, m_moveTowards, m_duration, m_speed); + } + + public void TurnToFace(float angle, float turnSpeed, float elapsedSeconds) + { + float desiredAngle = angle; + float difference = MathHelper.WrapAngle(desiredAngle - this.ParentLogicSet.ParentGameObj.Orientation); + + float elapsedTurnSpeed = (turnSpeed * 60) * elapsedSeconds; + + difference = MathHelper.Clamp(difference, -elapsedTurnSpeed, elapsedTurnSpeed); + this.ParentLogicSet.ParentGameObj.Orientation = MathHelper.WrapAngle(this.ParentLogicSet.ParentGameObj.Orientation + difference); + } + + public void TurnToFace(Vector2 facePosition, float turnSpeed, float elapsedSeconds) + { + float x = facePosition.X - this.ParentLogicSet.ParentGameObj.Position.X; + float y = facePosition.Y - this.ParentLogicSet.ParentGameObj.Position.Y; + + float desiredAngle = (float)Math.Atan2(y, x); + float difference = MathHelper.WrapAngle(desiredAngle - this.ParentLogicSet.ParentGameObj.Orientation); + + float elapsedTurnSpeed = (turnSpeed * 60) * elapsedSeconds; + + difference = MathHelper.Clamp(difference, -elapsedTurnSpeed, elapsedTurnSpeed); + this.ParentLogicSet.ParentGameObj.Orientation = MathHelper.WrapAngle(this.ParentLogicSet.ParentGameObj.Orientation + difference); + } + } +} diff --git a/DS2DEngine/src/AI Logic/Actions/DebugTraceLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/DebugTraceLogicAction.cs new file mode 100644 index 0000000..69bb860 --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/DebugTraceLogicAction.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public class DebugTraceLogicAction : LogicAction + { + private string m_debugText; + + public DebugTraceLogicAction(string debugText) + { + m_debugText = debugText; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + Console.WriteLine(m_debugText); + base.Execute(); + } + } + + public override object Clone() + { + return new DebugTraceLogicAction(m_debugText); + } + + public override void Dispose() + { + if (IsDisposed == false) + base.Dispose(); + } + } +} diff --git a/DS2DEngine/src/AI Logic/Actions/DelayLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/DelayLogicAction.cs new file mode 100644 index 0000000..f1d6d37 --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/DelayLogicAction.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Tweener; +using Tweener.Ease; + +namespace DS2DEngine +{ + public class DelayLogicAction : LogicAction + { + private float m_minDelayDuration = 0; + private float m_maxDelayDuration = 0; + private bool m_useTicks; + //private TweenObject m_delayTween; + //private BlankObj m_blankObj; // Storing the blank object so that we can dispose it properly later. + private float m_delayCounter = 0; + + public DelayLogicAction(float delayInSecs, bool useTicks = false) + { + m_minDelayDuration = delayInSecs; + //m_blankObj = new BlankObj(1, 1); + m_useTicks = useTicks; + m_delayCounter = 0; + } + + public DelayLogicAction(float minDelayInSecs, float maxDelayInSecs, bool useTicks = false) + { + m_minDelayDuration = minDelayInSecs; + m_maxDelayDuration = maxDelayInSecs; + //m_blankObj = new BlankObj(1, 1); + m_useTicks = useTicks; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + SequenceType = Types.Sequence.Serial; + + if (m_maxDelayDuration > m_minDelayDuration) + m_minDelayDuration = CDGMath.RandomFloat(m_minDelayDuration, m_maxDelayDuration); + + m_delayCounter = m_minDelayDuration; + base.Execute(); + } + } + + public override void Update(Microsoft.Xna.Framework.GameTime gameTime) + { + m_delayCounter -= (float)gameTime.ElapsedGameTime.TotalSeconds; + this.ExecuteNext(); + base.Update(gameTime); + } + + public override void ExecuteNext() + { + if (m_delayCounter <= 0) + base.ExecuteNext(); + } + + //public override void Execute() + //{ + // if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + // { + // SequenceType = Types.Sequence.Serial; + + // if (m_maxDelayDuration > m_minDelayDuration) + // m_minDelayDuration = CDGMath.RandomFloat(m_minDelayDuration, m_maxDelayDuration); + + // m_delayTween = Tween.To(m_blankObj, m_minDelayDuration, Linear.EaseNone, "X", "1"); + // m_delayTween.UseTicks = m_useTicks; + // base.Execute(); + // } + //} + + //public override void ExecuteNext() + //{ + // if (m_delayTween != null) + // { + // if (NextLogicAction != null) + // m_delayTween.EndHandler(NextLogicAction, "Execute"); + // else + // m_delayTween.EndHandler(ParentLogicSet, "ExecuteComplete"); + // } + // else + // base.ExecuteNext(); + // //base.ExecuteNext(); Must override base.ExecuteNext() entirely. + //} + + public override void Stop() + { + // Okay. Big problem with delay tweens. Because logic actions are never disposed in-level (due to garbage collection concerns) the reference to the delay tween in this logic action will exist until it is + // disposed, EVEN if the tween completes. If the tween completes, it goes back into the pool, and then something else will call it, but this logic action's delay tween reference will still be pointing to it. + // This becomes a HUGE problem if this logic action's Stop() method is called, because it will then stop the tween that this tween reference is pointing to. + // The solution is to comment out the code below. This means that this tween reference will always call it's endhandler, which in this case is either Execute() or ExecuteComplete(). This turns out + // to not be a problem, because when a logic set is called to stop, its IsActive flag is set to false, and all Execute() methods in logic actions have to have their parent logic set's IsActive flag to true + // in order to run. Therefore, when the tween calls Execute() or ExecuteComplete() nothing will happen. + // - This bug kept you confused for almost 5 hours. DO NOT FORGET IT. That is what this long explanation is for. + // TL;DR - DO NOT UNCOMMENT THE CODE BELOW OR LOGIC SETS BREAK. + + //if (m_delayTween != null) + // m_delayTween.StopTween(false); + + base.Stop(); + } + + public override object Clone() + { + return new DelayLogicAction(m_minDelayDuration, m_maxDelayDuration, m_useTicks); + } + + //public override void Dispose() + //{ + // if (IsDisposed == false) + // { + // // See above for explanation. + // //if (m_delayTween != null) + // // m_delayTween.StopTween(false); + + // m_delayTween = null; + // m_blankObj.Dispose(); + // m_blankObj = null; + // base.Dispose(); + // } + //} + } +} diff --git a/DS2DEngine/src/AI Logic/Actions/MoveDirectionLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/MoveDirectionLogicAction.cs new file mode 100644 index 0000000..784f0de --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/MoveDirectionLogicAction.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public class MoveDirectionLogicAction : LogicAction + { + private Vector2 m_direction; + private float m_speed; + private bool m_moveBasedOnFlip = false; + + //To stop an object from moving, call this method and set overrideSpeed to 0. + public MoveDirectionLogicAction(Vector2 direction, float overrideSpeed = -1) + { + m_direction = direction; + m_speed = overrideSpeed; + m_direction.Normalize(); + m_moveBasedOnFlip = false; + } + + // Move an object based on its flip. + public MoveDirectionLogicAction(float overrideSpeed = -1) + { + m_moveBasedOnFlip = true; + m_speed = overrideSpeed; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + if (m_speed == -1) + m_speed = this.ParentLogicSet.ParentGameObj.Speed; + + if (m_moveBasedOnFlip == false) + { + this.ParentLogicSet.ParentGameObj.CurrentSpeed = m_speed; + this.ParentLogicSet.ParentGameObj.Heading = m_direction; + } + else + { + this.ParentLogicSet.ParentGameObj.CurrentSpeed = m_speed; + if (this.ParentLogicSet.ParentGameObj.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.None) + this.ParentLogicSet.ParentGameObj.Heading = new Vector2(1, 0); + else + this.ParentLogicSet.ParentGameObj.Heading = new Vector2(-1, 0); + } + + base.Execute(); + } + /* Vector2 seekPosition; + + if (m_moveTowards == true) + seekPosition = m_target.Position; + else + seekPosition = 2 * this.ParentLogicSet.ParentGameObj.Position - m_target.Position; + + TurnToFace(seekPosition, this.ParentLogicSet.ParentGameObj.TurnSpeed); + + this.ParentLogicSet.ParentGameObj.HeadingX = (float)Math.Cos(this.ParentLogicSet.ParentGameObj.Orientation); + this.ParentLogicSet.ParentGameObj.HeadingY = (float)Math.Sin(this.ParentLogicSet.ParentGameObj.Orientation); + */ + + } + + public override void Stop() + { + this.ParentLogicSet.ParentGameObj.CurrentSpeed = 0; + base.Stop(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + base.Dispose(); + } + } + + public override object Clone() + { + if (m_direction == Vector2.Zero) + return new MoveDirectionLogicAction(m_speed); + return new MoveDirectionLogicAction(m_direction, m_speed); + } + } +} diff --git a/DS2DEngine/src/AI Logic/Actions/MoveLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/MoveLogicAction.cs new file mode 100644 index 0000000..cc71e72 --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/MoveLogicAction.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public class MoveLogicAction : LogicAction + { + private bool m_moveTowards; + private GameObj m_target; + private float m_speed; + + //To stop an object from moving, call this method and set overrideSpeed to 0. + public MoveLogicAction(GameObj target, bool moveTowards, float overrideSpeed = -1) + { + m_moveTowards = moveTowards; + m_target = target; + m_speed = overrideSpeed; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + if (m_speed == -1) + m_speed = this.ParentLogicSet.ParentGameObj.Speed; + + this.ParentLogicSet.ParentGameObj.CurrentSpeed = m_speed; + + if (m_target != null) + { + Vector2 seekPosition; + + if (m_moveTowards == true) + seekPosition = m_target.Position; + else + seekPosition = 2 * this.ParentLogicSet.ParentGameObj.Position - m_target.Position; + + TurnToFace(seekPosition, this.ParentLogicSet.ParentGameObj.TurnSpeed); + + this.ParentLogicSet.ParentGameObj.HeadingX = (float)Math.Cos(this.ParentLogicSet.ParentGameObj.Orientation); + this.ParentLogicSet.ParentGameObj.HeadingY = (float)Math.Sin(this.ParentLogicSet.ParentGameObj.Orientation); + + if (ParentLogicSet.ParentGameObj.LockFlip == false) + { + if (ParentLogicSet.ParentGameObj.X > m_target.X) + ParentLogicSet.ParentGameObj.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + else + ParentLogicSet.ParentGameObj.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.None; + } + } + base.Execute(); + } + } + + public override void Stop() + { + this.ParentLogicSet.ParentGameObj.CurrentSpeed = 0; + base.Stop(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + m_target = null; // This class is not the class that should be disposing the target. + base.Dispose(); + } + } + + public override object Clone() + { + return new MoveLogicAction(m_target, m_moveTowards, m_speed); + } + + public void TurnToFace(float angle, float turnSpeed) + { + float desiredAngle = angle; + float difference = MathHelper.WrapAngle(desiredAngle - this.ParentLogicSet.ParentGameObj.Orientation); + + difference = MathHelper.Clamp(difference, -turnSpeed, turnSpeed); + this.ParentLogicSet.ParentGameObj.Orientation = MathHelper.WrapAngle(this.ParentLogicSet.ParentGameObj.Orientation + difference); + } + + public void TurnToFace(Vector2 facePosition, float turnSpeed) + { + float x = facePosition.X - this.ParentLogicSet.ParentGameObj.Position.X; + float y = facePosition.Y - this.ParentLogicSet.ParentGameObj.Position.Y; + + float desiredAngle = (float)Math.Atan2(y, x); + float difference = MathHelper.WrapAngle(desiredAngle - this.ParentLogicSet.ParentGameObj.Orientation); + + difference = MathHelper.Clamp(difference, -turnSpeed, turnSpeed); + this.ParentLogicSet.ParentGameObj.Orientation = MathHelper.WrapAngle(this.ParentLogicSet.ParentGameObj.Orientation + difference); + } + } +} diff --git a/DS2DEngine/src/AI Logic/Actions/Play3DSoundLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/Play3DSoundLogicAction.cs new file mode 100644 index 0000000..d2fa913 --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/Play3DSoundLogicAction.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public class Play3DSoundLogicAction : LogicAction + { + private string[] m_sounds; + private GameObj m_listener; + private GameObj m_emitter; + + public Play3DSoundLogicAction(GameObj emitter, GameObj listener, params string[] sounds) + { + m_sounds = sounds; + m_emitter = emitter; + m_listener = listener; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + SoundManager.Play3DSound(m_emitter, m_listener, m_sounds); + base.Execute(); + } + } + + public override object Clone() + { + return new Play3DSoundLogicAction(m_emitter, m_listener, m_sounds); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + m_listener = null; + m_emitter = null; + base.Dispose(); + } + } + } +} diff --git a/DS2DEngine/src/AI Logic/Actions/PlayAnimationLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/PlayAnimationLogicAction.cs new file mode 100644 index 0000000..ceb731f --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/PlayAnimationLogicAction.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Tweener; +using Tweener.Ease; + +namespace DS2DEngine +{ + public class PlayAnimationLogicAction : LogicAction + { + private int m_startFrame; + private int m_endFrame; + private bool m_loop; + + private string m_startLabel = ""; + private string m_endLabel = ""; + private bool m_useLabel = false; + + //private TweenObject m_tweenDelay; + //private BlankObj m_blankObj; + private IAnimateableObj m_animateableObj; + + public PlayAnimationLogicAction(int startingFrame, int endFrame, bool loopAnimation = false) + { + m_startFrame = startingFrame; + m_endFrame = endFrame; + m_loop = loopAnimation; + //m_blankObj = new BlankObj(1, 1); + } + + public PlayAnimationLogicAction(string startLabel, string endLabel, bool loopAnimation = false) + { + m_startLabel = startLabel; + m_endLabel = endLabel; + m_loop = loopAnimation; + m_useLabel = true; + //m_blankObj = new BlankObj(1, 1); + } + + public PlayAnimationLogicAction(bool loopAnimation = true) + { + m_loop = loopAnimation; + m_startFrame = 1; + m_endFrame = 1000; + //m_blankObj = new BlankObj(1, 1); + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + //IAnimateableObj animateableObj = this.ParentLogicSet.ParentGameObj as IAnimateableObj; + m_animateableObj = this.ParentLogicSet.ParentGameObj as IAnimateableObj; + + if (m_animateableObj != null) + { + if (m_useLabel == true) + { + m_startFrame = m_animateableObj.FindLabelIndex(m_startLabel); + m_endFrame = m_animateableObj.FindLabelIndex(m_endLabel); + if (m_startFrame == -1) + throw new Exception("Could not find starting label " + m_startLabel); + else if (m_endFrame == -1) + throw new Exception("Could not find ending label " + m_endLabel); + } + + m_animateableObj.PlayAnimation(m_startFrame, m_endFrame, m_loop); + //if (SequenceType == Types.Sequence.Serial && animateableObj.IsLooping == false) + //{ + // m_startFrame = (m_startFrame - 1) * animateableObj.AnimationSpeed + 1; + // m_endFrame = m_endFrame * animateableObj.AnimationSpeed; + // if (m_endFrame > animateableObj.TotalFrames) + // m_endFrame = animateableObj.TotalFrames; + + // m_tweenDelay = Tween.To(m_blankObj, m_endFrame - m_startFrame, Linear.EaseNone, "X", "1"); + // m_tweenDelay.UseTicks = true; + //} + } + + base.Execute(); + } + } + + public override void Update(Microsoft.Xna.Framework.GameTime gameTime) + { + this.ExecuteNext(); + base.Update(gameTime); + } + + public override void ExecuteNext() + { + if (m_loop == true || m_loop == true || (m_animateableObj != null && SequenceType == Types.Sequence.Serial && m_animateableObj.IsLooping == false && m_animateableObj.IsAnimating == false)) + { + base.ExecuteNext(); + } + } + + + //public override void ExecuteNext() + //{ + // if (m_tweenDelay != null) + // { + // if (NextLogicAction != null) + // m_tweenDelay.EndHandler(NextLogicAction, "Execute"); + // else + // m_tweenDelay.EndHandler(ParentLogicSet, "ExecuteComplete"); + // } + // else + // base.ExecuteNext(); + //} + + public override void Stop() + { + // Okay. Big problem with delay tweens. Because logic actions are never disposed in-level (due to garbage collection concerns) the reference to the delay tween in this logic action will exist until it is + // disposed, EVEN if the tween completes. If the tween completes, it goes back into the pool, and then something else will call it, but this logic action's delay tween reference will still be pointing to it. + // This becomes a HUGE problem if this logic action's Stop() method is called, because it will then stop the tween that this tween reference is pointing to. + // The solution is to comment out the code below. This means that this tween reference will always call it's endhandler, which in this case is either Execute() or ExecuteComplete(). This turns out + // to not be a problem, because when a logic set is called to stop, its IsActive flag is set to false, and all Execute() methods in logic actions have to have their parent logic set's IsActive flag to true + // in order to run. Therefore, when the tween calls Execute() or ExecuteComplete() nothing will happen. + // - This bug kept you confused for almost 5 hours. DO NOT FORGET IT. That is what this long explanation is for. + // TL;DR - DO NOT UNCOMMENT THE CODE BELOW OR LOGIC SETS BREAK. + + //if (m_tweenDelay != null) + // m_tweenDelay.StopTween(false); + + IAnimateableObj obj = this.ParentLogicSet.ParentGameObj as IAnimateableObj; + if (obj != null) + obj.StopAnimation(); + base.Stop(); + } + + public override object Clone() + { + if (m_useLabel == true) + return new PlayAnimationLogicAction(m_startLabel, m_endLabel, m_loop); + else + return new PlayAnimationLogicAction(m_startFrame, m_endFrame, m_loop); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // See above for explanation. + //if (m_tweenDelay != null) + // m_tweenDelay.StopTween(false); + + //m_tweenDelay = null; + //m_blankObj.Dispose(); + //m_blankObj = null; + m_animateableObj = null; + base.Dispose(); + } + } + } +} diff --git a/DS2DEngine/src/AI Logic/Actions/PlaySoundLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/PlaySoundLogicAction.cs new file mode 100644 index 0000000..2a4fb3d --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/PlaySoundLogicAction.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public class PlaySoundLogicAction : LogicAction + { + private string[] m_sounds; + + public PlaySoundLogicAction(params string[] sounds) + { + m_sounds = sounds; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + SoundManager.PlaySound(m_sounds); + base.Execute(); + } + } + + public override object Clone() + { + return new PlaySoundLogicAction(m_sounds); + } + } +} diff --git a/DS2DEngine/src/AI Logic/Actions/RunFunctionLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/RunFunctionLogicAction.cs new file mode 100644 index 0000000..a3a53b6 --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/RunFunctionLogicAction.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; + +namespace DS2DEngine +{ + public class RunFunctionLogicAction : LogicAction + { + MethodInfo m_methodInfo; + object m_methodObject; + object[] m_args; + string m_functionName; + Type m_objectType; + + public RunFunctionLogicAction(object methodObject, string functionName, params object[] args) + { + if (methodObject == null) + throw new Exception("methodObject cannot be null"); + + m_methodInfo = methodObject.GetType().GetMethod(functionName); + + if (m_methodInfo == null) + throw new Exception("Function " + functionName + " not found in class " + methodObject.GetType().ToString()); + + m_methodObject = methodObject; + m_args = args; + m_functionName = functionName; + } + + public RunFunctionLogicAction(Type objectType, string functionName, params object[] args) + { + Type[] argList = new Type[args.Length]; + for (int i = 0; i < args.Length; i++) + argList[i] = args[i].GetType(); + + m_methodInfo = objectType.GetMethod(functionName, argList); + m_args = args; + + if (m_methodInfo == null) + { + m_methodInfo = objectType.GetMethod(functionName, new Type[] { args[0].GetType().MakeArrayType() }); + m_args = new object[1]; + m_args[0] = args; + } + + if (m_methodInfo == null) + throw new Exception("Function " + functionName + " not found in class " + objectType.ToString()); + + m_methodObject = null; + m_functionName = functionName; + m_objectType = objectType; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + m_methodInfo.Invoke(m_methodObject, m_args); + base.Execute(); + } + } + + public override object Clone() + { + if (m_methodObject != null) + return new RunFunctionLogicAction(m_methodObject, m_functionName, m_args); + else + return new RunFunctionLogicAction(m_objectType, m_functionName, m_args); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + m_methodInfo = null; + m_methodObject = null; + if (m_args != null) + Array.Clear(m_args, 0, m_args.Length); + m_args = null; + m_objectType = null; + base.Dispose(); + } + } + } +} diff --git a/DS2DEngine/src/AI Logic/Actions/StopAnimationLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/StopAnimationLogicAction.cs new file mode 100644 index 0000000..e18d81a --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/StopAnimationLogicAction.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Tweener; +using Tweener.Ease; + +namespace DS2DEngine +{ + public class StopAnimationLogicAction : LogicAction + { + public StopAnimationLogicAction() + { + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + IAnimateableObj obj = this.ParentLogicSet.ParentGameObj as IAnimateableObj; + if (obj != null) + obj.StopAnimation(); + + base.Execute(); + } + } + + public override object Clone() + { + return new StopAnimationLogicAction(); + } + + public override void Dispose() + { + if (IsDisposed == false) + base.Dispose(); + } + } +} diff --git a/DS2DEngine/src/AI Logic/Actions/TeleportLogicAction.cs b/DS2DEngine/src/AI Logic/Actions/TeleportLogicAction.cs new file mode 100644 index 0000000..284ad89 --- /dev/null +++ b/DS2DEngine/src/AI Logic/Actions/TeleportLogicAction.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public class TeleportLogicAction : LogicAction + { + GameObj m_target = null; + Vector2 m_newPosition; + Vector2 m_minPosition; + Vector2 m_maxPosition; + + public TeleportLogicAction(GameObj target, Vector2 relativePos) + { + m_target = target; + m_newPosition = relativePos; + } + + public TeleportLogicAction(GameObj target, Vector2 minPos, Vector2 maxPos) + { + m_target = target; + m_minPosition = minPos; + m_maxPosition = maxPos; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + if (m_minPosition != m_maxPosition) + m_newPosition = new Vector2(CDGMath.RandomInt((int)m_minPosition.X, (int)m_maxPosition.X), CDGMath.RandomInt((int)m_minPosition.Y, (int)m_maxPosition.Y)); + + if (m_target == null) + ParentLogicSet.ParentGameObj.Position = m_newPosition; + else + ParentLogicSet.ParentGameObj.Position = m_target.Position + m_newPosition; + base.Execute(); + } + } + + public override object Clone() + { + if (m_minPosition != m_maxPosition) + return new TeleportLogicAction(m_target, m_minPosition, m_maxPosition); + else + return new TeleportLogicAction(m_target, m_newPosition); + } + + public override void Dispose() + { + if (IsDisposed == true) + { + m_target = null; + base.Dispose(); + } + } + } +} diff --git a/DS2DEngine/src/AI Logic/Base Objects/LogicAction.cs b/DS2DEngine/src/AI Logic/Base Objects/LogicAction.cs new file mode 100644 index 0000000..0756c9f --- /dev/null +++ b/DS2DEngine/src/AI Logic/Base Objects/LogicAction.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public abstract class LogicAction : IDisposableObj, ICloneable + { + // A linked list of trigger actions. + public LogicSet ParentLogicSet = null; + public LogicAction PreviousLogicAction = null; + public LogicAction NextLogicAction = null; + + public string Tag { get; set; } + public Types.Sequence SequenceType = Types.Sequence.Serial; + + private bool m_isDisposed = false; + public bool IsDisposed { get { return m_isDisposed; } } + + // All classes that override Execute() must be contained in the following if statement: + // if (this.ParentLogicSet.IsActive == true) { } + public virtual void Execute() + { + ParentLogicSet.ActiveLogicAction = this; + + if (SequenceType == Types.Sequence.Parallel && NextLogicAction != null) + NextLogicAction.Execute(); + else if (SequenceType == Types.Sequence.Serial) + ExecuteNext(); + else if (SequenceType == Types.Sequence.Parallel && NextLogicAction == null) + ParentLogicSet.ExecuteComplete(); + } + + public virtual void ExecuteNext() + { + if (NextLogicAction != null) + NextLogicAction.Execute(); + else + ParentLogicSet.ExecuteComplete(); + } + + public virtual void Update(GameTime gameTime) { } + + public virtual void Stop() + { + //Runs through all the logic actions and runs their Stop() method. + if (NextLogicAction != null) + NextLogicAction.Stop(); + } + + public virtual void Dispose() + { + ParentLogicSet = null; + NextLogicAction = null; + PreviousLogicAction = null; + m_isDisposed = true; + } + + public abstract object Clone(); + + } +} diff --git a/DS2DEngine/src/AI Logic/Base Objects/LogicBlock.cs b/DS2DEngine/src/AI Logic/Base Objects/LogicBlock.cs new file mode 100644 index 0000000..498fdd8 --- /dev/null +++ b/DS2DEngine/src/AI Logic/Base Objects/LogicBlock.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public class LogicBlock : IDisposableObj + { + List m_logicSetList; + private bool m_isActive; + private int[] m_percentParams; + + private LogicSet m_activeLS = null; + + private bool m_isDisposed = false; + + public LogicBlock() + { + m_logicSetList = new List(); + m_isActive = false; + } + + public void RunLogicBlock(params int[] percentParams) + { + m_percentParams = percentParams; + + if (percentParams.Length != m_logicSetList.Count) + throw new Exception("Number of percentage parameters (" + percentParams.Length + ") does not match the number of logic sets in this block (" + m_logicSetList.Count + ")."); + + m_isActive = true; + + int chance = CDGMath.RandomInt(1, 100); + int totalChance = 0; + + for (int i = 0; i < m_logicSetList.Count; i++) + { + // Automatically execute this logic set if it is the last one in the list. + if (i == m_logicSetList.Count - 1) + { + m_activeLS = m_logicSetList[i]; + m_logicSetList[i].Execute(); + break; + } + else + { + totalChance += percentParams[i]; + if (chance <= totalChance) + { + m_activeLS = m_logicSetList[i]; + m_logicSetList[i].Execute(); + break; + } + } + } + } + + public void Update(GameTime gameTime) + { + if (IsActive == true) + { + foreach (LogicSet set in m_logicSetList) + { + if (set.IsActive == true) + set.Update(gameTime); + } + } + } + + public void StopLogicBlock() + { + foreach (LogicSet set in m_logicSetList) + { + set.Stop(); + } + LogicBlockComplete(); + } + + public void LogicBlockComplete() + { + m_isActive = false; + } + + public void AddLogicSet(params LogicSet[] logicSet) + { + foreach (LogicSet set in logicSet) + { + LogicSet setToAdd = set.Clone(); + m_logicSetList.Add(setToAdd); + setToAdd.ParentLogicBlock = this; + } + } + + // Doesn't work because logicsets are cloned so the comparison will never be made. + //public void RemoveLogicSet(params LogicSet[] logicSet) + //{ + // foreach (LogicSet set in logicSet) + // { + // m_logicSetList.Remove(set); + // set.ParentLogicBlock = null; + // } + //} + + public void ClearAllLogicSets() + { + foreach (LogicSet set in m_logicSetList) + { + set.ParentLogicBlock = null; + } + m_logicSetList.Clear(); + } + + public bool IsActive + { + get { return m_isActive; } + } + + public void Dispose() + { + if (m_isDisposed == false) + { + m_isDisposed = true; + foreach (LogicSet set in m_logicSetList) + set.Dispose(); + m_logicSetList.Clear(); + m_logicSetList = null; + m_activeLS = null; // No need to dispose since it should already be disposed at this point. + m_isActive = false; + } + } + + public bool IsDisposed + { + get { return m_isDisposed; } + } + + public List LogicSetList + { + get { return m_logicSetList; } + } + + public LogicSet ActiveLS + { + get { return m_activeLS; } + } + } +} diff --git a/DS2DEngine/src/AI Logic/Base Objects/LogicSet.cs b/DS2DEngine/src/AI Logic/Base Objects/LogicSet.cs new file mode 100644 index 0000000..d5112be --- /dev/null +++ b/DS2DEngine/src/AI Logic/Base Objects/LogicSet.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public class LogicSet : IDisposableObj + { + private LogicAction m_firstLogicNode; + private LogicAction m_currentLogicNode; + private LogicAction m_lastLogicNode; + + private bool m_isActive = false; + private GameObj m_parentObject; + public LogicBlock ParentLogicBlock { get; set; } + + private bool m_isDisposed = false; + public int Tag = 0; + + public LogicSet(GameObj parentObj) + { + m_parentObject = parentObj; + } + + public void AddAction(LogicAction logicAction, Types.Sequence sequenceType = Types.Sequence.Serial) + { + logicAction.SequenceType = sequenceType; + logicAction.ParentLogicSet = this; + + if (m_firstLogicNode == null) + m_firstLogicNode = logicAction; + else + m_currentLogicNode.NextLogicAction = logicAction; + + m_currentLogicNode = logicAction; + m_lastLogicNode = m_currentLogicNode; + } + + public void Execute() + { + if (m_lastLogicNode == null) + throw new Exception("Cannot execute logic set. Call CompleteAddAction() first."); + + m_isActive = true; + m_firstLogicNode.Execute(); + } + + public void ExecuteComplete() + { + m_isActive = false; + //Console.WriteLine("logic set complete"); + if (ParentLogicBlock != null && ParentLogicBlock.ActiveLS == this) + { + ParentLogicBlock.LogicBlockComplete(); + } + } + + public void Stop() + { + m_isActive = false; + m_firstLogicNode.Stop(); + } + + public void Update(GameTime gameTime) + { + ActiveLogicAction.Update(gameTime); + } + + public LogicSet Clone() + { + LogicSet lsToReturn = new LogicSet(m_parentObject); + lsToReturn.AddAction(m_firstLogicNode.Clone() as LogicAction, m_firstLogicNode.SequenceType); + m_currentLogicNode = m_firstLogicNode; + while (m_currentLogicNode.NextLogicAction != null) + { + m_currentLogicNode = m_currentLogicNode.NextLogicAction; + lsToReturn.AddAction(m_currentLogicNode.Clone() as LogicAction, m_currentLogicNode.SequenceType); + } + m_currentLogicNode = m_lastLogicNode; + lsToReturn.Tag = this.Tag; + return lsToReturn; + } + + public bool IsActive + { + get { return m_isActive; } + } + + public GameObj ParentGameObj + { + get { return m_parentObject; } + } + + public LogicAction ActiveLogicAction + { + get + { + if (IsActive == false) + return null; + else + return m_currentLogicNode; + } + set { m_currentLogicNode = value; } + } + + public void Dispose() + { + if (m_isDisposed == false) + { + m_isDisposed = true; + m_currentLogicNode = m_firstLogicNode; + while (m_currentLogicNode != null) + { + LogicAction nextNode = m_currentLogicNode.NextLogicAction; + m_currentLogicNode.Dispose(); + m_currentLogicNode = nextNode; + } + m_isActive = false; + } + } + + public bool IsDisposed + { + get { return m_isDisposed; } + } + } +} diff --git a/DS2DEngine/src/CDGMath.cs b/DS2DEngine/src/CDGMath.cs new file mode 100644 index 0000000..4f77c90 --- /dev/null +++ b/DS2DEngine/src/CDGMath.cs @@ -0,0 +1,259 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public class CDGMath + { + private static Random m_randomSeed = new Random(); + + public static float AngleBetweenPts(Vector2 pt1, Vector2 pt2) + { + float x1 = pt2.X - pt1.X; + float y1 = pt2.Y - pt1.Y; + float desiredAngle = (float)Math.Atan2(y1,x1); + float difference = MathHelper.WrapAngle(desiredAngle); + return MathHelper.ToDegrees(difference); + } + + public static float VectorToAngle(Vector2 pt) + { + return AngleBetweenPts(Vector2.Zero, pt); + } + + public static Vector2 AngleToVector(float angle) + { + angle = MathHelper.ToRadians(angle); + return new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)); + } + + public static Vector2 VectorBetweenPts(Vector2 pt1, Vector2 pt2) + { + return new Vector2(pt2.X - pt1.X, pt2.Y - pt1.Y); + } + + public static float DistanceBetweenPts(Vector2 pt1, Vector2 pt2) + { + float dx = pt2.X - pt1.X; + float dy = pt2.Y - pt1.Y; + return (float)Math.Sqrt(dx* dx + dy * dy); + } + + public static float DotProduct(Vector2 pt1, Vector2 pt2) + { + return pt1.X * pt2.X + pt1.Y * pt2.Y; + } + + public static Vector2 RotatedPoint(Vector2 pt, float rotationAngle) + { + float radianPt = MathHelper.ToRadians(rotationAngle); + double cos = Math.Cos(radianPt); + double sin = Math.Sin(radianPt); + float x2 = (float)(cos * pt.X - sin * pt.Y); + float y2 = (float)(sin * pt.X + cos * pt.Y); + return new Vector2(x2, y2); + } + + public static Vector2 RotatedPoint(Vector2 thePoint, Vector2 theOrigin, float theRotation) + { + theRotation = MathHelper.ToRadians(theRotation); + double cos = Math.Cos(theRotation); + double sin = Math.Sin(theRotation); + Vector2 aTranslatedPoint = new Vector2(); + aTranslatedPoint.X = (float)(theOrigin.X + (thePoint.X - theOrigin.X) * cos + - (thePoint.Y - theOrigin.Y) * sin); + aTranslatedPoint.Y = (float)(theOrigin.Y + (thePoint.Y - theOrigin.Y) * cos + + (thePoint.X - theOrigin.X) * sin); + return aTranslatedPoint; + } + + public static string ConvertToHMS(uint milliseconds) + { + uint mills = milliseconds; + uint hours = ((mills/1000)/3600); + uint mins = ((mills/1000)/60) % 60; + uint secs = ((mills/1000) % 60); + + string hoursString; + string minsString; + string secsString; + + if (hours < 10) hoursString = "0" + hours.ToString(); + else hoursString = hours.ToString(); + + if (mins < 10) minsString = "0" + mins.ToString(); + else minsString = mins.ToString(); + + if (secs < 10) secsString = "0" + secs.ToString(); + else secsString = secs.ToString(); + + return (hoursString + ":" + minsString + ":" + secsString); + } + + /// + /// Returns a random positive integer. + /// + /// returns a random positive integer. + public static int RandomInt() + { + return m_randomSeed.Next(); + } + + public static int RandomInt(int min, int max) + { + return m_randomSeed.Next(min, max + 1); // Plus 1 because Next(int, int) returns a number less than maxvalue. + } + + /// + /// Returns a random float from 0.0 to 1.0. + /// + /// Returns a random float from 0.0 to 1.0. + public static float RandomFloat() + { + return (float)m_randomSeed.NextDouble(); + } + + public static float RandomFloat(float min, float max) + { + double range = (double)(max - min); + double sample = m_randomSeed.NextDouble(); + double scaled = (sample * range) + min; + return (float)scaled; + } + /* + public static float RandomMinMaxDecimal(float min, float max) + { + if (max < min) throw new Exception("CDGMath.RandomMinMax(): Cannot create random number when max is less than min."); + Random rand = new Random(); + double range = (double)(max - min); + double sample = rand.NextDouble(); + double scaled = (sample * range) + min; + return (float)scaled; + }*/ + + public static int RandomPlusMinus() + { + /*var rand : Number = Math.random() * 2; + if (rand < 1) return -1 + else return 1;*/ + int rand = RandomInt(0, 2); + if (rand < 1) return -1; + return 1; + } + + public static void TurnToFace(GameObj obj, float angle) + { + float desiredAngle = angle; + float difference = MathHelper.WrapAngle(desiredAngle - obj.Orientation); + + difference = MathHelper.Clamp(difference, -obj.TurnSpeed, obj.TurnSpeed); + obj.Orientation = MathHelper.WrapAngle(obj.Orientation + difference); + + obj.HeadingX = (float)Math.Cos(obj.Orientation); + obj.HeadingY = (float)Math.Sin(obj.Orientation); + } + + public static void TurnToFace(GameObj obj, Vector2 facePosition) + { + float x = facePosition.X - obj.Position.X; + float y = facePosition.Y - obj.Position.Y; + + float desiredAngle = (float)Math.Atan2(y, x); + float difference = MathHelper.WrapAngle(desiredAngle - obj.Orientation); + + difference = MathHelper.Clamp(difference, -obj.TurnSpeed, obj.TurnSpeed); + obj.Orientation = MathHelper.WrapAngle(obj.Orientation + difference); + + obj.HeadingX = (float)Math.Cos(obj.Orientation); + obj.HeadingY = (float)Math.Sin(obj.Orientation); + } + + // Placeholder code for bezier curves. + // t represents a time between 0 and 1. + public static Vector2 GetBezierPoint(float t, Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3) + { + float cx = 3 * (p1.X - p0.X); + float cy = 3 * (p1.Y - p0.Y); + + float bx = 3 * (p2.X - p1.X) - cx; + float by = 3 * (p2.Y - p1.Y) - cy; + + float ax = p3.X - p0.X - cx - bx; + float ay = p3.Y - p0.Y - cy - by; + + float Cube = t * t * t; + float Square = t * t; + + float resX = (ax * Cube) + (bx * Square) + (cx * t) + p0.X; + float resY = (ay * Cube) + (by * Square) + (cy * t) + p0.Y; + + return new Vector2(resX, resY); + } + + public static Vector2 GetCirclePosition(float angle, float distance, Vector2 centre) + { + angle = MathHelper.ToRadians(angle); + return new Vector2((float)(distance * Math.Cos(angle)), (float)(distance * Math.Sin(angle))) + centre; + } + + public static void Shuffle(List array) + { + for (int i = array.Count; i > 1; i--) + { + // Pick random element to swap. + int j = RandomInt(0, i - 1); // 0 <= j <= i-1 + // Swap. + T tmp = array[j]; + array[j] = array[i - 1]; + array[i - 1] = tmp; + } + } + + public static void Shuffle(T[] array) + { + for (int i = array.Length; i > 1; i--) + { + // Pick random element to swap. + int j = RandomInt(0, i - 1); // 0 <= j <= i-1 + // Swap. + T tmp = array[j]; + array[j] = array[i - 1]; + array[i - 1] = tmp; + } + } + + public static int NextPowerOf2(int x) + { + --x; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return ++x; + } + + public static string ToRoman(int number) + { + if ((number < 0) || (number > 3999)) throw new ArgumentOutOfRangeException("insert value betwheen 1 and 3999"); + if (number < 1) return string.Empty; + if (number >= 1000) return "M" + ToRoman(number - 1000); + if (number >= 900) return "CM" + ToRoman(number - 900); //EDIT: i've typed 400 instead 900 + if (number >= 500) return "D" + ToRoman(number - 500); + if (number >= 400) return "CD" + ToRoman(number - 400); + if (number >= 100) return "C" + ToRoman(number - 100); + if (number >= 90) return "XC" + ToRoman(number - 90); + if (number >= 50) return "L" + ToRoman(number - 50); + if (number >= 40) return "XL" + ToRoman(number - 40); + if (number >= 10) return "X" + ToRoman(number - 10); + if (number >= 9) return "IX" + ToRoman(number - 9); + if (number >= 5) return "V" + ToRoman(number - 5); + if (number >= 4) return "IV" + ToRoman(number - 4); + if (number >= 1) return "I" + ToRoman(number - 1); + throw new ArgumentOutOfRangeException("something bad happened"); + } + } +} diff --git a/DS2DEngine/src/Camera2D.cs b/DS2DEngine/src/Camera2D.cs new file mode 100644 index 0000000..eda6816 --- /dev/null +++ b/DS2DEngine/src/Camera2D.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace DS2DEngine +{ + public class Camera2D : SpriteBatch + { + private float m_zoom; + private Matrix m_transform; + private float m_rotation; + private Rectangle m_bounds; + private int m_width; + private int m_height; + + public Vector2 Position; + + private Texture2D DEBUG_texture; + private Color DEBUG_color = new Color(100, 100, 100); + + public GameTime GameTime { get; set; } + public float ElapsedTotalSeconds { get; set; } // Used to reduce performance load since this number is called a lot. + + public Camera2D(GraphicsDevice graphicsDevice, int width, int height) : base(graphicsDevice) + { + m_zoom = 1.0f; + m_rotation = 0.0f; + Position = Vector2.Zero; + + m_width = width; // EngineEV.ScreenWidth; //graphicsDevice.Viewport.Width; + m_height = height; // EngineEV.ScreenHeight; // graphicsDevice.Viewport.Height; + + + m_bounds = new Rectangle((int)(-Width * 0.5f), (int)(-Height * 0.5f), Width, Height); + + DEBUG_texture = new Texture2D(graphicsDevice, 1, 1, false, SurfaceFormat.Color); + Int32[] pixel = { 0xFFFFFF }; // White. 0xFF is Red, 0xFF0000 is Blue + DEBUG_texture.SetData(pixel, 0, 1); + } + + public Matrix GetTransformation() + { + m_transform = Matrix.CreateTranslation(new Vector3(-Position.X, -Position.Y, 0)) * + Matrix.CreateRotationZ(m_rotation) * + Matrix.CreateScale(new Vector3(Zoom, Zoom, 1)) * + Matrix.CreateTranslation(new Vector3(Width * 0.5f, + Height * 0.5f, 0)); + return m_transform; + } + + public void DrawLine(Texture2D texture, float width, Color color, Vector2 pt1, Vector2 pt2) + { + float angle = (float)Math.Atan2(pt2.Y - pt1.Y, pt2.X - pt1.X); + float length = Vector2.Distance(pt1, pt2); + + this.Draw(texture, pt1, null, color, + angle, Vector2.Zero, new Vector2(length, width), + SpriteEffects.None, 0); + } + + public void Draw_CameraBox() + { + this.Draw(DEBUG_texture, Bounds, DEBUG_color); + } + + public float Zoom + { + get { return m_zoom; } + set + { + m_zoom = value; + if (m_zoom < 0.025f) m_zoom = 0.025f; + //if (m_zoom > 2) m_zoom = 2; + } + } + + public float Rotation + { + get { return MathHelper.ToDegrees(m_rotation); } + set { m_rotation = MathHelper.ToRadians(value); } + } + + public float X + { + get { return Position.X; } + set { Position.X = value; } + } + + public float Y + { + get { return Position.Y; } + set { Position.Y = value; } + } + + public int Width + { + get { return m_width; } + } + + public int Height + { + get { return m_height; } + } + + public Rectangle Bounds + { + get { return new Rectangle((int)(Position.X - (Width * 0.5f * 1/Zoom)), + (int)(Position.Y - (Height * 0.5f * 1/Zoom)), + (int)(m_bounds.Width * 1/Zoom), (int)(m_bounds.Height * 1/Zoom)); } + } + + // A bounding box larger than the actual bounds of the camera that determines whether physics and logic should kick in. + public Rectangle LogicBounds + { + get { return new Rectangle(Bounds.X - 200, Bounds.Y - 200, Bounds.Width + 400, Bounds.Height + 400); } + } + + public Vector2 TopLeftCorner + { + get { return new Vector2(Position.X - (this.Width * 0.5f * 1/Zoom), Position.Y - (this.Height * 0.5f * 1/Zoom)); } + } + + public bool CenteredZoom + { + get { return (Zoom < 1.05f && Zoom > 0.95f); } + } + + protected override void Dispose(bool disposing) + { + if (IsDisposed == false) + { + DEBUG_texture.Dispose(); + DEBUG_texture = null; + base.Dispose(disposing); + } + } + } +} diff --git a/DS2DEngine/src/Circle.cs b/DS2DEngine/src/Circle.cs new file mode 100644 index 0000000..21911c0 --- /dev/null +++ b/DS2DEngine/src/Circle.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public struct Circle + { + private float m_x; + private float m_y; + private float m_radius; + + public Circle(float x, float y, float radius) + { + m_x = x; + m_y = y; + m_radius = radius; + } + + public static Circle Zero + { + get { return new Circle(0,0,0); } + } + + public float X + { + get { return m_x; } + set { m_x = value; } + } + + public float Y + { + get { return m_y; } + set { m_y = value; } + } + + public Vector2 Position + { + get { return new Vector2(m_x, m_y); } + set + { + m_x = value.X; + m_y = value.Y; + } + } + + public float Radius + { + get { return m_radius; } + set { m_radius = value; } + } + } +} diff --git a/DS2DEngine/src/CollisionMath.cs b/DS2DEngine/src/CollisionMath.cs new file mode 100644 index 0000000..2290d3b --- /dev/null +++ b/DS2DEngine/src/CollisionMath.cs @@ -0,0 +1,615 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace DS2DEngine +{ + public class CollisionMath + { + // Static variables used to calculate rotated rect collision + private static Vector2[] aRectangleAxis = new Vector2[4]; + private static int[] aRectangleAScalars = new int[4]; + private static int[] aRectangleBScalars = new int[4]; + + //Function that detects if two rectangles collide. + public static bool Intersects(Rectangle a, Rectangle b) + { + return a.Intersects(b); + } + + public static Vector2 RotatedRectIntersectsMTD(Rectangle a, float rotationA, Vector2 originA, Rectangle b, float rotationB, Vector2 originB) + { + if (rotationA == 0 && rotationB == 0) + return CalculateMTD(a, b); + + //List aRectangleAxis = new List(); + Vector2 upperLeftA = new Vector2(); + Vector2 upperRightA = new Vector2(); + Vector2 lowerLeftA = new Vector2(); + Vector2 lowerRightA = new Vector2(); + CalcCorners(ref upperLeftA, ref upperRightA, ref lowerLeftA, ref lowerRightA, a, rotationA, originA); + Vector2 upperLeftB = new Vector2(); + Vector2 upperRightB = new Vector2(); + Vector2 lowerLeftB = new Vector2(); + Vector2 lowerRightB = new Vector2(); + CalcCorners(ref upperLeftB, ref upperRightB, ref lowerLeftB, ref lowerRightB, b, rotationB, originB); + + aRectangleAxis[0] = (upperRightA - upperLeftA); + aRectangleAxis[1] = (upperRightA - lowerRightA); + aRectangleAxis[2] = (upperLeftB - lowerLeftB); + aRectangleAxis[3] = (upperLeftB - upperRightB); + + float shortestLength = int.MaxValue; + Vector2 shortestMTD = Vector2.Zero; + foreach (Vector2 aAxis in aRectangleAxis) + { + aAxis.Normalize(); + Vector2 mtd = AxisCollisionMTD(a, rotationA, originA, b, rotationB, originB, aAxis); + if (mtd.Length() < shortestLength) + { + shortestLength = mtd.Length(); + shortestMTD = mtd; + } + } + return new Vector2((int)shortestMTD.X, (int)shortestMTD.Y); + //return shortestMTD; + } + + //Do not convert to radians. The internal functions will do that. + //This version of the method assumes the origin of rotation is in the centre of the rectangle. + public static bool RotatedRectIntersects(Rectangle a, float rotationA, Rectangle b, float rotationB) + { + if (rotationA == 0 && rotationB == 0) + return a.Intersects(b); + + //List aRectangleAxis = new List(); + Vector2 upperLeftA = new Vector2(); + Vector2 upperRightA = new Vector2(); + Vector2 lowerLeftA = new Vector2(); + Vector2 lowerRightA = new Vector2(); + CalcCorners(ref upperLeftA, ref upperRightA, ref lowerLeftA, ref lowerRightA, a, rotationA); + Vector2 upperLeftB = new Vector2(); + Vector2 upperRightB = new Vector2(); + Vector2 lowerLeftB = new Vector2(); + Vector2 lowerRightB = new Vector2(); + CalcCorners(ref upperLeftB, ref upperRightB, ref lowerLeftB, ref lowerRightB, b, rotationB); + + aRectangleAxis[0] = (upperRightA - upperLeftA); + aRectangleAxis[1] = (upperRightA - lowerRightA); + aRectangleAxis[2] = (upperLeftB - lowerLeftB); + aRectangleAxis[3] = (upperLeftB - upperRightB); + + foreach (Vector2 aAxis in aRectangleAxis) + { + if (!IsAxisCollision(a, rotationA, b, rotationB, aAxis)) + return false; + } + + return true; + } + + //Do not convert to radians. The internal functions will do that. + public static bool RotatedRectIntersects(Rectangle a, float rotationA, Vector2 originA, Rectangle b, float rotationB, Vector2 originB) + { + if (rotationA == 0 && rotationB == 0) + return a.Intersects(b); + + //List aRectangleAxis = new List(); + Vector2 upperLeftA = new Vector2(); + Vector2 upperRightA = new Vector2(); + Vector2 lowerLeftA = new Vector2(); + Vector2 lowerRightA = new Vector2(); + CalcCorners(ref upperLeftA, ref upperRightA, ref lowerLeftA, ref lowerRightA, a, rotationA, originA); + Vector2 upperLeftB = new Vector2(); + Vector2 upperRightB = new Vector2(); + Vector2 lowerLeftB = new Vector2(); + Vector2 lowerRightB = new Vector2(); + CalcCorners(ref upperLeftB, ref upperRightB, ref lowerLeftB, ref lowerRightB, b, rotationB, originB); + + aRectangleAxis[0] = (upperRightA - upperLeftA); + aRectangleAxis[1] = (upperRightA - lowerRightA); + aRectangleAxis[2] = (upperLeftB - lowerLeftB); + aRectangleAxis[3] = (upperLeftB - upperRightB); + + foreach (Vector2 aAxis in aRectangleAxis) + { + aAxis.Normalize(); // This doesn't seem necessary. + if (!IsAxisCollision(a, rotationA, originA, b, rotationB, originB, aAxis)) + return false; + } + + return true; + } + // Do not convert to radians. + private static Vector2 RotatePoint(Vector2 thePoint, Vector2 theOrigin, float theRotation) + { + double cos = Math.Cos(theRotation); + double sin = Math.Sin(theRotation); + Vector2 aTranslatedPoint = new Vector2(); + aTranslatedPoint.X = (float)(theOrigin.X + (thePoint.X - theOrigin.X) * cos + - (thePoint.Y - theOrigin.Y) * sin); + aTranslatedPoint.Y = (float)(theOrigin.Y + (thePoint.Y - theOrigin.Y) * cos + + (thePoint.X - theOrigin.X) * sin); + return aTranslatedPoint; + } + + private static void RotatePoint(Vector2 thePoint, Vector2 theOrigin, double cos, double sin, ref Vector2 output) + { + float x = (float)(theOrigin.X + (thePoint.X - theOrigin.X) * cos + - (thePoint.Y - theOrigin.Y) * sin); + float y = (float)(theOrigin.Y + (thePoint.Y - theOrigin.Y) * cos + + (thePoint.X - theOrigin.X) * sin); + output.X = x; + output.Y = y; + } + + public static Vector2 UpperLeftCorner(Rectangle rect, float rotation) + { + rotation = MathHelper.ToRadians(rotation); + Vector2 origin = new Vector2(rect.Width * 0.5f, rect.Height * 0.5f); + Vector2 aUpperLeft = new Vector2(rect.Left, rect.Top); + aUpperLeft = RotatePoint(aUpperLeft, aUpperLeft + origin, rotation); + return aUpperLeft; + } + + public static Vector2 UpperLeftCorner(Rectangle rect, float rotation, Vector2 origin) + { + rotation = MathHelper.ToRadians(rotation); + Vector2 aUpperLeft = new Vector2(rect.Left, rect.Top); + aUpperLeft = RotatePoint(aUpperLeft, aUpperLeft + origin, rotation); + return aUpperLeft; + } + + public static Vector2 UpperRightCorner(Rectangle rect, float rotation) + { + rotation = MathHelper.ToRadians(rotation); + Vector2 origin = new Vector2(rect.Width * 0.5f, rect.Height * 0.5f); + Vector2 aUpperRight = new Vector2(rect.Right, rect.Top); + aUpperRight = RotatePoint(aUpperRight, aUpperRight + new Vector2(-origin.X, origin.Y), rotation); + return aUpperRight; + } + + public static Vector2 UpperRightCorner(Rectangle rect, float rotation, Vector2 origin) + { + rotation = MathHelper.ToRadians(rotation); + Vector2 aUpperRight = new Vector2(rect.Right, rect.Top); + Vector2 aUpperLeft = new Vector2(rect.Left, rect.Top); + aUpperRight = RotatePoint(aUpperRight, aUpperLeft + origin, rotation); + return aUpperRight; + } + + public static Vector2 LowerLeftCorner(Rectangle rect, float rotation) + { + rotation = MathHelper.ToRadians(rotation); + Vector2 origin = new Vector2(rect.Width * 0.5f, rect.Height * 0.5f); + Vector2 aLowerLeft = new Vector2(rect.Left, rect.Bottom); + aLowerLeft = RotatePoint(aLowerLeft, aLowerLeft + new Vector2(origin.X, -origin.Y), rotation); + return aLowerLeft; + } + + public static Vector2 LowerLeftCorner(Rectangle rect, float rotation, Vector2 origin) + { + rotation = MathHelper.ToRadians(rotation); + Vector2 aLowerLeft = new Vector2(rect.Left, rect.Bottom); + Vector2 aUpperLeft = new Vector2(rect.Left, rect.Top); + aLowerLeft = RotatePoint(aLowerLeft, aUpperLeft + origin, rotation); + return aLowerLeft; + } + + public static Vector2 LowerRightCorner(Rectangle rect, float rotation) + { + rotation = MathHelper.ToRadians(rotation); + Vector2 origin = new Vector2(rect.Width * 0.5f, rect.Height * 0.5f); + Vector2 aLowerRight = new Vector2(rect.Right, rect.Bottom); + aLowerRight = RotatePoint(aLowerRight, aLowerRight + new Vector2(-origin.X, -origin.Y), rotation); + return aLowerRight; + } + + public static Vector2 LowerRightCorner(Rectangle rect, float rotation, Vector2 origin) + { + rotation = MathHelper.ToRadians(rotation); + Vector2 aLowerRight = new Vector2(rect.Right, rect.Bottom); + Vector2 aUpperLeft = new Vector2(rect.Left, rect.Top); + aLowerRight = RotatePoint(aLowerRight, aUpperLeft + origin, rotation); + return aLowerRight; + } + + // More optimized to call this than each corner function separately + public static void CalcCorners(ref Vector2 upperLeft, ref Vector2 upperRight, ref Vector2 lowerLeft, ref Vector2 lowerRight, Rectangle rect, float rotation) + { + rotation = MathHelper.ToRadians(rotation); + Vector2 aUpperLeft = new Vector2(rect.Left, rect.Top); + Vector2 aUpperRight = new Vector2(rect.Right, rect.Top); + Vector2 aLowerLeft = new Vector2(rect.Left, rect.Bottom); + Vector2 aLowerRight = new Vector2(rect.Right, rect.Bottom); + Vector2 origin = new Vector2(rect.Width * 0.5f, rect.Height * 0.5f); + + double cos = Math.Cos(rotation); + double sin = Math.Sin(rotation); + RotatePoint(aUpperLeft, aUpperLeft + origin, cos, sin, ref upperLeft); + RotatePoint(aUpperRight, aUpperRight + new Vector2(-origin.X, origin.Y), cos, sin, ref upperRight); + RotatePoint(aLowerLeft, aLowerLeft + new Vector2(origin.X, -origin.Y), cos, sin, ref lowerLeft); + RotatePoint(aLowerRight, aLowerRight + new Vector2(-origin.X, -origin.Y), cos, sin, ref lowerRight); + } + + // More optimized to call this than each corner function separately + public static void CalcCorners(ref Vector2 upperLeft, ref Vector2 upperRight, ref Vector2 lowerLeft, ref Vector2 lowerRight, Rectangle rect, float rotation, Vector2 origin) + { + rotation = MathHelper.ToRadians(rotation); + Vector2 aUpperLeft = new Vector2(rect.Left, rect.Top); + Vector2 aUpperRight = new Vector2(rect.Right, rect.Top); + Vector2 aLowerLeft = new Vector2(rect.Left, rect.Bottom); + Vector2 aLowerRight = new Vector2(rect.Right, rect.Bottom); + + double cos = Math.Cos(rotation); + double sin = Math.Sin(rotation); + RotatePoint(aUpperLeft, aUpperLeft + origin, cos, sin, ref upperLeft); + RotatePoint(aUpperRight, aUpperLeft + origin, cos, sin, ref upperRight); + RotatePoint(aLowerLeft, aUpperLeft + origin, cos, sin, ref lowerLeft); + RotatePoint(aLowerRight, aUpperLeft + origin, cos, sin, ref lowerRight); + } + + + /// + /// Determines if a collision has occurred on an Axis of one of the + /// planes parallel to the Rectangle + /// + /// + /// + /// + /// Do not convert to Radians. + private static bool IsAxisCollision(Rectangle a, float rotationA, Rectangle b, float rotationB, Vector2 aAxis) + { + Vector2 upperLeftA = new Vector2(); + Vector2 upperRightA = new Vector2(); + Vector2 lowerLeftA = new Vector2(); + Vector2 lowerRightA = new Vector2(); + CalcCorners(ref upperLeftA, ref upperRightA, ref lowerLeftA, ref lowerRightA, a, rotationA); + Vector2 upperLeftB = new Vector2(); + Vector2 upperRightB = new Vector2(); + Vector2 lowerLeftB = new Vector2(); + Vector2 lowerRightB = new Vector2(); + CalcCorners(ref upperLeftB, ref upperRightB, ref lowerLeftB, ref lowerRightB, b, rotationB); + + //Project the corners of the Rectangle we are checking on to the Axis and + //get a scalar value of that project we can then use for comparison + //List aRectangleAScalars = new List(); + aRectangleAScalars[0] = (GenerateScalar(upperLeftB, aAxis)); + aRectangleAScalars[1] = (GenerateScalar(upperRightB, aAxis)); + aRectangleAScalars[2] = (GenerateScalar(lowerLeftB, aAxis)); + aRectangleAScalars[3] = (GenerateScalar(lowerRightB, aAxis)); + + //Project the corners of the current Rectangle on to the Axis and + //get a scalar value of that project we can then use for comparison + //List aRectangleBScalars = new List(); + aRectangleBScalars[0] = (GenerateScalar(upperLeftA, aAxis)); + aRectangleBScalars[1] = (GenerateScalar(upperRightA, aAxis)); + aRectangleBScalars[2] = (GenerateScalar(lowerLeftA, aAxis)); + aRectangleBScalars[3] = (GenerateScalar(lowerRightA, aAxis)); + + //Get the Maximum and Minium Scalar values for each of the Rectangles + int aRectangleAMinimum = aRectangleAScalars.Min(); + int aRectangleAMaximum = aRectangleAScalars.Max(); + int aRectangleBMinimum = aRectangleBScalars.Min(); + int aRectangleBMaximum = aRectangleBScalars.Max(); + + //If we have overlaps between the Rectangles (i.e. Min of B is less than Max of A) + //then we are detecting a collision between the rectangles on this Axis + if (aRectangleBMinimum <= aRectangleAMaximum && aRectangleBMaximum >= aRectangleAMaximum) + return true; + else if (aRectangleAMinimum <= aRectangleBMaximum && aRectangleAMaximum >= aRectangleBMaximum) + return true; + + return false; + } + + private static bool IsAxisCollision(Rectangle a, float rotationA, Vector2 originA, Rectangle b, float rotationB, Vector2 originB, Vector2 aAxis) + { + + //Project the corners of the Rectangle we are checking on to the Axis and + //get a scalar value of that project we can then use for comparison + //List aRectangleAScalars = new List(); + Vector2 upperLeft = new Vector2(); + Vector2 upperRight = new Vector2(); + Vector2 lowerLeft = new Vector2(); + Vector2 lowerRight = new Vector2(); + CalcCorners(ref upperLeft, ref upperRight, ref lowerLeft, ref lowerRight, b, rotationB, originB); + aRectangleAScalars[0] = (GenerateScalar(upperLeft, aAxis)); + aRectangleAScalars[1] = (GenerateScalar(upperRight, aAxis)); + aRectangleAScalars[2] = (GenerateScalar(lowerLeft, aAxis)); + aRectangleAScalars[3] = (GenerateScalar(lowerRight, aAxis)); + + //Project the corners of the current Rectangle on to the Axis and + //get a scalar value of that project we can then use for comparison + //List aRectangleBScalars = new List(); + CalcCorners(ref upperLeft, ref upperRight, ref lowerLeft, ref lowerRight, a, rotationA, originA); + aRectangleBScalars[0] = (GenerateScalar(upperLeft, aAxis)); + aRectangleBScalars[1] = (GenerateScalar(upperRight, aAxis)); + aRectangleBScalars[2] = (GenerateScalar(lowerLeft, aAxis)); + aRectangleBScalars[3] = (GenerateScalar(lowerRight, aAxis)); + + //Get the Maximum and Minium Scalar values for each of the Rectangles + int aRectangleAMinimum = aRectangleAScalars.Min(); + int aRectangleAMaximum = aRectangleAScalars.Max(); + int aRectangleBMinimum = aRectangleBScalars.Min(); + int aRectangleBMaximum = aRectangleBScalars.Max(); + + //If we have overlaps between the Rectangles (i.e. Min of B is less than Max of A) + //then we are detecting a collision between the rectangles on this Axis + if (aRectangleBMinimum <= aRectangleAMaximum && aRectangleBMaximum >= aRectangleAMaximum) + { + //Console.WriteLine((aRectangleAMaximum - aRectangleBMinimum) * -aAxis); + return true; + } + else if (aRectangleAMinimum <= aRectangleBMaximum && aRectangleAMaximum >= aRectangleBMaximum) + { + //Console.WriteLine((aRectangleBMaximum - aRectangleAMinimum) * -aAxis); + return true; + } + + return false; + } + + private static Vector2 AxisCollisionMTD(Rectangle a, float rotationA, Vector2 originA, Rectangle b, float rotationB, Vector2 originB, Vector2 aAxis) + { + //Project the corners of the Rectangle we are checking on to the Axis and + //get a scalar value of that project we can then use for comparison + //List aRectangleAScalars = new List(); + Vector2 upperLeft = new Vector2(); + Vector2 upperRight = new Vector2(); + Vector2 lowerLeft = new Vector2(); + Vector2 lowerRight = new Vector2(); + CalcCorners(ref upperLeft, ref upperRight, ref lowerLeft, ref lowerRight, b, rotationB, originB); + + aRectangleAScalars[0] = (GenerateScalar(upperLeft, aAxis)); + aRectangleAScalars[1] = (GenerateScalar(upperRight, aAxis)); + aRectangleAScalars[2] = (GenerateScalar(lowerLeft, aAxis)); + aRectangleAScalars[3] = (GenerateScalar(lowerRight, aAxis)); + + //Project the corners of the current Rectangle on to the Axis and + //get a scalar value of that project we can then use for comparison + //List aRectangleBScalars = new List(); + CalcCorners(ref upperLeft, ref upperRight, ref lowerLeft, ref lowerRight, a, rotationA, originA); + aRectangleBScalars[0] = (GenerateScalar(upperLeft, aAxis)); + aRectangleBScalars[1] = (GenerateScalar(upperRight, aAxis)); + aRectangleBScalars[2] = (GenerateScalar(lowerLeft, aAxis)); + aRectangleBScalars[3] = (GenerateScalar(lowerRight, aAxis)); + + //Get the Maximum and Minium Scalar values for each of the Rectangles + int aRectangleAMinimum = aRectangleAScalars.Min(); + int aRectangleAMaximum = aRectangleAScalars.Max(); + int aRectangleBMinimum = aRectangleBScalars.Min(); + int aRectangleBMaximum = aRectangleBScalars.Max(); + //If we have overlaps between the Rectangles (i.e. Min of B is less than Max of A) + //then we are detecting a collision between the rectangles on this Axis + if (aRectangleBMinimum <= aRectangleAMaximum && aRectangleBMaximum >= aRectangleAMaximum) + { + return (aRectangleAMaximum - aRectangleBMinimum) * aAxis; + } + else if (aRectangleAMinimum <= aRectangleBMaximum && aRectangleAMaximum >= aRectangleBMaximum) + { + return (aRectangleBMaximum - aRectangleAMinimum) * -aAxis; + } + return Vector2.Zero; + } + + /// + /// Generates a scalar value that can be used to compare where corners of + /// a rectangle have been projected onto a particular axis. + /// + /// + /// + /// + private static int GenerateScalar(Vector2 theRectangleCorner, Vector2 theAxis) + { + //Using the formula for Vector projection. Take the corner being passed in + //and project it onto the given Axis + float aNumerator = (theRectangleCorner.X * theAxis.X) + (theRectangleCorner.Y * theAxis.Y); + float aDenominator = (theAxis.X * theAxis.X) + (theAxis.Y * theAxis.Y); + float aDivisionResult = aNumerator / aDenominator; + Vector2 aCornerProjected = new Vector2(aDivisionResult * theAxis.X, aDivisionResult * theAxis.Y); + + //Now that we have our projected Vector, calculate a scalar of that projection + //that can be used to more easily do comparisons + float aScalar = (theAxis.X * aCornerProjected.X) + (theAxis.Y * aCornerProjected.Y); + return (int)aScalar; + } + + /* + * + * This function takes the first hitbox, finds the center, then does a distance + * check to the center of the second hitbox + * + */ + public static bool CircleIntersects( Rectangle a, float radius, Rectangle b) + { + // check if two Rectangles intersect + //if( a.Left + float deltaX = a.Center.X-b.Center.X; + float deltaY = a.Center.Y-b.Center.Y; + float distanceBetween = (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY ); + + if (distanceBetween <= radius) + { + return true; + } + else + { + return false; + } + } + + // Thank you Microsoft for intellisense with a name like that. ;) + public static Vector2 CalculateMTD(Rectangle left, Rectangle right) + { + // Our displacement result vector containing the translation (movement) information + // that resolves our intersection. + Vector2 result = Vector2.Zero; + + // This is re-used to calculate the difference in distance between sides. + float difference = 0.0f; + + // This stores the absolute minimum distance we'll need to separate our colliding object. + float minimumTranslationDistance = 0f; + + // Axis stores the value of X or Y. X = 0, Y = 1. + // Side stores the value of left (-1) or right (+1). + // They're used later in calculating the result vector. + int axis = 0, side = 0; + + // Left + difference = left.Right - right.Left; + if (difference < 0.0f) + { + return Vector2.Zero; + } + + { + // These braces are superfluous but should make it more + //clear that they're similiar to the if statements below. + minimumTranslationDistance = difference; + axis = 0; + side = -1; + } + + // Right + difference = right.Right - left.Left; + if (difference < 0.0f) + { + return Vector2.Zero; + } + if (difference < minimumTranslationDistance) + { + minimumTranslationDistance = difference; + axis = 0; + side = 1; + } + + // Down + difference = left.Bottom - right.Top; + if (difference < 0.0f) + { + return Vector2.Zero; + } + if (difference < minimumTranslationDistance) + { + minimumTranslationDistance = difference; + axis = 1; + side = -1; + } + + // Up + difference = right.Bottom - left.Top; + if (difference < 0.0f) + { + return Vector2.Zero; + } + if (difference < minimumTranslationDistance) + { + minimumTranslationDistance = difference; + axis = 1; + side = 1; + } + + // Intersection occurred: + if (axis == 1) // Y Axis + result.Y = (float)side * minimumTranslationDistance; + else // X Axis + result.X = (float)side * minimumTranslationDistance; + + return result; + } + + public static Rectangle RotatedRectBounds(Rectangle rect, Vector2 rotationOrigin, float degreesRotation) + { + float leftBound = float.MaxValue, topBound = float.MaxValue, rightBound = -float.MaxValue, bottomBound = -float.MaxValue; + Vector2 upperLeft = new Vector2(); + Vector2 upperRight = new Vector2(); + Vector2 lowerLeft = new Vector2(); + Vector2 lowerRight = new Vector2(); + CalcCorners(ref upperLeft, ref upperRight, ref lowerLeft, ref lowerRight, rect, degreesRotation, rotationOrigin); + + if (upperLeft.X < leftBound) leftBound = upperLeft.X; + if (upperRight.X < leftBound) leftBound = upperRight.X; + if (lowerLeft.X < leftBound) leftBound = lowerLeft.X; + if (lowerRight.X < leftBound) leftBound = lowerRight.X; + + if (upperLeft.Y < topBound) topBound = upperLeft.Y; + if (upperRight.Y < topBound) topBound = upperRight.Y; + if (lowerLeft.Y < topBound) topBound = lowerLeft.Y; + if (lowerRight.Y < topBound) topBound = lowerRight.Y; + + if (upperLeft.X > rightBound) rightBound = (upperLeft.X); + if (upperRight.X > rightBound) rightBound = (upperRight.X ); + if (lowerLeft.X > rightBound) rightBound = (lowerLeft.X ); + if (lowerRight.X > rightBound) rightBound = (lowerRight.X ); + + if (upperLeft.Y > bottomBound) bottomBound = (upperLeft.Y); + if (upperRight.Y > bottomBound) bottomBound = (upperRight.Y); + if (lowerLeft.Y > bottomBound) bottomBound = (lowerLeft.Y); + if (lowerRight.Y > bottomBound) bottomBound = (lowerRight.Y); + + return new Rectangle((int)leftBound, (int)topBound, (int)(rightBound - leftBound), (int)(bottomBound - topBound)); + } + + public static Vector2 LineToLineIntersect(Vector2 pt1Start, Vector2 pt1End, Vector2 pt2Start, Vector2 pt2End ) + { + float ua = (pt2End.X - pt2Start.X) * (pt1Start.Y - pt2Start.Y) - (pt2End.Y - pt2Start.Y) * (pt1Start.X - pt2Start.X); + float ub = (pt1End.X - pt1Start.X) * (pt1Start.Y - pt2Start.Y) - (pt1End.Y - pt1Start.Y) * (pt1Start.X - pt2Start.X); + float denominator = (pt2End.Y - pt2Start.Y) * (pt1End.X - pt1Start.X) - (pt2End.X - pt2Start.X) * (pt1End.Y - pt1Start.Y); + + Vector2 intersectionPoint = Vector2.Zero; + + if (Math.Abs(denominator) <= 0.00001f) + { + if (Math.Abs(ua) <= 0.00001f && Math.Abs(ub) <= 0.00001f) + { + intersectionPoint = (pt1Start + pt1End) / 2; + } + } + else + { + ua /= denominator; + ub /= denominator; + + if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) + { + intersectionPoint.X = pt1Start.X + ua * (pt1End.X - pt1Start.X); + intersectionPoint.Y = pt1Start.Y + ua * (pt1End.Y - pt1Start.Y); + } + } + + return intersectionPoint; + } + + public static Vector2 GetIntersectionDepth(Rectangle rectA, Rectangle rectB) + { + // Calculate half sizes. + float halfWidthA = rectA.Width / 2.0f; + float halfHeightA = rectA.Height / 2.0f; + float halfWidthB = rectB.Width / 2.0f; + float halfHeightB = rectB.Height / 2.0f; + + // Calculate centers. + Vector2 centerA = new Vector2(rectA.Left + halfWidthA, rectA.Top + halfHeightA); + Vector2 centerB = new Vector2(rectB.Left + halfWidthB, rectB.Top + halfHeightB); + + // Calculate current and minimum-non-intersecting distances between centers. + float distanceX = centerA.X - centerB.X; + float distanceY = centerA.Y - centerB.Y; + float minDistanceX = halfWidthA + halfWidthB; + float minDistanceY = halfHeightA + halfHeightB; + + // If we are not intersecting at all, return (0, 0). + if (Math.Abs(distanceX) >= minDistanceX || Math.Abs(distanceY) >= minDistanceY) + return Vector2.Zero; + + // Calculate and return intersection depths. + float depthX = distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX; + float depthY = distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY; + return new Vector2(depthX, depthY); + } + } +} diff --git a/DS2DEngine/src/Consts.cs b/DS2DEngine/src/Consts.cs new file mode 100644 index 0000000..ae600fd --- /dev/null +++ b/DS2DEngine/src/Consts.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public class Consts + { + public const bool DEBUG_ShowSafeZones = true; + + public const float FRAMERATE_CAP = 1 / 30f; + + // Hitbox Consts. + public const int NULL_HITBOX = -1; + public const int TERRAIN_HITBOX = 0; + public const int WEAPON_HITBOX = 1; + public const int BODY_HITBOX = 2; + + public const int COLLISIONRESPONSE_NULL = 0; + public const int COLLISIONRESPONSE_TERRAIN = 1; + public const int COLLISIONRESPONSE_FIRSTBOXHIT = 2; + public const int COLLISIONRESPONSE_SECONDBOXHIT = 3; + } +} diff --git a/DS2DEngine/src/DS2DPool.cs b/DS2DEngine/src/DS2DPool.cs new file mode 100644 index 0000000..a67f78f --- /dev/null +++ b/DS2DEngine/src/DS2DPool.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public class DS2DPool : IDisposableObj + { + private int m_poolSize; + private int m_numActiveObjs; + + private Stack m_ObjStack; + private List m_activeObjsList; // Since objects are constantly being added and removed, it might be a good idea to turn this into a linked list. + + private bool m_isDisposed = false; + + public DS2DPool() + { + m_ObjStack = new Stack(); + m_activeObjsList = new List(); + + m_poolSize = 0; + m_numActiveObjs = 0; + } + + public void AddToPool(OBJ_T obj) + { + m_ObjStack.Push(obj); + m_poolSize++; + + //if (!(obj is IPoolableObj)) + // throw new Exception("Cannot add object to pool. Please ensure that the object inherits from the IPoolableObj interface"); + } + + public OBJ_T CheckOut() + { + if (m_poolSize - m_numActiveObjs < 1) + throw new Exception("Resource pool out of items"); + + m_numActiveObjs++; + OBJ_T objToReturn = m_ObjStack.Pop(); + //(objToReturn as IPoolableObj).IsCheckedOut = true; + m_activeObjsList.Add(objToReturn); + return objToReturn; + } + + + public OBJ_T CheckOutReturnNull() + { + if (m_poolSize - m_numActiveObjs < 1) + return default(OBJ_T); + + m_numActiveObjs++; + OBJ_T objToReturn = m_ObjStack.Pop(); + //(objToReturn as IPoolableObj).IsCheckedOut = true; + m_activeObjsList.Add(objToReturn); + return objToReturn; + } + + + public void CheckIn(OBJ_T obj) + { + // Make sure to clear loc ID when TextObj is freed. This is because + // next use of this TextObj might not have loc ID and should not be + // refreshed on language change. + if (obj is TextObj) + (obj as TextObj).locStringID = ""; + + //This pool has been tested and the check below is unnecessary, so for performance purposes it has been removed. + //if ((obj as IPoolableObj).IsCheckedOut == true) + { + //(obj as IPoolableObj).IsCheckedOut = false; + m_numActiveObjs--; + m_ObjStack.Push(obj); + m_activeObjsList.Remove(obj); + } + } + + public void Dispose() + { + if (IsDisposed == false) + { + // Checkins all active objects before disposing of the pool. + while (m_activeObjsList.Count > 0) + { + CheckIn(m_activeObjsList[m_activeObjsList.Count-1]); + } + m_activeObjsList.Clear(); + + foreach (OBJ_T obj in m_ObjStack) + { + IDisposableObj disposableObj = obj as IDisposableObj; + if (disposableObj != null) + disposableObj.Dispose(); + } + m_ObjStack.Clear(); + m_isDisposed = true; + } + } + + public int NumActiveObjs + { + get { return m_numActiveObjs; } + } + + public int TotalPoolSize + { + get { return m_poolSize; } + } + + public int CurrentPoolSize + { + get { return TotalPoolSize - NumActiveObjs; } + } + + public List ActiveObjsList + { + get { return m_activeObjsList; } + } + + public Stack Stack + { + get { return m_ObjStack; } + } + + public bool IsDisposed + { + get { return m_isDisposed; } + } + } +} diff --git a/DS2DEngine/src/DebugHelper.cs b/DS2DEngine/src/DebugHelper.cs new file mode 100644 index 0000000..877e204 --- /dev/null +++ b/DS2DEngine/src/DebugHelper.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public class DebugHelper + { + public static Texture2D CreateCircleTexture(int radius, GraphicsDevice graphicsDevice) + { + int outerRadius = radius * 2 + 2; // So circle doesn't go out of bounds + Texture2D texture = new Texture2D(graphicsDevice, outerRadius, outerRadius); + + Color[] data = new Color[outerRadius * outerRadius]; + + // Colour the entire texture transparent first. + for (int i = 0; i < data.Length; i++) + data[i] = Color.Transparent; + + // Work out the minimum step necessary using trigonometry + sine approximation. + double angleStep = 1f / radius; + + for (double angle = 0; angle < Math.PI * 2; angle += angleStep) + { + // Use the parametric definition of a circle: http://en.wikipedia.org/wiki/Circle#Cartesian_coordinates + int x = (int)Math.Round(radius + radius * Math.Cos(angle)); + int y = (int)Math.Round(radius + radius * Math.Sin(angle)); + + data[y * outerRadius + x + 1] = Color.White; + } + + texture.SetData(data); + return texture; + } + } +} diff --git a/DS2DEngine/src/EngineEV.cs b/DS2DEngine/src/EngineEV.cs new file mode 100644 index 0000000..b32436d --- /dev/null +++ b/DS2DEngine/src/EngineEV.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace DS2DEngine +{ + public class EngineEV + { + public static int ScreenWidth = 800; + public static int ScreenHeight = 600; + + public static Vector2 ScreenRatio = Vector2.One; + + public static void RefreshEngine(GraphicsDevice graphicsDevice) + { + ScreenRatio = new Vector2((float)ScreenWidth / graphicsDevice.Viewport.Width, (float)ScreenHeight / graphicsDevice.Viewport.Height); + } + } +} diff --git a/DS2DEngine/src/FrameSoundObj.cs b/DS2DEngine/src/FrameSoundObj.cs new file mode 100644 index 0000000..10a8d47 --- /dev/null +++ b/DS2DEngine/src/FrameSoundObj.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public class FrameSoundObj : IDisposableObj + { + private int m_frame; + private IAnimateableObj m_obj; + private GameObj m_listener; + private string[] m_sounds; + private bool m_soundPlaying = false; + private bool m_isDisposed = false; + + public FrameSoundObj(IAnimateableObj obj, int frame, params string[] sounds) + { + m_obj = obj; + m_frame = frame; + m_sounds = sounds; + m_listener = null; + } + + public FrameSoundObj(IAnimateableObj obj, GameObj listener, int frame, params string[] sounds) + { + m_obj = obj; + m_frame = frame; + m_sounds = sounds; + m_listener = listener; + } + + public void Update() + { + if (m_soundPlaying == false && m_obj.CurrentFrame == m_frame) + { + m_soundPlaying = true; + if (m_listener == null) + SoundManager.PlaySound(m_sounds); + else + SoundManager.Play3DSound((m_obj as GameObj), m_listener, m_sounds); + } + + if (m_obj.CurrentFrame != m_frame) + m_soundPlaying = false; + } + + public void Dispose() + { + if (m_isDisposed == false) + { + m_isDisposed = true; + Array.Clear(m_sounds, 0, m_sounds.Length); + m_sounds = null; + m_obj = null; + m_listener = null; + } + } + + public bool IsDisposed + { + get { return m_isDisposed; } + } + } +} diff --git a/DS2DEngine/src/GameObjs/BackgroundObj.cs b/DS2DEngine/src/GameObjs/BackgroundObj.cs new file mode 100644 index 0000000..cd4b9f4 --- /dev/null +++ b/DS2DEngine/src/GameObjs/BackgroundObj.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public class BackgroundObj : SpriteObj + { + public Vector2 ParallaxSpeed = Vector2.Zero; + //public Vector2 ScrollSpeed = Vector2.Zero; + //public bool Scrollable = false; + private bool m_repeatHorizontal = false; + private bool m_repeatVertical = false; + private RenderTarget2D m_repeatedTexture; + //private Vector2 m_cameraStartPos = Vector2.Zero; + private Vector2 m_retainedScale; // The scale that the texture needs to be at to retain its original size (since it was modified to match a power of 2 size). + + private SamplerState m_samplerState; + + public bool isContentLost + { + get + { + if (m_repeatedTexture == null) + return false; + return m_repeatedTexture.IsContentLost; + } + } + + public BackgroundObj(string spriteName) + : base(spriteName) + { + this.ForceDraw = true; + } + + public void SetRepeated(bool repeatHorizontal, bool repeatVertical, Camera2D camera, SamplerState samplerState = null) + { + m_samplerState = samplerState; + + //if (m_repeatedTexture != null && (repeatHorizontal == true && repeatVertical == true)) + if (m_repeatedTexture != null) + { + m_repeatedTexture.Dispose(); + m_repeatedTexture = null; + } + + if (m_repeatedTexture == null && (repeatHorizontal == true || repeatVertical == true)) + { + m_repeatedTexture = this.ConvertToTexture(camera, true, samplerState); + m_retainedScale = new Vector2(this.Width / (float)m_repeatedTexture.Width, this.Height / (float)m_repeatedTexture.Height); + } + //else if (m_repeatedTexture != null && (repeatHorizontal == true && repeatVertical == true)) + //{ + // m_repeatedTexture.Dispose(); + // m_repeatedTexture = null; + //} + m_repeatHorizontal = repeatHorizontal; + m_repeatVertical = repeatVertical; + } + + public void ChangeSprite(string spriteName, Camera2D camera) + { + base.ChangeSprite(spriteName); + SetRepeated(m_repeatHorizontal, m_repeatVertical, camera, m_samplerState); + } + + + float m_totalXParallax = 0; + float m_totalYParallax = 0; + public override void Draw(Camera2D camera) + { + //if (Scrollable == true && m_cameraStartPos != Vector2.Zero) + { + m_totalXParallax += (this.ParallaxSpeed.X * 60 * camera.ElapsedTotalSeconds); + m_totalYParallax += (this.ParallaxSpeed.Y * 60 * camera.ElapsedTotalSeconds); + + if (RepeatHorizontal == true) + m_totalXParallax = m_totalXParallax % (this.Width * m_retainedScale.X); // Don't multiply by ScaleX because Width already does that. + if (RepeatVertical == true) + m_totalYParallax = m_totalYParallax % (this.Height * m_retainedScale.Y); + } + // m_cameraStartPos = camera.Position; + + if (RepeatHorizontal == true || RepeatVertical == true) + { + float posX = this.X; + float posY = this.Y; + int width = (int)(m_repeatedTexture.Width * ScaleX * m_retainedScale.X); + int height = (int)(m_repeatedTexture.Height * ScaleY * m_retainedScale.Y); + //int width = (int)(camera.GraphicsDevice.Viewport.Width * (1/(Scale.X * m_retainedScale.X))); + //int height = (int)(camera.GraphicsDevice.Viewport.Height * (1/(ScaleY * m_retainedScale.Y))); + + // Problem code below + if (RepeatHorizontal == true) + { + //posX = this.X - camera.GraphicsDevice.Viewport.Width * ScaleX * m_retainedScale.X; + //posX = this.X - camera.GraphicsDevice.Viewport.Width; + posX = this.X + m_totalXParallax - (m_repeatedTexture.Width * m_retainedScale.X * ScaleX * 5); + width = EngineEV.ScreenWidth * 10; //camera.GraphicsDevice.Viewport.Width * 10; + } + if (RepeatVertical == true) + { + //posY = this.Y - camera.GraphicsDevice.Viewport.Height * ScaleY * m_retainedScale.Y; + posY = this.Y + m_totalYParallax - (m_repeatedTexture.Height * m_retainedScale.Y * ScaleY * 5); + height = EngineEV.ScreenHeight * 10; //camera.GraphicsDevice.Viewport.Height * 10; + } + ///////////////////// + //camera.Draw(m_repeatedTexture, new Vector2(this.X + -GlobalEV.ScreenWidth, this.Y + -GlobalEV.ScreenHeight), new Rectangle(0, 0, GlobalEV.ScreenWidth * 3, GlobalEV.ScreenHeight * 3), this.TextureColor, 0, Vector2.Zero, this.Scale, SpriteEffects.None, 0); + camera.Draw(m_repeatedTexture, new Vector2(posX, posY), new Rectangle(0, 0, width, height), this.TextureColor * this.Opacity, this.Rotation, Vector2.Zero, m_retainedScale * Scale, this.Flip, 0); + //camera.Draw(m_repeatedTexture, this.Position, Color.White); + } + else + { + base.Draw(camera); + } + } + + public bool RepeatHorizontal + { + get { return m_repeatHorizontal; } + } + + public bool RepeatVertical + { + get { return m_repeatVertical; } + } + + protected override GameObj CreateCloneInstance() + { + return new BackgroundObj(_spriteName); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + // This one needs to be fixed. + } + + public override void Dispose() + { + if (IsDisposed == false) + { + if (m_repeatedTexture != null) + { + m_repeatedTexture.Dispose(); + m_repeatedTexture = null; + } + m_samplerState = null; + base.Dispose(); + } + } + + public RenderTarget2D Texture + { + get { return m_repeatedTexture; } + } + } +} diff --git a/DS2DEngine/src/GameObjs/BlankObj.cs b/DS2DEngine/src/GameObjs/BlankObj.cs new file mode 100644 index 0000000..c7c7ab1 --- /dev/null +++ b/DS2DEngine/src/GameObjs/BlankObj.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + + // A blank, invisible object that is mainly used for setting triggers. + public class BlankObj : GameObj, IPhysicsObj + { + public LinkedListNode Node { get; set; } + + public bool CollidesLeft { get; set; } + public bool CollidesRight { get; set; } + public bool CollidesTop { get; set; } + public bool CollidesBottom { get; set; } + + public int CollisionTypeTag { get; set; } + private Vector2 _acceleration = Vector2.Zero; + public Boolean IsWeighted { get; set; } + public Boolean IsCollidable { get; set; } + public bool AccelerationXEnabled { get; set; } + public bool AccelerationYEnabled { get; set; } + + public bool DisableHitboxUpdating { get; set; } + + private List _collisionBoxes = null; + public PhysicsManager PhysicsMngr { get; set; } + private Rectangle m_terrainBounds = new Rectangle(); + public bool DisableAllWeight { get; set; } + public bool SameTypesCollide { get; set; } + public bool DisableGravity { get; set; } + + // You must pass in the width and height into the constructor since these properties are currently read-only. + public BlankObj(int width, int height) + { + _width = width; + _height = height; + IsWeighted = false; + IsCollidable = false; + _collisionBoxes = new List(); + + CollidesLeft = true; + CollidesRight = true; + CollidesTop = true; + CollidesBottom = true; + + AccelerationXEnabled = true; + AccelerationYEnabled = true; + + DisableHitboxUpdating = true; + } + + public void UpdatePhysics(GameTime gameTime) + { + if (AccelerationXEnabled == true) + this.X += _acceleration.X; + if (AccelerationYEnabled == true) + this.Y += _acceleration.Y; + } + + public void UpdateCollisionBoxes() { } + + public void AddCollisionBox(int xPos, int yPos, int width, int height, int collisionType) + { + _collisionBoxes.Add(new CollisionBox((int)(xPos), (int)(yPos), width, height, collisionType, this)); + if (collisionType == Consts.TERRAIN_HITBOX) + m_terrainBounds = new Rectangle(xPos, yPos, width, height); + } + + public void ClearCollisionBoxes() + { + _collisionBoxes.Clear(); + } + + public virtual void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + if (this.IsWeighted == true && collisionResponseType == Consts.COLLISIONRESPONSE_TERRAIN) + { + this.AccelerationX = 0; + if (this.AccelerationY > 0) + this.AccelerationY = 0; + Vector2 mtdPos = CollisionMath.CalculateMTD(thisBox.AbsRect, otherBox.AbsRect); + this.X += mtdPos.X; + this.Y += mtdPos.Y; + } + } + + public void RemoveFromPhysicsManager() + { + if (this.PhysicsMngr != null) + this.PhysicsMngr.RemoveObject(this); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + if (PhysicsMngr != null) + PhysicsMngr.RemoveObject(this); + + Node = null; + + foreach (CollisionBox box in _collisionBoxes) + box.Dispose(); + + _collisionBoxes.Clear(); + base.Dispose(); + } + } + + protected override GameObj CreateCloneInstance() + { + return new BlankObj(_width, _height); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + BlankObj clone = obj as BlankObj; + if (this.PhysicsMngr != null) + this.PhysicsMngr.AddObject(clone); + + clone.CollidesLeft = this.CollidesLeft; + clone.CollidesRight = this.CollidesRight; + clone.CollidesBottom = this.CollidesBottom; + clone.CollidesTop = this.CollidesTop; + + clone.IsWeighted = this.IsWeighted; + clone.IsCollidable = this.IsCollidable; + clone.DisableHitboxUpdating = this.DisableHitboxUpdating; + clone.CollisionTypeTag = this.CollisionTypeTag; + clone.DisableAllWeight = this.DisableAllWeight; + clone.SameTypesCollide = this.SameTypesCollide; + + clone.AccelerationX = this.AccelerationX; + clone.AccelerationY = this.AccelerationY; + clone.AccelerationXEnabled = this.AccelerationXEnabled; + clone.AccelerationYEnabled = this.AccelerationYEnabled; + clone.DisableGravity = this.DisableGravity; + } + + public override void PopulateFromXMLReader(System.Xml.XmlReader reader, System.Globalization.CultureInfo ci) // Needed because this is a hacked together physics object. + { + base.PopulateFromXMLReader(reader, ci); + + if (reader.MoveToAttribute("CollidesTop")) + this.CollidesTop = bool.Parse(reader.Value); + if (reader.MoveToAttribute("CollidesBottom")) + this.CollidesBottom = bool.Parse(reader.Value); + if (reader.MoveToAttribute("CollidesLeft")) + this.CollidesLeft = bool.Parse(reader.Value); + if (reader.MoveToAttribute("CollidesRight")) + this.CollidesRight = bool.Parse(reader.Value); + if (reader.MoveToAttribute("Collidable")) + this.IsCollidable = bool.Parse(reader.Value); + if (reader.MoveToAttribute("Weighted")) + this.IsWeighted = bool.Parse(reader.Value); + } + + public List CollisionBoxes + { + get { return _collisionBoxes; } + } + + public Rectangle TerrainBounds + { + get { return new Rectangle((int)(this.X + m_terrainBounds.X), (int)(this.Y + m_terrainBounds.Y), m_terrainBounds.Width, m_terrainBounds.Height); } + } + + public float AccelerationX + { + set { _acceleration.X = value; } + get { return _acceleration.X; } + } + + public float AccelerationY + { + set { _acceleration.Y = value; } + get { return _acceleration.Y; } + } + + public void SetWidth(int width) + { + _width = width; + } + + public void SetHeight(int height) + { + _height = height; + } + + public bool HasTerrainHitBox + { + get + { + foreach (CollisionBox box in _collisionBoxes) + { + if (box.Type == Consts.TERRAIN_HITBOX) + return true; + } + return false; + } + } + + public bool DisableCollisionBoxRotations + { + set + { + foreach (CollisionBox box in _collisionBoxes) + box.DisableRotation = value; + } + get + { + foreach (CollisionBox box in _collisionBoxes) + return box.DisableRotation; + return false; + } + } + } +} diff --git a/DS2DEngine/src/GameObjs/CollisionBox.cs b/DS2DEngine/src/GameObjs/CollisionBox.cs new file mode 100644 index 0000000..5a0648a --- /dev/null +++ b/DS2DEngine/src/GameObjs/CollisionBox.cs @@ -0,0 +1,255 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public class CollisionBox : IDisposableObj + { + private Rectangle _rectangle; + private int _collisionType; + + private GameObj m_parentObj; + private float m_rotation; + public bool WasAdded = false; + + private bool m_isDisposed = false; + public bool DisableRotation = false; + + private Vector2 _cachedRotatedPoint; + private Rectangle _cachedAbsRect; + private float _cachedAbsRotation; + + public CollisionBox(GameObj parent) + { + _rectangle = new Rectangle(); + _cachedRotatedPoint = new Vector2(); + _cachedAbsRect = new Rectangle(); + _cachedAbsRotation = 0.0f; + m_parentObj = parent; + m_rotation = 0; + + UpdateCachedValues(); + } + + public CollisionBox(int x, int y, int width, int height, int type, GameObj parent) + { + _rectangle = new Rectangle(x, y, width, height); + _cachedRotatedPoint = new Vector2(); + _cachedAbsRect = new Rectangle(); + _cachedAbsRotation = 0.0f; + _collisionType = type; + m_parentObj = parent; + m_rotation = 0; + + UpdateCachedValues(); + } + + public void UpdateCachedValues() + { + _cachedRotatedPoint = RotatedPoint; + _cachedAbsRect = new Rectangle((int)_cachedRotatedPoint.X, (int)_cachedRotatedPoint.Y, Width, Height); + _cachedAbsRotation = AbsRotationNoCache(); + } + + public int X + { + set { _rectangle.X = value; } + get + { + if (m_rotation == 0 && m_parentObj.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally) + return (int)-(_rectangle.X + _rectangle.Width); + else + return _rectangle.X; + } + } + + public int Y + { + set { _rectangle.Y = value; } + get { return _rectangle.Y; } + } + + public int Width + { + set { _rectangle.Width = value; } + get { return _rectangle.Width; } + } + + public int Height + { + set { _rectangle.Height = value; } + get { return _rectangle.Height; } + } + + public int Type + { + set { _collisionType = value; } + get { return _collisionType; } + } + + public override String ToString() + { + return "[x: " + _rectangle.X + ", y: " + _rectangle.Y + ", absX: " + AbsX + ", absY: " + AbsY + ", width: " + _rectangle.Width + ", Height: " + _rectangle.Height + ", Type: " + _collisionType + "]"; + } + + public Rectangle Rect + { + get { return _rectangle; } + } + + public int AbsX + { + get + { + if (this.Parent.UseCachedValues == true) + return (int)(_cachedRotatedPoint.X); + else + return (int)(RotatedPoint.X); + } + } + + public int AbsY + { + get + { + if (this.Parent.UseCachedValues == true) + return (int)(_cachedRotatedPoint.Y); + else + return (int)(RotatedPoint.Y); + } + } + + private float Rotation + { + get + { + if (DisableRotation == true) + return 0; + + if (m_parentObj.Parent != null) + return m_parentObj.Parent.Rotation + m_parentObj.Rotation; + else + return m_parentObj.Rotation; + } + } + + private float AbsRotationNoCache() + { + if (DisableRotation == true) + return 0; + + if (m_parentObj.Parent != null) + return m_parentObj.Parent.Rotation + m_parentObj.Rotation + InternalRotation; + else + return m_parentObj.Rotation + InternalRotation; + } + + public float AbsRotation + { + get + { + if (this.Parent.UseCachedValues == true) + return _cachedAbsRotation; + else + return AbsRotationNoCache(); + } + } + + public float InternalRotation + { + get + { + if (m_parentObj.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally) + return MathHelper.ToDegrees(-m_rotation); + else + return MathHelper.ToDegrees(m_rotation); + } + set { m_rotation = MathHelper.ToRadians(value); } + } + + private Vector2 RotatedPoint + { + get + { + if (Rotation == 0) + { + if (m_rotation != 0 && m_parentObj.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally) + { + Vector2 topRight = CollisionMath.UpperRightCorner(new Rectangle(this.X, this.Y, Width, Height), MathHelper.ToDegrees(m_rotation), Vector2.Zero); + topRight.X = -topRight.X; + return new Vector2(topRight.X + m_parentObj.AbsX, topRight.Y + m_parentObj.AbsY); + } + else + return new Vector2(this.X + m_parentObj.AbsX, this.Y + m_parentObj.AbsY); + } + else + { + //if (m_parentObj.Parent != null) + if (m_rotation != 0 && m_parentObj.Parent != null && m_parentObj.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally) + { + // if (m_parentObj.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally && m_rotation != 0) + { + + Vector2 topRight = CollisionMath.UpperRightCorner(new Rectangle(this.X, this.Y, Width, Height), MathHelper.ToDegrees(m_rotation), Vector2.Zero); + topRight.X = -topRight.X; + return CDGMath.RotatedPoint(new Vector2(topRight.X + m_parentObj.AbsX, topRight.Y + m_parentObj.AbsY), new Vector2(m_parentObj.Parent.AbsX, m_parentObj.Parent.AbsY), this.Rotation); + } + // else + // return CDGMath.RotatedPoint(new Vector2(this.X + m_parentObj.AbsX, this.Y + m_parentObj.AbsY), new Vector2(m_parentObj.Parent.AbsX, m_parentObj.Parent.AbsY), this.Rotation); + } + else + return CDGMath.RotatedPoint(new Vector2(this.X + m_parentObj.AbsX, this.Y + m_parentObj.AbsY), new Vector2(m_parentObj.AbsX, m_parentObj.AbsY), this.Rotation); + } + } + } + + public Rectangle AbsRect + { + get + { + if (this.Parent.UseCachedValues == true) + return _cachedAbsRect; + else + return new Rectangle(AbsX, AbsY, Width, Height); + } + } + + public Rectangle NonRotatedAbsRect + { + get { return new Rectangle((int)(this.X + m_parentObj.AbsX), (int)(this.Y + m_parentObj.AbsY), Width, Height); } + } + + public GameObj Parent + { + get { return m_parentObj; } + } + + public GameObj AbsParent + { + get + { + if (m_parentObj.Parent == null) + return m_parentObj; + else + return m_parentObj.Parent; + } + } + + public void Dispose() + { + if (m_isDisposed == false) + { + m_isDisposed = true; + m_parentObj = null; + } + } + + public bool IsDisposed + { + get { return m_isDisposed; } + } + } +} diff --git a/DS2DEngine/src/GameObjs/GameObj.cs b/DS2DEngine/src/GameObjs/GameObj.cs new file mode 100644 index 0000000..99529a0 --- /dev/null +++ b/DS2DEngine/src/GameObjs/GameObj.cs @@ -0,0 +1,838 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input.Touch; +using InputSystem; +using System.Xml; +using System.Globalization; + +namespace DS2DEngine +{ + //TODO: Separate IDrawableObj from GameObj. + public abstract class GameObj : ITriggerableObj, IDrawableObj, IDisposableObj, ICloneable, IClickableObj + { + private Vector2 _position = Vector2.Zero; + protected Vector2 _anchor = Vector2.Zero; + protected int _width = 0; + protected int _height = 0; + protected Vector2 _scale = new Vector2(1,1); + public Boolean Visible { get; set; } + protected float _rotation = 0; + protected float _layer = 0; + protected float _orientation = 0; + protected Vector2 _heading = Vector2.Zero; + private ObjContainer _parent = null; + private ObjContainer _topmostParent = null; // Optimization for Flip test - calling up to test topmost parent is expensive + public bool AddToBounds = true; // Whether an object is added to the bounds of an object container or not. + public string Tag = ""; + + public float TurnSpeed = 2.0f; + + private bool m_forceDraw = false; + + protected SpriteEffects _flip = SpriteEffects.None; + + private float _speed = 0; // Speed represents the object's internal speed. + public float CurrentSpeed { get; set; } // Current Speed represents the object's actual speed. So it could have a speed of 10, but be moving at 0 (which means it's not moving at all). + + public string Name { get; set; } + + public int ID { get; set; } + + private bool m_isDisposed = false; + public bool IsDisposed { get { return m_isDisposed; } } + + public bool IsTriggered { get; set; } + public bool LockFlip { get; set; } + + public bool OverrideParentScale { get; set; } + + private bool _useCachedValues = false; + + public GameObj() + { + //GameObjHandler.GameObjList.Add(this); + Visible = true; + } + + public virtual void ChangeSprite(string spriteName) { } + + public virtual void Draw(Camera2D camera) { } + public virtual void DrawOutline(Camera2D camera) { } + + public void DrawBounds(Camera2D camera, Texture2D texture, Color color) + { + if (Parent != null) + camera.Draw(texture, new Rectangle((int)(Bounds.X + this.AbsX - (this.X * Parent.ScaleX)),(int)(Bounds.Y + this.AbsY - (this.Y * Parent.ScaleY)), Bounds.Width, Bounds.Height) , color); + else + camera.Draw(texture, Bounds, color); + } + + public void DrawAbsBounds(Camera2D camera, Texture2D texture, Color color) + { + camera.Draw(texture, AbsBounds, color); + } + + public virtual void PopulateFromXMLReader(XmlReader reader, CultureInfo ci) + { + if (reader.MoveToAttribute("Name")) + this.Name = reader.Value; + if (reader.MoveToAttribute("X")) + X = float.Parse(reader.Value, NumberStyles.Any, ci); + if (reader.MoveToAttribute("Y")) + Y = float.Parse(reader.Value, NumberStyles.Any, ci); + if (reader.MoveToAttribute("Width")) + _width = int.Parse(reader.Value, NumberStyles.Any, ci); + if (reader.MoveToAttribute("Height")) + _height = int.Parse(reader.Value, NumberStyles.Any, ci); + if (reader.MoveToAttribute("ScaleX")) + this.ScaleX = float.Parse(reader.Value, NumberStyles.Any, ci); + if (reader.MoveToAttribute("ScaleY")) + this.ScaleY = float.Parse(reader.Value, NumberStyles.Any, ci); + if (reader.MoveToAttribute("Rotation")) + this.Rotation= float.Parse(reader.Value, NumberStyles.Any, ci); + if (reader.MoveToAttribute("Tag")) + this.Tag= reader.Value; + if (reader.MoveToAttribute("Layer")) + this.Layer = int.Parse(reader.Value, NumberStyles.Any, ci); + + // Flip needs to be passed in as a bool instead of a SpriteEffects enum. + bool flip = false; + if (reader.MoveToAttribute("Flip")) + flip = bool.Parse(reader.Value); + + if (flip == true) + this.Flip = SpriteEffects.FlipHorizontally; + else + this.Flip = SpriteEffects.None; + } + + public virtual void Dispose() + { + //GameObjHandler.GameObjList.Remove(this); + _parent = null; + _topmostParent = null; + m_isDisposed = true; + } + + public object Clone() + { + GameObj obj = CreateCloneInstance(); + this.FillCloneInstance(obj); + return obj; + } + + protected abstract GameObj CreateCloneInstance(); + + protected virtual void FillCloneInstance(object obj) + { + // Must set flip to none before cloning data since flip affects some of the object's properties. + SpriteEffects storedFlip = this.Flip; + this.Flip = SpriteEffects.None; + + GameObj clone = obj as GameObj; + clone.Position = this.Position; + clone.Name = this.Name; + clone.Visible = this.Visible; + clone.Scale = this.Scale; + clone.Rotation = this.Rotation; + clone.Parent= this.Parent; + + clone.Anchor = this.Anchor; + clone.Orientation = this.Orientation; + clone.ForceDraw = this.ForceDraw; + clone.Tag = this.Tag; + clone.AddToBounds = this.AddToBounds; + clone.IsTriggered = this.IsTriggered; + clone.TurnSpeed = this.TurnSpeed; + clone.Speed = this.Speed; + clone.CurrentSpeed = this.CurrentSpeed; + clone.Layer = this.Layer; + clone.Heading = this.Heading; + clone.Opacity = this.Opacity; + clone.TextureColor = this.TextureColor; + + this.Flip = storedFlip; // Reset flip what it is supposed to be before cloning it. + clone.Flip = this.Flip; + clone.OverrideParentScale = this.OverrideParentScale; + clone.UseCachedValues = this.UseCachedValues; + } + + #region Properties + + public virtual int Width + { + get { return (int)(_width * ScaleX); } + } + + public virtual int Height + { + get { return (int)(_height * ScaleY); } + } + + public float Rotation + { + set { _rotation = MathHelper.ToRadians(value); } + get { return MathHelper.ToDegrees(_rotation); } + } + + public float Layer + { + set { _layer = value; } + get { return _layer; } + } + + public float X + { + set + { + _position.X = value; + + // This is what used to be here. If you read the logic, they all boiled down to the same thing :/ + //if (this.Flip == SpriteEffects.FlipHorizontally && Parent != null) + // _position.X = value; + // //_position.X = value / Parent.ScaleX; // Disabled this because calling ChangeSprite on scaled PhysicsObjectContainers resulted in wrong placements of the physics objects in the container. + //else + //{ + // if (Parent == null) + // _position.X = value; + // else + // _position.X = value; + // //_position.X = value / Parent.ScaleX; + //} + } + get + { + if (Parent == null || this.Flip != SpriteEffects.FlipHorizontally) + return _position.X; + return -_position.X * Parent.ScaleX; // otherwise flip it horizontally + } + } + + public float Y + { + set + { + _position.Y = value; + + // This is what used to be here. If you read the logic, they all boiled down to the same thing :/ + //if (Parent == null) + // _position.Y = value; + //else + // _position.Y = value; + // //_position.Y = value / Parent.ScaleY; + } + get + { + return _position.Y; + + // This is what used to be here. If you read the logic, they all boiled down to the same thing :/ + //if (Parent == null) + // return _position.Y; + //else + // return _position.Y;// *Parent.ScaleY; + } + } + + public Vector2 Position + { + set + { + if (Parent == null || Flip != SpriteEffects.FlipHorizontally) + _position = value; + else + _position = new Vector2(value.X, value.Y); + + // This is what used to be here. + //if (Flip == SpriteEffects.FlipHorizontally && Parent != null) + // _position = new Vector2(value.X, value.Y); + // //_position = new Vector2(value.X / Parent.ScaleX, value.Y / Parent.ScaleY); + //else + //{ + // if (Parent == null) + // _position = value; + // else + // _position = value; + // //_position = value / Parent.Scale; + //} + } + get + { + if (Parent == null) + return _position; + else if (Flip == SpriteEffects.FlipHorizontally) + return new Vector2(-_position.X * Parent.ScaleX, _position.Y * Parent.ScaleY); + else + return _position * Parent.Scale; + + // This is what used to be here. + //if (Flip == SpriteEffects.FlipHorizontally && Parent != null) + // return new Vector2(-_position.X * Parent.ScaleX, _position.Y * Parent.ScaleY); + //else + //{ + // if (Parent == null) + // return _position; + // else + // return _position * Parent.Scale; + //} + } + } + + public float AbsX + { + get + { + if (Parent == null) + return X; + else + return Parent.X + RotatedPoint.X; + } + } + + public Vector2 AbsPosition + { + get { return new Vector2(AbsX, AbsY); } + } + + public float AbsY + { + get + { + if (Parent == null) + return (int)this.Y; // Casting to int because too sensitive a Y value causes up/down jitter. + else + return (int)Parent.Y + (int)RotatedPoint.Y; + } + } + + private Vector2 RotatedPoint + { + get + { + if (Parent == null || Parent.Rotation == 0) + return Position; + else + return CDGMath.RotatedPoint(Position, Parent.Rotation); + } + } + + public virtual float AnchorX + { + set { _anchor.X = value; } + get + { + if (Flip == SpriteEffects.FlipHorizontally) + return this.Width / ScaleX - _anchor.X; // Cannot just call this._width because SpriteObj overrides Width. + else + return _anchor.X; + } + } + + public virtual float AnchorY + { + set { _anchor.Y = value; } + get { return _anchor.Y; } + } + + public virtual Vector2 Anchor + { + set { _anchor = value; } + get + { + if (Flip == SpriteEffects.FlipHorizontally) + return new Vector2(this.Width / ScaleX - _anchor.X, _anchor.Y); // Cannot just call this._width because SpriteObj overrides Width. + else + return _anchor; + } + } + + public virtual float ScaleX + { + set { _scale.X = value; } + get { return _scale.X; } + } + + public virtual float ScaleY + { + set { _scale.Y = value; } + get { return _scale.Y; } + } + + public virtual Vector2 Scale + { + set { _scale = value; } + get { return _scale; } + } + + public float Orientation + { + get { return _orientation; } + set { _orientation = value; } + } + + public float HeadingX + { + get { return _heading.X; } + set { _heading.X = value; } + } + + public float HeadingY + { + get { return _heading.Y; } + set { _heading.Y = value; } + } + + public Vector2 Heading + { + get { return _heading; } + set { _heading = value; } + } + + public float Speed + { + get { return _speed; } + set { _speed = value; } + } + + public virtual SpriteEffects Flip + { + get + { + if (_topmostParent == null) + return _flip; + else + return _topmostParent.Flip; + } + set + { + // if (this.Parent == null && (this is SpriteObj) && _flip != value) + // this.X += this.Width - this.AnchorX * 2; + _flip = value; + } + } + + public virtual Rectangle Bounds + { + get + { + if (Parent == null) + { + if (this.Rotation == 0) + { + return new Rectangle((int)(-this.AnchorX * ScaleX + this.X), + (int)(-this.AnchorY * ScaleY + this.Y), + this.Width, this.Height); // Do not multiply width and height by scale because their property already does that. + } + else + { + return CollisionMath.RotatedRectBounds(new Rectangle((int)(-this.AnchorX * ScaleX + this.X), + (int)(-this.AnchorY * ScaleY + this.Y), + this.Width, this.Height), this.Anchor, Rotation); + } + } + else + { + if (Parent.Rotation + this.Rotation == 0) + { + return new Rectangle((int)((-this.AnchorX * ScaleX + this.X) * Parent.ScaleX), + (int)((-this.AnchorY * ScaleY + this.Y) * Parent.ScaleY), + (int)(this.Width * Parent.ScaleX), (int)(this.Height * Parent.ScaleY)); // Do not multiply width and height by scale because their property already does that. + } + else + { + return CollisionMath.RotatedRectBounds(new Rectangle((int)(-this.AnchorX * ScaleX * Parent.ScaleX + this.X), + (int)(-this.AnchorY * ScaleY * Parent.ScaleY + this.Y), + (int)(this.Width * Parent.ScaleX), (int)(this.Height * Parent.ScaleY)), this.Anchor, Parent.Rotation + this.Rotation); + } + } + } + } + + public virtual Rectangle AbsBounds + { + get + { + if (Parent == null) + { + if (this.Rotation == 0) + { + return new Rectangle((int)(-this.AnchorX * ScaleX + this.AbsX), + (int)(-this.AnchorY * ScaleY + this.AbsY), + this.Width, this.Height); // Do not multiply width and height by scale because their property already does that. + } + else + { + return CollisionMath.RotatedRectBounds(new Rectangle((int)(-this.AnchorX * ScaleX + this.AbsX), + (int)(-this.AnchorY * ScaleY + this.AbsY), + this.Width, this.Height), this.Anchor, Rotation); + } + } + else + { + if (Parent.Rotation + this.Rotation == 0) + { + return new Rectangle((int)(-this.AnchorX * ScaleX * Parent.ScaleX + this.AbsX), + (int)(-this.AnchorY * ScaleY * Parent.ScaleY + this.AbsY), + (int)(this.Width * Parent.ScaleX), (int)(this.Height * Parent.ScaleY)); // Do not multiply width and height by scale because their property already does that. + } + else + { + return CollisionMath.RotatedRectBounds(new Rectangle((int)(-this.AnchorX * ScaleX * Parent.ScaleX + this.AbsX), + (int)(-this.AnchorY * ScaleY * Parent.ScaleY + this.AbsY), + (int)(this.Width * Parent.ScaleX), (int)(this.Height * Parent.ScaleY)), this.Anchor, Parent.Rotation + this.Rotation); + } + } + } + } + + private void SetTopMostParent(ObjContainer newParent) + { + if (newParent != null) + { + _topmostParent = newParent; + SetTopMostParent(newParent.Parent); + } + } + + public ObjContainer Parent + { + set + { + _parent = value; + if (value == null) + { + _topmostParent = null; + } + else + { + SetTopMostParent(value); + } + } + get { return _parent; } + } + + public bool ForceDraw + { + get + { + if (Parent != null) + return _topmostParent.ForceDraw; + else + return m_forceDraw; + } + set { m_forceDraw = value; } + } + + private float m_opacity = 1.0f; + public float Opacity + { + get + { + if (Parent == null) + return m_opacity; + else + return m_opacity * Parent.Opacity; + } + set { m_opacity = value; } + } + + private Color m_textureColor = Color.White; + public Color TextureColor + { + get + { + if (Parent == null || Parent.TextureColor == Color.White) + return m_textureColor;// * Opacity; + else + return Parent.TextureColor;// *Opacity; + } + set { m_textureColor = value; } + } + + public bool UseCachedValues + { + get + { + // Not totally convinced this below thing is an optimization yet...getting conflicting data + //if (_topmostParent == null) + // return _useCachedValues; + //else + // return _topmostParent.UseCachedValues; + if (Parent == null) + return _useCachedValues; + return Parent.UseCachedValues; + } + set { _useCachedValues = value; } + } + + #endregion + + #region ClickHandlers + + //public bool LeftJustPressed(Camera2D camera = null) + //{ + // Vector2 mousePos = new Vector2(InputManager.MouseX * EngineEV.ScreenRatio.X, InputManager.MouseY * EngineEV.ScreenRatio.Y); + + // if (camera == null) return InputManager.MouseLeftJustPressed() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)mousePos.X, (int)mousePos.Y, 1, 1)); + // else return InputManager.MouseLeftJustPressed() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)(mousePos.X + camera.X - camera.Width / 2), (int)(mousePos.Y + camera.Y - camera.Height / 2), 1, 1)); + //} + + //public bool LeftPressed(Camera2D camera = null) + //{ + // Vector2 mousePos = new Vector2(InputManager.MouseX * EngineEV.ScreenRatio.X, InputManager.MouseY * EngineEV.ScreenRatio.Y); + + // if (camera == null) return InputManager.MouseLeftPressed() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)mousePos.X, (int)mousePos.Y, 1, 1)); + // else return InputManager.MouseLeftPressed() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)(mousePos.X + camera.X - camera.Width / 2), (int)(mousePos.Y + camera.Y - camera.Height / 2), 1, 1)); + //} + + //public bool LeftJustReleased(Camera2D camera = null) + //{ + // Vector2 mousePos = new Vector2(InputManager.MouseX * EngineEV.ScreenRatio.X, InputManager.MouseY * EngineEV.ScreenRatio.Y); + + // if (camera == null) return InputManager.MouseLeftJustReleased() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)mousePos.X, (int)mousePos.Y, 1, 1)); + // else return InputManager.MouseLeftJustReleased() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)(mousePos.X + camera.X - camera.Width / 2), (int)(mousePos.Y + camera.Y - camera.Height / 2), 1, 1)); + //} + + //public bool RightJustPressed(Camera2D camera = null) + //{ + // Vector2 mousePos = new Vector2(InputManager.MouseX * EngineEV.ScreenRatio.X, InputManager.MouseY * EngineEV.ScreenRatio.Y); + + // if (camera == null) return InputManager.MouseRightJustPressed() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)mousePos.X, (int)mousePos.Y, 1, 1)); + // else return InputManager.MouseRightJustPressed() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)(mousePos.X + camera.X - camera.Width / 2), (int)(mousePos.Y + camera.Y - camera.Height / 2), 1, 1)); + //} + + //public bool RightPressed(Camera2D camera = null) + //{ + // Vector2 mousePos = new Vector2(InputManager.MouseX * EngineEV.ScreenRatio.X, InputManager.MouseY * EngineEV.ScreenRatio.Y); + + // if (camera == null) return InputManager.MouseRightPressed() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)mousePos.X, (int)mousePos.Y, 1, 1)); + // else return InputManager.MouseRightPressed() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)(mousePos.X + camera.X - camera.Width / 2), (int)(mousePos.Y + camera.Y - camera.Height / 2), 1, 1)); + //} + + //public bool RightJustReleased(Camera2D camera = null) + //{ + // if (camera == null) return InputManager.MouseRightJustReleased() && CollisionMath.Intersects(m_clickRect, new Rectangle(InputManager.MouseX, InputManager.MouseY, 1, 1)); + // else return InputManager.MouseRightJustReleased() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)(InputManager.MouseX + camera.X - camera.Width / 2), (int)(InputManager.MouseY + camera.Y - camera.Height / 2), 1, 1)); + //} + + + //public bool MiddleJustPressed(Camera2D camera = null) + //{ + // Vector2 mousePos = new Vector2(InputManager.MouseX * EngineEV.ScreenRatio.X, InputManager.MouseY * EngineEV.ScreenRatio.Y); + + // if (camera == null) return InputManager.MouseMiddleJustPressed() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)mousePos.X, (int)mousePos.Y, 1, 1)); + // else return InputManager.MouseMiddleJustPressed() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)(mousePos.X + camera.X - camera.Width / 2), (int)(mousePos.Y + camera.Y - camera.Height / 2), 1, 1)); + //} + + //public bool MiddlePressed(Camera2D camera = null) + //{ + // Vector2 mousePos = new Vector2(InputManager.MouseX * EngineEV.ScreenRatio.X, InputManager.MouseY * EngineEV.ScreenRatio.Y); + + // if (camera == null) return InputManager.MouseMiddlePressed() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)mousePos.X, (int)mousePos.Y, 1, 1)); + // else return InputManager.MouseMiddlePressed() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)(mousePos.X + camera.X - camera.Width / 2), (int)(mousePos.Y + camera.Y - camera.Height / 2), 1, 1)); + //} + + //public bool MiddleJustReleased(Camera2D camera = null) + //{ + // Vector2 mousePos = new Vector2(InputManager.MouseX * EngineEV.ScreenRatio.X, InputManager.MouseY * EngineEV.ScreenRatio.Y); + + // if (camera == null) return InputManager.MouseMiddleJustReleased() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)mousePos.X, (int)mousePos.Y, 1, 1)); + // else return InputManager.MouseMiddleJustReleased() && CollisionMath.Intersects(m_clickRect, new Rectangle((int)(mousePos.X + camera.X - camera.Width / 2), (int)(mousePos.Y + camera.Y - camera.Height / 2), 1, 1)); + //} + + public bool LeftMouseOverJustPressed(Camera2D camera) + { + return InputManager.MouseLeftJustPressed() && MouseOver(camera) == true; + } + + public bool LeftMouseOverPressed(Camera2D camera) + { + return InputManager.MouseLeftPressed() && MouseOver(camera) == true; + } + + public bool RightMouseOverJustPressed(Camera2D camera) + { + return InputManager.MouseRightJustPressed() && MouseOver(camera) == true; + } + + public bool RightMouseOverPressed(Camera2D camera) + { + return InputManager.MouseRightPressed() && MouseOver(camera) == true; + } + + public bool MiddleMouseOverJustPressed(Camera2D camera) + { + return InputManager.MouseMiddleJustPressed() && MouseOver(camera) == true; + } + + public bool MiddleMouseOverPressed(Camera2D camera) + { + return InputManager.MouseMiddlePressed() && MouseOver(camera) == true; + } + + //private Vector2 m_currentMousePos; + //private Vector2 m_previousMousePos; + private bool m_previousMouseOver = false; + public bool MouseOver(Camera2D camera = null) + { + //Vector2 mousePos = new Vector2(InputManager.MouseX * EngineEV.ScreenRatio.X, InputManager.MouseY * EngineEV.ScreenRatio.Y); + //m_previousMousePos = mousePos; + //if (camera == null) return CollisionMath.Intersects(m_clickRect, new Rectangle((int)mousePos.X, (int)mousePos.Y, 1, 1)); + //else return (CollisionMath.Intersects(m_clickRect, new Rectangle((int)(mousePos.X + camera.X - camera.Width / 2), (int)(mousePos.Y + camera.Y - camera.Height / 2), 1, 1))); + + bool mouseOver = false; + int mouseX = (int)(InputManager.MouseX * EngineEV.ScreenRatio.X); + int mouseY = (int)(InputManager.MouseY * EngineEV.ScreenRatio.Y); + if (camera != null) + { + mouseX += (int)(camera.X - (camera.Width / 2f)); // This compensates for camera shift. + float xDiff = (mouseX - camera.X) - ((mouseX - camera.X) * (1f / camera.Zoom)); // This compensates for camera zoom. + mouseX = (int)(mouseX - xDiff); + + mouseY += (int)(camera.Y - (camera.Height / 2f)); // This compensates for camera shift. + float yDiff = (mouseY - camera.Y) - ((mouseY - camera.Y) * (1f / camera.Zoom)); // This compensates for camera zoom. + mouseY = (int)(mouseY - yDiff); + } + + mouseOver = AbsBounds.Contains(mouseX, mouseY); + return mouseOver; + } + + public bool MouseJustOver(Camera2D camera = null) + { + //Vector2 mousePos = new Vector2(InputManager.MouseX * EngineEV.ScreenRatio.X, InputManager.MouseY * EngineEV.ScreenRatio.Y); + //if (m_previousMousePos.X != mousePos.X || m_previousMousePos.Y != mousePos.Y) + //{ + // m_previousMousePos = mousePos; + // if (camera == null) return CollisionMath.Intersects(m_clickRect, new Rectangle((int)mousePos.X, (int)mousePos.Y, 1, 1)); + // else return (CollisionMath.Intersects(m_clickRect, new Rectangle((int)(mousePos.X + camera.X - camera.Width / 2), (int)(mousePos.Y + camera.Y - camera.Height / 2), 1, 1))); + //} + //m_previousMousePos = mousePos; + //return false; + + bool mouseOver = MouseOver(camera); + bool mouseJustOver = false; + if (m_previousMouseOver == false && mouseOver == true) + { + mouseJustOver = true; + } + + m_previousMouseOver = mouseOver; + return mouseJustOver; + } + + #endregion + + #region Touch Handlers + + public bool JustTapped(Camera2D camera, bool relativeToCamera = false, bool useAbsBounds = true) + { + return JustTapped(camera, relativeToCamera, useAbsBounds ? AbsBounds : Bounds); + } + + public bool JustTapped(Camera2D camera, bool relativeToCamera, Rectangle bounds) + { + bool tapped = false; + + foreach (GestureSample tap in InputManager.Taps) + { + int touchX, touchY; + TouchCoordsToViewportCoords(camera, tap.Position, out touchX, out touchY, relativeToCamera); + if (bounds.Contains(touchX, touchY)) + { + tapped = true; + break; + } + } + + return tapped; + } + + public enum DragDirections + { + NONE, + LEFT, + RIGHT, + UP, + DOWN + } + + public bool JustDragged(Camera2D camera, DragDirections direction, bool relativeToCamera = false, bool useAbsBounds = true) + { + bool dragged = false; + + foreach (GestureSample drag in InputManager.Drags) + { + int touchX, touchY; + TouchCoordsToViewportCoords(camera, drag.Position, out touchX, out touchY, relativeToCamera); + + Rectangle bounds = (useAbsBounds ? AbsBounds : Bounds); + if (bounds.Contains(touchX, touchY)) + { + const int threshold = 5; + switch (direction) + { + case DragDirections.LEFT: + dragged = drag.Delta.X < -threshold; + break; + case DragDirections.RIGHT: + dragged = drag.Delta.X > threshold; + break; + case DragDirections.UP: + dragged = drag.Delta.Y < -threshold; + break; + case DragDirections.DOWN: + dragged = drag.Delta.Y > threshold; + break; + } + } + } + + return dragged; + } + + public static readonly Vector2 NoTouchPosition = new Vector2(-1, -1); + public Vector2 GetPositionTouched(Camera2D camera, Rectangle bounds, bool relativeToCamera = false) + { + TouchCollection touches = TouchPanel.GetState(); + foreach (TouchLocation touch in touches) + { + int touchX, touchY; + TouchCoordsToViewportCoords(camera, touch.Position, out touchX, out touchY, relativeToCamera); + if (bounds.Contains(touchX, touchY)) + { + return new Vector2(touchX, touchY); + } + } + + // Nothing is touching this object. Return (-1, -1) to indicate an invalid value. + return NoTouchPosition; + } + + public static void TouchCoordsToViewportCoords(Camera2D camera, Vector2 touchCoords, out int vx, out int vy, bool relativeToCamera) + { + Viewport viewport = camera.GraphicsDevice.Viewport; + int viewportX = (int)((touchCoords.X - viewport.X) / viewport.Width * EngineEV.ScreenWidth); + int viewportY = (int)((touchCoords.Y - viewport.Y) / viewport.Height * EngineEV.ScreenHeight); + + if (relativeToCamera) + { + viewportX += (int)(camera.X - (camera.Width / 2f)); // This compensates for camera shift. + float xDiff = (viewportX - camera.X) - ((viewportX - camera.X) * (1f / camera.Zoom)); // This compensates for camera zoom. + viewportX = (int)(viewportX - xDiff); + + viewportY += (int)(camera.Y - (camera.Height / 2f)); // This compensates for camera shift. + float yDiff = (viewportY - camera.Y) - ((viewportY - camera.Y) * (1f / camera.Zoom)); // This compensates for camera zoom. + viewportY = (int)(viewportY - yDiff); + } + + vx = viewportX; + vy = viewportY; + } + + #endregion + } +} diff --git a/DS2DEngine/src/GameObjs/Interfaces/IAnimateableObj.cs b/DS2DEngine/src/GameObjs/Interfaces/IAnimateableObj.cs new file mode 100644 index 0000000..615a0ca --- /dev/null +++ b/DS2DEngine/src/GameObjs/Interfaces/IAnimateableObj.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public interface IAnimateableObj + { + int AnimationSpeed { get; set; } + bool IsAnimating { get; } + bool IsPaused { get; } + bool IsLooping { get; } + int TotalFrames { get; } + int CurrentFrame { get; } + float AnimationDelay { get; set; } + string SpriteName { get; set; } + + void ChangeSprite(string spriteName); + void PlayAnimation(bool loopAnimation = true); + void PlayAnimation(int startIndex, int endIndex, bool loopAnimation); + void PauseAnimation(); + void ResumeAnimation(); + void StopAnimation(); + void GoToNextFrame(); + void GoToFrame(int frameIndex); + int FindLabelIndex(string label); + + } +} diff --git a/DS2DEngine/src/GameObjs/Interfaces/IClickableObj.cs b/DS2DEngine/src/GameObjs/Interfaces/IClickableObj.cs new file mode 100644 index 0000000..7d87196 --- /dev/null +++ b/DS2DEngine/src/GameObjs/Interfaces/IClickableObj.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public interface IClickableObj + { + //bool LeftJustPressed(Camera2D camera); + //bool LeftPressed(Camera2D camera); + //bool LeftJustReleased(Camera2D camera); + + //bool RightJustPressed(Camera2D camera); + //bool RightPressed(Camera2D camera); + //bool RightJustReleased(Camera2D camera); + + //bool MiddleJustPressed(Camera2D camera); + //bool MiddlePressed(Camera2D camera); + //bool MiddleJustReleased(Camera2D camera); + + bool LeftMouseOverJustPressed(Camera2D camera); + bool LeftMouseOverPressed(Camera2D camera); + //bool LeftJustReleased(Camera2D camera); + + bool RightMouseOverJustPressed(Camera2D camera); + bool RightMouseOverPressed(Camera2D camera); + //bool RightJustReleased(Camera2D camera); + + bool MiddleMouseOverJustPressed(Camera2D camera); + bool MiddleMouseOverPressed(Camera2D camera); + //bool MiddleJustReleased(Camera2D camera); + } +} diff --git a/DS2DEngine/src/GameObjs/Interfaces/IDisposableObj.cs b/DS2DEngine/src/GameObjs/Interfaces/IDisposableObj.cs new file mode 100644 index 0000000..28028e2 --- /dev/null +++ b/DS2DEngine/src/GameObjs/Interfaces/IDisposableObj.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public interface IDisposableObj + { + bool IsDisposed { get; } + void Dispose(); + } +} diff --git a/DS2DEngine/src/GameObjs/Interfaces/IDrawableObj.cs b/DS2DEngine/src/GameObjs/Interfaces/IDrawableObj.cs new file mode 100644 index 0000000..366f94b --- /dev/null +++ b/DS2DEngine/src/GameObjs/Interfaces/IDrawableObj.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public interface IDrawableObj + { + float Opacity { get; set; } + Color TextureColor { get; set; } + + void Draw(Camera2D camera); + void ChangeSprite(string spriteName); + } +} diff --git a/DS2DEngine/src/GameObjs/Interfaces/IKillableObj.cs b/DS2DEngine/src/GameObjs/Interfaces/IKillableObj.cs new file mode 100644 index 0000000..255d8bb --- /dev/null +++ b/DS2DEngine/src/GameObjs/Interfaces/IKillableObj.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public interface IKillableObj + { + bool IsKilled { get; } + } +} diff --git a/DS2DEngine/src/GameObjs/Interfaces/IPoolableObj.cs b/DS2DEngine/src/GameObjs/Interfaces/IPoolableObj.cs new file mode 100644 index 0000000..45d46d1 --- /dev/null +++ b/DS2DEngine/src/GameObjs/Interfaces/IPoolableObj.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public interface IPoolableObj + { + bool IsCheckedOut { get; set; } + bool IsActive { get; set; } + } +} diff --git a/DS2DEngine/src/GameObjs/Interfaces/IStateObj.cs b/DS2DEngine/src/GameObjs/Interfaces/IStateObj.cs new file mode 100644 index 0000000..bfcb635 --- /dev/null +++ b/DS2DEngine/src/GameObjs/Interfaces/IStateObj.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public interface IStateObj + { + int State { get; set; } + } +} diff --git a/DS2DEngine/src/GameObjs/Interfaces/ITriggerableObj.cs b/DS2DEngine/src/GameObjs/Interfaces/ITriggerableObj.cs new file mode 100644 index 0000000..f0de31f --- /dev/null +++ b/DS2DEngine/src/GameObjs/Interfaces/ITriggerableObj.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public interface ITriggerableObj + { + bool IsTriggered { get; set; } + } +} diff --git a/DS2DEngine/src/GameObjs/ObjContainer.cs b/DS2DEngine/src/GameObjs/ObjContainer.cs new file mode 100644 index 0000000..b38293c --- /dev/null +++ b/DS2DEngine/src/GameObjs/ObjContainer.cs @@ -0,0 +1,589 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using SpriteSystem; + +namespace DS2DEngine +{ + public class ObjContainer : GameObj, IAnimateableObj + { + protected List _objectList = null; + protected int _numChildren; + private Rectangle m_bounds = new Rectangle(); + protected string _spriteName = ""; + + protected bool m_animate = false; + protected bool m_loop = false; + protected int m_currentFrameIndex; + protected int m_startAnimationIndex; + protected int m_endAnimationIndex; + + protected int m_numCharData = 0; // An integer that keeps track of how many objects were added via ChangeSprite(). + protected int m_charDataStartIndex = -1; // An integer that keeps track of the starting index of the CharData. + + private bool m_wasAnimating = false; // A bool that determines whether an animation that was paused was actually animating when paused. + + public float AnimationDelay { get; set; } + private float m_timeDelayCounter = 0; + private float m_totalGameTime = 0; + + protected List m_spritesheetNameList; + + public Color OutlineColour = Color.Black; + public int OutlineWidth { get; set; } + + public ObjContainer() + { + AnimationSpeed = 1; + _objectList = new List(); + _numChildren = 0; + m_spritesheetNameList = new List(); + } + + public ObjContainer(string spriteName) + { + AnimationSpeed = 1; + _objectList = new List(); + m_spritesheetNameList = new List(); + + _numChildren = 0; + _spriteName = spriteName; + + List charDataList = SpriteLibrary.GetCharData(spriteName); + foreach (CharacterData chars in charDataList) + { + SpriteObj newObj = new SpriteObj(chars.Child); + newObj.X = chars.ChildX; // Not sure why this is commented. Only commented it out because it was commented out for PhysicsObjContainer. + newObj.Y = chars.ChildY; + if (!m_spritesheetNameList.Contains(newObj.SpritesheetName)) + m_spritesheetNameList.Add(newObj.SpritesheetName); + this.AddChild(newObj); + } + + m_numCharData = charDataList.Count; + m_charDataStartIndex = 0; + } + + public override void ChangeSprite(string spriteName) + { + _spriteName = spriteName; + + if (m_charDataStartIndex == -1) + m_charDataStartIndex = _objectList.Count; // Sets the starting index of when ChangeSprite was called to the end of the object list if it wasn't originally set in the constructor. + + List charDataList = SpriteLibrary.GetCharData(spriteName); + + m_spritesheetNameList.Clear(); + int indexCounter = 0; + for (int i = m_charDataStartIndex; i < charDataList.Count; i++) + { + CharacterData charData = charDataList[indexCounter]; + + if (i >= m_numCharData) + { + SpriteObj objToAdd = new SpriteObj(charData.Child); + objToAdd.X = charData.ChildX; + objToAdd.Y = charData.ChildY; + this.AddChildAt(i, objToAdd); + m_numCharData++; + } + else + { + SpriteObj spriteObj = _objectList[i] as SpriteObj; + spriteObj.Visible = true; + if (spriteObj != null) + { + spriteObj.ChangeSprite(charData.Child); + spriteObj.X = charData.ChildX; + spriteObj.Y = charData.ChildY; + if (!m_spritesheetNameList.Contains(spriteObj.SpritesheetName)) + m_spritesheetNameList.Add(spriteObj.SpritesheetName); + } + } + + indexCounter++; + } + + if (charDataList.Count < m_numCharData) + { + //for (int i = m_charDataStartIndex + (m_numCharData - charDataList.Count); i < m_charDataStartIndex + m_numCharData; i++) + //for (int i = m_charDataStartIndex + 1; i < m_charDataStartIndex + m_numCharData; i++) + for (int i = charDataList.Count; i < m_numCharData; i++) + { + _objectList[i].Visible = false; + } + } + + this.StopAnimation(); + CalculateBounds(); + } + + public virtual void AddChild(GameObj obj) + { + _objectList.Add(obj); + obj.Parent = this; + _numChildren++; + + SpriteObj spriteObj = obj as SpriteObj; + if (spriteObj != null && !m_spritesheetNameList.Contains(spriteObj.SpritesheetName)) + m_spritesheetNameList.Add(spriteObj.SpritesheetName); + + CalculateBounds(); + } + + public virtual void AddChildAt(int index, GameObj obj) + { + _objectList.Insert(index, obj); + obj.Parent = this; + _numChildren++; + + SpriteObj spriteObj = obj as SpriteObj; + if (spriteObj != null && !m_spritesheetNameList.Contains(spriteObj.SpritesheetName)) + m_spritesheetNameList.Add(spriteObj.SpritesheetName); + + CalculateBounds(); + } + + public virtual void RemoveChild(GameObj obj) + { + obj.Parent = null; + _objectList.Remove(obj); + _numChildren--; + + SpriteObj spriteObj = obj as SpriteObj; + if (spriteObj != null && m_spritesheetNameList.Contains(spriteObj.SpritesheetName)) + m_spritesheetNameList.Remove(spriteObj.SpritesheetName); + + CalculateBounds(); + } + + public virtual GameObj RemoveChildAt(int index) + { + _numChildren--; + GameObj objectToReturn = _objectList[index]; + objectToReturn.Parent = null; + _objectList.RemoveAt(index); + + CalculateBounds(); + + SpriteObj spriteObj = objectToReturn as SpriteObj; + if (spriteObj != null && m_spritesheetNameList.Contains(spriteObj.SpritesheetName)) + m_spritesheetNameList.Remove(spriteObj.SpritesheetName); + + return objectToReturn; + } + + public virtual void RemoveAll() + { + foreach (GameObj obj in _objectList) + obj.Parent = null; + _objectList.Clear(); + _numChildren = 0; + + m_bounds = new Rectangle(); + + m_spritesheetNameList.Clear(); + } + + public GameObj GetChildAt(int index) + { + return _objectList[index]; + } + + public override void Draw(Camera2D camera) + { + if (this.Visible == true) + { + if (CollisionMath.Intersects(this.Bounds, camera.LogicBounds) || ForceDraw == true) + { + if (OutlineWidth > 0) + { + DrawOutline(camera); + } + + foreach (GameObj obj in _objectList) + { + obj.Draw(camera); + } + + float elapsedTotalSeconds = camera.ElapsedTotalSeconds; + if (m_animate == true && m_totalGameTime != elapsedTotalSeconds) + { + m_totalGameTime = elapsedTotalSeconds; + + if (camera.GameTime != null) + m_timeDelayCounter += elapsedTotalSeconds;//(float)camera.GameTime.ElapsedGameTime.TotalSeconds; + + if (m_timeDelayCounter >= AnimationDelay) + { + m_timeDelayCounter = 0; + GoToNextFrame(); + } + } + } + } + } + + //public override void DrawOutline(Camera2D camera, int width) + public override void DrawOutline(Camera2D camera) + { + if (this.Visible == true) + { + //if (CollisionMath.Intersects(this.Bounds, camera.Bounds) || ForceDraw == true) + { + foreach (GameObj obj in _objectList) + { + obj.DrawOutline(camera); + } + } + } + } + + public void CalculateBounds() + { + int leftBound = int.MaxValue; + int rightBound = -int.MaxValue; + int topBound = int.MaxValue; + int bottomBound = -int.MaxValue; + + // Hack to fix bounds of pre-flipped objcontainers. + SpriteEffects storedFlip = _flip; + _flip = SpriteEffects.None; + + foreach (GameObj obj in _objectList) + { + if (obj.Visible == true && obj.AddToBounds == true) + { + //Rectangle boundsRect = new Rectangle((int)((-obj.AnchorX * obj.ScaleX + obj.X) * this.ScaleX), (int)(obj.Bounds.Y), obj.Width, obj.Height); + Rectangle objBounds = obj.Bounds; + + if (objBounds.Left < leftBound) + leftBound = objBounds.Left; + + if (objBounds.Right > rightBound) + rightBound = objBounds.Right; + + if (objBounds.Top < topBound) + topBound = objBounds.Top; + + if (objBounds.Bottom > bottomBound) + bottomBound = objBounds.Bottom; + } + } + + m_bounds.X = leftBound; + m_bounds.Y = topBound; + m_bounds.Width = rightBound - leftBound; + m_bounds.Height = bottomBound - topBound; + + // Hack to fix bounds of pre-flipped objcontainers. + if (storedFlip == SpriteEffects.FlipHorizontally) + m_bounds.X = -m_bounds.Right; + _flip = storedFlip; + + _width = (int)(m_bounds.Width / this.ScaleX); // Divide by scale because the Width property multiplies by scale, so it would be mulitplied by scale twice when calling the Width property. + _height = (int)(m_bounds.Height / this.ScaleY); // Same for Height. + } + + public void PlayAnimation(bool loopAnimation = true) + { + if (m_charDataStartIndex > -1) + { + foreach (GameObj obj in _objectList) + { + if (obj is IAnimateableObj) + (obj as IAnimateableObj).PlayAnimation(loopAnimation); + } + //(_objectList[m_charDataStartIndex] as IAnimateableObj).PlayAnimation(loopAnimation); // Uncomment this if you want to be able to separate the animating state + // of each object in this container. + m_loop = loopAnimation; + m_startAnimationIndex = 1; + m_endAnimationIndex = this.TotalFrames; + m_animate = true; + m_currentFrameIndex = m_startAnimationIndex; + + m_timeDelayCounter = 0; + } + } + + public void PlayAnimation(int startIndex, int endIndex, bool loopAnimation = false) + { + foreach (GameObj obj in _objectList) + { + IAnimateableObj animateableObj = obj as IAnimateableObj; + if (animateableObj != null) + animateableObj.PlayAnimation(startIndex, endIndex, loopAnimation); + } + m_loop = loopAnimation; + + // Must be called after PlayAnimation because SpriteObj.cs also does this change. + startIndex = (startIndex - 1) * AnimationSpeed + 1; + endIndex = endIndex * AnimationSpeed; + + if (startIndex < 1) + startIndex = 1; + else if (startIndex > TotalFrames) + startIndex = TotalFrames; + + if (endIndex < 1) + endIndex = 1; + else if (endIndex > TotalFrames) + endIndex = TotalFrames; + m_startAnimationIndex = startIndex; + m_endAnimationIndex = endIndex; + m_currentFrameIndex = startIndex; + m_animate = true; + } + + public void PlayAnimation(string startLabel, string endLabel, bool loopAnimation = false) + { + int startIndex = FindLabelIndex(startLabel); + int endIndex = FindLabelIndex(endLabel); + if (startIndex == -1) + throw new Exception("Could not find starting label " + startLabel); + else if (endIndex == -1) + throw new Exception("Could not find ending label " + endLabel); + else + PlayAnimation(startIndex, endIndex, loopAnimation); + } + + public int FindLabelIndex(string label) + { + foreach (GameObj obj in _objectList) + { + IAnimateableObj animateableObj = obj as IAnimateableObj; + if (animateableObj != null) + { + int index = animateableObj.FindLabelIndex(label); + if (index != -1) + return index; + } + } + return -1; + } + + /// + /// For ObjContainer, GoToNextFrame() only keeps track of the CurrentFrame Index + /// + public void GoToNextFrame() + { + m_currentFrameIndex++; + if (m_currentFrameIndex > m_endAnimationIndex && m_loop == true) + m_currentFrameIndex = m_startAnimationIndex; + else if (m_currentFrameIndex > m_endAnimationIndex && m_loop == false) + m_animate = false; + } + + public void GoToFrame(int index) + { + foreach (GameObj obj in _objectList) + { + if (obj is IAnimateableObj) + (obj as IAnimateableObj).GoToFrame(index); + } + //if (m_charDataStartIndex > -1) + // (_objectList[m_charDataStartIndex] as IAnimateableObj).GoToFrame(index); + } + + public void ResumeAnimation() + { + if (m_charDataStartIndex > -1) + { + foreach (GameObj obj in _objectList) + { + if (obj is IAnimateableObj) + (obj as IAnimateableObj).ResumeAnimation(); + } + //(_objectList[m_charDataStartIndex] as IAnimateableObj).ResumeAnimation(); + if (m_wasAnimating == true) + m_animate = true; + } + m_wasAnimating = false; + } + + public void PauseAnimation() + { + if (m_charDataStartIndex > -1) + { + foreach (GameObj obj in _objectList) + { + if (obj is IAnimateableObj) + (obj as IAnimateableObj).PauseAnimation(); + } + //(_objectList[m_charDataStartIndex] as IAnimateableObj).PauseAnimation(); + m_wasAnimating = this.IsAnimating; + m_animate = false; + } + } + + public void StopAnimation() + { + if (m_charDataStartIndex > -1) + { + foreach (GameObj obj in _objectList) + { + if (obj is IAnimateableObj) + (obj as IAnimateableObj).StopAnimation(); + } + //(_objectList[m_charDataStartIndex] as IAnimateableObj).StopAnimation(); + m_animate = false; + } + m_wasAnimating = false; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + foreach (GameObj obj in _objectList) + { + obj.Dispose(); + } + RemoveAll(); + _objectList.Clear(); + _objectList = null; + base.Dispose(); + } + } + + protected override GameObj CreateCloneInstance() + { + if (_spriteName != "") + return new ObjContainer(_spriteName); + else + { + ObjContainer clone = new ObjContainer(); + foreach (GameObj obj in _objectList) + clone.AddChild(obj.Clone() as GameObj); + + return clone; + } + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + + public int NumChildren + { + get { return _objectList.Count; } + } + + public override Rectangle Bounds + { + get + { + return new Rectangle((int)(m_bounds.X + this.X), + (int)(m_bounds.Y + this.Y), + m_bounds.Width, m_bounds.Height); + } + } + + public Rectangle PureBounds + { + get + { + return new Rectangle((int)(m_bounds.X + this.X), + (int)(m_bounds.Y + this.Y), + m_bounds.Width, m_bounds.Height); + } + } + + public Rectangle RelativeBounds + { + get { return m_bounds; } + } + + public string SpriteName + { + get { return _spriteName; } + set { _spriteName = value; } + } + + public bool IsAnimating + { + get { return m_animate; } + } + + public bool IsLooping + { + get { return m_loop; } + } + + public int CurrentFrame + { + get + { + if (m_currentFrameIndex > TotalFrames) + return TotalFrames; + return m_currentFrameIndex; + } + } + + public int TotalFrames // Only returns the largest number of frames in the object list. + { + get + { + int totalFrames = 1; + foreach (GameObj obj in _objectList) + { + IAnimateableObj animatableObj = obj as IAnimateableObj; + if (animatableObj != null && obj.Visible == true) + { + int largestNumberOfFrames = animatableObj.TotalFrames; + if (largestNumberOfFrames > totalFrames) + totalFrames = largestNumberOfFrames; + } + } + return totalFrames; + //if (m_charDataStartIndex > -1) + // return (_objectList[m_charDataStartIndex] as IAnimateableObj).TotalFrames; + //return 0; + } + } + + public int AnimationSpeed { get; set; } + + public List SpritesheetNameList + { + get { return m_spritesheetNameList; } + } + + public override float ScaleX + { + set { _scale.X = value; CalculateBounds(); } + get { return _scale.X; } + } + + public override float ScaleY + { + set { _scale.Y = value; CalculateBounds(); } + get { return _scale.Y; } + } + + public override Vector2 Scale + { + set { _scale = value; CalculateBounds(); } + get { return _scale; } + } + + public override SpriteEffects Flip + { + get { return base.Flip; } + set + { + base.Flip = value; + CalculateBounds(); + } + } + + public bool IsPaused + { + get { return IsAnimating == false && m_wasAnimating == true; } + } + } +} diff --git a/DS2DEngine/src/GameObjs/PhysicsObj.cs b/DS2DEngine/src/GameObjs/PhysicsObj.cs new file mode 100644 index 0000000..82fc424 --- /dev/null +++ b/DS2DEngine/src/GameObjs/PhysicsObj.cs @@ -0,0 +1,411 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Audio; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Media; +using SpriteSystem; + +namespace DS2DEngine +{ + public class PhysicsObj : SpriteObj, IPhysicsObj + { + public LinkedListNode Node { get; set; } + + public bool CollidesLeft { get; set; } + public bool CollidesRight { get; set; } + public bool CollidesTop { get; set; } + public bool CollidesBottom { get; set; } + public int CollisionTypeTag { get; set; } + + private Vector2 _acceleration = Vector2.Zero; + public Boolean IsWeighted { get; set; } + public Boolean IsCollidable { get; set; } + + private List _collisionBoxes = null; + public PhysicsManager PhysicsMngr { get; set; } + public bool DisableHitboxUpdating { get; set; } + + public bool AccelerationXEnabled { get; set; } + public bool AccelerationYEnabled { get; set; } + public bool DisableAllWeight { get; set; } + public bool SameTypesCollide { get; set; } + public bool DisableGravity { get; set; } + + private Rectangle m_terrainBounds; + + #region Constructors + public PhysicsObj(string spriteName, PhysicsManager physicsManager = null) + : base(spriteName) + { + IsWeighted = true; + IsCollidable = true; + _collisionBoxes = new List(); + + if (physicsManager != null) + physicsManager.AddObject(this); + + CollidesLeft = true; + CollidesRight = true; + CollidesTop = true; + CollidesBottom = true; + + AccelerationXEnabled = true; + AccelerationYEnabled = true; + + UpdateCollisionBoxes(); + } + + public PhysicsObj(Texture2D sprite, PhysicsManager physicsManager = null) + : base(sprite) + { + IsWeighted = true; + IsCollidable = true; + _collisionBoxes = new List(); + + if (physicsManager != null) + physicsManager.AddObject(this); + + CollidesLeft = true; + CollidesRight = true; + CollidesTop = true; + CollidesBottom = true; + + AccelerationXEnabled = true; + AccelerationYEnabled = true; + } + #endregion + + public void AddCollisionBox(int xPos, int yPos, int width, int height, int hitboxType) + { + _collisionBoxes.Add(new CollisionBox((int)(xPos - AnchorX), (int)(yPos - AnchorY), width, height, hitboxType, this) { WasAdded = true, }); + } + + public void ClearCollisionBoxes() + { + _collisionBoxes.Clear(); + } + + public override void ChangeSprite(string spriteName) + { + base.ChangeSprite(spriteName); + UpdateCollisionBoxes(); + } + + public void UpdatePhysics(GameTime gameTime) + { + float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds; + //if (elapsedSeconds > Consts.FRAMERATE_CAP) elapsedSeconds = Consts.FRAMERATE_CAP; + if (AccelerationXEnabled == true) + this.X += _acceleration.X * elapsedSeconds; + + float yAcceleration = _acceleration.Y * elapsedSeconds; + if (yAcceleration < _acceleration.Y * Consts.FRAMERATE_CAP) + yAcceleration = _acceleration.Y * elapsedSeconds; + if (AccelerationYEnabled == true) + this.Y += yAcceleration; + } + + public void UpdateCollisionBoxes() + { + if (Sprite.IsDisposed) + ReinitializeSprite(); + + if (m_frameDataList != null) + { + List hbList = m_frameDataList[_frameIndex].hitboxList; + m_terrainBounds = new Rectangle(); + int leftBound = int.MaxValue; + int rightBound = -int.MaxValue; + int topBound = int.MaxValue; + int bottomBound = -int.MaxValue; + + for (int i = 0; i < hbList.Count; i++) + { + if (_collisionBoxes.Count <= i) + { + CollisionBox newCollisionBox = new CollisionBox(this); + _collisionBoxes.Add(newCollisionBox); + + //Adds the collision box to the parent if it is a PhysicsObjContainer. + //Because it passes by references, any changes to these collision boxes will be reflected in the PhysicsObjContainer. + if (Parent != null) + { + PhysicsObjContainer container = Parent as PhysicsObjContainer; + if (container != null) + container.CollisionBoxes.Add(newCollisionBox); + } + } + + if (Parent == null) + { + _collisionBoxes[i].X = (int)(hbList[i].X * this.ScaleX); + _collisionBoxes[i].Y = (int)(hbList[i].Y * this.ScaleY); + _collisionBoxes[i].Width = (int)(hbList[i].Width * this.ScaleX); + _collisionBoxes[i].Height = (int)(hbList[i].Height * this.ScaleY); + } + else + { + _collisionBoxes[i].X = (int)(hbList[i].X * Parent.ScaleX * this.ScaleX); + _collisionBoxes[i].Y = (int)(hbList[i].Y * Parent.ScaleY * this.ScaleY); + _collisionBoxes[i].Width = (int)(hbList[i].Width * Parent.ScaleX * this.ScaleX); + _collisionBoxes[i].Height = (int)(hbList[i].Height * Parent.ScaleY * this.ScaleY); + } + _collisionBoxes[i].InternalRotation = hbList[i].Rotation; + _collisionBoxes[i].Type = hbList[i].Type; + + if (_collisionBoxes[i].Type == Consts.TERRAIN_HITBOX) + { + Rectangle absRect = _collisionBoxes[i].AbsRect; + + if (absRect.Left < leftBound) + leftBound = absRect.Left; + + if (absRect.Right > rightBound) + rightBound = absRect.Right; + + if (absRect.Top < topBound) + topBound = absRect.Top; + + if (absRect.Bottom > bottomBound) + bottomBound = absRect.Bottom; + } + } + + m_terrainBounds.X = leftBound; + m_terrainBounds.Y = topBound; + m_terrainBounds.Width = rightBound - leftBound; + m_terrainBounds.Height = bottomBound - topBound; + + //Clears out any collision boxes not being used. + for (int k = hbList.Count; k < _collisionBoxes.Count; k++) + { + if (_collisionBoxes[k].WasAdded == false) + { + _collisionBoxes[k].X = 0; + _collisionBoxes[k].Y = 0; + _collisionBoxes[k].Width = 1; + _collisionBoxes[k].Height = 1; + _collisionBoxes[k].InternalRotation = 0; + _collisionBoxes[k].Type = Consts.NULL_HITBOX; + } + } + + // This below optimziation didn't work. This cauese the hero's sword to + // go nuts animating up and down every other frame. + // - it seems to get an old value + // Optimization - Update cached values + //foreach (CollisionBox box in _collisionBoxes) + //{ + // box.UpdateCachedValues(); + //} + } + } + + public virtual void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + if (this.IsWeighted == true && collisionResponseType == Consts.COLLISIONRESPONSE_TERRAIN) + { + //Vector2 mtdPos = CollisionMath.CalculateMTD(thisBox.AbsRect, otherBox.AbsRect); + Vector2 mtdPos = CollisionMath.RotatedRectIntersectsMTD(thisBox.AbsRect, thisBox.AbsRotation, Vector2.Zero, otherBox.AbsRect, otherBox.AbsRotation, Vector2.Zero); + IPhysicsObj otherPhysicsObj = otherBox.AbsParent as IPhysicsObj; + int collisionMarginOfError = 10; + + if (mtdPos.Y < 0) // There is an object below this object. + { + if (this.AccelerationY > 0 && otherPhysicsObj.CollidesTop == true) // This object is falling and there is an object below, so stop this object from falling. + { + if (otherBox.AbsRotation != 0 || + (otherPhysicsObj.TerrainBounds.Left <= this.TerrainBounds.Right && otherPhysicsObj.TerrainBounds.Right >= this.TerrainBounds.Right && (this.TerrainBounds.Right - otherPhysicsObj.TerrainBounds.Left > collisionMarginOfError)) || + (this.TerrainBounds.Left <= otherPhysicsObj.TerrainBounds.Right && this.TerrainBounds.Right >= otherPhysicsObj.TerrainBounds.Right && (otherPhysicsObj.TerrainBounds.Right - this.TerrainBounds.Left > collisionMarginOfError))) + { + this.AccelerationY = 0; + this.Y += mtdPos.Y; + } + } + //else if (IsWeighted == false && otherPhysicsObj.CollidesTop == true) // The above code is only for weighted objects. Non-weighted objects presumably do not move by gravity, so collision detection needs to be always on. + // this.Y += mtdPos.Y; + } + else if (mtdPos.Y > 0) // There is an object above this object. + { + if (this.AccelerationY < 0 && otherPhysicsObj.CollidesBottom == true) // This object is going up and has hit an object above it, so stop this object from going up. + { + this.AccelerationY = 0; + this.Y += mtdPos.Y; + } + // else if (IsWeighted == false && otherPhysicsObj.CollidesBottom == true) // The above code is only for weighted objects. Non-weighted objects presumably do not move by gravity, so collision detection needs to be always on. + // this.Y += mtdPos.Y; + } + + if (mtdPos.X != 0) + { + this.AccelerationX = 0; + if (((otherBox.AbsParent as IPhysicsObj).CollidesLeft == true && mtdPos.X > 0) || + ((otherBox.AbsParent as IPhysicsObj).CollidesRight == true && mtdPos.X < 0)) + this.X += mtdPos.X; + } + } + } + + public override void Dispose() + { + if (IsDisposed == false) + { + foreach (CollisionBox box in _collisionBoxes) + { + box.Dispose(); + } + _collisionBoxes.Clear(); + _collisionBoxes = null; + if (PhysicsMngr != null) + PhysicsMngr.RemoveObject(this); + + Node = null; + base.Dispose(); + } + } + + protected override GameObj CreateCloneInstance() + { + return new PhysicsObj(_spriteName); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + PhysicsObj clone = obj as PhysicsObj; + if (this.PhysicsMngr != null) + this.PhysicsMngr.AddObject(clone); + + clone.CollidesLeft = this.CollidesLeft; + clone.CollidesRight = this.CollidesRight; + clone.CollidesBottom = this.CollidesBottom; + clone.CollidesTop = this.CollidesTop; + + clone.IsWeighted = this.IsWeighted; + clone.IsCollidable = this.IsCollidable; + clone.DisableHitboxUpdating = this.DisableHitboxUpdating; + clone.CollisionTypeTag = this.CollisionTypeTag; + clone.DisableAllWeight = this.DisableAllWeight; + clone.SameTypesCollide = this.SameTypesCollide; + + clone.AccelerationX = this.AccelerationX; + clone.AccelerationY = this.AccelerationY; + clone.AccelerationXEnabled = this.AccelerationXEnabled; + clone.AccelerationYEnabled = this.AccelerationYEnabled; + clone.DisableGravity = this.DisableGravity; + } + + public override void PopulateFromXMLReader(System.Xml.XmlReader reader, System.Globalization.CultureInfo ci) + { + base.PopulateFromXMLReader(reader, ci); + + if (reader.MoveToAttribute("CollidesTop")) + this.CollidesTop = bool.Parse(reader.Value); + if (reader.MoveToAttribute("CollidesBottom")) + this.CollidesBottom = bool.Parse(reader.Value); + if (reader.MoveToAttribute("CollidesLeft")) + this.CollidesLeft = bool.Parse(reader.Value); + if (reader.MoveToAttribute("CollidesRight")) + this.CollidesRight = bool.Parse(reader.Value); + if (reader.MoveToAttribute("Collidable")) + this.IsCollidable = bool.Parse(reader.Value); + if (reader.MoveToAttribute("Weighted")) + this.IsWeighted = bool.Parse(reader.Value); + } + + public virtual Rectangle TerrainBounds + { + get { return m_terrainBounds; } + } + + public void RemoveFromPhysicsManager() + { + if (this.PhysicsMngr != null) + this.PhysicsMngr.RemoveObject(this); + } + + public List CollisionBoxes + { + get { return _collisionBoxes; } + } + + public float AccelerationX + { + set { _acceleration.X = value; } + get { return _acceleration.X; } + } + + public float AccelerationY + { + set { _acceleration.Y = value; } + get { return _acceleration.Y; } + } + + public override Vector2 Scale + { + get { return base.Scale; } + set + { + base.Scale = value; + if (DisableHitboxUpdating == false) + UpdateCollisionBoxes(); + } + } + + public override float ScaleX + { + get { return base.ScaleX; } + set + { + base.ScaleX = value; + if (DisableHitboxUpdating == false) + UpdateCollisionBoxes(); + } + } + + public override float ScaleY + { + get { return base.ScaleY; } + set + { + base.ScaleY = value; + if (DisableHitboxUpdating == false) + UpdateCollisionBoxes(); + } + } + + public bool HasTerrainHitBox + { + get + { + foreach (CollisionBox box in _collisionBoxes) + { + if (box.Type == Consts.TERRAIN_HITBOX) + return true; + } + return false; + } + } + + public bool DisableCollisionBoxRotations + { + set + { + foreach (CollisionBox box in _collisionBoxes) + box.DisableRotation = value; + } + get + { + foreach (CollisionBox box in _collisionBoxes) + return box.DisableRotation; + return false; + } + } + } +} diff --git a/DS2DEngine/src/GameObjs/PhysicsObjContainer.cs b/DS2DEngine/src/GameObjs/PhysicsObjContainer.cs new file mode 100644 index 0000000..57f9ff7 --- /dev/null +++ b/DS2DEngine/src/GameObjs/PhysicsObjContainer.cs @@ -0,0 +1,481 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using SpriteSystem; +using Microsoft.Xna.Framework.Graphics; + +namespace DS2DEngine +{ + public class PhysicsObjContainer : ObjContainer, IPhysicsObj + { + public LinkedListNode Node { get; set; } + + public bool CollidesLeft { get; set; } + public bool CollidesRight { get; set; } + public bool CollidesTop { get; set; } + public bool CollidesBottom { get; set; } + public int CollisionTypeTag { get; set; } + + private Vector2 _acceleration = Vector2.Zero; + public Boolean IsWeighted { get; set; } + public Boolean IsCollidable { get; set; } + private List _collisionBoxes; + public PhysicsManager PhysicsMngr { get; set; } + + public bool DisableHitboxUpdating { get; set; } + + public bool AccelerationXEnabled { get; set; } + public bool AccelerationYEnabled { get; set; } + public bool DisableAllWeight { get; set; } + public bool SameTypesCollide { get; set; } + public bool DisableGravity { get; set; } + + protected Rectangle m_terrainBounds; + + // Calls ObjContainer() because other constructors for ObjContainer create SpriteObjs. This container needs PhysicsObjs. + public PhysicsObjContainer(PhysicsManager physicsManager = null) + { + IsWeighted = true; + IsCollidable = true; + _collisionBoxes = new List(); + + if (physicsManager != null) + { + PhysicsMngr = physicsManager; + PhysicsMngr.AddObject(this); + } + + CollidesLeft = true; + CollidesRight = true; + CollidesTop = true; + CollidesBottom = true; + + AccelerationXEnabled = true; + AccelerationYEnabled = true; + } + + public PhysicsObjContainer(string spriteName, PhysicsManager physicsManager = null) + { + IsWeighted = true; + IsCollidable = true; + _collisionBoxes = new List(); + _spriteName = spriteName; // Do not remove this line. + + List charDataList = SpriteLibrary.GetCharData(spriteName); + foreach (CharacterData chars in charDataList) + { + PhysicsObj newObj = new PhysicsObj(chars.Child); + + newObj.X = chars.ChildX; + newObj.Y = chars.ChildY; + this.AddChild(newObj); + + if (!m_spritesheetNameList.Contains(newObj.SpritesheetName)) + m_spritesheetNameList.Add(newObj.SpritesheetName); + } + + if (physicsManager != null) + { + PhysicsMngr = physicsManager; + PhysicsMngr.AddObject(this); + } + + CollidesLeft = true; + CollidesRight = true; + CollidesTop = true; + CollidesBottom = true; + + AccelerationXEnabled = true; + AccelerationYEnabled = true; + + m_numCharData = charDataList.Count; + m_charDataStartIndex = 0; + + UpdateCollisionBoxes(); + } + + public override void ChangeSprite(string spriteName) + { + _spriteName = spriteName; + + if (m_charDataStartIndex == -1) + m_charDataStartIndex = _objectList.Count; // Sets the starting index of when ChangeSprite was called to the end of the object list if it wasn't originally set in the constructor. + + List charDataList = SpriteLibrary.GetCharData(spriteName); + + m_spritesheetNameList.Clear(); + int indexCounter = 0; + for (int i = m_charDataStartIndex; i < charDataList.Count; i++) + { + CharacterData charData = charDataList[indexCounter]; + + if (i >= m_numCharData) + { + PhysicsObj objToAdd = new PhysicsObj(charData.Child); + objToAdd.X = charData.ChildX; + objToAdd.Y = charData.ChildY; + this.AddChildAt(i, objToAdd); + m_numCharData++; + } + else + { + PhysicsObj physicsObj = _objectList[i] as PhysicsObj; + physicsObj.Visible = true; + if (physicsObj != null) + { + physicsObj.ChangeSprite(charData.Child); + physicsObj.X = charData.ChildX; + physicsObj.Y = charData.ChildY; + if (!m_spritesheetNameList.Contains(physicsObj.SpritesheetName)) + m_spritesheetNameList.Add(physicsObj.SpritesheetName); + } + } + + indexCounter++; + } + + if (charDataList.Count < m_numCharData) + { + //for (int i = m_charDataStartIndex + (m_numCharData - charDataList.Count); i < m_charDataStartIndex + m_numCharData; i++) + //for (int i = m_charDataStartIndex + 1; i < m_charDataStartIndex + m_numCharData; i++) + for (int i = charDataList.Count; i < m_numCharData; i++) + { + _objectList[i].Visible = false; + } + + } + + this.StopAnimation(); + CalculateBounds(); + UpdateCollisionBoxes(); + } + + public void UpdatePhysics(GameTime gameTime) + { + float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds; + //if (elapsedSeconds > Consts.FRAMERATE_CAP) elapsedSeconds = Consts.FRAMERATE_CAP; + if (this.AccelerationXEnabled == true) + this.X += _acceleration.X *elapsedSeconds; + + float yAcceleration = _acceleration.Y * elapsedSeconds; + if (yAcceleration < _acceleration.Y * Consts.FRAMERATE_CAP) + yAcceleration = _acceleration.Y * elapsedSeconds; + if (this.AccelerationYEnabled == true) + this.Y += yAcceleration; + } + + public void UpdateCollisionBoxes() + { + m_terrainBounds = new Rectangle(); + int leftBound = int.MaxValue; + int rightBound = -int.MaxValue; + int topBound = int.MaxValue; + int bottomBound = -int.MaxValue; + + foreach (GameObj obj in _objectList) + { + PhysicsObj physObj = obj as PhysicsObj; + if (physObj != null) + { + physObj.UpdateCollisionBoxes(); + + if (physObj.TerrainBounds.Left < leftBound) + leftBound = physObj.TerrainBounds.Left; + + if (physObj.TerrainBounds.Right > rightBound) + rightBound = physObj.TerrainBounds.Right; + + if (physObj.TerrainBounds.Top < topBound) + topBound = physObj.TerrainBounds.Top; + + if (physObj.TerrainBounds.Bottom > bottomBound) + bottomBound = physObj.TerrainBounds.Bottom; + } + } + + m_terrainBounds.X = leftBound; + m_terrainBounds.Y = topBound; + m_terrainBounds.Width = rightBound - leftBound; + m_terrainBounds.Height = bottomBound - topBound; + } + + public virtual void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + if (collisionResponseType == Consts.COLLISIONRESPONSE_TERRAIN && IsWeighted == true) + { + Vector2 mtdPos = CollisionMath.RotatedRectIntersectsMTD(thisBox.AbsRect, thisBox.AbsRotation, Vector2.Zero, otherBox.AbsRect, otherBox.AbsRotation, Vector2.Zero); + IPhysicsObj otherPhysicsObj = otherBox.AbsParent as IPhysicsObj; + int collisionMarginOfError = 10; + if (mtdPos.Y < 0) // There is an object below this object. + { + // This used to be this.AccelerationY > 0. Was changed for player dashing. If it causes problems, revert it back. + if (this.AccelerationY >= 0 && otherPhysicsObj.CollidesTop == true && IsWeighted == true) // This object is falling and there is an object below, so stop this object from falling. + { + // This code is for dropping through blocks. + if (otherBox.AbsRotation != 0 || + + (otherPhysicsObj.TerrainBounds.Left <= this.TerrainBounds.Right && otherPhysicsObj.TerrainBounds.Right >= this.TerrainBounds.Right && (this.TerrainBounds.Right - otherPhysicsObj.TerrainBounds.Left > collisionMarginOfError)) || + (this.TerrainBounds.Left <= otherPhysicsObj.TerrainBounds.Right && this.TerrainBounds.Right >= otherPhysicsObj.TerrainBounds.Right && (otherPhysicsObj.TerrainBounds.Right - this.TerrainBounds.Left > collisionMarginOfError))) + { + this.AccelerationY = 0; + this.Y += mtdPos.Y; + } + } + } + else if (mtdPos.Y > 0) // There is an object above this object. + { + if (this.AccelerationY < 0 && otherPhysicsObj.CollidesBottom == true && IsWeighted == true) // This object is going up and has hit an object above it, so stop this object from going up. + { + this.AccelerationY = 0; + this.Y += mtdPos.Y; + } + } + + if (mtdPos.X != 0) + { + if ((otherPhysicsObj.CollidesLeft == true && mtdPos.X > 0) || + (otherPhysicsObj.CollidesRight == true && mtdPos.X < 0)) + { + this.AccelerationX = 0; + this.X += mtdPos.X; + } + } + + } + } + + public override void AddChild(GameObj obj) + { + PhysicsObj physicsObj = obj as PhysicsObj; + if (physicsObj != null) + { + foreach (CollisionBox box in physicsObj.CollisionBoxes) + { + if (!_collisionBoxes.Contains(box)) + _collisionBoxes.Add(box); + } + } + base.AddChild(obj); + } + + public override void AddChildAt(int index, GameObj obj) + { + PhysicsObj physicsObj = obj as PhysicsObj; + if (physicsObj != null) + { + foreach (CollisionBox box in physicsObj.CollisionBoxes) + { + if (!_collisionBoxes.Contains(box)) + _collisionBoxes.Add(box); + } + } + base.AddChildAt(index, obj); + } + + public override void RemoveChild(GameObj obj) + { + PhysicsObj physicsObj = obj as PhysicsObj; + if (physicsObj != null) + { + foreach (CollisionBox box in physicsObj.CollisionBoxes) + { + if (!_collisionBoxes.Contains(box)) + _collisionBoxes.Remove(box); + } + } + base.RemoveChild(obj); + } + + public override GameObj RemoveChildAt(int index) + { + PhysicsObj obj = null; + + if (_objectList[index] is PhysicsObj) + obj = _objectList[index] as PhysicsObj; + + if (obj != null) + { + foreach (CollisionBox box in obj.CollisionBoxes) + { + _collisionBoxes.Remove(box); + } + } + return base.RemoveChildAt(index); + } + + public override void RemoveAll() + { + _collisionBoxes.Clear(); + base.RemoveAll(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + if (PhysicsMngr != null) + PhysicsMngr.RemoveObject(this); + + foreach (CollisionBox box in _collisionBoxes) + { + box.Dispose(); + } + _collisionBoxes.Clear(); + Node = null; + base.Dispose(); + } + } + + public void RemoveFromPhysicsManager() + { + if (this.PhysicsMngr != null) + this.PhysicsMngr.RemoveObject(this); + } + + + protected override GameObj CreateCloneInstance() + { + + if (_spriteName != "") + return new PhysicsObjContainer(_spriteName); + else + { + PhysicsObjContainer clone = new PhysicsObjContainer(); + + foreach (GameObj obj in _objectList) + clone.AddChild(obj.Clone() as GameObj); + return clone; + } + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + PhysicsObjContainer clone = obj as PhysicsObjContainer; + + if (this.PhysicsMngr != null) + this.PhysicsMngr.AddObject(clone); + + clone.CollidesLeft = this.CollidesLeft; + clone.CollidesRight = this.CollidesRight; + clone.CollidesBottom = this.CollidesBottom; + clone.CollidesTop = this.CollidesTop; + + clone.IsWeighted = this.IsWeighted; + clone.IsCollidable = this.IsCollidable; + clone.DisableHitboxUpdating = this.DisableHitboxUpdating; + clone.CollisionTypeTag = this.CollisionTypeTag; + clone.DisableAllWeight = this.DisableAllWeight; + clone.SameTypesCollide = this.SameTypesCollide; + + clone.AccelerationX = this.AccelerationX; + clone.AccelerationY = this.AccelerationY; + clone.AccelerationXEnabled = this.AccelerationXEnabled; + clone.AccelerationYEnabled = this.AccelerationYEnabled; + clone.DisableGravity = this.DisableGravity; + } + + public override void PopulateFromXMLReader(System.Xml.XmlReader reader, System.Globalization.CultureInfo ci) + { + base.PopulateFromXMLReader(reader, ci); + + if (reader.MoveToAttribute("CollidesTop")) + this.CollidesTop = bool.Parse(reader.Value); + if (reader.MoveToAttribute("CollidesBottom")) + this.CollidesBottom = bool.Parse(reader.Value); + if (reader.MoveToAttribute("CollidesLeft")) + this.CollidesLeft = bool.Parse(reader.Value); + if (reader.MoveToAttribute("CollidesRight")) + this.CollidesRight = bool.Parse(reader.Value); + if (reader.MoveToAttribute("Collidable")) + this.IsCollidable = bool.Parse(reader.Value); + if (reader.MoveToAttribute("Weighted")) + this.IsWeighted = bool.Parse(reader.Value); + } + + public List CollisionBoxes + { + get { return _collisionBoxes; } + } + + public float AccelerationX + { + set { _acceleration.X = value; } + get { return _acceleration.X; } + } + + public float AccelerationY + { + set { _acceleration.Y = value; } + get { return _acceleration.Y; } + } + + public virtual Rectangle TerrainBounds + { + get { return m_terrainBounds; } + } + + public override Vector2 Scale + { + get { return base.Scale; } + set + { + base.Scale = value; + if (DisableHitboxUpdating == false) + UpdateCollisionBoxes(); + } + } + + public override float ScaleX + { + get { return base.ScaleX; } + set + { + base.ScaleX = value; + if (DisableHitboxUpdating == false) + UpdateCollisionBoxes(); + } + } + + public override float ScaleY + { + get { return base.ScaleY; } + set + { + base.ScaleY = value; + if (DisableHitboxUpdating == false) + UpdateCollisionBoxes(); + } + } + + public bool HasTerrainHitBox + { + get + { + foreach (CollisionBox box in _collisionBoxes) + { + if (box.Type == Consts.TERRAIN_HITBOX) + return true; + } + return false; + } + } + + public bool DisableCollisionBoxRotations + { + set + { + foreach (CollisionBox box in _collisionBoxes) + box.DisableRotation = value; + } + get + { + foreach (CollisionBox box in _collisionBoxes) + return box.DisableRotation; + return false; + } + } + } +} diff --git a/DS2DEngine/src/GameObjs/SpriteObj.cs b/DS2DEngine/src/GameObjs/SpriteObj.cs new file mode 100644 index 0000000..2899fb0 --- /dev/null +++ b/DS2DEngine/src/GameObjs/SpriteObj.cs @@ -0,0 +1,604 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using SpriteSystem; + +namespace DS2DEngine +{ + public class SpriteObj : GameObj, IAnimateableObj + { + protected Texture2D _sprite = null; + protected string _spriteName = ""; + protected string m_spritesheetName; + protected Rectangle _ssRect; + protected int _frameDelayCounter; + protected int _frameDuration; + protected int _frameIndex; // The index of the animation if it did not take delay on frames into account. + protected int _frameCount; + protected int _currentFrameIndex = 1; // The index the animation is at if it took delays on frames into account. + private bool m_atEndFrame = false; + private float m_totalGameTime = 0; + + protected int _startAnimationIndex; + protected int _endAnimationIndex; + + protected string m_startLabel; + protected string m_endLabel; + + protected List m_frameDataList; + protected List m_imageDataList; + protected bool _animate = false; + protected bool _loop = true; + private bool m_wasAnimating = false; + + private int m_hackFrameRate = 1; + + private float m_timeDelay = 0; + private float m_timeDelayCounter = 0; + + public bool OverrideParentAnimationDelay = false; + + public Vector2 DropShadow { get; set; } + private Color m_outlineColour = Color.Black; + private int m_outlineWidth = 0; + + #region Constructors + public SpriteObj(string spriteName) + { + _spriteName = spriteName; + + //Fetching sprite data from Sprite Library. + m_imageDataList = SpriteLibrary.GetImageDataList(spriteName); + ImageData imageData = m_imageDataList[0]; + _sprite = SpriteLibrary.GetSprite(spriteName); + _ssRect = new Rectangle((int)(imageData.SSPos.X), (int)(imageData.SSPos.Y), imageData.Width, imageData.Height); + AnchorX = imageData.Anchor.X; + AnchorY = imageData.Anchor.Y; + + m_spritesheetName = SpriteLibrary.GetSpritesheetName(spriteName); + + //Fetching animation data from Sprite Library. + m_frameDataList = SpriteLibrary.GetFrameDataList(spriteName); + _frameCount = m_frameDataList.Count; + if (_frameCount > 1) + { + _frameIndex = 0; + FrameData fd = m_frameDataList[_frameIndex]; + _frameDuration = fd.Duration * AnimationSpeed; + _frameDelayCounter = 1; + } + + TextureColor = Color.White; + Opacity = 1; + + if (SpriteLibrary.ContainsCharacter(_spriteName)) + throw new Exception("Error: Trying to create a SpriteObj or PhysicsObj using Character Name: '" + _spriteName + "'. Character names are used for obj containers. Try using a sprite name instead."); + } + + public SpriteObj(Texture2D sprite) + { + _sprite = sprite; + _ssRect = new Rectangle(0,0, _sprite.Width, _sprite.Height); + _frameIndex = 0; + _frameDuration = 1; + _frameDelayCounter = 1; + _frameCount = 0; + + TextureColor = Color.White; + Opacity = 1; + } + #endregion + + public override void ChangeSprite(string spriteName) + { + // Clear out old Sprite information. + //_sprite = null; + //m_frameDataList = null; + // m_imageDataList = null; + + _spriteName = spriteName; + + //Fetching sprite data from Sprite Library. + m_imageDataList = SpriteLibrary.GetImageDataList(spriteName); + ImageData imageData = m_imageDataList[0]; + _sprite = SpriteLibrary.GetSprite(spriteName); + _ssRect = new Rectangle((int)(imageData.SSPos.X), (int)(imageData.SSPos.Y), imageData.Width, imageData.Height); + AnchorX = imageData.Anchor.X; + AnchorY = imageData.Anchor.Y; + + //Fetching animation data from Sprite Library. + m_frameDataList = SpriteLibrary.GetFrameDataList(spriteName); + _frameCount = m_frameDataList.Count; + _frameIndex = 0; + if (_frameCount > 1) + { + //_frameIndex = 0; + FrameData fd = m_frameDataList[_frameIndex]; + _frameDuration = fd.Duration * AnimationSpeed; + _frameDelayCounter = 1; + } + + this.StopAnimation(); + //PlayAnimation(1, 1); // What is this for and why was it not commented? + } + + public override void Draw(Camera2D camera) + { + if (_sprite.IsDisposed) + ReinitializeSprite(); + + if (_sprite != null && this.Visible == true) + { + if (OutlineWidth > 0 && (Parent == null || Parent.OutlineWidth == 0)) + DrawOutline(camera); + + if (DropShadow != Vector2.Zero) + DrawDropShadow(camera); + + if (Parent == null || OverrideParentScale == true) + { + if (CollisionMath.Intersects(this.Bounds, camera.LogicBounds) || this.ForceDraw == true) + camera.Draw(Sprite, AbsPosition, _ssRect, this.TextureColor * Opacity, MathHelper.ToRadians(Rotation), Anchor, Scale, Flip, 1); + } + else // Don't do a collision intersect test with the camera bounds here because the parent does it. + camera.Draw(Sprite, AbsPosition, _ssRect, this.TextureColor * Opacity, MathHelper.ToRadians(Parent.Rotation + this.Rotation), Anchor, (Parent.Scale * this.Scale), Flip, Layer); + + float elapsedTotalSeconds = camera.ElapsedTotalSeconds; + if (_animate == true && m_totalGameTime != elapsedTotalSeconds) + { + m_totalGameTime = elapsedTotalSeconds; // Used to make sure if you call draw more than once, it doesn't keep animating. + + if (camera.GameTime != null) + m_timeDelayCounter += elapsedTotalSeconds;// (float)camera.GameTime.ElapsedGameTime.TotalSeconds; + + if (_frameCount > 1 && m_timeDelayCounter >= AnimationDelay) + { + m_timeDelayCounter = 0; + if (_currentFrameIndex < _endAnimationIndex || IsLooping == true) + GoToNextFrame(); + else + { + if (m_atEndFrame == false) + m_atEndFrame = true; + else + { + m_atEndFrame = false; + _animate = false; + } + } + } + } + } + } + + //public override void DrawOutline(Camera2D camera, int width) + public override void DrawOutline(Camera2D camera) + { + if (_sprite.IsDisposed) + ReinitializeSprite(); + + int width = OutlineWidth; + if (_sprite != null && this.Visible == true) + { + if (this.Opacity == 1) // Don't do a collision intersect test with the camera bounds here because the parent does it. + { + // Optimization - cache frequently referenced values + Vector2 absPos = AbsPosition; + float posX = absPos.X; + float posY = absPos.Y; + SpriteEffects flip = Flip; + float radianRot = MathHelper.ToRadians(this.Rotation); + Color outlineColor = OutlineColour * Opacity; + Vector2 anchor = Anchor; + float layer = Layer; + Texture2D sprite = Sprite; + Vector2 scale = this.Scale; + + if (Parent == null || OverrideParentScale == true) + { + // Cardinal directions. + camera.Draw(sprite, new Vector2(posX - width, posY), _ssRect, outlineColor, radianRot, anchor, scale, flip, layer); + camera.Draw(sprite, new Vector2(posX + width, posY), _ssRect, outlineColor, radianRot, anchor, scale, flip, layer); + camera.Draw(sprite, new Vector2(posX, posY - width), _ssRect, outlineColor, radianRot, anchor, scale, flip, layer); + camera.Draw(sprite, new Vector2(posX, posY + width), _ssRect, outlineColor, radianRot, anchor, scale, flip, layer); + // The corners. + camera.Draw(sprite, new Vector2(posX - width, posY - width), _ssRect, outlineColor, radianRot, anchor, scale, flip, layer); + camera.Draw(sprite, new Vector2(posX + width, posY + width), _ssRect, outlineColor, radianRot, anchor, scale, flip, layer); + camera.Draw(sprite, new Vector2(posX + width, posY - width), _ssRect, outlineColor, radianRot, anchor, scale, flip, layer); + camera.Draw(sprite, new Vector2(posX - width, posY + width), _ssRect, outlineColor, radianRot, anchor, scale, flip, layer); + } + else + { + Vector2 parentScale = Parent.Scale * scale; + radianRot = MathHelper.ToRadians(Parent.Rotation + this.Rotation); + + // Cardinal directions. + camera.Draw(sprite, new Vector2(posX - width, posY), _ssRect, outlineColor, radianRot, anchor, parentScale, flip, layer); + camera.Draw(sprite, new Vector2(posX + width, posY), _ssRect, outlineColor, radianRot, anchor, parentScale, flip, layer); + camera.Draw(sprite, new Vector2(posX, posY - width), _ssRect, outlineColor, radianRot, anchor, parentScale, flip, layer); + camera.Draw(sprite, new Vector2(posX, posY + width), _ssRect, outlineColor, radianRot, anchor, parentScale, flip, layer); + // The corners. + camera.Draw(sprite, new Vector2(posX - width, posY - width), _ssRect, outlineColor, radianRot, anchor, parentScale, flip, layer); + camera.Draw(sprite, new Vector2(posX + width, posY + width), _ssRect, outlineColor, radianRot, anchor, parentScale, flip, layer); + camera.Draw(sprite, new Vector2(posX + width, posY - width), _ssRect, outlineColor, radianRot, anchor, parentScale, flip, layer); + camera.Draw(sprite, new Vector2(posX - width, posY + width), _ssRect, outlineColor, radianRot, anchor, parentScale, flip, layer); + } + } + } + + //base.DrawOutline(camera); + } + + + public void DrawDropShadow(Camera2D camera) + { + if (this.Visible == true) + { + if (Parent == null || OverrideParentScale == true) + camera.Draw(Sprite, this.AbsPosition + DropShadow, _ssRect, Color.Black * this.Opacity, MathHelper.ToRadians(this.Rotation), Anchor, (this.Scale), Flip, Layer); + else + camera.Draw(Sprite, this.AbsPosition + DropShadow, _ssRect, Color.Black * this.Opacity, MathHelper.ToRadians(Parent.Rotation + this.Rotation), Anchor, (Parent.Scale * this.Scale), Flip, Layer); + } + } + + + public void PlayAnimation(bool loopAnimation = true) + { + _animate = true; + _loop = loopAnimation; + + _startAnimationIndex = 1; + _endAnimationIndex = TotalFrames; + m_timeDelayCounter = 0; + GoToFrame(_startAnimationIndex); + //_currentFrameIndex = 1; + } + + public void PlayAnimation(int startIndex, int endIndex, bool loopAnimation = false) + { + startIndex = (startIndex - 1) * AnimationSpeed + 1; + endIndex = endIndex * AnimationSpeed; + + if (startIndex < 1) + startIndex = 1; + else if (startIndex > TotalFrames) + startIndex = TotalFrames; + + if (endIndex < 1) + endIndex = 1; + else if (endIndex > TotalFrames) + endIndex = TotalFrames; + + _animate = true; + _loop = loopAnimation; + + _startAnimationIndex = startIndex; + _endAnimationIndex = endIndex; + m_timeDelayCounter = 0; + GoToFrame(startIndex); + } + + public void PlayAnimation(string startLabel, string endLabel, bool loopAnimation = false) + { + int startIndex = FindLabelIndex(startLabel); + int endIndex = FindLabelIndex(endLabel); + + if (startIndex == -1) + throw new Exception("Could not find starting label " + startLabel); + else if (endIndex == -1) + throw new Exception("Could not find ending label " + endLabel); + else + PlayAnimation(startIndex, endIndex, loopAnimation); + } + + public int FindLabelIndex(string label) + { + if (Sprite.IsDisposed) + this.ReinitializeSprite(); + + for (int i = 0; i < m_frameDataList.Count; i++) + { + if (m_frameDataList[i].Label == label) + return m_frameDataList[i].Frame; + } + return -1; + } + + public void ResumeAnimation() + { + if (m_wasAnimating == true) + _animate = true; + m_wasAnimating = false; + } + + public void PauseAnimation() + { + m_wasAnimating = this.IsAnimating; + _animate = false; + } + + public void StopAnimation() + { + _animate = false; + m_wasAnimating = false; + } + + public void GoToNextFrame() + { + if (_frameCount > 1) // Only animate if there is more than one frame in the animation. + { + if (_loop == true || _currentFrameIndex < _endAnimationIndex) // Only animate if it hasn't reached the end of the animation or loop is equal to true. + { + if (_frameDelayCounter < _frameDuration) + { + _frameDelayCounter++; + _currentFrameIndex++; + } + else + { + _frameDelayCounter = 1; + _frameIndex++; + _currentFrameIndex++; + + //if (_currentFrameIndex >= _endAnimationIndex) // This was causing problems with PlayAnimation(string startLabel, string endLabel) so it was changed to > only. + if (_currentFrameIndex > _endAnimationIndex) + { + // If current frame goes passed endframe, go back to the starting frame. + GoToFrame(_startAnimationIndex); + } + + if (Sprite.IsDisposed) + this.ReinitializeSprite(); + + FrameData fd = m_frameDataList[_frameIndex]; + _frameDuration = fd.Duration * AnimationSpeed; // Extends the duration of each frame by 2, turning this into 30 fps animations. + ImageData id = m_imageDataList[_frameIndex]; + _ssRect.X = (int)id.SSPos.X; + _ssRect.Y = (int)id.SSPos.Y; + _ssRect.Width = id.Width; + _ssRect.Height = id.Height; + AnchorX = id.Anchor.X; + AnchorY = id.Anchor.Y; + } + } + else if (IsAnimating == true) + { + _animate = false; + } + } + } + + public void GoToFrame(int frameIndex) + { + if (Sprite.IsDisposed) + this.ReinitializeSprite(); + + int frameStart = 0; + int totalFrames = 0; + foreach (FrameData fd in m_frameDataList) + { + totalFrames += fd.Duration * AnimationSpeed; // Remove this 2 to change fps. Hack for now. DO NOT FORGET ABOUT THIS. + if (totalFrames >= frameIndex) + { + frameStart = fd.Index; + break; + } + } + + //_frameDelayCounter = totalFrames - frameIndex; + + _frameIndex = frameStart; + _currentFrameIndex = frameIndex; + + FrameData fd2 = m_frameDataList[_frameIndex]; + _frameDuration = fd2.Duration * AnimationSpeed; // Extends the duration of each frame by 2, turning this into 30 fps animations. + + _frameDelayCounter = _frameDuration - (totalFrames - frameIndex); + + ImageData id = m_imageDataList[_frameIndex]; + _ssRect.X = (int)id.SSPos.X; + _ssRect.Y = (int)id.SSPos.Y; + _ssRect.Width = id.Width; + _ssRect.Height = id.Height; + AnchorX = id.Anchor.X; + AnchorY = id.Anchor.Y; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + if (m_spritesheetName == null) + { + if (_sprite.IsDisposed == false) + _sprite.Dispose(); // Only dispose sprites that don't have a spritesheet name. Because that means they are manual Texture2Ds passed into the constructor. + } + _sprite = null; + m_frameDataList = null; // Do not clear out the lists either since they're also linked to the sprite library. + m_imageDataList = null; + + base.Dispose(); + } + } + + protected override GameObj CreateCloneInstance() + { + return new SpriteObj(_spriteName); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + SpriteObj clone = obj as SpriteObj; + clone.OutlineColour = this.OutlineColour; + clone.OutlineWidth = this.OutlineWidth; + clone.DropShadow = this.DropShadow; + clone.AnimationDelay = this.AnimationDelay; + } + + public RenderTarget2D ConvertToTexture(Camera2D camera, bool resizeToPowerOf2 = true, SamplerState samplerState = null) + { + SpriteEffects storedFlip = this.Flip; + this.Flip = SpriteEffects.None; + + int nextPowerOf2Width = this.Width; + int nextPowerOf2Height = this.Height; + Vector2 newScale = new Vector2(1, 1); + + if (resizeToPowerOf2 == true) + { + nextPowerOf2Width = CDGMath.NextPowerOf2(Width); + nextPowerOf2Height = CDGMath.NextPowerOf2(Height); + newScale = new Vector2(nextPowerOf2Width / (float)Width, nextPowerOf2Height / (float)Height); + } + + float storedRotation = this.Rotation; + this.Rotation = 0; + + if (Sprite.IsDisposed) + this.ReinitializeSprite(); + + RenderTarget2D texture = new RenderTarget2D(camera.GraphicsDevice, nextPowerOf2Width, nextPowerOf2Height); + camera.GraphicsDevice.SetRenderTarget(texture); + camera.GraphicsDevice.Clear(Color.Transparent); + camera.Begin(SpriteSortMode.Immediate, null, samplerState, null, null); + camera.Draw(this.Sprite, this.Anchor, this.SpriteRect, this.TextureColor, this.Rotation, Vector2.Zero, this.Scale * newScale, this.Flip, this.Layer); + camera.End(); + camera.GraphicsDevice.SetRenderTarget(null); + + this.Rotation = storedRotation; + + this.Flip = storedFlip; + return texture; + } + + public void ReinitializeSprite() + { + if (SpriteName != "") + { + m_imageDataList = SpriteLibrary.GetImageDataList(SpriteName); + _sprite = SpriteLibrary.GetSprite(SpriteName); + m_frameDataList = SpriteLibrary.GetFrameDataList(SpriteName); + } + } + + public Texture2D Sprite + { get { return _sprite; } } + + public override int Width + { + get { return (int)(_ssRect.Width * ScaleX); } + } + + public override int Height + { + get { return (int)(_ssRect.Height * ScaleY); } + } + + public int CurrentFrame + { + get { return (int)(_currentFrameIndex / AnimationSpeed); } + } + + public bool IsAnimating + { + get { return _animate; } + } + + public bool IsLooping + { + get { return _loop; } + } + + public int TotalFrames + { + get + { + if (Sprite.IsDisposed) + this.ReinitializeSprite(); + + int totalFrames = 0; + foreach (FrameData fd in m_frameDataList) + { + totalFrames += fd.Duration * AnimationSpeed; // Remove this 2 to change fps. Hack for now. DO NOT FORGET ABOUT THIS. + } + return totalFrames; + } + } + + public string SpriteName + { + get { return _spriteName; } + set { _spriteName = value; } + } + + public int AnimationSpeed + { + get + { + if (Parent == null) + return m_hackFrameRate; + else + return Parent.AnimationSpeed; + } + set { m_hackFrameRate = value; } + } + + public float AnimationDelay + { + get + { + if (Parent == null || OverrideParentAnimationDelay == true) + return m_timeDelay; + else + return Parent.AnimationDelay; + } + set { m_timeDelay = value; } + } + + + public string SpritesheetName + { + get { return m_spritesheetName; } + } + + public Rectangle SpriteRect + { + get { return _ssRect; } + set { _ssRect = value; } + } + + public Color OutlineColour + { + get + { + if (Parent == null || (Parent != null && Parent.OutlineColour == Color.Black)) + return m_outlineColour; + else + return Parent.OutlineColour; + } + set { m_outlineColour = value; } + } + + public int OutlineWidth + { + get + { + if (Parent == null) + return m_outlineWidth; + else + return Parent.OutlineWidth; + } + set { m_outlineWidth = value; } + } + + public bool IsPaused + { + get { return IsAnimating == false && m_wasAnimating == true; } + } + } +} diff --git a/DS2DEngine/src/GameObjs/TextObj.cs b/DS2DEngine/src/GameObjs/TextObj.cs new file mode 100644 index 0000000..ec610be --- /dev/null +++ b/DS2DEngine/src/GameObjs/TextObj.cs @@ -0,0 +1,436 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; +using System.Text.RegularExpressions; +using System.Reflection; + +namespace DS2DEngine +{ + public class TextObj : GameObj + { +#region Fields + + private SpriteFont m_defaultFont = null; // default font for this TextObj + private SpriteFont m_font = null; // current font used for drawing + private string m_text = ""; + private Vector2 m_textSize = Vector2.Zero; + public Types.TextAlign Align = Types.TextAlign.None; + private float m_fontSize = 1; + protected Vector2 m_internalFontSizeScale = new Vector2(1, 1); + public Vector2 DropShadow { get; set; } + public int OutlineWidth { get; set; } + + private string m_typewriteText = ""; + private bool m_isTypewriting = false; + private float m_typewriteSpeed; + private float m_typewriteCounter; + private int m_typewriteCharLength; + + private string m_tapSFX = ""; + + private bool m_isPaused = false; + + private Color m_outlineColour = Color.Black; + private int m_fontIndex = -1; + private Texture2D m_textureValue; + + public bool LimitCorners = false; + +#endregion + +#region Properties + + // language stuff + public string locStringID { get; set; } + + public SpriteFont defaultFont + { get { return m_defaultFont; } } + + public bool isLogographic { get; set; } + + public virtual string Text + { + get { return m_text; } + set + { + m_text = value; + if (Font != null) + m_textSize = Font.MeasureString(m_text); + } + } + + public SpriteFont Font + { + get { return m_font; } + set + { + if (value != null) + { + m_fontIndex = SpriteFontArray.SpriteFontList.IndexOf(value); + if (m_fontIndex == -1) throw new Exception("Cannot find font in SpriteFontArray"); + FieldInfo fieldInfo = value.GetType().GetField("textureValue", BindingFlags.NonPublic | BindingFlags.Instance); + m_textureValue = (Texture2D)fieldInfo.GetValue(value); + } + m_defaultFont = value; + m_font = value; + } + } + + public override Vector2 Anchor + { + get + { + if (Align != Types.TextAlign.None) + { + float scaleX = 1 / (this.ScaleX * m_internalFontSizeScale.X); + //if (Parent != null) // Not sure why this code breaks things. + // scaleX = 1/(this.ScaleX * Parent.ScaleX * m_internalFontSizeScale.X); + + Vector2 anchor; + if (Align == Types.TextAlign.Left) + anchor = new Vector2(0, _anchor.Y); + else if (Align == Types.TextAlign.Centre) + anchor = new Vector2(this.Width / 2 * scaleX, _anchor.Y); + else + anchor = new Vector2(this.Width * scaleX, _anchor.Y); + + if (Flip == SpriteEffects.FlipHorizontally) + anchor.X = Width * scaleX - anchor.X; + return anchor; + } + else + return base.Anchor; + } + set { base.Anchor = value; } + } + + public override float AnchorX + { + get { return Anchor.X; } + set { base.AnchorX = value; } + } + + public override float AnchorY + { + get { return _anchor.Y; } + set { _anchor.Y = value; } + } + + public override int Width + { + get { return (int)(m_textSize.X * ScaleX * m_internalFontSizeScale.X); } + } + + public override int Height + { + get { return (int)(m_textSize.Y * ScaleY * m_internalFontSizeScale.Y); } + } + + public virtual float FontSize + { + get { return m_fontSize; } + set + { + Vector2 minSize = Font.MeasureString("0"); + float newScale = value / minSize.X; + //Scale = new Vector2(newScale, newScale); + m_internalFontSizeScale = new Vector2(newScale, newScale); + m_fontSize = value; + } + } + + public bool IsTypewriting + { + get { return m_isTypewriting; } + } + + public bool IsPaused + { + get { return m_isPaused; } + } + + public Color OutlineColour + { + get + { + if (Parent == null || (Parent != null && Parent.OutlineColour == Color.Black)) + return m_outlineColour; + else + return Parent.OutlineColour; + } + set { m_outlineColour = value; } + } + +#endregion + +#region Methods + + public TextObj(SpriteFont font = null) + { + m_defaultFont = font; + m_font = font; + isLogographic = false; + if (font != null) + { + m_fontIndex = SpriteFontArray.SpriteFontList.IndexOf(font); + if (m_fontIndex == -1) throw new Exception("Cannot find font in SpriteFontArray"); + FieldInfo fieldInfo = font.GetType().GetField("textureValue", BindingFlags.NonPublic | BindingFlags.Instance); + m_textureValue = (Texture2D)fieldInfo.GetValue(font); + } + } + + // This method differs from Font set as it doesn't override default font. + // It is used specifically for changing languages. + public void ChangeFontNoDefault(SpriteFont font) + { + m_font = font; + this.FontSize = m_fontSize; // update font sizing + + // Don't recalculate font and text sizes until next Text property set + } + + public void BeginTypeWriting(float duration, string sound = "") + { + m_isTypewriting = true; + m_typewriteText = this.Text; + m_typewriteSpeed = duration / this.Text.Length; + m_typewriteCounter = m_typewriteSpeed; + m_typewriteCharLength = 0; + this.Text = ""; + + m_tapSFX = sound; + } + + public void PauseTypewriting() + { + m_isPaused = true; + } + + public void ResumeTypewriting() + { + m_isPaused = false; + } + + public void StopTypeWriting(bool completeText) + { + m_isTypewriting = false; + if (completeText == true) + this.Text = m_typewriteText; + } + + //public override void DrawOutline(Camera2D camera, int width) + public override void DrawOutline(Camera2D camera) + { + if (m_textureValue.IsDisposed) + m_font = SpriteFontArray.SpriteFontList[m_fontIndex]; + + int width = OutlineWidth; + if (m_font != null && this.Visible == true) + { + // Optimization - cache frequently referenced values + Vector2 absPos = AbsPosition; + float posX = absPos.X; + float posY = absPos.Y; + SpriteEffects flip = Flip; + float radianRot = MathHelper.ToRadians(this.Rotation); + Color outlineColour = OutlineColour * Opacity; + Vector2 anchor = Anchor; + float layer = Layer; + Vector2 scale = this.Scale * m_internalFontSizeScale; + + //if (this.Opacity == 1) // Don't do a collision intersect test with the camera bounds here because the parent does it. + { + if (Parent == null || OverrideParentScale == true) + { + // Cardinal directions. + camera.DrawString(m_font, m_text, new Vector2(posX - width, posY), outlineColour, radianRot, anchor, scale, flip, layer); + camera.DrawString(m_font, m_text, new Vector2(posX + width, posY), outlineColour, radianRot, anchor, scale, flip, layer); + camera.DrawString(m_font, m_text, new Vector2(posX, posY - width), outlineColour, radianRot, anchor, scale, flip, layer); + camera.DrawString(m_font, m_text, new Vector2(posX, posY + width), outlineColour, radianRot, anchor, scale, flip, layer); + // The corners. + if (LimitCorners == false) + { + camera.DrawString(m_font, m_text, new Vector2(posX - width, posY - width), outlineColour, radianRot, anchor, scale, flip, layer); + camera.DrawString(m_font, m_text, new Vector2(posX + width, posY + width), outlineColour, radianRot, anchor, scale, flip, layer); + camera.DrawString(m_font, m_text, new Vector2(posX + width, posY - width), outlineColour, radianRot, anchor, scale, flip, layer); + camera.DrawString(m_font, m_text, new Vector2(posX - width, posY + width), outlineColour, radianRot, anchor, scale, flip, layer); + } + } + else + { + Vector2 parentScale = Parent.Scale * Scale * m_internalFontSizeScale; + radianRot = MathHelper.ToRadians(Parent.Rotation + this.Rotation); + + // Cardinal directions. + camera.DrawString(m_font, m_text, new Vector2(posX - width, posY), outlineColour, radianRot, anchor, parentScale, flip, layer); + camera.DrawString(m_font, m_text, new Vector2(posX + width, posY), outlineColour, radianRot, anchor, parentScale, flip, layer); + camera.DrawString(m_font, m_text, new Vector2(posX, posY - width), outlineColour, radianRot, anchor, parentScale, flip, layer); + camera.DrawString(m_font, m_text, new Vector2(posX, posY + width), outlineColour, radianRot, anchor, parentScale, flip, layer); + // The corners. + if (LimitCorners == false) + { + camera.DrawString(m_font, m_text, new Vector2(posX - width, posY - width), outlineColour, radianRot, anchor, parentScale, flip, layer); + camera.DrawString(m_font, m_text, new Vector2(posX + width, posY + width), outlineColour, radianRot, anchor, parentScale, flip, layer); + camera.DrawString(m_font, m_text, new Vector2(posX + width, posY - width), outlineColour, radianRot, anchor, parentScale, flip, layer); + camera.DrawString(m_font, m_text, new Vector2(posX - width, posY + width), outlineColour, radianRot, anchor, parentScale, flip, layer); + } + } + } + } + //base.DrawOutline(camera, width); + } + + public override void Draw(Camera2D camera) + { + if (m_textureValue.IsDisposed) + m_font = SpriteFontArray.SpriteFontList[m_fontIndex]; + + if (IsTypewriting == true && m_typewriteCounter > 0 && IsPaused == false) + { + m_typewriteCounter -= (float)camera.GameTime.ElapsedGameTime.TotalSeconds; + if (m_typewriteCounter <= 0 && this.Text != m_typewriteText) + { + if (m_tapSFX != "") + SoundManager.PlaySound(m_tapSFX); + + m_typewriteCounter = m_typewriteSpeed; + m_typewriteCharLength++; + this.Text = m_typewriteText.Substring(0, m_typewriteCharLength); + } + } + + if (IsTypewriting == true && this.Text == m_typewriteText) + m_isTypewriting = false; + + if (DropShadow != Vector2.Zero) + DrawDropShadow(camera); + if (OutlineWidth > 0 && (Parent == null || Parent.OutlineWidth == 0)) + DrawOutline(camera); + //DrawOutline(camera, OutlineWidth); + + if (this.Visible == true) + { + if (Parent == null || OverrideParentScale == true) + camera.DrawString(m_font, m_text, this.AbsPosition, this.TextureColor * this.Opacity, MathHelper.ToRadians(this.Rotation), this.Anchor, this.Scale * m_internalFontSizeScale, SpriteEffects.None, this.Layer); + else + camera.DrawString(m_font, m_text, this.AbsPosition, this.TextureColor * this.Opacity, MathHelper.ToRadians(Parent.Rotation + this.Rotation), Anchor, (Parent.Scale * this.Scale * m_internalFontSizeScale), SpriteEffects.None, Layer); // Flip disabled for now. + } + } + + public void DrawDropShadow(Camera2D camera) + { + if (this.Visible == true) + { + if (Parent == null || OverrideParentScale == true) + camera.DrawString(m_font, m_text, this.AbsPosition + DropShadow, Color.Black * this.Opacity, MathHelper.ToRadians(this.Rotation), this.Anchor, this.Scale * m_internalFontSizeScale, SpriteEffects.None, this.Layer); + else + camera.DrawString(m_font, m_text, this.AbsPosition + DropShadow, Color.Black * this.Opacity, MathHelper.ToRadians(Parent.Rotation + this.Rotation), Anchor, (Parent.Scale * this.Scale * m_internalFontSizeScale), SpriteEffects.None, Layer); // Flip disabled for now. + } + } + + public virtual void WordWrap(int width) + { + if (this.Width > width) + { + String line = String.Empty; + String returnString = String.Empty; + String[] wordArray; + + if (isLogographic) + wordArray = this.Text.Select(x => x.ToString()).ToArray(); + else + wordArray = this.Text.Split(' '); + + foreach (String word in wordArray) + { + if (this.Font.MeasureString(line + word).X * (ScaleX * m_internalFontSizeScale.X) > width) + { + returnString = returnString + line + '\n'; + line = String.Empty; + } + + if (isLogographic) line = line + word; + else line = line + word + ' '; + } + + this.Text = returnString + line; + } + } + + public void RandomizeSentence(bool randomizeNumbers) + { + MatchCollection matches = Regex.Matches(this.Text, @"\b[\w']*\b"); + + foreach (Match match in matches) + { + string word = match.Value; + int result = 0; + if (randomizeNumbers == true || (randomizeNumbers == false && int.TryParse(word, out result) == false)) + { + if (word.Length > 3) // only shuffle words longer than 3 letters. + { + List charArray = word.ToList(); + char firstLetter = charArray[0]; + char lastLetter = charArray[charArray.Count - 1]; + + // Remove the first and last letters from the shuffle array. + charArray.RemoveAt(charArray.Count - 1); + charArray.RemoveAt(0); + + CDGMath.Shuffle(charArray); + string shuffledWord = new string(charArray.ToArray()); + + // Add back the first and last letter to the newly shuffled word. + shuffledWord = firstLetter + shuffledWord + lastLetter; + this.Text = Text.Replace(word, shuffledWord); + + //char[] charArray = word.ToArray(); + //CDGMath.Shuffle(charArray); + //string shuffledWord = new string(charArray); + //this.Text = Text.Replace(word, shuffledWord); + } + } + } + } + + protected override GameObj CreateCloneInstance() + { + TextObj clone = new TextObj(m_defaultFont); + clone.ChangeFontNoDefault(this.m_font); // current font may be different from default font, use it! + return clone; + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + TextObj clone = obj as TextObj; + clone.Text = this.Text; + clone.FontSize = this.FontSize; + clone.OutlineColour = this.OutlineColour; + clone.OutlineWidth = this.OutlineWidth; + clone.DropShadow = this.DropShadow; + clone.Align = this.Align; + clone.LimitCorners = this.LimitCorners; + } + + // A way to insert additional Dispose functionality to the engine's TextObj without having to subclass + public delegate void DisposeDelegate(TextObj textObj); + public static DisposeDelegate disposeMethod; + + public override void Dispose() + { + if (IsDisposed == false) + { + m_font = null; + if (disposeMethod != null) disposeMethod(this); + base.Dispose(); + } + } + +#endregion + } +} diff --git a/DS2DEngine/src/MoveToLogicAction.cs b/DS2DEngine/src/MoveToLogicAction.cs new file mode 100644 index 0000000..d018b0a --- /dev/null +++ b/DS2DEngine/src/MoveToLogicAction.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public class MoveToLogicAction : LogicAction + { + private Vector2 m_targetPos; + private float m_speed; + + //To stop an object from moving, call this method and set overrideSpeed to 0. + public MoveToLogicAction(Vector2 targetPos, float overrideSpeed = -1) + { + m_targetPos = targetPos; + m_speed = overrideSpeed; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + if (m_speed == -1) + m_speed = this.ParentLogicSet.ParentGameObj.Speed; + + this.ParentLogicSet.ParentGameObj.CurrentSpeed = m_speed; + + GameObj mover = ParentLogicSet.ParentGameObj; + mover.Heading = new Vector2(m_targetPos.X - mover.X, m_targetPos.Y - mover.Y); + + if (this.ParentLogicSet.ParentGameObj.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.None) + this.ParentLogicSet.ParentGameObj.Heading = new Vector2(1, 0); + else + this.ParentLogicSet.ParentGameObj.Heading = new Vector2(-1, 0); + base.Execute(); + } + } + + public override void ExecuteNext() + { + if (CDGMath.DistanceBetweenPts(ParentLogicSet.ParentGameObj.Position, m_targetPos) <= 10) + { + ParentLogicSet.ParentGameObj.Position = m_targetPos; + base.ExecuteNext(); + } + } + + + public override void Stop() + { + this.ParentLogicSet.ParentGameObj.CurrentSpeed = 0; + base.Stop(); + } + + public override object Clone() + { + return new MoveToLogicAction(m_targetPos, m_speed); + } + } +} diff --git a/DS2DEngine/src/ParticleObj.cs b/DS2DEngine/src/ParticleObj.cs new file mode 100644 index 0000000..aaff177 --- /dev/null +++ b/DS2DEngine/src/ParticleObj.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace DS2DEngine +{ + public class ParticleObj : GameObj + { + // Position, Velocity, and Acceleration represent exactly what their names + // indicate. They are public fields rather than properties so that users + // can directly access their .X and .Y properties. + public Vector2 Velocity; + public Vector2 Acceleration; + + // how long this particle will "live" + private float lifetime; + public float Lifetime + { + get { return lifetime; } + set { lifetime = value; } + } + + // how long it has been since initialize was called + private float timeSinceStart; + public float TimeSinceStart + { + get { return timeSinceStart; } + set { timeSinceStart = value; } + } + + // how fast does it rotate? In radians. + private float rotationSpeed; + public float RotationSpeed + { + get { return rotationSpeed; } + set { rotationSpeed = value; } + } + + private Texture2D sprite; + public Texture2D Sprite + { + get { return sprite; } + set { sprite = value; } + } + + private float startDelay; + public float StartDelay + { + get { return startDelay; } + set { startDelay = value; } + } + + public Vector2 Origin + { + get { return new Vector2(SpriteSourceRect.Width / 2, SpriteSourceRect.Height / 2); } + } + + public Rectangle SpriteSourceRect = new Rectangle(0, 0, 0, 0); + + // is this particle still alive? once TimeSinceStart becomes greater than + // Lifetime, the particle should no longer be drawn or updated. + public bool Active + { + get { return TimeSinceStart < Lifetime; } + } + + + // initialize is called by ParticleSystem to set up the particle, and prepares + // the particle for use. + public void Initialize(Vector2 position, Vector2 velocity, Vector2 acceleration, + float lifetime, Vector2 scale, float rotationSpeed, float startingRotation) + { + // set the values to the requested values + this.Position = position; + this.Velocity = velocity; + this.Acceleration = acceleration; + this.Lifetime = lifetime; + this.Scale = scale; + this.RotationSpeed = rotationSpeed; + + // reset TimeSinceStart - we have to do this because particles will be + // reused. + this.TimeSinceStart = 0.0f; + + // set rotation to some random value between 0 and 360 degrees. + this.Rotation = startingRotation; + } + + // update is called by the ParticleSystem on every frame. This is where the + // particle's position and that kind of thing get updated. + public void Update(float dt) + { + if (StartDelay <= 0) + { + Velocity += Acceleration * dt; + Position += Velocity * dt; + + Rotation += RotationSpeed * dt; + + TimeSinceStart += dt; + } + else + StartDelay -= dt; + } + + public void Stop() + { + TimeSinceStart = Lifetime; + } + + protected override GameObj CreateCloneInstance() + { + return new ParticleObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + ParticleObj clone = obj as ParticleObj; + clone.Lifetime = this.Lifetime; + clone.Acceleration = this.Acceleration; + clone.Velocity = this.Velocity; + clone.TimeSinceStart = this.TimeSinceStart; + clone.StartDelay = this.StartDelay; + clone.RotationSpeed = this.RotationSpeed; + clone.Sprite = this.Sprite; + } + } +} diff --git a/DS2DEngine/src/ParticleSystem.cs b/DS2DEngine/src/ParticleSystem.cs new file mode 100644 index 0000000..0100cd1 --- /dev/null +++ b/DS2DEngine/src/ParticleSystem.cs @@ -0,0 +1,355 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using SpriteSystem; + +namespace DS2DEngine +{ + public abstract class ParticleSystem : IDisposableObj + { + + private bool m_isDisposed = false; + + // these two values control the order that particle systems are drawn in. + // typically, particles that use additive blending should be drawn on top of + // particles that use regular alpha blending. ParticleSystems should therefore + // set their DrawOrder to the appropriate value in InitializeConstants, though + // it is possible to use other values for more advanced effects. + public const int AlphaBlendDrawOrder = 100; + public const int AdditiveDrawOrder = 200; + + // the texture this particle system will use. + private Texture2D texture; + + // the origin when we're drawing textures. this will be the middle of the + // texture. + private Vector2 origin; + + // this number represents the maximum number of effects this particle system + // will be expected to draw at one time. this is set in the constructor and is + // used to calculate how many particles we will need. + private int howManyEffects; + + // the array of particles used by this system. these are reused, so that calling + // AddParticles will not cause any allocations. + protected ParticleObj[] particles; + + // the queue of free particles keeps track of particles that are not curently + // being used by an effect. when a new effect is requested, particles are taken + // from this queue. when particles are finished they are put onto this queue. + Queue freeParticles; + /// + /// returns the number of particles that are available for a new effect. + /// + public int FreeParticleCount + { + get { return freeParticles.Count; } + } + + + // This region of values control the "look" of the particle system, and should + // be set by deriving particle systems in the InitializeConstants method. The + // values are then used by the virtual function InitializeParticle. Subclasses + // can override InitializeParticle for further + // customization. + #region constants to be set by subclasses + + /// + /// minNumParticles and maxNumParticles control the number of particles that are + /// added when AddParticles is called. The number of particles will be a random + /// number between minNumParticles and maxNumParticles. + /// + protected int minNumParticles; + protected int maxNumParticles; + + /// + /// this controls the texture that the particle system uses. It will be used as + /// an argument to ContentManager.Load. + /// + protected string textureFilename; + + /// + /// minInitialSpeed and maxInitialSpeed are used to control the initial velocity + /// of the particles. The particle's initial speed will be a random number + /// between these two. The direction is determined by the function + /// PickRandomDirection, which can be overriden. + /// + protected float minInitialSpeed; + protected float maxInitialSpeed; + + /// + /// minAcceleration and maxAcceleration are used to control the acceleration of + /// the particles. The particle's acceleration will be a random number between + /// these two. By default, the direction of acceleration is the same as the + /// direction of the initial velocity. + /// + protected float minAcceleration; + protected float maxAcceleration; + + /// + /// minRotationSpeed and maxRotationSpeed control the particles' angular + /// velocity: the speed at which particles will rotate. Each particle's rotation + /// speed will be a random number between minRotationSpeed and maxRotationSpeed. + /// Use smaller numbers to make particle systems look calm and wispy, and large + /// numbers for more violent effects. + /// + protected float minRotationSpeed; + protected float maxRotationSpeed; + + /// + /// minLifetime and maxLifetime are used to control the lifetime. Each + /// particle's lifetime will be a random number between these two. Lifetime + /// is used to determine how long a particle "lasts." Also, in the base + /// implementation of Draw, lifetime is also used to calculate alpha and scale + /// values to avoid particles suddenly "popping" into view + /// + protected float minLifetime; + protected float maxLifetime; + + /// + /// to get some additional variance in the appearance of the particles, we give + /// them all random scales. the scale is a value between minScale and maxScale, + /// and is additionally affected by the particle's lifetime to avoid particles + /// "popping" into view. + /// + protected float minScale; + protected float maxScale; + + /// + /// different effects can use different blend states. fire and explosions work + /// well with additive blending, for example. + /// + protected BlendState blendState; + + protected Rectangle spriteSourceRect; + + #endregion + + /// + /// Constructs a new ParticleSystem. + /// + /// The host for this particle system. The game keeps the + /// content manager and sprite batch for us. + /// the maximum number of particle effects that + /// are expected on screen at once. + /// it is tempting to set the value of howManyEffects very high. + /// However, this value should be set to the minimum possible, because + /// it has a large impact on the amount of memory required, and slows down the + /// Update and Draw functions. + protected ParticleSystem(int howManyEffects) + { + this.howManyEffects = howManyEffects; + } + + /// + /// override the base class's Initialize to do some additional work; we want to + /// call InitializeConstants to let subclasses set the constants that we'll use. + /// + /// also, the particle array and freeParticles queue are set up here. + /// + public void Initialize() + { + InitializeConstants(); + + texture = SpriteLibrary.GetSprite(textureFilename); + + if (spriteSourceRect == new Rectangle(0, 0, 0, 0)) + { + ImageData imageData = SpriteLibrary.GetImageData(textureFilename, 0); + spriteSourceRect = new Rectangle((int)(imageData.SSPos.X), (int)(imageData.SSPos.Y), imageData.Width, imageData.Height); + } + + // ... and calculate the center. this'll be used in the draw call, we + // always want to rotate and scale around this point. + origin.X = spriteSourceRect.Width / 2; + origin.Y = spriteSourceRect.Height / 2; + + // calculate the total number of particles we will ever need, using the + // max number of effects and the max number of particles per effect. + // once these particles are allocated, they will be reused, so that + // we don't put any pressure on the garbage collector. + particles = new ParticleObj[howManyEffects * maxNumParticles]; + freeParticles = new Queue(howManyEffects * maxNumParticles); + for (int i = 0; i < particles.Length; i++) + { + particles[i] = new ParticleObj(); + freeParticles.Enqueue(particles[i]); + particles[i].Sprite = texture; + particles[i].SpriteSourceRect = spriteSourceRect; + } + } + + /// + /// this abstract function must be overriden by subclasses of ParticleSystem. + /// It's here that they should set all the constants marked in the region + /// "constants to be set by subclasses", which give each ParticleSystem its + /// specific flavor. + /// + protected abstract void InitializeConstants(); + + /// + /// AddParticles's job is to add an effect somewhere on the screen. If there + /// aren't enough particles in the freeParticles queue, it will use as many as + /// it can. This means that if there not enough particles available, calling + /// AddParticles will have no effect. + /// + /// where the particle effect should be created + public virtual void StartEffect(Vector2 startingPos) + { + // the number of particles we want for this effect is a random number + // somewhere between the two constants specified by the subclasses. + int numParticles = CDGMath.RandomInt(minNumParticles, maxNumParticles); + + // create that many particles, if you can. + for (int i = 0; i < numParticles && freeParticles.Count > 0; i++) + { + // grab a particle from the freeParticles queue, and Initialize it. + ParticleObj p = freeParticles.Dequeue(); + InitializeParticle(p, startingPos); + } + } + + /// + /// InitializeParticle randomizes some properties for a particle, then + /// calls initialize on it. It can be overriden by subclasses if they + /// want to modify the way particles are created. For example, + /// SmokePlumeParticleSystem overrides this function make all particles + /// accelerate to the right, simulating wind. + /// + /// the particle to initialize + /// the position on the screen that the particle should be + /// + protected virtual void InitializeParticle(ParticleObj p, Vector2 startingPos) + { + // first, call PickRandomDirection to figure out which way the particle + // will be moving. velocity and acceleration's values will come from this. + Vector2 direction = PickRandomDirection(); + + // pick some random values for our particle + float velocity = CDGMath.RandomFloat(minInitialSpeed, maxInitialSpeed); + float acceleration = CDGMath.RandomFloat(minAcceleration, maxAcceleration); + float lifetime = CDGMath.RandomFloat(minLifetime, maxLifetime); + float scale = CDGMath.RandomFloat(minScale, maxScale); + float rotationSpeed = CDGMath.RandomFloat(minRotationSpeed, maxRotationSpeed); + float startingRotation = CDGMath.RandomFloat(0, 360); + + // then initialize it with those random values. initialize will save those, + // and make sure it is marked as active. + p.Initialize( + startingPos, velocity * direction, acceleration * direction, + lifetime, new Vector2(scale, scale), MathHelper.ToRadians(rotationSpeed), startingRotation); + } + + /// + /// PickRandomDirection is used by InitializeParticles to decide which direction + /// particles will move. The default implementation is a random vector in a + /// circular pattern. + /// + protected virtual Vector2 PickRandomDirection() + { + float angle = MathHelper.ToRadians(CDGMath.RandomInt(0,360)); + return new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)); + } + + /// + /// overriden from DrawableGameComponent, Update will update all of the active + /// particles. + /// + public void Update(GameTime gameTime) + { + // calculate dt, the change in the since the last frame. the particle + // updates will use this value. + float dt = (float)gameTime.ElapsedGameTime.TotalSeconds; + // go through all of the particles... + foreach (ParticleObj p in particles) + { + + if (p.Active) + { + // ... and if they're active, update them. + p.Update(dt); + // if that update finishes them, put them onto the free particles + // queue. + } + if (!p.Active) + { + freeParticles.Enqueue(p); + } + } + } + + /// + /// overriden from DrawableGameComponent, Draw will use ParticleSampleGame's + /// sprite batch to render all of the active particles. + /// + public void Draw(Camera2D camera) + { + // tell sprite batch to begin, using the spriteBlendMode specified in + // initializeConstants + //camera.Begin(SpriteSortMode.Deferred, blendState); + + foreach (ParticleObj p in particles) + { + // skip inactive particles + if (!p.Active) + continue; + + // normalized lifetime is a value from 0 to 1 and represents how far + // a particle is through its life. 0 means it just started, .5 is half + // way through, and 1.0 means it's just about to be finished. + // this value will be used to calculate alpha and scale, to avoid + // having particles suddenly appear or disappear. + float normalizedLifetime = p.TimeSinceStart / p.Lifetime; + + // we want particles to fade in and fade out, so we'll calculate alpha + // to be (normalizedLifetime) * (1-normalizedLifetime). this way, when + // normalizedLifetime is 0 or 1, alpha is 0. the maximum value is at + // normalizedLifetime = .5, and is + // (normalizedLifetime) * (1-normalizedLifetime) + // (.5) * (1-.5) + // .25 + // since we want the maximum alpha to be 1, not .25, we'll scale the + // entire equation by 4. + float alpha = 4 * normalizedLifetime * (1 - normalizedLifetime); + Color color = Color.White * alpha; + + // make particles grow as they age. they'll start at 75% of their size, + // and increase to 100% once they're finished. + Vector2 scale = p.Scale * (.75f + .25f * normalizedLifetime); + + //camera.Draw(texture, p.Position, null, color, p.Rotation, origin, scale, SpriteEffects.None, 0.0f); + camera.Draw(texture, p.Position, spriteSourceRect, color, p.Rotation, origin, scale, SpriteEffects.None, 1); + } + + //camera.End(); + } + + public void ResetSystem() + { + foreach (ParticleObj particle in particles) + particle.Stop(); + } + + public void Dispose() + { + if (IsDisposed == false) + { + freeParticles.Clear(); + foreach (ParticleObj particle in particles) + particle.Dispose(); + Array.Clear(particles, 0, particles.Length); + + m_isDisposed = true; + texture = null; + } + } + + public bool IsDisposed + { + get { return m_isDisposed; } + } + } +} diff --git a/DS2DEngine/src/Physics/IPhysicsObj.cs b/DS2DEngine/src/Physics/IPhysicsObj.cs new file mode 100644 index 0000000..f0fffda --- /dev/null +++ b/DS2DEngine/src/Physics/IPhysicsObj.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public interface IPhysicsObj + { + bool CollidesLeft { get; set; } + bool CollidesRight { get; set; } + bool CollidesTop { get; set; } + bool CollidesBottom { get; set; } + bool Visible { get; set; } + bool SameTypesCollide { get; set; } + LinkedListNode Node { get; set; } + + bool DisableHitboxUpdating { get; set; } + + int CollisionTypeTag { get; set; } // A generic tag that developers can use to tag the type of collision object you are running into. + bool IsWeighted { get; set; } + bool AccelerationXEnabled { get; set; } + bool AccelerationYEnabled { get; set; } + bool IsCollidable { get; set; } + float AccelerationX { get; set; } + float AccelerationY { get; set; } + float X { get; set; } + float Y { get; set; } + float Rotation { get; set; } + int Width { get; } + int Height { get; } + + Rectangle Bounds { get; } + Rectangle TerrainBounds { get; } + + PhysicsManager PhysicsMngr { get; set; } + + List CollisionBoxes { get; } + + void UpdatePhysics(GameTime gameTime); + void UpdateCollisionBoxes(); + void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType); + void RemoveFromPhysicsManager(); + + bool DisableAllWeight { get; set; } + + bool HasTerrainHitBox { get; } + bool DisableCollisionBoxRotations { get; set; } + bool DisableGravity { get; set; } + bool UseCachedValues { get; set; } + } +} diff --git a/DS2DEngine/src/Physics/PhysicsManager.cs b/DS2DEngine/src/Physics/PhysicsManager.cs new file mode 100644 index 0000000..4818d0f --- /dev/null +++ b/DS2DEngine/src/Physics/PhysicsManager.cs @@ -0,0 +1,280 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace DS2DEngine +{ + public class PhysicsManager: IDisposable + { + private LinkedList _poList; + public int TerminalVelocity { get; set; } + + private Vector2 _gravity = Vector2.Zero; // In metres per second. + + private Color m_damageHitboxColor = new Color(255, 0, 0, 100); + private Color m_attackHitboxColor = new Color(0, 0, 155, 100); + private Color m_collisionHitboxColor = new Color(0, 53, 0, 100); + private Camera2D m_camera; + + private bool m_isDisposed = false; + + public PhysicsManager() + { + _poList = new LinkedList(); + TerminalVelocity = 1000; + } + + public void Initialize(Camera2D camera) + { + m_camera = camera; + } + + public void AddObject(IPhysicsObj obj) + { + if (obj.Node == null) + { + obj.Node = _poList.AddLast(obj); + obj.PhysicsMngr = this; + } + else + { + _poList.AddLast(obj.Node); + obj.PhysicsMngr = this; + } + + // Optimization - cache the physics values for each collision box + // Calling UpdateCachedValues in the constructor of CollisionBoxes alone + // did not work. Without this cache update, the character would + // fall through the world on the first frame and end up below the ground. + foreach (CollisionBox box in obj.CollisionBoxes) + { + box.UpdateCachedValues(); + } + } + + public void RemoveObject(IPhysicsObj obj) + { + if (obj.Node != null && obj.PhysicsMngr != null) + { + // try + { + _poList.Remove(obj.Node); + obj.PhysicsMngr = null; + } + // catch { Console.WriteLine("Could not remove " + obj + " from Physics Manager as it was not found."); } + } + } + + public void RemoveAllObjects() + { + int counter = _poList.Count; + while (counter > 0) + { + RemoveObject(_poList.Last.Value); + counter--; + } + } + + public void Update(GameTime gameTime) + { + float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds; + + foreach (IPhysicsObj weightedObj in _poList) + { + if (weightedObj.Visible == true)// && CollisionMath.Intersects(weightedObj.Bounds, m_camera.LogicBounds)) + { + if (weightedObj.DisableAllWeight == false) + { + if (weightedObj.IsWeighted == true) + { + Vector2 gravity = new Vector2(_gravity.X * elapsedTime, _gravity.Y * elapsedTime); + + if (weightedObj.AccelerationXEnabled == true && weightedObj.DisableGravity == false) + weightedObj.AccelerationX += gravity.X; + if (weightedObj.AccelerationYEnabled == true && weightedObj.DisableGravity == false) + weightedObj.AccelerationY += gravity.Y; + + if (weightedObj.AccelerationY > TerminalVelocity) + weightedObj.AccelerationY = TerminalVelocity; + } + + weightedObj.UpdatePhysics(gameTime); + } + } + // Update code, physics, and collision code goes here. Only update collision boxes if the flag isn't disabled. (Needed in case you manually add collision boxes, in which case this method + // would constantly override those hitboxes. + if (weightedObj.DisableHitboxUpdating == false) + weightedObj.UpdateCollisionBoxes(); + + weightedObj.UseCachedValues = true; + foreach (CollisionBox box in weightedObj.CollisionBoxes) + box.UpdateCachedValues(); + } + + //Converted to linked list, and had IPhysicsObjs hold a reference to their linkedlist node, so that their addition and removal from the Physics Manager is quick and painless. + LinkedListNode firstNode = _poList.First; + LinkedListNode secondNode = null; + if (firstNode != null) secondNode = firstNode.Next; + + while (firstNode != null) + { + IPhysicsObj firstObj = firstNode.Value; + int firstBoxHBCount = firstObj.CollisionBoxes.Count; + + if (firstObj.IsCollidable == true && firstObj.Visible == true)// && CollisionMath.Intersects(firstObj.Bounds, m_camera.LogicBounds)) + { + while (secondNode != null) + { + IPhysicsObj secondObj = secondNode.Value; + int secondBoxHBCount = secondObj.CollisionBoxes.Count; + secondNode = secondNode.Next; + + // If both objects are the same type (i.e. enemies) & SameType flag is false for BOTH, move to next iteration. + if (firstObj.CollisionTypeTag == secondObj.CollisionTypeTag && (firstObj.SameTypesCollide == false && secondObj.SameTypesCollide == false)) + continue; + + if (secondObj.IsCollidable == true && secondObj.Visible == true)// && CollisionMath.Intersects(secondObj.Bounds, m_camera.LogicBounds)) + { + for (int l = 0; l < firstBoxHBCount; l++) + { + CollisionBox firstBox = firstObj.CollisionBoxes[l]; + + Rectangle firstBoxAbsRect = firstBox.AbsRect; // Optimization so we don't keep pinging it, despite being cached. + float firstBoxAbsRotation = firstBox.AbsRotation; // Optimization so we don't keep pinging it, despite being cached. + + for (int m = 0; m < secondBoxHBCount; m++) + { + CollisionBox secondBox = secondObj.CollisionBoxes[m]; + + Rectangle secondBoxAbsRect = secondBox.AbsRect; + float secondBoxAbsRotation = secondBox.AbsRotation; + + if (firstBox.Type != Consts.NULL_HITBOX && secondBox.Type != Consts.NULL_HITBOX && firstBox.Parent.Visible == true && secondBox.Parent.Visible == true) + { + bool runHitDetection = false; + int collisionResponseType = 0; + // Perform terrain hit detection. + if (firstBox.Type == Consts.TERRAIN_HITBOX && secondBox.Type == Consts.TERRAIN_HITBOX )//&& (firstObj.IsWeighted == false || secondObj.IsWeighted == false)) + { + runHitDetection = true; + collisionResponseType = Consts.COLLISIONRESPONSE_TERRAIN; + } + // Perform weapon/body body/weapon hit detection. + else if ((firstBox.Type == Consts.WEAPON_HITBOX && secondBox.Type == Consts.BODY_HITBOX) || (firstBox.Type == Consts.BODY_HITBOX && secondBox.Type == Consts.WEAPON_HITBOX)) + { + runHitDetection = true; + if (firstBox.Type == Consts.WEAPON_HITBOX) + collisionResponseType = Consts.COLLISIONRESPONSE_SECONDBOXHIT; + else + collisionResponseType = Consts.COLLISIONRESPONSE_FIRSTBOXHIT; + } + + if (runHitDetection == true) + { + if (CollisionMath.RotatedRectIntersects(firstBoxAbsRect, firstBoxAbsRotation, Vector2.Zero, + secondBoxAbsRect, secondBoxAbsRotation, Vector2.Zero) == true) + { + if (collisionResponseType == Consts.COLLISIONRESPONSE_FIRSTBOXHIT) + { + firstObj.CollisionResponse(firstBox, secondBox, Consts.COLLISIONRESPONSE_FIRSTBOXHIT); + secondObj.CollisionResponse(secondBox, firstBox, Consts.COLLISIONRESPONSE_SECONDBOXHIT); + } + else if (collisionResponseType == Consts.COLLISIONRESPONSE_SECONDBOXHIT) + { + firstObj.CollisionResponse(firstBox, secondBox, Consts.COLLISIONRESPONSE_SECONDBOXHIT); + secondObj.CollisionResponse(secondBox, firstBox, Consts.COLLISIONRESPONSE_FIRSTBOXHIT); + } + else + { + firstObj.CollisionResponse(firstBox, secondBox, collisionResponseType); + secondObj.CollisionResponse(secondBox, firstBox, collisionResponseType); + } + + firstBox.UpdateCachedValues(); + secondBox.UpdateCachedValues(); + } + } + } + } + } + } + } + } + + firstNode = firstNode.Next; + if (firstNode != null) + secondNode = firstNode.Next; + } + + foreach (IPhysicsObj weightedObj in _poList) + { + weightedObj.UseCachedValues = false; + } + } + + public void SetGravity(float xGrav, float yGrav) + { + _gravity.X = xGrav; + _gravity.Y = yGrav; + } + + public Vector2 GetGravity() + { + return _gravity; + } + + public LinkedList ObjectList + { + get {return _poList;} + } + + public void DrawAllCollisionBoxes(SpriteBatch spriteBatch, Texture2D texture, int collBoxType) + { + foreach (IPhysicsObj po in _poList) + { + foreach (CollisionBox cb in po.CollisionBoxes) + { + if (cb.Type == collBoxType && cb.Parent.Visible == true && cb.AbsParent.Visible == true) + { + switch (cb.Type) + { + case (Consts.WEAPON_HITBOX): + //spriteBatch.Draw(texture, cb.AbsRect, m_attackHitboxColor); + spriteBatch.Draw(texture, cb.AbsRect, null, m_attackHitboxColor, MathHelper.ToRadians(cb.AbsRotation), Vector2.Zero, SpriteEffects.None, 1); + break; + case (Consts.BODY_HITBOX): + //spriteBatch.Draw(texture, cb.AbsRect, m_damageHitboxColor); + spriteBatch.Draw(texture, cb.AbsRect, null, m_damageHitboxColor, MathHelper.ToRadians(cb.AbsRotation), Vector2.Zero, SpriteEffects.None, 1); + break; + case (Consts.TERRAIN_HITBOX): + //spriteBatch.Draw(texture, cb.AbsRect, m_collisionHitboxColor); + spriteBatch.Draw(texture, cb.AbsRect, null, m_collisionHitboxColor, MathHelper.ToRadians(cb.AbsRotation), Vector2.Zero, SpriteEffects.None, 1); + break; + + } + } + } + } + } + + public bool IsDisposed + { + get { return m_isDisposed;} + } + + public void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Physics Manager"); + + _poList.Clear(); + _poList = null; + m_isDisposed = true; + } + } + } +} diff --git a/DS2DEngine/src/RectangleTree.cs b/DS2DEngine/src/RectangleTree.cs new file mode 100644 index 0000000..76f8012 --- /dev/null +++ b/DS2DEngine/src/RectangleTree.cs @@ -0,0 +1,343 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace DS2DEngine +{ + public class RectangleTree + { + public Dictionary AllItems; + protected Func PositionDelegate; + protected RectangleTreeNode Root; + + public class RectangleTreeItem + { + public RectangleTreeNode Parent; + public Rectangle Position; + public T Value; + } + + public class RectangleTreeNode + { + public RectangleTreeNode Parent; + public RectangleTreeNode[] Children; + public List Items; + public Rectangle Position; + public int ItemCount; + + public RectangleTreeNode(Rectangle dimensions, RectangleTreeNode parent) + { + Items = new List(); + Position = dimensions; + Parent = parent; + } + } + + public RectangleTree(Func positionDelegate, Rectangle dimensions) { + PositionDelegate = positionDelegate; + AllItems = new Dictionary(); + Root = new RectangleTreeNode(dimensions, null); + } + + public void Add(T item) { + RectangleTreeItem i = new RectangleTreeItem(); + i.Value = item; + i.Position = PositionDelegate(item); + AllItems.Add(item, i); + Add(Root, i); + } + + private bool Add(RectangleTreeNode node, RectangleTreeItem item) + { + Rectangle nodePosition = node.Position; + //check if the item is entirely contained in this node + if (nodePosition.Contains(item.Position)) + { + if (node.Children == null) + { + //Bucket has not been split yet + if (node.Items.Count < 5) + { + InnerAdd(node, item); + return true; + } + + //Bucket needs to be split + CreateChildren(node); + + //Move all nodes down + for (int i = 0; i < node.Items.Count; i++) + { + if (MoveDown(node.Items[i])) + { + i--; + } + } + } + //bucket has been split + //try to add the item to each child + foreach (RectangleTreeNode child in node.Children) + { + if (Add(child, item)) + { + node.ItemCount++; + return true; + } + } + + //couldn't add to any children, add to this node + InnerAdd(node, item); + return true; + } + + return false; + } + + private void CreateChildren(RectangleTreeNode node) + { + Rectangle nodePosition = node.Position; + int w = nodePosition.Width / 2, h = nodePosition.Height / 2; + node.Children = new RectangleTreeNode[4] { + new RectangleTreeNode(new Rectangle(nodePosition.X, nodePosition.Y, w, h), node), + new RectangleTreeNode(new Rectangle(nodePosition.X + w, nodePosition.Y, w,h), node), + new RectangleTreeNode(new Rectangle(nodePosition.X, nodePosition.Y + h, w, h), node), + new RectangleTreeNode(new Rectangle(nodePosition.X + w, nodePosition.Y + h, w, h), node) + }; + } + + private bool MoveDown(RectangleTreeItem item) + { + foreach (RectangleTreeNode child in item.Parent.Children) + { + if (Add(child, item)) + { + return true; + } + } + + return false; + } + + private void InnerAdd(RectangleTreeNode node, RectangleTreeItem item) + { + if (item.Parent != null) + { + item.Parent.Items.Remove(item); + } + node.Items.Add(item); + node.ItemCount++; + item.Parent = node; + } + + public void Remove(T item) { + Remove(AllItems[item].Parent, AllItems[item]); + AllItems.Remove(item); + } + + private void Remove(RectangleTreeNode node, RectangleTreeItem item) + { + node.Items.Remove(item); + item.Parent = null; + + while (node != null) + { + node.ItemCount--; + if (node.ItemCount < 6) + { + CollapseChildren(node); + } + node = node.Parent; + } + } + + private void CollapseChildren(RectangleTreeNode node) + { + foreach (RectangleTreeNode child in node.Children) + { + while (child.Items.Count > 0) + { + MoveUp(child.Items[0]); + } + } + + node.Children = null; + } + + private void MoveUp(RectangleTreeItem item) + { + item.Parent.Items.Remove(item); + item.Parent.ItemCount--; + if (item.Parent.Children != null && item.Parent.ItemCount < 6) + { + CollapseChildren(item.Parent); + } + item.Parent = item.Parent.Parent; + + + if (item.Parent == null) + { + AllItems.Remove(item.Value); + } + else + { + item.Parent.Items.Add(item); + } + } + + public void UpdatePosition(T item){ + RectangleTreeItem ri = AllItems[item]; + Rectangle newPosition = PositionDelegate(item); + + if (newPosition == ri.Position) + { + return; + } + + ri.Position = newPosition; + if (ri.Parent.Position.Contains(newPosition)) + { //Step Into + if (ri.Parent.Children != null) + MoveDown(ri); + } + else + { + do + { //Step Out Of + MoveUp(ri); + } while (ri.Parent != null && !ri.Parent.Position.Contains(newPosition)); + + if (ri.Parent != null) + { + Add(ri.Parent, ri); + } + } + } + + public T[] GetItems(Rectangle area) { + return GetItems(Root, area); + } + + private T[] GetItems(RectangleTreeNode node, Rectangle area) + { + List items = new List(); + foreach (RectangleTreeItem item in node.Items) + { + if (item.Position.Intersects(area) || item.Position.Contains(area) || area.Contains(item.Position)) + { + items.Add(item.Value); + } + } + + if (node.Children != null) + { + foreach (RectangleTreeNode child in node.Children) + { + if (area.Contains(child.Position)) + { + items.AddRange(GetAllItems(node)); + } + else if (child.Position.Contains(area)) + { + items.AddRange(GetItems(child, area)); + break; + } + else if (child.Position.Intersects(area)) + { + items.AddRange(GetItems(child, area)); + } + } + } + + return items.ToArray(); + } + + private T[] GetAllItems(RectangleTreeNode node) + { + T[] items = new T[node.ItemCount]; + int i = 0; + foreach (RectangleTreeItem item in node.Items) + { + items[i++] = item.Value; + } + + if (node.Children != null) + { + int q; + foreach (RectangleTreeNode child in node.Children) + { + T[] tmp = GetAllItems(child); + for (q = i; q < tmp.Length + i; q++) + { + items[q] = tmp[q - i]; + } + i = q; + } + } + + return items; + } + + public T[] GetItems(Point point) { + return GetItems(Root, point); + } + + private T[] GetItems(RectangleTreeNode node, Point point) + { + List items = new List(); + foreach (RectangleTreeItem item in node.Items) + { + if (item.Position.Contains(point)) + { + items.Add(item.Value); + } + } + + if (node.Children != null) + { + foreach (RectangleTreeNode child in node.Children) + { + if(child.Position.Contains(point)) { + items.AddRange(GetItems(child, point)); + break; + } + } + } + return items.ToArray(); + } + } + + public class RectangleDrawer : RectangleTree + { + Texture2D pixel; + + public RectangleDrawer(GraphicsDevice graphicsDevice, Func positionDelegate, Rectangle dimensions) + : base(positionDelegate, dimensions) + { + pixel = new Texture2D(graphicsDevice, 1, 1); + pixel.SetData(new Color[] { Color.White }); + } + public void Draw(SpriteBatch spriteBatch) + { + Draw(Root, spriteBatch); + } + + private void Draw(RectangleTreeNode Root, SpriteBatch spriteBatch) + { + spriteBatch.Draw(pixel, new Rectangle(Root.Position.X, Root.Position.Y, 1, Root.Position.Height), Color.White); + spriteBatch.Draw(pixel, new Rectangle(Root.Position.X, Root.Position.Y, Root.Position.Width, 1), Color.White); + spriteBatch.Draw(pixel, new Rectangle(Root.Position.X, Root.Position.Bottom, Root.Position.Width, 1), Color.White); + spriteBatch.Draw(pixel, new Rectangle(Root.Position.Right, Root.Position.Y, 1, Root.Position.Height), Color.White); + + if (Root.Children != null) + { + foreach (RectangleTreeNode child in Root.Children) + { + Draw(child, spriteBatch); + } + } + } + } +} \ No newline at end of file diff --git a/DS2DEngine/src/SafeArea.cs b/DS2DEngine/src/SafeArea.cs new file mode 100644 index 0000000..a9e0cd5 --- /dev/null +++ b/DS2DEngine/src/SafeArea.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace DS2DEngine +{ + /// + /// Credit goes to Manders (on internet) for the basis of this code. + /// + /// A helper class to indicate the "safe area" for rendering to a + /// television. The inner 90% of the viewport is the "action safe" area, + /// meaning all important "action" should be shown within this area. The + /// inner 80% of the viewport is the "title safe area", meaning all text + /// and other key information should be shown within in this area. This + /// class shows the area that is not "title safe" in yellow, and the area + /// that is not "action safe" in red. + /// + public class SafeArea : DrawableGameComponent + { + SpriteBatch spriteBatch; + Texture2D tex; // Holds a 1x1 texture containing a single white texel + int width; // Viewport width + int height; // Viewport height + int dx; // 5% of width + int dy; // 5% of height + Color notActionSafeColor = new Color(255, 0, 0, 127); // Red, 50% opacity + Color notTitleSafeColor = new Color(255, 255, 0, 127); // Yellow, 50% opacity + + public SafeArea(Game game) + : base(game) + { + //this.DrawOrder = (int)(DrawLevel.SafeArea); + game.Components.Add(this); + } + + public override void Initialize() + { + base.Initialize(); + this.Enabled = false; // No need to call update for this + this.Visible = true; + } + + protected override void LoadContent() + { + base.LoadContent(); + + spriteBatch = new SpriteBatch(base.GraphicsDevice); + tex = new Texture2D(base.GraphicsDevice, 1, 1, false, SurfaceFormat.Color); + Color[] texData = new Color[1]; + texData[0] = Color.White; + tex.SetData(texData); + width = base.GraphicsDevice.Viewport.Width; + height = base.GraphicsDevice.Viewport.Height; + dx = (int)(width * 0.05); + dy = (int)(height * 0.05); + } + + public override void Draw(GameTime gameTime) + { + base.Draw(gameTime); + + if (Consts.DEBUG_ShowSafeZones == true) + { + spriteBatch.Begin(); + + // Tint the non-action-safe area red + spriteBatch.Draw(tex, new Rectangle(0, 0, width, dy), notActionSafeColor); + spriteBatch.Draw(tex, new Rectangle(0, height - dy, width, dy), notActionSafeColor); + spriteBatch.Draw(tex, new Rectangle(0, dy, dx, height - 2 * dy), notActionSafeColor); + spriteBatch.Draw(tex, new Rectangle(width - dx, dy, dx, height - 2 * dy), notActionSafeColor); + + // Tint the non-title-safe area yellow + spriteBatch.Draw(tex, new Rectangle(dx, dy, width - 2 * dx, dy), notTitleSafeColor); + spriteBatch.Draw(tex, new Rectangle(dx, height - 2 * dy, width - 2 * dx, dy), notTitleSafeColor); + spriteBatch.Draw(tex, new Rectangle(dx, 2 * dy, dx, height - 4 * dy), notTitleSafeColor); + spriteBatch.Draw(tex, new Rectangle(width - 2 * dx, 2 * dy, dx, height - 4 * dy), notTitleSafeColor); + spriteBatch.End(); + } + } + } +} diff --git a/DS2DEngine/src/Screens/Screen.cs b/DS2DEngine/src/Screens/Screen.cs new file mode 100644 index 0000000..dad0dd0 --- /dev/null +++ b/DS2DEngine/src/Screens/Screen.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public abstract class Screen : IDisposableObj + { + public bool UpdateIfCovered { get; set; } + public bool DrawIfCovered { get; set; } + public bool HandleInputIfCovered { get; set; } + public bool HasFocus {get;set;} + public PlayerIndex? ControllingPlayer { get; set; } + public ScreenManager ScreenManager { get; set; } + private bool m_isInitialized = false; + private bool m_isPaused = false; + private bool m_isContentLoaded = false; + private bool m_isDisposed = false; + + public Screen() + { + UpdateIfCovered = false; + DrawIfCovered = false; + HasFocus = false; + } + + public virtual void Initialize() + { + m_isInitialized = true; + } + + public virtual void ReinitializeRTs() + { + } + + public virtual void DisposeRTs() + { + } + + public virtual void RefreshTextObjs() {} + + public virtual void LoadContent() + { + m_isContentLoaded = true; + } + + /// + /// Allows the screen to handle user input. Unlike Update, this method + /// is only called when the screen is active, and not when some other + /// screen has taken the focus. + /// + public virtual void HandleInput() { } + + /// + /// Allows the screen to accept data from other screens. + /// + /// The list of data to be passed in. + public virtual void PassInData(List objList) + { + objList.Clear(); // Just in case. + } + + public virtual void Update(GameTime gameTime) + { + } + + public virtual void Draw(GameTime gametime) { } + + /// + /// Called right after is a screen is added to the ScreenManager's screen list. + /// In case some initializing needs to take place on the as it enters. + /// + public virtual void OnEnter() { } + + /// + /// Called right after the screen is removed from the ScreenManager's screen list. + /// In case some de-initializing needs to take place on the screen as it leaves. + /// + public virtual void OnExit() { } + + /// + /// Pauses the screen. + /// + public virtual void PauseScreen() { m_isPaused = true; } + + /// + /// Unpauses the screen. + /// + public virtual void UnpauseScreen() { m_isPaused = false; } + + public virtual void Dispose() + { + m_isDisposed = true; + } + + public bool IsInitialized + { + get { return m_isInitialized; } + } + + public bool IsPaused + { + get { return m_isPaused; } + } + + public bool IsContentLoaded + { + get { return m_isContentLoaded; } + } + + public bool IsDisposed + { + get { return m_isDisposed; } + } + + public Camera2D Camera + { + get { return ScreenManager.Camera; } + } + } +} diff --git a/DS2DEngine/src/Screens/ScreenManager.cs b/DS2DEngine/src/Screens/ScreenManager.cs new file mode 100644 index 0000000..8cbb4c5 --- /dev/null +++ b/DS2DEngine/src/Screens/ScreenManager.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; + +namespace DS2DEngine +{ + public class ScreenManager + { + protected List m_screenArray; + private List m_screensToUpdate; + protected Camera2D m_camera; + private Game m_game; + private bool m_isInitialized = false; + private bool m_isContentLoaded = false; + + public ScreenManager(Game game) + { + m_screenArray = new List(); + m_screensToUpdate = new List(); + m_game = game; + } + + public virtual void Initialize() + { + if (IsInitialized == false) + { + ContentManager content = m_game.Content; + m_camera = new Camera2D(m_game.GraphicsDevice, EngineEV.ScreenWidth, EngineEV.ScreenHeight); + m_isInitialized = true; + } + } + + public virtual void LoadContent() + { + m_isContentLoaded = true; + } + + public virtual void AddScreen(Screen screen, PlayerIndex? controllingPlayer) + { + AddScreenAt(screen, controllingPlayer, m_screenArray.Count); + } + + public virtual void AddScreenAt(Screen screen, PlayerIndex? controllingPlayer, int index) + { + screen.ControllingPlayer = controllingPlayer; + screen.ScreenManager = this; + + // If we have a graphics device, tell the screen to load content. + if (IsInitialized && screen.IsContentLoaded == false) + screen.LoadContent(); + + m_screenArray.Insert(index, screen); + screen.OnEnter(); + } + + public virtual void RemoveScreen(Screen screen, bool disposeScreen) + { + screen.OnExit(); + if (disposeScreen == true) + screen.Dispose(); + + m_screenArray.Remove(screen); + screen.ScreenManager = null; + } + + public virtual void Update(GameTime gameTime) + { + m_screensToUpdate.Clear(); + foreach (Screen screen in m_screenArray) + m_screensToUpdate.Add(screen); + + Camera.GameTime = gameTime; + Camera.ElapsedTotalSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds; + + int screensToUpdateCount = m_screensToUpdate.Count; + for (int i = 0; i < screensToUpdateCount; i++) + { + Screen screen = m_screensToUpdate[i]; + if (i < screensToUpdateCount - 1) + { + if (screen.UpdateIfCovered == false) + continue; + screen.Update(gameTime); + if (screen.HandleInputIfCovered == false) + continue; + screen.HandleInput(); + } + else + { + screen.Update(gameTime); + screen.HandleInput(); + } + } + + //foreach (Screen screen in m_screensToUpdate) + //{ + // if (screen.UpdateIfCovered == false && screen != CurrentScreen) + // continue; + // screen.Update(gameTime); + // if (screen.HandleInputIfCovered == false && screen != CurrentScreen) + // screen.HandleInput(); + //} + } + + public virtual void Draw(GameTime gameTime) + { + foreach (Screen screen in m_screenArray) + { + //if (screen.ScreenState == ScreenState.Hidden) + // continue; + + if (screen.DrawIfCovered == false && screen != CurrentScreen) + continue; + + screen.Draw(gameTime); + } + } + + public Screen CurrentScreen + { + get + { + if (m_screenArray.Count < 1) return null; + return m_screenArray[m_screenArray.Count - 1]; + } + } + + public bool Contains(Screen screen) + { + return m_screenArray.Contains(screen); + } + + public Screen[] GetScreens() + { + return m_screenArray.ToArray(); + } + + public Game Game + { + get { return m_game; } + } + + public Camera2D Camera + { + get { return m_camera; } + } + + public bool IsInitialized + { + get { return m_isInitialized; } + } + + public bool IsContentLoaded + { + get { return m_isContentLoaded; } + } + } +} diff --git a/DS2DEngine/src/SoundManager.cs b/DS2DEngine/src/SoundManager.cs new file mode 100644 index 0000000..d6da08b --- /dev/null +++ b/DS2DEngine/src/SoundManager.cs @@ -0,0 +1,556 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework.Audio; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework; + +namespace DS2DEngine +{ + public class SoundManager + { + public static bool IsDisposed { get { return m_isDisposed; } } + private static bool m_isDisposed = false; + + private static WaveBank m_musicWaveBank; + private static SoundBank m_musicSoundBank; + private static AudioEngine m_audioEngine; + private static SoundBank m_sfxSoundBank; + private static WaveBank m_sfxWaveBank; + + // Variables for dealing with music fading. + private static Cue m_currentMusicCue; + private static Cue m_nextMusicCue; + private static string m_songName; + private static bool m_loopMusic = false; + private static float m_musicFadeIn = 0; + private static float m_musicFadeInCounter = 0; + private static float m_musicFadeOut = 0; + private static float m_musicFadeOutCounter = 0; + private static float m_musicVolume = 1; + private static bool m_musicFadingIn = false; + private static bool m_musicFadingOut = false; + + private static List m_positionalSoundList; + private static AudioEmitter m_emitter; + private static AudioListener m_listener; + + private static float m_globalMusicVolume = 1; + private static float m_globalSFXVolume = 1; + + private static List m_queuedSoundList; + + public static void Initialize(string settingsFile) + { + try + { + m_audioEngine = new AudioEngine(settingsFile); + m_positionalSoundList = new List(); + m_emitter = new AudioEmitter(); + m_listener = new AudioListener(); + + m_queuedSoundList = new List(); + } + catch (Exception e) + { + Console.WriteLine("Failed to initialize audio engine. Original Error:" + e.ToString()); + } + } + + public static void LoadWaveBank(string wbFilename, bool isMusicWB = false) + { + if (m_audioEngine != null) + { + if (isMusicWB == true) + { + if (m_musicWaveBank != null) + m_musicWaveBank.Dispose(); + m_musicWaveBank = new WaveBank(m_audioEngine, wbFilename); + } + else + { + if (m_sfxWaveBank != null) + m_sfxWaveBank.Dispose(); + m_sfxWaveBank = new WaveBank(m_audioEngine, wbFilename); + } + } + } + + public static void LoadSoundBank(string sbFileName, bool isMusicSB = false) + { + if (m_audioEngine != null) + { + if (isMusicSB == true) + { + if (m_musicSoundBank != null) + m_musicSoundBank.Dispose(); + m_musicSoundBank = new SoundBank(m_audioEngine, sbFileName); + } + else + { + if (m_sfxSoundBank != null) + m_sfxSoundBank.Dispose(); + m_sfxSoundBank = new SoundBank(m_audioEngine, sbFileName); + } + } + } + + public static Cue PlayMusic(string songName, bool loopSong, float fade = 0) + { + if (m_audioEngine != null) + { + m_songName = songName; + m_loopMusic = loopSong; + + if (fade == 0) + { + if (m_currentMusicCue != null) + { + m_currentMusicCue.Stop(AudioStopOptions.Immediate); + m_currentMusicCue.Dispose(); + } + m_currentMusicCue = m_musicSoundBank.GetCue(songName); + m_currentMusicCue.Play(); + + m_audioEngine.GetCategory("Music").SetVolume(m_musicVolume * m_globalMusicVolume); + m_musicFadeOutCounter = 0; + return m_currentMusicCue; + } + else + { + // A song is already playing. So fade it out by the set time then play the next song. + if (IsMusicPlaying == true) + { + if (IsMusicFadingIn == true) + { + m_musicFadeOut = m_musicFadeIn; + m_musicFadeOutCounter = m_musicFadeIn - m_musicFadeInCounter; + m_musicFadeIn = m_musicFadeInCounter = fade; + } + else if (IsMusicFadingOut == true) + m_musicFadeIn = m_musicFadeInCounter = fade; + else + m_musicFadeIn = m_musicFadeInCounter = m_musicFadeOut = m_musicFadeOutCounter = fade; + + m_nextMusicCue = m_musicSoundBank.GetCue(songName); + + return m_nextMusicCue; + } + else + { + m_musicFadeOut = m_musicFadeOutCounter = 0; + m_musicFadeIn = m_musicFadeInCounter = fade; + + m_audioEngine.GetCategory("Music").SetVolume(0); + + if (m_currentMusicCue != null) + m_currentMusicCue.Dispose(); + m_currentMusicCue = m_musicSoundBank.GetCue(songName); + m_currentMusicCue.Play(); + return m_currentMusicCue; + } + } + } + return null; + } + + public static void StopMusic(float fade = 0) + { + if (m_audioEngine != null) + { + if (fade == 0) + { + m_musicFadeIn = m_musicFadeInCounter = m_musicFadeOut = m_musicFadeOutCounter = 0; + if (m_currentMusicCue != null) + m_currentMusicCue.Stop(AudioStopOptions.Immediate); + } + else + { + if (IsMusicFadingOut == false) // If music is already fading out, just let it fade out. Otherwise do the fade. + m_musicFadeOut = m_musicFadeOutCounter = fade; + } + + if (m_nextMusicCue != null) + { + m_nextMusicCue.Dispose(); + m_nextMusicCue = null; + } + + m_loopMusic = false; + } + } + + public static void PauseMusic() + { + if (m_audioEngine != null) + { + if (m_currentMusicCue != null && m_currentMusicCue.IsPaused == false) + m_currentMusicCue.Pause(); + } + } + + public static void ResumeMusic() + { + if (m_audioEngine != null) + { + if (m_currentMusicCue != null && m_currentMusicCue.IsPaused == true) + m_currentMusicCue.Resume(); + } + } + + public static Cue PlaySound(string soundName) + { + if (m_audioEngine != null) + { + Cue cue = m_sfxSoundBank.GetCue(soundName); + cue.Play(); + return cue; + } + return null; + } + + public static Cue PlaySound(params string[] soundName) + { + if (m_audioEngine != null) + { + Cue cue = m_sfxSoundBank.GetCue(soundName[CDGMath.RandomInt(0, soundName.Length - 1)]); + cue.Play(); + return cue; + } + return null; + } + + public static Cue Play3DSound(GameObj emitter, GameObj listener, string soundName) + { + if (m_audioEngine != null) + { + Cue cue = m_sfxSoundBank.GetCue(soundName); + PositionalSoundObj positionalSound = new PositionalSoundObj() { Emitter = emitter, Listener = listener, AttachedCue = cue }; + positionalSound.Update(m_listener, m_emitter); + + // This code checks to see if a sound is played multiple times, and if so, find the one closest to the player and play that one. + PositionalSoundObj soundObjToRemove = null; + foreach (PositionalSoundObj soundObj in m_queuedSoundList) + { + Cue cueCheck = soundObj.AttachedCue; + if (cueCheck.Name == cue.Name) + { + soundObj.Update(m_listener, m_emitter); + // The stored cue is further away and needs to be replaced. + if (cueCheck.GetVariable("Distance") > cue.GetVariable("Distance")) + soundObjToRemove = soundObj; + else // The stored cue is closer, therefore break out of this method and just return the created cue.. + return cue; + } + } + + if (soundObjToRemove != null) + { + // This code replaces the stored sound with the new sound. + m_queuedSoundList.Remove(soundObjToRemove); + soundObjToRemove.Dispose(); + m_queuedSoundList.Add(positionalSound); + } + else + // This happens if this is the only instance of the sound found in the positional sound list. + m_queuedSoundList.Add(positionalSound); + + return cue; + } + return null; + } + + public static Cue Play3DSound(GameObj emitter, GameObj listener, params string[] soundName) + { + if (m_audioEngine != null) + { + Cue cue = m_sfxSoundBank.GetCue(soundName[CDGMath.RandomInt(0, soundName.Length - 1)]); + PositionalSoundObj positionalSound = new PositionalSoundObj() { Emitter = emitter, Listener = listener, AttachedCue = cue }; + positionalSound.Update(m_listener, m_emitter); + + // This code checks to see if a sound is played multiple times, and if so, find the one closest to the player and play that one. + PositionalSoundObj soundObjToRemove = null; + foreach (PositionalSoundObj soundObj in m_queuedSoundList) + { + Cue cueCheck = soundObj.AttachedCue; + if (cueCheck.Name == cue.Name) + { + soundObj.Update(m_listener, m_emitter); + // The stored cue is further away and needs to be replaced. + if (cueCheck.GetVariable("Distance") > cue.GetVariable("Distance")) + soundObjToRemove = soundObj; + else // The stored cue is closer, therefore break out of this method and just return the created cue.. + return cue; + } + } + + if (soundObjToRemove != null) + { + // This code replaces the stored sound with the new sound. + m_queuedSoundList.Remove(soundObjToRemove); + soundObjToRemove.Dispose(); + m_queuedSoundList.Add(positionalSound); + } + else + // This happens if this is the only instance of the sound found in the positional sound list. + m_queuedSoundList.Add(positionalSound); + + return cue; + } + return null; + } + + public static void StopAllSounds(string category) + { + if (m_audioEngine != null) + m_audioEngine.GetCategory(category).Stop(AudioStopOptions.Immediate); + } + + public static void PauseAllSounds(string category) + { + if (m_audioEngine != null) + m_audioEngine.GetCategory(category).Pause(); + } + + public static void ResumeAllSounds(string category) + { + if (m_audioEngine != null) + m_audioEngine.GetCategory(category).Resume(); + } + + public static void Update(GameTime gameTime) + { + if (m_audioEngine != null) + { + float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds; + + m_audioEngine.Update(); + // Makes music loop if IsLooping is set to true. + if (IsMusicLooping == true && IsMusicPlaying == false && m_musicFadeInCounter <= 0 && m_musicFadeOutCounter <= 0) + PlayMusic(m_songName, true, 0); + //PlayMusic(m_songName, true, m_musicFadeIn); + + if (IsMusicPlaying == true && IsMusicPaused == false) + { + if (m_musicFadeOutCounter > 0) // If there is a fade out, fade out the volume. + { + m_musicFadingIn = false; + m_musicFadingOut = true; + + m_musicFadeOutCounter -= elapsedTime; + float reductionPercent = m_musicFadeOutCounter / m_musicFadeOut; + if (reductionPercent < 0) reductionPercent = 0; + m_audioEngine.GetCategory("Music").SetVolume(m_musicVolume * reductionPercent * m_globalMusicVolume); + + if (m_musicFadeOutCounter <= 0 && m_nextMusicCue == null) + m_currentMusicCue.Stop(AudioStopOptions.Immediate); + } + else if (m_musicFadeOutCounter <= 0 && m_nextMusicCue != null) // If fade out is 0 but a song is queued, switch songs and play the next song. + { + m_currentMusicCue.Stop(AudioStopOptions.Immediate); + m_currentMusicCue.Dispose(); + m_currentMusicCue = m_nextMusicCue; + m_nextMusicCue = null; + m_currentMusicCue.Play(); + } + + if (m_musicFadeOutCounter <= 0 && m_musicFadeInCounter > 0) // If there is a fade in, fade in the volume. + { + m_musicFadingIn = true; + m_musicFadingOut = false; + + m_musicFadeInCounter -= elapsedTime; + float increasePercent = 1 - m_musicFadeInCounter / m_musicFadeIn; + if (increasePercent < 0) increasePercent = 0; + m_audioEngine.GetCategory("Music").SetVolume(m_musicVolume * increasePercent * m_globalMusicVolume); + } + else + { + m_musicFadingIn = false; + m_musicFadingOut = false; + } + } + } + } + + public static void Update3DSounds() + { + if (m_audioEngine != null) + { + foreach (PositionalSoundObj soundObj in m_queuedSoundList) + { + soundObj.AttachedCue.Play(); + m_positionalSoundList.Add(soundObj); + } + m_queuedSoundList.Clear(); + + for (int i = 0; i < m_positionalSoundList.Count; i++) + { + PositionalSoundObj sound = m_positionalSoundList[i]; + + if (sound.AttachedCue.IsPlaying == false) + { + if (sound.IsDisposed == false) + sound.Dispose(); + m_positionalSoundList.Remove(sound); + i--; + } + else + { + sound.Update(m_listener, m_emitter); + } + } + } + } + + public static void Dispose() + { + if (IsDisposed == false) + { + if (m_audioEngine != null) + { + if (m_currentMusicCue != null) + m_currentMusicCue.Dispose(); + m_currentMusicCue = null; + if (m_nextMusicCue != null) + m_nextMusicCue.Dispose(); + m_nextMusicCue = null; + + m_sfxSoundBank.Dispose(); + m_musicSoundBank.Dispose(); + m_sfxWaveBank.Dispose(); + m_musicWaveBank.Dispose(); + m_audioEngine.Dispose(); + + foreach (PositionalSoundObj soundObj in m_positionalSoundList) + soundObj.Dispose(); + m_positionalSoundList.Clear(); + m_positionalSoundList = null; + + m_emitter = null; + m_listener = null; + } + m_isDisposed = true; + } + } + + public static bool IsMusicFadingIn + { get { return m_musicFadingIn; } } + + public static bool IsMusicFadingOut + { get { return m_musicFadingOut; } } + + public static bool IsMusicPlaying + { + get + { + if (m_currentMusicCue == null) + return false; + return m_currentMusicCue.IsPlaying; + } + } + + public static bool IsMusicLooping + { + get { return m_loopMusic; } + } + + public static bool IsMusicPaused + { + get + { + if (m_currentMusicCue == null) + return false; + return m_currentMusicCue.IsPaused; + } + } + + public static Cue GetCue(string cueName) + { + if (m_audioEngine == null) + return null; + return m_sfxSoundBank.GetCue(cueName); + } + + public static Cue GetMusicCue(string cueName) + { + if (m_audioEngine == null) + return null; + return m_musicSoundBank.GetCue(cueName); + } + + public static Cue GetCurrentMusicCue() + { + return m_currentMusicCue; + } + + public static string GetCurrentMusicName() + { + return m_songName; + } + + public static float GlobalMusicVolume + { + get { return m_globalMusicVolume; } + set + { + if (m_audioEngine == null) + return; + m_globalMusicVolume = value; + if (m_globalMusicVolume < 0) m_globalMusicVolume = 0; + if (m_globalMusicVolume > 1) m_globalMusicVolume = 1; + m_audioEngine.GetCategory("Music").SetVolume(m_musicVolume * m_globalMusicVolume); + //m_audioEngine.GetCategory("Legacy").SetVolume(m_musicVolume * m_globalMusicVolume); // Hack + } + } + + public static float GlobalSFXVolume + { + get { return m_globalSFXVolume; } + set + { + if (m_audioEngine == null) + return; + m_globalSFXVolume = value; + if (m_globalSFXVolume < 0) m_globalSFXVolume = 0; + if (m_globalSFXVolume > 1) m_globalSFXVolume = 1; + m_audioEngine.GetCategory("Default").SetVolume(m_globalSFXVolume); + m_audioEngine.GetCategory("Pauseable").SetVolume(m_globalSFXVolume); // Hack + } + } + + public static AudioEngine AudioEngine + { + get { return m_audioEngine; } + } + + } + + public class PositionalSoundObj : IDisposableObj + { + private bool m_isDisposed = false; + public bool IsDisposed { get { return m_isDisposed; } } + + public GameObj Emitter; + public GameObj Listener; + public Cue AttachedCue; + + public void Update(AudioListener listener, AudioEmitter emitter) + { + emitter.Position = new Vector3(0, 0, CDGMath.DistanceBetweenPts(this.Listener.AbsPosition, this.Emitter.AbsPosition)); // Only modify the Z value to turn off stereo mixing. + AttachedCue.Apply3D(listener, emitter); + } + + public void Dispose() + { + if (IsDisposed == false) + { + m_isDisposed = true; + Emitter = null; + Listener = null; + AttachedCue = null; + } + } + } +} diff --git a/DS2DEngine/src/SpriteFontArray.cs b/DS2DEngine/src/SpriteFontArray.cs new file mode 100644 index 0000000..f80e997 --- /dev/null +++ b/DS2DEngine/src/SpriteFontArray.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework.Graphics; + +namespace DS2DEngine +{ + public class SpriteFontArray + { + public static List SpriteFontList = new List(); + } +} diff --git a/DS2DEngine/src/Triggers/Actions/ChangeSpriteTriggerAction.cs b/DS2DEngine/src/Triggers/Actions/ChangeSpriteTriggerAction.cs new file mode 100644 index 0000000..bd7db8b --- /dev/null +++ b/DS2DEngine/src/Triggers/Actions/ChangeSpriteTriggerAction.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public class ChangeSpriteTriggerAction : TriggerAction + { + private IDrawableObj m_objToChange; + private string m_spriteName; + + public ChangeSpriteTriggerAction(IDrawableObj objToChange, string spriteName) + { + m_objToChange = objToChange; + m_spriteName = spriteName; + } + + public override void Execute() + { + if (ParentTriggerSet.IsActive) + { + m_objToChange.ChangeSprite(m_spriteName); + base.Execute(); + } + } + + public override void Stop() + { + throw new NotImplementedException(); + } + + public override TriggerAction Clone() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + } +} diff --git a/DS2DEngine/src/Triggers/Actions/DelayTriggerAction.cs b/DS2DEngine/src/Triggers/Actions/DelayTriggerAction.cs new file mode 100644 index 0000000..626918f --- /dev/null +++ b/DS2DEngine/src/Triggers/Actions/DelayTriggerAction.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Tweener; + +namespace DS2DEngine +{ + public class DelayTriggerAction : TriggerAction + { + private float m_duration; + private BlankObj m_blankObj; + private TweenObject m_tween; + + public DelayTriggerAction(float delayInSeconds) + { + m_duration = delayInSeconds; + m_blankObj = new BlankObj(1, 1); + } + + public override void Execute() + { + if (ParentTriggerSet.IsActive) + { + // Delays can only be run in serial. + SequenceType = Types.Sequence.Serial; + m_tween = Tween.To(m_blankObj, m_duration, Tweener.Ease.Linear.EaseNone, "X", "1"); + + base.Execute(); + } + } + + public override void ExecuteNext() + { + if (NextTrigger != null) + m_tween.EndHandler(NextTrigger, "Execute"); + else + m_tween.EndHandler(ParentTriggerSet, "TriggerComplete"); + } + + public override void Stop() + { + // m_tween.StopTween(false); + } + + public override TriggerAction Clone() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + } +} diff --git a/DS2DEngine/src/Triggers/Actions/MoveObjTriggerAction.cs b/DS2DEngine/src/Triggers/Actions/MoveObjTriggerAction.cs new file mode 100644 index 0000000..0254f37 --- /dev/null +++ b/DS2DEngine/src/Triggers/Actions/MoveObjTriggerAction.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Tweener; + +namespace DS2DEngine +{ + //TODO: Change to TweenTriggerAction + public class MoveObjTriggerAction : TriggerAction + { + private GameObj m_objToMove; + private float m_duration; + private Easing m_easeType; + private Vector2 m_pos; + private TweenObject m_tween; + private bool m_moveTo; + + public MoveObjTriggerAction(GameObj objToMove, bool moveTo, Vector2 newPos, float timeInSeconds, Easing easeType) + { + m_objToMove = objToMove; + m_duration = timeInSeconds; + m_easeType = easeType; + m_pos = newPos; + m_moveTo = moveTo; + } + + public override void Execute() + { + if (ParentTriggerSet.IsActive) + { + if (m_moveTo == true) + m_tween = Tween.To(m_objToMove, m_duration, m_easeType, "X", m_pos.X.ToString(), "Y", m_pos.Y.ToString()); + else + m_tween = Tween.By(m_objToMove, m_duration, m_easeType, "X", m_pos.X.ToString(), "Y", m_pos.Y.ToString()); + + base.Execute(); + } + } + + public override void ExecuteNext() + { + if (NextTrigger != null) + m_tween.EndHandler(NextTrigger, "Execute"); + else + m_tween.EndHandler(ParentTriggerSet, "TriggerComplete"); + } + + public override void Stop() + { + //m_tween.StopTween(false); + } + + public override TriggerAction Clone() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + } +} diff --git a/DS2DEngine/src/Triggers/Actions/RunFunctionTriggerAction.cs b/DS2DEngine/src/Triggers/Actions/RunFunctionTriggerAction.cs new file mode 100644 index 0000000..13d5d9b --- /dev/null +++ b/DS2DEngine/src/Triggers/Actions/RunFunctionTriggerAction.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; + +namespace DS2DEngine +{ + public class RunFunctionTriggerAction : TriggerAction + { + MethodInfo m_methodInfo; + object m_methodObject; + object[] m_args; + + public RunFunctionTriggerAction(object methodObject, string functionName, params object[] args) + { + if (methodObject == null) + throw new Exception("methodObject cannot be null"); + + m_methodInfo = methodObject.GetType().GetMethod(functionName); + + if (m_methodInfo == null) + throw new Exception("Function " + functionName + " not found in class " + methodObject.GetType().ToString()); + + m_methodObject = methodObject; + m_args = args; + } + + // Used for static methods. + public RunFunctionTriggerAction(Type objectType, string functionName, params object[] args) + { + m_methodInfo = objectType.GetMethod(functionName); + m_methodObject = null; + m_args = args; + } + + public override void Execute() + { + if (ParentTriggerSet.IsActive) + { + m_methodInfo.Invoke(m_methodObject, m_args); + base.Execute(); + } + } + + public override void Stop() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public override TriggerAction Clone() + { + throw new NotImplementedException(); + } + + } +} diff --git a/DS2DEngine/src/Triggers/Base Objects/TriggerAction.cs b/DS2DEngine/src/Triggers/Base Objects/TriggerAction.cs new file mode 100644 index 0000000..a34dcf1 --- /dev/null +++ b/DS2DEngine/src/Triggers/Base Objects/TriggerAction.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public abstract class TriggerAction + { + // A linked list of trigger actions. + public TriggerSet ParentTriggerSet = null; + public TriggerAction PreviousTrigger = null; + public TriggerAction NextTrigger = null; + + public string Tag { get; set; } + public Types.Sequence SequenceType = Types.Sequence.Serial; + + public virtual void Execute() + { + ParentTriggerSet.ActiveTriggerAction = this; + + if (SequenceType == Types.Sequence.Parallel && NextTrigger != null) + NextTrigger.Execute(); + else if (SequenceType == Types.Sequence.Serial) + ExecuteNext(); + } + + public virtual void Update() { } + + public virtual void ExecuteNext() + { + if (NextTrigger != null) + NextTrigger.Execute(); + else + ParentTriggerSet.TriggerComplete(); + } + + public abstract void Stop(); + + public abstract void Dispose(); + + public abstract TriggerAction Clone(); + } +} diff --git a/DS2DEngine/src/Triggers/Base Objects/TriggerSet.cs b/DS2DEngine/src/Triggers/Base Objects/TriggerSet.cs new file mode 100644 index 0000000..68b91e6 --- /dev/null +++ b/DS2DEngine/src/Triggers/Base Objects/TriggerSet.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public class TriggerSet + { + //TriggerActions are compiled in a linked list. + private TriggerAction m_firstActionNode; + private TriggerAction m_currentActionNode; + private TriggerAction m_lastActionNode; + private int m_numActionNodes; + + //private List m_triggerList; // The GameObj list that is used to check when to activate the trigger. + private ITriggerableObj[] m_triggerList; + private bool m_isActive; + private bool m_triggerComplete; + + public TriggerSet(List triggerList) :this() + { + m_triggerList = new ITriggerableObj[triggerList.Count]; + for (int i = 0; i < triggerList.Count; i++) + { + m_triggerList[i] = triggerList[i]; + } + } + + public TriggerSet(params ITriggerableObj[] triggerList) + : this() + { + m_triggerList = triggerList; + } + + public TriggerSet(ITriggerableObj triggerObj) + : this() + { + m_triggerList = new ITriggerableObj[1] { triggerObj }; + } + + private TriggerSet() + { + m_numActionNodes = 0; + m_firstActionNode = null; + } + + public void AddTriggerAction(TriggerAction triggerAction, Types.Sequence sequenceType = Types.Sequence.Serial) + { + triggerAction.ParentTriggerSet = this; + triggerAction.SequenceType = sequenceType; + + // If this is the first trigger added. + if (m_firstActionNode == null) + { + m_firstActionNode = triggerAction; + m_firstActionNode.PreviousTrigger = null; + m_currentActionNode = triggerAction; + } + else + { + // Sets the current action node to the next trigger. + m_currentActionNode.NextTrigger = triggerAction; + // Sets the next triggers previous action node to the current node. + triggerAction.PreviousTrigger = m_currentActionNode; + // Sets the current node to the next trigger. + m_currentActionNode = triggerAction; + } + //Sets the last node to be the current node. + m_lastActionNode = m_currentActionNode; + m_numActionNodes++; + } + + public void CheckForActivation() + { + if (IsActive == false && m_triggerComplete == false) + { + foreach (ITriggerableObj obj in m_triggerList) + { + if (obj.IsTriggered == false) + return; + } + Execute(); + } + } + + public void Execute() + { + if (m_triggerComplete == false) + { + if (IsActive == false) + { + if (m_firstActionNode != null) + { + m_isActive = true; + m_currentActionNode = m_firstActionNode; + m_firstActionNode.Execute(); + } + } + else + Console.WriteLine("Cannot activate already running trigger"); + } + else + Console.WriteLine("Cannot activate a completed trigger."); + } + + public void Stop() + { + } + + public void TriggerComplete() + { + Console.WriteLine("Trigger Complete"); + m_isActive = false; + m_triggerComplete = true; + } + + public void Update() + { + if (ActiveTriggerAction != null) + ActiveTriggerAction.Update(); + } + + public void ResetTrigger() + { + foreach (ITriggerableObj obj in m_triggerList) + obj.IsTriggered = false; + + m_isActive = false; + m_triggerComplete = false; + } + + public void DisposeAllTriggers() + { + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public bool IsActive + { + get { return m_isActive; } + } + + public int NumNodes + { + get { return m_numActionNodes; } + } + + public TriggerAction ActiveTriggerAction + { + get + { + if (m_isActive == false) + return null; + else + return m_currentActionNode; + } + set { m_currentActionNode = value; } + } + + public bool AlreadyTriggered + { + get { return m_triggerComplete; } + } + } +} diff --git a/DS2DEngine/src/Triggers/Base Objects/TriggerSystem.cs b/DS2DEngine/src/Triggers/Base Objects/TriggerSystem.cs new file mode 100644 index 0000000..9abe69f --- /dev/null +++ b/DS2DEngine/src/Triggers/Base Objects/TriggerSystem.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public class TriggerSystem + { + private List m_triggerList; + + public TriggerSystem() + { + m_triggerList = new List(); + } + + public void AddTriggerObject(params TriggerSet[] objs) + { + foreach (TriggerSet trigger in objs) + m_triggerList.Add(trigger); + } + + public void RemoveTriggerObject(params TriggerSet[] objs) + { + foreach (TriggerSet trigger in objs) + { + if (m_triggerList.Contains(trigger)) + m_triggerList.Remove(trigger); + } + } + + public void Update() + { + foreach (TriggerSet trigger in m_triggerList) + { + if (trigger.IsActive == false) + trigger.CheckForActivation(); + + if (trigger.IsActive == true) + trigger.Update(); + } + } + } +} diff --git a/DS2DEngine/src/TxtToBinConverter.cs b/DS2DEngine/src/TxtToBinConverter.cs new file mode 100644 index 0000000..5f05bb5 --- /dev/null +++ b/DS2DEngine/src/TxtToBinConverter.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; + +namespace DS2DEngine +{ + public class TxtToBinConverter + { + public static void Convert(string inputPath) + { + string path = inputPath.Substring(0, inputPath.LastIndexOf(Path.DirectorySeparatorChar)); + string fileName = inputPath.Substring(inputPath.LastIndexOf(Path.DirectorySeparatorChar) + 1); + fileName = fileName.Replace(".txt", ".bin"); + + string outputPath = path + Path.DirectorySeparatorChar + fileName; + Console.WriteLine(outputPath); + + using (FileStream fileStream = new FileStream(outputPath, FileMode.Create)) + { + using (BinaryWriter writer = new BinaryWriter(fileStream)) + { + using (StreamReader sr = new StreamReader(inputPath)) + { + while (!sr.EndOfStream) + writer.Write(sr.ReadLine()); + } + } + } + } + } +} diff --git a/DS2DEngine/src/Types.cs b/DS2DEngine/src/Types.cs new file mode 100644 index 0000000..e4aac90 --- /dev/null +++ b/DS2DEngine/src/Types.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DS2DEngine +{ + public class Types + { + public enum Sequence + { + Parallel, + Serial, + } + + public enum TextAlign + { + None, + Left, + Centre, + Right, + } + } +} diff --git a/DS2DEngine/src/XMLCompiler.cs b/DS2DEngine/src/XMLCompiler.cs new file mode 100644 index 0000000..e652609 --- /dev/null +++ b/DS2DEngine/src/XMLCompiler.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using System.Xml; +using Microsoft.Xna.Framework.Graphics; + +namespace DS2DEngine +{ + public class XMLCompiler + { +#if !XBOX + public static void CompileTriggers(List triggerActionList, string filePath) + { + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Indent = true; + settings.ConformanceLevel = ConformanceLevel.Fragment; + XmlWriter writer = XmlWriter.Create(filePath + System.IO.Path.DirectorySeparatorChar + "testoutput.xml", settings); + + + string xmlStringtest = ""; + writer.WriteStartElement("xml"); + + foreach (TriggerAction trigger in triggerActionList) + { + Type type = trigger.GetType(); + ConstructorInfo[] ctors = type.GetConstructors(); + xmlStringtest += "\n"; + writer.WriteStartElement("TriggerAction"); + + foreach (ConstructorInfo ctor in ctors) + { + ParameterInfo[] parameterList = ctor.GetParameters(); + + writer.WriteStartElement("Constructor"); + writer.WriteAttributeString("name", type.ToString().Substring(type.ToString().LastIndexOf(".") + 1)); + xmlStringtest += "\n"; + + foreach (ParameterInfo parameter in parameterList) + { + writer.WriteStartElement("Parameter"); + writer.WriteAttributeString("type", parameter.ParameterType.ToString().Substring(parameter.ParameterType.ToString().LastIndexOf(".") + 1)); + writer.WriteAttributeString("name", parameter.Name); + xmlStringtest += "\n"; + writer.WriteEndElement(); + } + + xmlStringtest += "\n"; + writer.WriteEndElement(); + } + + writer.WriteEndElement(); + xmlStringtest += "\n"; + } + writer.WriteEndElement(); + // Console.WriteLine(xmlStringtest); + writer.Flush(); + writer.Close(); + + } + + public static List ParseTriggerFile(string filePath) + { + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true; + settings.IgnoreWhitespace = true; + + XmlReader reader = XmlReader.Create(filePath, settings); + + List stringListToReturn = new List(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + if (reader.Name == "Constructor") + { + reader.MoveToAttribute("name"); + stringListToReturn.Add("Constructor:" + reader.Value); + } + else if (reader.Name == "Parameter") + { + reader.MoveToAttribute("type"); + stringListToReturn.Add("Parameter:" + reader.Value); + } + } + } + + return stringListToReturn; + } +#endif + } +} diff --git a/EXCEPTIONS.md b/EXCEPTIONS.md new file mode 100644 index 0000000..766b974 --- /dev/null +++ b/EXCEPTIONS.md @@ -0,0 +1,10 @@ +Rogue Legacy 1's source code is made available under a [custom license](LICENSE.md), which states that you must not distribute any materials from the game (i.e. the game's assets) which are not included in this repo unless approved by us in writing. In general, if you're interested in creating something that falls outside the license terms, [get in touch](https://cellardoorgames.com/contact/)! + +The following is a list of projects which have been given permission by Cellar Door Games to distribute the assets with distributions of the game, and under what conditions. + +Exceptions granted to the Rogue Legacy Source Code License v1.0 +--------------------------------------------------------------- +Last updated on October 8, 2024. + +| Project | Creator | Description | Conditions | Link | +|---|---|---|---|---| diff --git a/InputSystem/InputManager.cs b/InputSystem/InputManager.cs new file mode 100644 index 0000000..7ede974 --- /dev/null +++ b/InputSystem/InputManager.cs @@ -0,0 +1,616 @@ +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Input.Touch; + +namespace InputSystem +{ + public enum PadTypes + { + Keyboard = 0, + GamePad, + } + + public enum ThumbStick + { + LeftStick = 0, + RightStick, + } + + // This file used to have Nuclex stuff everywhere. It's gone now. -flibit + + public class InputManager + { + // Only currently supports one non-Xbox 360 controller. + private const int MaxInputs = 4; + + private static KeyboardState[] CurrentKeyboardStates; + private static GamePadState[] CurrentGamePadStates; + private static KeyboardState[] PreviousKeyboardStates; // Previous states are used to determine if a button was just pressed or held. + private static GamePadState[] PreviousGamePadStates; + + private static MouseState CurrentMouseState; + private static MouseState PreviousMouseState; + + public static List Taps = new List(); + public static List Drags = new List(); + public static List Pinches = new List(); + public static float PinchDelta; + + private static bool[] WasConnected; + private static PadTypes[] PadType; + + public static float Deadzone = 0; + + public InputManager() + { + } + + public static void Initialize() + { + CurrentKeyboardStates = new KeyboardState[MaxInputs]; + CurrentGamePadStates = new GamePadState[MaxInputs]; + + PreviousKeyboardStates = new KeyboardState[MaxInputs]; + PreviousGamePadStates = new GamePadState[MaxInputs]; + + WasConnected = new bool[MaxInputs]; + PadType = new PadTypes[MaxInputs]; + + TouchPanel.EnabledGestures = GestureType.Tap | GestureType.FreeDrag; + } + + public static void InitializeDXManager(GameServiceContainer service, GameWindow window) + { + // No-op for FNA + } + + public static void RemapDXPad(Buttons[] buttonList) + { + // No-op for FNA + } + + public static bool GamePadIsConnected(PlayerIndex playerIndex) + { + return GamePad.GetState(playerIndex).IsConnected; + } + + public static bool XInputPadIsConnected(PlayerIndex playerIndex) + { + return GamePad.GetState(playerIndex).IsConnected; + } + + public static bool DXPadConnected() + { + return false; + } + + public static PadTypes GetPadType(PlayerIndex playerIndex) + { + return PadType[(int)playerIndex]; + } + + public static void SetPadType(PlayerIndex playerIndex, PadTypes padType) + { + PadType[(int)playerIndex] = padType; + } + + public static Vector2 GetThumbStickDirection(ThumbStick stick, PlayerIndex playerIndex) + { + if (stick == ThumbStick.LeftStick) + return CurrentGamePadStates[(int)playerIndex].ThumbSticks.Left; + else + return CurrentGamePadStates[(int)playerIndex].ThumbSticks.Right; + } + + public static void Update(GameTime gameTime) + { + // Xinput and keyboard updeate code. + for (int i = 0; i < MaxInputs; i++) + { + PreviousKeyboardStates[i] = CurrentKeyboardStates[i]; + PreviousGamePadStates[i] = CurrentGamePadStates[i]; + + CurrentKeyboardStates[i] = Keyboard.GetState((PlayerIndex)i); + CurrentGamePadStates[i] = GamePad.GetState((PlayerIndex)i, GamePadDeadZone.Circular); + // Keep track of whether a gamepad has ever been + // connected, so we can detect if it is unplugged. + //if (XInputPadIsConnected((PlayerIndex)i)) + //{ + // WasConnected[i] = true; + //} + } + + // Mouse input code. + PreviousMouseState = CurrentMouseState; + CurrentMouseState = Mouse.GetState(); + + // Touch input code. + Taps.Clear(); + Drags.Clear(); + Pinches.Clear(); + + while (TouchPanel.IsGestureAvailable) + { + GestureSample gesture = TouchPanel.ReadGesture(); + switch (gesture.GestureType) + { + case GestureType.Tap: + Taps.Add(gesture); + break; + case GestureType.FreeDrag: + Drags.Add(gesture); + break; + case GestureType.Pinch: + Pinches.Add(gesture); + + Vector2 a = gesture.Position; + Vector2 aOld = gesture.Position - gesture.Delta; + Vector2 b = gesture.Position2; + Vector2 bOld = gesture.Position2 - gesture.Delta2; + + float d = Vector2.Distance(a, b); + float dOld = Vector2.Distance(aOld, bOld); + + PinchDelta = d - dOld; + break; + } + } + } + + public static bool AnyKeyPressed() + { + return Keyboard.GetState().GetPressedKeys().Length > 0; + } + + public static bool AnyMousePressed() + { + return MouseLeftJustPressed() || MouseRightJustPressed() || MouseMiddleJustPressed(); + } + + public static bool AnyButtonPressed(PlayerIndex playerIndex) + { + foreach (Buttons button in Enum.GetValues(typeof(Buttons))) + { + if (CurrentGamePadStates[(int)playerIndex].IsButtonDown(button) == true) + return true; + } + return false; + } + + public static bool MouseLeftPressed() + { + return CurrentMouseState.LeftButton == ButtonState.Pressed; + } + + public static bool MouseLeftJustPressed() + { + return CurrentMouseState.LeftButton == ButtonState.Pressed && PreviousMouseState.LeftButton == ButtonState.Released; + } + + public static bool MouseLeftJustReleased() + { + return CurrentMouseState.LeftButton == ButtonState.Released && PreviousMouseState.LeftButton == ButtonState.Pressed; + } + + public static bool MouseRightPressed() + { + return CurrentMouseState.RightButton == ButtonState.Pressed; + } + + public static bool MouseRightJustPressed() + { + return CurrentMouseState.RightButton == ButtonState.Pressed && PreviousMouseState.RightButton == ButtonState.Released; + } + + public static bool MouseRightJustReleased() + { + return CurrentMouseState.RightButton == ButtonState.Released && PreviousMouseState.RightButton == ButtonState.Pressed; + } + + public static bool MouseMiddlePressed() + { + return CurrentMouseState.MiddleButton == ButtonState.Pressed; + } + + public static bool MouseMiddleJustPressed() + { + return CurrentMouseState.MiddleButton == ButtonState.Pressed && PreviousMouseState.MiddleButton == ButtonState.Released; + } + + public static bool MouseMiddleJustReleased() + { + return CurrentMouseState.MiddleButton == ButtonState.Released && PreviousMouseState.MiddleButton == ButtonState.Pressed; + } + + public static int MouseX + { + get { return CurrentMouseState.X; } + } + + public static int MouseY + { + get { return CurrentMouseState.Y; } + } + + public static int MouseMiddleScroll + { + get { return CurrentMouseState.ScrollWheelValue; } + } + + /// + /// Returns whether the keyboard key is being held down or not. + /// + public static bool Pressed(Keys key, PlayerIndex playerIndex) + { + return CurrentKeyboardStates[(int)playerIndex].IsKeyDown(key); + } + + public static bool Pressed(Buttons button, PlayerIndex playerIndex) + { + // All this extra code is to support deadzones. + bool isButtonDown = CurrentGamePadStates[(int)playerIndex].IsButtonDown(button); + bool isThumbstick = false; + Vector2 thumbstickAmount = GetThumbstickState(button, playerIndex, out isThumbstick); + if (isThumbstick == false) + return isButtonDown; + else + { + if (ThumbstickMovementIsSignificant(thumbstickAmount, Deadzone) && isButtonDown == true) + return true; + } + return false; + } + + public static bool PreviousStatePressed(Buttons button, PlayerIndex playerIndex) + { + // All this extra code is to support deadzones. + bool isButtonDown = PreviousGamePadStates[(int)playerIndex].IsButtonDown(button); + bool isThumbstick = false; + Vector2 thumbstickAmount = GetPreviousThumbstickState(button, playerIndex, out isThumbstick); + if (isThumbstick == false) + return isButtonDown; + else + { + if (ThumbstickMovementIsSignificant(thumbstickAmount, Deadzone) && isButtonDown == true) + return true; + } + return false; + } + + /// + /// Helper for checking if a key was newly pressed during this update. The + /// controllingPlayer parameter specifies which player to read input for. + /// If this is null, it will accept input from any player. When a keypress + /// is detected, the output playerIndex reports which player pressed it. + /// + public static bool JustPressed(Keys key, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex) + { + if (controllingPlayer.HasValue) + { + // Read input from the specified player. + playerIndex = controllingPlayer.Value; + + int i = (int)playerIndex; + + return (CurrentKeyboardStates[i].IsKeyDown(key) && + PreviousKeyboardStates[i].IsKeyUp(key)); + } + else + { + // Accept input from any player. + return (JustPressed(key, PlayerIndex.One, out playerIndex) || + JustPressed(key, PlayerIndex.Two, out playerIndex) || + JustPressed(key, PlayerIndex.Three, out playerIndex) || + JustPressed(key, PlayerIndex.Four, out playerIndex)); + } + } + + /// + /// Same as above, but used in case you don't care which player pressed the button. + /// + public static bool JustPressed(Keys key, PlayerIndex? controllingPlayer) + { + if (controllingPlayer.HasValue) + { + int i = (int)controllingPlayer.Value; + return (CurrentKeyboardStates[i].IsKeyDown(key) && + PreviousKeyboardStates[i].IsKeyUp(key)); + } + else + { + // Accept input from any player. + return (JustPressed(key, PlayerIndex.One) || + JustPressed(key, PlayerIndex.Two) || + JustPressed(key, PlayerIndex.Three) || + JustPressed(key, PlayerIndex.Four)); + } + } + + /// + /// Helper for checking if a button was newly pressed during this update. + /// The controllingPlayer parameter specifies which player to read input for. + /// If this is null, it will accept input from any player. When a button press + /// is detected, the output playerIndex reports which player pressed it. + /// + public static bool JustPressed(Buttons button, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex) + { + if (controllingPlayer.HasValue) + { + playerIndex = controllingPlayer.Value; + + int i = (int)playerIndex; + + //if (GamePadIsConnected(controllingPlayer.Value) == true) + //{ + //return (CurrentGamePadStates[i].IsButtonDown(button) && + // PreviousGamePadStates[i].IsButtonUp(button)); + + + //if (XInputPadIsConnected(controllingPlayer.Value) == true) + //{ + // This one supports deadzones. + return (Pressed(button, controllingPlayer.Value) == true && + PreviousStatePressed(button, controllingPlayer.Value) == false); + //} + //else + //{ + // return (CurrentDXState.IsButtonDown(button) && + // PreviousDXState.IsButtonUp(button)); + //} + } + else + { + // Accept input from any player. + return (JustPressed(button, PlayerIndex.One, out playerIndex) || + JustPressed(button, PlayerIndex.Two, out playerIndex) || + JustPressed(button, PlayerIndex.Three, out playerIndex) || + JustPressed(button, PlayerIndex.Four, out playerIndex)); + } + } + + /// + /// Same as above, but used in case you don't care which player pressed the button. + /// + public static bool JustPressed(Buttons button, PlayerIndex? controllingPlayer) + { + if (controllingPlayer.HasValue) + { + int i = (int)controllingPlayer.Value; + + //if (XInputPadIsConnected(controllingPlayer.Value) == true) + //{ + //return (CurrentGamePadStates[i].IsButtonDown(button) && + // PreviousGamePadStates[i].IsButtonUp(button)); + + // This one supports deadzones. + return (Pressed(button, controllingPlayer.Value) == true && + PreviousStatePressed(button, controllingPlayer.Value) == false); + + //} + //else + //{ + // return (CurrentDXState.IsButtonDown(button) && + // PreviousDXState.IsButtonUp(button)); + //} + } + else + { + // Accept input from any player. + return (JustPressed(button, PlayerIndex.One) || + JustPressed(button, PlayerIndex.Two) || + JustPressed(button, PlayerIndex.Three) || + JustPressed(button, PlayerIndex.Four)); + } + } + + public static bool JustPressed(JoystickInput input, PlayerIndex? controllingPlayer) + { + if (controllingPlayer.HasValue) + { + int i = (int)controllingPlayer.Value; + + Vector2 currentThumbDirection = Vector2.Zero; + Vector2 previousThumbDirection = Vector2.Zero; + + if (input.ThumbStick == ThumbStick.LeftStick) + { + currentThumbDirection = CurrentGamePadStates[i].ThumbSticks.Left; + previousThumbDirection = PreviousGamePadStates[i].ThumbSticks.Left; + } + else + { + currentThumbDirection = CurrentGamePadStates[i].ThumbSticks.Right; + previousThumbDirection = PreviousGamePadStates[i].ThumbSticks.Right; + } + + float currentAngle = -MathHelper.ToDegrees((float)Math.Atan2(currentThumbDirection.Y, currentThumbDirection.X)); + float previousAngle = -MathHelper.ToDegrees((float)Math.Atan2(previousThumbDirection.Y, previousThumbDirection.X)); + bool isSignificant = ThumbstickMovementIsSignificant(currentThumbDirection, Deadzone); + bool previousIsSignificant = ThumbstickMovementIsSignificant(previousThumbDirection, Deadzone); + + if ((currentAngle > input.Direction - input.Hysteresis && currentAngle < input.Direction + input.Hysteresis) == true && isSignificant == true && + ((previousAngle > input.Direction - input.Hysteresis && previousAngle < input.Direction + input.Hysteresis) == false || previousIsSignificant == false)) + return true; + else + return false; + } + else + return (JustPressed(input, PlayerIndex.One) || + JustPressed(input, PlayerIndex.Two) || + JustPressed(input, PlayerIndex.Three) || + JustPressed(input, PlayerIndex.Four)); + } + + public static bool Pressed(JoystickInput input, PlayerIndex playerIndex) + { + Vector2 currentThumbDirection = Vector2.Zero; + + if (input.ThumbStick == ThumbStick.LeftStick) + currentThumbDirection = CurrentGamePadStates[(int)playerIndex].ThumbSticks.Left; + else + currentThumbDirection = CurrentGamePadStates[(int)playerIndex].ThumbSticks.Right; + + float currentAngle = -MathHelper.ToDegrees((float)Math.Atan2(currentThumbDirection.Y, currentThumbDirection.X)); + + bool isSignificant = ThumbstickMovementIsSignificant(currentThumbDirection, Deadzone); + + return (currentAngle > input.Direction - input.Hysteresis && currentAngle < input.Direction + input.Hysteresis) == true && isSignificant == true; + } + + public static bool JustTapped() + { + return Taps.Count > 0; + } + + /// + /// Resets the control input for a specific player. + /// + /// The PlayerIndex to reset. If null, all player indices are reset. + public static void Reset(PlayerIndex? playerIndex) + { + if (playerIndex.HasValue) + { + CurrentGamePadStates[(int)playerIndex] = new GamePadState(); + CurrentKeyboardStates[(int)playerIndex] = new KeyboardState(); + PreviousGamePadStates[(int)playerIndex] = new GamePadState(); + PreviousKeyboardStates[(int)playerIndex] = new KeyboardState(); + WasConnected[(int)playerIndex] = false; + PadType[(int)playerIndex] = new PadTypes(); + } + else + { + CurrentKeyboardStates = new KeyboardState[MaxInputs]; + CurrentGamePadStates = new GamePadState[MaxInputs]; + PreviousKeyboardStates = new KeyboardState[MaxInputs]; + PreviousGamePadStates = new GamePadState[MaxInputs]; + WasConnected = new bool[MaxInputs]; + PadType = new PadTypes[MaxInputs]; + } + + CurrentMouseState = new MouseState(); + PreviousMouseState = new MouseState(); + } + + public static Keys[] KeysPressedArray + { + get { return Keyboard.GetState().GetPressedKeys(); } + } + + public static Buttons[] ButtonsPressedArray(PlayerIndex playerIndex) + { + List buttonArray = new List(); + + foreach (Buttons button in Enum.GetValues(typeof(Buttons))) + { + if (CurrentGamePadStates[(int)playerIndex].IsButtonDown(button) == true) + buttonArray.Add(button); + } + return buttonArray.ToArray(); + } + + /// + /// Determines if the thumbstickState passed in is significant enough, given the constraint + /// of how much movement should be ignored. + /// + /// + /// Percentage of the unit-circle which is ignored. If 25.0f, then the inner-quarter of movements will be considered too slight. If 50.0f, then the inner half will be ignored, etc.. + public static bool ThumbstickMovementIsSignificant(Vector2 thumbstickState, float percentToIgnore) + { + bool isSignificant = true; + if (percentToIgnore > 0) + { + // Uses pythagorean theorem to see if the hypotenuse ends inside of the "significant" area or not. + float a = thumbstickState.X; + float b = thumbstickState.Y; + + // Thumbstick numbers are in a unit-circle so scale the percentToIgnore to the range of 0.0 to 1.0 + float minHyphotenuseLengthForSignificance = (percentToIgnore / 100); + + // This function is likely to be called every tick, so we square the minimum hyptotenuse instead of comparing it the sqrt of a^2 + b^2 (square roots are a bit slow). + if (((a * a) + (b * b)) < (minHyphotenuseLengthForSignificance * minHyphotenuseLengthForSignificance)) + isSignificant = false; + } + return isSignificant; + } + + public static Vector2 GetThumbstickState(Buttons button, PlayerIndex playerIndex, out bool isThumbstick) + { + switch (button) + { + case (Buttons.LeftThumbstickUp): + case (Buttons.LeftThumbstickDown): + case (Buttons.LeftThumbstickLeft): + case (Buttons.LeftThumbstickRight): + isThumbstick = true; + return CurrentGamePadStates[(int)playerIndex].ThumbSticks.Left; + case (Buttons.RightThumbstickUp): + case (Buttons.RightThumbstickDown): + case (Buttons.RightThumbstickRight): + case (Buttons.RightThumbstickLeft): + isThumbstick = true; + return CurrentGamePadStates[(int)playerIndex].ThumbSticks.Right; + } + + isThumbstick = false; + return Vector2.Zero; + } + + public static Vector2 GetPreviousThumbstickState(Buttons button, PlayerIndex playerIndex, out bool isThumbstick) + { + switch (button) + { + case (Buttons.LeftThumbstickUp): + case (Buttons.LeftThumbstickDown): + case (Buttons.LeftThumbstickLeft): + case (Buttons.LeftThumbstickRight): + isThumbstick = true; + return PreviousGamePadStates[(int)playerIndex].ThumbSticks.Left; + case (Buttons.RightThumbstickUp): + case (Buttons.RightThumbstickDown): + case (Buttons.RightThumbstickRight): + case (Buttons.RightThumbstickLeft): + isThumbstick = true; + return PreviousGamePadStates[(int)playerIndex].ThumbSticks.Right; + } + + isThumbstick = false; + return Vector2.Zero; + } + + private static bool ButtonIsThumbstick(Buttons button) + { + switch (button) + { + case (Buttons.LeftThumbstickUp): + case (Buttons.LeftThumbstickDown): + case (Buttons.LeftThumbstickLeft): + case (Buttons.LeftThumbstickRight): + case (Buttons.RightThumbstickUp): + case (Buttons.RightThumbstickDown): + case (Buttons.RightThumbstickRight): + case (Buttons.RightThumbstickLeft): + return true; + } + + return false; + } + } + + public struct JoystickInput + { + public float Direction; + public float Hysteresis; + public int ID; + public ThumbStick ThumbStick; + + public JoystickInput(ThumbStick thumbstick, float direction, float hysteresis, int id) + { + ThumbStick = thumbstick; + Direction = direction; + Hysteresis = hysteresis; + ID = id; + } + } +} diff --git a/InputSystem/InputMap.cs b/InputSystem/InputMap.cs new file mode 100644 index 0000000..6850174 --- /dev/null +++ b/InputSystem/InputMap.cs @@ -0,0 +1,227 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; + +namespace InputSystem +{ + public class InputMap + { + private PlayerIndex m_playerIndex; + private List m_keyList; + private List m_buttonList; + private List m_joystickList; + private bool m_usingGamePad = false; + + private bool m_isDisposed = false; + + public bool LockKeyboardInput { get; set; } + + public InputMap(PlayerIndex playerIndex, bool useGamePad) + { + m_playerIndex = playerIndex; + m_keyList = new List(); + m_buttonList = new List(); + m_joystickList = new List(); + + m_usingGamePad = useGamePad; + if ((InputManager.XInputPadIsConnected(playerIndex) || InputManager.DXPadConnected()) && m_usingGamePad == true) + InputManager.SetPadType(playerIndex, PadTypes.GamePad); + else + InputManager.SetPadType(playerIndex, PadTypes.Keyboard); + } + + public void SwitchInputType(PadTypes padType) + { + if (padType == PadTypes.GamePad && (InputManager.XInputPadIsConnected(m_playerIndex) || InputManager.DXPadConnected())) + InputManager.SetPadType(m_playerIndex, PadTypes.GamePad); + else + InputManager.SetPadType(m_playerIndex, PadTypes.Keyboard); + } + + public void AddInput(int id, Keys key) + { + int iterate = id + 1 - m_keyList.Count; + for (int i = 0; i < iterate; i++) + { + m_keyList.Add(new Keys()); + } + m_keyList[id] = key; + } + + public void AddInput(int id, Buttons button) + { + // when ID is 1 count needs to be 2. otherwise run else. + int iterate = id + 1 - m_buttonList.Count; + for (int i = 0; i < iterate; i++) + { + m_buttonList.Add(new Buttons()); + } + m_buttonList[id] = button; + } + + public void AddInput(int id, ThumbStick thumbstick, float direction, float hysteresis) + { + if (id > m_buttonList.Count) + { + for (int i = m_buttonList.Count; i < id - m_buttonList.Count; i++) + { + m_buttonList.Add(new Buttons()); + } + } + + JoystickInput input = new JoystickInput(thumbstick, direction, hysteresis, id); + m_joystickList.Add(input); + } + + public bool JustPressed(int id) + { + //if (InputManager.GetPadType(m_playerIndex) == PadTypes.GamePad) + if (id < m_buttonList.Count) + { + //if (id >= m_buttonList.Count) return false; + + if (m_buttonList[id] == 0) + { + foreach (JoystickInput input in m_joystickList) + { + if (input.ID == id) + { + bool pressed = InputManager.JustPressed(input, m_playerIndex); + if (pressed == true) // This is necessary because if it is false, it needs to break out and check the keyboard. + return true; + } + } + //return false; + } + else if (InputManager.JustPressed(m_buttonList[id], m_playerIndex) == true) + return true; + //return InputManager.JustPressed(m_buttonList[id], m_playerIndex); + } + + if (LockKeyboardInput == false) + { + if (id >= m_keyList.Count) return false; + + switch (m_keyList[id]) + { + case (Keys.F13): + return InputManager.MouseLeftJustPressed(); + case (Keys.F14): + return InputManager.MouseRightJustPressed(); + case (Keys.F15): + return InputManager.MouseMiddleJustPressed(); + default: + return InputManager.JustPressed(m_keyList[id], m_playerIndex); + } + } + + return false; + } + + public bool Pressed(int id) + { + //if (InputManager.GetPadType(m_playerIndex) == PadTypes.GamePad) + if (id < m_buttonList.Count) + { + //if (id >= m_buttonList.Count) return false; + + if (m_buttonList[id] == 0) + { + foreach (JoystickInput input in m_joystickList) + { + if (input.ID == id) + { + bool pressed = InputManager.Pressed(input, m_playerIndex); + if (pressed == true) // This is necessary because if it is false, it needs to break out and check the keyboard. + return true; + } + } + //return false; + } + else if (InputManager.Pressed(m_buttonList[id], m_playerIndex)) + return true; + } + + if (LockKeyboardInput == false) + { + if (id >= m_keyList.Count) return false; + + switch (m_keyList[id]) + { + case (Keys.F13): + return InputManager.MouseLeftPressed(); + case (Keys.F14): + return InputManager.MouseRightPressed(); + case (Keys.F15): + return InputManager.MouseMiddlePressed(); + default: + return InputManager.Pressed(m_keyList[id], m_playerIndex); + } + } + return false; + } + + public void ClearKeyboardList() + { + m_keyList.Clear(); + } + + public void ClearGamepadList() + { + m_buttonList.Clear(); + m_joystickList.Clear(); + } + + public void ClearAll() + { + m_joystickList.Clear(); + m_keyList.Clear(); + m_buttonList.Clear(); + } + + public void Dispose() + { + if (m_isDisposed == false) + { + m_isDisposed = true; + + m_joystickList.Clear(); + m_joystickList = null; + m_keyList.Clear(); + m_keyList = null; + m_buttonList.Clear(); + m_buttonList = null; + } + } + + public PlayerIndex PlayerIndex + { + get { return m_playerIndex; } + } + + public bool UsingGamePad + { + get { return m_usingGamePad; } + } + + public List ButtonList + { + get { return m_buttonList; } + } + + public List KeyList + { + get { return m_keyList; } + } + + public bool IsDisposed + { + get { return m_isDisposed; } + } + + } + +} diff --git a/InputSystem/InputReader.cs b/InputSystem/InputReader.cs new file mode 100644 index 0000000..104abb1 --- /dev/null +++ b/InputSystem/InputReader.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework.Input; + +namespace InputSystem +{ + public class InputReader + { + public static string GetInputString(Keys? key, bool shift, bool capsLock, bool numLock) + { + if (key.HasValue == false) + return "Any Key"; + + switch (key) + { + case Keys.A: return TranslateAlphabetic('a', shift, capsLock); + case Keys.B: return TranslateAlphabetic('b', shift, capsLock); + case Keys.C: return TranslateAlphabetic('c', shift, capsLock); + case Keys.D: return TranslateAlphabetic('d', shift, capsLock); + case Keys.E: return TranslateAlphabetic('e', shift, capsLock); + case Keys.F: return TranslateAlphabetic('f', shift, capsLock); + case Keys.G: return TranslateAlphabetic('g', shift, capsLock); + case Keys.H: return TranslateAlphabetic('h', shift, capsLock); + case Keys.I: return TranslateAlphabetic('i', shift, capsLock); + case Keys.J: return TranslateAlphabetic('j', shift, capsLock); + case Keys.K: return TranslateAlphabetic('k', shift, capsLock); + case Keys.L: return TranslateAlphabetic('l', shift, capsLock); + case Keys.M: return TranslateAlphabetic('m', shift, capsLock); + case Keys.N: return TranslateAlphabetic('n', shift, capsLock); + case Keys.O: return TranslateAlphabetic('o', shift, capsLock); + case Keys.P: return TranslateAlphabetic('p', shift, capsLock); + case Keys.Q: return TranslateAlphabetic('q', shift, capsLock); + case Keys.R: return TranslateAlphabetic('r', shift, capsLock); + case Keys.S: return TranslateAlphabetic('s', shift, capsLock); + case Keys.T: return TranslateAlphabetic('t', shift, capsLock); + case Keys.U: return TranslateAlphabetic('u', shift, capsLock); + case Keys.V: return TranslateAlphabetic('v', shift, capsLock); + case Keys.W: return TranslateAlphabetic('w', shift, capsLock); + case Keys.X: return TranslateAlphabetic('x', shift, capsLock); + case Keys.Y: return TranslateAlphabetic('y', shift, capsLock); + case Keys.Z: return TranslateAlphabetic('z', shift, capsLock); + + case Keys.D0: return (shift) ? ")" : "0"; + case Keys.D1: return (shift) ? "!" : "1"; + case Keys.D2: return (shift) ? "@" : "2"; + case Keys.D3: return (shift) ? "#" : "3"; + case Keys.D4: return (shift) ? "$" : "4"; + case Keys.D5: return (shift) ? "%" : "5"; + case Keys.D6: return (shift) ? "^" : "6"; + case Keys.D7: return (shift) ? "&" : "7"; + case Keys.D8: return (shift) ? "*" : "8"; + case Keys.D9: return (shift) ? "(" : "9"; + + case Keys.Add: return "+"; + case Keys.Divide: return "/"; + case Keys.Multiply: return "*"; + case Keys.Subtract: return "-"; + + //case Keys.Space: return " "; + case Keys.Space: return "Space"; + case Keys.Tab: return "Tab"; + case Keys.Enter: return "Enter"; + case Keys.Back: return "Back"; + case Keys.LeftControl: return "L-Ctrl"; + case Keys.RightControl: return "R-Ctrl"; + case Keys.LeftAlt: return "L-Alt"; + case Keys.RightAlt: return "R-Alt"; + case Keys.LeftShift: return "LShift"; + case Keys.RightShift: return "RShift"; + + case Keys.Down: return "Down"; + case Keys.Left: return "Left"; + case Keys.Right: return "Right"; + case Keys.Up: return "Up"; + case Keys.Escape: return "Esc"; + + case Keys.Decimal: if (numLock && !shift) return "."; break; + //case Keys.NumPad0: if (numLock && !shift) return "0"; break; + //case Keys.NumPad1: if (numLock && !shift) return "1"; break; + //case Keys.NumPad2: if (numLock && !shift) return "2"; break; + //case Keys.NumPad3: if (numLock && !shift) return "3"; break; + //case Keys.NumPad4: if (numLock && !shift) return "4"; break; + //case Keys.NumPad5: if (numLock && !shift) return "5"; break; + //case Keys.NumPad6: if (numLock && !shift) return "6"; break; + //case Keys.NumPad7: if (numLock && !shift) return "7"; break; + //case Keys.NumPad8: if (numLock && !shift) return "8"; break; + //case Keys.NumPad9: if (numLock && !shift) return "9"; break; + case Keys.NumPad0: return "NUM 0"; + case Keys.NumPad1: return "NUM 1"; + case Keys.NumPad2: return "NUM 2"; + case Keys.NumPad3: return "NUM 3"; + case Keys.NumPad4: return "NUM 4"; + case Keys.NumPad5: return "NUM 5"; + case Keys.NumPad6: return "NUM 6"; + case Keys.NumPad7: return "NUM 7"; + case Keys.NumPad8: return "NUM 8"; + case Keys.NumPad9: return "NUM 9"; + + case Keys.OemBackslash: return shift ? "|" : "\\"; + case Keys.OemCloseBrackets: return shift ? "}" : "]"; + case Keys.OemComma: return shift ? "<" : ","; + case Keys.OemMinus: return shift ? "_" : "-"; + case Keys.OemOpenBrackets: return shift ? "{" : "["; + case Keys.OemPeriod: return shift ? ">" : "."; + case Keys.OemPipe: return shift ? "|" : "\\"; + case Keys.OemPlus: return shift ? "+" : "="; + case Keys.OemQuestion: return shift ? "?" : "/"; + case Keys.OemQuotes: return shift ? "'" : "\""; + case Keys.OemSemicolon: return shift ? ":" : ";"; + case Keys.OemTilde: return shift ? "~" : "`"; + } + + return ""; + } + + public static string TranslateAlphabetic(char baseChar, bool shift, bool capsLock) + { + return ((capsLock ^ shift) ? char.ToUpper(baseChar) : baseChar).ToString(); + } + + } +} diff --git a/InputSystem/InputSystem.csproj b/InputSystem/InputSystem.csproj new file mode 100644 index 0000000..506d4bb --- /dev/null +++ b/InputSystem/InputSystem.csproj @@ -0,0 +1,14 @@ + + + + Library + net40 + + + + + {35253CE1-C864-4CD3-8249-4D1319748E8F} + FNA + + + diff --git a/InputSystem/TouchGamepad.cs b/InputSystem/TouchGamepad.cs new file mode 100644 index 0000000..00e3f93 --- /dev/null +++ b/InputSystem/TouchGamepad.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Input.Touch; + +namespace InputSystem +{ + public class TouchGamepad + { + class TouchButton + { + internal Rectangle Bounds; + internal ButtonState PreviousState; + internal ButtonState State; + internal string Text; + } + + Dictionary buttons = new Dictionary(); + Texture2D pixel; + const float opacity = 0.3f; + + #region Life Cycle + + public void Initialize(GraphicsDevice graphicsDevice) + { + pixel = new Texture2D(graphicsDevice, 1, 1); + pixel.SetData(new Color[] { Color.White }); + } + + public void Update() + { + TouchCollection touches = TouchPanel.GetState(); + + foreach (TouchButton button in buttons.Values) + { + button.PreviousState = button.State; + button.State = ButtonState.Released; + + foreach (TouchLocation touch in touches) + { + if (button.Bounds.Contains((int)touch.Position.X, (int)touch.Position.Y)) + { + button.State = ButtonState.Pressed; + break; + } + } + } + } + + public void Draw(SpriteBatch spriteBatch, SpriteFont font) + { + foreach (TouchButton button in buttons.Values) + { + Color drawColor = Color.White; + if (button.State == ButtonState.Pressed) + drawColor = Color.Red; + + spriteBatch.Draw(pixel, button.Bounds, drawColor * opacity); + + spriteBatch.DrawString( + font, + button.Text, + new Vector2( + button.Bounds.X + (button.Bounds.Width / 2) - 16, + button.Bounds.Y + (button.Bounds.Height / 2) - 16 + ), + Color.Yellow, + 0, + Vector2.Zero, + 4, + SpriteEffects.None, + 0 + ); + } + } + + #endregion + + #region Getters + + public bool IsDown(Buttons action) + { + if (!IsValidButton(action)) + return false; + + return buttons[action].State == ButtonState.Pressed; + } + + public bool IsUp(Buttons action) + { + if (!IsValidButton(action)) + return false; + + return buttons[action].State == ButtonState.Released; + } + + public bool WasDown(Buttons action) + { + if (!IsValidButton(action)) + return false; + + return buttons[action].PreviousState == ButtonState.Pressed; + } + + public bool WasUp(Buttons action) + { + if (!IsValidButton(action)) + return false; + + return buttons[action].PreviousState == ButtonState.Released; + } + + public bool JustPressed(Buttons action) + { + if (!IsValidButton(action)) + return false; + + return buttons[action].State == ButtonState.Pressed && + buttons[action].PreviousState == ButtonState.Released; + } + + public bool JustReleased(Buttons action) + { + if (!IsValidButton(action)) + return false; + + return buttons[action].State == ButtonState.Released && + buttons[action].PreviousState == ButtonState.Pressed; + } + + #endregion + + #region Setters + + public void AddButton(Buttons action, int x, int y, int width, int height, string text = "") + { + buttons.Add(action, new TouchButton + { + Bounds = new Rectangle(x, y, width, height), + Text = text + }); + } + + public void RemoveButton(Buttons action) + { + if (!IsValidButton(action)) + throw new Exception("Attempting to remove button not registered by the touch gamepad!"); + + buttons.Remove(action); + } + + #endregion + + #region Utilities + + bool IsValidButton(Buttons button) + { + return buttons.ContainsKey(button); + } + + #endregion + } +} diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..746129b --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +Rogue Legacy 1's source code is made available under a custom license. Basically, you can compile yourself a copy, for free, for personal use. But if you want to distribute a compiled version of the game, you might need permission first. See the [EXCEPTIONS.md](EXCEPTIONS.md) page for more information. + +Rogue Legacy Source Code License v1.0 +------------------------------------- +Last updated on October 8, 2024. + +This repo contains the source code for Rogue Legacy 1, including all localized text from the game. It does not, however, contain any of the icons, art, graphics or music for the game, which are still under a proprietary license. You will still need to purchase the game to access these files. + +If you are interested in distributing work that falls outside the terms in the license below, or if you are interested in distributing work that includes using any part of Rogue Legacy not included in this repo then please get in touch - we can discuss granting a license for that on a case by case basis. The purpose of making the contents of this repo available is for others to learn from, to inspire new work, and to allow the creation of new tools and modifications for Rogue Legacy 1. + +This software available from here is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any claim, damages or other liability arising from the use or in connection with this software. All materials in the repo are copyright of Cellar Door Games © 2013-2024. + +Permission is granted to anyone to use this software and to alter it and redistribute it freely, subject to the following restrictions: + + - You may not alter or redistribute this software in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. This includes, but is not limited to, selling altered or unaltered versions of this software, or including advertisements of any kind in altered or unaltered versions of this software. + - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, you are required to include an acknowledgement in the product that this software is the copyright of Cellar Door Games and is based on the Rogue Legacy 1 source code. + - Altered source/binary versions must be plainly marked as such, and must not be misrepresented as being the original software. + - You must not distribute any materials from the game which are not included in this repo unless approved by us in writing. + - This notice may not be removed or altered from any source/binary distribution. + +This license is based on the [VVVVVV Source Code License v1.0](https://github.com/TerryCavanagh/VVVVVV/blob/master/LICENSE.md). diff --git a/README.md b/README.md new file mode 100644 index 0000000..b3e4c40 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# Rogue Legacy 1 Source Code + +This is the source code for Rogue Legacy - more specifically, it is _only_ the +code, and only the FNA build. The assets and contentproj are _not_ included. + +## License + +Rogue Legacy's source code is released under a specialized, non-commercial-use +license. See +[LICENSE.md](https://github.com/flibitijibibo/RogueLegacy1/blob/main/LICENSE.md) +for details. + +## Build Environment + +The build environment for Rogue Legacy matches the one recommended by the FNA +project: + +https://fna-xna.github.io/docs/1%3A-Setting-Up-FNA/ + +## Build Instructions + +First, download this repository, FNA, and the native FNA libraries: + +``` +git clone --recursive https://github.com/FNA-XNA/FNA.git +git clone --recursive https://github.com/flibitijibibo/RogueLegacy1.git +curl -O https://fna.flibitijibibo.com/archive/fnalibs3.tar.bz2 +tar xvfj fnalibs3.tar.bz2 --one-top-level +``` + +From here you should be able to `dotnet build RogueLegacy.sln`. The output +should be at `RogueCastle/bin/x64/Debug/net40/`. + +Lastly, you'll need to copy a few files to the output folder manually: + +- Copy the Content folder from your personal copy of the game +- Depending on your OS/architecture, copy the appropriate native libraries from fnalibs (for example, on Windows you would copy `fnalibs/x64/*.dll` next to RogueLegacy.exe) + +The game should now start! diff --git a/RogueCastle/LocaleBuilder.cs b/RogueCastle/LocaleBuilder.cs new file mode 100644 index 0000000..5d335b7 --- /dev/null +++ b/RogueCastle/LocaleBuilder.cs @@ -0,0 +1,388 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System.Globalization; +using System.IO; +using Microsoft.Xna.Framework.Content; +using System.Reflection; +using DS2DEngine; + +namespace RogueCastle +{ + static class LocaleBuilder + { + +#region Fields + + private static Dictionary m_stringDict = new Dictionary(); + private static List m_textObjRefreshList = new List(); + private static LanguageType m_languageType; + private static CultureInfo DEFAULT_CULTUREINFO = new CultureInfo("en-US", false); + private static string SPACE_SEPARATOR = " "; + +#endregion + +#region Properties + + public static LanguageType languageType + { + get { return m_languageType; } + set + { + if (m_languageType != value) + { + m_languageType = value; + + CultureInfo newCI = null; + switch (value) + { + default: + case (LanguageType.English): + newCI = new CultureInfo("en-US", false); + break; + case(LanguageType.French): + newCI = new CultureInfo("fr", false); + break; + case(LanguageType.German): + newCI = new CultureInfo("de", false); + break; + case(LanguageType.Portuguese_Brazil): + newCI = new CultureInfo("pt-BR", false); + break; + case(LanguageType.Spanish_Spain): + newCI = new CultureInfo("es-ES", false); + break; + case (LanguageType.Russian): + newCI = new CultureInfo("ru-RU", false); + break; + case (LanguageType.Polish): + newCI = new CultureInfo("pl", false); + break; + case (LanguageType.Chinese_Simp): + newCI = new CultureInfo("zh-CHS", false); + break; + } + + newCI.NumberFormat.CurrencyDecimalSeparator = "."; + Resources.LocStrings.Culture = newCI; + if (m_languageType == LanguageType.Chinese_Simp) + SPACE_SEPARATOR = ""; + else + SPACE_SEPARATOR = " "; + } + else + m_languageType = value; + } + } + + public static string getResourceString(string stringID, bool forceMale = false) + { + return getResourceStringCustomFemale(stringID, Game.PlayerStats.IsFemale, forceMale); + } + + public static string getResourceStringCustomFemale(string stringID, bool isFemale, bool forceMale = false) + { + if (forceMale == true || LocaleBuilder.languageType == LanguageType.English || LocaleBuilder.languageType == LanguageType.Chinese_Simp) + isFemale = false; + + if (stringID.Length > 0) + { + string resourceString = ""; + if (isFemale == false) + resourceString = Resources.LocStrings.ResourceManager.GetString(stringID, Resources.LocStrings.Culture); + else + resourceString = Resources.LocStrings.ResourceManager.GetString(stringID + "_F", Resources.LocStrings.Culture); + if (resourceString == null) + { + // There is no female version, try again with the male version. + if (isFemale == true) + resourceString = Resources.LocStrings.ResourceManager.GetString(stringID, Resources.LocStrings.Culture); + + // If it's still null, then the entire string is missing both a male and female version (i.e. missing completely). + if (isFemale == false || resourceString == null) + resourceString = "{NULLSTRING: " + stringID + "}"; + } + + resourceString = resourceString.Replace("\\n", "\n"); + return resourceString; + } + else + return ""; + } + + public static int getResourceInt(string stringID) + { + // First try getting from language + string resourceString = Resources.LocStrings.ResourceManager.GetString(stringID, Resources.LocStrings.Culture); + if (resourceString == null || resourceString.Length == 0) + // If empty string or not found, use default english values + resourceString = Resources.LocStrings.ResourceManager.GetString(stringID, DEFAULT_CULTUREINFO); + + int resourceInt = 0; + if (resourceString != null && resourceString.Length > 0) + resourceInt = Convert.ToInt32(resourceString); + + return resourceInt; + } + + // Uncomment this to read off loc text file instead for easier debugging. + //public static string getString(string stringID) + //{ + // string returnString = "{NULL: " + stringID + "}"; + // try + // { + // returnString = m_stringDict[stringID]; + // } + // catch + // { + // //CDConsole.Log("ERROR: Cannot find locale string id: " + stringID); + // } + + // return returnString; + //} + + public static string getString(string stringID, TextObj textObj, bool forceMale = false) + { + if (textObj != null) + { + textObj.locStringID = stringID; + AddToTextRefreshList(textObj); + + if (languageType != LanguageType.English) + { + textObj.Text = ""; + + textObj.isLogographic = false; + if (languageType == LanguageType.Chinese_Simp) + textObj.isLogographic = true; + + textObj.ChangeFontNoDefault(GetLanguageFont(textObj)); + } + } + + string textString = LocaleBuilder.getResourceString(stringID, forceMale); + return textString; + } + + public static SpriteFont GetLanguageFont(TextObj textObj) + { + bool ignoreLanguage = false; + + SpriteFont font = textObj.defaultFont; + + if (font == Game.BitFont || font == Game.EnemyLevelFont || font == Game.PlayerLevelFont + || font == Game.NotoSansSCFont || font == Game.GoldFont || font == Game.PixelArtFont || font == Game.PixelArtFontBold) + ignoreLanguage = true; + + if (ignoreLanguage == true) + return font; + + switch (languageType) + { + case(LanguageType.Chinese_Simp): + return Game.NotoSansSCFont; + case(LanguageType.Russian): + return Game.RobotoSlabFont; + default: + return font; + } + + /* + switch (fontName) + { + case ("LoveYa15"): + switch (languageType) + { + case (LanguageType.Chinese_Simp): + return "NotoSans35CJK"; + default: + return "RobotoSlab15"; + } + case ("LoveYa35"): + switch (languageType) + { + case (LanguageType.Chinese_Simp): + return "NotoSans35CJK"; + default: + return "RobotoSlab35"; + } + case ("RobotoBold20Squeezed"): + switch (languageType) + { + case (LanguageType.Chinese_Simp): + return "NotoSans35CJK"; + default: + return fontName; + } + case ("Banger10"): + case ("Banger35"): + switch (languageType) + { + case (LanguageType.Chinese_Simp): + return "NotoSans35CJK"; + default: + return fontName; + } + case ("AllertaStencil35"): + case ("Allerta15"): + switch (languageType) + { + case (LanguageType.Chinese_Simp): + return "NotoSans35CJK"; + default: + return "NotoSans35"; + } + } + + return fontName; + */ + } + + /* + public static void setString(string stringID, string value) + { + if (m_stringDict.ContainsKey(stringID)) + CDConsole.Log("WARNING: String ID: " + stringID + " already found in dictionary. Overwriting string..."); + + m_stringDict.Add(stringID, value); + }*/ + +#endregion + +#region Methods + + public static void LoadLanguageFile(ContentManager content, string filePath) + { + // Console.WriteLine("Loading language file: " + filePath); + + string line = null; + string languageText = null; + m_stringDict.Clear(); // Clear the dictionary first. + + //using (StreamReader reader = new StreamReader(content.RootDirectory + "\\Languages\\" + filePath)) +#if UNSHARPER + //Blit: todo correct path + using (StreamReader reader = new StreamReader( content.RootDirectory + "\\Languages\\" + filePath)) +#else + using (StreamReader reader = new StreamReader(AppDomain.CurrentDomain.BaseDirectory + "\\" + content.RootDirectory + "\\Languages\\" + filePath)) +#endif + { + try + { + while ((line = reader.ReadLine()) != null) + { + languageText += line + ";"; + languageText = languageText.Replace("\\n", "\n"); + } + + } + catch //(Exception e) + { + // Console.WriteLine("Could not load language file - Error: " + e.Message); + } + finally + { + if (reader != null) + reader.Close(); + } + } + + // Removes all tab instances. + languageText = languageText.Replace("\t", ""); + // Putting all lines into a list, delineated by the semi-colon. + List languageList = languageText.Split(';').ToList(); + // Remove the last entry. ToList() adds a blank entry at the end because the code ends with a semi-colon. + languageList.RemoveAt(languageList.Count -1); + + foreach (string value in languageList) + { + // Ignore blank strings. + if (value.Length <= 0) + continue; + int indexOfFirstComma = value.IndexOf(","); + string stringID = value.Substring(0, indexOfFirstComma); + string text = value.Substring(indexOfFirstComma + 1); + text = text.TrimStart(' '); // Trims any leading whitespaces. + + if (m_stringDict.ContainsKey(stringID) == false) + m_stringDict.Add(stringID, text); + // else + // Console.WriteLine("WARNING: Cannot add StringID: " + stringID + ", Value: " + text + " as it already exists in the dictionary"); + } + } + + public static void RefreshAllText() + { + foreach (TextObj textObj in m_textObjRefreshList) + { + if (textObj != null) + { + textObj.Text = ""; + + if (textObj != null) + { + textObj.Text = ""; + textObj.ChangeFontNoDefault(GetLanguageFont(textObj)); + textObj.Text = getResourceString(textObj.locStringID, false); + + textObj.isLogographic = false; + if (languageType == LanguageType.Chinese_Simp) + textObj.isLogographic = true; + } + +// if (languageType == LanguageType.Chinese_Simp) +// { +// textObj.ChangeFontNoDefault(Game.NotoSansSCFont); +// textObj.isLogographic = true; +// } +//#if false +// else if (languageType == LanguageType.Russian) +// { +// if (textObj.defaultFont == Game.JunicodeFont || textObj.defaultFont == Game.JunicodeLargeFont) +// textObj.ChangeFontNoDefault(Game.RussianFont); +// textObj.isLogographic = false; +// } +//#endif +// else +// { +// textObj.ChangeFontNoDefault(textObj.defaultFont); +// textObj.isLogographic = false; +// } +// textObj.Text = getResourceString(textObj.locStringID); + } + } + + Screen[] screenList = Game.ScreenManager.GetScreens(); + foreach (Screen screen in screenList) + screen.RefreshTextObjs(); + } + + public static void AddToTextRefreshList(TextObj textObj) + { + if (m_textObjRefreshList.Contains(textObj) == false) + m_textObjRefreshList.Add(textObj); + } + + public static void RemoveFromTextRefreshList(TextObj textObj) + { + if (m_textObjRefreshList.Contains(textObj) == true) + m_textObjRefreshList.Remove(textObj); + } + + public static void ClearTextRefreshList() + { + m_textObjRefreshList.Clear(); + } + + public static bool TextRefreshListContains(TextObj textObj) + { + return m_textObjRefreshList.Contains(textObj); + } + +#endregion + + } +} diff --git a/RogueCastle/Properties/AssemblyInfo.cs b/RogueCastle/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7f14786 --- /dev/null +++ b/RogueCastle/Properties/AssemblyInfo.cs @@ -0,0 +1,34 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Rogue Legacy")] +[assembly: AssemblyProduct("RogueLegacy")] +[assembly: AssemblyDescription("Rogue Legacy")] +[assembly: AssemblyCompany("Cellar Door Games, Inc.")] +[assembly: AssemblyCopyright("Copyright © Cellar Door Games, Inc. 2013 - 2018")] +[assembly: AssemblyTrademark("Trademark Cellar Door Games, Inc. 2013 - 2018")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. Only Windows +// assemblies support COM. +[assembly: ComVisible(false)] + +// On Windows, the following GUID is for the ID of the typelib if this +// project is exposed to COM. On other platforms, it unique identifies the +// title storage container when deploying this assembly to the device. +[assembly: Guid("3ea23e9a-fdb7-4465-9cd3-162a6413667f")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.2.0.0")] diff --git a/RogueCastle/Resources/LocStrings.Designer.cs b/RogueCastle/Resources/LocStrings.Designer.cs new file mode 100644 index 0000000..0f6cfa9 --- /dev/null +++ b/RogueCastle/Resources/LocStrings.Designer.cs @@ -0,0 +1,14634 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace RogueCastle.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class LocStrings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal LocStrings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RogueCastle.Resources.LocStrings", typeof(LocStrings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to The castle has been conquered [x] times worldwide.. + /// + internal static string LOC_ID_ACTIVITY_1 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [x] monsters have been slain worldwide.. + /// + internal static string LOC_ID_ACTIVITY_10 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to has slain [x] monsters. + /// + internal static string LOC_ID_ACTIVITY_11 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [x] clowns have been bested worldwide.. + /// + internal static string LOC_ID_ACTIVITY_12 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [x] farts have been farted worldwide.. + /// + internal static string LOC_ID_ACTIVITY_13 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to has sent [x] [y] into the castle.. + /// + internal static string LOC_ID_ACTIVITY_14 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [x] random castles have been generated worldwide.. + /// + internal static string LOC_ID_ACTIVITY_15 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to has conquered the castle [x] times.. + /// + internal static string LOC_ID_ACTIVITY_2 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [x] gold has been given to Charon worldwide.. + /// + internal static string LOC_ID_ACTIVITY_3 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to has have given [x] gold to Charon.. + /// + internal static string LOC_ID_ACTIVITY_4 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [x] heroes have fallen to the Castle worldwide.. + /// + internal static string LOC_ID_ACTIVITY_5 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [x] heroes have been slain by [y] worldwide.. + /// + internal static string LOC_ID_ACTIVITY_6 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [x] has been defeated [y] times worldwide.. + /// + internal static string LOC_ID_ACTIVITY_7 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to greatest family defeated [x] with [y] children. + /// + internal static string LOC_ID_ACTIVITY_8 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to greatest family conquered the castle with [x] children. + /// + internal static string LOC_ID_ACTIVITY_9 { + get { + return ResourceManager.GetString("LOC_ID_ACTIVITY_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Quit to Title Screen. + /// + internal static string LOC_ID_BACK_TO_MENU_OPTIONS_1 { + get { + return ResourceManager.GetString("LOC_ID_BACK_TO_MENU_OPTIONS_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Quit to Title Screen (skip tutorial). + /// + internal static string LOC_ID_BACK_TO_MENU_OPTIONS_2 { + get { + return ResourceManager.GetString("LOC_ID_BACK_TO_MENU_OPTIONS_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to Change Profile. + /// + internal static string LOC_ID_BACK_TO_MENU_OPTIONS_3 { + get { + return ResourceManager.GetString("LOC_ID_BACK_TO_MENU_OPTIONS_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:25] to Change Profile ({0}). + /// + internal static string LOC_ID_BACK_TO_MENU_OPTIONS_3_NEW { + get { + return ResourceManager.GetString("LOC_ID_BACK_TO_MENU_OPTIONS_3_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Health. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Arrow keys to navigate. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_10 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to navigate. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_11 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Button:LeftStick] to navigate. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_11_NEW { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_11_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Select a category. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_12 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Blueprint needed. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_13 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Purchase Info Here. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_14 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to None. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_15 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to unlock. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_16 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} to unlock. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_16_NEW { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_16_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mana. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Damage. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Magic. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Armor. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_5 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Weight. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_6 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Additional Properties:. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_7 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to select/equip. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_8 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:0] select/equip. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_8_NEW { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_8_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to cancel/close menu. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_9 { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:2] cancel/close menu. + /// + internal static string LOC_ID_BLACKSMITH_SCREEN_9_NEW { + get { + return ResourceManager.GetString("LOC_ID_BLACKSMITH_SCREEN_9_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Targets Destroyed. + /// + internal static string LOC_ID_CARNIVAL_BONUS_ROOM_1 { + get { + return ResourceManager.GetString("LOC_ID_CARNIVAL_BONUS_ROOM_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Targets Remaining. + /// + internal static string LOC_ID_CARNIVAL_BONUS_ROOM_2 { + get { + return ResourceManager.GetString("LOC_ID_CARNIVAL_BONUS_ROOM_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reward. + /// + internal static string LOC_ID_CARNIVAL_BONUS_ROOM_3 { + get { + return ResourceManager.GetString("LOC_ID_CARNIVAL_BONUS_ROOM_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to gold. + /// + internal static string LOC_ID_CARNIVAL_BONUS_ROOM_4 { + get { + return ResourceManager.GetString("LOC_ID_CARNIVAL_BONUS_ROOM_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to view map any time. + /// + internal static string LOC_ID_CASTLE_ENTRANCE_ROOM_OBJ_1 { + get { + return ResourceManager.GetString("LOC_ID_CASTLE_ENTRANCE_ROOM_OBJ_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Change Controls. + /// + internal static string LOC_ID_CHANGE_CONTROLS_OPTIONS_1 { + get { + return ResourceManager.GetString("LOC_ID_CHANGE_CONTROLS_OPTIONS_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dash Right. + /// + internal static string LOC_ID_CHANGE_CONTROLS_OPTIONS_10 { + get { + return ResourceManager.GetString("LOC_ID_CHANGE_CONTROLS_OPTIONS_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cast Spell. + /// + internal static string LOC_ID_CHANGE_CONTROLS_OPTIONS_11 { + get { + return ResourceManager.GetString("LOC_ID_CHANGE_CONTROLS_OPTIONS_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reset Controls. + /// + internal static string LOC_ID_CHANGE_CONTROLS_OPTIONS_12 { + get { + return ResourceManager.GetString("LOC_ID_CHANGE_CONTROLS_OPTIONS_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press Any Button. + /// + internal static string LOC_ID_CHANGE_CONTROLS_OPTIONS_13 { + get { + return ResourceManager.GetString("LOC_ID_CHANGE_CONTROLS_OPTIONS_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press Any Key. + /// + internal static string LOC_ID_CHANGE_CONTROLS_OPTIONS_14 { + get { + return ResourceManager.GetString("LOC_ID_CHANGE_CONTROLS_OPTIONS_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Up. + /// + internal static string LOC_ID_CHANGE_CONTROLS_OPTIONS_2 { + get { + return ResourceManager.GetString("LOC_ID_CHANGE_CONTROLS_OPTIONS_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Down. + /// + internal static string LOC_ID_CHANGE_CONTROLS_OPTIONS_3 { + get { + return ResourceManager.GetString("LOC_ID_CHANGE_CONTROLS_OPTIONS_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Left. + /// + internal static string LOC_ID_CHANGE_CONTROLS_OPTIONS_4 { + get { + return ResourceManager.GetString("LOC_ID_CHANGE_CONTROLS_OPTIONS_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Right. + /// + internal static string LOC_ID_CHANGE_CONTROLS_OPTIONS_5 { + get { + return ResourceManager.GetString("LOC_ID_CHANGE_CONTROLS_OPTIONS_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Attack. + /// + internal static string LOC_ID_CHANGE_CONTROLS_OPTIONS_6 { + get { + return ResourceManager.GetString("LOC_ID_CHANGE_CONTROLS_OPTIONS_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Jump. + /// + internal static string LOC_ID_CHANGE_CONTROLS_OPTIONS_7 { + get { + return ResourceManager.GetString("LOC_ID_CHANGE_CONTROLS_OPTIONS_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Special. + /// + internal static string LOC_ID_CHANGE_CONTROLS_OPTIONS_8 { + get { + return ResourceManager.GetString("LOC_ID_CHANGE_CONTROLS_OPTIONS_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dash Left. + /// + internal static string LOC_ID_CHANGE_CONTROLS_OPTIONS_9 { + get { + return ResourceManager.GetString("LOC_ID_CHANGE_CONTROLS_OPTIONS_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your standard hero. Pretty good at everything.. + /// + internal static string LOC_ID_CLASS_DESC_1 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A walking tank. This hero can take a beating.\nSPECIAL: Barbarian Shout.. + /// + internal static string LOC_ID_CLASS_DESC_10 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A fast hero. Deal massive damage, but you cannot crit.. + /// + internal static string LOC_ID_CLASS_DESC_11 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A fast hero. Deal massive damage, but you cannot crit.\nSPECIAL: Replacement Technique.. + /// + internal static string LOC_ID_CLASS_DESC_12 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A hero for experts. Hit enemies to restore mana.. + /// + internal static string LOC_ID_CLASS_DESC_13 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A hero for experts. Hit enemies to restore mana.\nSPECIAL: Empowered Spell.. + /// + internal static string LOC_ID_CLASS_DESC_14 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Feed off the dead. Gain permanent life for every kill up to a cap. Extremely intelligent.. + /// + internal static string LOC_ID_CLASS_DESC_15 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Feed off the dead. Gain permanent life for every kill up to a cap. Extremely intelligent.\nSPECIAL: HP Conversion.. + /// + internal static string LOC_ID_CLASS_DESC_16 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are a man-dragon. + /// + internal static string LOC_ID_CLASS_DESC_17 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ?????. + /// + internal static string LOC_ID_CLASS_DESC_18 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your standard hero. Pretty good at everything.\nSPECIAL: Guardians Shield.. + /// + internal static string LOC_ID_CLASS_DESC_2 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A risky hero. Low stats but can land devastating critical strikes.. + /// + internal static string LOC_ID_CLASS_DESC_3 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A risky hero. Low stats but can land devastating critical strikes.\nSPECIAL: Mist Form.. + /// + internal static string LOC_ID_CLASS_DESC_4 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A hero for hoarders. Very weak, but has a huge bonus to gold.. + /// + internal static string LOC_ID_CLASS_DESC_5 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A hero for hoarders. Very weak, but has a huge bonus to gold.\nSPECIAL: Ordinary Headlamp.. + /// + internal static string LOC_ID_CLASS_DESC_6 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A powerful spellcaster. Every kill gives you mana.. + /// + internal static string LOC_ID_CLASS_DESC_7 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A powerful spellcaster. Every kill gives you mana.\nSPECIAL: Spell Cycle.. + /// + internal static string LOC_ID_CLASS_DESC_8 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A walking tank. This hero can take a beating.. + /// + internal static string LOC_ID_CLASS_DESC_9 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_DESC_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Knight. + /// + internal static string LOC_ID_CLASS_NAME_1_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_1_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Knight. + /// + internal static string LOC_ID_CLASS_NAME_1_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_1_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Barbarian Queen. + /// + internal static string LOC_ID_CLASS_NAME_10_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_10_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Barbarian King. + /// + internal static string LOC_ID_CLASS_NAME_10_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_10_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Shinobi. + /// + internal static string LOC_ID_CLASS_NAME_11 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hokage. + /// + internal static string LOC_ID_CLASS_NAME_12 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spellthief. + /// + internal static string LOC_ID_CLASS_NAME_13_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_13_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spellthief. + /// + internal static string LOC_ID_CLASS_NAME_13_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_13_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spellsword. + /// + internal static string LOC_ID_CLASS_NAME_14_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_14_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spellsword. + /// + internal static string LOC_ID_CLASS_NAME_14_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_14_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lich. + /// + internal static string LOC_ID_CLASS_NAME_15 { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lich Queen. + /// + internal static string LOC_ID_CLASS_NAME_16_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_16_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lich King. + /// + internal static string LOC_ID_CLASS_NAME_16_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_16_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dragon. + /// + internal static string LOC_ID_CLASS_NAME_17_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_17_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dragon. + /// + internal static string LOC_ID_CLASS_NAME_17_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_17_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Traitor. + /// + internal static string LOC_ID_CLASS_NAME_18_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_18_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Traitor. + /// + internal static string LOC_ID_CLASS_NAME_18_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_18_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Paladin. + /// + internal static string LOC_ID_CLASS_NAME_2_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_2_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Paladin. + /// + internal static string LOC_ID_CLASS_NAME_2_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_2_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Knave. + /// + internal static string LOC_ID_CLASS_NAME_3_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_3_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Knave. + /// + internal static string LOC_ID_CLASS_NAME_3_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_3_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Assassin. + /// + internal static string LOC_ID_CLASS_NAME_4_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_4_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Assassin. + /// + internal static string LOC_ID_CLASS_NAME_4_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_4_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Miner. + /// + internal static string LOC_ID_CLASS_NAME_5_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_5_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Miner. + /// + internal static string LOC_ID_CLASS_NAME_5_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_5_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spelunkette. + /// + internal static string LOC_ID_CLASS_NAME_6_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_6_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spelunker. + /// + internal static string LOC_ID_CLASS_NAME_6_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_6_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mage. + /// + internal static string LOC_ID_CLASS_NAME_7_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_7_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mage. + /// + internal static string LOC_ID_CLASS_NAME_7_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_7_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Archmage. + /// + internal static string LOC_ID_CLASS_NAME_8_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_8_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Archmage. + /// + internal static string LOC_ID_CLASS_NAME_8_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_8_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Barbarian. + /// + internal static string LOC_ID_CLASS_NAME_9_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_9_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Barbarian. + /// + internal static string LOC_ID_CLASS_NAME_9_MALE { + get { + return ResourceManager.GetString("LOC_ID_CLASS_NAME_9_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection to "PSN" lost, Cross-Save will be unavailable.. + /// + internal static string LOC_ID_CLOUDSAVING_1 { + get { + return ResourceManager.GetString("LOC_ID_CLOUDSAVING_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are currently not connected to "PSN". Cross-Save data will not be synced online until you reconnect.. + /// + internal static string LOC_ID_CLOUDSAVING_2 { + get { + return ResourceManager.GetString("LOC_ID_CLOUDSAVING_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your local save data is older than the currently uploaded Cross-Save data. Do you wish to upload save data? If you select ''NO'' the currently uploaded Cross-Save data will be downloaded.. + /// + internal static string LOC_ID_CLOUDSAVING_3 { + get { + return ResourceManager.GetString("LOC_ID_CLOUDSAVING_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your local save data is newer than the currently uploaded Cross-Save data. Do you wish to download the Cross-Save data? If you select ''NO'' your local save data will be uploaded as your Cross-Save data.. + /// + internal static string LOC_ID_CLOUDSAVING_4 { + get { + return ResourceManager.GetString("LOC_ID_CLOUDSAVING_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cross-Save is disabled on your Sony Entertainment Network account due to parental control restrictions. + /// + internal static string LOC_ID_CLOUDSAVING_5 { + get { + return ResourceManager.GetString("LOC_ID_CLOUDSAVING_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cross-Save synchronization is disabled on your Sony Entertainment Network account due to parental control restrictions.. + /// + internal static string LOC_ID_CLOUDSAVING_6 { + get { + return ResourceManager.GetString("LOC_ID_CLOUDSAVING_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sync Cross-Save data now. + /// + internal static string LOC_ID_CLOUDSAVING_7 { + get { + return ResourceManager.GetString("LOC_ID_CLOUDSAVING_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cross-Save succeeded. + /// + internal static string LOC_ID_CLOUDSAVING_8 { + get { + return ResourceManager.GetString("LOC_ID_CLOUDSAVING_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Automatic Cross-Save Sync. + /// + internal static string LOC_ID_CLOUDSAVING_9 { + get { + return ResourceManager.GetString("LOC_ID_CLOUDSAVING_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Copyright (C) 2013-2018, Cellar Door Games Inc. . + /// + internal static string LOC_ID_COPYRIGHT_GENERIC { + get { + return ResourceManager.GetString("LOC_ID_COPYRIGHT_GENERIC", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Japanese Localization & Production By. + /// + internal static string LOC_ID_CREDITS_JAPAN { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_JAPAN", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Quality Assurance. + /// + internal static string LOC_ID_CREDITS_QA { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_QA", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Thanks for playing!. + /// + internal static string LOC_ID_CREDITS_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Art. + /// + internal static string LOC_ID_CREDITS_SCREEN_10 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Music & Audio Design. + /// + internal static string LOC_ID_CREDITS_SCREEN_11 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Music. + /// + internal static string LOC_ID_CREDITS_SCREEN_12 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Marketing & Story. + /// + internal static string LOC_ID_CREDITS_SCREEN_13 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Additional Audio Design. + /// + internal static string LOC_ID_CREDITS_SCREEN_14 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Additional Background Art. + /// + internal static string LOC_ID_CREDITS_SCREEN_15 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Business Support. + /// + internal static string LOC_ID_CREDITS_SCREEN_16 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Super Special Thanks: Turbo Edition. + /// + internal static string LOC_ID_CREDITS_SCREEN_17 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Special Thanks. + /// + internal static string LOC_ID_CREDITS_SCREEN_18 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Additional Thanks. + /// + internal static string LOC_ID_CREDITS_SCREEN_19 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_19", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Total Children. + /// + internal static string LOC_ID_CREDITS_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mac/Linux Adaptation by. + /// + internal static string LOC_ID_CREDITS_SCREEN_20 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_20", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mac/Linux QA Team. + /// + internal static string LOC_ID_CREDITS_SCREEN_21 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_21", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Thanks to all our fans for their support!. + /// + internal static string LOC_ID_CREDITS_SCREEN_22 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_22", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Primary Localization by. + /// + internal static string LOC_ID_CREDITS_SCREEN_23 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_23", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Chinese & Add'l Localization by. + /// + internal static string LOC_ID_CREDITS_SCREEN_24 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_24", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Additional Programming. + /// + internal static string LOC_ID_CREDITS_SCREEN_25 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_25", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Adaptation By. + /// + internal static string LOC_ID_CREDITS_SCREEN_26 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_26", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Time Played. + /// + internal static string LOC_ID_CREDITS_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press. + /// + internal static string LOC_ID_CREDITS_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:0] to exit. + /// + internal static string LOC_ID_CREDITS_SCREEN_4_NEW { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_4_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to exit. + /// + internal static string LOC_ID_CREDITS_SCREEN_5 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Developed By. + /// + internal static string LOC_ID_CREDITS_SCREEN_6 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Design & Story. + /// + internal static string LOC_ID_CREDITS_SCREEN_7 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Programming. + /// + internal static string LOC_ID_CREDITS_SCREEN_8 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Production. + /// + internal static string LOC_ID_CREDITS_SCREEN_9 { + get { + return ResourceManager.GetString("LOC_ID_CREDITS_SCREEN_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Joystick Dead Zone. + /// + internal static string LOC_ID_DEAD_ZONE_OPTIONS_1 { + get { + return ResourceManager.GetString("LOC_ID_DEAD_ZONE_OPTIONS_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Delete Save. + /// + internal static string LOC_ID_DELETE_SAVE_OPTIONS_1 { + get { + return ResourceManager.GetString("LOC_ID_DELETE_SAVE_OPTIONS_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Yes. + /// + internal static string LOC_ID_DIALOG_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_DIALOG_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No. + /// + internal static string LOC_ID_DIALOG_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_DIALOG_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_1 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Although I am the eldest child, I am not my father's favorite. I have always known he planned to leave me with nothing.. + /// + internal static string LOC_ID_DIARY_10 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ...And what if I mistook them for a monster?. + /// + internal static string LOC_ID_DIARY_100 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_100", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_101 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_101", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #17. + /// + internal static string LOC_ID_DIARY_102 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_102", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I must be going insane. I stumbled across a carnival inside this castle. Complete with a sad clown and everything.. + /// + internal static string LOC_ID_DIARY_103 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_103", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to He's sort of an ass. But I guess you can't be picky with your friends in a place like this.. + /// + internal static string LOC_ID_DIARY_104 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_104", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I'm getting hungry again. Good thing I topped up on chicken legs. I found these in a chandelier.. + /// + internal static string LOC_ID_DIARY_105 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_105", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This castle... Sometimes I wonder if it's all just a big joke.. + /// + internal static string LOC_ID_DIARY_106 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_106", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_107 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_107", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #18. + /// + internal static string LOC_ID_DIARY_108 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_108", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I have bested the beast of the tower, and once again I could feel the throne room give up some of its power.. + /// + internal static string LOC_ID_DIARY_109 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_109", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to But if I find the cure, everything will change.. + /// + internal static string LOC_ID_DIARY_11 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The rush I feel from this victory is intoxicating! Never have I felt so confident, so powerful, so...at home. Just a little further and I will be able to earn my reward!. + /// + internal static string LOC_ID_DIARY_110 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_110", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I'm so close! I will make my father proud!. + /// + internal static string LOC_ID_DIARY_111 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_111", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_112 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_112", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #19. + /// + internal static string LOC_ID_DIARY_113 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_113", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I have been standing outside the dungeon gate for longer then I care to admit.. + /// + internal static string LOC_ID_DIARY_114 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_114", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to My courage has finally been sapped, for I have spied the monsters below, and they make my previous struggles laughable in comparison.. + /// + internal static string LOC_ID_DIARY_115 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_115", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I must steel myself. I must focus. There is so little light down there, I fear that I may lose myself.. + /// + internal static string LOC_ID_DIARY_116 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_116", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_117 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_117", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #20. + /// + internal static string LOC_ID_DIARY_118 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_118", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I thought I knew what darkness was, but here in the dungeon, the darkness has a voice.. + /// + internal static string LOC_ID_DIARY_119 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_119", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The victor will earn nothing less than the throne upon his passing!. + /// + internal static string LOC_ID_DIARY_12 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It calls at me through grates, and around corners. It taunts me.. + /// + internal static string LOC_ID_DIARY_120 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_120", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The darkness is so thick, it is almost tangible, and the beasts here have made it their home. They move swiftly through the corridors, and are more terrifying then anything I've fought before.. + /// + internal static string LOC_ID_DIARY_121 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_121", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I must be prudent and choose my battles carefully. Being confrontational now may cost me my life.. + /// + internal static string LOC_ID_DIARY_122 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_122", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_123 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_123", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #21. + /// + internal static string LOC_ID_DIARY_124 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_124", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I have done it! I have defeated the dungeon's master! All that remains is to enter the throne room.. + /// + internal static string LOC_ID_DIARY_125 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_125", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to After this, the king will honor me for my valor and acknowledge me as rightful successor to the throne!. + /// + internal static string LOC_ID_DIARY_126 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_126", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Not my faceless siblings!. + /// + internal static string LOC_ID_DIARY_127 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_127", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_128 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_128", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #22. + /// + internal static string LOC_ID_DIARY_129 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_129", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upon my ascension, my wife and my children shall move back into the royal quarters. Back to the royal city, where we once again will be treated with the respect we deserve!. + /// + internal static string LOC_ID_DIARY_13 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I sit here making my final preparations. All that lays between me and the lord of this castle is the golden doors.. + /// + internal static string LOC_ID_DIARY_130 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_130", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There is an nervousness in my body that I cannot quell. Is this fear, or fearcitement? All I know is that my journey is finally reaching an end.. + /// + internal static string LOC_ID_DIARY_131 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_131", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I have almost forgotten why I entered this castle in the first place, but I remember now.. + /// + internal static string LOC_ID_DIARY_132 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_132", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I have bested my siblings, I will save the king, and leave this castle a greater man then when I entered. My family will get the honor they so rightfully deserve.. + /// + internal static string LOC_ID_DIARY_133 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_133", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Now, I enter the throne room.. + /// + internal static string LOC_ID_DIARY_134 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_134", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_135 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_135", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #23. + /// + internal static string LOC_ID_DIARY_136 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_136", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I never knew what treasure lay in this castle. I knew only that it would cure the king.. + /// + internal static string LOC_ID_DIARY_137 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_137", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Who could have suspected it would be the fountain of youth?. + /// + internal static string LOC_ID_DIARY_138 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_138", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I expected a monster to greet me at the dias; a foe of unimaginable strength. I imagined it would take all my strength to best him.. + /// + internal static string LOC_ID_DIARY_139 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_139", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No longer will we stand for the gossip and petty slander of my cousins. The other dukes shall bow as we pass! But I am getting ahead of myself.. + /// + internal static string LOC_ID_DIARY_14 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to But when I entered the castle and saw my father - the king - sitting atop the dias with goblet in hand, I knew all was lost.. + /// + internal static string LOC_ID_DIARY_140 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_140", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to He would never die.... + /// + internal static string LOC_ID_DIARY_141 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_141", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ...and I would never be heir.. + /// + internal static string LOC_ID_DIARY_142 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_142", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There are no words to express what I feel.. + /// + internal static string LOC_ID_DIARY_143 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_143", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_144 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_144", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #24. + /// + internal static string LOC_ID_DIARY_145 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_145", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ............................... + /// + internal static string LOC_ID_DIARY_146 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_146", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ..... + /// + internal static string LOC_ID_DIARY_147 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_147", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_148 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_148", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #25. + /// + internal static string LOC_ID_DIARY_149 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_149", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I must keep my priorities clear: Conquer the castle. Find the cure. Collect my reward.. + /// + internal static string LOC_ID_DIARY_15 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Today marks the rest of eternity.. + /// + internal static string LOC_ID_DIARY_150 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_150", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I never knew what treasure lay in this castle. Just that it would cure the king of his illness.. + /// + internal static string LOC_ID_DIARY_151 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_151", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ... Who would have known it would have been the fountain of youth? A myth, which grants one eternal life.. + /// + internal static string LOC_ID_DIARY_152 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_152", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to As I look down on the body of the king I realize that it is inevitable: children will always answer for their father's sins.. + /// + internal static string LOC_ID_DIARY_153 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_153", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I entered this castle a swordsman, a savior.... + /// + internal static string LOC_ID_DIARY_154 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_154", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to But all I have left is a rogue's legacy.. + /// + internal static string LOC_ID_DIARY_155 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_155", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I can feel your anger, but know it was not I who sent your family to ruin.. + /// + internal static string LOC_ID_DIARY_156 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_156", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The moment the king set foot within this castle, the royal coffers were emptied by Charon. My family - all families - had lost all hope for a better life.. + /// + internal static string LOC_ID_DIARY_157 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_157", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to And in my mind's eye, I foresaw only desperation and poverty ravage the country. There was nothing for me to go back to.. + /// + internal static string LOC_ID_DIARY_158 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_158", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to To my children, and my children's children, here I sit, impassive, immortal, and await thee.. + /// + internal static string LOC_ID_DIARY_159 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_159", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_16 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Johannes. + /// + internal static string LOC_ID_DIARY_160 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_160", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to What is this? Are you... mocking me?!. + /// + internal static string LOC_ID_DIARY_161 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_161", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to After countless generations of your ancestors sacrificed their lives to be where you are now, the final steps to achieving their hollow justice. And you arrive and mock me?. + /// + internal static string LOC_ID_DIARY_162 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_162", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Very well, I will spare your ignorance. Let us begin!. + /// + internal static string LOC_ID_DIARY_163 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_163", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Johannes. + /// + internal static string LOC_ID_DIARY_164 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_164", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Why do you wish to fight me? How many sons and daughters have been lost in your pathetic attempts at revenge?. + /// + internal static string LOC_ID_DIARY_165 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_165", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It was the king who brought ruin to your country, not I!. + /// + internal static string LOC_ID_DIARY_166 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_166", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to He lied to us. He said he was wounded, yet it was only time that threatened him!. + /// + internal static string LOC_ID_DIARY_167 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_167", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to He pitted his children against one another, sacrificed everything to satisfy his own selfish desires, and in the end, left us penniless and alone.. + /// + internal static string LOC_ID_DIARY_168 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_168", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to So I took the only option left to me. I rejected king and country.... + /// + internal static string LOC_ID_DIARY_169 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_169", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #3. + /// + internal static string LOC_ID_DIARY_17 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to And chose a new family instead!. + /// + internal static string LOC_ID_DIARY_170 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_170", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Johannes. + /// + internal static string LOC_ID_DIARY_171 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_171", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You think you have slain me?. + /// + internal static string LOC_ID_DIARY_172 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_172", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I have lived for over a thousand years, and I will live for ten thousand more!. + /// + internal static string LOC_ID_DIARY_173 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_173", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Alexander... Khidr... Ponce De Leon.... + /// + internal static string LOC_ID_DIARY_174 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_174", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I was not the first hero to reach the fountain.... + /// + internal static string LOC_ID_DIARY_175 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_175", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to But I will be the last!. + /// + internal static string LOC_ID_DIARY_176 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_176", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fountain of Youth. + /// + internal static string LOC_ID_DIARY_177 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_177", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to .... + /// + internal static string LOC_ID_DIARY_178 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_178", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have defeated me... But at what price?. + /// + internal static string LOC_ID_DIARY_179 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_179", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I have paid my dues, and entered the castle proper. That devil Charon has taken all that I own as payment.. + /// + internal static string LOC_ID_DIARY_18 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I may have slain the king, but only after he betrayed his people.. + /// + internal static string LOC_ID_DIARY_180 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_180", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ask yourself what justice has been met?. + /// + internal static string LOC_ID_DIARY_181 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_181", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to In the end we are all guilty of the same sin. Look to your forefathers - such is the cost for unquestioned loyalty.. + /// + internal static string LOC_ID_DIARY_182 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_182", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to .... + /// + internal static string LOC_ID_DIARY_183 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_183", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to .... + /// + internal static string LOC_ID_DIARY_184 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_184", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The sun.... + /// + internal static string LOC_ID_DIARY_185 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_185", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I had forgotten how it feels.... + /// + internal static string LOC_ID_DIARY_186 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_186", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to He has even pilfered my private coffers! I have left my wife and children with nothing.. + /// + internal static string LOC_ID_DIARY_19 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_19", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #1. + /// + internal static string LOC_ID_DIARY_2 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to He says it's the price for any and all who hazard the depths of the castle. He says it is fair.. + /// + internal static string LOC_ID_DIARY_20 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_20", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It is fair because of all who have entered, none have returned. But I will change that.. + /// + internal static string LOC_ID_DIARY_21 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_21", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I will be victorious! There is no greater swordsman than I, even amongst my siblings.. + /// + internal static string LOC_ID_DIARY_22 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_22", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_23 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_23", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #4. + /// + internal static string LOC_ID_DIARY_24 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_24", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Everything about this castle is off. I can't seem to keep track of my headings, and there is no sun or stars to guide me.. + /// + internal static string LOC_ID_DIARY_25 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_25", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I find myself backtracking constantly, and I must painstakingly map out my progress lest I go in circles. . + /// + internal static string LOC_ID_DIARY_26 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_26", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The maps I have pilfered off the corpses of other adventurers are breathtakingly inaccurate. It is almost as if they were describing a different castle altogether!. + /// + internal static string LOC_ID_DIARY_27 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_27", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Perhaps this place does something to the mind.... + /// + internal static string LOC_ID_DIARY_28 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_28", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Or are the stones truly shifting beneath my feet?. + /// + internal static string LOC_ID_DIARY_29 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_29", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Treason! An assassin has wounded my father, the king!. + /// + internal static string LOC_ID_DIARY_3 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_30 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_30", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #5. + /// + internal static string LOC_ID_DIARY_31 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_31", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I cannot exit through the front gate, but that is of little concern. I am committed to my cause and will not back out!. + /// + internal static string LOC_ID_DIARY_32 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_32", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to So far none of the maps I've found coincide with my own.. + /// + internal static string LOC_ID_DIARY_33 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_33", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Yet upon comparing them as a whole, I believe I have unearthed a slight pattern. It seems the forest is always to the right; the tower above.... + /// + internal static string LOC_ID_DIARY_34 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_34", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to And below? Well, hopefully I won't have to find out.. + /// + internal static string LOC_ID_DIARY_35 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_35", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_36 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_36", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #6. + /// + internal static string LOC_ID_DIARY_37 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_37", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I have never liked the dark. I prefer to meet my enemies on an open field in plain sight.. + /// + internal static string LOC_ID_DIARY_38 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_38", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to But now I find myself braving these darkened gallows with one gauntlet outstreched, the other by my hilt. I can never tell what horror lies beyond each corner.. + /// + internal static string LOC_ID_DIARY_39 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_39", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to To bring order back to the kingdom, he has sent my siblings and I on a quest to save him. Together, we will venture into the cursed woods, and enter Castle Hamson.. + /// + internal static string LOC_ID_DIARY_4 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I am the greatest swordsman in all the lands, yet even I am having trouble keeping these demons at bay.. + /// + internal static string LOC_ID_DIARY_40 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_40", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to My siblings should be grateful that I rushed ahead of them. For them it was a blessing in disguise. They would not have the fortitude to survive these halls.. + /// + internal static string LOC_ID_DIARY_41 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_41", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_42 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_42", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #7. + /// + internal static string LOC_ID_DIARY_43 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_43", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It is still night. Past every window stares back the same melancholic moon, but I swear I have been here for at least a whole waking day.. + /// + internal static string LOC_ID_DIARY_44 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_44", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It must be the adrenaline. I have never felt so powerful, yet simultaneously challenged. It is exhilarating to charge through these rooms, cutting down enemy after enemy.. + /// + internal static string LOC_ID_DIARY_45 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_45", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to In some ways the foes in this castle feel tailored to me. Training me, guiding me, watching me.. + /// + internal static string LOC_ID_DIARY_46 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_46", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This may sound crazy, but if this castle can somehow sense those within it, I fear it may hold malicious intent as well. If my assumptions are correct, the design of these halls could all be a ploy, culling me down further into a trap.. + /// + internal static string LOC_ID_DIARY_47 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_47", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I must stay alert.. + /// + internal static string LOC_ID_DIARY_48 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_48", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_49 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_49", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This cursed castle has stood on the edge of the woods since time immemorial, but rumors say that within it dwells an item which will cure any ailment.. + /// + internal static string LOC_ID_DIARY_5 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #8. + /// + internal static string LOC_ID_DIARY_50 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_50", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to From the number of dead adventurers I have passed in these halls, I have come to the following conclusions:. + /// + internal static string LOC_ID_DIARY_51 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_51", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 1: Many did not take enough provisions with them. I assume many died of hunger. I myself am running low and will have to find more supplies.. + /// + internal static string LOC_ID_DIARY_52 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_52", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 2: Many are missing clothes, which explains the pant-wearing zombies.. + /// + internal static string LOC_ID_DIARY_53 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_53", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 3: No one has made it as far as I, since I haven't passed any corpses in over an hour.. + /// + internal static string LOC_ID_DIARY_54 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_54", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_55 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_55", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #9. + /// + internal static string LOC_ID_DIARY_56 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_56", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The door to the throne room is driving me mad! Beyond it lies the king's salvation, and my reward, but it stands silent in the middle of the castle foyer, taunting me.. + /// + internal static string LOC_ID_DIARY_57 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_57", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I've tried pushing it, kicking it, yelling "Open Sesame", but nothing works.. + /// + internal static string LOC_ID_DIARY_58 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_58", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There are icons emblazoned into the doors, and one of them looks like a beast I avoided deeper in the castle. Perhaps there is some sort of correlation?. + /// + internal static string LOC_ID_DIARY_59 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_59", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tonight I will get a headstart over my brothers and sisters, and set forth on my quest while they lay asleep.. + /// + internal static string LOC_ID_DIARY_6 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_60 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_60", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #10. + /// + internal static string LOC_ID_DIARY_61 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_61", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The emblems on the castle door are a clue! I slew the giant beast that matched one of the icons, and I sensed something shift behind the throne room doors.. + /// + internal static string LOC_ID_DIARY_62 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_62", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to As if in a dream, I could see an emblem on the door glowing in my mind's eye.. + /// + internal static string LOC_ID_DIARY_63 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_63", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A truly out of body experience.. + /// + internal static string LOC_ID_DIARY_64 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_64", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to At least I know I'm on the right track. But I must hasten my pace, for the king could succumb to his injuries at any moment.... + /// + internal static string LOC_ID_DIARY_65 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_65", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to But first I must rest. Tomorrow, I enter the Forest.. + /// + internal static string LOC_ID_DIARY_66 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_66", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_67 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_67", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #11. + /// + internal static string LOC_ID_DIARY_68 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_68", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This forest is unlike anything I've ever seen before. It is both serene and terrifying. I stand on lush grass, but beside me yawns open a chasm so wide and deep, it threatens to swallow me whole.. + /// + internal static string LOC_ID_DIARY_69 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_69", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to To fail this quest would be an embarrassment to my name.. + /// + internal static string LOC_ID_DIARY_7 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I still have not heard a response from the rock I tossed in earlier. A single misstep, and my descent would be eternal. It is truly a horrifying thought.. + /// + internal static string LOC_ID_DIARY_70 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_70", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An eternity of darkness is more frightening than any beast I have fought thus far. If I fell, what would kill me first? The hunger, or myself?. + /// + internal static string LOC_ID_DIARY_71 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_71", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to On a side note, I am now using the forest fissure as my own personal lavatory. I wonder if I am pooping into another dimension.... + /// + internal static string LOC_ID_DIARY_72 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_72", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_73 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_73", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #12. + /// + internal static string LOC_ID_DIARY_74 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_74", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I have found a solution to my hunger problem. The forest holds an endless bounty of delicious mushrooms.. + /// + internal static string LOC_ID_DIARY_75 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_75", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to And within these mushrooms lie chicken legs! Also gold coins, and vials of sparkling water... I broke open a tree trunk earlier, and a bag of money fell out.. + /// + internal static string LOC_ID_DIARY_76 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_76", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sometimes I feel like I have gone insane.. + /// + internal static string LOC_ID_DIARY_77 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_77", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ... Plus, what is up with the moon? It's HUGE!. + /// + internal static string LOC_ID_DIARY_78 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_78", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_79 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_79", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_8 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #13. + /// + internal static string LOC_ID_DIARY_80 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_80", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I slew the beast of the forest, and I have felt the throne room weaken once more.. + /// + internal static string LOC_ID_DIARY_81 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_81", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to So far my assumptions have proven correct. Each wing of the castle houses its own guardian beast. Was this designed as a test of will? If so, then I cannot fail, for the further I venture, the more bold I become!. + /// + internal static string LOC_ID_DIARY_82 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_82", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tomorrow I scour the tower. I am on a roll.. + /// + internal static string LOC_ID_DIARY_83 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_83", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_84 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_84", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #14. + /// + internal static string LOC_ID_DIARY_85 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_85", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I have been methodically clearing the demons in these rooms in my quest to slay the next guardian, but I am losing track of time... and other things.... + /// + internal static string LOC_ID_DIARY_86 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_86", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to As I entered the tower, I felt time stand still. Or perhaps that is the vertigo talking? I was never keen on heights...or was I?. + /// + internal static string LOC_ID_DIARY_87 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_87", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I am finding it increasingly difficult to remember my past.... + /// + internal static string LOC_ID_DIARY_88 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_88", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_89 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_89", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #2. + /// + internal static string LOC_ID_DIARY_9 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #15. + /// + internal static string LOC_ID_DIARY_90 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_90", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I remember being a famous adventurer. My martial prowress surpassed all of my brothers. That, I am sure of. While they spent their days buried in their bookish studies, I was out killing brigands and monsters.. + /// + internal static string LOC_ID_DIARY_91 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_91", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I always wondered why my father favoured them over me? Isn't it always the opposite in fairytales?. + /// + internal static string LOC_ID_DIARY_92 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_92", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fortune favors the bold. Not the insipid intellectual... Or something like that.. + /// + internal static string LOC_ID_DIARY_93 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_93", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Man, I would love to see my brothers try to out think my sword in their face!. + /// + internal static string LOC_ID_DIARY_94 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_94", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prince's Journal. + /// + internal static string LOC_ID_DIARY_95 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_95", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Journal Entry #16. + /// + internal static string LOC_ID_DIARY_96 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_96", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to What if years have passed since I first entered these walls? It is true that I am becoming more proficient in clearing monsters, but it feels like an age has passed.. + /// + internal static string LOC_ID_DIARY_97 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_97", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I have even forgotten what my own kin look like.. + /// + internal static string LOC_ID_DIARY_98 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_98", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to What if they think I have failed? What if one of my brothers has beaten me to the cure?. + /// + internal static string LOC_ID_DIARY_99 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_99", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Entry #. + /// + internal static string LOC_ID_DIARY_ENTRY_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_DIARY_ENTRY_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Donate {0} gold and permanently empower your specter for this boss?\nTimes Empowered: {1}. + /// + internal static string LOC_ID_DONATIONBOX_TEXT_1 { + get { + return ResourceManager.GetString("LOC_ID_DONATIONBOX_TEXT_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The donation box is filled to the brim. Your specter cannot be empowered any further. Thanks for the money dood.. + /// + internal static string LOC_ID_DONATIONBOX_TEXT_2 { + get { + return ResourceManager.GetString("LOC_ID_DONATIONBOX_TEXT_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You cannot afford to donate. Come back when you've earned more gold.. + /// + internal static string LOC_ID_DONATIONBOX_TEXT_3 { + get { + return ResourceManager.GetString("LOC_ID_DONATIONBOX_TEXT_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your specter has become stronger!. + /// + internal static string LOC_ID_DONATIONBOX_TEXT_4 { + get { + return ResourceManager.GetString("LOC_ID_DONATIONBOX_TEXT_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Donation Box. + /// + internal static string LOC_ID_DONATIONBOX_TITLE_1 { + get { + return ResourceManager.GetString("LOC_ID_DONATIONBOX_TITLE_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Castle Hamson. + /// + internal static string LOC_ID_DUNGEON_NAME_1 { + get { + return ResourceManager.GetString("LOC_ID_DUNGEON_NAME_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Land of Darkness. + /// + internal static string LOC_ID_DUNGEON_NAME_2 { + get { + return ResourceManager.GetString("LOC_ID_DUNGEON_NAME_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Forest Abkhazia. + /// + internal static string LOC_ID_DUNGEON_NAME_3 { + get { + return ResourceManager.GetString("LOC_ID_DUNGEON_NAME_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Maya. + /// + internal static string LOC_ID_DUNGEON_NAME_4 { + get { + return ResourceManager.GetString("LOC_ID_DUNGEON_NAME_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Select a category. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rune needed. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_10 { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Purchase Info Here. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_11 { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to unlock. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_12 { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} to unlock. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_12_NEW { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_12_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rune. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_13 { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to close map. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to re-center on player. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to move map. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Instructions. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_5 { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to select/equip. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_6 { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:0] select/equip. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_6_NEW { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_6_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to cancel/close menu. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_7 { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:2] cancel/close menu. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_7_NEW { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_7_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Arrow keys to navigate. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_8 { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to navigate. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_9 { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Button:LeftStick] to navigate. + /// + internal static string LOC_ID_ENCHANTRESS_SCREEN_9_NEW { + get { + return ResourceManager.GetString("LOC_ID_ENCHANTRESS_SCREEN_9_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Slain. + /// + internal static string LOC_ID_ENDING_ROOM_OBJ_1 { + get { + return ResourceManager.GetString("LOC_ID_ENDING_ROOM_OBJ_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press. + /// + internal static string LOC_ID_ENDING_ROOM_OBJ_2 { + get { + return ResourceManager.GetString("LOC_ID_ENDING_ROOM_OBJ_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:0] to exit. + /// + internal static string LOC_ID_ENDING_ROOM_OBJ_2_NEW { + get { + return ResourceManager.GetString("LOC_ID_ENDING_ROOM_OBJ_2_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to exit. + /// + internal static string LOC_ID_ENDING_ROOM_OBJ_3 { + get { + return ResourceManager.GetString("LOC_ID_ENDING_ROOM_OBJ_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Skeleton. + /// + internal static string LOC_ID_ENEMY_NAME_1 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bloobasaurus Rex. + /// + internal static string LOC_ID_ENEMY_NAME_10 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Grandpa Spark. + /// + internal static string LOC_ID_ENEMY_NAME_100 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_100", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lord Spark, King of Sparkatonia. + /// + internal static string LOC_ID_ENEMY_NAME_101 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_101", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mimic. + /// + internal static string LOC_ID_ENEMY_NAME_102 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_102", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mimicant. + /// + internal static string LOC_ID_ENEMY_NAME_103 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_103", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mimicrunch. + /// + internal static string LOC_ID_ENEMY_NAME_104 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_104", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Chesticles. + /// + internal static string LOC_ID_ENEMY_NAME_105 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_105", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Barbatos. + /// + internal static string LOC_ID_ENEMY_NAME_106 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_106", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stolas. + /// + internal static string LOC_ID_ENEMY_NAME_107 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_107", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Berith. + /// + internal static string LOC_ID_ENEMY_NAME_108 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_108", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Amon. + /// + internal static string LOC_ID_ENEMY_NAME_109 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_109", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Herodotus. + /// + internal static string LOC_ID_ENEMY_NAME_11 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Focalor. + /// + internal static string LOC_ID_ENEMY_NAME_110 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_110", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Halphas. + /// + internal static string LOC_ID_ENEMY_NAME_111 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_111", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Neo Khidr. + /// + internal static string LOC_ID_ENEMY_NAME_112 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_112", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Alexander the IV. + /// + internal static string LOC_ID_ENEMY_NAME_113 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_113", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Astrodotus. + /// + internal static string LOC_ID_ENEMY_NAME_114 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_114", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ponce de Freon. + /// + internal static string LOC_ID_ENEMY_NAME_115 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_115", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Brohannes. + /// + internal static string LOC_ID_ENEMY_NAME_116 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_116", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Wall Turret. + /// + internal static string LOC_ID_ENEMY_NAME_117 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_117", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Gatekeeper. + /// + internal static string LOC_ID_ENEMY_NAME_118 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_118", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Infinite. + /// + internal static string LOC_ID_ENEMY_NAME_119 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_119", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Chaintor. + /// + internal static string LOC_ID_ENEMY_NAME_12 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Forgotten. + /// + internal static string LOC_ID_ENEMY_NAME_120 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_120", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Forsaken. + /// + internal static string LOC_ID_ENEMY_NAME_121 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_121", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Sentinel. + /// + internal static string LOC_ID_ENEMY_NAME_122 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_122", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Traitor. + /// + internal static string LOC_ID_ENEMY_NAME_123 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_123", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Fountain. + /// + internal static string LOC_ID_ENEMY_NAME_124 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_124", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Berith & Halphas. + /// + internal static string LOC_ID_ENEMY_NAME_125 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_125", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Barbatos & Amon. + /// + internal static string LOC_ID_ENEMY_NAME_126 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_126", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stolas & Focalor. + /// + internal static string LOC_ID_ENEMY_NAME_127 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_127", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Chaintex. + /// + internal static string LOC_ID_ENEMY_NAME_13 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Chaintus. + /// + internal static string LOC_ID_ENEMY_NAME_14 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pantheon. + /// + internal static string LOC_ID_ENEMY_NAME_15 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Earthsor. + /// + internal static string LOC_ID_ENEMY_NAME_16 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gravisor. + /// + internal static string LOC_ID_ENEMY_NAME_17 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Terrasor. + /// + internal static string LOC_ID_ENEMY_NAME_18 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Flamelock. + /// + internal static string LOC_ID_ENEMY_NAME_19 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_19", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mr Bones. + /// + internal static string LOC_ID_ENEMY_NAME_2 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Blazelock. + /// + internal static string LOC_ID_ENEMY_NAME_20 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_20", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sollock. + /// + internal static string LOC_ID_ENEMY_NAME_21 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_21", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sol Mage. + /// + internal static string LOC_ID_ENEMY_NAME_22 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_22", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Frosten. + /// + internal static string LOC_ID_ENEMY_NAME_23 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_23", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Icen. + /// + internal static string LOC_ID_ENEMY_NAME_24 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_24", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Glacien. + /// + internal static string LOC_ID_ENEMY_NAME_25 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_25", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Luna Mage. + /// + internal static string LOC_ID_ENEMY_NAME_26 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_26", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scout. + /// + internal static string LOC_ID_ENEMY_NAME_27 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_27", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pupil. + /// + internal static string LOC_ID_ENEMY_NAME_28 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_28", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Visionary. + /// + internal static string LOC_ID_ENEMY_NAME_29 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_29", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to McRib. + /// + internal static string LOC_ID_ENEMY_NAME_3 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Khidr. + /// + internal static string LOC_ID_ENEMY_NAME_30 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_30", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fury. + /// + internal static string LOC_ID_ENEMY_NAME_31 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_31", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rage. + /// + internal static string LOC_ID_ENEMY_NAME_32 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_32", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Wrath. + /// + internal static string LOC_ID_ENEMY_NAME_33 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_33", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Alexander. + /// + internal static string LOC_ID_ENEMY_NAME_34 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_34", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tall Guard. + /// + internal static string LOC_ID_ENEMY_NAME_35 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_35", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hulk Guard. + /// + internal static string LOC_ID_ENEMY_NAME_36 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_36", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tower Guard. + /// + internal static string LOC_ID_ENEMY_NAME_37 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_37", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sentinel. + /// + internal static string LOC_ID_ENEMY_NAME_38 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_38", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spiketor. + /// + internal static string LOC_ID_ENEMY_NAME_39 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_39", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Corrupt Knight. + /// + internal static string LOC_ID_ENEMY_NAME_4 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spiketex. + /// + internal static string LOC_ID_ENEMY_NAME_40 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_40", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spiketus. + /// + internal static string LOC_ID_ENEMY_NAME_41 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_41", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spiker. + /// + internal static string LOC_ID_ENEMY_NAME_42 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_42", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gray Knight. + /// + internal static string LOC_ID_ENEMY_NAME_43 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_43", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gray Baron. + /// + internal static string LOC_ID_ENEMY_NAME_44 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_44", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Graydiator. + /// + internal static string LOC_ID_ENEMY_NAME_45 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_45", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Graypion. + /// + internal static string LOC_ID_ENEMY_NAME_46 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_46", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Warg. + /// + internal static string LOC_ID_ENEMY_NAME_47 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_47", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Wargen. + /// + internal static string LOC_ID_ENEMY_NAME_48 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_48", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Wargenflorgen. + /// + internal static string LOC_ID_ENEMY_NAME_49 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_49", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Corrupt Vanguard. + /// + internal static string LOC_ID_ENEMY_NAME_5 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Zorg Warg. + /// + internal static string LOC_ID_ENEMY_NAME_50 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_50", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Zombie. + /// + internal static string LOC_ID_ENEMY_NAME_51 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_51", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Zomboner. + /// + internal static string LOC_ID_ENEMY_NAME_52 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_52", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Zombishnu. + /// + internal static string LOC_ID_ENEMY_NAME_53 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_53", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Zomg. + /// + internal static string LOC_ID_ENEMY_NAME_54 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_54", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Energon. + /// + internal static string LOC_ID_ENEMY_NAME_55 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_55", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mastertron. + /// + internal static string LOC_ID_ENEMY_NAME_56 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_56", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Voltron. + /// + internal static string LOC_ID_ENEMY_NAME_57 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_57", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prime. + /// + internal static string LOC_ID_ENEMY_NAME_58 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_58", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ninjo. + /// + internal static string LOC_ID_ENEMY_NAME_59 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_59", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Corrupt Lord. + /// + internal static string LOC_ID_ENEMY_NAME_6 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ninpo. + /// + internal static string LOC_ID_ENEMY_NAME_60 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_60", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ninpojo. + /// + internal static string LOC_ID_ENEMY_NAME_61 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_61", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Master Ninja. + /// + internal static string LOC_ID_ENEMY_NAME_62 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_62", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bud. + /// + internal static string LOC_ID_ENEMY_NAME_63 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_63", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Plantite. + /// + internal static string LOC_ID_ENEMY_NAME_64 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_64", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Flowermon. + /// + internal static string LOC_ID_ENEMY_NAME_65 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_65", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Charite. + /// + internal static string LOC_ID_ENEMY_NAME_66 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_66", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pyrite. + /// + internal static string LOC_ID_ENEMY_NAME_67 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_67", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Infernite. + /// + internal static string LOC_ID_ENEMY_NAME_68 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_68", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ponce de Leon. + /// + internal static string LOC_ID_ENEMY_NAME_69 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_69", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Botis. + /// + internal static string LOC_ID_ENEMY_NAME_7 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spike Trap. + /// + internal static string LOC_ID_ENEMY_NAME_70 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_70", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Archer. + /// + internal static string LOC_ID_ENEMY_NAME_71 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_71", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ranger. + /// + internal static string LOC_ID_ENEMY_NAME_72 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_72", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sniper. + /// + internal static string LOC_ID_ENEMY_NAME_73 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_73", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sharpshooter. + /// + internal static string LOC_ID_ENEMY_NAME_74 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_74", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Johannes. + /// + internal static string LOC_ID_ENEMY_NAME_75 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_75", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Fountain. + /// + internal static string LOC_ID_ENEMY_NAME_76 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_76", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fountain of Youth. + /// + internal static string LOC_ID_ENEMY_NAME_77 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_77", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Doomvas. + /// + internal static string LOC_ID_ENEMY_NAME_78 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_78", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Doomtrait. + /// + internal static string LOC_ID_ENEMY_NAME_79 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_79", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bloob. + /// + internal static string LOC_ID_ENEMY_NAME_8 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Doomscape. + /// + internal static string LOC_ID_ENEMY_NAME_80 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_80", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sallos. + /// + internal static string LOC_ID_ENEMY_NAME_81 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_81", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Plinky. + /// + internal static string LOC_ID_ENEMY_NAME_82 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_82", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Planky. + /// + internal static string LOC_ID_ENEMY_NAME_83 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_83", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Plonky. + /// + internal static string LOC_ID_ENEMY_NAME_84 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_84", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ploo. + /// + internal static string LOC_ID_ENEMY_NAME_85 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_85", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Kentucky. + /// + internal static string LOC_ID_ENEMY_NAME_86 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_86", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fried. + /// + internal static string LOC_ID_ENEMY_NAME_87 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_87", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Chicken. + /// + internal static string LOC_ID_ENEMY_NAME_88 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_88", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Delicious. + /// + internal static string LOC_ID_ENEMY_NAME_89 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_89", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bloobite. + /// + internal static string LOC_ID_ENEMY_NAME_9 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to GuardBox. + /// + internal static string LOC_ID_ENEMY_NAME_90 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_90", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to GuardBox XL. + /// + internal static string LOC_ID_ENEMY_NAME_91 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_91", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to GuardBox 2000. + /// + internal static string LOC_ID_ENEMY_NAME_92 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_92", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to GuardBox Gigasaur. + /// + internal static string LOC_ID_ENEMY_NAME_93 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_93", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Headless Horse. + /// + internal static string LOC_ID_ENEMY_NAME_94 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_94", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dark Stallion. + /// + internal static string LOC_ID_ENEMY_NAME_95 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_95", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Night Mare. + /// + internal static string LOC_ID_ENEMY_NAME_96 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_96", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to My Little Pony. + /// + internal static string LOC_ID_ENEMY_NAME_97 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_97", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sparky. + /// + internal static string LOC_ID_ENEMY_NAME_98 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_98", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mr. Spark. + /// + internal static string LOC_ID_ENEMY_NAME_99 { + get { + return ResourceManager.GetString("LOC_ID_ENEMY_NAME_99", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Vault. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY_1 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Curse. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY_10 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Grace. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY_11 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Architect's Fee. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY_12 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to NG+ Bonus. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY_13 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sprint. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY_2 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Vampire. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY_3 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sky. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY_4 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Siphon. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY_5 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Balance. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY_6 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Retaliation. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY_7 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bounty. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY_8 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Haste. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY_9 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Vault. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY2_1 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY2_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Curse. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY2_10 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY2_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Grace. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY2_11 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY2_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Architect's Fee. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY2_12 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY2_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to NG+ Bonus. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY2_13 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY2_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sprint. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY2_2 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY2_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Vampire. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY2_3 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY2_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sky. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY2_4 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY2_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Siphon. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY2_5 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY2_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Balance. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY2_6 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY2_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Retaliation. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY2_7 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY2_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bounty. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY2_8 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY2_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Haste. + /// + internal static string LOC_ID_EQUIPMENT_ABILITY2_9 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_ABILITY2_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Squire. + /// + internal static string LOC_ID_EQUIPMENT_BASE_1 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Slayer. + /// + internal static string LOC_ID_EQUIPMENT_BASE_10 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sage. + /// + internal static string LOC_ID_EQUIPMENT_BASE_11 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Blood. + /// + internal static string LOC_ID_EQUIPMENT_BASE_12 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Retribution. + /// + internal static string LOC_ID_EQUIPMENT_BASE_13 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Holy. + /// + internal static string LOC_ID_EQUIPMENT_BASE_14 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dark. + /// + internal static string LOC_ID_EQUIPMENT_BASE_15 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Silver. + /// + internal static string LOC_ID_EQUIPMENT_BASE_2 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Guardian. + /// + internal static string LOC_ID_EQUIPMENT_BASE_3 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Imperial. + /// + internal static string LOC_ID_EQUIPMENT_BASE_4 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Royal. + /// + internal static string LOC_ID_EQUIPMENT_BASE_5 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Knight. + /// + internal static string LOC_ID_EQUIPMENT_BASE_6 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ranger. + /// + internal static string LOC_ID_EQUIPMENT_BASE_7 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sky. + /// + internal static string LOC_ID_EQUIPMENT_BASE_8 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dragon. + /// + internal static string LOC_ID_EQUIPMENT_BASE_9 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} {1}. + /// + internal static string LOC_ID_EQUIPMENT_BASE_FORMAT { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_BASE_FORMAT", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sword. + /// + internal static string LOC_ID_EQUIPMENT_CAT_1 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_CAT_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cape. + /// + internal static string LOC_ID_EQUIPMENT_CAT_2 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_CAT_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Limbs. + /// + internal static string LOC_ID_EQUIPMENT_CAT_3 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_CAT_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Helm. + /// + internal static string LOC_ID_EQUIPMENT_CAT_4 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_CAT_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Chest. + /// + internal static string LOC_ID_EQUIPMENT_CAT_5 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_CAT_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to None. + /// + internal static string LOC_ID_EQUIPMENT_CAT_6 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_CAT_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sword. + /// + internal static string LOC_ID_EQUIPMENT_CAT2_1 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_CAT2_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cape. + /// + internal static string LOC_ID_EQUIPMENT_CAT2_2 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_CAT2_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bracers. + /// + internal static string LOC_ID_EQUIPMENT_CAT2_3 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_CAT2_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Helm. + /// + internal static string LOC_ID_EQUIPMENT_CAT2_4 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_CAT2_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Chestplate. + /// + internal static string LOC_ID_EQUIPMENT_CAT2_5 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_CAT2_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to None. + /// + internal static string LOC_ID_EQUIPMENT_CAT2_6 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_CAT2_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Grants you the power to jump in the air. Multiple runes stack, allowing for multiple jumps.. + /// + internal static string LOC_ID_EQUIPMENT_DESC_1 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_DESC_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Harder enemies, but greater rewards. Multiple runes stack making enemies even harder.. + /// + internal static string LOC_ID_EQUIPMENT_DESC_10 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_DESC_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enemies scale slower, easier but lesser rewards. Multiple runes stack slowing enemy scaling more.. + /// + internal static string LOC_ID_EQUIPMENT_DESC_11 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_DESC_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gain the power to dash short distances. Multiple runes stack allowing for multiple dashes.. + /// + internal static string LOC_ID_EQUIPMENT_DESC_2 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_DESC_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Killing enemies will drain them of their health. Multiple runes stack for increased life drain.. + /// + internal static string LOC_ID_EQUIPMENT_DESC_3 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_DESC_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gain the power of flight. Multiple runes stack for longer flight duration.. + /// + internal static string LOC_ID_EQUIPMENT_DESC_4 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_DESC_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Steals mana from slain enemies. Multiple runes stack for increased mana drain.. + /// + internal static string LOC_ID_EQUIPMENT_DESC_5 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_DESC_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Slaying enemies grants both HP and MP. Multiple runes stack for increased hp/mp drain.. + /// + internal static string LOC_ID_EQUIPMENT_DESC_6 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_DESC_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Returns damage taken from enemies. Multiple runes stack increasing the damage return. + /// + internal static string LOC_ID_EQUIPMENT_DESC_7 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_DESC_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Increase the amount of gold you get from coins. Multiple runes stack for increased gold gain.. + /// + internal static string LOC_ID_EQUIPMENT_DESC_8 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_DESC_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Increase your base move speed. Multiple runes stack making you even faster.. + /// + internal static string LOC_ID_EQUIPMENT_DESC_9 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_DESC_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press. + /// + internal static string LOC_ID_EQUIPMENT_INST_1 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:10] while in air.. + /// + internal static string LOC_ID_EQUIPMENT_INST_1_NEW { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_1_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enemies are harder.. + /// + internal static string LOC_ID_EQUIPMENT_INST_10 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enemies scale slower.. + /// + internal static string LOC_ID_EQUIPMENT_INST_11 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to while in air.. + /// + internal static string LOC_ID_EQUIPMENT_INST_1b { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_1b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to or. + /// + internal static string LOC_ID_EQUIPMENT_INST_2 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:14] or [Input:15] to dash.. + /// + internal static string LOC_ID_EQUIPMENT_INST_2_NEW { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_2_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to dash.. + /// + internal static string LOC_ID_EQUIPMENT_INST_2b { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_2b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Kill enemies to regain health.. + /// + internal static string LOC_ID_EQUIPMENT_INST_3 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press. + /// + internal static string LOC_ID_EQUIPMENT_INST_4 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:10] while in air.. + /// + internal static string LOC_ID_EQUIPMENT_INST_4_NEW { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_4_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to while in air.. + /// + internal static string LOC_ID_EQUIPMENT_INST_4b { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_4b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Kill enemies to regain mana.. + /// + internal static string LOC_ID_EQUIPMENT_INST_5 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Kill enemies to regain health and mana.. + /// + internal static string LOC_ID_EQUIPMENT_INST_6 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Damage returned to enemies.. + /// + internal static string LOC_ID_EQUIPMENT_INST_7 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Coins give more gold.. + /// + internal static string LOC_ID_EQUIPMENT_INST_8 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Move faster.. + /// + internal static string LOC_ID_EQUIPMENT_INST_9 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_INST_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Critical Chance. + /// + internal static string LOC_ID_EQUIPMENT_SEC_1 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Air Dash. + /// + internal static string LOC_ID_EQUIPMENT_SEC_10 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Block. + /// + internal static string LOC_ID_EQUIPMENT_SEC_11 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Float. + /// + internal static string LOC_ID_EQUIPMENT_SEC_12 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Can attack projectiles. + /// + internal static string LOC_ID_EQUIPMENT_SEC_13 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Flight. + /// + internal static string LOC_ID_EQUIPMENT_SEC_14 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Move Speed. + /// + internal static string LOC_ID_EQUIPMENT_SEC_15 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to None. + /// + internal static string LOC_ID_EQUIPMENT_SEC_16 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Critical Damage. + /// + internal static string LOC_ID_EQUIPMENT_SEC_2 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Vampirism. + /// + internal static string LOC_ID_EQUIPMENT_SEC_3 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gold Bonus. + /// + internal static string LOC_ID_EQUIPMENT_SEC_4 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Siphon. + /// + internal static string LOC_ID_EQUIPMENT_SEC_5 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to XP Bonus. + /// + internal static string LOC_ID_EQUIPMENT_SEC_6 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to AirAttack. + /// + internal static string LOC_ID_EQUIPMENT_SEC_7 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Air Jump. + /// + internal static string LOC_ID_EQUIPMENT_SEC_8 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Damage Return. + /// + internal static string LOC_ID_EQUIPMENT_SEC_9 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SEC_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Air jump. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_1 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Air jump {0} times. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_1_NEW_A { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_1_NEW_A", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Air jump {0} time. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_1_NEW_B { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_1_NEW_B", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Earn 60% total gold in the castle.. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_10 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bounty increased by. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_11 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bounty increased by {0}%. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_11_NEW { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_11_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enemies start. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_12 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enemies start {0} levels higher. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_12_NEW { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_12_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to levels higher. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_12b { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_12b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enemies scale. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_13 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enemies scale {0} units slower. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_13_NEW_A { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_13_NEW_A", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enemies scale {0} unit slower. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_13_NEW_B { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_13_NEW_B", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to units slower. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_13b { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_13b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to unit slower. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_13c { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_13c", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to times. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_1b { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_1b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to time. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_1c { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_1c", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dash up to. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_2 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dash up to {0} times. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_2_NEW_A { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_2_NEW_A", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dash up to {0} time. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_2_NEW_B { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_2_NEW_B", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to times. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_2b { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_2b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to time. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_2c { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_2c", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gain back. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_3 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gain back {0} HP for every kill. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_3_NEW { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_3_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to hp for every kill. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_3b { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_3b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fly for. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_4 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fly for {0} seconds. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_4_NEW_A { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_4_NEW_A", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fly for {0} second. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_4_NEW_B { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_4_NEW_B", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to seconds. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_4b { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_4b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to second. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_4c { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_4c", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gain back. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_5 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gain back {0} MP for every kill. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_5_NEW { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_5_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to mp for every kill. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_5b { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_5b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mana HP. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_6 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Return. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_7 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Return {0}% damage after getting hit. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_7_NEW { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_7_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to % damage after getting hit. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_7b { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_7b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Each gold drop is. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_8 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Each gold drop is {0}% more valuable. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_8_NEW { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_8_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to % more valuable. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_8b { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_8b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Move. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_9 { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Move {0} % faster. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_9_NEW { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_9_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to % faster. + /// + internal static string LOC_ID_EQUIPMENT_SHORT_9b { + get { + return ResourceManager.GetString("LOC_ID_EQUIPMENT_SHORT_9b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Quit Rogue Legacy. + /// + internal static string LOC_ID_EXIT_ROGUE_LEGACY_OPTIONS_1 { + get { + return ResourceManager.GetString("LOC_ID_EXIT_ROGUE_LEGACY_OPTIONS_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press. + /// + internal static string LOC_ID_GAME_OVER_BOSS_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_BOSS_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:0] to move on. + /// + internal static string LOC_ID_GAME_OVER_BOSS_SCREEN_1_NEW { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_BOSS_SCREEN_1_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to move on. + /// + internal static string LOC_ID_GAME_OVER_BOSS_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_BOSS_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The sun... I had forgotten how it feels.... + /// + internal static string LOC_ID_GAME_OVER_BOSS_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_BOSS_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to s Parting Words. + /// + internal static string LOC_ID_GAME_OVER_BOSS_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_BOSS_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to has been slain by. + /// + internal static string LOC_ID_GAME_OVER_BOSS_SCREEN_5 { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_BOSS_SCREEN_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} has been slain by {1}. + /// + internal static string LOC_ID_GAME_OVER_BOSS_SCREEN_5_NEW { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_BOSS_SCREEN_5_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:0] to move on. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_1_NEW { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_1_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to move on. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to has been slain by. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} has been slain by {1}. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_3_NEW { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_3_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to has been slain by a. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} has been slain by a {1}. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_4_NEW { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_4_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to was done in by a projectile. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_5 { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} was done in by a projectile. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_5_NEW { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_5_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to slipped and was impaled by spikes. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_6 { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} slipped and was impaled by spikes. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_6_NEW { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_6_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to has been slain. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_7 { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} has been slain. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_7_NEW { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_7_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 's Parting Words. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_8 { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to -{0}'s Parting Words. + /// + internal static string LOC_ID_GAME_OVER_SCREEN_8_NEW { + get { + return ResourceManager.GetString("LOC_ID_GAME_OVER_SCREEN_8_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to continue. + /// + internal static string LOC_ID_GET_ITEM_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_GET_ITEM_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:0] to continue. + /// + internal static string LOC_ID_GET_ITEM_SCREEN_1_NEW { + get { + return ResourceManager.GetString("LOC_ID_GET_ITEM_SCREEN_1_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to HP Increased. + /// + internal static string LOC_ID_GET_ITEM_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_GET_ITEM_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MP Increased. + /// + internal static string LOC_ID_GET_ITEM_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_GET_ITEM_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Strength Increased. + /// + internal static string LOC_ID_GET_ITEM_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_GET_ITEM_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Magic Damage Increased. + /// + internal static string LOC_ID_GET_ITEM_SCREEN_5 { + get { + return ResourceManager.GetString("LOC_ID_GET_ITEM_SCREEN_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Armor Increased. + /// + internal static string LOC_ID_GET_ITEM_SCREEN_6 { + get { + return ResourceManager.GetString("LOC_ID_GET_ITEM_SCREEN_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Max Weight Load Increased. + /// + internal static string LOC_ID_GET_ITEM_SCREEN_7 { + get { + return ResourceManager.GetString("LOC_ID_GET_ITEM_SCREEN_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Medallion completed!. + /// + internal static string LOC_ID_GET_ITEM_SCREEN_8 { + get { + return ResourceManager.GetString("LOC_ID_GET_ITEM_SCREEN_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You've collected a medallion piece!. + /// + internal static string LOC_ID_GET_ITEM_SCREEN_9 { + get { + return ResourceManager.GetString("LOC_ID_GET_ITEM_SCREEN_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Forest is always to the right side of the Castle.. + /// + internal static string LOC_ID_HINT_1 { + get { + return ResourceManager.GetString("LOC_ID_HINT_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sky runes let you fly by pressing. + /// + internal static string LOC_ID_HINT_10 { + get { + return ResourceManager.GetString("LOC_ID_HINT_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sky runes let you fly by pressing [Input:10] while in the air.. + /// + internal static string LOC_ID_HINT_10_NEW { + get { + return ResourceManager.GetString("LOC_ID_HINT_10_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to while in the air.. + /// + internal static string LOC_ID_HINT_10b { + get { + return ResourceManager.GetString("LOC_ID_HINT_10b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Vampirism and Siphon runes are very powerful when stacked.. + /// + internal static string LOC_ID_HINT_11 { + get { + return ResourceManager.GetString("LOC_ID_HINT_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mastering mobility runes makes you awesome.. + /// + internal static string LOC_ID_HINT_12 { + get { + return ResourceManager.GetString("LOC_ID_HINT_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Make sure to expand your manor. You never know what new skills can be revealed.. + /// + internal static string LOC_ID_HINT_13 { + get { + return ResourceManager.GetString("LOC_ID_HINT_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to All classes can be upgraded with unique class abilities.. + /// + internal static string LOC_ID_HINT_14 { + get { + return ResourceManager.GetString("LOC_ID_HINT_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlocked class abilities can be activated with. + /// + internal static string LOC_ID_HINT_15 { + get { + return ResourceManager.GetString("LOC_ID_HINT_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlocked class abilities can be activated with [Input:13]. + /// + internal static string LOC_ID_HINT_15_NEW { + get { + return ResourceManager.GetString("LOC_ID_HINT_15_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upgrade your classes early to obtain powerful class abilities.. + /// + internal static string LOC_ID_HINT_16 { + get { + return ResourceManager.GetString("LOC_ID_HINT_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If you are having trouble with a room, see if you can bypass it instead.. + /// + internal static string LOC_ID_HINT_17 { + get { + return ResourceManager.GetString("LOC_ID_HINT_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Buying equipment is the fastest way to raise your stats.. + /// + internal static string LOC_ID_HINT_18 { + get { + return ResourceManager.GetString("LOC_ID_HINT_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Purchasing equipment is cheaper and more flexible than raising your base stats.. + /// + internal static string LOC_ID_HINT_19 { + get { + return ResourceManager.GetString("LOC_ID_HINT_19", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Maya is always at the top of the Castle.. + /// + internal static string LOC_ID_HINT_2 { + get { + return ResourceManager.GetString("LOC_ID_HINT_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You should have picked the other child.. + /// + internal static string LOC_ID_HINT_20 { + get { + return ResourceManager.GetString("LOC_ID_HINT_20", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Runes are very powerful. Equip runes at the Enchantress, and don't forget to use them!. + /// + internal static string LOC_ID_HINT_21 { + get { + return ResourceManager.GetString("LOC_ID_HINT_21", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Learn the nuances of your spell to maximize their potential.. + /// + internal static string LOC_ID_HINT_22 { + get { + return ResourceManager.GetString("LOC_ID_HINT_22", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Try to hit enemies near the apex of the axe's arc in order to hit them multiple times.. + /// + internal static string LOC_ID_HINT_23 { + get { + return ResourceManager.GetString("LOC_ID_HINT_23", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Avoid picking up the conflux orbs after casting it to maximize damage.. + /// + internal static string LOC_ID_HINT_24 { + get { + return ResourceManager.GetString("LOC_ID_HINT_24", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dodge the chakrams return trip in order to maximize its damage.. + /// + internal static string LOC_ID_HINT_25 { + get { + return ResourceManager.GetString("LOC_ID_HINT_25", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Better to use mana to kill enemies than to take unnecessary damage.. + /// + internal static string LOC_ID_HINT_26 { + get { + return ResourceManager.GetString("LOC_ID_HINT_26", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Learning enemy 'tells' is integral to surviving the castle.. + /// + internal static string LOC_ID_HINT_27 { + get { + return ResourceManager.GetString("LOC_ID_HINT_27", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spike traps check for a pulse to tell the dead from the living.. + /// + internal static string LOC_ID_HINT_28 { + get { + return ResourceManager.GetString("LOC_ID_HINT_28", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press. + /// + internal static string LOC_ID_HINT_29 { + get { + return ResourceManager.GetString("LOC_ID_HINT_29", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:9] to open the map.. + /// + internal static string LOC_ID_HINT_29_NEW { + get { + return ResourceManager.GetString("LOC_ID_HINT_29_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to open the map.. + /// + internal static string LOC_ID_HINT_29b { + get { + return ResourceManager.GetString("LOC_ID_HINT_29b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Darkness is always at the bottom of the Castle.. + /// + internal static string LOC_ID_HINT_3 { + get { + return ResourceManager.GetString("LOC_ID_HINT_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fairy chests hold all the runes in the game. Runes will help you immensely.. + /// + internal static string LOC_ID_HINT_30 { + get { + return ResourceManager.GetString("LOC_ID_HINT_30", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If you fail a Fairy chest room, the Architect can give you a second chance.. + /// + internal static string LOC_ID_HINT_31 { + get { + return ResourceManager.GetString("LOC_ID_HINT_31", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Architect has a hefty fee for those who use his service.. + /// + internal static string LOC_ID_HINT_32 { + get { + return ResourceManager.GetString("LOC_ID_HINT_32", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bosses drop large amounts of gold on their death.. + /// + internal static string LOC_ID_HINT_33 { + get { + return ResourceManager.GetString("LOC_ID_HINT_33", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bury me with my money.. + /// + internal static string LOC_ID_HINT_34 { + get { + return ResourceManager.GetString("LOC_ID_HINT_34", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If you are having trouble, try equipping Grace runes.. + /// + internal static string LOC_ID_HINT_35 { + get { + return ResourceManager.GetString("LOC_ID_HINT_35", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to In options you can enable Quick Drop to downstrike and drop with. + /// + internal static string LOC_ID_HINT_36 { + get { + return ResourceManager.GetString("LOC_ID_HINT_36", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to In options you can enable Quick Drop to downstrike and drop with [Input:18]. + /// + internal static string LOC_ID_HINT_36_NEW { + get { + return ResourceManager.GetString("LOC_ID_HINT_36_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The architect is very useful for practicing against bosses.. + /// + internal static string LOC_ID_HINT_37 { + get { + return ResourceManager.GetString("LOC_ID_HINT_37", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The third row of equipment usually has major tradeoffs. Be careful.. + /// + internal static string LOC_ID_HINT_38 { + get { + return ResourceManager.GetString("LOC_ID_HINT_38", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Certain runes work better with certain bosses.. + /// + internal static string LOC_ID_HINT_39 { + get { + return ResourceManager.GetString("LOC_ID_HINT_39", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If you're having trouble with a boss, try using different runes.. + /// + internal static string LOC_ID_HINT_4 { + get { + return ResourceManager.GetString("LOC_ID_HINT_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You should practice fighting bosses using the architect.. + /// + internal static string LOC_ID_HINT_40 { + get { + return ResourceManager.GetString("LOC_ID_HINT_40", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Health is a very important stat to raise.. + /// + internal static string LOC_ID_HINT_41 { + get { + return ResourceManager.GetString("LOC_ID_HINT_41", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Retribution runes can damage invulnerable objects.. + /// + internal static string LOC_ID_HINT_42 { + get { + return ResourceManager.GetString("LOC_ID_HINT_42", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Class abilities are very powerful if used correctly.. + /// + internal static string LOC_ID_HINT_43 { + get { + return ResourceManager.GetString("LOC_ID_HINT_43", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Some classes have advantages over certain bosses.. + /// + internal static string LOC_ID_HINT_44 { + get { + return ResourceManager.GetString("LOC_ID_HINT_44", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Vault runes let you to jump in the air with. + /// + internal static string LOC_ID_HINT_5 { + get { + return ResourceManager.GetString("LOC_ID_HINT_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Vault runes let you to jump in the air with [Input:10]. + /// + internal static string LOC_ID_HINT_5_NEW { + get { + return ResourceManager.GetString("LOC_ID_HINT_5_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sprint runes let you dash with [Input:PLAYER_DASHLEFT] or [Input:PLAYER_DASHRIGHT]. + /// + internal static string LOC_ID_HINT_6 { + get { + return ResourceManager.GetString("LOC_ID_HINT_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to or. + /// + internal static string LOC_ID_HINT_6b { + get { + return ResourceManager.GetString("LOC_ID_HINT_6b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Each class has pros and cons. Make sure to change your playstyle accordingly.. + /// + internal static string LOC_ID_HINT_7 { + get { + return ResourceManager.GetString("LOC_ID_HINT_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Exploring and finding chests is the best way to earn gold.. + /// + internal static string LOC_ID_HINT_8 { + get { + return ResourceManager.GetString("LOC_ID_HINT_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Harder areas offer greater rewards.. + /// + internal static string LOC_ID_HINT_9 { + get { + return ResourceManager.GetString("LOC_ID_HINT_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to My duties are to my family.... + /// + internal static string LOC_ID_INTRO_ROOM_OBJ_1 { + get { + return ResourceManager.GetString("LOC_ID_INTRO_ROOM_OBJ_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to But I am loyal only to myself.. + /// + internal static string LOC_ID_INTRO_ROOM_OBJ_2 { + get { + return ResourceManager.GetString("LOC_ID_INTRO_ROOM_OBJ_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to gold. + /// + internal static string LOC_ID_ITEM_DROP_OBJ_1 { + get { + return ResourceManager.GetString("LOC_ID_ITEM_DROP_OBJ_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to hp recovered. + /// + internal static string LOC_ID_ITEM_DROP_OBJ_2 { + get { + return ResourceManager.GetString("LOC_ID_ITEM_DROP_OBJ_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to mp recovered. + /// + internal static string LOC_ID_ITEM_DROP_OBJ_3 { + get { + return ResourceManager.GetString("LOC_ID_ITEM_DROP_OBJ_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Armor Up. + /// + internal static string LOC_ID_ITEM_DROP_OBJ_4 { + get { + return ResourceManager.GetString("LOC_ID_ITEM_DROP_OBJ_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Max Health Up. + /// + internal static string LOC_ID_ITEM_DROP_OBJ_5 { + get { + return ResourceManager.GetString("LOC_ID_ITEM_DROP_OBJ_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Max Mana Up. + /// + internal static string LOC_ID_ITEM_DROP_OBJ_6 { + get { + return ResourceManager.GetString("LOC_ID_ITEM_DROP_OBJ_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Attack Up. + /// + internal static string LOC_ID_ITEM_DROP_OBJ_7 { + get { + return ResourceManager.GetString("LOC_ID_ITEM_DROP_OBJ_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Magic Up. + /// + internal static string LOC_ID_ITEM_DROP_OBJ_8 { + get { + return ResourceManager.GetString("LOC_ID_ITEM_DROP_OBJ_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Max Weight Up. + /// + internal static string LOC_ID_ITEM_DROP_OBJ_9 { + get { + return ResourceManager.GetString("LOC_ID_ITEM_DROP_OBJ_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Now Playing. + /// + internal static string LOC_ID_JUKEBOX_BONUS_ROOM_1 { + get { + return ResourceManager.GetString("LOC_ID_JUKEBOX_BONUS_ROOM_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Now Entering. + /// + internal static string LOC_ID_LEVEL_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_LEVEL_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fairy Chest Objective:. + /// + internal static string LOC_ID_LEVEL_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_LEVEL_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reach the chest in 15 seconds:. + /// + internal static string LOC_ID_LEVEL_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_LEVEL_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Time Remaining:. + /// + internal static string LOC_ID_LEVEL_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_LEVEL_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Objective Complete!. + /// + internal static string LOC_ID_LEVEL_SCREEN_5 { + get { + return ResourceManager.GetString("LOC_ID_LEVEL_SCREEN_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Objective Failed. + /// + internal static string LOC_ID_LEVEL_SCREEN_6 { + get { + return ResourceManager.GetString("LOC_ID_LEVEL_SCREEN_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No Traits. + /// + internal static string LOC_ID_LINEAGE_OBJ_1 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Heroic. + /// + internal static string LOC_ID_LINEAGE_OBJ_10 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Heroic {0}. + /// + internal static string LOC_ID_LINEAGE_OBJ_10_NEW { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_10_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Divine. + /// + internal static string LOC_ID_LINEAGE_OBJ_11 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Divine {0}. + /// + internal static string LOC_ID_LINEAGE_OBJ_11_NEW { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_11_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sir. + /// + internal static string LOC_ID_LINEAGE_OBJ_12 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sir {0} {1}. + /// + internal static string LOC_ID_LINEAGE_OBJ_12_NEW { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_12_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sir Hero. + /// + internal static string LOC_ID_LINEAGE_OBJ_13 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lady. + /// + internal static string LOC_ID_LINEAGE_OBJ_14 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lady {0} {1}. + /// + internal static string LOC_ID_LINEAGE_OBJ_14_NEW { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_14_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lady Heroine. + /// + internal static string LOC_ID_LINEAGE_OBJ_15 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to the. + /// + internal static string LOC_ID_LINEAGE_OBJ_2_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_2_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to the. + /// + internal static string LOC_ID_LINEAGE_OBJ_2_MALE { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_2_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Legendary. + /// + internal static string LOC_ID_LINEAGE_OBJ_3 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Legendary {0}. + /// + internal static string LOC_ID_LINEAGE_OBJ_3_NEW { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_3_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Useless. + /// + internal static string LOC_ID_LINEAGE_OBJ_4 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Useless {0}. + /// + internal static string LOC_ID_LINEAGE_OBJ_4_NEW { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_4_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Feeble. + /// + internal static string LOC_ID_LINEAGE_OBJ_5 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Feeble {0}. + /// + internal static string LOC_ID_LINEAGE_OBJ_5_NEW { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_5_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Determined. + /// + internal static string LOC_ID_LINEAGE_OBJ_6 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Determined {0}. + /// + internal static string LOC_ID_LINEAGE_OBJ_6_NEW { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_6_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stout. + /// + internal static string LOC_ID_LINEAGE_OBJ_7 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stout {0}. + /// + internal static string LOC_ID_LINEAGE_OBJ_7_NEW { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_7_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gallant. + /// + internal static string LOC_ID_LINEAGE_OBJ_8 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gallant {0}. + /// + internal static string LOC_ID_LINEAGE_OBJ_8_NEW { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_8_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Valiant. + /// + internal static string LOC_ID_LINEAGE_OBJ_9 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Valiant {0}. + /// + internal static string LOC_ID_LINEAGE_OBJ_9_NEW { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_OBJ_9_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to select a child. + /// + internal static string LOC_ID_LINEAGE_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:0] to select a child. + /// + internal static string LOC_ID_LINEAGE_SCREEN_1_NEW { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_SCREEN_1_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to view family tree. + /// + internal static string LOC_ID_LINEAGE_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Button:LeftStick] to view family tree. + /// + internal static string LOC_ID_LINEAGE_SCREEN_2_NEW { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_SCREEN_2_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Arrow keys to view family tree. + /// + internal static string LOC_ID_LINEAGE_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to re-roll your children once. + /// + internal static string LOC_ID_LINEAGE_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:9] to re-roll your children once. + /// + internal static string LOC_ID_LINEAGE_SCREEN_4_NEW { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_SCREEN_4_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Class. + /// + internal static string LOC_ID_LINEAGE_SCREEN_5 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_SCREEN_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Trait. + /// + internal static string LOC_ID_LINEAGE_SCREEN_6 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_SCREEN_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Traits – None. + /// + internal static string LOC_ID_LINEAGE_SCREEN_7 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_SCREEN_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spell. + /// + internal static string LOC_ID_LINEAGE_SCREEN_8 { + get { + return ResourceManager.GetString("LOC_ID_LINEAGE_SCREEN_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Building. + /// + internal static string LOC_ID_LOADING_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_LOADING_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Balding. + /// + internal static string LOC_ID_LOADING_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_LOADING_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reminiscing. + /// + internal static string LOC_ID_LOADING_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_LOADING_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Jacking In. + /// + internal static string LOC_ID_LOADING_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_LOADING_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to close map. + /// + internal static string LOC_ID_MAP_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:9] to close map. + /// + internal static string LOC_ID_MAP_SCREEN_1_NEW { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_1_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Opened chest. + /// + internal static string LOC_ID_MAP_SCREEN_10 { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Teleporter. + /// + internal static string LOC_ID_MAP_SCREEN_11 { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bonus Room. + /// + internal static string LOC_ID_MAP_SCREEN_12 { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to center on player. + /// + internal static string LOC_ID_MAP_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:0] to center on player. + /// + internal static string LOC_ID_MAP_SCREEN_2_NEW { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_2_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use arrow keys to move map. + /// + internal static string LOC_ID_MAP_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to move map. + /// + internal static string LOC_ID_MAP_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Button:LeftStick] to move map. + /// + internal static string LOC_ID_MAP_SCREEN_4_NEW { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_4_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Legend. + /// + internal static string LOC_ID_MAP_SCREEN_5 { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are here. + /// + internal static string LOC_ID_MAP_SCREEN_6 { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Boss location. + /// + internal static string LOC_ID_MAP_SCREEN_7 { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unopened chest. + /// + internal static string LOC_ID_MAP_SCREEN_8 { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fairy chest. + /// + internal static string LOC_ID_MAP_SCREEN_9 { + get { + return ResourceManager.GetString("LOC_ID_MAP_SCREEN_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Music Volume. + /// + internal static string LOC_ID_MUSICVOL_OPTIONS_1 { + get { + return ResourceManager.GetString("LOC_ID_MUSICVOL_OPTIONS_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Chinese. + /// + internal static string LOC_ID_OPTIONS_LANGUAGE_CHINESE { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_LANGUAGE_CHINESE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to English. + /// + internal static string LOC_ID_OPTIONS_LANGUAGE_ENGLISH { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_LANGUAGE_ENGLISH", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to French. + /// + internal static string LOC_ID_OPTIONS_LANGUAGE_FRENCH { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_LANGUAGE_FRENCH", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to German. + /// + internal static string LOC_ID_OPTIONS_LANGUAGE_GERMAN { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_LANGUAGE_GERMAN", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Polish. + /// + internal static string LOC_ID_OPTIONS_LANGUAGE_POLISH { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_LANGUAGE_POLISH", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Portuguese (Brazil). + /// + internal static string LOC_ID_OPTIONS_LANGUAGE_PORTUGUESE { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_LANGUAGE_PORTUGUESE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Russian. + /// + internal static string LOC_ID_OPTIONS_LANGUAGE_RUSSIAN { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_LANGUAGE_RUSSIAN", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spanish (Spain). + /// + internal static string LOC_ID_OPTIONS_LANGUAGE_SPANISH { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_LANGUAGE_SPANISH", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Language. + /// + internal static string LOC_ID_OPTIONS_LANGUAGE_TITLE { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_LANGUAGE_TITLE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to *Quick drop allows you to drop down ledges and down-attack in \nthe air by pressing the DOWN button. + /// + internal static string LOC_ID_OPTIONS_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Resolution. + /// + internal static string LOC_ID_OPTIONS_SCREEN_10 { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fullscreen. + /// + internal static string LOC_ID_OPTIONS_SCREEN_11 { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reduce Shader Quality. + /// + internal static string LOC_ID_OPTIONS_SCREEN_12 { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use Dinput Gamepads. + /// + internal static string LOC_ID_OPTIONS_SCREEN_13 { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enable Steam Cloud. + /// + internal static string LOC_ID_OPTIONS_SCREEN_14 { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to navigate options. + /// + internal static string LOC_ID_OPTIONS_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Button:LeftStick] to navigate options. + /// + internal static string LOC_ID_OPTIONS_SCREEN_2_NEW { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_2_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Arrow keys to navigate options. + /// + internal static string LOC_ID_OPTIONS_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to select option. + /// + internal static string LOC_ID_OPTIONS_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:0] to select option. + /// + internal static string LOC_ID_OPTIONS_SCREEN_4_NEW { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_4_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to exit options. + /// + internal static string LOC_ID_OPTIONS_SCREEN_5 { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:2] to exit options. + /// + internal static string LOC_ID_OPTIONS_SCREEN_5_NEW { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_5_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Screen Size. + /// + internal static string LOC_ID_OPTIONS_SCREEN_6 { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Help. + /// + internal static string LOC_ID_OPTIONS_SCREEN_7 { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to *The game must be restarted for this change to come into effect.. + /// + internal static string LOC_ID_OPTIONS_SCREEN_8 { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to *Cloud support must be enabled on the Steam platform as well for\nthis feature to work.. + /// + internal static string LOC_ID_OPTIONS_SCREEN_9 { + get { + return ResourceManager.GetString("LOC_ID_OPTIONS_SCREEN_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Class: . + /// + internal static string LOC_ID_PAUSE_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_PAUSE_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Strength: . + /// + internal static string LOC_ID_PAUSE_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_PAUSE_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Magic: . + /// + internal static string LOC_ID_PAUSE_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_PAUSE_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Armor: . + /// + internal static string LOC_ID_PAUSE_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_PAUSE_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Level: . + /// + internal static string LOC_ID_PAUSE_SCREEN_5 { + get { + return ResourceManager.GetString("LOC_ID_PAUSE_SCREEN_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Health: . + /// + internal static string LOC_ID_PAUSE_SCREEN_6 { + get { + return ResourceManager.GetString("LOC_ID_PAUSE_SCREEN_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Xbox One Wireless Controller disconnected. Reconnect it.. + /// + internal static string LOC_ID_PAUSE_SCREEN_7 { + get { + return ResourceManager.GetString("LOC_ID_PAUSE_SCREEN_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ?????. + /// + internal static string LOC_ID_PAUSE_SCREEN_8 { + get { + return ResourceManager.GetString("LOC_ID_PAUSE_SCREEN_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to gold. + /// + internal static string LOC_ID_PLAYER_OBJ_1 { + get { + return ResourceManager.GetString("LOC_ID_PLAYER_OBJ_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to max mp. + /// + internal static string LOC_ID_PLAYER_OBJ_2 { + get { + return ResourceManager.GetString("LOC_ID_PLAYER_OBJ_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to max hp. + /// + internal static string LOC_ID_PLAYER_OBJ_3 { + get { + return ResourceManager.GetString("LOC_ID_PLAYER_OBJ_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Max MP Converted. Need higher level.. + /// + internal static string LOC_ID_PLAYER_OBJ_4 { + get { + return ResourceManager.GetString("LOC_ID_PLAYER_OBJ_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Full Metal Furies\nDevelopment Time: 4 years.\nRelease Date: January 17, 2018. + /// + internal static string LOC_ID_PORTRAIT_TEXT_NEW_1 { + get { + return ResourceManager.GetString("LOC_ID_PORTRAIT_TEXT_NEW_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Full Metal Furies is from the future! It’s our follow-up game after Rogue Legacy, and the tenth game we’ve ever made. . + /// + internal static string LOC_ID_PORTRAIT_TEXT_NEW_2 { + get { + return ResourceManager.GetString("LOC_ID_PORTRAIT_TEXT_NEW_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to After RL, we promised ourselves we would never make a game without planning it out ever again. We lied. Curse you past-selves! . + /// + internal static string LOC_ID_PORTRAIT_TEXT_NEW_3 { + get { + return ResourceManager.GetString("LOC_ID_PORTRAIT_TEXT_NEW_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The game ended up becoming one of our most ambitious projects ever, and was a mishmash of a brawler/multiplayer/meta-puzzle/coming-of-age disco ideas that turned the traditional view a brawler on its head the longer you played. . + /// + internal static string LOC_ID_PORTRAIT_TEXT_NEW_4 { + get { + return ResourceManager.GetString("LOC_ID_PORTRAIT_TEXT_NEW_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to At 4 years, FMF is the longest time we’ve ever spent on development, and sadly also has some of lowest returns we've seen for our games. (Excluding those iOS games which generated negative bucks, curse you past-selves!) . + /// + internal static string LOC_ID_PORTRAIT_TEXT_NEW_5 { + get { + return ResourceManager.GetString("LOC_ID_PORTRAIT_TEXT_NEW_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to But we’re still immensely proud of what we created, and even more proud of the FRIENDS WE MADE ALONG THE WAY. AWWWWWWW!!! . + /// + internal static string LOC_ID_PORTRAIT_TEXT_NEW_6 { + get { + return ResourceManager.GetString("LOC_ID_PORTRAIT_TEXT_NEW_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Is choosing an heir.. + /// + internal static string LOC_ID_PRESENCE_1 { + get { + return ResourceManager.GetString("LOC_ID_PRESENCE_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to has gas.. + /// + internal static string LOC_ID_PRESENCE_10 { + get { + return ResourceManager.GetString("LOC_ID_PRESENCE_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Is bald.. + /// + internal static string LOC_ID_PRESENCE_11 { + get { + return ResourceManager.GetString("LOC_ID_PRESENCE_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Is exploring the Castle. + /// + internal static string LOC_ID_PRESENCE_2 { + get { + return ResourceManager.GetString("LOC_ID_PRESENCE_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Is exploring the Tower. + /// + internal static string LOC_ID_PRESENCE_3 { + get { + return ResourceManager.GetString("LOC_ID_PRESENCE_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Is exploring the Forest. + /// + internal static string LOC_ID_PRESENCE_4 { + get { + return ResourceManager.GetString("LOC_ID_PRESENCE_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Is exploring the Dungeon. + /// + internal static string LOC_ID_PRESENCE_5 { + get { + return ResourceManager.GetString("LOC_ID_PRESENCE_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Is fighting [x]. + /// + internal static string LOC_ID_PRESENCE_6 { + get { + return ResourceManager.GetString("LOC_ID_PRESENCE_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Is in a climactic final battle. + /// + internal static string LOC_ID_PRESENCE_7 { + get { + return ResourceManager.GetString("LOC_ID_PRESENCE_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Is watching the ending.. + /// + internal static string LOC_ID_PRESENCE_8 { + get { + return ResourceManager.GetString("LOC_ID_PRESENCE_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Is afraid of chickens.. + /// + internal static string LOC_ID_PRESENCE_9 { + get { + return ResourceManager.GetString("LOC_ID_PRESENCE_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Health. + /// + internal static string LOC_ID_PROFILE_CARD_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_CARD_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enchantments. + /// + internal static string LOC_ID_PROFILE_CARD_SCREEN_10 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_CARD_SCREEN_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to exit. + /// + internal static string LOC_ID_PROFILE_CARD_SCREEN_11 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_CARD_SCREEN_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:2] to exit. + /// + internal static string LOC_ID_PROFILE_CARD_SCREEN_11_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_CARD_SCREEN_11_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lv.. + /// + internal static string LOC_ID_PROFILE_CARD_SCREEN_12 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_CARD_SCREEN_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mana. + /// + internal static string LOC_ID_PROFILE_CARD_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_CARD_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Armor. + /// + internal static string LOC_ID_PROFILE_CARD_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_CARD_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Weight. + /// + internal static string LOC_ID_PROFILE_CARD_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_CARD_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Strength. + /// + internal static string LOC_ID_PROFILE_CARD_SCREEN_5 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_CARD_SCREEN_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Intelligence. + /// + internal static string LOC_ID_PROFILE_CARD_SCREEN_6 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_CARD_SCREEN_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Crit. Chance. + /// + internal static string LOC_ID_PROFILE_CARD_SCREEN_7 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_CARD_SCREEN_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Crit. Damage. + /// + internal static string LOC_ID_PROFILE_CARD_SCREEN_8 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_CARD_SCREEN_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Equipment. + /// + internal static string LOC_ID_PROFILE_CARD_SCREEN_9 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_CARD_SCREEN_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 100% Base stats.. + /// + internal static string LOC_ID_PROFILE_DESC_1 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SPECIAL: Barbarian Shout.\nHuge HP. Low Str and MP.. + /// + internal static string LOC_ID_PROFILE_DESC_10 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Huge Str, but you cannot land critical strikes.. + /// + internal static string LOC_ID_PROFILE_DESC_11 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Huge Str, but you cannot land critical strikes.\n+{0}% Move Speed. Low HP and MP.. + /// + internal static string LOC_ID_PROFILE_DESC_11_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_11_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to % Move Speed. Low HP and MP.. + /// + internal static string LOC_ID_PROFILE_DESC_11b { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_11b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SPECIAL: Replacement Technique.\nHuge Str, but you cannot land critical strikes.. + /// + internal static string LOC_ID_PROFILE_DESC_12 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SPECIAL: Replacement Technique.\nHuge Str, but you cannot land critical strikes.\n+{0}% Move Speed. Low HP and MP.. + /// + internal static string LOC_ID_PROFILE_DESC_12_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_12_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to % Move Speed. Low HP and MP.. + /// + internal static string LOC_ID_PROFILE_DESC_12b { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_12b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to % of damage dealt is converted into mana.\nLow Str, HP, and MP.. + /// + internal static string LOC_ID_PROFILE_DESC_13 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}% of damage dealt is converted into mana.\nLow Str, HP, and MP.. + /// + internal static string LOC_ID_PROFILE_DESC_13_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_13_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SPECIAL: Empowered Spell.. + /// + internal static string LOC_ID_PROFILE_DESC_14 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SPECIAL: Empowered Spell.\n{0}% of damage dealt is converted into mana.\nLow Str, HP, and MP.. + /// + internal static string LOC_ID_PROFILE_DESC_14_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_14_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to % of damage dealt is converted into mana.\nLow Str, HP, and MP.. + /// + internal static string LOC_ID_PROFILE_DESC_14b { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_14b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Kills are coverted into max HP.\nVery low Str, HP and MP. High Int.. + /// + internal static string LOC_ID_PROFILE_DESC_15 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SPECIAL: HP Conversion.\nKills are coverted into max HP.\nVery low Str, HP and MP. High Int.. + /// + internal static string LOC_ID_PROFILE_DESC_16 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are a man-dragon. + /// + internal static string LOC_ID_PROFILE_DESC_17 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ?????. + /// + internal static string LOC_ID_PROFILE_DESC_18 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SPECIAL: Guardian's Shield.\n100% Base stats.. + /// + internal static string LOC_ID_PROFILE_DESC_2 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to % Crit. Chance. + /// + internal static string LOC_ID_PROFILE_DESC_3 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to +{0}% Crit. Chance, +{1}% Crit. Damage.\nLow HP, MP, and Str.. + /// + internal static string LOC_ID_PROFILE_DESC_3_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_3_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to % Crit. Damage.\nLow HP, MP, and Str.. + /// + internal static string LOC_ID_PROFILE_DESC_3b { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_3b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SPECIAL: Mist Form. + /// + internal static string LOC_ID_PROFILE_DESC_4 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SPECIAL: Mist Form\n+{0}% Crit.Chance, +{1}% Crit. Damage.\nLow HP, MP, and Str.. + /// + internal static string LOC_ID_PROFILE_DESC_4_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_4_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to % Crit. Chance. + /// + internal static string LOC_ID_PROFILE_DESC_4b { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_4b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to % Crit. Damage.\nLow HP, MP, and Str.. + /// + internal static string LOC_ID_PROFILE_DESC_4c { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_4c", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to % Gold gain.\nVery weak in all other stats.. + /// + internal static string LOC_ID_PROFILE_DESC_5 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to +{0}% Gold gain.\nVery weak in all other stats.. + /// + internal static string LOC_ID_PROFILE_DESC_5_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_5_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SPECIAL: Ordinary Headlamp.. + /// + internal static string LOC_ID_PROFILE_DESC_6 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SPECIAL: Ordinary Headlamp.\n+{0}% Gold gain.\nVery weak in all other stats.. + /// + internal static string LOC_ID_PROFILE_DESC_6_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_6_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to % Gold gain.\nVery weak in all other stats.. + /// + internal static string LOC_ID_PROFILE_DESC_6b { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_6b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Every kill gives you. + /// + internal static string LOC_ID_PROFILE_DESC_7 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Every kill gives you {0} mana.\nLow Str and HP. High Int and MP.. + /// + internal static string LOC_ID_PROFILE_DESC_7_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_7_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to mana.\nLow Str and HP. High Int and MP.. + /// + internal static string LOC_ID_PROFILE_DESC_7b { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_7b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SPECIAL: Spell Cycle.\nEvery kill gives you. + /// + internal static string LOC_ID_PROFILE_DESC_8 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SPECIAL: Spell Cycle.\nEvery kill gives you {0} mana.\nLow Str and HP. High Int and MP.. + /// + internal static string LOC_ID_PROFILE_DESC_8_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_8_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to mana.\nLow Str and HP. High Int and MP.. + /// + internal static string LOC_ID_PROFILE_DESC_8b { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_8b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Huge HP. Low Str and MP.. + /// + internal static string LOC_ID_PROFILE_DESC_9 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_DESC_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to - START NEW LEGACY -. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to NG+. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_10 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to navigate. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Button:LeftStick] to navigate. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_2_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_2_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Arrow keys to navigate profiles. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to select. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:0] to select. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_4_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_4_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to exit. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_5 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:2] to exit. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_5_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_5_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to delete. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_6 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:26] to delete. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_6_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_6_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to the. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_7_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_7_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} the {1}. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_7_FEMALE_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_7_FEMALE_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to the. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_7_MALE { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_7_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} the {1}. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_7_MALE_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_7_MALE_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to the Deceased. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_8_FEMALE { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_8_FEMALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} the Deceased. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_8_FEMALE_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_8_FEMALE_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to the Deceased. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_8_MALE { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_8_MALE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} the Deceased. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_8_MALE_NEW { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_8_MALE_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lvl.. + /// + internal static string LOC_ID_PROFILE_SEL_SCREEN_9 { + get { + return ResourceManager.GetString("LOC_ID_PROFILE_SEL_SCREEN_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enable Quick Drop. + /// + internal static string LOC_ID_QUICKDROP_OPTIONS_1 { + get { + return ResourceManager.GetString("LOC_ID_QUICKDROP_OPTIONS_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No. + /// + internal static string LOC_ID_QUICKDROP_OPTIONS_2 { + get { + return ResourceManager.GetString("LOC_ID_QUICKDROP_OPTIONS_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Yes. + /// + internal static string LOC_ID_QUICKDROP_OPTIONS_3 { + get { + return ResourceManager.GetString("LOC_ID_QUICKDROP_OPTIONS_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} {1}. + /// + internal static string LOC_ID_RUNE_BASE_FORMAT { + get { + return ResourceManager.GetString("LOC_ID_RUNE_BASE_FORMAT", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save data is corrupted. The save data will now be deleted.. + /// + internal static string LOC_ID_SAVING_1 { + get { + return ResourceManager.GetString("LOC_ID_SAVING_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save data ownership conflict. Save data will be reset and game progress will be lost.. + /// + internal static string LOC_ID_SAVING_2 { + get { + return ResourceManager.GetString("LOC_ID_SAVING_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There is not enough free space on the system storage. At least %i KB more free space is needed. Delete other save data and retry?. + /// + internal static string LOC_ID_SAVING_3 { + get { + return ResourceManager.GetString("LOC_ID_SAVING_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Do you want to retry saving?. + /// + internal static string LOC_ID_SAVING_4 { + get { + return ResourceManager.GetString("LOC_ID_SAVING_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Do not turn off the PlayStation®Vita system while the following icon is displayed on screen. + /// + internal static string LOC_ID_SAVING_5 { + get { + return ResourceManager.GetString("LOC_ID_SAVING_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Do not turn off the PlayStation®3 system while the following icon is displayed on screen. + /// + internal static string LOC_ID_SAVING_6 { + get { + return ResourceManager.GetString("LOC_ID_SAVING_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Do not turn off the PlayStation®4 system while the following icon is displayed on screen. + /// + internal static string LOC_ID_SAVING_7 { + get { + return ResourceManager.GetString("LOC_ID_SAVING_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_SAVING_8 { + get { + return ResourceManager.GetString("LOC_ID_SAVING_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your progress will not be saved unless you sign-in.. + /// + internal static string LOC_ID_SAVING_9 { + get { + return ResourceManager.GetString("LOC_ID_SAVING_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SFX Volume. + /// + internal static string LOC_ID_SFXVOL_OPTIONS_1 { + get { + return ResourceManager.GetString("LOC_ID_SFXVOL_OPTIONS_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Improve your cardio workout. A better heart means better health.. + /// + internal static string LOC_ID_SKILL_DESC_1 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlock the smithy and gain access to phat loot.. + /// + internal static string LOC_ID_SKILL_DESC_10 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlock the enchantress and gain access to her magical runes and powers.. + /// + internal static string LOC_ID_SKILL_DESC_11 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlock the architect and gain the powers to lock down the castle.. + /// + internal static string LOC_ID_SKILL_DESC_12 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upgrading your carry capacity will allow you to wear better and heavier armor.. + /// + internal static string LOC_ID_SKILL_DESC_13 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Strengthen your innards through natural means to reduce incoming damage.. + /// + internal static string LOC_ID_SKILL_DESC_14 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Improve your looting skills, and get more bang for your buck.. + /// + internal static string LOC_ID_SKILL_DESC_15 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lower Charon's toll by learning how to barter with death itself.. + /// + internal static string LOC_ID_SKILL_DESC_16 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gut cleansing leads to noticable improvements from both potions and meat.. + /// + internal static string LOC_ID_SKILL_DESC_17 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use the power of science to make a whole new batch of babies. Just... don't ask.. + /// + internal static string LOC_ID_SKILL_DESC_18 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Release the power of the Lich! A being of massive potential.. + /// + internal static string LOC_ID_SKILL_DESC_19 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_19", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Strengthen your adrenal glands and be invulnerable like Bane. Let the games begin!. + /// + internal static string LOC_ID_SKILL_DESC_2 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlock the skills of the Miner and raise your family fortune.. + /// + internal static string LOC_ID_SKILL_DESC_20 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_20", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlock the Spellthief, and become a martial mage.. + /// + internal static string LOC_ID_SKILL_DESC_21 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_21", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlock the Shinobi, the fleetest of fighters.. + /// + internal static string LOC_ID_SKILL_DESC_22 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_22", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Practice your basics to reduce mana costs when casting spells.. + /// + internal static string LOC_ID_SKILL_DESC_23 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_23", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Turn your knights into Paladins. A ferocious forefront fighter.. + /// + internal static string LOC_ID_SKILL_DESC_24 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_24", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlock the latent powers of the Mage and transform them into the all powerful Archmage.. + /// + internal static string LOC_ID_SKILL_DESC_25 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_25", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Learn the dark arts, and turn the Knave into an Assassin.. + /// + internal static string LOC_ID_SKILL_DESC_26 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_26", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Earn your geology degree and go from Miner to Spelunker. Spiffy.. + /// + internal static string LOC_ID_SKILL_DESC_27 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_27", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Become a Barbarian King. The king of freemen. That makes no sense.. + /// + internal static string LOC_ID_SKILL_DESC_28 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_28", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Royalize your all-powerful Liches, and turn them into Lich Kings.. + /// + internal static string LOC_ID_SKILL_DESC_29 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_29", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Release your inner cat, and avoid death. Sometimes.. + /// + internal static string LOC_ID_SKILL_DESC_3 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Become the leader of your village, and turn your Shinobi into a Hokage. Believe it!. + /// + internal static string LOC_ID_SKILL_DESC_30 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_30", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ride the vortexes of magic, and turn your Spellthiefs into Spellswords.. + /// + internal static string LOC_ID_SKILL_DESC_31 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_31", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Half man, half ******, all awesome.. + /// + internal static string LOC_ID_SKILL_DESC_32 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_32", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to QUICK OF BREATH \nYou're a heavy breather. Bad for stalking, good for walking! \n\nIncrease your natural endurance regeneration.. + /// + internal static string LOC_ID_SKILL_DESC_33 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_33", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You were infused with tiger blood at a young age. You have now been infused with the power to release tiger blood when stabbed. \nRunning drains less endurance.. + /// + internal static string LOC_ID_SKILL_DESC_34 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_34", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your have viking ancestry. \n\nIncrease your starting endurance.. + /// + internal static string LOC_ID_SKILL_DESC_35 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_35", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You're an early waker. If leveling was like waking up.\n Gain bonus HP and MP every time you level.. + /// + internal static string LOC_ID_SKILL_DESC_36 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_36", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You were born with absolute power in your fingertips. \nAll spells deal more damage.. + /// + internal static string LOC_ID_SKILL_DESC_37 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_37", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You were born with arcane energy coarsing through your veins. Ow. \nSpells cost less to cast.. + /// + internal static string LOC_ID_SKILL_DESC_38 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_38", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to OCD finally comes in handy. \nGain more gold.. + /// + internal static string LOC_ID_SKILL_DESC_39 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_39", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A proper gym will allow you to really strengthen your arms and butt muscles.. + /// + internal static string LOC_ID_SKILL_DESC_4 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to By law, you are now the best man. \nGive birth to more children.. + /// + internal static string LOC_ID_SKILL_DESC_40 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_40", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your parents said learning how to sift for gold was useless for a farmer. Whose laughing now? \n Display treasure rooms at the start of the game.. + /// + internal static string LOC_ID_SKILL_DESC_41 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_41", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to War is hell. Luckily you were never in one. \n Fire more mortars.. + /// + internal static string LOC_ID_SKILL_DESC_42 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_42", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to As a child, you showed an affinity for blowing things up. \n Bombs have a larger radius.. + /// + internal static string LOC_ID_SKILL_DESC_43 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_43", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You're great grandfather was a snowman. He taught you nothing. \n Icicles pierce through more enemies.. + /// + internal static string LOC_ID_SKILL_DESC_44 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_44", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are Zen-like. \n Regain endurance faster while still.. + /// + internal static string LOC_ID_SKILL_DESC_45 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_45", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Generic SKILL. Increase total Endurance.. + /// + internal static string LOC_ID_SKILL_DESC_46 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_46", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You fight with finesse \n Attacks Drain X% less endurance.. + /// + internal static string LOC_ID_SKILL_DESC_47 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_47", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Generic SKILL. Increase Health. + /// + internal static string LOC_ID_SKILL_DESC_48 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_48", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You suck... Blood. \n Restore a small amount of life with every hit.. + /// + internal static string LOC_ID_SKILL_DESC_49 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_49", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A pogo practice room has its benefits. Deal more damage with consecutive down strikes.. + /// + internal static string LOC_ID_SKILL_DESC_5 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Come back to life, just like Jesus. But you're still not jesus. \n Revive once after dying.. + /// + internal static string LOC_ID_SKILL_DESC_50 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_50", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Clearing a room is like clearing your mind. I don't know how. \nRegain health for every room fully cleared.. + /// + internal static string LOC_ID_SKILL_DESC_51 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_51", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cartography /n Each percentage of map revealed adds 0.1 damage.. + /// + internal static string LOC_ID_SKILL_DESC_52 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_52", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Generic SKILL. Increase Attack Damage.. + /// + internal static string LOC_ID_SKILL_DESC_53 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_53", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You're a very, very sore loser. \n Deal massive damage to all enemies on screen upon death.. + /// + internal static string LOC_ID_SKILL_DESC_54 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_54", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have learned that hitting the balls deals massive damage. \n Crits deal more damage.. + /// + internal static string LOC_ID_SKILL_DESC_55 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_55", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to GENERIC SKILL.. + /// + internal static string LOC_ID_SKILL_DESC_56 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_56", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Oh. They were in my back pocket. \nGain 2 extra keys.. + /// + internal static string LOC_ID_SKILL_DESC_57 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_57", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Like a pheonix you are reborn from your crappy ashes. \n Regain all HP and MP.. + /// + internal static string LOC_ID_SKILL_DESC_58 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_58", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Retire, and invest your money wisely. End your game early, and gain a bonus to gold found.. + /// + internal static string LOC_ID_SKILL_DESC_59 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_59", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Teaching yourself about the weaknesses of enemies allows you to strike with deadly efficiency.. + /// + internal static string LOC_ID_SKILL_DESC_6 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to CHUG CHUG CHUG! \n Drink potions instantly.. + /// + internal static string LOC_ID_SKILL_DESC_60 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_60", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Practice the deadly strikes to be even deadlier. Enemies will be so dead.. + /// + internal static string LOC_ID_SKILL_DESC_7 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Learn the secrets of the universe, so you can use it to kill with spells better.. + /// + internal static string LOC_ID_SKILL_DESC_8 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Increase your mental fortitude in order to increase your mana pool.. + /// + internal static string LOC_ID_SKILL_DESC_9 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_DESC_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press. + /// + internal static string LOC_ID_SKILL_INPUT_1 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to cast empowered spells. + /// + internal static string LOC_ID_SKILL_INPUT_10 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to awesome.. + /// + internal static string LOC_ID_SKILL_INPUT_11 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:9] to randomize your children. + /// + internal static string LOC_ID_SKILL_INPUT_18 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to randomize your children. + /// + internal static string LOC_ID_SKILL_INPUT_2 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:13] to block all incoming damage.. + /// + internal static string LOC_ID_SKILL_INPUT_24 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_24", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:13] to switch spells. + /// + internal static string LOC_ID_SKILL_INPUT_25 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_25", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:13] to turn to mist. + /// + internal static string LOC_ID_SKILL_INPUT_26 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_26", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:13] to turn on your headlamp. + /// + internal static string LOC_ID_SKILL_INPUT_27 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_27", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:13] to cast an epic shout that knocks virtually everything away.. + /// + internal static string LOC_ID_SKILL_INPUT_28 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_28", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:13] to convert max hp into max mp. + /// + internal static string LOC_ID_SKILL_INPUT_29 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_29", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to block all incoming damage.. + /// + internal static string LOC_ID_SKILL_INPUT_3 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:13] to flash. + /// + internal static string LOC_ID_SKILL_INPUT_30 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_30", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:13] to cast empowered spells. + /// + internal static string LOC_ID_SKILL_INPUT_31 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_31", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:10] to awesome.. + /// + internal static string LOC_ID_SKILL_INPUT_32 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_32", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to switch spells. + /// + internal static string LOC_ID_SKILL_INPUT_4 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to turn to mist. + /// + internal static string LOC_ID_SKILL_INPUT_5 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to turn on your headlamp. + /// + internal static string LOC_ID_SKILL_INPUT_6 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to cast an epic shout that knocks virtually everything away.. + /// + internal static string LOC_ID_SKILL_INPUT_7 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to convert max hp into max mp. + /// + internal static string LOC_ID_SKILL_INPUT_8 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to flash. + /// + internal static string LOC_ID_SKILL_INPUT_9 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_SKILL_INPUT_SPACE { + get { + return ResourceManager.GetString("LOC_ID_SKILL_INPUT_SPACE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Health Up. + /// + internal static string LOC_ID_SKILL_NAME_1 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Smithy. + /// + internal static string LOC_ID_SKILL_NAME_10 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enchantress. + /// + internal static string LOC_ID_SKILL_NAME_11 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Architect. + /// + internal static string LOC_ID_SKILL_NAME_12 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Equip Up. + /// + internal static string LOC_ID_SKILL_NAME_13 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Armor Up. + /// + internal static string LOC_ID_SKILL_NAME_14 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gold Gain Up. + /// + internal static string LOC_ID_SKILL_NAME_15 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Haggle. + /// + internal static string LOC_ID_SKILL_NAME_16 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Potion Up. + /// + internal static string LOC_ID_SKILL_NAME_17 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Randomize Children. + /// + internal static string LOC_ID_SKILL_NAME_18 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlock Lich. + /// + internal static string LOC_ID_SKILL_NAME_19 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_19", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invuln Time Up. + /// + internal static string LOC_ID_SKILL_NAME_2 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlock Miner. + /// + internal static string LOC_ID_SKILL_NAME_20 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_20", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlock Spell Thief. + /// + internal static string LOC_ID_SKILL_NAME_21 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_21", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlock Shinobi. + /// + internal static string LOC_ID_SKILL_NAME_22 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_22", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mana Cost Down. + /// + internal static string LOC_ID_SKILL_NAME_23 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_23", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upgrade Knight. + /// + internal static string LOC_ID_SKILL_NAME_24 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_24", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upgrade Mage. + /// + internal static string LOC_ID_SKILL_NAME_25 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_25", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upgrade Knave. + /// + internal static string LOC_ID_SKILL_NAME_26 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_26", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upgrade Miner. + /// + internal static string LOC_ID_SKILL_NAME_27 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_27", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upgrade Barbarian. + /// + internal static string LOC_ID_SKILL_NAME_28 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_28", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upgrade Lich. + /// + internal static string LOC_ID_SKILL_NAME_29 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_29", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Death Defy. + /// + internal static string LOC_ID_SKILL_NAME_3 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upgrade Shinobi. + /// + internal static string LOC_ID_SKILL_NAME_30 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_30", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upgrade Spell Thief. + /// + internal static string LOC_ID_SKILL_NAME_31 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_31", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Beastiality. + /// + internal static string LOC_ID_SKILL_NAME_32 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_32", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Quick of Breath. + /// + internal static string LOC_ID_SKILL_NAME_33 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_33", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Born to Run. + /// + internal static string LOC_ID_SKILL_NAME_34 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_34", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stout Heart. + /// + internal static string LOC_ID_SKILL_NAME_35 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_35", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Out the Gate. + /// + internal static string LOC_ID_SKILL_NAME_36 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_36", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spellsword. + /// + internal static string LOC_ID_SKILL_NAME_37 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_37", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sorcerer. + /// + internal static string LOC_ID_SKILL_NAME_38 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_38", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Perfectionist. + /// + internal static string LOC_ID_SKILL_NAME_39 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_39", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Attack Up. + /// + internal static string LOC_ID_SKILL_NAME_4 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Well Endowed. + /// + internal static string LOC_ID_SKILL_NAME_40 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_40", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Treasure Hunter. + /// + internal static string LOC_ID_SKILL_NAME_41 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_41", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mortar Master. + /// + internal static string LOC_ID_SKILL_NAME_42 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_42", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Explosive Expert. + /// + internal static string LOC_ID_SKILL_NAME_43 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_43", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Icicle. + /// + internal static string LOC_ID_SKILL_NAME_44 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_44", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Guru. + /// + internal static string LOC_ID_SKILL_NAME_45 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_45", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Iron Lung. + /// + internal static string LOC_ID_SKILL_NAME_46 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_46", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sword Master. + /// + internal static string LOC_ID_SKILL_NAME_47 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_47", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tank. + /// + internal static string LOC_ID_SKILL_NAME_48 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_48", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Vampire. + /// + internal static string LOC_ID_SKILL_NAME_49 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_49", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Down Strike Up. + /// + internal static string LOC_ID_SKILL_NAME_5 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Second Chance. + /// + internal static string LOC_ID_SKILL_NAME_50 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_50", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Peace of Mind. + /// + internal static string LOC_ID_SKILL_NAME_51 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_51", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cartography Ninja. + /// + internal static string LOC_ID_SKILL_NAME_52 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_52", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Strong Man. + /// + internal static string LOC_ID_SKILL_NAME_53 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_53", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Suicidalist. + /// + internal static string LOC_ID_SKILL_NAME_54 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_54", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Crit Barbarian. + /// + internal static string LOC_ID_SKILL_NAME_55 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_55", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Magician. + /// + internal static string LOC_ID_SKILL_NAME_56 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_56", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Keymaster. + /// + internal static string LOC_ID_SKILL_NAME_57 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_57", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to One Time Only. + /// + internal static string LOC_ID_SKILL_NAME_58 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_58", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cutting Out Early. + /// + internal static string LOC_ID_SKILL_NAME_59 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_59", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Crit Chance Up. + /// + internal static string LOC_ID_SKILL_NAME_6 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Quaffer. + /// + internal static string LOC_ID_SKILL_NAME_60 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_60", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Crit Damage Up. + /// + internal static string LOC_ID_SKILL_NAME_7 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Magic Damage Up. + /// + internal static string LOC_ID_SKILL_NAME_8 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mana Up. + /// + internal static string LOC_ID_SKILL_NAME_9 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_NAME_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to purchase/upgrade trait. + /// + internal static string LOC_ID_SKILL_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:0] to purchase/upgrade trait. + /// + internal static string LOC_ID_SKILL_SCREEN_1_NEW { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_1_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to gold to. + /// + internal static string LOC_ID_SKILL_SCREEN_10 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} gold to {1}. + /// + internal static string LOC_ID_SKILL_SCREEN_10_NEW { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_10_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to unlock. + /// + internal static string LOC_ID_SKILL_SCREEN_11 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to upgrade. + /// + internal static string LOC_ID_SKILL_SCREEN_12 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to weight. + /// + internal static string LOC_ID_SKILL_SCREEN_13 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to hp. + /// + internal static string LOC_ID_SKILL_SCREEN_14 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to mp. + /// + internal static string LOC_ID_SKILL_SCREEN_15 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to str. + /// + internal static string LOC_ID_SKILL_SCREEN_16 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to int. + /// + internal static string LOC_ID_SKILL_SCREEN_17 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to hp/mp. + /// + internal static string LOC_ID_SKILL_SCREEN_18 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Max. + /// + internal static string LOC_ID_SKILL_SCREEN_19 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_19", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to toggle icons off. + /// + internal static string LOC_ID_SKILL_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:9] to toggle icons off. + /// + internal static string LOC_ID_SKILL_SCREEN_2_NEW { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_2_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to armor. + /// + internal static string LOC_ID_SKILL_SCREEN_20 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_20", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to sec. + /// + internal static string LOC_ID_SKILL_SCREEN_21 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_21", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to exit the manor. + /// + internal static string LOC_ID_SKILL_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:2] to exit the manor. + /// + internal static string LOC_ID_SKILL_SCREEN_3_NEW { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_3_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to navigate skills. + /// + internal static string LOC_ID_SKILL_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Button:LeftStick] to navigate skills. + /// + internal static string LOC_ID_SKILL_SCREEN_4_NEW { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_4_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Arrow keys to navigate skills. + /// + internal static string LOC_ID_SKILL_SCREEN_5 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to toggle icons on. + /// + internal static string LOC_ID_SKILL_SCREEN_6 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Input:9] to toggle icons on. + /// + internal static string LOC_ID_SKILL_SCREEN_6_NEW { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_6_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Current. + /// + internal static string LOC_ID_SKILL_SCREEN_7 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upgrade. + /// + internal static string LOC_ID_SKILL_SCREEN_8 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Level. + /// + internal static string LOC_ID_SKILL_SCREEN_9 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_SCREEN_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Blacksmith can build the finest equipment in the world, turning you into a veritably virtuous violent-villain vaporizer.\nGathering blueprints will give him an even wider array of assorted armaments for your armory.. + /// + internal static string LOC_ID_SKILL_UNLOCK_1 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Convert your Barbarians into Barbarian KINGS! Learn the secret shouts of the bears, and shout at things until they explode.. + /// + internal static string LOC_ID_SKILL_UNLOCK_10 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Go from a measly Shinobi, to the all powerful Hokage! Master the art of looking like you're hit, but secretly turning into a log at the last minute. Good thing you carry a lot of logs on you.. + /// + internal static string LOC_ID_SKILL_UNLOCK_11 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Train your Knaves to become full fledged Assassins. Use the power of the shadows to slip secretly past enemy ranks.. + /// + internal static string LOC_ID_SKILL_UNLOCK_12 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to All that digging has turned your Miners into Spelunkers! Now that spiffy light on your head actually does something! (Not really).. + /// + internal static string LOC_ID_SKILL_UNLOCK_13 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Turn your Spellthieves into Spellswords, and grant yourself the power of summoning empowered spells.\nYou call that an axe? THIS is an axe.. + /// + internal static string LOC_ID_SKILL_UNLOCK_14 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Raise your Liches into Lich Kings, and grant yourself the power of both mind AND matter! With a single press, convert your permanant health, into permanent mana.. + /// + internal static string LOC_ID_SKILL_UNLOCK_15 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have discovered the lost art of the dragons. Though you cannot jump, you have unlimited flight, and can cast forth powerful fireballs at your foes.. + /// + internal static string LOC_ID_SKILL_UNLOCK_16 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have discovered the hidden arts known only by Johannes the Traitor. All shall bow before your might!. + /// + internal static string LOC_ID_SKILL_UNLOCK_17 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Enchantress can empower your body with magical runes, making you better, stronger, faster, jumpier.\nFind runes to increase her repertoire of body modifiying talents.\n\nHer crystal ball is just for show.. + /// + internal static string LOC_ID_SKILL_UNLOCK_2 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Architect can lock a castle down and prevent it from changing.\n\nLike the layout of a castle?\nLOCK IT DOWN!\nJust make sure you can afford his fees.. + /// + internal static string LOC_ID_SKILL_UNLOCK_3 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Shinobi. A super fast, super deadly warrior, who wears a super head band. They can't take a lot of hits, but they can dish out the pain. Believe it!. + /// + internal static string LOC_ID_SKILL_UNLOCK_4 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Trained more in the art of making money then killing enemies. Miners are best used for scouring the castle for treasure chests, and avoiding confrontation.. + /// + internal static string LOC_ID_SKILL_UNLOCK_5 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Spellthief drains mana from the enemies they hit. This grants them access to an infinite supply of mana in the heat of a battle. Rock on!. + /// + internal static string LOC_ID_SKILL_UNLOCK_6 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Masters of life and death. The lich has mammoth potential. Every kill grants the Lich permanent health (to a cap), making them truly dangerous beings.. + /// + internal static string LOC_ID_SKILL_UNLOCK_7 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Promote your Knights into Paladins. Through rigorous training, Paladins have learned how to block blows from any direction.. + /// + internal static string LOC_ID_SKILL_UNLOCK_8 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Transform your measly Mages into Archmages. Master all of the arcane arts, and change whatever spells you have on the fly.. + /// + internal static string LOC_ID_SKILL_UNLOCK_9 { + get { + return ResourceManager.GetString("LOC_ID_SKILL_UNLOCK_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hyperion's Ring. + /// + internal static string LOC_ID_SPECIAL_ITEM_TYPE_1 { + get { + return ResourceManager.GetString("LOC_ID_SPECIAL_ITEM_TYPE_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ponce De Leon's Obol. + /// + internal static string LOC_ID_SPECIAL_ITEM_TYPE_10 { + get { + return ResourceManager.GetString("LOC_ID_SPECIAL_ITEM_TYPE_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Herodotus' Obol. + /// + internal static string LOC_ID_SPECIAL_ITEM_TYPE_11 { + get { + return ResourceManager.GetString("LOC_ID_SPECIAL_ITEM_TYPE_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Traitor's Obol. + /// + internal static string LOC_ID_SPECIAL_ITEM_TYPE_12 { + get { + return ResourceManager.GetString("LOC_ID_SPECIAL_ITEM_TYPE_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hermes' Boots. + /// + internal static string LOC_ID_SPECIAL_ITEM_TYPE_2 { + get { + return ResourceManager.GetString("LOC_ID_SPECIAL_ITEM_TYPE_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hedgehog's Curse. + /// + internal static string LOC_ID_SPECIAL_ITEM_TYPE_3 { + get { + return ResourceManager.GetString("LOC_ID_SPECIAL_ITEM_TYPE_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Charon's Obol. + /// + internal static string LOC_ID_SPECIAL_ITEM_TYPE_4 { + get { + return ResourceManager.GetString("LOC_ID_SPECIAL_ITEM_TYPE_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Calypso's Compass. + /// + internal static string LOC_ID_SPECIAL_ITEM_TYPE_5 { + get { + return ResourceManager.GetString("LOC_ID_SPECIAL_ITEM_TYPE_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Helios' Blessing. + /// + internal static string LOC_ID_SPECIAL_ITEM_TYPE_6 { + get { + return ResourceManager.GetString("LOC_ID_SPECIAL_ITEM_TYPE_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Nerdy Glasses. + /// + internal static string LOC_ID_SPECIAL_ITEM_TYPE_7 { + get { + return ResourceManager.GetString("LOC_ID_SPECIAL_ITEM_TYPE_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Khidr's Obol. + /// + internal static string LOC_ID_SPECIAL_ITEM_TYPE_8 { + get { + return ResourceManager.GetString("LOC_ID_SPECIAL_ITEM_TYPE_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Alexander's Obol. + /// + internal static string LOC_ID_SPECIAL_ITEM_TYPE_9 { + get { + return ResourceManager.GetString("LOC_ID_SPECIAL_ITEM_TYPE_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fires a dagger directly in front of you.. + /// + internal static string LOC_ID_SPELL_DESC_1 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Summon a Grand Blade to defend you.. + /// + internal static string LOC_ID_SPELL_DESC_10 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Encircles you with protective fire.. + /// + internal static string LOC_ID_SPELL_DESC_11 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Launches orbs that bounce everywhere.. + /// + internal static string LOC_ID_SPELL_DESC_12 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fire a laser that blasts everyone it touches.. + /// + internal static string LOC_ID_SPELL_DESC_13 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Shoot fireballs at your enemies.. + /// + internal static string LOC_ID_SPELL_DESC_14 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fire a barrage of daggers.. + /// + internal static string LOC_ID_SPELL_DESC_15 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Throws a giant axe in an arc.. + /// + internal static string LOC_ID_SPELL_DESC_2 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Summons a bomb that explodes after a while.. + /// + internal static string LOC_ID_SPELL_DESC_3 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Toggles freezing all enemies on-screen.. + /// + internal static string LOC_ID_SPELL_DESC_4 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hits all enemies on screen. Costly.. + /// + internal static string LOC_ID_SPELL_DESC_5 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Drops and teleports to your shadow.. + /// + internal static string LOC_ID_SPELL_DESC_6 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sends out a marker which teleports you.. + /// + internal static string LOC_ID_SPELL_DESC_7 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Throws a chakram which comes back to you.. + /// + internal static string LOC_ID_SPELL_DESC_8 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Send Scythes flying out from above you.. + /// + internal static string LOC_ID_SPELL_DESC_9 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_DESC_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Axe. + /// + internal static string LOC_ID_SPELL_NAME_1 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Katana. + /// + internal static string LOC_ID_SPELL_NAME_10 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Leaf. + /// + internal static string LOC_ID_SPELL_NAME_11 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Chaos. + /// + internal static string LOC_ID_SPELL_NAME_12 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Laser. + /// + internal static string LOC_ID_SPELL_NAME_13 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dragon Fire. + /// + internal static string LOC_ID_SPELL_NAME_14 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rapid Dagger. + /// + internal static string LOC_ID_SPELL_NAME_15 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dragon Fire Neo. + /// + internal static string LOC_ID_SPELL_NAME_16 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dagger. + /// + internal static string LOC_ID_SPELL_NAME_2 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Runic Trigger. + /// + internal static string LOC_ID_SPELL_NAME_3 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stop Watch. + /// + internal static string LOC_ID_SPELL_NAME_4 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Nuke. + /// + internal static string LOC_ID_SPELL_NAME_5 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Quantum Translocater. + /// + internal static string LOC_ID_SPELL_NAME_6 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Displacer. + /// + internal static string LOC_ID_SPELL_NAME_7 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cross. + /// + internal static string LOC_ID_SPELL_NAME_8 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spark. + /// + internal static string LOC_ID_SPELL_NAME_9 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_NAME_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dagger. + /// + internal static string LOC_ID_SPELL_TYPE_1 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Blade Wall. + /// + internal static string LOC_ID_SPELL_TYPE_10 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Flame Barrier. + /// + internal static string LOC_ID_SPELL_TYPE_11 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Conflux. + /// + internal static string LOC_ID_SPELL_TYPE_12 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to B.E.A.M. + /// + internal static string LOC_ID_SPELL_TYPE_13 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dragon Fire. + /// + internal static string LOC_ID_SPELL_TYPE_14 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rapid Dagger. + /// + internal static string LOC_ID_SPELL_TYPE_15 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Axe. + /// + internal static string LOC_ID_SPELL_TYPE_2 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bomb. + /// + internal static string LOC_ID_SPELL_TYPE_3 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Time Stop. + /// + internal static string LOC_ID_SPELL_TYPE_4 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Crow Storm. + /// + internal static string LOC_ID_SPELL_TYPE_5 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Quantum Translocator. + /// + internal static string LOC_ID_SPELL_TYPE_6 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Displacer. + /// + internal static string LOC_ID_SPELL_TYPE_7 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Chakram. + /// + internal static string LOC_ID_SPELL_TYPE_8 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scythe. + /// + internal static string LOC_ID_SPELL_TYPE_9 { + get { + return ResourceManager.GetString("LOC_ID_SPELL_TYPE_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ...Loading. + /// + internal static string LOC_ID_SPLASH_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_SPLASH_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Blacksmith. + /// + internal static string LOC_ID_TEXT_1 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I used to be a very powerful Enchantress. But one day, the monsters of this castle invaded my dreams and stole my knowledge.. + /// + internal static string LOC_ID_TEXT_10 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No sound. + /// + internal static string LOC_ID_TEXT_100 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_100", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fairy Chest. + /// + internal static string LOC_ID_TEXT_101 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_101", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The floor is lava.. + /// + internal static string LOC_ID_TEXT_102 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_102", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Booyan. + /// + internal static string LOC_ID_TEXT_103 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_103", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hi there! Care to test your dexterity?\nYou only get one shot, but it's free of charge! If you succeed, I'll give you a nice reward!. + /// + internal static string LOC_ID_TEXT_104 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_104", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You only get one shot, but it's free of charge! If you succeed, I'll give you a nice reward!. + /// + internal static string LOC_ID_TEXT_105 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_105", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 10 daggers to destroy 8 targets. Care to give it a try?. + /// + internal static string LOC_ID_TEXT_106 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_106", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Booyan. + /// + internal static string LOC_ID_TEXT_107 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_107", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ok, you had your fun. Beat it!. + /// + internal static string LOC_ID_TEXT_108 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_108", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Booyan. + /// + internal static string LOC_ID_TEXT_109 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_109", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to They encased that knowledge in runes, and without those runes, I suck at my job.. + /// + internal static string LOC_ID_TEXT_11 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I haven't seen that many shots since my last visit to the alehouse (yesterday). For destroying all the targets, I've got a little reward for you!. + /// + internal static string LOC_ID_TEXT_110 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_110", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Booyan. + /// + internal static string LOC_ID_TEXT_111 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_111", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You couldn't even hit 8 targets?\nPffft. Good luck with the rest of the castle.. + /// + internal static string LOC_ID_TEXT_112 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_112", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pffft. Good luck with the rest of the castle.. + /// + internal static string LOC_ID_TEXT_113 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_113", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Booyan. + /// + internal static string LOC_ID_TEXT_114 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_114", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hi there! Let's see how good you are at your skills.\nYou only get one shot, but it's free of charge! If you succeed, I'll give you a nice reward!. + /// + internal static string LOC_ID_TEXT_115 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_115", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You only get one shot, but it's free of charge! If you succeed, I'll give you a nice reward!. + /// + internal static string LOC_ID_TEXT_116 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_116", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You get 5 axes to destroy as many targets as possible. Leave less than 10 standing, and I'll give you a special prize. Care to give it a try?. + /// + internal static string LOC_ID_TEXT_117 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_117", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Booyan. + /// + internal static string LOC_ID_TEXT_118 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_118", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Smashing! You managed to leave no more than 10 targets! Since I no longer have enough targets to run this gig, I might as well give you my stash.. + /// + internal static string LOC_ID_TEXT_119 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_119", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please Hero, if you find any runes, bring them back to me, and then I'll sell it back to you at a profit!. + /// + internal static string LOC_ID_TEXT_12 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Booyan. + /// + internal static string LOC_ID_TEXT_120 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_120", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You left more than 10 targets remaining.\nI guess you don't want the prize. Snarf!. + /// + internal static string LOC_ID_TEXT_121 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_121", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I guess you don't want the prize. Snarf!. + /// + internal static string LOC_ID_TEXT_122 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_122", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ???. + /// + internal static string LOC_ID_TEXT_123 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_123", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Greetings adventurer. I am here to give you a chance of a lifetime!. + /// + internal static string LOC_ID_TEXT_124 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_124", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Miserly Elf. + /// + internal static string LOC_ID_TEXT_125 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_125", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to For the measly sum of 25% your current gold, I will give you a chance to open 1 of 3 chests.. + /// + internal static string LOC_ID_TEXT_126 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_126", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to One chest will triple what you paid, but the other two are empty.. + /// + internal static string LOC_ID_TEXT_127 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_127", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cheapskate Elf. + /// + internal static string LOC_ID_TEXT_128 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_128", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Care to give it a shot?. + /// + internal static string LOC_ID_TEXT_129 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_129", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Architect. + /// + internal static string LOC_ID_TEXT_13 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ???. + /// + internal static string LOC_ID_TEXT_130 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_130", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Greetings adventurer. I am here to give you a chance of a lifetime!. + /// + internal static string LOC_ID_TEXT_131 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_131", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Miserly Elf. + /// + internal static string LOC_ID_TEXT_132 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_132", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to For the measly sum of 50% your current gold, I will give you a chance to open 1 of 3 chests.. + /// + internal static string LOC_ID_TEXT_133 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_133", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to One chest will triple what you paid, but the other two are empty.. + /// + internal static string LOC_ID_TEXT_134 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_134", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cheapskate Elf. + /// + internal static string LOC_ID_TEXT_135 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_135", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Care to give it a shot?. + /// + internal static string LOC_ID_TEXT_136 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_136", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ???. + /// + internal static string LOC_ID_TEXT_137 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_137", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Greetings adventurer. I am here to give you a chance of a lifetime!. + /// + internal static string LOC_ID_TEXT_138 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_138", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Miserly Elf. + /// + internal static string LOC_ID_TEXT_139 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_139", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Grrrrreeeeetings Boy!. + /// + internal static string LOC_ID_TEXT_14 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to For the measly sum of 75% your current gold, I will give you a chance to open 1 of 3 chests.. + /// + internal static string LOC_ID_TEXT_140 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_140", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to One chest will triple what you paid, but the other two are empty.. + /// + internal static string LOC_ID_TEXT_141 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_141", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cheapskate Elf. + /// + internal static string LOC_ID_TEXT_142 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_142", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Care to give it a shot?. + /// + internal static string LOC_ID_TEXT_143 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_143", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cheapskate Elf. + /// + internal static string LOC_ID_TEXT_144 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_144", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You don't have enough money? You suck.. + /// + internal static string LOC_ID_TEXT_145 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_145", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sore Winner Elf. + /// + internal static string LOC_ID_TEXT_146 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_146", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to What's in the box?. + /// + internal static string LOC_ID_TEXT_147 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_147", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to NOTHING!. + /// + internal static string LOC_ID_TEXT_148 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_148", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You stupid! Soooo stupid!. + /// + internal static string LOC_ID_TEXT_149 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_149", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Wanna know a cool fact? I'm crrrrrrrazy!. + /// + internal static string LOC_ID_TEXT_15 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sore Loser Elf. + /// + internal static string LOC_ID_TEXT_150 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_150", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tch! You were lucky this time.. + /// + internal static string LOC_ID_TEXT_151 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_151", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Impatient Elf. + /// + internal static string LOC_ID_TEXT_152 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_152", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Open a chest already!. + /// + internal static string LOC_ID_TEXT_153 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_153", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cheapskate Elf. + /// + internal static string LOC_ID_TEXT_154 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_154", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sorry dude, one chest per person.. + /// + internal static string LOC_ID_TEXT_155 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_155", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Developers. + /// + internal static string LOC_ID_TEXT_156 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_156", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Don't **** Your Pants.\nDevelopment Time: 2 days.\nRelease Date: February 16, 2009. + /// + internal static string LOC_ID_TEXT_157 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_157", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Development Time: 2 days.. + /// + internal static string LOC_ID_TEXT_158 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_158", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Release Date: February 16, 2009. + /// + internal static string LOC_ID_TEXT_159 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_159", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This lever here? With a simple pull, I can prevent the castle from changing.. + /// + internal static string LOC_ID_TEXT_16 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This was the first game we ever made, and back then we used to be called Decade Studios. In it you must stop a man from pooping himself using only text input.. + /// + internal static string LOC_ID_TEXT_160 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_160", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It was originally designed on a bus, and we decided to make it on the weekend. It did pretty well.. + /// + internal static string LOC_ID_TEXT_161 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_161", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The game has a swear word in it, and we were thinking about changing the title to be more friendly. But then our balls grew back and we stuck to our guns.. + /// + internal static string LOC_ID_TEXT_162 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_162", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A big part of the game revolved around making a text adventure that allowed people to input whatever they wanted. To solve this we had to pre-empt what we thought people would type.. + /// + internal static string LOC_ID_TEXT_163 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_163", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to We did this in 2 ways. First, we reduced the amount of options a player had (A man and a door), and secondly, we built an achievement system which was used to give the player direction.. + /// + internal static string LOC_ID_TEXT_164 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_164", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The game revolved around the achievement system so heavily that it was placed into the game over screen progression. That was a small but very vital change.. + /// + internal static string LOC_ID_TEXT_165 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_165", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Developers. + /// + internal static string LOC_ID_TEXT_166 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_166", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Band of Bears\nDevelopment Time: 4 months.\nRelease Date: August 6, 2009. + /// + internal static string LOC_ID_TEXT_167 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_167", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Development Time: 4 months.. + /// + internal static string LOC_ID_TEXT_168 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_168", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Release Date: August 6, 2009. + /// + internal static string LOC_ID_TEXT_169 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_169", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This way you can go through exactly what your ancestors went through. Impreeeessed? You should be.. + /// + internal static string LOC_ID_TEXT_17 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This was our second game we ever attempted, and it was for the 2009 DreamBuildPlay contest. We found out about it pretty late, so we had to play catch up with everyone else.. + /// + internal static string LOC_ID_TEXT_170 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_170", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fresh off the success of DSYP we decided to go big... stupidly big. And thus, Cellar Door Games was formed.. + /// + internal static string LOC_ID_TEXT_171 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_171", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to On top of starting a project well beyond our resources and expertise, we also juggled full-time jobs to get this game running. It was pretty sucky.. + /// + internal static string LOC_ID_TEXT_172 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_172", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The game featured the B.E.A.R.S system (Bare Effort Adaptable Room System), which would change rooms depending on the number of players playing.. + /// + internal static string LOC_ID_TEXT_173 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_173", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The BEARS system didn't just tweak numbers, it tweaked puzzles as well. We ended up in the Top 20 which was good but not high enough to win anything.. + /// + internal static string LOC_ID_TEXT_174 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_174", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Eventually reality (and common sense) came back to us and we realized we had to scrap the project, or in the very least put it on indefinite hiatus.. + /// + internal static string LOC_ID_TEXT_175 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_175", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The demo boss was pretty frickin cool.. + /// + internal static string LOC_ID_TEXT_176 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_176", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Developers. + /// + internal static string LOC_ID_TEXT_177 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_177", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tribal Tallies\nDevelopment Time: 3 months.\nRelease Date: November 23rd, 2009. + /// + internal static string LOC_ID_TEXT_178 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_178", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Development Time: 3 months.. + /// + internal static string LOC_ID_TEXT_179 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_179", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to How did I build this fantastic connnnnnnntraption? With sccccccience of course! And magic.. + /// + internal static string LOC_ID_TEXT_18 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Release Date: November 23rd, 2009. + /// + internal static string LOC_ID_TEXT_180 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_180", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tribal Tallies was the first project we had worked on months after the horrible experience with Band of Bears.. + /// + internal static string LOC_ID_TEXT_181 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_181", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It was a bit of a test project, to dabble our feet in water of iOS gaming since we had never tried making something on mobile platforms before.. + /// + internal static string LOC_ID_TEXT_182 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_182", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The game was simple in concept, as you tapped numbers in sequence as fast as you could.. + /// + internal static string LOC_ID_TEXT_183 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_183", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to To spice things up we implemented several modes, like tap backwards, hidden numbers, and tap matching.. + /// + internal static string LOC_ID_TEXT_184 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_184", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to We thought the scope was reasonable, but the game ended up taking much more time to make than expected. It didn't help it was all coded on a hackintosh.. + /// + internal static string LOC_ID_TEXT_185 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_185", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It was a pretty plain game. We could have done better, but we were all playing it safe after Band of Bears.. + /// + internal static string LOC_ID_TEXT_186 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_186", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Developers. + /// + internal static string LOC_ID_TEXT_187 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_187", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Q\nDevelopment Time: 1 month.\nRelease Date: March 18th, 2010. + /// + internal static string LOC_ID_TEXT_188 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_188", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Development Time: 1 month.. + /// + internal static string LOC_ID_TEXT_189 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_189", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ... Mostly magic.. + /// + internal static string LOC_ID_TEXT_19 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_19", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Release Date: March 18th, 2010. + /// + internal static string LOC_ID_TEXT_190 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_190", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Our fourth project. After Tribal Tallies we took a few months off from making games and just focused on our full-time jobs. We got angsty again, so we decided to make a puzzle game.. + /// + internal static string LOC_ID_TEXT_191 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_191", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to At this point most of the original founders of Cellar Door Games left to pursue other opportunities, and the unwanted remnants are what compose the company today.. + /// + internal static string LOC_ID_TEXT_192 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_192", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The game used a queuing combo mechanism to force players to think about how the tiles would fall in order to build massive combos.. + /// + internal static string LOC_ID_TEXT_193 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_193", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to We made it free but nobody picked it up either. After the failures of Band of Bears, Tribal Tallies, and Q, we prepped ourselves to pack it in and close the company.. + /// + internal static string LOC_ID_TEXT_194 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_194", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Developers. + /// + internal static string LOC_ID_TEXT_195 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_195", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to My First Quantum Translocator\nDevelopment Time: 1 month.\nRelease Date: October 13th, 2010. + /// + internal static string LOC_ID_TEXT_196 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_196", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Development Time: 1 month.. + /// + internal static string LOC_ID_TEXT_197 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_197", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Release Date: October 13th, 2010. + /// + internal static string LOC_ID_TEXT_198 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_198", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to My First Quantum Translocator came about when our company was at its lowest point. After 3 failed games we had already mentally checked out, and decided to make this tiny flash game for kicks.. + /// + internal static string LOC_ID_TEXT_199 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_199", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Welcome Hero.. + /// + internal static string LOC_ID_TEXT_2 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to But my skills aren't freeeeee. If I lock this castle, I will take 40% of allll the gold you earn!. + /// + internal static string LOC_ID_TEXT_20 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_20", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Absolutely no expectations were made during development, and it was more of something we did for fun than anything else.. + /// + internal static string LOC_ID_TEXT_200 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_200", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Needless to say, response to the game was huge and it is the sole reason that Cellar Door Games exists today. The moment we released MFQT we knew there was no going back.. + /// + internal static string LOC_ID_TEXT_201 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_201", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Interestingly enough, most people believe the game was inspired by Portal, but their similarities were completely coincidental.. + /// + internal static string LOC_ID_TEXT_202 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_202", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The game actually spawned from a character we had dreamt up for the game, League of Legends.. + /// + internal static string LOC_ID_TEXT_203 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_203", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to In truth the commonalities between Portal and MFQT only started to come up once we added final art and story to the game.. + /// + internal static string LOC_ID_TEXT_204 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_204", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Either way, we were pretty proud of the game. It played well and it had a nice ending.. + /// + internal static string LOC_ID_TEXT_205 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_205", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Developers. + /// + internal static string LOC_ID_TEXT_206 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_206", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I Have 1 Day\nDevelopment Time: 1.5 months.\nRelease Date: April 15th, 2011. + /// + internal static string LOC_ID_TEXT_207 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_207", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Development Time: 1.5 months.. + /// + internal static string LOC_ID_TEXT_208 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_208", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Release Date: April 15th, 2011. + /// + internal static string LOC_ID_TEXT_209 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_209", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_21 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_21", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If you ever asked us, of all the game we made which one would be our favourite, there would be a unanimous agreement with I Have 1 Day.. + /// + internal static string LOC_ID_TEXT_210 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_210", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to As children we were raised on the adventure game classics like Kings Quest and Monkey Island, so this was really our homage to some of the best experiences we ever had in gaming.. + /// + internal static string LOC_ID_TEXT_211 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_211", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The game revolves around a meta-time puzzle where the player had only 24 hours to beat the game.. + /// + internal static string LOC_ID_TEXT_212 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_212", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Every puzzle had multiple solutions with time repercussions, which forced players to think of the best way to go about solving things.. + /// + internal static string LOC_ID_TEXT_213 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_213", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to One interesting fact. The second ending was added at virtually the last minute, and without it the entire game would have sucked.. + /// + internal static string LOC_ID_TEXT_214 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_214", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Developers. + /// + internal static string LOC_ID_TEXT_215 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_215", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Villainous\nDevelopment Time: 3 months.\nRelease Date: April 15th, 2011. + /// + internal static string LOC_ID_TEXT_216 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_216", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Development Time: 3 months.. + /// + internal static string LOC_ID_TEXT_217 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_217", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Release Date: April 15th, 2011. + /// + internal static string LOC_ID_TEXT_218 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_218", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Villainous was one of the more risky endeavours we undertook.. + /// + internal static string LOC_ID_TEXT_219 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_219", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Do you want to lock the castle and get only 60% gold?. + /// + internal static string LOC_ID_TEXT_22 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_22", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The initial concept was a reverse tower defense, which sounded like it could be a good idea, but we had a hard time converting the 'could' to 'would'.. + /// + internal static string LOC_ID_TEXT_220 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_220", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Most people who have played the game thinks the process was an obvious one, but lots of stress and arguments were involved in this project.. + /// + internal static string LOC_ID_TEXT_221 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_221", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The entire idea was scrapped 3 or 4 times before we settled on its final version.. + /// + internal static string LOC_ID_TEXT_222 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_222", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It is ironic then, that to-date Villainous is far and away one of our most successful titles. It was also the most painful.. + /// + internal static string LOC_ID_TEXT_223 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_223", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Developers. + /// + internal static string LOC_ID_TEXT_224 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_224", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bullet Audyssey\nDevelopment Time: 3.5 months.\nRelease Date: November 29th, 2011. + /// + internal static string LOC_ID_TEXT_225 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_225", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Development Time: 3.5 months.. + /// + internal static string LOC_ID_TEXT_226 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_226", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Release Date: November 29th, 2011. + /// + internal static string LOC_ID_TEXT_227 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_227", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bullet Audyssey was our very last game prior to working on Rogue Legacy.. + /// + internal static string LOC_ID_TEXT_228 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_228", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Being a bullet hell that was based on rhythm and beat charts, Bullet Audyssey was the most technically challenging game we had ever worked on (yes, even moreso than Rogue Legacy).. + /// + internal static string LOC_ID_TEXT_229 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_229", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_23 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_23", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Just to create a stage required 3 editors running in unison.. + /// + internal static string LOC_ID_TEXT_230 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_230", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Development for this game was also a little non-traditional, as a lot of pre-planning was required to make sure everything clicked.. + /// + internal static string LOC_ID_TEXT_231 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_231", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Being heavy advocates against documentation, this didn't settle well with us, so we had to talk out the whole game, for like, half a day.. + /// + internal static string LOC_ID_TEXT_232 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_232", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The game had the player absorbing enemy bullets in order to fire them back and absorption happened on a beat which matched the song being played.. + /// + internal static string LOC_ID_TEXT_233 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_233", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Initial playtests were disastrous, as the game was too hard and people became incredibly frustrated in the very first minute.. + /// + internal static string LOC_ID_TEXT_234 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_234", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to By playtests, we mean 1 dude who doesn't even like Bullet Hells. But that's larger then our usual test pool.. + /// + internal static string LOC_ID_TEXT_235 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_235", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The game didn't perform very well when it released. That gave us the confidence to make Rogue Legacy!. + /// + internal static string LOC_ID_TEXT_236 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_236", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Confirm. + /// + internal static string LOC_ID_TEXT_237 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_237", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cancel. + /// + internal static string LOC_ID_TEXT_238 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_238", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Warning!. + /// + internal static string LOC_ID_TEXT_239 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_239", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Do you want to lock the castle and get only 60% gold?. + /// + internal static string LOC_ID_TEXT_24 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_24", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to start a new game? All previous save game data will be erased.. + /// + internal static string LOC_ID_TEXT_240 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_240", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Restore Controls. + /// + internal static string LOC_ID_TEXT_241 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_241", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to restore back to the default control scheme?. + /// + internal static string LOC_ID_TEXT_242 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_242", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_243 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_243", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to begin a new adventure with this chosen hero?. + /// + internal static string LOC_ID_TEXT_244 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_244", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Resolution Changed. + /// + internal static string LOC_ID_TEXT_245 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_245", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to run at this resolution?\n(The resolution will revert back in 10 seconds). + /// + internal static string LOC_ID_TEXT_246 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_246", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_247 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_247", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Delete Save File. + /// + internal static string LOC_ID_TEXT_248 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_248", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to delete your save file?\n(All skills, traits, lineages, and equipment will be erased FOREVER). + /// + internal static string LOC_ID_TEXT_249 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_249", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Architect. + /// + internal static string LOC_ID_TEXT_25 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_25", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (All skills, traits, lineages, and equipment will be erased FOREVER). + /// + internal static string LOC_ID_TEXT_250 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_250", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Delete Save File. + /// + internal static string LOC_ID_TEXT_251 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_251", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you ABSOLUTELY sure? (No Backsies)\n(All skills, traits, lineages, and equipment will be erased FOREVER). + /// + internal static string LOC_ID_TEXT_252 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_252", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (All skills, traits, lineages, and equipment will be erased FOREVER). + /// + internal static string LOC_ID_TEXT_253 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_253", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_254 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_254", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to quit to main menu? (Your current status will be saved). + /// + internal static string LOC_ID_TEXT_255 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_255", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_256 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_256", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to quit playing Rogue Legacy? (Your current status will be saved). + /// + internal static string LOC_ID_TEXT_257 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_257", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save Error. + /// + internal static string LOC_ID_TEXT_258 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_258", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Oh no! Somehow your save file got corrupted!. + /// + internal static string LOC_ID_TEXT_259 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_259", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sorry boy, there's no castle to build right now. This screw is just for show.. + /// + internal static string LOC_ID_TEXT_26 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_26", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Attempting to load a backup version of the game. Hopefully it doesn't set you too far back!. + /// + internal static string LOC_ID_TEXT_260 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_260", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save Error. + /// + internal static string LOC_ID_TEXT_261 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_261", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It doesn't look like your back up is working either. Please contact: support@cellardoorgames.com. + /// + internal static string LOC_ID_TEXT_262 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_262", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save Error. + /// + internal static string LOC_ID_TEXT_263 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_263", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your game has failed to save 3 times in a row.. + /// + internal static string LOC_ID_TEXT_264 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_264", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Anti-virus software and manual backup saving programs can conflict with save files. Please disable any of these programs before running the game.. + /// + internal static string LOC_ID_TEXT_265 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_265", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Architect. + /// + internal static string LOC_ID_TEXT_27 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_27", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dood, the castle's already locked.. + /// + internal static string LOC_ID_TEXT_28 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_28", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Architect. + /// + internal static string LOC_ID_TEXT_29 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_29", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Maybe you can help me. I used to be the greatest blacksmith in all the lands. But one day, the monsters of this castle attacked my smithy and stole all my blueprints.. + /// + internal static string LOC_ID_TEXT_3 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enjooooy! Maybe you can reach some trrrreasures your ancestors missed!. + /// + internal static string LOC_ID_TEXT_30 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_30", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Charon. + /// + internal static string LOC_ID_TEXT_31 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_31", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ... One must pay the toll.. + /// + internal static string LOC_ID_TEXT_32 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_32", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_33 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_33", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Give Charon all of your money and enter the castle?). + /// + internal static string LOC_ID_TEXT_34 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_34", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_35 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_35", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Give Charon all of your money and enter the castle?). + /// + internal static string LOC_ID_TEXT_36 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_36", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_37 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_37", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Give Charon 90% of your money and enter the castle?). + /// + internal static string LOC_ID_TEXT_38 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_38", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_39 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_39", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Without those blueprints, I can only make cutlery and stuff.. + /// + internal static string LOC_ID_TEXT_4 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Give Charon 80% of your money and enter the castle?). + /// + internal static string LOC_ID_TEXT_40 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_40", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_41 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_41", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Give Charon 70% of your money and enter the castle?). + /// + internal static string LOC_ID_TEXT_42 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_42", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_43 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_43", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Give Charon 60% of your money and enter the castle?). + /// + internal static string LOC_ID_TEXT_44 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_44", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_45 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_45", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Give Charon 50% of your money and enter the castle?). + /// + internal static string LOC_ID_TEXT_46 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_46", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Charon. + /// + internal static string LOC_ID_TEXT_47 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_47", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Oh ho ho! So you have my obol. I will let you pass for free, but only this one time.. + /// + internal static string LOC_ID_TEXT_48 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_48", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Charon. + /// + internal static string LOC_ID_TEXT_49 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_49", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please bring back any blueprints you find, and I can build the most amazing equipment ever. EVER. . + /// + internal static string LOC_ID_TEXT_5 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Oh ho! This is a very special obol.. + /// + internal static string LOC_ID_TEXT_50 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_50", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Give it to me, and I shall let your soul pass through the other gates.. + /// + internal static string LOC_ID_TEXT_51 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_51", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Give Charon the Obol, and pay his toll?). + /// + internal static string LOC_ID_TEXT_52 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_52", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Charon. + /// + internal static string LOC_ID_TEXT_53 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_53", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Oh ho! This is a very special obol.. + /// + internal static string LOC_ID_TEXT_54 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_54", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Give it to me, and I shall let your soul pass through the other gates.. + /// + internal static string LOC_ID_TEXT_55 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_55", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Give Charon the Obol, and pay his toll?). + /// + internal static string LOC_ID_TEXT_56 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_56", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Charon. + /// + internal static string LOC_ID_TEXT_57 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_57", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Oh ho! This is a very special obol.. + /// + internal static string LOC_ID_TEXT_58 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_58", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Give it to me, and I shall let your soul pass through the other gates.. + /// + internal static string LOC_ID_TEXT_59 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_59", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ... At a price of course.. + /// + internal static string LOC_ID_TEXT_6 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Give Charon the Obol, and pay his toll?). + /// + internal static string LOC_ID_TEXT_60 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_60", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Charon. + /// + internal static string LOC_ID_TEXT_61 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_61", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Oh ho! This is a very special obol.. + /// + internal static string LOC_ID_TEXT_62 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_62", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Give it to me, and I shall let your soul pass through the other gates.. + /// + internal static string LOC_ID_TEXT_63 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_63", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Give Charon the Obol, and pay his toll?). + /// + internal static string LOC_ID_TEXT_64 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_64", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Charon. + /// + internal static string LOC_ID_TEXT_65 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_65", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Oh... You should not have taken this obol.. + /// + internal static string LOC_ID_TEXT_66 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_66", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prepare yourself.. + /// + internal static string LOC_ID_TEXT_67 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_67", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Give Charon the Obol, and pay his toll?). + /// + internal static string LOC_ID_TEXT_68 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_68", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spiritual Shrine. + /// + internal static string LOC_ID_TEXT_69 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_69", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enchantress. + /// + internal static string LOC_ID_TEXT_7 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Will you pray for assistance?. + /// + internal static string LOC_ID_TEXT_70 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_70", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Last Boss. + /// + internal static string LOC_ID_TEXT_71 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_71", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Welcome Hero! It was quite impressive for you to get this far. Unfortunately however, this shall be as far as you go!. + /// + internal static string LOC_ID_TEXT_72 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_72", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fairy Chest - Nothing. + /// + internal static string LOC_ID_TEXT_73 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_73", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to NO TEXT. + /// + internal static string LOC_ID_TEXT_74 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_74", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Defeat All Enemies. + /// + internal static string LOC_ID_TEXT_75 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_75", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_76 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_76", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Low Health. + /// + internal static string LOC_ID_TEXT_77 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_77", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_78 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_78", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No Looking. + /// + internal static string LOC_ID_TEXT_79 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_79", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hello Hero.. + /// + internal static string LOC_ID_TEXT_8 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_80 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_80", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No Jumping. + /// + internal static string LOC_ID_TEXT_81 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_81", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_82 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_82", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No Noise. + /// + internal static string LOC_ID_TEXT_83 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_83", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_84 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_84", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Don't Touch The Floor. + /// + internal static string LOC_ID_TEXT_85 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_85", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_86 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_86", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No Fighting. + /// + internal static string LOC_ID_TEXT_87 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_87", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_88 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_88", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reach Me In Time. + /// + internal static string LOC_ID_TEXT_89 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_89", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could I borrow your ear for a moment, I'm in need of your help.. + /// + internal static string LOC_ID_TEXT_9 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_90 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_90", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Take No Damage. + /// + internal static string LOC_ID_TEXT_91 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_91", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_92 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_92", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Find Me. + /// + internal static string LOC_ID_TEXT_93 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_93", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TEXT_94 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_94", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fairy Chest. + /// + internal static string LOC_ID_TEXT_95 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_95", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Don't look at me!. + /// + internal static string LOC_ID_TEXT_96 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_96", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fairy Chest. + /// + internal static string LOC_ID_TEXT_97 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_97", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No Jumping. + /// + internal static string LOC_ID_TEXT_98 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_98", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fairy Chest. + /// + internal static string LOC_ID_TEXT_99 { + get { + return ResourceManager.GetString("LOC_ID_TEXT_99", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press. + /// + internal static string LOC_ID_THRONE_ROOM_OBJ_1 { + get { + return ResourceManager.GetString("LOC_ID_THRONE_ROOM_OBJ_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press [Input:12] to Attack. + /// + internal static string LOC_ID_THRONE_ROOM_OBJ_1_NEW { + get { + return ResourceManager.GetString("LOC_ID_THRONE_ROOM_OBJ_1_NEW", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to Attack. + /// + internal static string LOC_ID_THRONE_ROOM_OBJ_2 { + get { + return ResourceManager.GetString("LOC_ID_THRONE_ROOM_OBJ_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to Change Slot. + /// + internal static string LOC_ID_TITLE_SCREEN_1 { + get { + return ResourceManager.GetString("LOC_ID_TITLE_SCREEN_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Continue Your Quest. + /// + internal static string LOC_ID_TITLE_SCREEN_2 { + get { + return ResourceManager.GetString("LOC_ID_TITLE_SCREEN_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Choose Your Heir. + /// + internal static string LOC_ID_TITLE_SCREEN_3 { + get { + return ResourceManager.GetString("LOC_ID_TITLE_SCREEN_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Start Your Legacy. + /// + internal static string LOC_ID_TITLE_SCREEN_4 { + get { + return ResourceManager.GetString("LOC_ID_TITLE_SCREEN_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} is a trademark of Cellar Door Games Inc. All Right Reserved.. + /// + internal static string LOC_ID_TRADEMARK_GENERIC { + get { + return ResourceManager.GetString("LOC_ID_TRADEMARK_GENERIC", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Training Dummy. + /// + internal static string LOC_ID_TRAINING_DUMMY_1 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to IT HUURRRTS. + /// + internal static string LOC_ID_TRAINING_DUMMY_10 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Oof. + /// + internal static string LOC_ID_TRAINING_DUMMY_11 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ouch. + /// + internal static string LOC_ID_TRAINING_DUMMY_12 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to BLARGH. + /// + internal static string LOC_ID_TRAINING_DUMMY_13 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I give up!. + /// + internal static string LOC_ID_TRAINING_DUMMY_14 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Do you even lift?. + /// + internal static string LOC_ID_TRAINING_DUMMY_15 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ok, that one hurt. + /// + internal static string LOC_ID_TRAINING_DUMMY_16 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to That tickled. + /// + internal static string LOC_ID_TRAINING_DUMMY_17 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to That all you got?. + /// + internal static string LOC_ID_TRAINING_DUMMY_18 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dost thou even hoist?. + /// + internal static string LOC_ID_TRAINING_DUMMY_19 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_19", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Oh god!. + /// + internal static string LOC_ID_TRAINING_DUMMY_2 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Nice try. + /// + internal static string LOC_ID_TRAINING_DUMMY_20 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_20", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Weak. + /// + internal static string LOC_ID_TRAINING_DUMMY_21 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_21", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Try again. + /// + internal static string LOC_ID_TRAINING_DUMMY_22 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_22", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The pain!. + /// + internal static string LOC_ID_TRAINING_DUMMY_3 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It hurts so much. + /// + internal static string LOC_ID_TRAINING_DUMMY_4 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to STOP IT!!. + /// + internal static string LOC_ID_TRAINING_DUMMY_5 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to What'd I do to you?. + /// + internal static string LOC_ID_TRAINING_DUMMY_6 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to WHY???. + /// + internal static string LOC_ID_TRAINING_DUMMY_7 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stop hitting me. + /// + internal static string LOC_ID_TRAINING_DUMMY_8 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Why you do this?. + /// + internal static string LOC_ID_TRAINING_DUMMY_9 { + get { + return ResourceManager.GetString("LOC_ID_TRAINING_DUMMY_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can't see colors due to monochromacy.. + /// + internal static string LOC_ID_TRAIT_DESC_1 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You're skinny, so every hit sends you flying.. + /// + internal static string LOC_ID_TRAIT_DESC_10 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have trouble remembering where you are.. + /// + internal static string LOC_ID_TRAIT_DESC_11 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your MP and HP pools are swapped. Who knew?. + /// + internal static string LOC_ID_TRAIT_DESC_12 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to %#&@!. + /// + internal static string LOC_ID_TRAIT_DESC_13 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to So energetic! You move faster.. + /// + internal static string LOC_ID_TRAIT_DESC_14 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Must. Clear. House. Break stuff to restore MP.. + /// + internal static string LOC_ID_TRAIT_DESC_15 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You're perma-roided. Attacks knock enemies further.. + /// + internal static string LOC_ID_TRAIT_DESC_16 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have weak limbs. Enemies won't get knocked back.. + /// + internal static string LOC_ID_TRAIT_DESC_17 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can't see in 3D.. + /// + internal static string LOC_ID_TRAIT_DESC_18 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Even the most valiant heroes can suffer from irritable bowels.. + /// + internal static string LOC_ID_TRAIT_DESC_19 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_19", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You like the ladies.. + /// + internal static string LOC_ID_TRAIT_DESC_2 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Welcome to Barfs-ville.. + /// + internal static string LOC_ID_TRAIT_DESC_20 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_20", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No peripheral vision.. + /// + internal static string LOC_ID_TRAIT_DESC_21 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_21", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You've got two left hands, and can't cast spells properly.. + /// + internal static string LOC_ID_TRAIT_DESC_22 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_22", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Peripheral Arterial Disease. No foot pulse.. + /// + internal static string LOC_ID_TRAIT_DESC_23 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_23", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Chickens freak you out.. + /// + internal static string LOC_ID_TRAIT_DESC_24 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_24", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You tend to EXAGGERATE.. + /// + internal static string LOC_ID_TRAIT_DESC_25 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_25", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are insane.. + /// + internal static string LOC_ID_TRAIT_DESC_26 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_26", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are very flexible.. + /// + internal static string LOC_ID_TRAIT_DESC_27 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_27", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You remember things with extreme clarity.. + /// + internal static string LOC_ID_TRAIT_DESC_28 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_28", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You miss the good old days.. + /// + internal static string LOC_ID_TRAIT_DESC_29 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_29", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are a fan of the man.. + /// + internal static string LOC_ID_TRAIT_DESC_2b { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_2b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Anything far away is blurry.. + /// + internal static string LOC_ID_TRAIT_DESC_3 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Congenital Insensitivity to Pain. Know no pain.. + /// + internal static string LOC_ID_TRAIT_DESC_30 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_30", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You're very talented. With a few issues.. + /// + internal static string LOC_ID_TRAIT_DESC_31 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_31", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There is no spork.. + /// + internal static string LOC_ID_TRAIT_DESC_32 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_32", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You break a lot of things.. + /// + internal static string LOC_ID_TRAIT_DESC_33 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_33", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You conduct electricity really well.. + /// + internal static string LOC_ID_TRAIT_DESC_34 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_34", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It's so dark.. + /// + internal static string LOC_ID_TRAIT_DESC_35 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_35", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have random muscle spasms.. + /// + internal static string LOC_ID_TRAIT_DESC_36 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_36", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can't tell people apart.. + /// + internal static string LOC_ID_TRAIT_DESC_37 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_37", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Anything close-up is blurry.. + /// + internal static string LOC_ID_TRAIT_DESC_4 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You hvae trboule raednig tinhgs.. + /// + internal static string LOC_ID_TRAIT_DESC_5 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You were born to be a basketball player.. + /// + internal static string LOC_ID_TRAIT_DESC_6 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You never get to ride rollercoasters.. + /// + internal static string LOC_ID_TRAIT_DESC_7 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The bald and the beautiful.. + /// + internal static string LOC_ID_TRAIT_DESC_8 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You're so heavy, enemies can't knock you back.. + /// + internal static string LOC_ID_TRAIT_DESC_9 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_DESC_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can't see colors.. + /// + internal static string LOC_ID_TRAIT_PROF_1 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hits send you flying.. + /// + internal static string LOC_ID_TRAIT_PROF_10 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Where are you?. + /// + internal static string LOC_ID_TRAIT_PROF_11 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MP + HP pools swapped.. + /// + internal static string LOC_ID_TRAIT_PROF_12 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to %#&@!. + /// + internal static string LOC_ID_TRAIT_PROF_13 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You move faster.. + /// + internal static string LOC_ID_TRAIT_PROF_14 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Break stuff to restore MP.. + /// + internal static string LOC_ID_TRAIT_PROF_15 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You knock enemies out of the park.. + /// + internal static string LOC_ID_TRAIT_PROF_16 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can't knock enemies back.. + /// + internal static string LOC_ID_TRAIT_PROF_17 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can't see in 3D.. + /// + internal static string LOC_ID_TRAIT_PROF_18 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You fart a lot.. + /// + internal static string LOC_ID_TRAIT_PROF_19 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_19", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You like the ladies.. + /// + internal static string LOC_ID_TRAIT_PROF_2 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Everything is upside down.. + /// + internal static string LOC_ID_TRAIT_PROF_20 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_20", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No early indicators.. + /// + internal static string LOC_ID_TRAIT_PROF_21 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_21", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spells come out your back.. + /// + internal static string LOC_ID_TRAIT_PROF_22 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_22", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No foot pulse.. + /// + internal static string LOC_ID_TRAIT_PROF_23 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_23", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are scared of chickens.. + /// + internal static string LOC_ID_TRAIT_PROF_24 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_24", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Exaggerate the damage you take.. + /// + internal static string LOC_ID_TRAIT_PROF_25 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_25", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You see things that aren't there.. + /// + internal static string LOC_ID_TRAIT_PROF_26 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_26", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You turn while fighting.. + /// + internal static string LOC_ID_TRAIT_PROF_27 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_27", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Remember enemy placement.. + /// + internal static string LOC_ID_TRAIT_PROF_28 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_28", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Everything is old-timey.. + /// + internal static string LOC_ID_TRAIT_PROF_29 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_29", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are a fan of the man.. + /// + internal static string LOC_ID_TRAIT_PROF_2b { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_2b", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Anything far away is blurry.. + /// + internal static string LOC_ID_TRAIT_PROF_3 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No visible health bar.. + /// + internal static string LOC_ID_TRAIT_PROF_30 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_30", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Randomized spells.. + /// + internal static string LOC_ID_TRAIT_PROF_31 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_31", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There is no spork.. + /// + internal static string LOC_ID_TRAIT_PROF_32 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_32", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You break stuff and have no balance.. + /// + internal static string LOC_ID_TRAIT_PROF_33 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_33", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Platforms stay open.. + /// + internal static string LOC_ID_TRAIT_PROF_34 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_34", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It's so dark.. + /// + internal static string LOC_ID_TRAIT_PROF_35 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_35", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have random muscle spasms.. + /// + internal static string LOC_ID_TRAIT_PROF_36 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_36", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can't tell people apart.. + /// + internal static string LOC_ID_TRAIT_PROF_37 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_37", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Anything close-up is blurry.. + /// + internal static string LOC_ID_TRAIT_PROF_4 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You hvae trboule raednig tinhgs.. + /// + internal static string LOC_ID_TRAIT_PROF_5 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are huge.. + /// + internal static string LOC_ID_TRAIT_PROF_6 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are tiny.. + /// + internal static string LOC_ID_TRAIT_PROF_7 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are bald.. + /// + internal static string LOC_ID_TRAIT_PROF_8 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Can't get knocked back.. + /// + internal static string LOC_ID_TRAIT_PROF_9 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_PROF_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Color Blind. + /// + internal static string LOC_ID_TRAIT_TYPE_1 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ectomorph. + /// + internal static string LOC_ID_TRAIT_TYPE_10 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Alzheimers. + /// + internal static string LOC_ID_TRAIT_TYPE_11 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dextrocardia. + /// + internal static string LOC_ID_TRAIT_TYPE_12 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Coprolalia. + /// + internal static string LOC_ID_TRAIT_TYPE_13 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ADHD. + /// + internal static string LOC_ID_TRAIT_TYPE_14 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to O.C.D.. + /// + internal static string LOC_ID_TRAIT_TYPE_15 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hypergonadism. + /// + internal static string LOC_ID_TRAIT_TYPE_16 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Muscle Wk.. + /// + internal static string LOC_ID_TRAIT_TYPE_17 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stereo Blind. + /// + internal static string LOC_ID_TRAIT_TYPE_18 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I.B.S.. + /// + internal static string LOC_ID_TRAIT_TYPE_19 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_19", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gay. + /// + internal static string LOC_ID_TRAIT_TYPE_2 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Vertigo. + /// + internal static string LOC_ID_TRAIT_TYPE_20 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_20", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tunnel Vision. + /// + internal static string LOC_ID_TRAIT_TYPE_21 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_21", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ambilevous. + /// + internal static string LOC_ID_TRAIT_TYPE_22 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_22", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to P.A.D.. + /// + internal static string LOC_ID_TRAIT_TYPE_23 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_23", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Alektorophobia. + /// + internal static string LOC_ID_TRAIT_TYPE_24 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_24", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hypochondriac. + /// + internal static string LOC_ID_TRAIT_TYPE_25 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_25", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dementia. + /// + internal static string LOC_ID_TRAIT_TYPE_26 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_26", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Flexible. + /// + internal static string LOC_ID_TRAIT_TYPE_27 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_27", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Eid. Mem.. + /// + internal static string LOC_ID_TRAIT_TYPE_28 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_28", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Nostalgic. + /// + internal static string LOC_ID_TRAIT_TYPE_29 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_29", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Near-Sighted. + /// + internal static string LOC_ID_TRAIT_TYPE_3 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to C.I.P.. + /// + internal static string LOC_ID_TRAIT_TYPE_30 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_30", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Savant. + /// + internal static string LOC_ID_TRAIT_TYPE_31 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_31", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The One. + /// + internal static string LOC_ID_TRAIT_TYPE_32 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_32", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Clumsy. + /// + internal static string LOC_ID_TRAIT_TYPE_33 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_33", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to EHS. + /// + internal static string LOC_ID_TRAIT_TYPE_34 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_34", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Glaucoma. + /// + internal static string LOC_ID_TRAIT_TYPE_35 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_35", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Clonus. + /// + internal static string LOC_ID_TRAIT_TYPE_36 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_36", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prosopagnosia. + /// + internal static string LOC_ID_TRAIT_TYPE_37 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_37", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Far-Sighted. + /// + internal static string LOC_ID_TRAIT_TYPE_4 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dyslexia. + /// + internal static string LOC_ID_TRAIT_TYPE_5 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gigantism. + /// + internal static string LOC_ID_TRAIT_TYPE_6 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dwarfism. + /// + internal static string LOC_ID_TRAIT_TYPE_7 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Baldness. + /// + internal static string LOC_ID_TRAIT_TYPE_8 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Endomorph. + /// + internal static string LOC_ID_TRAIT_TYPE_9 { + get { + return ResourceManager.GetString("LOC_ID_TRAIT_TYPE_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Developed by. + /// + internal static string LOC_ID_TUTORIAL_CREDITS_TITLE_1 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_CREDITS_TITLE_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Design. + /// + internal static string LOC_ID_TUTORIAL_CREDITS_TITLE_2 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_CREDITS_TITLE_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Programming. + /// + internal static string LOC_ID_TUTORIAL_CREDITS_TITLE_3 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_CREDITS_TITLE_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Production. + /// + internal static string LOC_ID_TUTORIAL_CREDITS_TITLE_4 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_CREDITS_TITLE_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Art. + /// + internal static string LOC_ID_TUTORIAL_CREDITS_TITLE_5 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_CREDITS_TITLE_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sound Design & Music. + /// + internal static string LOC_ID_TUTORIAL_CREDITS_TITLE_6 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_CREDITS_TITLE_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Music. + /// + internal static string LOC_ID_TUTORIAL_CREDITS_TITLE_7 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_CREDITS_TITLE_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string LOC_ID_TUTORIAL_CREDITS_TITLE_8 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_CREDITS_TITLE_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tap. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_1 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Down Attack this. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_10 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tap [Input:11] to Jump. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_11 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hold [Input:11] to Jump Higher. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_12 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tap [Input:12] to Attack. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_13 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hold [Input:19] and Tap [Input:11] to Drop Ledges. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_14 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Air) Hold [Input:19] and Tap [Input:12] to Attack Down. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_15 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tap [Input:10] to Jump. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_16 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hold [Input:10] to Jump Higher. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_17 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tap [Input:12] to Attack. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_18 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hold [Input:18] and Tap [Input:10] to Drop Ledges. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_19 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_19", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to Jump. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_2 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Air) Hold [Input:18] and Tap [Input:12] to Attack Down. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_20 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_20", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hold. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_3 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to Jump Higher. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_4 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to Attack. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_5 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to and Tap. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_6 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to Drop Ledges. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_7 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Air) Hold. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_8 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to to Attack Down. + /// + internal static string LOC_ID_TUTORIAL_ROOM_OBJ_9 { + get { + return ResourceManager.GetString("LOC_ID_TUTORIAL_ROOM_OBJ_9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlock Traitor. + /// + internal static string LOC_ID_UNLOCK_TRAITOR_OPTIONS { + get { + return ResourceManager.GetString("LOC_ID_UNLOCK_TRAITOR_OPTIONS", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlock Traitor. + /// + internal static string LOC_ID_UNLOCK_TRAITOR_OPTIONS_F { + get { + return ResourceManager.GetString("LOC_ID_UNLOCK_TRAITOR_OPTIONS_F", resourceCulture); + } + } + } +} diff --git a/RogueCastle/Resources/LocStrings.de.resx b/RogueCastle/Resources/LocStrings.de.resx new file mode 100644 index 0000000..800335a --- /dev/null +++ b/RogueCastle/Resources/LocStrings.de.resx @@ -0,0 +1,8349 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Zum Titelbildschirm zurückkehren + + + Zum Titelbildschirm zurückkehren + + + Zum Titelbildschirm zurückkehren + + + Zum Titelbildschirm zurückkehren + + + [Input:25], um das Profil zu wechseln ({0}) + + + [Input:25], um das Profil zu wechseln ({0}) + + + Leben + + + Pfeiltasten, um zu navigieren + + + Pfeiltasten, um zu navigieren + + + [Button:LeftStick] zum Navigieren + + + [Button:LeftStick] zum Navigieren + + + Wähle eine Kategorie. + + + Wähle eine Kategorie. + + + Blaupause fehlt + + + Blaupause fehlt + + + Kaufinformation hier + + + Kaufinformation hier + + + Keine + + + Keine + + + {0} zum Freischalten + + + {0} zum Freischalten + + + Leben + + + Mana + + + Mana + + + Schaden + + + Schaden + + + Magie + + + Magie + + + Rüstung + + + Rüstung + + + Gewicht + + + Gewicht + + + Zusätzliche Eigenschaften: + + + Zusätzliche Eigenschaften: + + + [Input:0]: wählen/ausrüsten + + + [Input:0]: wählen/ausrüsten + + + [Input:2]: abbrechen/Menü schließen + + + [Input:2]: abbrechen/Menü schließen + + + Ziele zerstört + + + Ziele zerstört + + + Verbleibende Ziele + + + Verbleibende Ziele + + + Belohnung + + + Belohnung + + + Gold + + + Gold + + + jederzeit Karte ansehen + + + jederzeit Karte ansehen + + + Steuerung ändern + + + Sprint (rechts) + + + Sprint (rechts) + + + Zauberspruch wirken + + + Zauberspruch wirken + + + Steuerung zurücksetzen + + + Steuerung zurücksetzen + + + Beliebige Taste drücken + + + Beliebige Taste drücken + + + Steuerung ändern + + + Hoch + + + Hoch + + + Runter + + + Runter + + + Links + + + Links + + + Rechts + + + Rechts + + + Angriff + + + Angriff + + + Springen + + + Springen + + + Spezialfähigkeit + + + Spezialfähigkeit + + + Sprint (links) + + + Sprint (links) + + + Der Standardheld. Ziemlich gut in allem. + + + Ein unaufhaltsamer Koloss. Dieser Held kann einiges wegstecken.\nSPEZIALFÄHIGKEIT: Barbarenschrei. + + + Ein unaufhaltsamer Koloss. Diese Heldin kann einiges wegstecken.\nSPEZIALFÄHIGKEIT: Barbarenschrei. + + + Ein schneller Held. Kann massiven Schaden verursachen, aber nicht kritisch treffen. + + + Eine schnelle Heldin. Kann massiven Schaden verursachen, aber nicht kritisch treffen. + + + Ein schneller Held. Kann massiven Schaden verursachen, aber nicht kritisch treffen.\nSPEZIALFÄHIGKEIT: Wechseltechnik. + + + Eine schnelle Heldin. Kann massiven Schaden verursachen, aber nicht kritisch treffen.\nSPEZIALFÄHIGKEIT: Wechseltechnik. + + + Ein Held für Experten. Triff Feinde, um Mana wiederherzustellen. + + + Eine Heldin für Experten. Triff Feinde, um Mana wiederherzustellen. + + + Ein Held für Experten. Triff Feinde, um Mana wiederherzustellen.\nSPEZIALFÄHIGKEIT: Verstärkter Zauber. + + + Eine Heldin für Experten. Triff Feinde, um Mana wiederherzustellen.\nSPEZIALFÄHIGKEIT: Verstärkter Zauber. + + + Zurück von den Toten. Gewinne dauerhaftes Leben für jede Tötung bis zu einer bestimmten Kapazität. Äußerst intelligent. + + + Zurück von den Toten. Gewinne dauerhaftes Leben für jede Tötung bis zu einer bestimmten Kapazität. Äußerst intelligent. + + + Zurück von den Toten. Gewinne dauerhaftes Leben für jede Tötung bis zu einer bestimmten Kapazität. Äußerst intelligent.\nSPEZIALFÄHIGKEIT: LP-Umwandlung + + + Zurück von den Toten. Gewinne dauerhaftes Leben für jede Tötung bis zu einer bestimmten Kapazität. Äußerst intelligent.\nSPEZIALFÄHIGKEIT: LP-Umwandlung + + + Du bist ein Drachenmensch. + + + Du bist ein Drachenmensch. + + + ????? + + + ????? + + + Die Standardheldin. Ziemlich gut in allem. + + + Der Standardheld. Ziemlich gut in allem.\nSPEZIALFÄHIGKEIT: Schutzschild. + + + Die Standardheldin. Ziemlich gut in allem.\nSPEZIALFÄHIGKEIT: Schutzschild. + + + Ein riskanter Held. Geringe Werte, aber kann verheerende Kritische Treffer landen. + + + Eine riskante Heldin. Geringe Werte, aber kann verheerende Kritische Treffer landen. + + + Ein riskanter Held. Geringe Werte, aber kann verheerende Kritische Treffer landen.\nSPEZIALFÄHIGKEIT: Nebelschleier. + + + Eine riskante Heldin. Geringe Werte, aber kann verheerende Kritische Treffer landen.\nSPEZIALFÄHIGKEIT: Nebelschleier. + + + Ein Held für Sammelwütige. Sehr schwach, aber hat einen großen Bonus auf Gold. + + + Eine Heldin für Sammelwütige. Sehr schwach, aber hat einen großen Bonus auf Gold. + + + Ein Held für Sammelwütige. Sehr schwach, aber hat einen großen Bonus auf Gold.\nSPEZIALFÄHIGKEIT: Gewöhnliche Stirnlampe. + + + Eine Heldin für Sammelwütige. Sehr schwach, aber hat einen großen Bonus auf Gold.\nSPEZIALFÄHIGKEIT: Gewöhnliche Stirnlampe. + + + Ein mächtiger Zauberkundiger. Jede Tötung gewährt dir Mana. + + + Eine mächtige Zauberkundige. Jede Tötung gewährt dir Mana. + + + Ein mächtiger Zauberkundiger. Jede Tötung gewährt dir Mana.\nSPEZIALFÄHIGKEIT: Zauberwechsel. + + + Eine mächtige Zauberkundige. Jede Tötung gewährt dir Mana.\nSPEZIALFÄHIGKEIT: Zauberwechsel. + + + Ein unaufhaltsamer Koloss. Dieser Held kann einiges wegstecken. + + + Ein unaufhaltsamer Koloss. Diese Heldin kann einiges wegstecken. + + + Barbarenkönigin + + + Barbarenkönigin + + + Barbarenkönig + + + Barbarenkönig + + + Shinobi + + + Kunoichi + + + Hokage + + + Hokage + + + Zauberdiebin + + + Zauberdiebin + + + Zauberdieb + + + Zauberdieb + + + Zauberkriegerin + + + Zauberkriegerin + + + Zauberkrieger + + + Zauberkrieger + + + Lich + + + Lichin + + + Lichkönigin + + + Lichkönigin + + + Lichkönig + + + Lichkönig + + + Drachin + + + Drachin + + + Drache + + + Drache + + + Verräterin + + + Verräterin + + + Verräter + + + Verräter + + + Ritterin + + + Ritterin + + + Ritter + + + Ritter + + + Paladinin + + + Paladinin + + + Paladin + + + Paladin + + + Schurkin + + + Schurkin + + + Schurke + + + Schurke + + + Assassinin + + + Assassinin + + + Assassine + + + Assassine + + + Minenarbeiterin + + + Minenarbeiterin + + + Minenarbeiter + + + Minenarbeiter + + + Höhlenforscherin + + + Höhlenforscherin + + + Höhlenforscher + + + Höhlenforscher + + + Magierin + + + Magierin + + + Magier + + + Magier + + + Erzmagierin + + + Erzmagierin + + + Erzmagier + + + Erzmagier + + + Barbarin + + + Barbarin + + + Barbar + + + Barbar + + + Copyright (C) 2013-2018, Cellar Door Games Inc. + + + Japanische Lokalisierung & Produktion von + + + Qualitätssicherung + + + Danke fürs Spielen! + + + Grafik + + + Grafik + + + Musik & Audiodesign + + + Musik & Audiodesign + + + Musik + + + Musik + + + Marketing & Story + + + Marketing & Story + + + Zusätzliches Audiodesign + + + Zusätzliches Audiodesign + + + Zusätzliche Hintergrundgrafiken + + + Zusätzliche Hintergrundgrafiken + + + Business Support + + + Business Support + + + Besondere Danksagung: Turbo Edition + + + Besondere Danksagung: Turbo Edition + + + Besondere Danksagung + + + Besondere Danksagung + + + Weitere Danksagung + + + Weitere Danksagung + + + Danke fürs Spielen! + + + Kinder insgesamt + + + Umsetzung für Mac/Linux von + + + Umsetzung für Mac/Linux von + + + QS für Mac/Linux + + + QS für Mac/Linux + + + Danke an alle Fans für ihre Unterstützung! + + + Danke an alle Fans für ihre Unterstützung! + + + Primär lokalisiert von + + + Primär lokalisiert von + + + Chinesisch & weitere Lokalisierung von + + + Chinesisch & weitere Lokalisierung von + + + Zusätzliche Programmierung + + + Adaptiert von + + + Kinder insgesamt + + + Gespielte Zeit + + + Gespielte Zeit + + + [Input:0] zum Verlassen + + + [Input:0] zum Verlassen + + + Entwickelt von + + + Entwickelt von + + + Design & Story + + + Design & Story + + + Programmierung + + + Programmierung + + + Produktion + + + Produktion + + + Joystick-Totzone + + + Joystick-Totzone + + + Speicherstand löschen + + + Speicherstand löschen + + + Tagebuch des Prinzen + + + Obwohl ich der Erstgeborene bin, so bin ich doch nicht meines Vaters Liebling. Ich wusste schon immer, dass er mir nichts hinterlassen würde. + + + ... und wenn ich sie aus Versehen für ein Monster hielt? + + + ... und wenn ich sie aus Versehen für ein Monster hielt? + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #17 + + + Tagebucheintrag #17 + + + Ich muss langsam verrückt werden. Ich bin in diesem Schloss auf einen Jahrmarkt gestoßen. Mit traurigem Clown und allem, was dazugehört. + + + Ich muss langsam verrückt werden. Ich bin in diesem Schloss auf einen Jahrmarkt gestoßen. Mit traurigem Clown und allem, was dazugehört. + + + Ein ziemlicher Esel. Aber ich schätze, an so einem Ort kann man sich seine Freunde nicht aussuchen. + + + Ein ziemlicher Esel. Aber ich schätze, an so einem Ort kann man sich seine Freunde nicht aussuchen. + + + Ich habe schon wieder Hunger. Gut, dass ich mich mit Hähnchenkeulen eingedeckt habe. Diese habe ich in einem Kronleuchter gefunden. + + + Ich habe schon wieder Hunger. Gut, dass ich mich mit Hähnchenkeulen eingedeckt habe. Diese habe ich in einem Kronleuchter gefunden. + + + Dieses Schloss ... Manchmal frage ich mich, ob all dies bloß ein schlechter Scherz ist. + + + Dieses Schloss ... Manchmal frage ich mich, ob all dies bloß ein schlechter Scherz ist. + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #18 + + + Tagebucheintrag #18 + + + Ich habe die Bestie im Turm besiegt und wieder habe ich gespürt, wie der Thronsaal ein wenig von seiner Macht verloren hat. + + + Ich habe die Bestie im Turm besiegt und wieder habe ich gespürt, wie der Thronsaal ein wenig von seiner Macht verloren hat. + + + Obwohl ich der Erstgeborene bin, so bin ich doch nicht meines Vaters Liebling. Ich wusste schon immer, dass er mir nichts hinterlassen würde. + + + Aber wenn ich das Heilmittel finde, wird sich alles ändern. + + + Der Rausch, den ich durch diesen Sieg verspüre, ist fantastisch! Ich habe mich noch nie so selbstbewusst, so mächtig, so ... zu Hause gefühlt. Nur noch ein wenig weiter und ich werde mir meine Belohnung verdienen können! + + + Der Rausch, den ich durch diesen Sieg verspüre, ist fantastisch! Ich habe mich noch nie so selbstbewusst, so mächtig, so ... zu Hause gefühlt. Nur noch ein wenig weiter und ich werde mir meine Belohnung verdienen können! + + + Ich bin so nah dran! Mein Vater wird stolz auf mich sein! + + + Ich bin so nah dran! Mein Vater wird stolz auf mich sein! + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #19 + + + Tagebucheintrag #19 + + + Ich habe länger vor der Kerkertür gestanden, als ich es zugeben möchte. + + + Ich habe länger vor der Kerkertür gestanden, als ich es zugeben möchte. + + + Mein Mut ist endlich aufgezehrt, denn ich habe die Monster gesehen, die dort unten auf mich warten. Sie lassen meine bisherigen Herausforderungen im Vergleich lachhaft erscheinen. + + + Mein Mut ist endlich aufgezehrt, denn ich habe die Monster gesehen, die dort unten auf mich warten. Sie lassen meine bisherigen Herausforderungen im Vergleich lachhaft erscheinen. + + + Ich muss mich wappnen. Ich muss mich konzentrieren. Dort unten gibt es so wenig Licht, dass ich befürchte, mich zu verirren. + + + Ich muss mich wappnen. Ich muss mich konzentrieren. Dort unten gibt es so wenig Licht, dass ich befürchte, mich zu verirren. + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #20 + + + Tagebucheintrag #20 + + + Ich dachte zu wissen, was Dunkelheit ist. Aber hier im Kerker hat die Dunkelheit eine Stimme. + + + Ich dachte zu wissen, was Dunkelheit ist. Aber hier im Kerker hat die Dunkelheit eine Stimme. + + + Aber wenn ich das Heilmittel finde, wird sich alles ändern. + + + Der Preis des Siegers ist nichts geringeres als der Thron selbst! + + + Sie ruft nach mir, durch Gitter und um Ecken. Sie verhöhnt mich. + + + Sie ruft nach mir, durch Gitter und um Ecken. Sie verhöhnt mich. + + + Die Dunkelheit ist undurchdringlich, fast greifbar. Die Bestien, die sie ihr zu Hause nennen... Wie schnell sie durch die Gänge huschen. Sie sind furchteinflößender als alles, mit dem ich es bisher aufgenommen habe. + + + Die Dunkelheit ist undurchdringlich, fast greifbar. Die Bestien, die sie ihr zu Hause nennen... Wie schnell sie durch die Gänge huschen. Sie sind furchteinflößender als alles, mit dem ich es bisher aufgenommen habe. + + + Ich muss umsichtig sein und meine Kämpfe vorsichtig wählen. Jetzt streitlustig zu sein, könnte mich das Leben kosten. + + + Ich muss umsichtig sein und meine Kämpfe vorsichtig wählen. Jetzt streitlustig zu sein, könnte mich das Leben kosten. + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #21 + + + Tagebucheintrag #21 + + + Ich habe es geschafft! Ich habe den Kerkermeister besiegt! Jetzt muss ich nur noch den Thronsaal betreten. + + + Ich habe es geschafft! Ich habe den Kerkermeister besiegt! Jetzt muss ich nur noch den Thronsaal betreten. + + + Hiernach wird der König mich für meine Tapferkeit ehren und mich zum rechtmäßigen Thronfolger ernennen! + + + Hiernach wird der König mich für meine Tapferkeit ehren und mich zum rechtmäßigen Thronfolger ernennen! + + + Nicht meine gesichtslosen Geschwister! + + + Nicht meine gesichtslosen Geschwister! + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #22 + + + Tagebucheintrag #22 + + + Der Preis des Siegers ist nichts geringeres als der Thron selbst! + + + Nach meinem Aufstieg werden meine Frau und meine Kinder wieder in die königlichen Gemächer ziehen. Zurück in die königliche Stadt, in der wir wieder mit dem Respekt behandelt werden, der uns gebührt! + + + Ich sitze hier und treffe die letzten Vorbereitungen. Zwischen mir und dem Herren dieses Schlosses liegen nur noch diese goldenen Türen. + + + Ich sitze hier und treffe die letzten Vorbereitungen. Zwischen mir und dem Herren dieses Schlosses liegen nur noch diese goldenen Türen. + + + In mir tobt eine Nervosität, die ich nicht unterdrücken kann. Ist es Angst, oder angstvolle Aufregung? Ich weiß nur, dass meine Reise endlich ein Ende finden wird. + + + In mir tobt eine Nervosität, die ich nicht unterdrücken kann. Ist es Angst, oder angstvolle Aufregung? Ich weiß nur, dass meine Reise endlich ein Ende finden wird. + + + Ich hatte fast vergessen, warum ich dieses Schloss überhaupt betreten habe, aber ich erinnere mich jetzt. + + + Ich hatte fast vergessen, warum ich dieses Schloss überhaupt betreten habe, aber ich erinnere mich jetzt. + + + Ich habe meine Geschwister bezwungen. Ich werde den König retten. Wenn ich dieses Schloss verlasse, werde ich ein größerer Mann sein als zuvor. Meiner Familie wird die Ehre zuteil werden, die ihr rechtmäßig zusteht. + + + Ich habe meine Geschwister bezwungen. Ich werde den König retten. Wenn ich dieses Schloss verlasse, werde ich ein größerer Mann sein als zuvor. Meiner Familie wird die Ehre zuteil werden, die ihr rechtmäßig zusteht. + + + Nun betrete ich den Thronsaal. + + + Nun betrete ich den Thronsaal. + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #23 + + + Tagebucheintrag #23 + + + Ich wusste nie, welcher Schatz in diesem Schloss verborgen ist. Ich wusste nur, dass er den König heilen würde. + + + Ich wusste nie, welcher Schatz in diesem Schloss verborgen ist. Ich wusste nur, dass er den König heilen würde. + + + Wer hätte ahnen können, dass es sich um den Jungbrunnen handelt? + + + Wer hätte ahnen können, dass es sich um den Jungbrunnen handelt? + + + Ich hatte erwartet, dass mich ein Monster auf dem Podium begrüßen würde, ein Feind von unglaublicher Macht. Ich hatte mir vorgestellt, dass ich all meine Kraft aufbringen müsste, um ihn zu bezwingen. + + + Ich hatte erwartet, dass mich ein Monster auf dem Podium begrüßen würde, ein Feind von unglaublicher Macht. Ich hatte mir vorgestellt, dass ich all meine Kraft aufbringen müsste, um ihn zu bezwingen. + + + Nach meinem Aufstieg werden meine Frau und meine Kinder wieder in die königlichen Gemächer ziehen. Zurück in die königliche Stadt, in der wir wieder mit dem Respekt behandelt werden, der uns gebührt! + + + Nie wieder werden wir den Klatsch und die kleinlichen Beleidigungen meiner Cousins ertragen müssen. Die anderen Herzöge sollen sich verneigen, wenn wir vorbeigehen! Aber eines nach dem anderen. + + + Aber als ich das Schloss betrat und sah, wie mein Vater, der König, mit einem Kelch in der Hand auf dem Podium saß, wusste ich, dass alles verloren war. + + + Aber als ich das Schloss betrat und sah, wie mein Vater, der König, mit einem Kelch in der Hand auf dem Podium saß, wusste ich, dass alles verloren war. + + + Er würde niemals sterben ... + + + Er würde niemals sterben ... + + + ... und ich würde nie der Erbe sein. + + + ... und ich würde nie der Erbe sein. + + + Es gibt keine Worte, um auszudrücken, was ich fühle. + + + Es gibt keine Worte, um auszudrücken, was ich fühle. + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #24 + + + Tagebucheintrag #24 + + + .............................. + + + .............................. + + + .... + + + .... + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #25 + + + Tagebucheintrag #25 + + + Nie wieder werden wir den Klatsch und die kleinlichen Beleidigungen meiner Cousins ertragen müssen. Die anderen Herzöge sollen sich verneigen, wenn wir vorbeigehen! Aber eines nach dem anderen. + + + Ich muss meine Ziele klar ins Auge fassen. Das Schloss erobern. Das Heilmittel finden. Meine Belohnung erhalten. + + + Heute beginnt der Rest der Ewigkeit. + + + Heute beginnt der Rest der Ewigkeit. + + + Ich wusste nie, welcher Schatz in diesem Schloss verborgen ist. Ich wusste nur, dass er den König heilen würde. + + + Ich wusste nie, welcher Schatz in diesem Schloss verborgen ist. Ich wusste nur, dass er den König heilen würde. + + + Wer hätte ahnen können, dass es sich um den Jungbrunnen handelt? Ein Mythos, der ewiges Leben gewährt. + + + Wer hätte ahnen können, dass es sich um den Jungbrunnen handelt? Ein Mythos, der ewiges Leben gewährt. + + + Wie ich nun auf den Körper des Königs herabblicke, wird mir das Unvermeidliche bewusst: Kinder werden immer für die Sünden ihrer Väter zahlen. + + + Wie ich nun auf den Körper des Königs herabblicke, wird mir das Unvermeidliche bewusst: Kinder werden immer für die Sünden ihrer Väter zahlen. + + + Ich habe dieses Schloss als Krieger betreten, als nobler Retter... + + + Ich habe dieses Schloss als Krieger betreten, als nobler Retter... + + + Und alles, was mir bleibt, ist das Vermächtnis eines Schurken. + + + Und alles, was mir bleibt, ist das Vermächtnis eines Schurken. + + + Ich kann deinen Ärger spüren, aber wisse, dass nicht ich deine Familie in den Ruin getrieben habe. + + + Ich kann deinen Ärger spüren, aber wisse, dass nicht ich deine Familie in den Ruin getrieben habe. + + + In dem Moment, als der König den Fuß in dieses Schloss setzte, wurde die königliche Schatzkammer von Charon geleert. Meine Familie... alle Familien... hatten jegliche Hoffnung auf ein besseres Leben verloren. + + + In dem Moment, als der König den Fuß in dieses Schloss setzte, wurde die königliche Schatzkammer von Charon geleert. Meine Familie... alle Familien... hatten jegliche Hoffnung auf ein besseres Leben verloren. + + + Und vor meinem geistigen Auge sah ich, wie Verzweiflung und Armut das Land verwüsteten. Es gab nichts, zu dem ich hätte zurückkehren können. + + + Und vor meinem geistigen Auge sah ich, wie Verzweiflung und Armut das Land verwüsteten. Es gab nichts, zu dem ich hätte zurückkehren können. + + + An meine Kinder und Kindeskinder, hier sitze ich, ungerührt, unsterblich, und erwarte euch. + + + An meine Kinder und Kindeskinder, hier sitze ich, ungerührt, unsterblich, und erwarte euch. + + + Ich muss meine Ziele klar ins Auge fassen. Das Schloss erobern. Das Heilmittel finden. Meine Belohnung erhalten. + + + Tagebuch des Prinzen + + + Johannes + + + Johannes + + + Was soll das? Du … verspottest du mich? + + + Was soll das? Du … verspottest du mich? + + + Unzählige Generationen deiner Vorfahren haben ihr Leben geopfert, um diesen Ort zu erreichen. Sie haben ihre letzten Schritte auf der Suche nach bedeutungsloser Gerechtigkeit getan. Und du kommst und verspottest mich? + + + Unzählige Generationen deiner Vorfahren haben ihr Leben geopfert, um diesen Ort zu erreichen. Sie haben ihre letzten Schritte auf der Suche nach bedeutungsloser Gerechtigkeit getan. Und du kommst und verspottest mich? + + + Nun gut, ich verzeihe dir deine Unwissenheit. Lass uns beginnen! + + + Nun gut, ich verzeihe dir deine Unwissenheit. Lass uns beginnen! + + + Johannes + + + Johannes + + + Warum willst du mich bekämpfen? Wie viele Söhne und Töchter sind durch deine armselige Suche nach Vergeltung gestorben? + + + Warum willst du mich bekämpfen? Wie viele Söhne und Töchter sind durch deine armselige Suche nach Vergeltung gestorben? + + + Der König hat euer Land ruiniert, nicht ich! + + + Der König hat euer Land ruiniert, nicht ich! + + + Er hat uns angelogen. Er sagte, er sei verwundet, aber es war nur die Zeit, die ihn bedrohte! + + + Er hat uns angelogen. Er sagte, er sei verwundet, aber es war nur die Zeit, die ihn bedrohte! + + + Er hat seine Kinder gegeneinander ausgespielt, alles geopfert, um seine selbstsüchtigen Wünsche zu befriedigen. Und uns hinterlässt er am Ende mittellos und allein. + + + Er hat seine Kinder gegeneinander ausgespielt, alles geopfert, um seine selbstsüchtigen Wünsche zu befriedigen. Und uns hinterlässt er am Ende mittellos und allein. + + + Also ergriff ich die einzige Möglichkeit, die mir noch blieb. Ich kehrte König und Vaterland den Rücken zu... + + + Also ergriff ich die einzige Möglichkeit, die mir noch blieb. Ich kehrte König und Vaterland den Rücken zu... + + + Tagebuch des Prinzen + + + Tagebucheintrag #3 + + + Und wählte stattdessen eine neue Familie! + + + Und wählte stattdessen eine neue Familie! + + + Johannes + + + Johannes + + + Du denkst, du hast mich erschlagen? + + + Du denkst, du hast mich erschlagen? + + + Ich lebe schon über tausend Jahre und ich werde noch zehntausend weitere leben! + + + Ich lebe schon über tausend Jahre und ich werde noch zehntausend weitere leben! + + + Alexander ... Khidr ... Ponce de Leon ... + + + Alexander ... Khidr ... Ponce de Leon ... + + + Ich war nicht der erste Held, der den Brunnen erreicht hat ... + + + Ich war nicht der erste Held, der den Brunnen erreicht hat ... + + + Aber ich werde der letzte sein! + + + Aber ich werde der letzte sein! + + + Jungbrunnen + + + Jungbrunnen + + + ... + + + ... + + + Du hast mich besiegt ... Aber zu welchem Preis? + + + Du hast mich besiegt ... Aber zu welchem Preis? + + + Tagebucheintrag #3 + + + Ich habe den Preis bezahlt und das Schloss betreten. Der Teufel Charon hat alles, was ich besitze, als Bezahlung genommen. + + + Ich habe vielleicht den König ermordet, aber nur nachdem er sein Volk verraten hatte. + + + Ich habe vielleicht den König ermordet, aber nur nachdem er sein Volk verraten hatte. + + + Frage dich selbst, welcher Gerechtigkeit damit Genüge getan wurde? + + + Frage dich selbst, welcher Gerechtigkeit damit Genüge getan wurde? + + + Am Ende machen wir uns alle derselben Sünde schuldig. Schaue zu deinen Vorfahren – dies ist der Preis von unumstrittener Loyalität. + + + Am Ende machen wir uns alle derselben Sünde schuldig. Schaue zu deinen Vorfahren – dies ist der Preis von unumstrittener Loyalität. + + + ... + + + ... + + + ... + + + ... + + + Die Sonne ... + + + Die Sonne ... + + + Ich hatte vergessen, wie sie sich anfühlt ... + + + Ich hatte vergessen, wie sie sich anfühlt ... + + + Ich habe den Preis bezahlt und das Schloss betreten. Der Teufel Charon hat alles, was ich besitze, als Bezahlung genommen. + + + Er hat sogar meine eigene Schatzkammer geleert! Ich habe meine Frau und meine Kinder mit nichts zurückgelassen. + + + Er hat sogar meine eigene Schatzkammer geleert! Ich habe meine Frau und meine Kinder mit nichts zurückgelassen. + + + Tagebuch des Prinzen + + + Tagebucheintrag #1 + + + Er sagt, das sei der Preis für alle, die in die Tiefen des Schlosses vordringen. Er sagt, es sei gerecht. + + + Er sagt, das sei der Preis für alle, die in die Tiefen des Schlosses vordringen. Er sagt, es sei gerecht. + + + Es ist deshalb gerecht, da von allen, die es betreten haben, niemand zurückgekehrt ist. Aber ich werde das ändern. + + + Es ist deshalb gerecht, da von allen, die es betreten haben, niemand zurückgekehrt ist. Aber ich werde das ändern. + + + Ich werde siegreich sein! Es gibt keinen besseren Schwertkämpfer als mich, selbst nicht unter meinen Geschwistern. + + + Ich werde siegreich sein! Es gibt keinen besseren Schwertkämpfer als mich, selbst nicht unter meinen Geschwistern. + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #4 + + + Tagebucheintrag #4 + + + Alles an diesem Schloss ist falsch. Ich verliere ständig meinen Pfad aus den Augen und es gibt keine Sonne und Sterne, die mich leiten könnten. + + + Alles an diesem Schloss ist falsch. Ich verliere ständig meinen Pfad aus den Augen und es gibt keine Sonne und Sterne, die mich leiten könnten. + + + Mir kommt vor, ich bewege mich einen Schritt nach vorne und zwei Schritte zurück. Ich muss meinen Fortschritt gewissenhaft aufzeichnen, sonst werde ich ewig im Kreis gehen. + + + Mir kommt vor, ich bewege mich einen Schritt nach vorne und zwei Schritte zurück. Ich muss meinen Fortschritt gewissenhaft aufzeichnen, sonst werde ich ewig im Kreis gehen. + + + Die Karten, die ich den Leichen anderer Abenteurer abgenommen habe, sind atemberaubend ungenau. Es ist fast so, also ob sie ein ganz anderes Schloss beschreiben! + + + Die Karten, die ich den Leichen anderer Abenteurer abgenommen habe, sind atemberaubend ungenau. Es ist fast so, also ob sie ein ganz anderes Schloss beschreiben! + + + Vielleicht stellt dieser Ort etwas mit dem Verstand an ... + + + Vielleicht stellt dieser Ort etwas mit dem Verstand an ... + + + Oder bewegen sich die Steine unter meinen Füßen tatsächlich? + + + Oder bewegen sich die Steine unter meinen Füßen tatsächlich? + + + Tagebucheintrag #1 + + + Verrat! Ein Attentäter hat meinen Vater, den König, verwundet! + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #5 + + + Tagebucheintrag #5 + + + Ich kann nicht durch das Vordertor hinaus, aber das ist nicht wichtig. Ich habe mich dieser Sache verschrieben und werde keinen Rückzieher machen! + + + Ich kann nicht durch das Vordertor hinaus, aber das ist nicht wichtig. Ich habe mich dieser Sache verschrieben und werde keinen Rückzieher machen! + + + Bis jetzt hat keine der Karten, die ich gefunden habe, mit meiner eigenen überein gestimmt. + + + Bis jetzt hat keine der Karten, die ich gefunden habe, mit meiner eigenen überein gestimmt. + + + Nachdem ich sie allerdings miteinander verglichen habe, glaube ich, ein leichtes Muster erkennen zu können. Anscheinend liegt der Wald immer rechts, der Turm oben ... + + + Nachdem ich sie allerdings miteinander verglichen habe, glaube ich, ein leichtes Muster erkennen zu können. Anscheinend liegt der Wald immer rechts, der Turm oben ... + + + Und unten? Nun, das muss ich hoffentlich nicht herausfinden. + + + Und unten? Nun, das muss ich hoffentlich nicht herausfinden. + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #6 + + + Tagebucheintrag #6 + + + Ich mochte die Dunkelheit noch nie. Ich ziehe es vor, meine Feinde auf dem offenen Feld zu treffen, wo ich sie klar sehen kann. + + + Ich mochte die Dunkelheit noch nie. Ich ziehe es vor, meine Feinde auf dem offenen Feld zu treffen, wo ich sie klar sehen kann. + + + Aber jetzt kämpfe ich mich durch die Dunkelheit, mit einer Hand nach vorne und der anderen an meinem Schwertgriff. Ich kann mir nie sicher sein, welcher Schrecken hinter der nächsten Ecke lauert. + + + Aber jetzt kämpfe ich mich durch die Dunkelheit, mit einer Hand nach vorne und der anderen an meinem Schwertgriff. Ich kann mir nie sicher sein, welcher Schrecken hinter der nächsten Ecke lauert. + + + Verrat! Ein Attentäter hat meinen Vater, den König, verwundet! + + + Um die Ordnung im Königreich wiederherzustellen, hat er mich und meine Geschwister auf eine Mission geschickt, um ihn zu retten. Zusammen werden wir uns in den verfluchten Wald begeben und Schloss Hamson betreten. + + + Ich bin der größte Schwertkämpfer weit und breit, doch selbst ich habe Probleme, diese Dämonen im Zaum zu halten. + + + Ich bin der größte Schwertkämpfer weit und breit, doch selbst ich habe Probleme, diese Dämonen im Zaum zu halten. + + + Meine Geschwister sollten dankbar sein, dass ich ihnen vorausgeeilt bin. Für sie ist das in Wirklichkeit ein Segen. Sie hätten nicht die Standhaftigkeit, diese Hallen zu überleben. + + + Meine Geschwister sollten dankbar sein, dass ich ihnen vorausgeeilt bin. Für sie ist das in Wirklichkeit ein Segen. Sie hätten nicht die Standhaftigkeit, diese Hallen zu überleben. + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #7 + + + Tagebucheintrag #7 + + + Es ist immer noch Nacht. Hinter jedem Fenster starrt derselbe melancholische Mond zurück, aber ich schwöre, dass ich schon mindestens einen ganzen Tag hier bin. + + + Es ist immer noch Nacht. Hinter jedem Fenster starrt derselbe melancholische Mond zurück, aber ich schwöre, dass ich schon mindestens einen ganzen Tag hier bin. + + + Es muss das Adrenalin sein. Ich habe mich noch nie so mächtig gefühlt, aber gleichzeitig doch gefordert. Es ist ein erhebendes Gefühl, durch diese Räume zu rennen und einen Feind nach dem anderen zu töten. + + + Es muss das Adrenalin sein. Ich habe mich noch nie so mächtig gefühlt, aber gleichzeitig doch gefordert. Es ist ein erhebendes Gefühl, durch diese Räume zu rennen und einen Feind nach dem anderen zu töten. + + + Irgendwie fühlen sich die Feinde in diesem Schloss an, als seien sie für mich maßgeschneidert. Sie trainieren mich, leiten mich, beobachten mich. + + + Irgendwie fühlen sich die Feinde in diesem Schloss an, als seien sie für mich maßgeschneidert. Sie trainieren mich, leiten mich, beobachten mich. + + + Es klingt verrückt, aber wenn dieses Schloss irgendwie spüren kann, wer es betritt, dann hat es vielleicht auch böse Absichten. Wenn das stimmt, könnte die Anordnung dieser Räume dazu gedacht sein, mich in die Falle zu locken. + + + Es klingt verrückt, aber wenn dieses Schloss irgendwie spüren kann, wer es betritt, dann hat es vielleicht auch böse Absichten. Wenn das stimmt, könnte die Anordnung dieser Räume dazu gedacht sein, mich in die Falle zu locken. + + + Ich muss wachsam bleiben. + + + Ich muss wachsam bleiben. + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Um die Ordnung im Königreich wiederherzustellen, hat er mich und meine Geschwister auf eine Mission geschickt, um ihn zu retten. Zusammen werden wir uns in den verfluchten Wald begeben und Schloss Hamson betreten. + + + Seit Urzeiten steht dieses verfluchte Schloss am Rand des Waldes, aber Gerüchten zufolge soll sich darin ein Gegenstand befinden, der alle Krankheiten heilen kann. + + + Tagebucheintrag #8 + + + Tagebucheintrag #8 + + + Der Anzahl der Abenteurer in diesen Hallen zufolge, bin ich zu dem folgenden Schluss gekommen: + + + Der Anzahl der Abenteurer in diesen Hallen zufolge, bin ich zu dem folgenden Schluss gekommen: + + + 1: Viele haben nicht ausreichend Proviant mitgenommen. Ich nehme an, dass viele verhungert sind. Ich selbst habe nicht mehr viel und muss mehr Vorräte finden. + + + 1: Viele haben nicht ausreichend Proviant mitgenommen. Ich nehme an, dass viele verhungert sind. Ich selbst habe nicht mehr viel und muss mehr Vorräte finden. + + + 2: Vielen fehlt Kleidung, was die hosentragenden Zombies erklärt. + + + 2: Vielen fehlt Kleidung, was die hosentragenden Zombies erklärt. + + + 3: Niemand ist so weit gekommen wie ich, da ich schon über eine Stunde keine Leichen mehr gesehen habe. + + + 3: Niemand ist so weit gekommen wie ich, da ich schon über eine Stunde keine Leichen mehr gesehen habe. + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #9 + + + Tagebucheintrag #9 + + + Die Tür zum Thronsaal macht mich verrückt! Dahinter liegen die Rettung des Königs und meine Belohnung, aber sie steht einfach stillschweigend mitten in der Eingangshalle und verhöhnt mich. + + + Die Tür zum Thronsaal macht mich verrückt! Dahinter liegen die Rettung des Königs und meine Belohnung, aber sie steht einfach stillschweigend mitten in der Eingangshalle und verhöhnt mich. + + + Ich habe versucht, sie zu schieben, sie zu treten und "Sesam, öffne dich" zu rufen, aber nichts hilft. + + + Ich habe versucht, sie zu schieben, sie zu treten und "Sesam, öffne dich" zu rufen, aber nichts hilft. + + + Die Tür ist mit Symbolen geschmückt, wovon eines aussieht wie eine Bestie, die ich tiefer im Schloss vermieden habe. Vielleicht gibt es da einen Zusammenhang? + + + Die Tür ist mit Symbolen geschmückt, wovon eines aussieht wie eine Bestie, die ich tiefer im Schloss vermieden habe. Vielleicht gibt es da einen Zusammenhang? + + + Seit Urzeiten steht dieses verfluchte Schloss am Rand des Waldes, aber Gerüchten zufolge soll sich darin ein Gegenstand befinden, der alle Krankheiten heilen kann. + + + Heute Nacht verschaffe ich mir einen Vorsprung. Während meine Brüder und Schwestern noch schlafen, werde ich mich bereits auf den Weg machen. + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #10 + + + Tagebucheintrag #10 + + + Die Symbole auf der Tür sind ein Hinweis! Ich habe die riesige Bestie getötet, die eines der Symbole zeigt, und gespürt, wie sich etwas hinter der Tür zum Thronsaal bewegt hat. + + + Die Symbole auf der Tür sind ein Hinweis! Ich habe die riesige Bestie getötet, die eines der Symbole zeigt, und gespürt, wie sich etwas hinter der Tür zum Thronsaal bewegt hat. + + + Wie in einem Traum konnte ich ein Symbol auf der Tür vor meinem geistigen Auge leuchten sehen. + + + Wie in einem Traum konnte ich ein Symbol auf der Tür vor meinem geistigen Auge leuchten sehen. + + + Wahrhaftig eine außerkörperliche Erfahrung. + + + Wahrhaftig eine außerkörperliche Erfahrung. + + + Zumindest weiß ich, dass ich auf dem richtigen Weg bin. Aber ich muss mich beeilen, denn der König könnte jeden Moment seinen Verletzungen erliegen ... + + + Zumindest weiß ich, dass ich auf dem richtigen Weg bin. Aber ich muss mich beeilen, denn der König könnte jeden Moment seinen Verletzungen erliegen ... + + + Aber zuerst muss ich mich ausruhen. Morgen betrete ich den Wald. + + + Aber zuerst muss ich mich ausruhen. Morgen betrete ich den Wald. + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #11 + + + Tagebucheintrag #11 + + + Dieser Wald ist mit nichts zu vergleichen, was ich jemals gesehen habe. Er ist sowohl heiter als auch beängstigend. Ich stehe auf üppigem Gras, aber neben mir klafft ein Abgrund so weit und tief, dass er mich zu verschlucken droht. + + + Dieser Wald ist mit nichts zu vergleichen, was ich jemals gesehen habe. Er ist sowohl heiter als auch beängstigend. Ich stehe auf üppigem Gras, aber neben mir klafft ein Abgrund so weit und tief, dass er mich zu verschlucken droht. + + + Heute Nacht verschaffe ich mir einen Vorsprung. Während meine Brüder und Schwestern noch schlafen, werde ich mich bereits auf den Weg machen. + + + Es wäre eine Schande für meinen Namen, bei dieser Mission zu versagen. + + + Ich habe vorhin einen Stein hineingeworfen, aber immer noch keinen Aufprall gehört. Ein falscher Schritt und ich stürze unendlich in die Tiefe. Ein wahrhaft furchterregender Gedanke. + + + Ich habe vorhin einen Stein hineingeworfen, aber immer noch keinen Aufprall gehört. Ein falscher Schritt und ich stürze unendlich in die Tiefe. Ein wahrhaft furchterregender Gedanke. + + + Eine Ewigkeit in der Finsternis macht mir mehr Angst als jede Bestie, die ich bisher bekämpft habe. Was würde mich wohl zuerst umbringen, wenn ich fallen sollte? Der Hunger, oder ich mich selbst? + + + Eine Ewigkeit in der Finsternis macht mir mehr Angst als jede Bestie, die ich bisher bekämpft habe. Was würde mich wohl zuerst umbringen, wenn ich fallen sollte? Der Hunger, oder ich mich selbst? + + + Nebenbei bemerkt nutze ich die Schlucht im Wald als meine persönliche Toilette. Ich frage mich, ob ich mich in eine andere Dimension erleichtere ... + + + Nebenbei bemerkt nutze ich die Schlucht im Wald als meine persönliche Toilette. Ich frage mich, ob ich mich in eine andere Dimension erleichtere ... + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #12 + + + Tagebucheintrag #12 + + + Ich habe eine Lösung für meine Hungerproblem gefunden. Im Wald gibt es einen unendlichen Vorrat an leckeren Pilzen. + + + Ich habe eine Lösung für meine Hungerproblem gefunden. Im Wald gibt es einen unendlichen Vorrat an leckeren Pilzen. + + + Und in diesen Pilzen stecken Hühnerkeulen! Auch Goldmünzen und Fläschchen mit funkelndem Wasser ... Vorhin habe ich einen Baumstumpf aufgebrochen und ein Geldbeutel fiel heraus. + + + Und in diesen Pilzen stecken Hühnerkeulen! Auch Goldmünzen und Fläschchen mit funkelndem Wasser ... Vorhin habe ich einen Baumstumpf aufgebrochen und ein Geldbeutel fiel heraus. + + + Manchmal denke ich, dass ich verrückt geworden bin. + + + Manchmal denke ich, dass ich verrückt geworden bin. + + + ... Und was ist mit diesem Mond los? Er ist RIESIG! + + + ... Und was ist mit diesem Mond los? Er ist RIESIG! + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Es wäre eine Schande für meinen Namen, bei dieser Mission zu versagen. + + + Tagebuch des Prinzen + + + Tagebucheintrag #13 + + + Tagebucheintrag #13 + + + Ich habe die Bestie des Waldes getötet und habe gespürt, wie der Thronraum wieder schwächer wurde. + + + Ich habe die Bestie des Waldes getötet und habe gespürt, wie der Thronraum wieder schwächer wurde. + + + Bis jetzt hatte ich recht. Jeder Flügel des Schlosses ist Heimat einer Wächterbestie. Soll das meine Entschlossenheit testen? Wenn ja, dann kann ich nicht scheitern, denn mit jedem Schritt werde ich mutiger. + + + Bis jetzt hatte ich recht. Jeder Flügel des Schlosses ist Heimat einer Wächterbestie. Soll das meine Entschlossenheit testen? Wenn ja, dann kann ich nicht scheitern, denn mit jedem Schritt werde ich mutiger. + + + Morgen durchkämme ich den Turm. Ich habe einen Lauf. + + + Morgen durchkämme ich den Turm. Ich habe einen Lauf. + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #14 + + + Tagebucheintrag #14 + + + Auf meiner Suche nach dem nächsten Wächter habe ich all diese Räume systematisch von Dämonen gesäubert, aber ich verliere mein Zeitgefühl ... und andere Gefühle auch … + + + Auf meiner Suche nach dem nächsten Wächter habe ich all diese Räume systematisch von Dämonen gesäubert, aber ich verliere mein Zeitgefühl ... und andere Gefühle auch … + + + Als ich den Turm betrat, spürte ich, wie die Zeit stillstand. Oder vielleicht spricht da die Höhenangst? Ich hatte nie viel für Höhen übrig ... oder doch? + + + Als ich den Turm betrat, spürte ich, wie die Zeit stillstand. Oder vielleicht spricht da die Höhenangst? Ich hatte nie viel für Höhen übrig ... oder doch? + + + Mir fällt es immer schwerer, mich an meine Vergangenheit zu erinnern ... + + + Mir fällt es immer schwerer, mich an meine Vergangenheit zu erinnern ... + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #2 + + + Tagebucheintrag #15 + + + Tagebucheintrag #15 + + + Ich erinnere mich … ich war ein berühmter Abenteurer. In der Kampfkunst meinen Brüdern weit voraus, da bin ich mir sicher. Während sie mit ihren Nasen in Büchern steckten, war ich aus, um Monster und Briganten zu töten. + + + Ich erinnere mich … ich war ein berühmter Abenteurer. In der Kampfkunst meinen Brüdern weit voraus, da bin ich mir sicher. Während sie mit ihren Nasen in Büchern steckten, war ich aus, um Monster und Briganten zu töten. + + + Ich habe mich immer gefragt, warum mein Vater sie mir vorgezogen hat. Ist es in Märchen nicht immer umgekehrt? + + + Ich habe mich immer gefragt, warum mein Vater sie mir vorgezogen hat. Ist es in Märchen nicht immer umgekehrt? + + + Das Glück ist mit den Tapferen. Nicht mit den geistlosen Intellektuellen ... Oder so. + + + Das Glück ist mit den Tapferen. Nicht mit den geistlosen Intellektuellen ... Oder so. + + + Mann, ich würde gerne sehen, wie meine Brüder versuchen, mein Schwert aus ihrem Gesicht wegzudenken! + + + Mann, ich würde gerne sehen, wie meine Brüder versuchen, mein Schwert aus ihrem Gesicht wegzudenken! + + + Tagebuch des Prinzen + + + Tagebuch des Prinzen + + + Tagebucheintrag #16 + + + Tagebucheintrag #16 + + + Was, wenn schon Jahre vergangen sind, seit ich diese Gemäuer zum ersten Mal betrat? Ich werde zwar immer geschickter im Ausrotten dieser Monster, aber es fühlt sich an, als ob eine Ewigkeit vergangen ist. + + + Was, wenn schon Jahre vergangen sind, seit ich diese Gemäuer zum ersten Mal betrat? Ich werde zwar immer geschickter im Ausrotten dieser Monster, aber es fühlt sich an, als ob eine Ewigkeit vergangen ist. + + + Ich habe sogar vergessen, wie meine eigenen Verwandten aussehen. + + + Ich habe sogar vergessen, wie meine eigenen Verwandten aussehen. + + + Und wenn sie denken, dass ich versagt habe? Vielleicht war einer meiner Brüder das Heilmittel vor mir erreicht? + + + Und wenn sie denken, dass ich versagt habe? Vielleicht war einer meiner Brüder das Heilmittel vor mir erreicht? + + + Tagebucheintrag #2 + + + Eintrag # + + + Eintrag # + + + {0} Gold spenden, um deinen Geist für diesen Boss dauerhaft zu verstärken?\nBisher {1}-mal verstärkt. + + + Deine Spendenkiste ist randvoll. Du kannst deinen Geist nicht weiter verstärken. Danke für die Kohle, Kumpel. + + + Du kannst dir die Spende nicht leisten. Komm wieder, wenn du dir mehr Gold verdient hast. + + + Dein Geist ist stärker geworden! + + + Spendenbox + + + Schloss Hamson + + + Schloss Hamson + + + Das Land der Dunkelheit + + + Das Land der Dunkelheit + + + Abchasien-Wald + + + Abchasien-Wald + + + Das Maya + + + Das Maya + + + Wähle eine Kategorie + + + Rune notwendig + + + Rune notwendig + + + Kaufinformation hier + + + Kaufinformation hier + + + {0} zum Freischalten + + + {0} zum Freischalten + + + rune + + + rune + + + Wähle eine Kategorie + + + Anweisungen + + + Anweisungen + + + [Input:0]: wählen/ausrüsten + + + [Input:0]: wählen/ausrüsten + + + [Input:2]: abbrechen/Menü schließen + + + [Input:2]: abbrechen/Menü schließen + + + Pfeiltasten, um zu navigieren + + + Pfeiltasten, um zu navigieren + + + [Button:LeftStick] zum Navigieren + + + [Button:LeftStick] zum Navigieren + + + Getötet + + + Getötet + + + [Input:0] zum Verlassen + + + [Input:0] zum Verlassen + + + Skelett + + + Blobbosaurus Rex + + + Opa Funke + + + Opa Funke + + + Fürst Funke, König von Funkhausen + + + Fürst Funke, König von Funkhausen + + + Mimik + + + Mimik + + + Mimikant + + + Mimikant + + + Mimiknirsch + + + Mimiknirsch + + + Truhbadour + + + Truhbadour + + + Barbatos + + + Barbatos + + + Stolas + + + Stolas + + + Berith + + + Berith + + + Amon + + + Amon + + + Blobbosaurus Rex + + + Herodot + + + Focalor + + + Focalor + + + Halphas + + + Halphas + + + Neo-Khidr + + + Neo-Khidr + + + Alexander IV. + + + Alexander IV. + + + Astrodot + + + Astrodot + + + Ponce de Freon + + + Ponce de Freon + + + Johannes Bros. + + + Johannes Bros. + + + Wandgeschütz + + + Wandgeschütz + + + Der Torwächter + + + Der Torwächter + + + Der Unendliche + + + Der Unendliche + + + Herodot + + + Kettor + + + Der Vergessene + + + Der Vergessene + + + Der Verlorene + + + Der Verlorene + + + Der Verdammte + + + Der Verdammte + + + Der Verräter + + + Der Verräter + + + Der Brunnen + + + Der Brunnen + + + Berith & Halphas + + + Berith & Halphas + + + Barbatos & Amon + + + Barbatos & Amon + + + Stolas & Focalor + + + Stolas & Focalor + + + Kettor + + + Kettex + + + Kettex + + + Kettus + + + Kettus + + + Pantheon + + + Pantheon + + + Erdmagus + + + Erdmagus + + + Gravitagus + + + Gravitagus + + + Terragus + + + Terragus + + + Flammenhexer + + + Flammenhexer + + + Skelett + + + Knochenknilch + + + Gluthexor + + + Gluthexor + + + Solarhexus + + + Solarhexus + + + Solarmagier + + + Solarmagier + + + Frosterer + + + Frosterer + + + Eiserer + + + Eiserer + + + Gletscherer + + + Gletscherer + + + Lunarmagier + + + Lunarmagier + + + Späher + + + Späher + + + Pupille + + + Pupille + + + Visionär + + + Visionär + + + Knochenknilch + + + McRipp + + + Khidr + + + Khidr + + + Wut + + + Wut + + + Rage + + + Rage + + + Zorn + + + Zorn + + + Alexander + + + Alexander + + + Große Wache + + + Große Wache + + + Kolosswache + + + Kolosswache + + + Turmwache + + + Turmwache + + + Schildwache + + + Schildwache + + + Stachlor + + + Stachlor + + + McRipp + + + Korrupter Ritter + + + Stachlex + + + Stachlex + + + Stachlus + + + Stachlus + + + Stachler + + + Stachler + + + Grauer Ritter + + + Grauer Ritter + + + Grauer Baron + + + Grauer Baron + + + Graudiator + + + Graudiator + + + Graupion + + + Graupion + + + Warg + + + Warg + + + Wargen + + + Wargen + + + Wargenflorgen + + + Wargenflorgen + + + Korrupter Ritter + + + Korrupter Gardist + + + Zorgwarg + + + Zorgwarg + + + Zombie + + + Zombie + + + Zombator + + + Zombator + + + Zombishnu + + + Zombishnu + + + Zomg + + + Zomg + + + Energon + + + Energon + + + Mastertron + + + Mastertron + + + Voltron + + + Voltron + + + Prime + + + Prime + + + Ninjo + + + Ninjo + + + Korrupter Gardist + + + Korrupter Fürst + + + Ninpo + + + Ninpo + + + Ninpojo + + + Ninpojo + + + Ninjameister + + + Ninjameister + + + Knospe + + + Knospe + + + Pflanzling + + + Pflanzling + + + Blumon + + + Blumon + + + Kohlit + + + Kohlit + + + Pyrit + + + Pyrit + + + Infernit + + + Infernit + + + Ponce de Leon + + + Ponce de Leon + + + Korrupter Fürst + + + Botis + + + Stachelfalle + + + Stachelfalle + + + Bogenschütze + + + Bogenschütze + + + Heckenschütze + + + Heckenschütze + + + Scharfschütze + + + Scharfschütze + + + Jägermeister + + + Jägermeister + + + Johannes + + + Johannes + + + Der Brunnen + + + Der Brunnen + + + Jungbrunnen + + + Jungbrunnen + + + Unheilsbild + + + Unheilsbild + + + Unheilsporträt + + + Unheilsporträt + + + Botis + + + Blob + + + Unheilswerk + + + Unheilswerk + + + Sallos + + + Sallos + + + Plinki + + + Plinki + + + Planki + + + Planki + + + Plonki + + + Plonki + + + Ploo + + + Ploo + + + Kentucky + + + Kentucky + + + Fried + + + Fried + + + Chicken + + + Chicken + + + Leckerschmecker + + + Leckerschmecker + + + Blob + + + Blobit + + + Wachkiste + + + Wachkiste + + + Wachkiste XL + + + Wachkiste XL + + + Wachkiste 2000 + + + Wachkiste 2000 + + + Wachkiste Giganto + + + Wachkiste Giganto + + + Kopfloses Pferd + + + Kopfloses Pferd + + + Dunkler Hengst + + + Dunkler Hengst + + + Nachtmähre + + + Nachtmähre + + + Mein kleines Pony + + + Mein kleines Pony + + + Fünklein + + + Fünklein + + + Herr Funke + + + Herr Funke + + + Blobit + + + Springen + + + Fluch + + + Fluch + + + Gnaden + + + Gnaden + + + Architektenhonorar + + + Architektenhonorar + + + NS+ Bonus + + + NS+ Bonus + + + Springen + + + Sprinten + + + Sprinten + + + Vampir + + + Vampir + + + Fliegen + + + Fliegen + + + Absorption + + + Absorption + + + Gleichgewicht + + + Gleichgewicht + + + Vergeltung + + + Vergeltung + + + Beute + + + Beute + + + Eile + + + Eile + + + Sprung + + + Fluch + + + Fluch + + + Gnaden + + + Gnaden + + + Architektenhonorar + + + Architektenhonorar + + + NS+ Bonus + + + NS+ Bonus + + + Sprung + + + Sprint + + + Sprint + + + Vampir + + + Vampir + + + Himmels + + + Himmels + + + Absorptions + + + Absorptions + + + Gleichgewichts + + + Gleichgewichts + + + Vergeltungs + + + Vergeltungs + + + Beute + + + Beute + + + Eil + + + Eil + + + Knappen + + + Rächer + + + Rächer + + + Weisen + + + Weisen + + + Blut + + + Blut + + + Vergeltungs + + + Vergeltungs + + + Sakral + + + Sakral + + + Schatten + + + Schatten + + + Knappen + + + Silber + + + Silber + + + Wächter + + + Wächter + + + Kaiser + + + Kaiser + + + Königs + + + Königs + + + Ritter + + + Ritter + + + Waldläufer + + + Waldläufer + + + Himmels + + + Himmels + + + Drachen + + + Drachen + + + {0}{1} + + + Schwert + + + Schwert + + + Umhang + + + Umhang + + + Armschienen + + + Armschienen + + + Helm + + + Helm + + + Brustplatte + + + Brustplatte + + + Nichts + + + Nichts + + + schwert + + + schwert + + + umhang + + + umhang + + + schienen + + + schienen + + + helm + + + helm + + + brustplatte + + + brustplatte + + + Nichts + + + Nichts + + + Gewährt dir die Kraft, in der Luft zu springen. Mehrere gestapelte Runen ermöglichen mehrere Sprünge. + + + Schwerere Gegner, aber bessere Belohnungen. Mehrere gestapelte Runen machen Feinde sogar noch schwerer zu besiegen. + + + Schwerere Gegner, aber bessere Belohnungen. Mehrere gestapelte Runen machen Feinde sogar noch schwerer zu besiegen. + + + Leichtere Gegner, aber geringere Belohnungen. Mehrere gestapelte Runen machen Feinde noch einfacher zu besiegen. + + + Leichtere Gegner, aber geringere Belohnungen. Mehrere gestapelte Runen machen Feinde noch einfacher zu besiegen. + + + Gewährt dir die Kraft, in der Luft zu springen. Mehrere gestapelte Runen ermöglichen mehrere Sprünge. + + + Gewährt dir die Kraft, über kurze Strecken zu sprinten. Mehrere gestapelte Runen ermöglichen mehrere Sprints. + + + Gewährt dir die Kraft, über kurze Strecken zu sprinten. Mehrere gestapelte Runen ermöglichen mehrere Sprints. + + + Stiehlt Leben von getöteten Feinden. Mehrere gestapelte Runen erhöhen den Manaentzug. + + + Stiehlt Leben von getöteten Feinden. Mehrere gestapelte Runen erhöhen den Manaentzug. + + + Gewährt dir die Kraft zu fliegen. Mehrere gestapelte Runen gewähren dir eine längere Flugdauer. + + + Gewährt dir die Kraft zu fliegen. Mehrere gestapelte Runen gewähren dir eine längere Flugdauer. + + + Stiehlt Mana von getöteten Feinden. Mehrere gestapelte Runen erhöhen den Manaentzug. + + + Stiehlt Mana von getöteten Feinden. Mehrere gestapelte Runen erhöhen den Manaentzug. + + + Entzieht getöteten Feinden sowohl LP als auch MP. Mehrere gestapelte Runen verstärken den Effekt. + + + Entzieht getöteten Feinden sowohl LP als auch MP. Mehrere gestapelte Runen verstärken den Effekt. + + + Fügt erlittenen Schaden auch den Angreifern zu. Mehrere gestapelte Runen erhöht den reflektierten Schaden. + + + Fügt erlittenen Schaden auch den Angreifern zu. Mehrere gestapelte Runen erhöht den reflektierten Schaden. + + + Erhöht die Menge an Gold, die man von Münzen erhält. Mehrere gestapelte Runen erhöhen den Goldgewinn. + + + Erhöht die Menge an Gold, die man von Münzen erhält. Mehrere gestapelte Runen erhöhen den Goldgewinn. + + + Erhöht deine Laufgeschwindigkeit. Mehrere gestapelte Runen machen dich sogar noch schneller. + + + Erhöht deine Laufgeschwindigkeit. Mehrere gestapelte Runen machen dich sogar noch schneller. + + + Feinde sind schwieriger. + + + Feinde sind schwieriger. + + + Feinde sind leichter. + + + Feinde sind leichter. + + + Drücke [Input:10], während du in der Luft bist. + + + Drücke [Input:10], während du in der Luft bist. + + + Sprinte: [Input:14] oder [Input:15] + + + Sprinte: [Input:14] oder [Input:15] + + + Töte Feinde, um Leben zurückzugewinnen. + + + Töte Feinde, um Leben zurückzugewinnen. + + + Drücke [Input:10], während du in der Luft bist. + + + Drücke [Input:10], während du in der Luft bist. + + + Töte Feinde, um Mana zurückzugewinnen. + + + Töte Feinde, um Mana zurückzugewinnen. + + + Töte Feinde, um Leben und Mana zurückzugewinnen. + + + Töte Feinde, um Leben und Mana zurückzugewinnen. + + + Reflektiert erlittenen Schaden. + + + Reflektiert erlittenen Schaden. + + + Münzen geben mehr Gold. + + + Münzen geben mehr Gold. + + + Bewege dich schneller. + + + Bewege dich schneller. + + + Kritische Trefferchance + + + Luftsprint + + + Luftsprint + + + Verteidigen + + + Verteidigen + + + Schweben + + + Schweben + + + Kann Projektile angreifen + + + Kann Projektile angreifen + + + Flug + + + Flug + + + Geschwindigkeit + + + Geschwindigkeit + + + Nichts + + + Nichts + + + Kritische Trefferchance + + + Kritischer Schaden + + + Kritischer Schaden + + + Vampirismus + + + Vampirismus + + + Goldbonus + + + Goldbonus + + + MP-Absorption + + + MP-Absorption + + + EP-Bonus + + + EP-Bonus + + + Luftangriff + + + Luftangriff + + + Luftsprung + + + Luftsprung + + + Schadensreflektion + + + Schadensreflektion + + + Verdiene im Schloss 60% Gold. + + + Verdiene im Schloss 60% Gold. + + + Beute um {0}% erhöht + + + Beute um {0}% erhöht + + + Feinde beginnen {0} Level höher. + + + Feinde beginnen {0} Level höher. + + + Feinde beginnen {0} Level niedriger. + + + Feinde beginnen {0} Level niedriger. + + + Feinde beginnen {0} Level niedriger. + + + Feinde beginnen {0} Level niedriger. + + + Springe {0}-mal in der Luft. + + + Springe {0}-mal in der Luft. + + + Springe {0}-mal in der Luft. + + + Springe {0}-mal in der Luft. + + + Sprinte bis zu {0}-mal. + + + Sprinte bis zu {0}-mal. + + + Sprinte bis zu {0}-mal. + + + Sprinte bis zu {0}-mal. + + + Erhalte {0} LP für jede Tötung zurück. + + + Erhalte {0} LP für jede Tötung zurück. + + + Fliege für {0} Sekunden. + + + Fliege für {0} Sekunden. + + + Fliege für {0} Sekunden. + + + Fliege für {0} Sekunden. + + + Erhalte {0} MP für jede Tötung zurück. + + + Erhalte {0} MP für jede Tötung zurück. + + + Mana-LP + + + Mana-LP + + + Reflektiere {0}% erlittenen Schaden. + + + Reflektiere {0}% erlittenen Schaden. + + + Goldbeute ist {0}% mehr wert. + + + Goldbeute ist {0}% mehr wert. + + + Bewege dich {0}% schneller. + + + Bewege dich {0}% schneller. + + + Rogue Legacy beenden + + + Rogue Legacy beenden + + + Drücke [Input:0], um weiterzumachen. + + + Drücke [Input:0], um weiterzumachen. + + + Die Sonne ... Ich hatte vergessen, wie sie sich anfühlt ... + + + Die Sonne ... Ich hatte vergessen, wie sie sich anfühlt ... + + + {0} wurde von {1} getötet. + + + {0} wurde von {1} getötet. + + + Drücke [Input:0], um weiterzumachen. + + + Drücke [Input:0], um weiterzumachen. + + + {0} wurde von {1} getötet. + + + {0} wurde von {1} getötet. + + + {0} wurde von {1} getötet. + + + {0} wurde von {1} getötet. + + + {0} wurde von einem Projektil getötet. + + + {0} wurde von einem Projektil getötet. + + + {0} ist ausgerutscht und wurde aufgespießt. + + + {0} ist ausgerutscht und wurde aufgespießt. + + + {0} wurde getötet. + + + {0} wurde getötet. + + + -Letze Worte von {0} + + + -Letze Worte von {0} + + + [Input:0], um fortzufahren + + + [Input:0], um fortzufahren + + + LP erhöht + + + LP erhöht + + + MP erhöht + + + MP erhöht + + + Stärke erhöht + + + Stärke erhöht + + + Magieschaden erhöht + + + Magieschaden erhöht + + + Rüstung erhöht + + + Rüstung erhöht + + + Maximales Gewicht erhöht + + + Maximales Gewicht erhöht + + + Medaillon fertiggestellt! + + + Medaillon fertiggestellt! + + + Du hast Teil eines Medaillons gefunden! + + + Du hast Teil eines Medaillons gefunden! + + + Der Wald liegt immer an der rechten Seite des Schlosses. + + + Mit Himmelsrunen kannst du fliegen, indem du in der Luft [Input:10] drückst. + + + Mit Himmelsrunen kannst du fliegen, indem du in der Luft [Input:10] drückst. + + + Vampirismus- und Absorptionsrunen sind sehr mächtig, wenn sie gestapelt werden. + + + Vampirismus- und Absorptionsrunen sind sehr mächtig, wenn sie gestapelt werden. + + + Wenn du die Mobilitätsrunen meisterst, kann dich nichts mehr aufhalten. + + + Wenn du die Mobilitätsrunen meisterst, kann dich nichts mehr aufhalten. + + + Vergiss nicht, dein Rittergut auszubauen. Du weißt nie, was sich dir offenbaren wird! + + + Vergiss nicht, dein Rittergut auszubauen. Du weißt nie, was sich dir offenbaren wird! + + + Alle Klassen können mit einzigartigen Klassenfähigkeiten verbessert werden. + + + Alle Klassen können mit einzigartigen Klassenfähigkeiten verbessert werden. + + + Freigeschaltete Klassenfähigkeiten können mit [Input:13] aktiviert werden. + + + Freigeschaltete Klassenfähigkeiten können mit [Input:13] aktiviert werden. + + + Verbessere deine Klassen frühzeitig, um mächtige Klassenfähigkeiten zu erhalten. + + + Verbessere deine Klassen frühzeitig, um mächtige Klassenfähigkeiten zu erhalten. + + + Wenn du mit einem Raum Probleme hast, such nach einem Weg, um ihn zu umgehen. + + + Wenn du mit einem Raum Probleme hast, such nach einem Weg, um ihn zu umgehen. + + + Du kannst deine Werte am schnellsten verbessern, indem du Ausrüstung kaufst. + + + Du kannst deine Werte am schnellsten verbessern, indem du Ausrüstung kaufst. + + + Ausrüstung zu kaufen ist günstiger und flexibler als deine Grundwerte zu verbessern. + + + Ausrüstung zu kaufen ist günstiger und flexibler als deine Grundwerte zu verbessern. + + + Der Wald liegt immer an der rechten Seite des Schlosses. + + + Das Maya liegt immer an der oberen Seite des Schlosses. + + + Du hättest das andere Kind auswählen sollen. + + + Du hättest das andere Kind auswählen sollen. + + + Runen sind sehr mächtig. Vergiss nicht, Runen anzulegen und auch zu verwenden! + + + Runen sind sehr mächtig. Vergiss nicht, Runen anzulegen und auch zu verwenden! + + + Lerne die Feinheiten deiner Zaubersprüche, um ihr Potenzial zu maximieren. + + + Lerne die Feinheiten deiner Zaubersprüche, um ihr Potenzial zu maximieren. + + + Die Axt kann Feinde mehrmals treffen, wenn du sie aus dem richtigen Winkel wirfst. + + + Die Axt kann Feinde mehrmals treffen, wenn du sie aus dem richtigen Winkel wirfst. + + + Weiche deinen eigenen Konflux-Kugeln aus, um ihren Schaden zu maximieren. + + + Weiche deinen eigenen Konflux-Kugeln aus, um ihren Schaden zu maximieren. + + + Weiche den Chakrams aus, wenn sie zurückfliegen, um ihren Schaden zu maximieren. + + + Weiche den Chakrams aus, wenn sie zurückfliegen, um ihren Schaden zu maximieren. + + + Besser Mana verschwenden im Kampf verschwenden als unnötig Schaden zu erleiden. + + + Besser Mana verschwenden im Kampf verschwenden als unnötig Schaden zu erleiden. + + + Um im Schloss zu überleben, solltest du gegnerische Bewegungsmuster gut studieren. + + + Um im Schloss zu überleben, solltest du gegnerische Bewegungsmuster gut studieren. + + + Stachelfallen suchen nach einem Puls, um Tote von den Lebenden zu unterscheiden. + + + Stachelfallen suchen nach einem Puls, um Tote von den Lebenden zu unterscheiden. + + + Drücke [Input:9], um die Karte zu öffnen. + + + Drücke [Input:9], um die Karte zu öffnen. + + + Das Maya liegt immer an der oberen Seite des Schlosses. + + + Die Dunkelheit liegt immer an der Unterseite des Schlosses. + + + Feentruhen beinhalten alle Runen des Spiels. Sie werden dir ungemein weiterhelfen. + + + Feentruhen beinhalten alle Runen des Spiels. Sie werden dir ungemein weiterhelfen. + + + Wenn du einen Feentruhen-Raum nicht schaffst, kann dir der Architekt helfen. + + + Wenn du einen Feentruhen-Raum nicht schaffst, kann dir der Architekt helfen. + + + Der Architekt berechnet für seine Dienste eine hohe Gebühr. + + + Der Architekt berechnet für seine Dienste eine hohe Gebühr. + + + Bosse lassen nach ihrem Tod große Mengen Gold fallen. + + + Bosse lassen nach ihrem Tod große Mengen Gold fallen. + + + Begrab mich mit meinem Geld. + + + Begrab mich mit meinem Geld. + + + Wenn du Probleme hast, könnte es dir helfen, Gnadenrunen auszurüsten. + + + Wenn du Probleme hast, könnte es dir helfen, Gnadenrunen auszurüsten. + + + Aktiviere Blitzfall, um mit [Input:18] nach unten zu schlagen und dich fallen zu lassen. + + + Aktiviere Blitzfall, um mit [Input:18] nach unten zu schlagen und dich fallen zu lassen. + + + Der Architekt ist sehr nützlich, um die Bosse zu üben. + + + Der Architekt ist sehr nützlich, um die Bosse zu üben. + + + Die dritte Ausrüstungsreihe birgt oft gefährliche Nebenwirkungen. Vorsicht! + + + Die dritte Ausrüstungsreihe birgt oft gefährliche Nebenwirkungen. Vorsicht! + + + Bestimmte Runen funktionieren bei bestimmten Bossen besser. + + + Bestimmte Runen funktionieren bei bestimmten Bossen besser. + + + Die Dunkelheit liegt immer an der Unterseite des Schlosses. + + + Wenn du Probleme mit einem Boss hast, probiere unterschiedliche Runen aus. + + + Du solltest das Bekämpfen von Bossen mit Hilfe des Architekten üben. + + + Du solltest das Bekämpfen von Bossen mit Hilfe des Architekten üben. + + + Leben ist ein sehr wichtiger Wert, der angehoben werden muss. + + + Leben ist ein sehr wichtiger Wert, der angehoben werden muss. + + + Vergeltungsrunen können unzerstörbare Objekte beschädigen. + + + Vergeltungsrunen können unzerstörbare Objekte beschädigen. + + + Klassenfähigkeiten sind sehr mächtig, wenn sie richtig eingesetzt werden. + + + Klassenfähigkeiten sind sehr mächtig, wenn sie richtig eingesetzt werden. + + + Einige Klassen haben bestimmten Bossen gegenüber Vorteile. + + + Einige Klassen haben bestimmten Bossen gegenüber Vorteile. + + + Wenn du Probleme mit einem Boss hast, probiere unterschiedliche Runen aus. + + + Sprungrunen lassen dich mit [Input:10] in die Luft springen. + + + Sprungrunen lassen dich mit [Input:10] in die Luft springen. + + + Sprintrunen lassen dich mit [Input:PLAYER_DASHLEFT] oder [Input:PLAYER_DASHRIGHT] sprinten. + + + Sprintrunen lassen dich mit [Input:PLAYER_DASHLEFT] oder [Input:PLAYER_DASHRIGHT] sprinten. + + + Jede Klasse hat ihre Vor- und Nachteile. Passe deinen Spielstil entsprechend an. + + + Jede Klasse hat ihre Vor- und Nachteile. Passe deinen Spielstil entsprechend an. + + + Gold bekommst du am besten, wenn du die Umgebung erkundest und Truhen findest. + + + Gold bekommst du am besten, wenn du die Umgebung erkundest und Truhen findest. + + + In gefährlicheren Gebieten findest du größere Belohnungen. + + + In gefährlicheren Gebieten findest du größere Belohnungen. + + + Ich bin meiner Familie verpflichtet ... + + + Ich bin meiner Familie verpflichtet ... + + + Aber treu bin ich nur mir selbst. + + + Aber treu bin ich nur mir selbst. + + + Gold + + + Gold + + + LP wiederhergestellt + + + LP wiederhergestellt + + + MP wiederhergestellt + + + MP wiederhergestellt + + + Rüstung + + + + Rüstung + + + + Max. Leben + + + + Max. Leben + + + + Max. Mana + + + + Max. Mana + + + + Angriffskraft + + + + Angriffskraft + + + + Magie + + + + Magie + + + + Max. Gewicht + + + + Max. Gewicht + + + + Aktueller Song: + + + Aktueller Song: + + + Du betrittst + + + Du betrittst + + + Aufgabe für Feentruhe: + + + Aufgabe für Feentruhe: + + + Erreiche die Truhe in 15 Sekunden: + + + Erreiche die Truhe in 15 Sekunden: + + + Verbleibende Zeit: + + + Verbleibende Zeit: + + + Aufgabe abgeschlossen! + + + Aufgabe abgeschlossen! + + + Aufgabe nicht erfüllt + + + Aufgabe nicht erfüllt + + + Keine Merkmale + + + Heldenhafter {0} + + + Heldenhafte {0} + + + Göttlicher {0} + + + Göttliche {0} + + + Sir {0} {1} + + + Sir {0} {1} + + + Sir Held + + + Sir Held + + + Lady {0} {1} + + + Lady {0} {1} + + + Lady Heldin + + + Lady Heldin + + + Keine Merkmale + + + der + + + der + + + Legendärer {0} + + + Legendäre {0} + + + Nutzloser {0} + + + Nutzlose {0} + + + Schwächlicher {0} + + + Schwächliche {0} + + + Entschlossener {0} + + + Entschlossene {0} + + + Stämmiger {0} + + + Stämmige {0} + + + Galanter {0} + + + Galante {0} + + + Tapferer {0} + + + Tapfere {0} + + + [Input:0], um ein Kind auszuwählen + + + [Input:0], um ein Kind auszuwählen + + + [Button:LeftStick], um den Stammbaum anzusehen + + + [Button:LeftStick], um den Stammbaum anzusehen + + + Pfeiltasten, um den Stammbaum anzusehen + + + Pfeiltasten, um den Stammbaum anzusehen + + + [Input:9], um Kinder einmal neu auszuwürfeln + + + [Input:9], um Kinder einmal neu auszuwürfeln + + + Klasse + + + Klasse + + + Merkmal + + + Merkmal + + + Merkmale – Keine + + + Merkmale – Keine + + + Zauberspruch + + + Zauberspruch + + + Baue Schloss + + + Baue Schloss + + + Poliere Platte + + + Poliere Platte + + + Drehe Zeit zurück + + + Drehe Zeit zurück + + + Lade Matrix + + + Lade Matrix + + + Geöffnete Truhe + + + Geöffnete Truhe + + + Teleporter + + + Teleporter + + + Bonusraum + + + Bonusraum + + + [Input:9], um Karte zu schließen + + + [Input:9], um Karte zu schließen + + + [Input:0], um auf den Spieler zu zentrieren + + + [Input:0], um auf den Spieler zu zentrieren + + + Verwende Pfeiltasten, um die Karte zu bewegen + + + Verwende Pfeiltasten, um die Karte zu bewegen + + + [Button:LeftStick], um die Karte zu bewegen + + + [Button:LeftStick], um die Karte zu bewegen + + + Legende + + + Legende + + + Du bist hier + + + Du bist hier + + + Bossraum + + + Bossraum + + + Ungeöffnete Truhe + + + Ungeöffnete Truhe + + + Feentruhe + + + Feentruhe + + + Musik-Lautstärke + + + Musik-Lautstärke + + + 中文 + + + 中文 + + + English + + + English + + + Français + + + Français + + + Deutsch + + + Deutsch + + + Polski + + + Polski + + + Português brasileiro + + + Português brasileiro + + + русский + + + русский + + + Español castellano + + + Español castellano + + + Sprache + + + Sprache + + + *Mit Blitzfall kannst du Vorsprünge hinunterfallen und in der Luft\nnach unten schlagen, indem du die UNTEN-Taste drückst. + + + Auflösung + + + Auflösung + + + Vollbild + + + Vollbild + + + Shader-Qualität verringern + + + Shader-Qualität verringern + + + DInput-Controller verwenden + + + DInput-Controller verwenden + + + Steam-Cloud aktivieren + + + Steam-Cloud aktivieren + + + *Mit Blitzfall kannst du Vorsprünge hinunterfallen und in der Luft\nnach unten schlagen, indem du die UNTEN-Taste drückst. + + + [Button:LeftStick], um durch Optionen zu navigieren + + + [Button:LeftStick], um durch Optionen zu navigieren + + + Pfeiltasten, um Optionen zu ändern + + + Pfeiltasten, um Optionen zu ändern + + + [Input:0], um Option auszuwählen + + + [Input:0], um Option auszuwählen + + + [Input:2], um Optionen zu verlassen + + + [Input:2], um Optionen zu verlassen + + + *Das Spiel muss neu gestartet werden, damit diese Änderung wirksam wird. + + + *Das Spiel muss neu gestartet werden, damit diese Änderung wirksam wird. + + + *Cloud-Unterstützung muss auch auf Steam aktiviert sein,\ndamit das funktioniert. + + + *Cloud-Unterstützung muss auch auf Steam aktiviert sein,\ndamit das funktioniert. + + + Klasse: + + + Klasse: + + + Stärke: + + + Stärke: + + + Magie: + + + Magie: + + + Rüstung: + + + Rüstung: + + + Level: + + + Level: + + + Leben: + + + Leben: + + + ????? + + + ????? + + + Gold + + + Gold + + + max. MP + + + max. MP + + + max. LP + + + max. LP + + + Max. MP umgewandelt. Höheres Level notwendig. + + + Max. MP umgewandelt. Höheres Level notwendig. + + + Full Metal Furies\nEntwicklungszeit: 4 Jahre.\nVeröffentlichungsdatum: 17. Januar 2018 + + + Full Metal Furies ist aus der Zukunft! Es ist das Nachfolgespiel von Rogue Legacy und unser insgesamt zehntes Spiel. + + + Nach RL haben wir uns gesagt, dass wir niemals wieder ein Spiel machen, das wir bis zum Ende durchplanen. Wir haben gelogen. Verflucht seien unsere früheren Ichs! + + + Das Spiel ist zu einem unserer ehrgeizigsten Projekte überhaupt geworden. Rausgekommen ist dabei ein Mischmasch aus Prügel-/Multiplayer-/Meta-Puzzle-/ Coming-of-Age-Disco-Spiel. + + + Mit 4 Jahren hat FMF die längste Zeit in Anspruch genommen, die wir je für eine Entwicklung gebraucht haben. Leider haben wir auch mit am wenigstens Umsatz damit gemacht. + + + Aber wir sind immer noch sehr stolz auf das, was wir geschaffen haben, und noch stolzer sind wir auf die FREUNDSCHAFTEN, DIE WIR WÄHREND DER ENTWICKLUNG GESCHLOSSEN HABEN. OCHHHHHHHH!!! + + + Leben + + + Verzauberungen + + + Verzauberungen + + + [Input:2] zum Verlassen + + + [Input:2] zum Verlassen + + + Lv. + + + Lv. + + + Leben + + + Mana + + + Mana + + + Rüstung + + + Rüstung + + + Gewicht + + + Gewicht + + + Stärke + + + Stärke + + + Intelligenz + + + Intelligenz + + + Krit. Chance + + + Krit. Chance + + + Krit. Schaden + + + Krit. Schaden + + + Ausrüstung + + + Ausrüstung + + + 100 % Grundwerte. + + + SPEZIALFÄHIGKEIT: Barbarenschrei.\nViele LP. Geringe Str. und MP. + + + SPEZIALFÄHIGKEIT: Barbarenschrei.\nViele LP. Geringe Str. und MP. + + + Hohe Str., aber keine kritischen Treffer.\n+{0}% Geschwindigkeit. Geringe LP und MP. + + + Hohe Str., aber keine kritischen Treffer.\n+{0}% Geschwindigkeit. Geringe LP und MP. + + + SPEZIALFÄHIGKEIT: Wechseltechnik.\nHohe Str., aber keine kritischen Treffer.\n+{0}% Geschwindigkeit. Geringe LP und MP. + + + SPEZIALFÄHIGKEIT: Wechseltechnik.\nHohe Str., aber keine kritischen Treffer.\n+{0}% Geschwindigkeit. Geringe LP und MP. + + + Erhält {0}% des verursachten Schadens als Mana.\nGeringe Str., LP und MP. + + + Erhält {0}% des verursachten Schadens als Mana.\nGeringe Str., LP und MP. + + + BESONDERHEIT: Verstärkter Spruch.\nErhält {0}% des verursachten Schadens als Mana.\nGeringe Str., LP und MP. + + + BESONDERHEIT: Verstärkter Spruch.\nErhält {0}% des verursachten Schadens als Mana.\nGeringe Str., LP und MP. + + + Tötungen werden in maximale LP umgewandelt.\nSehr geringe Str., LP und MP. Hohe Int. + + + Tötungen werden in maximale LP umgewandelt.\nSehr geringe Str., LP und MP. Hohe Int. + + + SPEZIALFÄHIGKEIT: LP-Umwandlung.\nTötungen werden in maximale LP umgewandelt.\nSehr geringe Str., LP und MP. Hohe Int. + + + SPEZIALFÄHIGKEIT: LP-Umwandlung.\nTötungen werden in maximale LP umgewandelt.\nSehr geringe Str., LP und MP. Hohe Int. + + + Du bist ein Drachenmensch. + + + Du bist ein Drachenmensch. + + + ????? + + + ????? + + + 100 % Grundwerte. + + + SPEZIALFÄHIGKEIT: Schutzschild.\n100 % Grundwerte. + + + SPEZIALFÄHIGKEIT: Schutzschild.\n100 % Grundwerte. + + + +{0}% Krit. Chance, +{1}% Krit. Schaden.\nGeringe LP, MP und Str. + + + +{0}% Krit. Chance, +{1}% Krit. Schaden.\nGeringe LP, MP und Str. + + + SPEZIALFÄHIGKEIT: Nebelschleier\n+{0}% Krit.Chance, +{1}% Krit. Schaden.\nGeringe LP, MP und Str. + + + SPEZIALFÄHIGKEIT: Nebelschleier\n+{0}% Krit.Chance, +{1}% Krit. Schaden.\nGeringe LP, MP und Str. + + + +{0}% Goldgewinn.\nSehr schwach in allen anderen Werten. + + + +{0}% Goldgewinn.\nSehr schwach in allen anderen Werten. + + + SPEZIALFÄHIGKEIT: Gewöhnliche Stirnlampe.\n+{0}% Goldgewinn.\nSehr schwach in allen anderen Werten. + + + SPEZIALFÄHIGKEIT: Gewöhnliche Stirnlampe.\n+{0}% Goldgewinn.\nSehr schwach in allen anderen Werten. + + + Jede Tötung gewährt dir {0} Mana.\nGeringe Str. und LP. Hohe Int. und MP. + + + Jede Tötung gewährt dir {0} Mana.\nGeringe Str. und LP. Hohe Int. und MP. + + + SPEZIALFÄHIGKEIT: Zauberwechsel.\nJede Tötung gewährt dir {0} Mana.\nGeringe Str. und LP. Hohe Int. und MP. + + + SPEZIALFÄHIGKEIT: Zauberwechsel.\nJede Tötung gewährt dir {0} Mana.\nGeringe Str. und LP. Hohe Int. und MP. + + + Massenhaft LP. Geringe Str. und MP. + + + Massenhaft LP. Geringe Str. und MP. + + + - NEUES VERMÄCHTNIS - + + + NS+ + + + NS+ + + + - NEUES VERMÄCHTNIS - + + + [Button:LeftStick] zum Navigieren + + + [Button:LeftStick] zum Navigieren + + + Pfeiltasten, um Profile zu ändern + + + Pfeiltasten, um Profile zu ändern + + + [Input:0] zum Auswählen + + + [Input:0] zum Auswählen + + + [Input:2] zum Verlassen + + + [Input:2] zum Verlassen + + + [Input:26] zum Löschen + + + [Input:26] zum Löschen + + + {0} die {1} + + + {0} die {1} + + + {0} der {1} + + + {0} der {1} + + + {0} die Verstorbene + + + {0} die Verstorbene + + + {0} der Verstorbene + + + {0} der Verstorbene + + + Lvl. + + + Lvl. + + + Blitzfall aktivieren + + + Blitzfall aktivieren + + + Nein + + + Nein + + + Ja + + + Ja + + + {0}{1} + + + SFX-Lautstärke + + + SFX-Lautstärke + + + Verbessere dein Kardiotraining. Ein stärkeres Herz bedeutet ein längeres Leben. + + + Schalte die Schmiede frei und erhalte Zugang zu krassem Loot. + + + Schalte die Schmiede frei und erhalte Zugang zu krassem Loot. + + + Schalte die Zauberin frei und erhalte Zugang zu ihren magischen Runen und Kräften. + + + Schalte die Zauberin frei und erhalte Zugang zu ihren magischen Runen und Kräften. + + + Schalte den Architekten frei und erhalte die Macht, das Schloss einzufrieren. + + + Schalte den Architekten frei und erhalte die Macht, das Schloss einzufrieren. + + + Wenn du deine Tragfähigkeit erhöhst, kannst du bessere und schwerere Rüstung tragen. + + + Wenn du deine Tragfähigkeit erhöhst, kannst du bessere und schwerere Rüstung tragen. + + + Stärke deine Innereien durch natürliche Mittel, um Schaden zu reduzieren. + + + Stärke deine Innereien durch natürliche Mittel, um Schaden zu reduzieren. + + + Werde ein besserer Schatzsucher und verdiene mehr Geld für weniger Arbeit. + + + Werde ein besserer Schatzsucher und verdiene mehr Geld für weniger Arbeit. + + + Reduziere Charons Tribut, indem du lernst, mit dem Tod selbst zu feilschen. + + + Reduziere Charons Tribut, indem du lernst, mit dem Tod selbst zu feilschen. + + + Darmreinigung führt zu spürbar besserer Wirkung von Tränken und Fleisch. + + + Darmreinigung führt zu spürbar besserer Wirkung von Tränken und Fleisch. + + + Verwende die Macht der Wissenschaft, um einen neuen Satz Babys zu erzeugen. Bitte... frag einfach nicht. + + + Verwende die Macht der Wissenschaft, um einen neuen Satz Babys zu erzeugen. Bitte... frag einfach nicht. + + + Entfessle die Kraft des Lichs! Ein Wesen mit gewaltigem Potenzial. + + + Entfessle die Kraft der Lichin! Ein Wesen mit großem Potenzial. + + + Verbessere dein Kardiotraining. Ein stärkeres Herz bedeutet ein längeres Leben. + + + Stärke deine Nebennieren und sei unverwundbar wie Bane. Lasst die Spiele beginnen! + + + Entdecke die Fähigkeiten des Minenarbeiters und vermehre das Vermögen deiner Familie. + + + Entdecke die Fähigkeiten der Minenarbeiterin und vermehre das Vermögen deiner Familie. + + + Schalte den Zauberdieb frei und werde zu einem kriegerischen Magier. + + + Schalte die Zauberdiebin frei und werde zu einer kriegerischen Magierin. + + + Schalte den Shinobi frei, den flinksten aller Kämpfer. + + + Schalte die Kunoichi frei, die flinkste aller Kämpferinnen. + + + Übe die Grundlagen, um die Manakosten deiner Zauber zu reduzieren. + + + Übe die Grundlagen, um die Manakosten deiner Zauber zu reduzieren. + + + Mach deinen Ritter zum Paladin, einem furchtlosen Kämpfer an vorderster Front. + + + Mach deine Ritterin zur Paladinin, einer furchtlosen Kämpferin an vorderster Front. + + + Entfessle die verborgenen Talente des Magiers und verwandle ihn in einen mächtigen Erzmagier. + + + Entfessle die verborgenen Talente der Magierin und verwandle sie in eine mächtige Erzmagierin. + + + Erlerne die dunklen Künste und mache deinen Schurken zu einem Assassinen. + + + Erlerne die dunklen Künste und mache deine Schurkin zu einer Assassinin. + + + Besorge dir dein Geologiediplom und werde vom Minenarbeiter zum Höhlenforscher. Schick. + + + Besorge dir dein Geologiediplom und werde von der Minenarbeiterin zur Höhlenforscherin. Schick. + + + Werde zum Barbarenkönig. Der König freier Männer. Das ergibt keinen Sinn. + + + Werde zur Barbarenkönigin. Die Königin freier Frauen. Das ergibt keinen Sinn. + + + Kröne deinen allmächtigen Lich zum Lichkönig. + + + Kröne deine allmächtige Lichin zur Lichkönigin. + + + Stärke deine Nebennieren und sei unverwundbar wie Bane. Lasst die Spiele beginnen! + + + Lass deine innere Katze raus und schlag dem Tod ein Schnippchen. Manchmal. + + + Werde zum Anführer deines Dorfes und verwandle deinen Shinobi in einen Hokage. Echt jetzt! + + + Werde zur Anführerin deines Dorfes und verwandle deine Kunoichi in eine Hokage. Echt jetzt! + + + Reite auf den Winden der Magie und verwandle deine Zauberdiebe in Zauberkrieger. + + + Reite auf den Winden der Magie und verwandle deine Zauberdiebinnen in Zauberkriegerinnen. + + + Halb Mann, halb ******, 100% heißes Teil. + + + Halb Frau, halb ******, 100% heißes Teil. + + + BLITZSCHNELL\nDu atmest tief. Schlecht fürs Schleichen, gut fürs Weichen! \n\nErhöhe deine natürliche Ausdauerregeneration. + + + BLITZSCHNELL\nDu atmest tief. Schlecht fürs Schleichen, gut fürs Weichen! \n\nErhöhe deine natürliche Ausdauerregeneration. + + + In jungen Jahren wurde dir Tigerblut verabreicht. Jetzt hast du die Macht, dieses Tigerblut zu entfesseln, wenn du getroffen wirst. \nRennen entzieht weniger Ausdauer. + + + In jungen Jahren wurde dir Tigerblut verabreicht. Jetzt hast du die Macht, dieses Tigerblut zu entfesseln, wenn du getroffen wirst. \nRennen entzieht weniger Ausdauer. + + + Du hast Wikingervorfahren. \n\nErhöhe deine anfängliche Ausdauer. + + + Du hast Wikingervorfahren. \n\nErhöhe deine anfängliche Ausdauer. + + + Du wachst früh auf. Wenn Aufsteigen nur wie Aufwachen wäre.\nErhalte zusätzliche LP und MP, wenn du ein Level aufsteigst. + + + Du wachst früh auf. Wenn Aufsteigen nur wie Aufwachen wäre.\nErhalte zusätzliche LP und MP, wenn du ein Level aufsteigst. + + + Du wurdest mit der absoluten Macht in deinen Fingerspitzen geboren. \nAlle Zaubersprüche verursachen mehr Schaden. + + + Du wurdest mit der absoluten Macht in deinen Fingerspitzen geboren. \nAlle Zaubersprüche verursachen mehr Schaden. + + + Schon bei deiner Geburt schoss arkane Energie durch deine Adern. Au. \nZaubersprüche verbrauchen weniger Mana. + + + Schon bei deiner Geburt schoss arkane Energie durch deine Adern. Au. \nZaubersprüche verbrauchen weniger Mana. + + + Endlich ist die Zwangsstörung nützlich. \nErhalte mehr Gold. + + + Endlich ist die Zwangsstörung nützlich. \nErhalte mehr Gold. + + + Lass deine innere Katze raus und schlag dem Tod ein Schnippchen. Manchmal. + + + Ein ordentliches Fitnessstudio ermöglicht es dir, deine Arme und deine Pomuskeln zu stärken. + + + Per Gesetz bist du jetzt der Trauzeuge. \nBringe mehr Kinder zur Welt. + + + Per Gesetz bist du jetzt die Trauzeugin. \nBringe mehr Kinder zur Welt. + + + Deine Eltern sagten, die Goldsuche sei nutzlos für einen Bauern. Wer lacht jetzt? \nZeigt Schatzkammern zu Beginn des Spiels an. + + + Deine Eltern sagten, die Goldsuche sei nutzlos für einen Bäuerin. Wer lacht jetzt? \nZeigt Schatzkammern zu Beginn des Spiels an. + + + Krieg ist die Hölle. Zum Glück warst du nie in einem. \nFeuere mehr Mörser ab. + + + Krieg ist die Hölle. Zum Glück warst du nie in einem. \nFeuere mehr Mörser ab. + + + Als Kind hast du gerne Dinge in die Luft gejagt. \nBomben haben einen größeren Radius. + + + Als Kind hast du gerne Dinge in die Luft gejagt. \nBomben haben einen größeren Radius. + + + Dein Urgroßvater war ein Schneemann. Er hat dir nichts beigebracht. \nEiszapfen durchstoßen mehr Feinde. + + + Dein Urgroßvater war ein Schneemann. Er hat dir nichts beigebracht. \nEiszapfen durchstoßen mehr Feinde. + + + Du lebst das Zen. \nGewinne Ausdauer schneller wieder, wenn du stillhältst. + + + Du lebst das Zen. \nGewinne Ausdauer schneller wieder, wenn du stillhältst. + + + Allgemeine FÄHIGKEIT. Erhöhe die Gesamtausdauer. + + + Allgemeine FÄHIGKEIT. Erhöhe die Gesamtausdauer. + + + Du kämpfst mit Finesse.\nAngriffe entziehen X % weniger Ausdauer. + + + Du kämpfst mit Finesse.\nAngriffe entziehen X % weniger Ausdauer. + + + Allgemeine FÄHIGKEIT. Erhöhe deine Gesundheit + + + Allgemeine FÄHIGKEIT. Erhöhe deine Gesundheit + + + Du ziehst ... Blut. \nStelle mit jedem Schlag wieder ein wenig Leben her. + + + Du ziehst ... Blut. \nStelle mit jedem Schlag wieder ein wenig Leben her. + + + Ein ordentliches Fitnessstudio ermöglicht es dir, deine Arme und deine Pomuskeln zu stärken. + + + Ein Übungsraum fürs Hüpfen hat seine Vorteile. Verursache mehr Schaden mit aufeinanderfolgenden Sturzschlägen. + + + Erstehe wieder auf, genau wie Jesus. Aber du bist trotzdem nicht Jesus. \nErstehe einmal nach dem Sterben wieder auf. + + + Erstehe wieder auf, genau wie Jesus. Aber du bist trotzdem nicht Jesus. \nErstehe einmal nach dem Sterben wieder auf. + + + Das Leeren eines Raumes gleicht dem Säubern deines Geistes. Ich weiß nicht wie. \nErhalte Leben für jeden geleerten Raum zurück. + + + Das Leeren eines Raumes gleicht dem Säubern deines Geistes. Ich weiß nicht wie. \nErhalte Leben für jeden geleerten Raum zurück. + + + Kartografie /n Jeder enthüllte Teil der Karte fügt 0,1 Schaden hinzu. + + + Kartografie /n Jeder enthüllte Teil der Karte fügt 0,1 Schaden hinzu. + + + Allgemeine FÄHIGKEIT. Erhöhe den Angriffsschaden. + + + Allgemeine FÄHIGKEIT. Erhöhe den Angriffsschaden. + + + Du bist ein sehr, sehr schlechter Verlierer. \nVerursacht bei allen Feinden auf dem Bildschirm nach deinem Tod großen Schaden. + + + Du bist eine sehr, sehr schlechte Verliererin. \nVerursacht bei allen Feinden auf dem Bildschirm nach deinem Tod großen Schaden. + + + Du hast gelernt, dass das Treffen der Weichteile großen Schaden verursacht. \nKritische Treffer verursachen mehr Schaden. + + + Du hast gelernt, dass das Treffen der Weichteile großen Schaden verursacht. \nKritische Treffer verursachen mehr Schaden. + + + ALLGEMEINE FÄHIGKEIT. + + + ALLGEMEINE FÄHIGKEIT. + + + Oh. Sie waren in meiner Gesäßtasche. \nErhalte zwei zusätzliche Schlüssel. + + + Oh. Sie waren in meiner Gesäßtasche. \nErhalte zwei zusätzliche Schlüssel. + + + Wie ein Phönix wirst du aus schlechter Asche wiedergeboren. \nErhalte alle LP und MP zurück. + + + Wie ein Phönix wirst du aus schlechter Asche wiedergeboren. \nErhalte alle LP und MP zurück. + + + Geh in Rente und investiere dein Geld weise. Beende dein Spiel frühzeitig und erhalte einen Bonus auf gefundenes Gold. + + + Geh in Rente und investiere dein Geld weise. Beende dein Spiel frühzeitig und erhalte einen Bonus auf gefundenes Gold. + + + Ein Übungsraum fürs Hüpfen hat seine Vorteile. Verursache mehr Schaden mit aufeinanderfolgenden Sturzschlägen. + + + Wenn du etwas über die Schwächen deiner Feinde lernst, kannst du mit tödlicher Wirksamkeit zuschlagen. + + + GLUCK GLUCK GLUCK! \nTrinke Tränke sofort. + + + GLUCK GLUCK GLUCK! \nTrinke Tränke sofort. + + + Wenn du etwas über die Schwächen deiner Feinde lernst, kannst du mit tödlicher Wirksamkeit zuschlagen. + + + Übe die tödlichen Schläge, um noch tödlicher zu sein. Deine Feinde werden so was von tot sein. + + + Übe die tödlichen Schläge, um noch tödlicher zu sein. Deine Feinde werden so was von tot sein. + + + Lerne die Geheimnisse des Universums kennen, damit du besser mit Zaubersprüchen töten kannst. + + + Lerne die Geheimnisse des Universums kennen, damit du besser mit Zaubersprüchen töten kannst. + + + Erhöhe deine geistige Stärke, um deine Manaanzeige zu erhöhen. + + + Erhöhe deine geistige Stärke, um deine Manaanzeige zu erhöhen. + + + Drücke [Input:9], um deine Kinder neu anzuordnen. + + + Drücke [Input:9], um deine Kinder neu anzuordnen. + + + Drücke [Input:13], um jeglichen Schaden zu blockieren. + + + Drücke [Input:13], um jeglichen Schaden zu blockieren. + + + Drücke [Input:13], um zwischen Zaubern zu wechseln. + + + Drücke [Input:13], um zwischen Zaubern zu wechseln. + + + Drücke [Input:13], um dich in Nebel zu verwandeln. + + + Drücke [Input:13], um dich in Nebel zu verwandeln. + + + Drücke [Input:13], um deine Stirnlampe einzuschalten. + + + Drücke [Input:13], um deine Stirnlampe einzuschalten. + + + Drücke [Input:13], um einen epischen Schrei auszustoßen, der so gut wie alles von dir wegschleudert. + + + Drücke [Input:13], um einen epischen Schrei auszustoßen, der so gut wie alles von dir wegschleudert. + + + Drücke [Input:13], um maximale LP in maximale MP umzuwandeln. + + + Drücke [Input:13], um maximale LP in maximale MP umzuwandeln. + + + Drücke [Input:13], um zu leuchten. + + + Drücke [Input:13], um zu leuchten. + + + Drücke [Input:13], um verstärkte Sprüche zu wirken. + + + Drücke [Input:13], um verstärkte Sprüche zu wirken. + + + Drücke [Input:10], um deinen Feinden die Hölle heiß zu machen. + + + Drücke [Input:10], um deinen Feinden die Hölle heiß zu machen. + + + + + + + + + Leben + + + + Schmiede + + + Schmiede + + + Zauberin + + + Zauberin + + + Architekt + + + Architekt + + + Ausrüstung + + + + Ausrüstung + + + + Rüstung + + + + Rüstung + + + + Gold + + + + Gold + + + + Feilschen + + + Feilschen + + + Trank + + + + Trank + + + + Kinder neu anordnen + + + Kinder neu anordnen + + + Lich freischalten + + + Lichin freischalten + + + Leben + + + + Unverwundbarkeit + + + + Minenarbeiter freisch. + + + Minenarbeiterin freisch. + + + Zauberdieb freisch. + + + Zauberdiebin freisch. + + + Shinobi freischalten + + + Kunoichi freischalten + + + Manakosten - + + + Manakosten - + + + Ritter verbessern + + + Ritterin verbessern + + + Magier verbessern + + + Magierin verbessern + + + Schurke verbessern + + + Schurkin verbessern + + + Minenarbeiter verb. + + + Minenarbeiterin verb. + + + Barbar verbessern + + + Barbarin verbessern + + + Lich verbessern + + + Lichin verbessern + + + Unverwundbarkeit + + + + Trotze dem Tod + + + Shinobi verbessern + + + Kunoichi verbessern + + + Zauberdieb verb. + + + Zauberdiebin verb. + + + Bestialität + + + Bestialität + + + Blitzschnell + + + Blitzschnell + + + Geborener Läufer + + + Geborener Läuferin + + + Kräftiges Herz + + + Kräftiges Herz + + + Frühaufsteher + + + Frühaufsteherin + + + Zauberkrieger + + + Zauberkriegerin + + + Zauberer + + + Zauberin + + + Perfektionist + + + Perfektionistin + + + Trotze dem Tod + + + Angriffskraft + + + + Gut ausgestattet + + + Gut ausgestattet + + + Schatzsucher + + + Schatzsucherin + + + Mörsermeister + + + Mörsermeisterin + + + Explosiver Experte + + + Explosive Expertin + + + Eiszapfen + + + Eiszapfen + + + Guru + + + Guru + + + Eiserne Lunge + + + Eiserne Lunge + + + Schwertmeister + + + Schwertmeisterin + + + Panzer + + + Panzer + + + Vampir + + + Vampirin + + + Angriffskraft + + + + Sturzschlag + + + + Zweite Chance + + + Zweite Chance + + + Gemütsruhe + + + Gemütsruhe + + + Kartografenninja + + + Kartografenninja + + + Starker Mann + + + Starke Frau + + + Selbstmörder + + + Selbstmörderin + + + Krit. Barbar + + + Krit. Barbarin + + + Zauberer + + + Zauberin + + + Schlüsselmeister + + + Schlüsselmeisterin + + + Nur einmal + + + Nur einmal + + + Vorzeitig abhauen + + + Vorzeitig abhauen + + + Sturzschlag + + + + Krit. Chance + + + + Schlucker + + + Schluckerin + + + Krit. Chance + + + + Krit. Schaden + + + + Krit. Schaden + + + + Magie + + + + Magie + + + + Mana + + + + Mana + + + + {0} Gold zum {1} + + + {0} Gold zum {1} + + + Freischalten + + + Freischalten + + + Verbessern + + + Verbessern + + + Gewicht + + + Gewicht + + + LP + + + LP + + + MP + + + MP + + + STR + + + STR + + + INT + + + INT + + + LP/MP + + + LP/MP + + + Max. + + + Max. + + + [Input:0], um ein Merkmal zu kaufen/zu verbessern + + + [Input:0], um ein Merkmal zu kaufen/zu verbessern + + + Rüstung + + + Rüstung + + + Sek. + + + Sek. + + + [Input:9], um Icons auszublenden + + + [Input:9], um Icons auszublenden + + + [Input:2], um das Rittergut zu verlassen + + + [Input:2], um das Rittergut zu verlassen + + + [Button:LeftStick], um durch Fähigkeiten zu navigieren + + + [Button:LeftStick], um durch Fähigkeiten zu navigieren + + + Pfeiltasten, um durch Fähigkeiten zu navigieren + + + Pfeiltasten, um durch Fähigkeiten zu navigieren + + + [Input:9], um Icons einzublenden. + + + [Input:9], um Icons einzublenden. + + + Aktuell + + + Aktuell + + + Verbessern + + + Verbessern + + + Level + + + Level + + + Der Schmied kann die beste Ausrüstung der Welt herstellen und dich dabei in einen fürwahr vortrefflich furiosen Feindverdampfer verwandeln.\nSammle Blaupausen und erhalte so eine noch ausführlichere Auswahl an Ausrüstung für dein Arsenal. + + + Erhebe deine Barbaren zu BarbarenKÖNIGEN! Lerne die geheimen Schreie der Bären und brülle Dinge an, bis sie explodieren. + + + Erhebe deine Barbarinnen zu BarbarenKÖNIGINNEN! Lerne die geheimen Schreie der Bären und brülle Dinge an, bis sie explodieren. + + + Werde von einem armseligen Shinobi zu einem mächtigen Hokage! Meistere die Kunst, scheinbar getroffen zu werden, dich aber heimlich in letzter Sekunde in einen Holzklotz zu verwandeln. Gut, dass du so viel Holz mit dir herumträgst. + + + Werde von einer armseligen Kunoichi zu einer mächtigen Hokage! Meistere die Kunst, scheinbar getroffen zu werden, dich aber heimlich in letzter Sekunde in einen Holzklotz zu verwandeln. Gut, dass du so viel Holz mit dir herumträgst. + + + Trainiere deinen Schurken, damit er ein vollwertiger Assassine wird. Werde eins mit den Schatten, um heimlich durch die feindlichen Linien zu schlüpfen. + + + Trainiere deine Schurkin, damit sie eine vollwertige Assassinin wird. Werde eins mit den Schatten, um heimlich durch die feindlichen Linien zu schlüpfen. + + + Das ganze Herumgegrabe hat deine Minenarbeiter zu Höhlenforschern gemacht! Jetzt macht dieses schicke Licht auf deinem Kopf auch endlich etwas! (Nicht wirklich) + + + Das ganze Herumgegrabe hat deine Minenarbeiterinnen zu Höhlenforscherinnen gemacht! Jetzt macht dieses schicke Licht auf deinem Kopf auch endlich etwas! (Nicht wirklich) + + + Verwandle deine Zauberdiebe in Zauberkrieger und gewähre dir selbst die Macht, verstärkte Zauber zu wirken.\nDas ist doch keine Axt. DAS ist eine Axt. + + + Verwandle deine Zauberdiebinnen in Zauberkriegerinnen und gewähre dir selbst die Macht, verstärkte Zauber zu wirken.\nDas ist doch keine Axt. DAS ist eine Axt. + + + Erhebe deine Liche zu Lichkönigen und entfessle die Macht von Geist UND Materie! Verwandle dein maximales Leben mit nur einem Knopfdruck in maximales Mana. + + + Erhebe deine Lichinnen zu Lichköniginnen und entfessle die Macht von Geist UND Materie! Verwandle dein maximales Leben mit nur einem Knopfdruck in maximales Mana. + + + Du hast die verlorene Kunst der Drachen entdeckt. Obwohl du nicht springen kannst, hast du die Möglichkeit, unbegrenzt zu fliegen und mächtige Feuerbälle auf deine Feine abzuschießen. + + + Du hast die verlorene Kunst der Drachen entdeckt. Obwohl du nicht springen kannst, hast du die Möglichkeit, unbegrenzt zu fliegen und mächtige Feuerbälle auf deine Feine abzuschießen. + + + Du hast die versteckten Künste von Johannes dem Verräter entdeckt. Mögen sich Alle vor deiner Macht verneigen! + + + Du hast die versteckten Künste von Johannes dem Verräter entdeckt. Mögen sich Alle vor deiner Macht verneigen! + + + Der Schmied kann die beste Ausrüstung der Welt herstellen und dich dabei in einen fürwahr vortrefflich furiosen Feindverdampfer verwandeln.\nSammle Blaupausen und erhalte so eine noch ausführlichere Auswahl an Ausrüstung für dein Arsenal. + + + Die Zauberin kann deinen Körper mit mächtigen Runen verstärken und dich damit besser, stärker, schneller und sprunghafter machen.\nFinde Runen, um ihr Repertoire an körperkräftigenden Talenten zu erweitern.\n\nIhre Kristallkugel ist nur Zierde. + + + Die Zauberin kann deinen Körper mit mächtigen Runen verstärken und dich damit besser, stärker, schneller und sprunghafter machen.\nFinde Runen, um ihr Repertoire an körperkräftigenden Talenten zu erweitern.\n\nIhre Kristallkugel ist nur Zierde. + + + Der Architekt kann das Schloss einfrieren und damit verhindern, dass es sich verändert.\n\nGefällt dir die Anordnung des Schlosses?\nFRIERE ES EIN!\nDie Frage ist, ob du dir sein Honorar leisten kannst. + + + Der Architekt kann das Schloss einfrieren und damit verhindern, dass es sich verändert.\n\nGefällt dir die Anordnung des Schlosses?\nFRIERE ES EIN!\nDie Frage ist, ob du dir sein Honorar leisten kannst. + + + Der Shinobi. Ein superschneller und superstarker Krieger, der ein supertolles Stirnband trägt. Er kann nicht viel einstecken, aber ordentlich austeilen. Echt jetzt! + + + Die Kunoichi. Eine superschnelle und superstarke Kriegerin, die ein supertolles Stirnband trägt. Sie kann nicht viel einstecken, aber ordentlich austeilen. Echt jetzt! + + + Besser im Geldverdienen als im Feinde töten. Minenarbeiter sind am besten dafür geeignet, das Schloss nach Schatztruhen zu durchsuchen und einer Konfrontation aus dem Weg zu gehen. + + + Besser im Geldverdienen als im Feinde töten. Minenarbeiter sind am besten dafür geeignet, das Schloss nach Schatztruhen zu durchsuchen und einer Konfrontation aus dem Weg zu gehen. + + + Der Zauberdieb entzieht Feinden Mana. Dadurch hat er in der Hitze des Gefechts unendlich viel Mana parat. Weiter so! + + + Die Zauberdiebin entzieht Feinden Mana. Dadurch hat sie in der Hitze des Gefechts unendlich viel Mana parat. Weiter so! + + + Herr über Leben und Tod. Der Lich hat unvorstellbares Potenzial. Jede Tötung gewährt dem Lich dauerhaftes Leben (bis zu einer gewissen Grenze), was ihn zu einem äußerst gefährlichen Wesen macht. + + + Herrin über Leben und Tod. Die Lichin hat unvorstellbares Potenzial. Jede Tötung gewährt der Lichin dauerhaftes Leben (bis zu einer gewissen Grenze), was sie zu einem äußerst gefährlichen Wesen macht. + + + Befördere deine Ritter zu Paladinen. Durch strenges Training haben Paladine gelernt, wie man Angriffe von allen Seiten abwehrt. + + + Befördere deine Ritterinnen zu Paladininnen. Durch strenges Training haben Paladininnen gelernt, wie man Angriffe von allen Seiten abwehrt. + + + Verwandle deine armseligen Magier in Erzmagier. Meistere die arkanen Künste und wechsle im Nu zwischen deinen Zaubersprüchen. + + + Verwandle deine armseligen Magierinnen in Erzmagierinnen. Meistere die arkanen Künste und wechsle im Nu zwischen deinen Zaubersprüchen. + + + Hyperions Ring + + + Ponce de Leons Obolus + + + Ponce de Leons Obolus + + + Herodots Obolus + + + Herodots Obolus + + + Obolus des Verräters + + + Obolus des Verräters + + + Hyperions Ring + + + Hermesstiefel + + + Hermesstiefel + + + Fluch des Igels + + + Fluch des Igels + + + Charons Obolus + + + Charons Obolus + + + Calypsos Kompass + + + Calypsos Kompass + + + Segen des Helios + + + Segen des Helios + + + Streberbrille + + + Streberbrille + + + Khidrs Obolus + + + Khidrs Obolus + + + Alexanders Obolus + + + Alexanders Obolus + + + Schießt einen Dolch direkt nach vorne. + + + Beschwört eine große Klinge, die dich beschützt. + + + Beschwört eine große Klinge, die dich beschützt. + + + Umgibt dich mit schützendem Feuer. + + + Umgibt dich mit schützendem Feuer. + + + Feuert Kugeln ab, die wild herumfliegen. + + + Feuert Kugeln ab, die wild herumfliegen. + + + Feuert einen Laserstrahl ab, der jeden vernichtet, den er berührt. + + + Feuert einen Laserstrahl ab, der jeden vernichtet, den er berührt. + + + Schieße Feuerbälle auf deine Feinde. + + + Schieße Feuerbälle auf deine Feinde. + + + Feuere einen Schwall Dolche ab. + + + Feuere einen Schwall Dolche ab. + + + Schießt einen Dolch direkt nach vorne. + + + Wirft eine riesige Axt in einem Bogen. + + + Wirft eine riesige Axt in einem Bogen. + + + Beschwört eine Bombe, die nach einer Weile explodiert. + + + Beschwört eine Bombe, die nach einer Weile explodiert. + + + Friert alle Feinde auf dem Bildschirm ein. + + + Friert alle Feinde auf dem Bildschirm ein. + + + Trifft alle Feinde auf dem Bildschirm. Teuer. + + + Trifft alle Feinde auf dem Bildschirm. Teuer. + + + Hinterlasse deinen Schatten und teleporte dich zu ihm. + + + Hinterlasse deinen Schatten und teleporte dich zu ihm. + + + Sendet eine Markierung aus, die dich teleportiert. + + + Sendet eine Markierung aus, die dich teleportiert. + + + Feuert ein Chakram ab, das zu dir zurückkommt. + + + Feuert ein Chakram ab, das zu dir zurückkommt. + + + Feuert über deinem Kopf Sensen ab. + + + Feuert über deinem Kopf Sensen ab. + + + Dolch + + + Klingenwand + + + Klingenwand + + + Flammenbarriere + + + Flammenbarriere + + + Konflux + + + Konflux + + + S.T.R.A.H.L + + + S.T.R.A.H.L + + + Drachenfeuer + + + Drachenfeuer + + + Schneller Dolch + + + Schneller Dolch + + + Dolch + + + Axt + + + Axt + + + Bombe + + + Bombe + + + Zeitstopp + + + Zeitstopp + + + Krähensturm + + + Krähensturm + + + Quantum-Translokator + + + Quantum-Translokator + + + Teleporter + + + Teleporter + + + Chakram + + + Chakram + + + Sense + + + Sense + + + Lade … + + + Lade … + + + Schmied + + + Einst war ich eine mächtige Zauberin. Aber eines Tages sind die Monster dieses Schlosses in meine Träume eingedrungen und haben mein Wissen gestohlen. + + + Kein Mucks + + + Kein Mucks + + + Feentruhe + + + Feentruhe + + + Der Boden ist Lava. + + + Der Boden ist Lava. + + + Booyan + + + Booyan + + + Hallo! Möchtest du deine Geschicklichkeit testen?\nDu hast nur einen Versuch, aber es kostet nichts! Wenn du erfolgreich bist, gebe ich dir eine hübsche Belohnung! + + + Hallo! Möchtest du deine Geschicklichkeit testen?\nDu hast nur einen Versuch, aber es kostet nichts! Wenn du erfolgreich bist, gebe ich dir eine hübsche Belohnung! + + + 10 Dolche, um 8 Ziele zu zerstören. Willst du es probieren? + + + 10 Dolche, um 8 Ziele zu zerstören. Willst du es probieren? + + + Booyan + + + Booyan + + + Okay, du hattest Spaß. Zisch ab! + + + Okay, du hattest Spaß. Zisch ab! + + + Booyan + + + Booyan + + + Einst war ich eine mächtige Zauberin. Aber eines Tages sind die Monster dieses Schlosses in meine Träume eingedrungen und haben mein Wissen gestohlen. + + + Sie haben dieses Wissen in Runen eingeschlossen, und ohne diese Runen bin ich ein Versager in meinem Job. + + + Wow, dein Wurfarm ist so durchtrainiert wie der eines einsamen Clowns, der mit nichts als ein paar Zeitschriften in einem alten Schloss festsitzt. Du hast alle Ziele zerstört, also hab' ich eine kleine Belohnung für dich! + + + Wow, dein Wurfarm ist so durchtrainiert wie der eines einsamen Clowns, der mit nichts als ein paar Zeitschriften in einem alten Schloss festsitzt. Du hast alle Ziele zerstört, also hab' ich eine kleine Belohnung für dich! + + + Booyan + + + Booyan + + + Du konntest nicht einmal 8 Ziele treffen?\nPffft. Viel Glück mit dem restlichen Schloss. + + + Du konntest nicht einmal 8 Ziele treffen?\nPffft. Viel Glück mit dem restlichen Schloss. + + + Booyan + + + Booyan + + + Hallo! Sehen wir mal, was du draufhast.\nDu hast nur einen Versuch, aber es kostet nichts! Wenn du erfolgreich bist, gebe ich dir eine hübsche Belohnung! + + + Hallo! Sehen wir mal, was du draufhast.\nDu hast nur einen Versuch, aber es kostet nichts! Wenn du erfolgreich bist, gebe ich dir eine hübsche Belohnung! + + + Du bekommst 5 Äxte, um möglichst viele Ziele zu zerstören. Wenn du weniger als 10 stehen lässt, gebe ich dir einen besonderen Preis. Willst du es probieren? + + + Du bekommst 5 Äxte, um möglichst viele Ziele zu zerstören. Wenn du weniger als 10 stehen lässt, gebe ich dir einen besonderen Preis. Willst du es probieren? + + + Booyan + + + Booyan + + + Umwerfend! Du hast nicht mehr als 10 Ziele stehen lassen! Jetzt hab' ich nicht mal mehr genug Ziele, um diesen Stand zu betreiben, also kannst do meinetwegen auch den Preis haben. + + + Umwerfend! Du hast nicht mehr als 10 Ziele stehen lassen! Jetzt hab' ich nicht mal mehr genug Ziele, um diesen Stand zu betreiben, also kannst do meinetwegen auch den Preis haben. + + + Sie haben dieses Wissen in Runen eingeschlossen, und ohne diese Runen bin ich ein Versager in meinem Job. + + + Bitte, Held, wenn du Runen findest, dann bring sie mir zurück! Tu das, und ich werde nur einen kleinen Aufpreis verlangen, wenn ich sie dir zurückverkaufe. + + + Booyan + + + Booyan + + + Du hast mehr als 10 Ziele übrig gelassen.\nIch schätze, du willst den Preis nicht. Schade! + + + Du hast mehr als 10 Ziele übrig gelassen.\nIch schätze, du willst den Preis nicht. Schade! + + + ??? + + + ??? + + + Sei gegrüßt, Abenteurer. Von mir erhältst du die Chance deines Lebens! + + + Sei gegrüßt, Abenteurerin. Von mir erhältst du die Chance deines Lebens! + + + Geiziger Elf + + + Geiziger Elf + + + Für die mickrige Summe von 25% deines derzeitigen Goldes erhältst du die Chance, 1 von 3 Truhen zu öffnen. + + + Für die mickrige Summe von 25% deines derzeitigen Goldes erhältst du die Chance, 1 von 3 Truhen zu öffnen. + + + Eine Truhe wird die gezahlte Summe verdreifachen, die anderen beiden sind leer. + + + Eine Truhe wird die gezahlte Summe verdreifachen, die anderen beiden sind leer. + + + Knausriger Elf + + + Knausriger Elf + + + Willst du es versuchen? + + + Willst du es versuchen? + + + Bitte, Heldin, wenn du Runen findest, dann bring sie mir zurück! Tu das, und ich werde nur einen kleinen Aufpreis verlangen, wenn ich sie dir zurückverkaufe. + + + Architekt + + + ??? + + + ??? + + + Sei gegrüßt, Abenteurer. Von mir erhältst du die Chance deines Lebens! + + + Sei gegrüßt, Abenteurerin. Von mir erhältst du die Chance deines Lebens! + + + Geiziger Elf + + + Geiziger Elf + + + Für die mickrige Summe von 50% deines derzeitigen Goldes erhältst du die Chance, 1 von 3 Truhen zu öffnen. + + + Für die mickrige Summe von 50% deines derzeitigen Goldes erhältst du die Chance, 1 von 3 Truhen zu öffnen. + + + Eine Truhe wird die gezahlte Summe verdreifachen, die anderen beiden sind leer. + + + Eine Truhe wird die gezahlte Summe verdreifachen, die anderen beiden sind leer. + + + Knausriger Elf + + + Knausriger Elf + + + Willst du es versuchen? + + + Willst du es versuchen? + + + ??? + + + ??? + + + Sei gegrüßt, Abenteurer. Von mir erhältst du die Chance deines Lebens! + + + Sei gegrüßt, Abenteurerin. Von mir erhältst du die Chance deines Lebens! + + + Geiziger Elf + + + Geiziger Elf + + + Architekt + + + Grrrrrrrrüße, Junge! + + + Für die mickrige Summe von 75% deines derzeitigen Goldes erhältst du die Chance, 1 von 3 Truhen zu öffnen. + + + Für die mickrige Summe von 75% deines derzeitigen Goldes erhältst du die Chance, 1 von 3 Truhen zu öffnen. + + + Eine Truhe wird die gezahlte Summe verdreifachen, die anderen beiden sind leer. + + + Eine Truhe wird die gezahlte Summe verdreifachen, die anderen beiden sind leer. + + + Knausriger Elf + + + Knausriger Elf + + + Willst du es versuchen? + + + Willst du es versuchen? + + + Knausriger Elf + + + Knausriger Elf + + + Du hast nicht genug Geld? Du bist doof. + + + Du hast nicht genug Geld? Du bist doof. + + + Schlechter-Gewinner-Elf + + + Schlechter-Gewinner-Elf + + + Was ist in der Kiste? + + + Was ist in der Kiste? + + + NICHTS! + + + NICHTS! + + + Du bist dumm! Soooo dumm! + + + Du bist dumm! Soooo dumm! + + + Grrrrrrrrüße, Mädel! + + + Willst du was Lustiges wissen? Ich bin verrrrrrrrückt! + + + Schlechter-Verlierer-Elf + + + Schlechter-Verlierer-Elf + + + Tss! Du hattest einfach Glück. + + + Tss! Du hattest einfach Glück. + + + Ungeduldiger Elf + + + Ungeduldiger Elf + + + Nun öffne schon eine Truhe! + + + Nun öffne schon eine Truhe! + + + Knausriger Elf + + + Knausriger Elf + + + Tut mir leid, aber nur eine Truhe pro Person. + + + Tut mir leid, aber nur eine Truhe pro Person. + + + Entwickler + + + Entwickler + + + Don't Shit Your Pants.\nEntwicklungszeit: 2 Tage.\nVeröffentlichungsdatum: 16. Februar 2009 + + + Don't Shit Your Pants.\nEntwicklungszeit: 2 Tage.\nVeröffentlichungsdatum: 16. Februar 2009 + + + Willst du was Lustiges wissen? Ich bin verrrrrrrrückt! + + + Dieser Hebel hier? Ich muss nur daran ziehen und schon kann ich das Schloss davon abhalten, sich zu verändern. + + + Das war unser allererstes Spiel. Damals hießen wir noch Decade Studios. Im Spiel musstest du nur mit Hilfe von Texteingabebefehlen einen Mann davon abhalten, sich in die Hose zu machen. + + + Das war unser allererstes Spiel. Damals hießen wir noch Decade Studios. Im Spiel musstest du nur mit Hilfe von Texteingabebefehlen einen Mann davon abhalten, sich in die Hose zu machen. + + + Es wurde ursprünglich in einem Bus entworfen und wir haben uns entschlossen, es über ein Wochenende hinweg zu programmieren. Es ist ziemlich gut angekommen. + + + Es wurde ursprünglich in einem Bus entworfen und wir haben uns entschlossen, es über ein Wochenende hinweg zu programmieren. Es ist ziemlich gut angekommen. + + + In dem Spiel kommt ein Schimpfwort vor und wir wollten erst den Titel ändern, damit er verträglicher ist. Dann haben wir aber unsere Eier wiedergefunden und sind unserer Sache treu geblieben. + + + In dem Spiel kommt ein Schimpfwort vor und wir wollten erst den Titel ändern, damit er verträglicher ist. Dann haben wir aber unsere Eier wiedergefunden und sind unserer Sache treu geblieben. + + + Ein großer Teil des Spiels drehte sich darum, ein Text-Abenteuer zu erstellen, indem die Leute alles eingeben konnten, was sie wollten. Dadurch mussten wir vorwegnehmen, was die Leute eintippen würden. + + + Ein großer Teil des Spiels drehte sich darum, ein Text-Abenteuer zu erstellen, indem die Leute alles eingeben konnten, was sie wollten. Dadurch mussten wir vorwegnehmen, was die Leute eintippen würden. + + + Das haben wir auf zwei Arten gemacht. Zuerst haben wir die Optionen reduziert, die ein Spieler hat (ein Mann und eine Tür). Zweitens haben wir ein Erfolgssystem eingebaut, um den Spielern Lösungsansätze zu geben. + + + Das haben wir auf zwei Arten gemacht. Zuerst haben wir die Optionen reduziert, die ein Spieler hat (ein Mann und eine Tür). Zweitens haben wir ein Erfolgssystem eingebaut, um den Spielern Lösungsansätze zu geben. + + + Das Spiel hat sich so sehr um das Erfolgssystem gedreht, dass es im Spiel über den Bildschirmverlauf gelegt wurde. Das war eine kleine, aber entscheidende Änderung. + + + Das Spiel hat sich so sehr um das Erfolgssystem gedreht, dass es im Spiel über den Bildschirmverlauf gelegt wurde. Das war eine kleine, aber entscheidende Änderung. + + + Entwickler + + + Entwickler + + + Band of Bears\nEntwicklungszeit: 4 Monate.\nVeröffentlichungsdatum: 6. August 2009 + + + Band of Bears\nEntwicklungszeit: 4 Monate.\nVeröffentlichungsdatum: 6. August 2009 + + + Dieser Hebel hier? Ich muss nur daran ziehen und schon kann ich das Schloss davon abhalten, sich zu verändern. + + + So kannst du dieselben Räume wie deine Vorfahren erkunden. Beeindrrrrrruckt? Das solltest du sein. + + + Das war das zweite Spiel, an dem wir gearbeitet haben. Es war für den DreamBuildPlay-Wettbewerb 2009. Wir haben ziemlich spät von dem Wettbewerb erfahren, also mussten wir alle anderen einholen. + + + Das war das zweite Spiel, an dem wir gearbeitet haben. Es war für den DreamBuildPlay-Wettbewerb 2009. Wir haben ziemlich spät von dem Wettbewerb erfahren, also mussten wir alle anderen einholen. + + + Nach dem Erfolg von DSYP haben wir uns entschieden, größer zu denken... idiotisch viel größer. Und so wurde Cellar Door Games gegründet. + + + Nach dem Erfolg von DSYP haben wir uns entschieden, größer zu denken... idiotisch viel größer. Und so wurde Cellar Door Games gegründet. + + + Zusätzlich zu einem Projekt, das weit jenseits unserer Mittel und Erfahrung lag, hatten wir auch noch Vollzeitjobs und mussten das Spiel zum Laufen bringen. Das war ziemlich beschissen. + + + Zusätzlich zu einem Projekt, das weit jenseits unserer Mittel und Erfahrung lag, hatten wir auch noch Vollzeitjobs und mussten das Spiel zum Laufen bringen. Das war ziemlich beschissen. + + + In dem Spiel gab es das B.E.A.R.S-System (Bare Effort Adaptable Room System), das die Räume abhängig von der Anzahl der Spieler verändern würde. + + + In dem Spiel gab es das B.E.A.R.S-System (Bare Effort Adaptable Room System), das die Räume abhängig von der Anzahl der Spieler verändern würde. + + + Das BEARS-System hat nicht nur Zahlen beeinflusst, sondern auch die Rätsel. Wir kamen unter die besten 20, was gut war, aber nicht gut genug, um etwas zu gewinnen. + + + Das BEARS-System hat nicht nur Zahlen beeinflusst, sondern auch die Rätsel. Wir kamen unter die besten 20, was gut war, aber nicht gut genug, um etwas zu gewinnen. + + + Irgendwann hat uns die Realität (und der gesunde Menschenverstand) eingeholt und wir wussten, dass wir das Projekt verwerfen oder es zumindest auf Eis legen mussten. + + + Irgendwann hat uns die Realität (und der gesunde Menschenverstand) eingeholt und wir wussten, dass wir das Projekt verwerfen oder es zumindest auf Eis legen mussten. + + + Der Demo-Boss war wirklich richtig cool. + + + Der Demo-Boss war wirklich richtig cool. + + + Entwickler + + + Entwickler + + + Tribal Tallies\nEntwicklungszeit: 3 Monate.\nVeröffentlichungsdatum: 23. November 2009 + + + Tribal Tallies\nEntwicklungszeit: 3 Monate.\nVeröffentlichungsdatum: 23. November 2009 + + + So kannst du dieselben Räume wie deine Vorfahren erkunden. Beeindrrrrrruckt? Das solltest du sein. + + + Wie habe ich diese fantastische Vorrrrrrrrrichtung gebaut? Mit Wissssssenschaft natürlich! Und Magie. + + + Tribal Tallies war Monate nach der furchtbaren Erfahrung mit Band of Bears das erste Projekt, an dem wir wieder gearbeitet haben. + + + Tribal Tallies war Monate nach der furchtbaren Erfahrung mit Band of Bears das erste Projekt, an dem wir wieder gearbeitet haben. + + + Es war eine Art Testprojekt, um ein wenig in die Welt der iOS-Spiele hineinzuschnuppern, da wir noch nie etwas für eine mobile Plattform gemacht hatten. + + + Es war eine Art Testprojekt, um ein wenig in die Welt der iOS-Spiele hineinzuschnuppern, da wir noch nie etwas für eine mobile Plattform gemacht hatten. + + + Das Spiel hatte ein einfaches Konzept, bei dem du so schnell wie möglich hintereinander Zahlen in der richtigen Reihenfolge antippen musstest. + + + Das Spiel hatte ein einfaches Konzept, bei dem du so schnell wie möglich hintereinander Zahlen in der richtigen Reihenfolge antippen musstest. + + + Um das Ganze etwas aufzupeppen, haben wir mehrere Modi implementiert, z.B. rückwärts tippen, versteckte Zahlen und Tippübereinstimmung. + + + Um das Ganze etwas aufzupeppen, haben wir mehrere Modi implementiert, z.B. rückwärts tippen, versteckte Zahlen und Tippübereinstimmung. + + + Wir dachten, der Umfang sei vernünftig, aber am Ende hat die Entwicklung viel länger gedauert, als wir zuerst dachten. Es war auch nicht hilfreich, dass es auf einem Hackintosh programmiert wurde. + + + Wir dachten, der Umfang sei vernünftig, aber am Ende hat die Entwicklung viel länger gedauert, als wir zuerst dachten. Es war auch nicht hilfreich, dass es auf einem Hackintosh programmiert wurde. + + + Es war ein ziemlich schlichtes Spiel. Wir hätten es besser machen können, aber nach Band of Bears wollten wir alle auf Nummer sicher gehen. + + + Es war ein ziemlich schlichtes Spiel. Wir hätten es besser machen können, aber nach Band of Bears wollten wir alle auf Nummer sicher gehen. + + + Entwickler + + + Entwickler + + + Q\nEntwicklungszeit: 1 Monat.\nVeröffentlichungsdatum: 18 März 2010 + + + Q\nEntwicklungszeit: 1 Monat.\nVeröffentlichungsdatum: 18 März 2010 + + + Wie habe ich diese fantastische Vorrrrrrrrrichtung gebaut? Mit Wissssssenschaft natürlich! Und Magie. + + + ... Hauptsächlich Magie. + + + Unser viertes Projekt. Nach Tribal Tallies haben wir uns ein paar Monate Auszeit genommen und uns nur auf unsere Vollzeitjobs konzentriert. Dann wurden wir unruhig und entschieden, ein Puzzlespiel zu machen. + + + Unser viertes Projekt. Nach Tribal Tallies haben wir uns ein paar Monate Auszeit genommen und uns nur auf unsere Vollzeitjobs konzentriert. Dann wurden wir unruhig und entschieden, ein Puzzlespiel zu machen. + + + Zu diesem Zeitpunkt hatten die meisten ursprünglichen Gründer von Cellar Door Games uns verlassen, um anderen Möglichkeiten nachzugehen und der ungewollte Rest macht heute die Firma aus. + + + Zu diesem Zeitpunkt hatten die meisten ursprünglichen Gründer von Cellar Door Games uns verlassen, um anderen Möglichkeiten nachzugehen und der ungewollte Rest macht heute die Firma aus. + + + Das Spiel verwendete ein Warteschlangenprinzip, um die Spieler dazu zu zwingen, darüber nachzudenken, wie die Steine fallen würden, um große Kombos bilden zu können. + + + Das Spiel verwendete ein Warteschlangenprinzip, um die Spieler dazu zu zwingen, darüber nachzudenken, wie die Steine fallen würden, um große Kombos bilden zu können. + + + Wir haben es kostenlos veröffentlicht, aber niemand hat sich dafür interessiert. Nach den Rückschlägen mit Band of Bears, Tribal Tallies und Q haben wir uns darauf vorbereitet, einzupacken und die Firma zu schließen. + + + Wir haben es kostenlos veröffentlicht, aber niemand hat sich dafür interessiert. Nach den Rückschlägen mit Band of Bears, Tribal Tallies und Q haben wir uns darauf vorbereitet, einzupacken und die Firma zu schließen. + + + Entwickler + + + Entwickler + + + My First Quantum Translocator\nEntwicklungszeit: 1 Monat.\nVeröffentlichungsdatum: 13. Oktober 2010 + + + My First Quantum Translocator\nEntwicklungszeit: 1 Monat.\nVeröffentlichungsdatum: 13. Oktober 2010 + + + My First Quantum Translocator wurde entwickelt, als unsere Firma an ihrem Tiefpunkt war. Nach 3 gescheiterten Spielen hatten wir uns schon fast verabschiedet und entschieden, zum Spaß dieses Flashspiel zu machen. + + + My First Quantum Translocator wurde entwickelt, als unsere Firma an ihrem Tiefpunkt war. Nach 3 gescheiterten Spielen hatten wir uns schon fast verabschiedet und entschieden, zum Spaß dieses Flashspiel zu machen. + + + ... Hauptsächlich Magie. + + + Schmied + + + Willkommen, Held. + + + Aber meine Fähigkeiten sind nicht kooooostenlos. Wenn ich dieses Schloss einfriere, nehme ich 40% all des Goldes, das du verdienst! + + + Während der Entwicklung gab es überhaupt keine Erwartungen und wir haben es wirklich nur zum Spaß und nicht für den Erfolg gemacht. + + + Während der Entwicklung gab es überhaupt keine Erwartungen und wir haben es wirklich nur zum Spaß und nicht für den Erfolg gemacht. + + + Natürlich waren die Reaktionen auf das Spiel gewaltig und es ist der einzige Grund, warum Cellar Door Games heute noch existiert. Als wir MFQT veröffentlicht haben, wussten wir, es würde kein Zurück geben. + + + Natürlich waren die Reaktionen auf das Spiel gewaltig und es ist der einzige Grund, warum Cellar Door Games heute noch existiert. Als wir MFQT veröffentlicht haben, wussten wir, es würde kein Zurück geben. + + + Interessanterweise denken viele, dass das Spiel von Portal inspiriert wurde, aber die Gemeinsamkeiten sind rein zufällig. + + + Interessanterweise denken viele, dass das Spiel von Portal inspiriert wurde, aber die Gemeinsamkeiten sind rein zufällig. + + + Das Spiel entstand eigentlich aus einem Charakter, den wir uns für das Spiel League of Legends ausgedacht hatten. + + + Das Spiel entstand eigentlich aus einem Charakter, den wir uns für das Spiel League of Legends ausgedacht hatten. + + + In Wahrheit haben sich die Gemeinsamkeiten zwischen Portal und MFQT erst gezeigt, als wir angefangen haben, die endgültigen Grafikelemente und die Geschichte ins Spiel zu packen. + + + In Wahrheit haben sich die Gemeinsamkeiten zwischen Portal und MFQT erst gezeigt, als wir angefangen haben, die endgültigen Grafikelemente und die Geschichte ins Spiel zu packen. + + + Trotzdem waren wir ziemlich stolz auf das Spiel. Es ließ sich gut spielen und hatte ein schönes Ende. + + + Trotzdem waren wir ziemlich stolz auf das Spiel. Es ließ sich gut spielen und hatte ein schönes Ende. + + + Entwickler + + + Entwickler + + + I Have 1 Day\nEntwicklungszeit: 1,5 Monate.\nVeröffentlichungsdatum: 15. April 2011 + + + I Have 1 Day\nEntwicklungszeit: 1,5 Monate.\nVeröffentlichungsdatum: 15. April 2011 + + + Aber meine Fähigkeiten sind nicht kooooostenlos. Wenn ich dieses Schloss einfriere, nehme ich 40% all des Goldes, das du verdienst! + + + + + + Wenn ihr uns fragen würdet, welches von all unseren Spielen unser Lieblingsspiel ist, würden alle einstimmig für I Have 1 Day plädieren. + + + Wenn ihr uns fragen würdet, welches von all unseren Spielen unser Lieblingsspiel ist, würden alle einstimmig für I Have 1 Day plädieren. + + + Als Kinder sind wir mit den Adventure-Klassikern wie King's Quest und Monkey Island groß geworden, also war das eigentlich unsere Hommage an einige der besten Spielerfahrungen, die wir je hatten. + + + Als Kinder sind wir mit den Adventure-Klassikern wie King's Quest und Monkey Island groß geworden, also war das eigentlich unsere Hommage an einige der besten Spielerfahrungen, die wir je hatten. + + + Das Spiel dreht sich um ein Echtzeitpuzzle, in dem der Spieler nur 24 Stunden Zeit hat, das Spiel zu gewinnen. + + + Das Spiel dreht sich um ein Echtzeitpuzzle, in dem der Spieler nur 24 Stunden Zeit hat, das Spiel zu gewinnen. + + + Jedes Rätsel hatte mehrere Lösungen mit zeitlichen Auswirkungen. Daher waren die Spieler gezwungen, über den besten Lösungsweg nachzudenken. + + + Jedes Rätsel hatte mehrere Lösungen mit zeitlichen Auswirkungen. Daher waren die Spieler gezwungen, über den besten Lösungsweg nachzudenken. + + + Ein interessanter Fakt. Das zweite Ende wurde nahezu in letzter Minute hinzugefügt und ohne es wäre das gesamte Spiel Mist. + + + Ein interessanter Fakt. Das zweite Ende wurde nahezu in letzter Minute hinzugefügt und ohne es wäre das gesamte Spiel Mist. + + + Entwickler + + + Entwickler + + + Villainous\nEntwicklungszeit: 3 Monate.\nVeröffentlichungsdatum: 15. April 2011 + + + Villainous\nEntwicklungszeit: 3 Monate.\nVeröffentlichungsdatum: 15. April 2011 + + + Villainous war eines unserer riskantesten Projekte. + + + Villainous war eines unserer riskantesten Projekte. + + + + + + Möchtest du das Schloss einfrieren und nur 60% Gold erhalten? + + + Das eigentlich Konzept war Tower Defense, aber rückwärts. Das hat zwar nach einer guten Idee geklungen, aber wir hatten große Probleme, es in die Tat umzusetzen. + + + Das eigentlich Konzept war Tower Defense, aber rückwärts. Das hat zwar nach einer guten Idee geklungen, aber wir hatten große Probleme, es in die Tat umzusetzen. + + + Die meisten, die das Spiel gespielt haben, halten den Prozess für offensichtlich, aber dieses Projekt brachte uns viel Stress und Streit. + + + Die meisten, die das Spiel gespielt haben, halten den Prozess für offensichtlich, aber dieses Projekt brachte uns viel Stress und Streit. + + + Die gesamte Idee wurde drei- oder viermal verworfen, bevor wir uns auf die endgültige Version geeinigt haben. + + + Die gesamte Idee wurde drei- oder viermal verworfen, bevor wir uns auf die endgültige Version geeinigt haben. + + + Es ist irgendwie ironisch, dass Villainous bis heute bei Weitem unser erfolgreichstes Spiel ist. Es war auch das schmerzhafteste. + + + Es ist irgendwie ironisch, dass Villainous bis heute bei Weitem unser erfolgreichstes Spiel ist. Es war auch das schmerzhafteste. + + + Entwickler + + + Entwickler + + + Bullet Audyssey\nEntwicklungszeit: 3,5 Monate.\nVeröffentlichungsdatum: 29. November 2011 + + + Bullet Audyssey\nEntwicklungszeit: 3,5 Monate.\nVeröffentlichungsdatum: 29. November 2011 + + + Bullet Audyssey war unser letztes Spiel vor der Arbeit an Rogue Legacy. + + + Bullet Audyssey war unser letztes Spiel vor der Arbeit an Rogue Legacy. + + + Als Shoot 'em up, das auf Rhythmus und Taktschlag basiert, war Bullet Audyssey für uns die größte technische Herausforderung, der wir je gegenübergestanden haben (ja, sogar noch größer als Rogue Legacy). + + + Als Shoot 'em up, das auf Rhythmus und Taktschlag basiert, war Bullet Audyssey für uns die größte technische Herausforderung, der wir je gegenübergestanden haben (ja, sogar noch größer als Rogue Legacy). + + + Möchtest du das Schloss einfrieren und nur 60% Gold erhalten? + + + + + + Nur um einen Level zu konstruieren, mussten 3 Editoren gleichzeitig arbeiten. + + + Nur um einen Level zu konstruieren, mussten 3 Editoren gleichzeitig arbeiten. + + + Auch die Entwicklung für dieses Spiel war ein wenig unkonventionell, da viel Vorplanung notwendig war, um dafür zu sorgen, dass alles passte. + + + Auch die Entwicklung für dieses Spiel war ein wenig unkonventionell, da viel Vorplanung notwendig war, um dafür zu sorgen, dass alles passte. + + + Da Dokumentation überhaupt nicht unsere Stärke ist, hat uns das nicht so gut gefallen, also mussten wir das ganze Spiel einen halben Tag lang ausdiskutieren. + + + Da Dokumentation überhaupt nicht unsere Stärke ist, hat uns das nicht so gut gefallen, also mussten wir das ganze Spiel einen halben Tag lang ausdiskutieren. + + + Im Spiel absorbiert der Spieler feindliche Geschosse, um sie wieder zurückzufeuern. Das geschieht bei einem Taktschlag, der mit dem Song übereinstimmt, der gerade läuft. + + + Im Spiel absorbiert der Spieler feindliche Geschosse, um sie wieder zurückzufeuern. Das geschieht bei einem Taktschlag, der mit dem Song übereinstimmt, der gerade läuft. + + + Die ersten Spieltests waren eine Katastrophe, da das Spiel zu schwer war und die Spieler schon in der ersten Minute unheimlich frustriert waren. + + + Die ersten Spieltests waren eine Katastrophe, da das Spiel zu schwer war und die Spieler schon in der ersten Minute unheimlich frustriert waren. + + + Mit Spieltests meinen wir einen Kerl, der Shoot 'em ups nicht einmal mag. Aber das ist mehr als unser sonstiges Testpublikum. + + + Mit Spieltests meinen wir einen Kerl, der Shoot 'em ups nicht einmal mag. Aber das ist mehr als unser sonstiges Testpublikum. + + + Das Spiel machte sich nach Veröffentlichung nicht sehr gut. Das gab uns das Selbstvertrauen, Rogue Legacy zu entwickeln! + + + Das Spiel machte sich nach Veröffentlichung nicht sehr gut. Das gab uns das Selbstvertrauen, Rogue Legacy zu entwickeln! + + + Bestätigen + + + Bestätigen + + + Abbrechen + + + Abbrechen + + + Warnung! + + + Warnung! + + + + + + Möchtest du das Schloss einfrieren und nur 60% Gold erhalten? + + + Möchtest du wirklich ein neues Spiel beginnen? Alle vorherigen Speicherdaten werden gelöscht. + + + Möchtest du wirklich ein neues Spiel beginnen? Alle vorherigen Speicherdaten werden gelöscht. + + + Steuerung wiederherstellen + + + Steuerung wiederherstellen + + + Möchtest du wirklich die Standardsteuerungseinstellungen wiederherstellen? + + + Möchtest du wirklich die Standardsteuerungseinstellungen wiederherstellen? + + + + + + + + + Möchtest du wirklich mit diesem Held ein neues Abenteuer beginnen? + + + Möchtest du wirklich mit dieser Heldin ein neues Abenteuer beginnen? + + + Auflösung geändert + + + Auflösung geändert + + + Möchtest du wirklich mit dieser Auflösung spielen?\n(Die Auflösung wird in 10 Sek. zurückgesetzt.) + + + Möchtest du wirklich mit dieser Auflösung spielen?\n(Die Auflösung wird in 10 Sek. zurückgesetzt.) + + + Speicherdatei löschen + + + Speicherdatei löschen + + + Möchtest du wirklich deine Speicherdatei löschen?\n(Alle Fähigkeiten, Merkmale, Stammbäume und Ausrüstungsgegenstände werden UNWIDERRUFLICH gelöscht.) + + + Möchtest du wirklich deine Speicherdatei löschen?\n(Alle Fähigkeiten, Merkmale, Stammbäume und Ausrüstungsgegenstände werden UNWIDERRUFLICH gelöscht.) + + + Möchtest du das Schloss einfrieren und nur 60% Gold erhalten? + + + Architekt + + + Speicherdatei löschen + + + Speicherdatei löschen + + + Bist du WIRKLICH sicher? (Keine Hintertüren)\n(Alle Fähigkeiten, Merkmale, Stammbäume und Ausrüstungsgegenstände werden UNWIDERRUFLICH gelöscht.) + + + Bist du WIRKLICH sicher? (Keine Hintertüren)\n(Alle Fähigkeiten, Merkmale, Stammbäume und Ausrüstungsgegenstände werden UNWIDERRUFLICH gelöscht.) + + + + + + + + + Möchtest du wirklich zum Hauptmenü zurückkehren? (Dein derzeitiger Status wird gespeichert.) + + + Möchtest du wirklich zum Hauptmenü zurückkehren? (Dein derzeitiger Status wird gespeichert.) + + + + + + + + + Möchtest du Rogue Legacy wirklich verlassen? (Dein derzeitiger Status wird gespeichert.) + + + Möchtest du Rogue Legacy wirklich verlassen? (Dein derzeitiger Status wird gespeichert.) + + + Speicherfehler + + + Speicherfehler + + + Oh nein! Leider ist deine Speicherdatei fehlerhaft! + + + Oh nein! Leider ist deine Speicherdatei fehlerhaft! + + + Architekt + + + Tut mir leid, Junge, im Moment gibt es kein Schloss zu bauen. Diese Schraube ist nur Zierde. + + + Versuche, eine Sicherungsversion des Spiels zu laden. Hoffentlich wirft sie dich nicht zu weit zurück! + + + Versuche, eine Sicherungsversion des Spiels zu laden. Hoffentlich wirft sie dich nicht zu weit zurück! + + + Speicherfehler + + + Speicherfehler + + + Wie es aussieht, funktioniert die Sicherungsversion auch nicht. Bitte kontaktiere: support@cellardoorgames.com + + + Wie es aussieht, funktioniert die Sicherungsversion auch nicht. Bitte kontaktiere: support@cellardoorgames.com + + + Speicherfehler + + + Speicherfehler + + + Dein Spiel konnte dreimal hintereinander nicht speichern. + + + Dein Spiel konnte dreimal hintereinander nicht speichern. + + + Antivirus-Software und manuelle Backup-Speicherprogramme können zu Problemen mit Speicherdateien führen. Deaktiviere diese Programme bitte, bevor du das Spiel startest. + + + Antivirus-Software und manuelle Backup-Speicherprogramme können zu Problemen mit Speicherdateien führen. Deaktiviere diese Programme bitte, bevor du das Spiel startest. + + + Tut mir leid, Mädel, im Moment gibt es kein Schloss zu bauen. Diese Schraube ist nur Zierde. + + + Architekt + + + Architekt + + + Jungchen, das Schloss ist schon eingefroren. + + + Mädel, das Schloss ist schon eingefroren. + + + Architekt + + + Architekt + + + Willkommen, Heldin. + + + Vielleicht kannst du mir helfen. Einst war ich der beste Schmied in allen Landen. Aber eines Tages haben die Monster dieses Schlosses meine Schmiede angegriffen und all meine Blaupausen gestohlen. + + + Viel Spaaaß! Vielleicht erreichst du ein paar Schätze, die deine Vorfahren übersehen haben! + + + Viel Spaaaß! Vielleicht erreichst du ein paar Schätze, die deine Vorfahren übersehen haben! + + + Charon + + + Charon + + + ... Ihr müsst den Tribut zahlen. + + + ... Ihr müsst den Tribut zahlen. + + + + + + + + + (Willst du Charon all dein Geld geben und das Schloss betreten?) + + + (Willst du Charon all dein Geld geben und das Schloss betreten?) + + + + + + + + + (Willst du Charon all dein Geld geben und das Schloss betreten?) + + + (Willst du Charon all dein Geld geben und das Schloss betreten?) + + + + + + + + + (Willst du Charon 90% deines Geldes geben und das Schloss betreten?) + + + (Willst du Charon 90% deines Geldes geben und das Schloss betreten?) + + + + + + + + + Vielleicht kannst du mir helfen. Einst war ich der beste Schmied in allen Landen. Aber eines Tages haben die Monster dieses Schlosses meine Schmiede angegriffen und all meine Blaupausen gestohlen. + + + Ohne diese Baupläne kann ich nur Besteck und Kleinkram herstellen. + + + (Willst du Charon 80% deines Geldes geben und das Schloss betreten?) + + + (Willst du Charon 80% deines Geldes geben und das Schloss betreten?) + + + + + + + + + (Willst du Charon 70% deines Geldes geben und das Schloss betreten?) + + + (Willst du Charon 70% deines Geldes geben und das Schloss betreten?) + + + + + + + + + (Willst du Charon 60% deines Geldes geben und das Schloss betreten?) + + + (Willst du Charon 60% deines Geldes geben und das Schloss betreten?) + + + + + + + + + (Willst du Charon 50% deines Geldes geben und das Schloss betreten?) + + + (Willst du Charon 50% deines Geldes geben und das Schloss betreten?) + + + Charon + + + Charon + + + Oh ho ho! Also hast du meinen Obolus. Ich werde dich kostenlos durchlassen, aber nur dieses eine Mal. + + + Oh ho ho! Also hast du meinen Obolus. Ich werde dich kostenlos durchlassen, aber nur dieses eine Mal. + + + Charon + + + Charon + + + Ohne diese Baupläne kann ich nur Besteck und Kleinkram herstellen. + + + Bitte bring mir alle Blaupausen, die du finden kannst. Dann schmiede ich dir die beste. Ausrüstung. ÜBERHAUPT. + + + Oho! Das ist ein ganz besonderer Obolus. + + + Oho! Das ist ein ganz besonderer Obolus. + + + Gib ihn mir und ich lasse deine Seele durch die anderen Tore hindurch. + + + Gib ihn mir und ich lasse deine Seele durch die anderen Tore hindurch. + + + (Willst du Charon den Obolus geben und so seinen Tribut bezahlen?) + + + (Willst du Charon den Obolus geben und so seinen Tribut bezahlen?) + + + Charon + + + Charon + + + Oho! Das ist ein ganz besonderer Obolus. + + + Oho! Das ist ein ganz besonderer Obolus. + + + Gib ihn mir und ich lasse deine Seele durch die anderen Tore hindurch. + + + Gib ihn mir und ich lasse deine Seele durch die anderen Tore hindurch. + + + (Willst du Charon den Obolus geben und so seinen Tribut bezahlen?) + + + (Willst du Charon den Obolus geben und so seinen Tribut bezahlen?) + + + Charon + + + Charon + + + Oho! Das ist ein ganz besonderer Obolus. + + + Oho! Das ist ein ganz besonderer Obolus. + + + Gib ihn mir und ich lasse deine Seele durch die anderen Tore hindurch. + + + Gib ihn mir und ich lasse deine Seele durch die anderen Tore hindurch. + + + Bitte bring mir alle Blaupausen, die du finden kannst. Dann schmiede ich dir die beste. Ausrüstung. ÜBERHAUPT. + + + ... zu einem gewissen Preis, natürlich. + + + (Willst du Charon den Obolus geben und so seinen Tribut bezahlen?) + + + (Willst du Charon den Obolus geben und so seinen Tribut bezahlen?) + + + Charon + + + Charon + + + Oho! Das ist ein ganz besonderer Obolus. + + + Oho! Das ist ein ganz besonderer Obolus. + + + Gib ihn mir und ich lasse deine Seele durch die anderen Tore hindurch. + + + Gib ihn mir und ich lasse deine Seele durch die anderen Tore hindurch. + + + (Willst du Charon den Obolus geben und so seinen Tribut bezahlen?) + + + (Willst du Charon den Obolus geben und so seinen Tribut bezahlen?) + + + Charon + + + Charon + + + Oh ... Du hättest diesen Obolus nicht nehmen sollen. + + + Oh ... Du hättest diesen Obolus nicht nehmen sollen. + + + Mach dich bereit. + + + Mach dich bereit. + + + (Willst du Charon den Obolus geben und so seinen Tribut bezahlen?) + + + (Willst du Charon den Obolus geben und so seinen Tribut bezahlen?) + + + Spiritueller Schrein + + + Spiritueller Schrein + + + ... zu einem gewissen Preis, natürlich. + + + Zauberin + + + Willst du um Hilfe beten? + + + Willst du um Hilfe beten? + + + Letzter Boss + + + Letzter Boss + + + Willkommen, Held! Es ist ziemlich beeindruckend, dass du so weit gekommen bist. Hier aber endet deine Reise! + + + Willkommen, Heldin! Es ist ziemlich beeindruckend, dass du so weit gekommen bist. Hier aber endet deine Reise! + + + Feentruhe – Nichts + + + Feentruhe – Nichts + + + KEIN TEXT + + + KEIN TEXT + + + Besiege alle Feinde. + + + Besiege alle Feinde. + + + + + + + + + Wenig Leben + + + Wenig Leben + + + + + + + + + Nicht hinsehen + + + Nicht hinsehen + + + Zauberin + + + Hallo, Held. + + + + + + + + + Nicht springen + + + Nicht springen + + + + + + + + + Keine Geräusche + + + Keine Geräusche + + + + + + + + + Berühre den Boden nicht. + + + Berühre den Boden nicht. + + + + + + + + + Nicht kämpfen + + + Nicht kämpfen + + + + + + + + + Erreiche mich rechtzeitig + + + Erreiche mich rechtzeitig + + + Hallo, Heldin. + + + Leih mir bitte kurz dein Ohr. Ich brauche deine Hilfe. + + + + + + + + + Nimm keinen Schaden + + + Nimm keinen Schaden + + + + + + + + + Finde mich + + + Finde mich + + + + + + + + + Feentruhe + + + Feentruhe + + + Schau mich nicht an! + + + Schau mich nicht an! + + + Feentruhe + + + Feentruhe + + + Nicht springen + + + Nicht springen + + + Feentruhe + + + Feentruhe + + + Leih mir bitte kurz dein Ohr. Ich brauche deine Hilfe. + + + Drücke [Input:12], um anzugreifen. + + + Drücke [Input:12], um anzugreifen. + + + Setze dein Abenteuer fort + + + Setze dein Abenteuer fort + + + Wähle deinen Erben + + + Wähle deine Erbin + + + Beginne dein Vermächtnis + + + Beginne dein Vermächtnis + + + {0} ist ein Warenzeichen von Cellar Door Games Inc. Alle Rechte vorbehalten. + + + Trainingspuppe + + + ES TUT WEEHH! + + + ES TUT WEEHH! + + + Uff. + + + Uff. + + + Autsch. + + + Autsch. + + + BLARGH. + + + BLARGH. + + + Ich gebe auf! + + + Ich gebe auf! + + + Pumpst du? + + + Pumpst du? + + + Das tat weh. + + + Das tat weh. + + + Das kitzelt. + + + Das kitzelt. + + + Ist das alles? + + + Ist das alles? + + + Pumpet Ihr? + + + Pumpet Ihr? + + + Trainingspuppe + + + Oh Gott! + + + Guter Versuch. + + + Guter Versuch. + + + Schwach. + + + Schwach. + + + Neuer Versuch! + + + Neuer Versuch! + + + Oh Gott! + + + Der Schmerz! + + + Der Schmerz! + + + Es tut so weh... + + + Es tut so weh... + + + AUFHÖREN! + + + AUFHÖREN! + + + Warum ich?! + + + Warum ich?! + + + WARUM??? + + + WARUM??? + + + Hör auf! + + + Hör auf! + + + Warum nur? + + + Warum nur? + + + Du kannst keine unterschiedlichen Farben sehen. + + + Du bist so dünn, dass dich jeder Treffer zurückwirft. + + + Du bist so dünn, dass dich jeder Treffer zurückwirft. + + + Du kannst dich nicht gut daran erinnern, wo du bist. + + + Du kannst dich nicht gut daran erinnern, wo du bist. + + + Deine MP- und LP-Anzeigen sind vertauscht. Wer hätte das gedacht? + + + Deine MP- und LP-Anzeigen sind vertauscht. Wer hätte das gedacht? + + + %#&@! + + + %#&@! + + + So voller Energie! Du bewegst dich schneller. + + + So voller Energie! Du bewegst dich schneller. + + + Muss. Alles. Zerstören. Zerbrich Dinge, um MP zu erhalten. + + + Muss. Alles. Zerstören. Zerbrich Dinge, um MP zu erhalten. + + + Du bist wie voller Anabolika. Angriffe werfen Feinde zurück. + + + Du bist wie voller Anabolika. Angriffe werfen Feinde zurück. + + + Du hast schwache Glieder. Du kannst Feinde nicht zurückwerfen. + + + Du hast schwache Glieder. Du kannst Feinde nicht zurückwerfen. + + + Du kannst nicht in 3D sehen. + + + Du kannst nicht in 3D sehen. + + + Selbst die tapfersten Helden können an Reizdarm leiden. + + + Selbst die tapfersten Heldeninnen können an Reizdarm leiden. + + + Du kannst keine unterschiedlichen Farben sehen. + + + Du magst die Damen. + + + Willkommen in Kotzhausen. + + + Willkommen in Kotzhausen. + + + Kein peripheres Sehen. + + + Kein peripheres Sehen. + + + Du hast zwei linke Hände und kannst Zauber nicht ordentlich wirken. + + + Du hast zwei linke Hände und kannst Zauber nicht ordentlich wirken. + + + Periphere arterielle Verschlusskrankheit. Kein Fußpuls. + + + Periphere arterielle Verschlusskrankheit. Kein Fußpuls. + + + Hühner machen dir Angst. + + + Hühner machen dir Angst. + + + Du neigst zu ÜBERTREIBUNGEN. + + + Du neigst zu ÜBERTREIBUNGEN. + + + Du bist verrückt. + + + Du bist verrückt. + + + Du bist sehr beweglich. + + + Du bist sehr beweglich. + + + Du behältst Dinge sehr genau im Gedächtnis. + + + Du behältst Dinge sehr genau im Gedächtnis. + + + Du vermisst die guten alten Zeiten. + + + Du vermisst die guten alten Zeiten. + + + Du magst die Herren. + + + Du magst die Herren. + + + Du magst die Damen. + + + Alles in der Ferne ist verschwommen. + + + Angeborene Analgesie. Du kennst keine Schmerzen. + + + Angeborene Analgesie. Du kennst keine Schmerzen. + + + Du bist sehr talentiert. Mit ein paar Problemen. + + + Du bist sehr talentiert. Mit ein paar Problemen. + + + Den Göffel gibt es nicht. + + + Den Göffel gibt es nicht. + + + Du zerbrichst viele Dinge. + + + Du zerbrichst viele Dinge. + + + Du leitest sehr gut Strom. + + + Du leitest sehr gut Strom. + + + Es ist so dunkel. + + + Es ist so dunkel. + + + Du leidest unter spontanen Muskelkrämpfen. + + + Du leidest unter spontanen Muskelkrämpfen. + + + Du kannst Leute nicht auseinanderhalten. + + + Du kannst Leute nicht auseinanderhalten. + + + Alles in der Ferne ist verschwommen. + + + Alles in der Nähe ist verschwommen. + + + Alles in der Nähe ist verschwommen. + + + Du hsat Porbelem bime Lseen. + + + Du hsat Porbelem bime Lseen. + + + Du bist der geborene Basketballspieler. + + + Du bist die geborene Basketballspielerin. + + + Du wirst niemals Achterbahnfahren können. + + + Du wirst niemals Achterbahnfahren können. + + + Eine Glatze steht jedem gut. + + + Eine Glatze steht jedem gut. + + + Du bist so schwer, dass Feinde dich nicht zurückwerfen können. + + + Du bist so schwer, dass Feinde dich nicht zurückwerfen können. + + + Du kannst keine Farben sehen. + + + Treffer lassen dich fliegen. + + + Treffer lassen dich fliegen. + + + Wo bist du? + + + Wo bist du? + + + Anzeige für MP und LP vertauscht. + + + Anzeige für MP und LP vertauscht. + + + %#&@! + + + %#&@! + + + Du bewegst dich schneller. + + + Du bewegst dich schneller. + + + Zerbrich Dinge, um MP zu erhalten. + + + Zerbrich Dinge, um MP zu erhalten. + + + Du haust Feinde aus den Schuhen. + + + Du haust Feinde aus den Schuhen. + + + Du kannst Feinde nicht zurückwerfen. + + + Du kannst Feinde nicht zurückwerfen. + + + Du kannst nicht in 3D sehen. + + + Du kannst nicht in 3D sehen. + + + Du furzt viel. + + + Du furzt viel. + + + Du kannst keine Farben sehen. + + + Du magst die Damen. + + + Alles steht auf dem Kopf. + + + Alles steht auf dem Kopf. + + + Keine frühzeitigen Warnzeichen. + + + Keine frühzeitigen Warnzeichen. + + + Zauber kommen aus deinem Rücken. + + + Zauber kommen aus deinem Rücken. + + + Kein Fußpuls. + + + Kein Fußpuls. + + + Du hast Angst vor Hühnern. + + + Du hast Angst vor Hühnern. + + + Du übertreibst erlittenen Schaden. + + + Du übertreibst erlittenen Schaden. + + + Du siehst Dinge, die nicht da sind. + + + Du siehst Dinge, die nicht da sind. + + + Du drehst dich beim Kämpfen. + + + Du drehst dich beim Kämpfen. + + + Merke dir Gegnerpositionen. + + + Merke dir Gegnerpositionen. + + + Alles ist wie damals. + + + Alles ist wie damals. + + + Du magst die Herren. + + + Du magst die Herren. + + + Du magst die Damen. + + + Alles in der Ferne ist verschwommen. + + + Keine sichtbare Lebensanzeige. + + + Keine sichtbare Lebensanzeige. + + + Zufällige Zaubersprüche. + + + Zufällige Zaubersprüche. + + + Den Göffel gibt es nicht. + + + Den Göffel gibt es nicht. + + + Tollpatschig. Du zerbrichst Alles. + + + Tollpatschig. Du zerbrichst Alles. + + + Plattformen bleiben offen. + + + Plattformen bleiben offen. + + + Es ist so dunkel. + + + Es ist so dunkel. + + + Alles in der Ferne ist verschwommen. + + + Alles in der Nähe ist verschwommen. + + + Alles in der Nähe ist verschwommen. + + + Du hsat Porbelem bime Lseen. + + + Du hsat Porbelem bime Lseen. + + + Du bist riesig. + + + Du bist riesig. + + + Du bist winzig. + + + Du bist winzig. + + + Du hast eine Glatze. + + + Du hast eine Glatze. + + + Kann nicht zurückgeworfen werden. + + + Kann nicht zurückgeworfen werden. + + + Farbenblind + + + Ektomorph + + + Ektomorph + + + Alzheimer + + + Alzheimer + + + Dextrokardie + + + Dextrokardie + + + Koprolalie + + + Koprolalie + + + ADHS + + + ADHS + + + Zwangsstörung + + + Zwangsstörung + + + Hormonüberschuss + + + Hormonüberschuss + + + Muskelschwäche + + + Muskelschwäche + + + Stereoblindheit + + + Stereoblindheit + + + Reizdarm + + + Reizdarm + + + Farbenblind + + + Homosexuell + + + Vertigo + + + Vertigo + + + Tunnelblick + + + Tunnelblick + + + Tollpatschig + + + Tollpatschig + + + Arterienverschluss + + + Arterienverschluss + + + Alektorophobie + + + Alektorophobie + + + Hypochonder + + + Hypochonderin + + + Demenz + + + Demenz + + + Flexibel + + + Flexibel + + + Fotogr. Gedächtnis + + + Fotogr. Gedächtnis + + + Nostalgisch + + + Nostalgisch + + + Homosexuell + + + Kurzsichtig + + + Analgesie + + + Analgesie + + + Hochbegabt + + + Hochbegabt + + + Der Auserwählte + + + Die Auserwählte + + + Ungeschickt + + + Ungeschickt + + + Elektrosensibilität + + + Elektrosensibilität + + + Glaukom + + + Glaukom + + + Klonus + + + Klonus + + + Prosopagnosie + + + Prosopagnosie + + + Kurzsichtig + + + Weitsichtig + + + Weitsichtig + + + Legasthenie + + + Legasthenie + + + Riesenwuchs + + + Riesenwuchs + + + Zwergenwuchs + + + Zwergenwuchs + + + Glatzköpfig + + + Glatzköpfig + + + Endomorph + + + Endomorph + + + Entwickelt von + + + Entwickelt von + + + Design + + + Design + + + Programmierung + + + Programmierung + + + Produktion + + + Produktion + + + Grafik + + + Grafik + + + Sounddesign & Musik + + + Sounddesign & Musik + + + Musik + + + Musik + + + + + + + + + Sturzschlag hierauf anwenden + + + Sturzschlag hierauf anwenden + + + Drücke [Input:11] zum Springen. + + + Drücke [Input:11] zum Springen. + + + Halte [Input:11], um höher zu springen. + + + Halte [Input:11], um höher zu springen. + + + Drücke [Input:12], um anzugreifen + + + Drücke [Input:12], um anzugreifen + + + Halte [Input:19] und drücke [Input:11], um hinunterzufallen + + + Halte [Input:19] und drücke [Input:11], um hinunterzufallen + + + (Luft) Halte [Input:19] und drücke [Input:12] zum Sturzschlag + + + (Luft) Halte [Input:19] und drücke [Input:12] zum Sturzschlag + + + Drücke [Input:10] zum Springen + + + Drücke [Input:10] zum Springen + + + Halte[Input:10], um höher zu springen. + + + Halte[Input:10], um höher zu springen. + + + Drücke [Input:12], um anzugreifen + + + Drücke [Input:12], um anzugreifen + + + Halte [Input:18] und drücke [Input:10], um hinunterzufallen + + + Halte [Input:18] und drücke [Input:10], um hinunterzufallen + + + (Luft) Halte [Input:18] und drücke [Input:12] zum Sturzschlag + + + (Luft) Halte [Input:18] und drücke [Input:12] zum Sturzschlag + + + Verräter freischalten + + + Verräter freischalten + + \ No newline at end of file diff --git a/RogueCastle/Resources/LocStrings.es.resx b/RogueCastle/Resources/LocStrings.es.resx new file mode 100644 index 0000000..1862102 --- /dev/null +++ b/RogueCastle/Resources/LocStrings.es.resx @@ -0,0 +1,8357 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Salir a la pantalla del título + + + Salir a la pantalla del título + + + Salir a la pantalla del título (omitir tutorial) + + + Salir a la pantalla del título (omitir tutorial) + + + [Input:25] para cambiar el perfil ({0}) + + + [Input:25] para cambiar el perfil ({0}) + + + Salud + + + Teclas de flecha para desplazarte + + + Teclas de flecha para desplazarte + + + [Button:LeftStick] para desplazarte + + + [Button:LeftStick] para desplazarte + + + Elige una categoría + + + Elige una categoría + + + Se necesita un plano + + + Se necesita un plano + + + Información de compra aquí + + + Información de compra aquí + + + Nada + + + Nada + + + {0} para desbloquear + + + {0} para desbloquear + + + Salud + + + Maná + + + Maná + + + Daño + + + Daño + + + Magia + + + Magia + + + Coraza + + + Coraza + + + Peso + + + Peso + + + Propiedades adicionales: + + + Propiedades adicionales: + + + [Input:0] para seleccionar/equipar + + + [Input:0] para seleccionar/equipar + + + [Input:2] para cancelar/cerrar menú + + + [Input:2] para cancelar/cerrar menú + + + Objetivos destruidos + + + Objetivos destruidos + + + Objetivos restantes + + + Objetivos restantes + + + Recompensa + + + Recompensa + + + moneda(s) + + + moneda(s) + + + ver el mapa en cualquier momento + + + ver el mapa en cualquier momento + + + Cambiar controles + + + Acelerar hacia la derecha + + + Acelerar hacia la derecha + + + Lanzar hechizo + + + Lanzar hechizo + + + Restablecer controles + + + Restablecer controles + + + Pulsa cualquier tecla + + + Pulsa cualquier tecla + + + Cambiar controles + + + Arriba + + + Arriba + + + Abajo + + + Abajo + + + Izquierda + + + Izquierda + + + Derecha + + + Derecha + + + Atacar + + + Atacar + + + Saltar + + + Saltar + + + Especial + + + Especial + + + Acelerar hacia la izquierda + + + Acelerar hacia la izquierda + + + Héroe estándar; se le da bien prácticamente todo. + + + Un tanque con patas; puede aguantar lo que le echen.\nESPECIAL: grito bárbaro. + + + Un tanque con patas; puede aguantar lo que le echen.\nESPECIAL: grito bárbaro. + + + Héroe rápido; provoca daños de consideración, pero no críticos. + + + Heroína rápida; provoca daños de consideración, pero no críticos. + + + Héroe rápido; provoca daños de consideración, pero no críticos.\nESPECIAL: técnica de sustitución. + + + Heroína rápida; provoca daños de consideración, pero no críticos.\nESPECIAL: técnica de sustitución. + + + Héroe para expertos; ataca a los enemigos para recuperar maná. + + + Heroína para expertos; ataca a los enemigos para recuperar maná. + + + Héroe para expertos; ataca a los enemigos para recuperar maná.\nESPECIAL: hechizo potenciado. + + + Heroína para expertos; ataca a los enemigos para recuperar maná.\nESPECIAL: hechizo potenciado. + + + Se alimenta de los muertos; aumenta el límite de vida permanentemente por cada muerte, hasta un límite máximo. Extremadamente inteligente. + + + Se alimenta de los muertos; aumenta el límite de vida permanentemente por cada muerte, hasta un límite máximo. Extremadamente inteligente. + + + Se alimenta de los muertos; aumenta el límite de vida permanentemente por cada muerte, hasta un límite máximo. Extremadamente inteligente.\nESPECIAL: conversión de PV. + + + Se alimenta de los muertos; aumenta el límite de vida permanentemente por cada muerte, hasta un límite máximo. Extremadamente inteligente.\nESPECIAL: conversión de PV. + + + Eres un hombre-dragón. + + + Eres una mujer-dragón. + + + ????? + + + ????? + + + Heroína estándar; se le da bien prácticamente todo. + + + Héroe estándar; se le da bien prácticamente todo.\nESPECIAL: escudo de guardián. + + + Heroína estándar; se le da bien prácticamente todo.\nESPECIAL: escudo de guardián. + + + Héroe amante del riesgo; tiene estadísticas bajas pero puede lanzar devastadores ataques críticos. + + + Heroína amante del riesgo; tiene estadísticas bajas pero puede lanzar devastadores ataques críticos. + + + Héroe amante del riesgo; tiene estadísticas bajas, pero puede lanzar devastadores ataques críticos.\nESPECIAL: forma de neblina. + + + Heroína amante del riesgo; tiene estadísticas bajas, pero puede lanzar devastadores ataques críticos.\nESPECIAL: forma de neblina. + + + Héroe para avariciosos; muy débil, pero tiene grandes bonificaciones de oro. + + + Heroína para avariciosos; muy débil, pero tiene grandes bonificaciones de oro. + + + Héroe para avariciosos; muy débil, pero tiene grandes bonificaciones de oro.\nESPECIAL: linterna de cabeza. + + + Heroína para avariciosos; muy débil, pero tiene grandes bonificaciones de oro.\nESPECIAL: linterna de cabeza. + + + Poderoso lanzador de hechizos; cada vez que mata, recibes maná. + + + Poderosa lanzadora de hechizos; cada vez que mata, recibes maná. + + + Poderoso lanzador de hechizos; cada vez que mata, recibes maná.\nESPECIAL: ciclo de hechizo. + + + Poderosa lanzadora de hechizos; cada vez que mata, recibes maná.\nESPECIAL: ciclo de hechizo. + + + Un tanque con patas; puede aguantar lo que le echen. + + + Un tanque con patas; puede aguantar lo que le echen. + + + Reina bárbara + + + Reina bárbara + + + Rey bárbaro + + + Rey bárbaro + + + Shinobi + + + Shinobi + + + Hokage + + + Hokage + + + Ladrona de hechizos + + + Ladrona de hechizos + + + Ladrón de hechizos + + + Ladrón de hechizos + + + Espadachina hechicera + + + Espadachina hechicera + + + Espadachín hechicero + + + Espadachín hechicero + + + Lich + + + Lich + + + Reina lich + + + Reina lich + + + Rey lich + + + Rey lich + + + Dragona + + + Dragona + + + Dragón + + + Dragón + + + Traidora + + + Traidora + + + Traidor + + + Traidor + + + Caballera + + + Caballera + + + Caballero + + + Caballero + + + Paladina + + + Paladina + + + Paladín + + + Paladín + + + Granuja + + + Granuja + + + Granuja + + + Granuja + + + Asesina + + + Asesina + + + Asesino + + + Asesino + + + Minera + + + Minera + + + Minero + + + Minero + + + Espeleóloga + + + Espeleóloga + + + Espeleólogo + + + Espeleólogo + + + Maga + + + Maga + + + Mago + + + Mago + + + Archimaga + + + Archimaga + + + Archimago + + + Archimago + + + Bárbara + + + Bárbara + + + Bárbaro + + + Bárbaro + + + ¡Gracias por jugar! + + + Arte + + + Arte + + + Música y diseño de audio + + + Música y diseño de audio + + + Música + + + Música + + + Marketing y guion + + + Marketing y guion + + + Diseño de audio adicional + + + Diseño de audio adicional + + + Diseño de fondos adicional + + + Diseño de fondos adicional + + + Apoyo empresarial + + + Apoyo empresarial + + + Agradecimientos superespeciales: edición Turbo + + + Agradecimientos superespeciales: edición Turbo + + + Agradecimientos especiales + + + Agradecimientos especiales + + + Agradecimientos adicionales + + + Agradecimientos adicionales + + + ¡Gracias por jugar! + + + Total de hijos + + + Adaptación a Mac/Linux por + + + Adaptación a Mac/Linux por + + + Equipo de CC en Mac/Linux + + + Equipo de CC en Mac/Linux + + + ¡Gracias a todos nuestros fans por su apoyo! + + + ¡Gracias a todos nuestros fans por su apoyo! + + + Localización principal por + + + Localización principal por + + + Localización al chino y adicional por + + + Localización al chino y adicional por + + + Total de hijos + + + Tiempo de juego + + + Tiempo de juego + + + Pulsa [Input:0] para salir + + + Pulsa [Input:0] para salir + + + Desarrollado por + + + Desarrollado por + + + Diseño y guion + + + Diseño y guion + + + Programación + + + Programación + + + Producción + + + Producción + + + Zona muerta joystick + + + Zona muerta joystick + + + Borrar datos guardados + + + Borrar datos guardados + + + Diario del príncipe + + + Aunque soy el primogénito, no soy el preferido de mi padre. Siempre he sabido que no pensaba dejarme nada a mí. + + + ¿... Y si los hubiera confundido con monstruos? + + + ¿... Y si los hubiera confundido con monstruos? + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 17 + + + Entrada del diario n.º 17 + + + Creo que me estoy volviendo loco. Me he encontrado con un carnaval entero en este castillo, con su payaso triste y todo. + + + Creo que me estoy volviendo loco. Me he encontrado con un carnaval entero en este castillo, con su payaso triste y todo. + + + Es un poco pesado, pero supongo que no puedo ser muy exigente con mis amistades en un lugar como este. + + + Es un poco pesado, pero supongo que no puedo ser muy exigente con mis amistades en un lugar como este. + + + Tengo hambre otra vez, menos mal que me he guardado muslos de pollo. Estos los encontré en un candelabro. + + + Tengo hambre otra vez, menos mal que me he guardado muslos de pollo. Estos los encontré en un candelabro. + + + Este castillo... a veces me pregunto si no será todo una broma de mal gusto. + + + Este castillo... a veces me pregunto si no será todo una broma de mal gusto. + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 18 + + + Entrada del diario n.º 18 + + + He derrotado a la bestia de la torre y, de nuevo, he sentido cómo la sala del trono cedía parte de su poder. + + + He derrotado a la bestia de la torre y, de nuevo, he sentido cómo la sala del trono cedía parte de su poder. + + + Aunque soy el primogénito, no soy el preferido de mi padre. Siempre he sabido que no pensaba dejarme nada a mí. + + + Pero, si encuentro la cura, todo cambiará. + + + ¡Esta victoria me produce una emoción totalmente embriagadora! ¡Nunca me había sentido tan seguro de mí mismo, tan poderoso, tan... en casa! ¡Un poco más y conseguiré mi recompensa! + + + ¡Esta victoria me produce una emoción totalmente embriagadora! ¡Nunca me había sentido tan seguro de mí mismo, tan poderoso, tan... en casa! ¡Un poco más y conseguiré mi recompensa! + + + ¡Estoy tan cerca! ¡Haré que mi padre se sienta orgulloso de mí! + + + ¡Estoy tan cerca! ¡Haré que mi padre se sienta orgulloso de mí! + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 19 + + + Entrada del diario n.º 19 + + + Llevo delante de esta puerta de la mazmorra más tiempo del que me atrevo a admitir. + + + Llevo delante de esta puerta de la mazmorra más tiempo del que me atrevo a admitir. + + + Mi coraje se ha debilitado, pues he visto a los monstruos de abajo y, en comparación, hacen que mis hazañas anteriores parezcan irrisorias. + + + Mi coraje se ha debilitado, pues he visto a los monstruos de abajo y, en comparación, hacen que mis hazañas anteriores parezcan irrisorias. + + + Tengo que prepararme, concentrarme. Ahí abajo hay tan poca luz que temo perderme. + + + Tengo que prepararme, concentrarme. Ahí abajo hay tan poca luz que temo perderme. + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 20 + + + Entrada del diario n.º 20 + + + Pensé que sabía lo que era la oscuridad, pero en esta mazmorra la oscuridad tiene su propia voz. + + + Pensé que sabía lo que era la oscuridad, pero en esta mazmorra la oscuridad tiene su propia voz. + + + Pero, si encuentro la cura, todo cambiará. + + + ¡El ganador conseguirá nada menos que el trono después de su deceso! + + + Me llama a través de las rejillas, por todas las esquinas. Se burla de mí. + + + Me llama a través de las rejillas, por todas las esquinas. Se burla de mí. + + + La oscuridad es tan densa que casi se diría tangible, y las bestias han hecho de esto su hogar. Se mueven rápidamente por los pasadizos y son más aterradoras que todo a lo que me había enfrentado hasta ahora. + + + La oscuridad es tan densa que casi se diría tangible, y las bestias han hecho de esto su hogar. Se mueven rápidamente por los pasadizos y son más aterradoras que todo a lo que me había enfrentado hasta ahora. + + + Debo ser prudente y elegir bien mis combates. En estos momentos, un exceso de confrontación podría costarme la vida. + + + Debo ser prudente y elegir bien mis combates. En estos momentos, un exceso de confrontación podría costarme la vida. + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 21 + + + Entrada del diario n.º 21 + + + ¡Lo he conseguido! ¡He derrotado al señor de la mazmorra! Ahora solo me falta entrar en la sala del trono. + + + ¡Lo he conseguido! ¡He derrotado al señor de la mazmorra! Ahora solo me falta entrar en la sala del trono. + + + ¡Después de esto, el rey me honrará por mi valor y reconocerá mi legítimo derecho a ocupar el trono! + + + ¡Después de esto, el rey me honrará por mi valor y reconocerá mi legítimo derecho a ocupar el trono! + + + ¡En lugar de mis hermanos sin rostro! + + + ¡En lugar de mis hermanos sin rostro! + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 22 + + + Entrada del diario n.º 22 + + + ¡El ganador conseguirá nada menos que el trono después de su deceso! + + + Cuando ocupe el trono, mi esposa y mis hijos se trasladarán a los aposentos reales. ¡Volveremos a la ciudad regia, donde de nuevo se nos tratará con el respeto que merecemos! + + + Estoy aquí sentado, haciendo los últimos preparativos. Lo único que me separa del señor de este castillo son las puertas doradas. + + + Estoy aquí sentado, haciendo los últimos preparativos. Lo único que me separa del señor de este castillo son las puertas doradas. + + + Siento una ansiedad que no soy capaz de reprimir. ¿Es miedo o excitación? Lo único que sé es que mi viaje está llegando a su fin. + + + Siento una ansiedad que no soy capaz de reprimir. ¿Es miedo o excitación? Lo único que sé es que mi viaje está llegando a su fin. + + + Casi había olvidado para qué entré en este castillo, pero ahora lo recuerdo. + + + Casi había olvidado para qué entré en este castillo, pero ahora lo recuerdo. + + + He superado a mis hermanos, salvaré al rey, y cuando salga de este castillo seré más hombre que cuando entré. Por fin, mi familia recibirá el honor que le corresponde. + + + He superado a mis hermanos, salvaré al rey, y cuando salga de este castillo seré más hombre que cuando entré. Por fin, mi familia recibirá el honor que le corresponde. + + + Y ahora voy a entrar en la sala del trono. + + + Y ahora voy a entrar en la sala del trono. + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 23 + + + Entrada del diario n.º 23 + + + Nunca supe qué tesoro encerraba este castillo; solo sabía que curaría al rey. + + + Nunca supe qué tesoro encerraba este castillo; solo sabía que curaría al rey. + + + ¿Quién iba a sospechar que se trataba de la Fuente de la Juventud? + + + ¿Quién iba a sospechar que se trataba de la Fuente de la Juventud? + + + Esperaba encontrar a un monstruo dándome la bienvenida desde el estrado; o a un enemigo dotado de una fuerza inimaginable. Pensé que debería emplear toda mi fuerza para derrotarlo. + + + Esperaba encontrar a un monstruo dándome la bienvenida desde el estrado; o a un enemigo dotado de una fuerza inimaginable. Pensé que debería emplear toda mi fuerza para derrotarlo. + + + Cuando ocupe el trono, mi esposa y mis hijos se trasladarán a los aposentos reales. ¡Volveremos a la ciudad regia, donde de nuevo se nos tratará con el respeto que merecemos! + + + Ya no tendremos que soportar el chismorreo y las calumnias mezquinas de mis primos. ¡Los duques se inclinarán a nuestro paso! Pero me estoy adelantando a las circunstancias... + + + Pero cuando entré en el castillo y vi a mi padre, el rey, sentado sobre el estrado con un cáliz en la mano, supe que todo estaba perdido. + + + Pero cuando entré en el castillo y vi a mi padre, el rey, sentado sobre el estrado con un cáliz en la mano, supe que todo estaba perdido. + + + Jamás iba a morir... + + + Jamás iba a morir... + + + ... y yo nunca sería el heredero. + + + ... y yo nunca sería el heredero. + + + No tengo palabras para expresar lo que siento. + + + No tengo palabras para expresar lo que siento. + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 24 + + + Entrada del diario n.º 24 + + + .............................. + + + .............................. + + + .... + + + .... + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 25 + + + Entrada del diario n.º 25 + + + Ya no tendremos que soportar el chismorreo y las calumnias mezquinas de mis primos. ¡Los duques se inclinarán a nuestro paso! Pero me estoy adelantando a las circunstancias... + + + Debo tener claras mis prioridades: conquistar el castillo. Encontrar la cura. Conseguir mi recompensa. + + + Hoy comienza el resto de la eternidad. + + + Hoy comienza el resto de la eternidad. + + + Nunca supe qué tesoro encerraba este castillo; solo sabía que curaría al rey. + + + Nunca supe qué tesoro encerraba este castillo; solo sabía que curaría al rey. + + + ... ¿Quién habría sabido que se trataba de la Fuente de la Juventud? Un mito que te concede la vida eterna. + + + ... ¿Quién habría sabido que se trataba de la Fuente de la Juventud? Un mito que te concede la vida eterna. + + + Al mirar el cuerpo del rey, me doy cuenta de que es inevitable: los hijos siempre pagarán por los pecados de sus padres. + + + Al mirar el cuerpo del rey, me doy cuenta de que es inevitable: los hijos siempre pagarán por los pecados de sus padres. + + + Cuando entré en este castillo era un espadachín, un salvador... + + + Cuando entré en este castillo era un espadachín, un salvador... + + + Pero ahora, lo único que me queda es el legado de un canalla. + + + Pero ahora, lo único que me queda es el legado de un canalla. + + + Puedo percibir tu ira, pero quiero que sepas que no fui yo quien le trajo la ruina a tu familia. + + + Puedo percibir tu ira, pero quiero que sepas que no fui yo quien le trajo la ruina a tu familia. + + + En el momento en que el rey pisó este castillo, Charon vació las arcas reales y mi familia, todas las familias, perdieron toda esperanza de una vida mejor. + + + En el momento en que el rey pisó este castillo, Charon vació las arcas reales y mi familia, todas las familias, perdieron toda esperanza de una vida mejor. + + + Y en mi imaginación vi cómo la desesperación y la pobreza asolaban este país. Ya no me quedaba nada a lo que regresar. + + + Y en mi imaginación vi cómo la desesperación y la pobreza asolaban este país. Ya no me quedaba nada a lo que regresar. + + + Por mis hijos y los hijos de mis hijos me siento aquí, impasible, inmortal... te estoy esperando. + + + Por mis hijos y los hijos de mis hijos me siento aquí, impasible, inmortal... te estoy esperando. + + + Debo tener claras mis prioridades: conquistar el castillo. Encontrar la cura. Conseguir mi recompensa. + + + Diario del príncipe + + + Johannes + + + Johannes + + + ¿Qué es esto? ¡¿Te estás... burlando de mí?! + + + ¿Qué es esto? ¡¿Te estás... burlando de mí?! + + + Innumerables generaciones de antepasados tuyos sacrificaron su vida por estar donde tú estás ahora, los últimos pasos para lograr su justicia hueca. ¿Y tú llegas y te burlas de mí? + + + Innumerables generaciones de antepasados tuyos sacrificaron su vida por estar donde tú estás ahora, los últimos pasos para lograr su justicia hueca. ¿Y tú llegas y te burlas de mí? + + + Está bien, te perdono tu ignorancia. ¡Comencemos! + + + Está bien, te perdono tu ignorancia. ¡Comencemos! + + + Johannes + + + Johannes + + + ¿Por qué deseas enfrentarte a mí? ¿Cuántos hijos e hijas se han perdido con vuestros patéticos intentos de venganza? + + + ¿Por qué deseas enfrentarte a mí? ¿Cuántos hijos e hijas se han perdido con vuestros patéticos intentos de venganza? + + + ¡Fue el rey quién trajo la ruina a tu país, no yo! + + + ¡Fue el rey quién trajo la ruina a tu país, no yo! + + + Nos mintió. Nos dijo que estaba herido, ¡pero el tiempo era la única amenaza que se cernía sobre él! + + + Nos mintió. Nos dijo que estaba herido, ¡pero el tiempo era la única amenaza que se cernía sobre él! + + + Enfrentó a sus hijos entre sí, lo sacrificó todo para satisfacer sus deseos egoístas, y al final nos dejó solos y en la ruina. + + + Enfrentó a sus hijos entre sí, lo sacrificó todo para satisfacer sus deseos egoístas, y al final nos dejó solos y en la ruina. + + + Así que acepté la única opción que me quedaba: rechacé al rey, al país... + + + Así que acepté la única opción que me quedaba: rechacé al rey, al país... + + + Diario del príncipe + + + Entrada del diario n.º 3 + + + ¡Y elegí una nueva familia! + + + ¡Y elegí una nueva familia! + + + Johannes + + + Johannes + + + ¿Crees que has acabado conmigo? + + + ¿Crees que has acabado conmigo? + + + ¡Llevo vivo más de mil años y viviré mil más! + + + ¡Llevo vivo más de mil años y viviré mil más! + + + Alejandro... Khidr... Ponce de León... + + + Alejandro... Khidr... Ponce de León... + + + Yo no fui el primer héroe que logró llegar hasta la fuente... + + + Yo no fui la primera heroína que logró llegar hasta la fuente... + + + ¡Pero sí voy a ser el último! + + + ¡Pero sí voy a ser la última! + + + Fuente de la Juventud + + + Fuente de la Juventud + + + ... + + + ... + + + Me has derrotado, pero... ¿a qué precio? + + + Me has derrotado, pero... ¿a qué precio? + + + Entrada del diario n.º 3 + + + He pagado la cuota y he entrado al castillo legítimamente. El demonio Charon se ha quedado con todo lo que tengo. + + + He destruido al rey, pero después de que traicionara a su gente. + + + He destruido al rey, pero después de que traicionara a su gente. + + + ¿Te preguntas si se ha hecho justicia? + + + ¿Te preguntas si se ha hecho justicia? + + + Al final, todos somos culpables del mismo pecado. Mira a tus antepasados: ese es el precio de la lealtad incuestionable. + + + Al final, todos somos culpables del mismo pecado. Mira a tus antepasados: ese es el precio de la lealtad incuestionable. + + + ... + + + ... + + + ... + + + ... + + + El sol... + + + El sol... + + + Había olvidado lo que era sentir su calor... + + + Había olvidado lo que era sentir su calor... + + + He pagado la cuota y he entrado al castillo legítimamente. El demonio Charon se ha quedado con todo lo que tengo. + + + ¡Hasta ha saqueado mis arcas privadas! A mi mujer y mis hijos no les queda nada. + + + ¡Hasta ha saqueado mis arcas privadas! A mi mujer y mis hijos no les queda nada. + + + Diario del príncipe + + + Entrada del diario n.º 1 + + + Dice que es el precio que deben pagar todos los que osan adentrarse en el castillo; opina que es lo justo. + + + Dice que es el precio que deben pagar todos los que osan adentrarse en el castillo; opina que es lo justo. + + + Es justo porque ninguno de los que han entrado ha regresado jamás. Pero eso está a punto de cambiar. + + + Es justo porque ninguno de los que han entrado ha regresado jamás. Pero eso está a punto de cambiar. + + + ¡Lograré la victoria! No hay quien me supere con la espada, ni siquiera ninguno de mis hermanos. + + + ¡Lograré la victoria! No hay quien me supere con la espada, ni siquiera ninguno de mis hermanos. + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 4 + + + Entrada del diario n.º 4 + + + En este castillo todo resulta muy extraño, no consigo controlar la dirección en la que voy, y no hay ni estrellas ni sol para poder guiarme. + + + En este castillo todo resulta muy extraño, no consigo controlar la dirección en la que voy, y no hay ni estrellas ni sol para poder guiarme. + + + Cada dos por tres tengo que retroceder, y constantemente me toca analizar mis progresos para no ir moviéndome en círculos. + + + Cada dos por tres tengo que retroceder, y constantemente me toca analizar mis progresos para no ir moviéndome en círculos. + + + Los mapas que he cogido de los cadáveres de otros aventureros son terriblemente imprecisos. ¡Es como si describieran un castillo completamente diferente! + + + Los mapas que he cogido de los cadáveres de otros aventureros son terriblemente imprecisos. ¡Es como si describieran un castillo completamente diferente! + + + Tal vez, este lugar juega con tu mente... + + + Tal vez, este lugar juega con tu mente... + + + ¿O es cierto que las piedras se mueven bajo mis pies? + + + ¿O es cierto que las piedras se mueven bajo mis pies? + + + Entrada del diario n.º 1 + + + ¡Traición! ¡Un asesino ha herido al rey, mi padre! + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 5 + + + Entrada del diario n.º 5 + + + No puedo salir por la puerta principal, pero no me preocupa demasiado. ¡Me he comprometido con la causa y no pienso retroceder! + + + No puedo salir por la puerta principal, pero no me preocupa demasiado. ¡Me he comprometido con la causa y no pienso retroceder! + + + Hasta ahora, ninguno de los mapas que he encontrado coincide con el mío. + + + Hasta ahora, ninguno de los mapas que he encontrado coincide con el mío. + + + Pero si los comparo todos creo que, en general, tienen ciertas características comunes: parece que el bosque siempre está a la derecha, la torre arriba... + + + Pero si los comparo todos creo que, en general, tienen ciertas características comunes: parece que el bosque siempre está a la derecha, la torre arriba... + + + ¿Y abajo? Bueno, espero no tener que descubrirlo. + + + ¿Y abajo? Bueno, espero no tener que descubrirlo. + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 6 + + + Entrada del diario n.º 6 + + + Nunca me gustó la oscuridad, prefiero vérmelas con mis enemigos en campo abierto y a plena vista. + + + Nunca me gustó la oscuridad, prefiero vérmelas con mis enemigos en campo abierto y a plena vista. + + + Pero ahora me veo adentrándome en estos siniestros patíbulos con una mano hacia delante y la otra en la empuñadura de mi espada. Nunca sé qué horrores me voy a encontrar tras cada esquina. + + + Pero ahora me veo adentrándome en estos siniestros patíbulos con una mano hacia delante y la otra en la empuñadura de mi espada. Nunca sé qué horrores me voy a encontrar tras cada esquina. + + + ¡Traición! ¡Un asesino ha herido al rey, mi padre! + + + Para poder restablecer el orden en el reino, nos ha enviado a mí y a mis hermanos a una misión para salvarlo. Juntos penetraremos en el bosque maldito y entraremos en el Castillo de Hamson. + + + Soy el mejor espadachín de todas las tierras y, a pesar de todo, me cuesta controlar a estos demonios. + + + Soy el mejor espadachín de todas las tierras y, a pesar de todo, me cuesta controlar a estos demonios. + + + Mis hermanos deberían estar agradecidos de que me haya adelantado. Para ellos ha sido una bendición encubierta, no tendrían la fortaleza para sobrevivir en estos pasadizos. + + + Mis hermanos deberían estar agradecidos de que me haya adelantado. Para ellos ha sido una bendición encubierta, no tendrían la fortaleza para sobrevivir en estos pasadizos. + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 7 + + + Entrada del diario n.º 7 + + + Sigue siendo de noche. Cada ventana me muestra la mirada de la misma luna melancólica, pero yo juraría que ya llevo aquí un día entero. + + + Sigue siendo de noche. Cada ventana me muestra la mirada de la misma luna melancólica, pero yo juraría que ya llevo aquí un día entero. + + + Debe de ser la adrenalina. Nunca me había sentido tan poderoso y desafiado al mismo tiempo. Atravesar estas salas cargando contra un enemigo tras otro me resulta muy estimulante. + + + Debe de ser la adrenalina. Nunca me había sentido tan poderoso y desafiado al mismo tiempo. Atravesar estas salas cargando contra un enemigo tras otro me resulta muy estimulante. + + + De algún modo, parece que los enemigos del castillo se adaptan a mí: me van entrenando, guiándome, vigilándome. + + + De algún modo, parece que los enemigos del castillo se adaptan a mí: me van entrenando, guiándome, vigilándome. + + + Puede que parezca una locura pero, me temo que este castillo podría tener intenciones malignas. Y si mis conjeturas son acertadas, estos pasillos podrían conducirme hasta una trampa terrible. + + + Puede que parezca una locura pero, me temo que este castillo podría tener intenciones malignas. Y si mis conjeturas son acertadas, estos pasillos podrían conducirme hasta una trampa terrible. + + + Debo mantenerme alerta. + + + Debo mantenerme alerta. + + + Diario del príncipe + + + Diario del príncipe + + + Para poder restablecer el orden en el reino, nos ha enviado a mí y a mis hermanos a una misión para salvarlo. Juntos penetraremos en el bosque maldito y entraremos en el Castillo de Hamson. + + + Este castillo maldito se alza en el límite del bosque desde tiempos inmemoriales, pero se dice que en su interior hay un objeto capaz de curar cualquier dolencia. + + + Entrada del diario n.º 8 + + + Entrada del diario n.º 8 + + + A juzgar por el número de aventureros muertos que he pasado en los pasillos, deduzco las siguientes conclusiones: + + + A juzgar por el número de aventureros muertos que he pasado en los pasillos, deduzco las siguientes conclusiones: + + + 1: Muchos de ellos no llevaban las provisiones necesarias. Supongo que muchos murieron de hambre. Yo también me estoy quedando sin provisiones, así que tendré que buscar más. + + + 1: Muchos de ellos no llevaban las provisiones necesarias. Supongo que muchos murieron de hambre. Yo también me estoy quedando sin provisiones, así que tendré que buscar más. + + + 2: A muchos les faltan prendas de ropa, lo que explica por qué hay zombis que llevan pantalones. + + + 2: A muchos les faltan prendas de ropa, lo que explica por qué hay zombis que llevan pantalones. + + + 3: Nadie ha llegado tan lejos como yo, puesto que hace más de una hora que no veo ningún cadáver. + + + 3: Nadie ha llegado tan lejos como yo, puesto que hace más de una hora que no veo ningún cadáver. + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 9 + + + Entrada del diario n.º 9 + + + ¡La puerta de la sala del trono me está volviendo loco! Tras esta puerta se encuentra la salvación del rey, y mi recompensa, pero permanece impávida mofándose de mí en el centro del hall del castillo. + + + ¡La puerta de la sala del trono me está volviendo loco! Tras esta puerta se encuentra la salvación del rey, y mi recompensa, pero permanece impávida mofándose de mí en el centro del hall del castillo. + + + He intentado empujarla, patearla, hasta gritar "Ábrete Sésamo", pero nada ha funcionado. + + + He intentado empujarla, patearla, hasta gritar "Ábrete Sésamo", pero nada ha funcionado. + + + Las puertas están adornadas con unos iconos, y uno de ellos se parece a una de las bestias que he encontrado en las profundidades del castillo. A lo mejor hay algún tipo de correlación. + + + Las puertas están adornadas con unos iconos, y uno de ellos se parece a una de las bestias que he encontrado en las profundidades del castillo. A lo mejor hay algún tipo de correlación. + + + Este castillo maldito se alza en el límite del bosque desde tiempos inmemoriales, pero se dice que en su interior hay un objeto capaz de curar cualquier dolencia. + + + Esta noche me adelantaré a mis hermanos y hermanas e iniciaré mi misión mientras duermen. + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 10 + + + Entrada del diario n.º 10 + + + ¡Los emblemas de la puerta del castillo son pistas! He matado a la bestia gigante que aparece en uno de los iconos y he sentido cómo cambiaba algo tras las puertas de la sala del trono. + + + ¡Los emblemas de la puerta del castillo son pistas! He matado a la bestia gigante que aparece en uno de los iconos y he sentido cómo cambiaba algo tras las puertas de la sala del trono. + + + Como si estuviera soñando, he visto un emblema en la puerta que brillaba en mi imaginación. + + + Como si estuviera soñando, he visto un emblema en la puerta que brillaba en mi imaginación. + + + Una experiencia verdaderamente sobrenatural. + + + Una experiencia verdaderamente sobrenatural. + + + Al menos sé que voy por buen camino. Debo acelerar el paso, pues el rey podría perecer en cualquier momento... + + + Al menos sé que voy por buen camino. Debo acelerar el paso, pues el rey podría perecer en cualquier momento... + + + Pero primero debo descansar. Mañana me adentraré en el bosque. + + + Pero primero debo descansar. Mañana me adentraré en el bosque. + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 11 + + + Entrada del diario n.º 11 + + + Este bosque no se parece a otros bosques. Es sereno y aterrador a la vez. Estoy sobre una zona de hierba pero, a mi lado, bosteza con las fauces abiertas una sima tan ancha y profunda, que amenaza con tragárseme de un bocado. + + + Este bosque no se parece a otros bosques. Es sereno y aterrador a la vez. Estoy sobre una zona de hierba pero, a mi lado, bosteza con las fauces abiertas una sima tan ancha y profunda, que amenaza con tragárseme de un bocado. + + + Esta noche me adelantaré a mis hermanos y hermanas e iniciaré mi misión mientras duermen. + + + Fracasar en esta misión supondría una gran humillación para mi buen nombre. + + + Todavía no he oído ninguna respuesta de la roca que he lanzado antes. Un paso en falso y mi descenso será eterno. La idea me inunda de terror. + + + Todavía no he oído ninguna respuesta de la roca que he lanzado antes. Un paso en falso y mi descenso será eterno. La idea me inunda de terror. + + + Una eternidad de tinieblas es más aterradora que cualquier bestia contra la que me he enfrentado hasta ahora. Si cayera, ¿qué me mataría primero? ¿El hambre o yo mismo? + + + Una eternidad de tinieblas es más aterradora que cualquier bestia contra la que me he enfrentado hasta ahora. Si cayera, ¿qué me mataría primero? ¿El hambre o yo mismo? + + + Me gustaría puntualizar que ahora estoy usando esta fisura del bosque como retrete personal. Me pregunto si estoy evacuando en otra dimensión... + + + Me gustaría puntualizar que ahora estoy usando esta fisura del bosque como retrete personal. Me pregunto si estoy evacuando en otra dimensión... + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 12 + + + Entrada del diario n.º 12 + + + He encontrado una solución al problema del hambre: el bosque cuenta con cantidades infinitas de deliciosos champiñones. + + + He encontrado una solución al problema del hambre: el bosque cuenta con cantidades infinitas de deliciosos champiñones. + + + ¡Y dentro de estos champiñones hay muslos de pollo! Y monedas de oro, y viales de agua con gas... Antes he abierto el tronco de un árbol y ha caído una bolsa de dinero. + + + ¡Y dentro de estos champiñones hay muslos de pollo! Y monedas de oro, y viales de agua con gas... Antes he abierto el tronco de un árbol y ha caído una bolsa de dinero. + + + A veces siento que he perdido el juicio. + + + A veces siento que he perdido el juicio. + + + ... ¿Y qué es lo que pasa con la luna? ¡Es ENORME! + + + ... ¿Y qué es lo que pasa con la luna? ¡Es ENORME! + + + Diario del príncipe + + + Diario del príncipe + + + Fracasar en esta misión supondría una gran humillación para mi buen nombre. + + + Diario del príncipe + + + Entrada del diario n.º 13 + + + Entrada del diario n.º 13 + + + He matado a la bestia del bosque y he vuelto a sentir, una vez más, cómo se debilitaba la sala del trono. + + + He matado a la bestia del bosque y he vuelto a sentir, una vez más, cómo se debilitaba la sala del trono. + + + Hasta ahora mis conjeturas han resultado ser ciertas. Cada ala del castillo tiene su propia bestia guardiana. ¿Fue diseñado como una prueba de templanza? Si es así, no puedo fallar: ¡cuanto más avanzo, más audaz me siento! + + + Hasta ahora mis conjeturas han resultado ser ciertas. Cada ala del castillo tiene su propia bestia guardiana. ¿Fue diseñado como una prueba de templanza? Si es así, no puedo fallar: ¡cuanto más avanzo, más audaz me siento! + + + Mañana recorreré la torre. Tengo una buena racha. + + + Mañana recorreré la torre. Tengo una buena racha. + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 14 + + + Entrada del diario n.º 14 + + + He estado limpiando de forma metódica estas salas en mi misión por derrotar al siguiente guardián, pero estoy perdiendo la noción del tiempo... y de otras cosas... + + + He estado limpiando de forma metódica estas salas en mi misión por derrotar al siguiente guardián, pero estoy perdiendo la noción del tiempo... y de otras cosas... + + + Cuando entro a la torre siento que el tiempo se detiene. ¿O es por culpa del vértigo? Nunca me han gustado las alturas... ¿o sí? + + + Cuando entro a la torre siento que el tiempo se detiene. ¿O es por culpa del vértigo? Nunca me han gustado las alturas... ¿o sí? + + + Cada vez me cuesta más recordar el pasado... + + + Cada vez me cuesta más recordar el pasado... + + + Diario del príncipe + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 2 + + + Entrada del diario n.º 15 + + + Entrada del diario n.º 15 + + + Recuerdo que fui un aventurero de renombre. Mis habilidades marciales superaban a las de mis hermanos, de eso no hay duda. Mientras ellos se pasaban los días entre libros, yo me dedicaba a matar forajidos y monstruos. + + + Recuerdo que fui un aventurero de renombre. Mis habilidades marciales superaban a las de mis hermanos, de eso no hay duda. Mientras ellos se pasaban los días entre libros, yo me dedicaba a matar forajidos y monstruos. + + + Siempre me he preguntado por qué mi padre los prefería a mí... ¿No suele ser al revés en los cuentos? + + + Siempre me he preguntado por qué mi padre los prefería a mí... ¿No suele ser al revés en los cuentos? + + + La fortuna favorece a los audaces... no a los intelectuales insípidos... O algo así. + + + La fortuna favorece a los audaces... no a los intelectuales insípidos... O algo así. + + + ¡Me encantaría ver a mis hermanos intentando librarse de mi espada con sus pensamientos profundos! + + + ¡Me encantaría ver a mis hermanos intentando librarse de mi espada con sus pensamientos profundos! + + + Diario del príncipe + + + Diario del príncipe + + + Entrada del diario n.º 16 + + + Entrada del diario n.º 16 + + + ¿Y si han pasado años desde que penetré entre estos muros? Es cierto que cada vez soy más hábil en la matanza de monstruos, pero me siento como si hubiera transcurrido toda una era. + + + ¿Y si han pasado años desde que penetré entre estos muros? Es cierto que cada vez soy más hábil en la matanza de monstruos, pero me siento como si hubiera transcurrido toda una era. + + + Hasta he olvidado la cara de mi gente. + + + Hasta he olvidado la cara de mi gente. + + + ¿Y si piensan que he fracasado? ¿Y si uno de mis hermanos se me ha adelantado y se ha hecho con la cura? + + + ¿Y si piensan que he fracasado? ¿Y si uno de mis hermanos se me ha adelantado y se ha hecho con la cura? + + + Entrada del diario n.º 2 + + + Diario n.º + + + Diario n.º + + + Castillo de Hamson + + + Castillo de Hamson + + + Tierra de las Tinieblas + + + Tierra de las Tinieblas + + + Bosque de Abkhazia + + + Bosque de Abkhazia + + + La Maya + + + La Maya + + + Elige una categoría + + + Runa necesaria + + + Runa necesaria + + + Información de compra aquí + + + Información de compra aquí + + + {0} para desbloquear + + + {0} para desbloquear + + + Runa + + + Runa + + + Elige una categoría + + + Instrucciones + + + Instrucciones + + + [Input:0] para seleccionar/equipar + + + [Input:0] para seleccionar/equipar + + + [Input:2] para cancelar/cerrar menú + + + [Input:2] para cancelar/cerrar menú + + + Teclas de flecha para desplazarte + + + Teclas de flecha para desplazarte + + + [Button:LeftStick] para desplazarte + + + [Button:LeftStick] para desplazarte + + + Has matado + + + Has matado + + + Pulsa [Input:0] para salir + + + Pulsa [Input:0] para salir + + + Esqueleto + + + Blubasaurio rex + + + Abuelo chispas + + + Abuelo chispas + + + Señor de las Chispas, Rey de Chispolandia + + + Señor de las Chispas, Rey de Chispolandia + + + Mimo + + + Mimo + + + Mimetista + + + Mimetista + + + Copicat + + + Copicat + + + Cofrescor + + + Cofrescor + + + Barbatos + + + Barbatos + + + Stolas + + + Stolas + + + Beriz + + + Beriz + + + Amón + + + Amón + + + Blubasaurio rex + + + Herodotus + + + Focalor + + + Focalor + + + Halfas + + + Halfas + + + Neo Khidr + + + Neo Khidr + + + Alejandro IV + + + Alejandro IV + + + Astrodotus + + + Astrodotus + + + Ponce de Freón + + + Ponce de Freón + + + Los Brohannes + + + Los Brohannes + + + Torreta de pared + + + Torreta de pared + + + El Guardián + + + El Guardián + + + El Infinito + + + El Infinito + + + Herodotus + + + Cornitor + + + El Olvidado + + + El Olvidado + + + El Abandonado + + + El Abandonado + + + El Centinela + + + El Centinela + + + El Traidor + + + El Traidor + + + La Fuente + + + La Fuente + + + Beriz y Halfas + + + Beriz y Halfas + + + Barbatos y Amón + + + Barbatos y Amón + + + Stolas y Focalor + + + Stolas y Focalor + + + Cornitor + + + Cornitex + + + Cornitex + + + Cornitus + + + Cornitus + + + Panteón + + + Panteón + + + Orbesor + + + Orbesor + + + Gravisor + + + Gravisor + + + Terrasor + + + Terrasor + + + Llamaflux + + + Llamaflux + + + Esqueleto + + + Osamenta + + + Igniflux + + + Igniflux + + + Solaflux + + + Solaflux + + + Magisol + + + Magisol + + + Escarchan + + + Escarchan + + + Nevinan + + + Nevinan + + + Glacienan + + + Glacienan + + + Magiluna + + + Magiluna + + + Explorador + + + Explorador + + + Pupila + + + Pupila + + + Visionario + + + Visionario + + + Osamenta + + + Costillas + + + Khidr + + + Khidr + + + Furia + + + Furia + + + Rabia + + + Rabia + + + Ira + + + Ira + + + Alejandro + + + Alejandro + + + Guardia espigado + + + Guardia espigado + + + Guardia corpos + + + Guardia corpos + + + Guardia torre + + + Guardia torre + + + Centinela + + + Centinela + + + Mazátor + + + Mazátor + + + Costillas + + + Noble corrupto + + + Mazátex + + + Mazátex + + + Mazátus + + + Mazátus + + + Magual + + + Magual + + + Caballero gris + + + Caballero gris + + + Barón gris + + + Barón gris + + + Grisgladiator + + + Grisgladiator + + + Grissoldator + + + Grissoldator + + + Warg + + + Warg + + + Wargen + + + Wargen + + + Wargenglorgen + + + Wargenglorgen + + + Noble corrupto + + + Élite corrupto + + + Zorg Warg + + + Zorg Warg + + + Zombi + + + Zombi + + + Zomboner + + + Zomboner + + + Zombishnu + + + Zombishnu + + + Zomg + + + Zomg + + + Energón + + + Energón + + + Mastertrón + + + Mastertrón + + + Voltrón + + + Voltrón + + + Electratrón + + + Electratrón + + + Ninjo + + + Ninjo + + + Élite corrupto + + + Señor corrupto + + + Ninpo + + + Ninpo + + + Ninpojo + + + Ninpojo + + + Maestro ninja + + + Maestro ninja + + + Capullo + + + Capullo + + + Brote + + + Brote + + + Floremón + + + Floremón + + + Quiarita + + + Quiarita + + + Pirita + + + Pirita + + + Infernita + + + Infernita + + + Ponce de León + + + Ponce de León + + + Señor corrupto + + + Botis + + + Clavocepo + + + Clavocepo + + + Arquero + + + Arquero + + + Forestal + + + Forestal + + + Francotirador + + + Francotirador + + + Certero + + + Certero + + + Johannes + + + Johannes + + + La Fuente + + + La Fuente + + + Fuente de la Juventud + + + Fuente de la Juventud + + + Lienzo destrux + + + Lienzo destrux + + + Retrato destrux + + + Retrato destrux + + + Botis + + + Blub + + + Paisaje destrux + + + Paisaje destrux + + + Cuadro destrux + + + Cuadro destrux + + + Plinky + + + Plinky + + + Planky + + + Planky + + + Plonky + + + Plonky + + + Plunk + + + Plunk + + + Kentucky + + + Kentucky + + + Fried + + + Fried + + + Chicken + + + Chicken + + + Delicioso + + + Delicioso + + + Blub + + + Blubito + + + Magullator + + + Magullator + + + Magullator XL + + + Magullator XL + + + Magullator 2000 + + + Magullator 2000 + + + Magullator gigasaurio + + + Magullator gigasaurio + + + Caballo decapitado + + + Caballo decapitado + + + Semental oscuro + + + Semental oscuro + + + Yegua daña + + + Yegua daña + + + Mi pequeño poni + + + Mi pequeño poni + + + Chispas + + + Chispas + + + Chispón + + + Chispón + + + Blubito + + + Cripta + + + Maldición + + + Maldición + + + Gracia + + + Gracia + + + Tarifa del arquitecto + + + Tarifa del arquitecto + + + Bonificación NP+ + + + Bonificación NP+ + + + Cripta + + + Aceleración + + + Aceleración + + + Vampiro + + + Vampiro + + + Celestial + + + Celestial + + + Sifón + + + Sifón + + + Equilibrio + + + Equilibrio + + + Contraataque + + + Contraataque + + + Botín + + + Botín + + + Velocidad + + + Velocidad + + + de escudero + + + de asesino + + + de asesina + + + de sabio + + + de sabia + + + de sangre + + + de sangre + + + de contra + + + de contra + + + de beato + + + de beata + + + de oscuridad + + + de oscuridad + + + de escudera + + + de plata + + + de plata + + + de guardián + + + de guardiana + + + imperial + + + imperial + + + real + + + real + + + de caballero + + + de caballera + + + de forestal + + + de forestal + + + celestial + + + celestial + + + de dragón + + + de dragona + + + Espada + + + Espada + + + Capa + + + Capa + + + Brazales + + + Brazales + + + Casco + + + Casco + + + Peto + + + Peto + + + Nada + + + Nada + + + Espada + + + Espada + + + Capa + + + Capa + + + Brazal + + + Brazal + + + Casco + + + Casco + + + Peto + + + Peto + + + Nada + + + Nada + + + Te da el poder de saltar por el aire. Se pueden acumular varias runas para hacer saltos múltiples. + + + Enemigos más duros, pero mejores recompensas. Acumular runas hace que los enemigos sean aún más duros. + + + Enemigos más duros, pero mejores recompensas. Acumular runas hace que los enemigos sean aún más duros. + + + Los enemigos aumentan de nivel despacio; pero hay menos recompensas. Acumular runas potencia el efecto. + + + Los enemigos aumentan de nivel despacio; pero hay menos recompensas. Acumular runas potencia el efecto. + + + Te da el poder de saltar por el aire. Se pueden acumular varias runas para hacer saltos múltiples. + + + Te da el poder de recorrer rápidamente distancias cortas. Se pueden acumular varias runas para hacer aceleraciones múltiples. + + + Te da el poder de recorrer rápidamente distancias cortas. Se pueden acumular varias runas para hacer aceleraciones múltiples. + + + Al matar enemigos absorberás su salud. Se pueden acumular varias runas para aumentar la absorción de salud. + + + Al matar enemigos absorberás su salud. Se pueden acumular varias runas para aumentar la absorción de salud. + + + Consigue el poder del vuelo. Se pueden acumular varias runas para aumentar la duración del vuelo. + + + Consigue el poder del vuelo. Se pueden acumular varias runas para aumentar la duración del vuelo. + + + Les roba maná a los enemigos muertos. Se pueden acumular varias runas para aumentar el robo de maná. + + + Les roba maná a los enemigos muertos. Se pueden acumular varias runas para aumentar el robo de maná. + + + Al matar enemigos recibes PV y PM. Se pueden acumular varias runas para aumentar la ganancia de PV/PM. + + + Al matar enemigos recibes PV y PM. Se pueden acumular varias runas para aumentar la ganancia de PV/PM. + + + Devuelve los daños recibidos de los enemigos. Se pueden acumular varias runas para aumentar la devolución de daños. + + + Devuelve los daños recibidos de los enemigos. Se pueden acumular varias runas para aumentar la devolución de daños. + + + Aumenta la cantidad de oro que recibes de las monedas. Se pueden acumular varias runas para aumentar la ganancia de oro. + + + Aumenta la cantidad de oro que recibes de las monedas. Se pueden acumular varias runas para aumentar la ganancia de oro. + + + Aumenta tu velocidad de movimiento básica. Se pueden acumular varias runas para ir aún más rápido. + + + Aumenta tu velocidad de movimiento básica. Se pueden acumular varias runas para ir aún más rápido. + + + Los enemigos son más duros. + + + Los enemigos son más duros. + + + Los enemigos son más débiles. + + + Los enemigos son más débiles. + + + Pulsa [Input:10] cuando estés en el aire + + + Pulsa [Input:10] cuando estés en el aire + + + [Input:14] o [Input:15] para acelerar + + + [Input:14] o [Input:15] para acelerar + + + Mata enemigos para recuperar salud. + + + Mata enemigos para recuperar salud. + + + Pulsa [Input:10] cuando estés en el aire + + + Pulsa [Input:10] cuando estés en el aire + + + Mata enemigos para recuperar maná. + + + Mata enemigos para recuperar maná. + + + Mata enemigos para recuperar salud y maná. + + + Mata enemigos para recuperar salud y maná. + + + El daño se vuelve contra los enemigos. + + + El daño se vuelve contra los enemigos. + + + Las monedas te dan más oro. + + + Las monedas te dan más oro. + + + Te mueves más rápido. + + + Te mueves más rápido. + + + Probabilidad crítica + + + Aceleración aérea + + + Aceleración aérea + + + Bloqueo + + + Bloqueo + + + Flote + + + Flote + + + Puede atacar proyectiles. + + + Puede atacar proyectiles. + + + Vuelo + + + Vuelo + + + Velocidad de movimiento + + + Velocidad de movimiento + + + Nada + + + Nada + + + Probabilidad crítica + + + Daño crítico + + + Daño crítico + + + Vampirismo + + + Vampirismo + + + Bonificación de oro + + + Bonificación de oro + + + Sifón + + + Sifón + + + Bonificación de EXP + + + Bonificación de EXP + + + Ataque aéreo + + + Ataque aéreo + + + Salto aéreo + + + Salto aéreo + + + Devolución de daños + + + Devolución de daños + + + Botín incrementado en un {0} % + + + Botín incrementado en un {0} % + + + Los enemigos empiezan con {0} niveles más + + + Los enemigos empiezan con {0} niveles más + + + Los enemigos aumentan de nivel {0} unidades más despacio + + + Los enemigos aumentan de nivel {0} unidades más despacio + + + Los enemigos aumentan de nivel {0} unidad más despacio + + + Los enemigos aumentan de nivel {0} unidad más despacio + + + Haz {0} saltos aéreos + + + Haz {0} saltos aéreos + + + Haz {0} salto aéreo + + + Haz {0} salto aéreo + + + Acelera hasta {0} veces + + + Acelera hasta {0} veces + + + Acelera hasta {0} vez + + + Acelera hasta {0} vez + + + Recupera {0} PV por cada muerte + + + Recupera {0} PV por cada muerte + + + Vuela durante {0} segundos + + + Vuela durante {0} segundos + + + Vuela durante {0} segundo + + + Vuela durante {0} segundo + + + Recupera {0} PM por cada muerte + + + Recupera {0} PM por cada muerte + + + PV y maná + + + PV y maná + + + Devuelve un {0} % de daño tras ser alcanzado + + + Devuelve un {0} % de daño tras ser alcanzado + + + El oro que cae tiene un {0} % más de valor + + + El oro que cae tiene un {0} % más de valor + + + Te mueves un {0} % más rápido + + + Te mueves un {0} % más rápido + + + Salir de Rogue Legacy + + + Salir de Rogue Legacy + + + Pulsa [Input:0] para avanzar + + + Pulsa [Input:0] para avanzar + + + El sol... Había olvidado lo que era sentir su calor... + + + El sol... Había olvidado lo que era sentir su calor... + + + {1} ha asesinado a {0} + + + {1} ha asesinado a {0} + + + Pulsa [Input:0] para avanzar + + + Pulsa [Input:0] para avanzar + + + {1} ha asesinado a {0} + + + {1} ha asesinado a {0} + + + {1} ha asesinado a: {0} + + + {1} ha asesinado a: {0} + + + {0} ha sido víctima de un proyectil + + + {0} ha sido víctima de un proyectil + + + {0} se ha caído y le han atravesado el cuerpo unos pinchos + + + {0} se ha caído y le han atravesado el cuerpo unos pinchos + + + Han asesinado a {0} + + + Han asesinado a {0} + + + Palabras de despedida de {0} + + + Palabras de despedida de {0} + + + [Input:0] para continuar + + + [Input:0] para continuar + + + PV aumentados + + + PV aumentados + + + PM aumentados + + + PM aumentados + + + Fuerza aumentada + + + Fuerza aumentada + + + Daño mágico aumentado + + + Daño mágico aumentado + + + Coraza aumentada + + + Coraza aumentada + + + Carga de peso máxima aumentada + + + Carga de peso máxima aumentada + + + ¡Medallón completado! + + + ¡Medallón completado! + + + ¡Has conseguido un trozo del medallón! + + + ¡Has conseguido un trozo del medallón! + + + El bosque siempre está a la derecha del castillo. + + + Con las runas celestiales puedes volar pulsando [Input:10] cuando estés en el aire + + + Con las runas celestiales puedes volar pulsando [Input:10] cuando estés en el aire + + + Si se acumulan, el vampirismo y las runas sifón tienen mucho poder. + + + Si se acumulan, el vampirismo y las runas sifón tienen mucho poder. + + + Si dominas las runas de movimiento te vuelves impresionante. + + + Si dominas las runas de movimiento te vuelves impresionante. + + + Es importante que amplíes tu caserón; nunca se sabe qué habilidades podrían aparecer. + + + Es importante que amplíes tu caserón; nunca se sabe qué habilidades podrían aparecer. + + + Todas las clases se pueden mejorar con habilidades exclusivas de cada una. + + + Todas las clases se pueden mejorar con habilidades exclusivas de cada una. + + + Las habilidades desbloqueadas de cada clase se pueden activar con [Input:13] + + + Las habilidades desbloqueadas de cada clase se pueden activar con [Input:13] + + + Mejora pronto tus clases y consigue poderosas habilidades de clase. + + + Mejora pronto tus clases y consigue poderosas habilidades de clase. + + + Si tienes problemas con una sala, intenta evitar pasar por ella. + + + Si tienes problemas con una sala, intenta evitar pasar por ella. + + + La manera más rápida de hacer subir tus estadísticas es comprar equipamiento. + + + La manera más rápida de hacer subir tus estadísticas es comprar equipamiento. + + + Comprar equipamiento es mejor que aumentar tus estadísticas básicas. + + + Comprar equipamiento es mejor que aumentar tus estadísticas básicas. + + + El bosque siempre está a la derecha del castillo. + + + La Maya siempre está en la parte de arriba del castillo. + + + Deberías haber elegido al otro hijo. + + + Deberías haber elegido al otro hijo. + + + Las runas son muy poderosas. ¡Añádelas a la encantadora y úsalas! + + + Las runas son muy poderosas. ¡Añádelas a la encantadora y úsalas! + + + Aprende los matices de tu hechizo para maximizar su potencial. + + + Aprende los matices de tu hechizo para maximizar su potencial. + + + Dales a los enemigos cerca del ápice del arco del hacha para impactar varias veces. + + + Dales a los enemigos cerca del ápice del arco del hacha para impactar varias veces. + + + No recojas las esferas de conflux después de lanzarlas para maximizar el daño. + + + No recojas las esferas de conflux después de lanzarlas para maximizar el daño. + + + Esquiva la trayectoria de regreso de los chakrams para maximizar el daño. + + + Esquiva la trayectoria de regreso de los chakrams para maximizar el daño. + + + Es mejor usar maná para matar enemigos que recibir daños innecesarios. + + + Es mejor usar maná para matar enemigos que recibir daños innecesarios. + + + Para sobrevivir en el castillo, aprende el «lenguaje corporal» de los enemigos. + + + Para sobrevivir en el castillo, aprende el «lenguaje corporal» de los enemigos. + + + Los clavocepos comprueban el pulso para distinguir a los vivos de los muertos. + + + Los clavocepos comprueban el pulso para distinguir a los vivos de los muertos. + + + Pulsa [Input:9] para abrir el mapa + + + Pulsa [Input:9] para abrir el mapa + + + La Maya siempre está en la parte de arriba del castillo. + + + Las Tinieblas siempre están en la parte de abajo del castillo. + + + Los cofres enigmáticos contienen todas las runas del juego. Las runas te ayudarán un montón. + + + Los cofres enigmáticos contienen todas las runas del juego. Las runas te ayudarán un montón. + + + Si fracasas con un cofre enigmático, el arquitecto te puede dar otra oportunidad. + + + Si fracasas con un cofre enigmático, el arquitecto te puede dar otra oportunidad. + + + Si contratas los servicios del arquitecto, tendrás que pagarle su tarifa. + + + Si contratas los servicios del arquitecto, tendrás que pagarle su tarifa. + + + Al morir, los jefes sueltan grandes cantidades de oro. + + + Al morir, los jefes sueltan grandes cantidades de oro. + + + Entiérrame con mi dinero. + + + Entiérrame con mi dinero. + + + Si tienes problemas, prueba a equiparte runas de gracia. + + + Si tienes problemas, prueba a equiparte runas de gracia. + + + Activa en las opciones la caída rápida para lanzar ataques descendentes y dejarte caer pulsando [Input:18] + + + Activa en las opciones la caída rápida para lanzar ataques descendentes y dejarte caer pulsando [Input:18] + + + El arquitecto es muy útil para practicar contra los jefes. + + + El arquitecto es muy útil para practicar contra los jefes. + + + La tercera fila de equipamiento suele tener efectos secundarios. Ten cuidado. + + + La tercera fila de equipamiento suele tener efectos secundarios. Ten cuidado. + + + Algunas runas funcionan mejor con determinados jefes. + + + Algunas runas funcionan mejor con determinados jefes. + + + Las Tinieblas siempre están en la parte de abajo del castillo. + + + Si tienes problemas con un jefe, prueba a utilizar diferentes runas. + + + Deberías practicar el combate contra los jefes utilizando el arquitecto. + + + Deberías practicar el combate contra los jefes utilizando el arquitecto. + + + Es muy importante mejorar la estadística de salud. + + + Es muy importante mejorar la estadística de salud. + + + Las runas de retribución pueden dañar objetos invulnerables. + + + Las runas de retribución pueden dañar objetos invulnerables. + + + Si se usan correctamente, las habilidades de clase pueden ser muy poderosas. + + + Si se usan correctamente, las habilidades de clase pueden ser muy poderosas. + + + Algunas clases tienen ventaja sobre determinados jefes. + + + Algunas clases tienen ventaja sobre determinados jefes. + + + Si tienes problemas con un jefe, prueba a utilizar diferentes runas. + + + Las runas cripta te permiten saltar pulsando [Input:10] + + + Las runas cripta te permiten saltar pulsando [Input:10] + + + Las runas de aceleración te permiten acelerar pulsando [Input:PLAYER_DASHLEFT] o [Input:PLAYER_DASHRIGHT]. + + + Las runas de aceleración te permiten acelerar pulsando [Input:PLAYER_DASHLEFT] o [Input:PLAYER_DASHRIGHT]. + + + Cada clase tiene ventajas y desventajas. Asegúrate de adaptar tu estilo de juego. + + + Cada clase tiene ventajas y desventajas. Asegúrate de adaptar tu estilo de juego. + + + La mejor manera de conseguir oro es encontrar cofres. + + + La mejor manera de conseguir oro es encontrar cofres. + + + En las zonas más difíciles se consiguen mejores premios. + + + En las zonas más difíciles se consiguen mejores premios. + + + Tengo una obligación para con mi familia... + + + Tengo una obligación para con mi familia... + + + ... pero solo soy fiel a mi persona. + + + ... pero solo soy fiel a mi persona. + + + moneda(s) + + + moneda(s) + + + PV recuperados + + + PV recuperados + + + PM recuperados + + + PM recuperados + + + Mejora de coraza + + + Mejora de coraza + + + Mejora de salud máxima + + + Mejora de salud máxima + + + Mejora de maná máximo + + + Mejora de maná máximo + + + Mejora de ataque + + + Mejora de ataque + + + Mejora de magia + + + Mejora de magia + + + Mejora de peso máximo + + + Mejora de peso máximo + + + Estás reproduciendo + + + Estás reproduciendo + + + Estás entrando + + + Estás entrando + + + Objetivo: + + + Objetivo: + + + Alcanza el cofre en 15 segundos: + + + Alcanza el cofre en 15 segundos: + + + Tiempo disponible: + + + Tiempo disponible: + + + ¡Objetivo cumplido! + + + ¡Objetivo cumplido! + + + Objetivo no cumplido + + + Objetivo no cumplido + + + Sin rasgos + + + {0} heroico + + + {0} heroica + + + {0} divino + + + {0} divina + + + Noble {0} {1} + + + Noble {0} {1} + + + Héroe noble + + + Héroe noble + + + Dama {0} {1} + + + Dama {0} {1} + + + Dama heroína + + + Dama heroína + + + Sin rasgos + + + the + + + the + + + {0} legendario + + + {0} legendaria + + + {0} inútil + + + {0} inútil + + + {0} débil + + + {0} débil + + + {0} decidido + + + {0} decidida + + + {0} vigoroso + + + {0} vigorosa + + + {0} galante + + + {0} galante + + + {0} valiente + + + {0} valiente + + + [Input:0] para seleccionar a un descendiente + + + [Input:0] para seleccionar a un descendiente + + + [Button:LeftStick] para ver el árbol genealógico + + + [Button:LeftStick] para ver el árbol genealógico + + + Teclas de flecha para ver el árbol genealógico. + + + Teclas de flecha para ver el árbol genealógico. + + + [Input:9] para reelegir a tu descendiente una vez + + + [Input:9] para reelegir a tu descendiente una vez + + + Clase + + + Clase + + + Rasgo + + + Rasgo + + + Rasgos: ninguno + + + Rasgos: ninguno + + + Hechizo + + + Hechizo + + + Construyendo + + + Construyendo + + + Perdiendo el pelo + + + Perdiendo el pelo + + + Recordando + + + Recordando + + + Conectando + + + Conectando + + + Cofre abierto + + + Cofre abierto + + + Teletransporte + + + Teletransporte + + + Sala especial + + + Sala especial + + + [Input:9] para cerrar el mapa + + + [Input:9] para cerrar el mapa + + + [Input:0] para centrarte en el jugador + + + [Input:0] para centrarte en el jugador + + + Usa las teclas de flecha para mover el mapa. + + + Usa las teclas de flecha para mover el mapa. + + + [Button:LeftStick] para mover el mapa + + + [Button:LeftStick] para mover el mapa + + + Leyenda + + + Leyenda + + + Estás aquí + + + Estás aquí + + + Ubicación del jefe + + + Ubicación del jefe + + + Cofre sin abrir + + + Cofre sin abrir + + + Cofre enigmático + + + Cofre enigmático + + + Volumen de la música + + + Volumen de la música + + + 汉语 + + + 汉语 + + + English + + + English + + + Français + + + Français + + + Deutsch + + + Deutsch + + + Polska + + + Polska + + + Português (Brasil) + + + Português (Brasil) + + + Русский + + + Русский + + + Castellano + + + Castellano + + + Idioma + + + Idioma + + + * La caída rápida te permite bajar desde los salientes y lanzar ataques \ndescendientes en el aire pulsando el botón hacia ABAJO. + + + Resolución + + + Resolución + + + Pantalla completa + + + Pantalla completa + + + Reducir calidad de sombreado + + + Reducir calidad de sombreado + + + Usar mandos con Dinput + + + Usar mandos con Dinput + + + Activar nube de Steam + + + Activar nube de Steam + + + * La caída rápida te permite bajar desde los salientes y lanzar ataques \ndescendientes en el aire pulsando el botón hacia ABAJO. + + + [Button:LeftStick] para desplazarte por las opciones + + + [Button:LeftStick] para desplazarte por las opciones + + + Teclas de flecha para desplazarte por las opciones. + + + Teclas de flecha para desplazarte por las opciones. + + + [Input:0] para seleccionar una opción + + + [Input:0] para seleccionar una opción + + + [Input:2] para salir de las opciones + + + [Input:2] para salir de las opciones + + + * El juego tiene que reiniciarse para que se haga efectivo el cambio. + + + * El juego tiene que reiniciarse para que se haga efectivo el cambio. + + + * Se debe activar la compatibilidad con la nube también en la plataforma de Steam\npara habilitar esta función. + + + * Se debe activar la compatibilidad con la nube también en la plataforma de Steam\npara habilitar esta función. + + + Clase: + + + Clase: + + + Fuerza: + + + Fuerza: + + + Magia: + + + Magia: + + + Coraza: + + + Coraza: + + + Nivel: + + + Nivel: + + + Salud: + + + Salud: + + + Mando Inalámbrico Xbox One desconectado, vuelve a conectarlo. + + + Mando Inalámbrico Xbox One desconectado, vuelve a conectarlo. + + + ????? + + + ????? + + + moneda(s) + + + moneda(s) + + + PM máx. + + + PM máx. + + + PV máx. + + + PV máx. + + + PM máx. convertidos. Se necesita un nivel más alto. + + + PM máx. convertidos. Se necesita un nivel más alto. + + + Salud + + + Encantamientos + + + Encantamientos + + + [Input:2] para salir + + + [Input:2] para salir + + + Lv. + + + Lv. + + + Salud + + + Maná + + + Maná + + + Coraza + + + Coraza + + + Peso + + + Peso + + + Fuerza + + + Fuerza + + + Inteligencia + + + Inteligencia + + + Prob. crítica + + + Prob. crítica + + + Daño crítico + + + Daño crítico + + + Equipamiento + + + Equipamiento + + + Estadísticas básicas al 100 %. + + + ESPECIAL: grito bárbaro.\nGran cantidad de PV. Bajo nivel de Frz. y PM. + + + ESPECIAL: grito bárbaro.\nGran cantidad de PV. Bajo nivel de Frz. y PM. + + + Gran cantidad de Frz., pero sin ataques críticos.\n+{0} % de velocidad de movimiento. Bajo nivel de PV y PM. + + + Gran cantidad de Frz., pero sin ataques críticos.\n+{0} % de velocidad de movimiento. Bajo nivel de PV y PM. + + + ESPECIAL: técnica de sustitución.\nGran cantidad de Frz., pero sin ataques críticos.\n+{0} % de velocidad de movimiento. Bajo nivel de PV y PM. + + + ESPECIAL: técnica de sustitución.\nGran cantidad de Frz., pero sin ataques críticos.\n+{0} % de velocidad de movimiento. Bajo nivel de PV y PM. + + + El {0} % de los daños provocados se convierte en maná.\nBajo nivel de Frz., PV y PM. + + + El {0} % de los daños provocados se convierte en maná.\nBajo nivel de Frz., PV y PM. + + + ESPECIAL: hechizo potenciado.\nEl {0} % de los daños provocados se convierte en maná.\nBajo nivel de Frz., PV y PM. + + + ESPECIAL: hechizo potenciado.\nEl {0} % de los daños provocados se convierte en maná.\nBajo nivel de Frz., PV y PM. + + + Las muertes se convierten en PV máximos.\nNivel muy bajo de Frz., PV y PM. Alto nivel de Int. + + + Las muertes se convierten en PV máximos.\nNivel muy bajo de Frz., PV y PM. Alto nivel de Int. + + + ESPECIAL: conversión de PV.\nLas muertes se convierten en PV máximos.\nNivel muy bajo de Frz., PV y PM. Alto nivel de Int. + + + ESPECIAL: conversión de PV.\nLas muertes se convierten en PV máximos.\nNivel muy bajo de Frz., PV y PM. Alto nivel de Int. + + + Eres un hombre-dragón. + + + Eres una mujer-dragón. + + + ????? + + + ????? + + + Estadísticas básicas al 100 %. + + + ESPECIAL: escudo de guardián.\nEstadísticas básicas al 100 %. + + + ESPECIAL: escudo de guardián.\nEstadísticas básicas al 100 %. + + + +{0} % de prob. crít., +{1} % de daño crít.\nNivel bajo de PV, PM, y Frz. + + + +{0} % de prob. crít., +{1} % de daño crít.\nNivel bajo de PV, PM, y Frz. + + + ESPECIAL: forma de neblina.\n+{0} % de prob. crít., +{1} % de daño crít.\nNivel bajo de PV, PM, y Frz. + + + ESPECIAL: forma de neblina.\n+{0} % de prob. crít., +{1} % de daño crít.\nNivel bajo de PV, PM, y Frz. + + + +{0} % de ganancia de oro.\nMuy débil en otras estadísticas. + + + +{0} % de ganancia de oro.\nMuy débil en otras estadísticas. + + + ESPECIAL: linterna de cabeza.\n+{0} % de ganancia de oro.\nMuy débil en otras estadísticas. + + + ESPECIAL: linterna de cabeza.\n+{0} % de ganancia de oro.\nMuy débil en otras estadísticas. + + + Cada vez que mata, recibes {0} de maná.\nBajo nivel de Frz. y PV. y PV. Alto nivel de Int. y PM. + + + Cada vez que mata, recibes {0} de maná.\nBajo nivel de Frz. y PV. y PV. Alto nivel de Int. y PM. + + + ESPECIAL: ciclo de hechizo.\nCada vez que mata, recibes {0} de maná.\nBajo nivel de Frz. y PV. y PV. Alto nivel de Int. y PM. + + + ESPECIAL: ciclo de hechizo.\nCada vez que mata, recibes {0} de maná.\nBajo nivel de Frz. y PV. y PV. Alto nivel de Int. y PM. + + + Gran cantidad de PV. Bajo nivel de Frz. y PM. + + + Gran cantidad de PV. Bajo nivel de Frz. y PM. + + + - COMENZAR NUEVO LEGADO - + + + NP+ + + + NP+ + + + - COMENZAR NUEVO LEGADO - + + + [Button:LeftStick] para desplazarte + + + [Button:LeftStick] para desplazarte + + + Teclas de flecha para desplazarte por los perfiles + + + Teclas de flecha para desplazarte por los perfiles + + + [Input:0] para seleccionar + + + [Input:0] para seleccionar + + + [Input:2] para salir + + + [Input:2] para salir + + + [Input:26] para eliminar + + + [Input:26] para eliminar + + + {0} la {1} + + + {0} la {1} + + + {0} el {1} + + + {0} el {1} + + + {0} la Difunta + + + {0} la Difunta + + + {0} el Difunto + + + {0} el Difunto + + + Lvl. + + + Lvl. + + + Activar caída rápida + + + Activar caída rápida + + + No + + + No + + + + + + + + + Volumen de efectos + + + Volumen de efectos + + + Mejora tu trabajo cardiovascular. Si tu corazón está sano, tendrás más salud. + + + Desbloquea la forja y accede a botines fabulosos. + + + Desbloquea la forja y accede a botines fabulosos. + + + Desbloquea a la encantadora para tener acceso a sus runas y poderes mágicos. + + + Desbloquea a la encantadora para tener acceso a sus runas y poderes mágicos. + + + Desbloquea al arquitecto y consigue el poder de bloquear el castillo. + + + Desbloquea al arquitecto y consigue el poder de bloquear el castillo. + + + Si mejoras tu capacidad de carga podrás llevar piezas de armadura mejores y más pesadas. + + + Si mejoras tu capacidad de carga podrás llevar piezas de armadura mejores y más pesadas. + + + Fortalece tus entrañas siguiendo procesos naturales para reducir los daños recibidos. + + + Fortalece tus entrañas siguiendo procesos naturales para reducir los daños recibidos. + + + Mejora tus habilidades de saqueo y sácale mejor partido a tu parné. + + + Mejora tus habilidades de saqueo y sácale mejor partido a tu parné. + + + Reduce el peaje de Charon aprendiendo cómo regatear con la mismísima muerte. + + + Reduce el peaje de Charon aprendiendo cómo regatear con la mismísima muerte. + + + La limpieza de entrañas mejora considerablemente tanto con las pociones como con la carne. + + + La limpieza de entrañas mejora considerablemente tanto con las pociones como con la carne. + + + Utiliza el poder de la ciencia para fabricar un nuevo lote de bebés. No hagas preguntas... + + + Utiliza el poder de la ciencia para fabricar un nuevo lote de bebés. No hagas preguntas... + + + ¡Libera el poder del lich! Es un ser dotado de un enorme potencial. + + + ¡Libera el poder del lich! Es un ser dotado de un enorme potencial. + + + Mejora tu trabajo cardiovascular. Si tu corazón está sano, tendrás más salud. + + + Fortalece tus glándulas adrenales y vuélvete tan invencible como Bane. ¡Que empiecen los juegos! + + + Desbloquea las habilidades del minero y aumenta tu fortuna familiar. + + + Desbloquea las habilidades de la minera y aumenta tu fortuna familiar. + + + Desbloquea al ladrón de hechizos y conviértete en un mago marcial. + + + Desbloquea a la ladrona de hechizos y conviértete en una maga marcial. + + + Desbloquea al shinobi, el más veloz de todos los luchadores. + + + Desbloquea a la shinobi, la más veloz de todas las luchadoras. + + + Practica tus habilidades básicas para reducir el consumo de maná al lanzar hechizos. + + + Practica tus habilidades básicas para reducir el consumo de maná al lanzar hechizos. + + + Convierte a tus caballeros en paladines, feroces combatientes de primera línea. + + + Convierte a tus caballeras en paladines, feroces combatientes de primera línea. + + + Desbloquea los poderes latentes del mago y transfórmalo en el poderoso archimago. + + + Desbloquea los poderes latentes de la maga y transfórmala en la poderosa archimaga. + + + Aprende las artes oscuras y transforma al granuja en asesino. + + + Aprende las artes oscuras y transforma a la granuja en asesina. + + + Licénciate en Geología y asciende de minero a espeleólogo. Canela fina. + + + Licénciate en Geología y asciende de minera a espeleóloga. Canela fina. + + + Conviértete en rey bárbaro. El rey de los hombres libres. Eso no tiene sentido alguno. + + + Conviértete en reina bárbara. La reina de los hombres libres. Eso no tiene sentido alguno. + + + Introduce a tus liches en la realeza y transfórmalos en reyes lich. + + + Introduce a tus liches en la realeza y transfórmalos en reinas lich. + + + Fortalece tus glándulas adrenales y vuélvete tan invencible como Bane. ¡Que empiecen los juegos! + + + Saca el gato que llevas dentro y evita la muerte. A veces. + + + Conviértete en el líder de tu pueblo y transforma a tu shinobi en hokage. ¡Verlo para creerlo! + + + Conviértete en la líder de tu pueblo y transforma a tu shinobi en hokage. ¡Verlo para creerlo! + + + Monta en los vórtices de la magia y transforma a tus ladrones de hechizos en espadachines hechiceros. + + + Monta en los vórtices de la magia y transforma a tus ladronas de hechizos en espadachinas hechiceras. + + + Medio hombre y medio ******, impresionante de pies a cabeza. + + + Medio mujer y medio ******, impresionante de pies a cabeza. + + + ALIENTO RÁPIDO \nRespiras profundamente. No es muy útil si quieres seguir a alguien, ¡pero sí para caminar! \n\nAumenta la regeneración de tu resistencia natural. + + + ALIENTO RÁPIDO \nRespiras profundamente. No es muy útil si quieres seguir a alguien, ¡pero sí para caminar! \n\nAumenta la regeneración de tu resistencia natural. + + + De pequeño te pusieron sangre de tigre. Ahora tienes el poder de sangrar como un tigre cuando te apuñalan. \nAl correr consumes menos resistencia. + + + De pequeña te pusieron sangre de tigre. Ahora tienes el poder de sangrar como un tigre cuando te apuñalan. \nAl correr consumes menos resistencia. + + + Tienes ascendencia vikinga. \n\nAumenta tu resistencia inicial. + + + Tienes ascendencia vikinga. \n\nAumenta tu resistencia inicial. + + + Eres un madrugador, si subir de nivel fuera como madrugar.\n Consigue bonificaciones de PV y PM cada vez que subes de nivel. + + + Eres una madrugadora, si subir de nivel fuera como madrugar.\n Consigue bonificaciones de PV y PM cada vez que subes de nivel. + + + Naciste con un poder absoluto en la punta de los dedos. \nTodos los hechizos provocan más daños. + + + Naciste con un poder absoluto en la punta de los dedos. \nTodos los hechizos provocan más daños. + + + Naciste con la energía arcana corriendo por tus venas. Impresionante. \nTe cuesta menos lanzar hechizos. + + + Naciste con la energía arcana corriendo por tus venas. Impresionante. \nTe cuesta menos lanzar hechizos. + + + Por fin, la obsesión compulsiva resulta útil. \nConsigue más oro. + + + Por fin, la obsesión compulsiva resulta útil. \nConsigue más oro. + + + Saca el gato que llevas dentro y evita la muerte. A veces. + + + En un gimnasio decente podrás fortalecer tus brazos y los músculos del trasero. + + + Por disposición legal, eres el mejor de los hombres. \nEngendra más herederos. + + + Por disposición legal, eres la mejor de las mujeres. \nEngendra más herederos. + + + Tus padres te dijeron que a un granjero no le servía de nada aprender a cribar oro. ¡Ah, pero el que ríe el último ríe mejor! \nMuestra las salas con tesoros al principio de la partida. + + + Tus padres te dijeron que a una granjera no le servía de nada aprender a cribar oro. ¡Ah, pero el que ríe el último ríe mejor! \nMuestra las salas con tesoros al principio de la partida. + + + La guerra es un infierno. Por suerte, tú nunca has vivido ninguna. \n Dispara más morteros. + + + La guerra es un infierno. Por suerte, tú nunca has vivido ninguna. \n Dispara más morteros. + + + De niño, mostraste cierto interés por la piromanía. \n Las bombas tienen mayor radio de alcance. + + + De niña, mostraste cierto interés por la piromanía. \n Las bombas tienen mayor radio de alcance. + + + Tu bisabuelo era un muñeco de nieve. No te enseñó nada de nada. \n Los carámbanos atraviesan más enemigos. + + + Tu bisabuelo era un muñeco de nieve. No te enseñó nada de nada. \n Los carámbanos atraviesan más enemigos. + + + Eres muy zen. \n Recupera resistencia más rápido cuando no estás en movimiento. + + + Eres muy zen. \n Recupera resistencia más rápido cuando no estás en movimiento. + + + HABILIDAD genérica. Aumenta la resistencia total. + + + HABILIDAD genérica. Aumenta la resistencia total. + + + Luchas con elegancia. \n Los ataques consumen un X % menos de resistencia. + + + Luchas con elegancia. \n Los ataques consumen un X % menos de resistencia. + + + HABILIDAD genérica. Aumenta la salud + + + HABILIDAD genérica. Aumenta la salud + + + Chúpate esa... sangre. \n Restablece una pequeña cantidad de vida con cada impacto. + + + Chúpate esa... sangre. \n Restablece una pequeña cantidad de vida con cada impacto. + + + En un gimnasio decente podrás fortalecer tus brazos y los músculos del trasero. + + + Contar con una sala para practicar pogo tiene sus ventajas. Inflige más daños con ataques descendentes consecutivos. + + + Resucitas, como Jesús... pero no eres Jesús. \n Revive una vez después de morir. + + + Resucitas, como Jesús... pero no eres Jesús. \n Revive una vez después de morir. + + + Vaciar una sala es como vaciar tu mente. No sé muy bien por qué. \nRecupera salud por cada sala que vacíes completamente. + + + Vaciar una sala es como vaciar tu mente. No sé muy bien por qué. \nRecupera salud por cada sala que vacíes completamente. + + + Cartografía /n Cada porcentaje del mapa desvelado añade un 0,1 de daño. + + + Cartografía /n Cada porcentaje del mapa desvelado añade un 0,1 de daño. + + + HABILIDAD genérica. Aumenta los daños del ataque. + + + HABILIDAD genérica. Aumenta los daños del ataque. + + + Se te da fatal perder, eres terrible. \n Al morir, inflige daños muy graves a todos los enemigos en pantalla. + + + Se te da fatal perder, eres terrible. \n Al morir, inflige daños muy graves a todos los enemigos en pantalla. + + + Has aprendido que al golpear las bolas infliges daños impresionantes. \n Los crít. infligen más daño. + + + Has aprendido que al golpear las bolas infliges daños impresionantes. \n Los crít. infligen más daño. + + + HABILIDAD GENÉRICA. + + + HABILIDAD GENÉRICA. + + + Oh. Las llevaba en el bolsillo de atrás. \nGana dos llaves extra. + + + Oh. Las llevaba en el bolsillo de atrás. \nGana dos llaves extra. + + + Como un fénix, renaces de tus cenizas de mierda. \n Recupera todos los PV y PM. + + + Como un fénix, renaces de tus cenizas de mierda. \n Recupera todos los PV y PM. + + + Retírate e invierte bien tu dinero. Termina la partida antes de hora y consigue una bonificación por el oro encontrado. + + + Retírate e invierte bien tu dinero. Termina la partida antes de hora y consigue una bonificación por el oro encontrado. + + + Contar con una sala para practicar pogo tiene sus ventajas. Inflige más daños con ataques descendentes consecutivos. + + + Si aprendes las debilidades de los enemigos podrás atacarlos con una eficacia letal. + + + ¡GLUP GLUP GLUP! \n Bebe pociones al instante. + + + ¡GLUP GLUP GLUP! \n Bebe pociones al instante. + + + Si aprendes las debilidades de los enemigos podrás atacarlos con una eficacia letal. + + + Practica los ataques letales para resultar aún más mortal. Los enemigos se irán a criar malvas. + + + Practica los ataques letales para resultar aún más mortal. Los enemigos se irán a criar malvas. + + + Aprende los secretos del universo y aprovéchalos para matar mejor con tus hechizos. + + + Aprende los secretos del universo y aprovéchalos para matar mejor con tus hechizos. + + + Mejora tu fortaleza mental para aumentar tu reserva de maná. + + + Mejora tu fortaleza mental para aumentar tu reserva de maná. + + + Pulsa [Input:9] para que tu descendencia sea aleatoria + + + Pulsa [Input:9] para que tu descendencia sea aleatoria + + + Pulsa [Input:13] para bloquear todos los daños dirigidos hacia ti + + + Pulsa [Input:13] para bloquear todos los daños dirigidos hacia ti + + + Pulsa [Input:13] para cambiar hechizos + + + Pulsa [Input:13] para cambiar hechizos + + + Pulsa [Input:13] para convertirte en neblina + + + Pulsa [Input:13] para convertirte en neblina + + + Pulsa [Input:13] para encender la linterna de tu cabeza + + + Pulsa [Input:13] para encender la linterna de tu cabeza + + + Pulsa [Input:13] para lanzar un grito épico que prácticamente lo derribe todo + + + Pulsa [Input:13] para lanzar un grito épico que prácticamente lo derribe todo + + + Pulsa [Input:13] para convertir los PV máximos en PM máximos + + + Pulsa [Input:13] para convertir los PV máximos en PM máximos + + + Pulsa [Input:13] para teletransportarte + + + Pulsa [Input:13] para teletransportarte + + + Pulsa [Input:13] para lanzar hechizos potenciados + + + Pulsa [Input:13] para lanzar hechizos potenciados + + + Pulsa [Input:10] para volverte impresionante + + + Pulsa [Input:10] para volverte impresionante + + + + + + + + + Mejora de salud + + + Forja + + + Forja + + + Encantadora + + + Encantadora + + + Arquitecto + + + Arquitecto + + + Mejora equipamiento + + + Mejora equipamiento + + + Mejora de coraza + + + Mejora de coraza + + + Mejora de botín + + + Mejora de botín + + + Regateo + + + Regateo + + + Mejora de poción + + + Mejora de poción + + + Herederos aleatorios + + + Herederas aleatorias + + + Desbloquear lich + + + Desbloquear lich + + + Mejora de salud + + + Mejora invulnerab. + + + Desbloquear minero + + + Desbloquear minera + + + Desb. ladrón hechizos + + + Desb. ladrona hechizos + + + Desbloquear shinobi + + + Desbloquear shinobi + + + Reducción de maná + + + Reducción de maná + + + Mejora de caballero + + + Mejora de caballera + + + Mejora de mago + + + Mejora de maga + + + Mejora de granuja + + + Mejora de granuja + + + Mejora de minero + + + Mejora de minera + + + Mejora de bárbaro + + + Mejora de bárbara + + + Mejora de lich + + + Mejora de lich + + + Mejora invulnerab. + + + Desafío a la muerte + + + Mejora de shinobi + + + Mejora de shinobi + + + Mej. ladrón hechizos + + + Mej. ladrona hechizos + + + Bestialidad + + + Bestialidad + + + Aliento rápido + + + Aliento rápido + + + Nacido para correr + + + Nacida para correr + + + Corazón vigoroso + + + Corazón vigoroso + + + Madrugador + + + Madrugadora + + + Espadachín hechicero + + + Espadachina hechicera + + + Hechicero + + + Hechicera + + + Perfeccionista + + + Perfeccionista + + + Desafío a la muerte + + + Mejora de ataque + + + Dotado + + + Dotada + + + Buscatesoros + + + Buscatesoros + + + Maestro del mortero + + + Maestra del mortero + + + Artillero + + + Artillera + + + Carámbano + + + Carámbano + + + Gurú + + + Gurú + + + Pulmón de hierro + + + Pulmón de hierro + + + Maestro de la espada + + + Maestra de la espada + + + Tanque + + + Tanque + + + Vampiro + + + Vampira + + + Mejora de ataque + + + Mejora golpe abajo + + + Segunda oportunidad + + + Segunda oportunidad + + + Buena conciencia + + + Buena conciencia + + + Cartografía ninja + + + Cartografía ninja + + + Fortachón + + + Fortachona + + + Suicida + + + Suicida + + + Bárbaro crít. + + + Bárbara crít. + + + Brujería + + + Brujería + + + Amo de llaves + + + Ama de llaves + + + Solo una vez + + + Solo una vez + + + Jubilación anticipada + + + Jubilación anticipada + + + Mejora golpe abajo + + + Mejora de prob. crít. + + + Bebedor + + + Bebedora + + + Mejora de prob. crít. + + + Mejora de daño crít. + + + Mejora de daño crít. + + + Mejora daño mágico + + + Mejora daño mágico + + + Mejora de maná + + + Mejora de maná + + + {0} monedas para {1} + + + {0} monedas para {1} + + + desbloq. + + + desbloq. + + + mejorar + + + mejorar + + + peso + + + peso + + + PV + + + PV + + + PM + + + PM + + + Frz + + + Frz + + + Int + + + Int + + + PV/PM + + + PV/PM + + + Máx. + + + Máx. + + + [Input:0] para comprar/mejorar un rasgo + + + [Input:0] para comprar/mejorar un rasgo + + + Coraza + + + Coraza + + + seg. + + + seg. + + + [Input:9] para desactivar iconos + + + [Input:9] para desactivar iconos + + + [Input:2] para salir del caserón + + + [Input:2] para salir del caserón + + + [Button:LeftStick] para navegar por las habilidades + + + [Button:LeftStick] para navegar por las habilidades + + + Teclas de flecha para navegar por las habilidades + + + Teclas de flecha para navegar por las habilidades + + + [Input:9] para activar los iconos + + + [Input:9] para activar los iconos + + + Actual + + + Actual + + + Mejora + + + Mejora + + + Nivel + + + Nivel + + + El herrero puede fabricar el mejor equipo del mundo para que te conviertas en un auténtico vaporizador virtuoso de violentos villanos.\nSi reúnes planos, pondrá a tu disposición una selección aún más amplia de armamentos selectos para la armería. + + + ¡Convierte a tus bárbaros en REYES bárbaros! Aprende los rugidos secretos de los osos y grítales a las cosas hasta hacerlas estallar. + + + ¡Convierte a tus bárbaros en REYES bárbaros! Aprende los rugidos secretos de los osos y grítales a las cosas hasta hacerlas estallar. + + + ¡Pasa de ser un mero shinobi a convertirte en un poderoso hokage! Domina el arte de hacerte el herido y, en el último minuto, convertirte en tronco. Es una suerte que lleves encima un montón de troncos. + + + ¡Pasa de ser una mera shinobi a convertirte en una poderosa hokage! Domina el arte de hacerte la herida y, en el último minuto, convertirte en tronco. Es una suerte que lleves encima un montón de troncos. + + + Entrena a tus granujas para transformarlos en asesinos hechos y derechos. Aprovecha el poder de las sombras para atravesar en secreto las filas enemigas. + + + Entrena a tus granujas para transformarlos en asesinos hechos y derechos. Aprovecha el poder de las sombras para atravesar en secreto las filas enemigas. + + + ¡Con tanto cavar, tus mineros se han convertido en espeleólogos! ¡A ver si esa elegante luz que llevas en la cabeza sirve para algo! (La verdad es que no...). + + + ¡Con tanto cavar, tus mineros se han convertido en espeleólogos! ¡A ver si esa elegante luz que llevas en la cabeza sirve para algo! (La verdad es que no...). + + + Convierte a tus ladrones de hechizos en espadachines hechiceros y disfruta del poder de los hechizos potenciados.\n¿A eso lo llamas un hacha? ESTO es un hacha. + + + Convierte a tus ladrones de hechizos en espadachines hechiceros y disfruta del poder de los hechizos potenciados.\n¿A eso lo llamas un hacha? ESTO es un hacha. + + + ¡Asciende a tus liches hasta convertirlos en reyes y domina los poderes de la mente Y la materia! Con solo pulsar una vez, puedes convertir tu salud permanente en maná permanente. + + + ¡Asciende a tus liches hasta convertirlos en reyes y domina los poderes de la mente Y la materia! Con solo pulsar una vez, puedes convertir tu salud permanente en maná permanente. + + + Has descubierto el arte perdido de los dragones. Aunque no puedas saltar, tienes una capacidad de vuelo ilimitada y puedes lanzarles a tus enemigos poderosas bolas de fuego. + + + Has descubierto el arte perdido de los dragones. Aunque no puedas saltar, tienes una capacidad de vuelo ilimitada y puedes lanzarles a tus enemigos poderosas bolas de fuego. + + + Has descubierto las artes ocultas conocidas únicamente por Johannes el traidor. ¡Todos se inclinarán ante tu poder! + + + Has descubierto las artes ocultas conocidas únicamente por Johannes el traidor. ¡Todos se inclinarán ante tu poder! + + + El herrero puede fabricar el mejor equipo del mundo para que te conviertas en un auténtico vaporizador virtuoso de violentos villanos.\nSi reúnes planos, pondrá a tu disposición una selección aún más amplia de armamentos selectos para la armería. + + + La encantadora puede llenar de poder tu cuerpo con runas mágicas, con lo que te hará mejor, más fuerte, más rápido y más saltarín.\nEncuentra runas para aumentar su repertorio de talentos de modificación corporal.\n\nTiene bola de cristal, pero es de pega. + + + La encantadora puede llenar de poder tu cuerpo con runas mágicas, con lo que te hará mejor, más fuerte, más rápida y más saltarina.\nEncuentra runas para aumentar su repertorio de talentos de modificación corporal.\n\nTiene bola de cristal, pero es de pega. + + + El arquitecto puede echarle el cerrojo a un castillo para evitar que cambie.\n\n¿Te gusta cómo está distribuido un castillo?\n¡PUES PÍDELE QUE LE ECHE EL CERROJO!\nPero asegúrate de poder permitirte su tarifa. + + + El arquitecto puede echarle el cerrojo a un castillo para evitar que cambie.\n\n¿Te gusta cómo está distribuido un castillo?\n¡PUES PÍDELE QUE LE ECHE EL CERROJO!\nPero asegúrate de poder permitirte su tarifa. + + + El shinobi: un guerrero superrápido y supermortal que lleva una cinta de superhéroe. No puede soportar muchos impactos, pero sabe repartir bien el dolor. ¡Verlo para creerlo! + + + El shinobi: un guerrero superrápido y supermortal que lleva una cinta de superhéroe. No puede soportar muchos impactos, pero sabe repartir bien el dolor. ¡Verlo para creerlo! + + + Más duchos en el arte de extraer ganancias que en el de matar enemigos. Lo mejor que se puede hacer con los mineros es rastrear el castillo en busca de cofres del tesoro evitando cualquier confrontación. + + + Más duchos en el arte de extraer ganancias que en el de matar enemigos. Lo mejor que se puede hacer con los mineros es rastrear el castillo en busca de cofres del tesoro evitando cualquier confrontación. + + + El ladrón de hechizos extrae maná de los enemigos a los que ataca, lo que le permite disfrutar de una reserva infinita de maná en el corazón del combate. ¡Imparable! + + + El ladrón de hechizos extrae maná de los enemigos a los que ataca, lo que le permite disfrutar de una reserva infinita de maná en el corazón del combate. ¡Imparable! + + + Señores de la vida y la muerte. El lich tiene un potencial descomunal. Cada vez que mata recibe salud permanente (con un límite máximo), por lo que es una criatura realmente peligrosa. + + + Señores de la vida y la muerte. El lich tiene un potencial descomunal. Cada vez que mata recibe salud permanente (con un límite máximo), por lo que es una criatura realmente peligrosa. + + + Asciende a tus caballeros a paladines. Tras un riguroso entrenamiento, los paladines han aprendido a bloquear ataques desde cualquier ángulo. + + + Asciende a tus caballeros a paladines. Tras un riguroso entrenamiento, los paladines han aprendido a bloquear ataques desde cualquier ángulo. + + + Transforma a tus simples magos en archimagos. Domina todas las artes arcanas y cambia al instante entre todos los hechizos que tengas. + + + Transforma a tus simples magos en archimagos. Domina todas las artes arcanas y cambia al instante entre todos los hechizos que tengas. + + + Anillo de Hyperión + + + Óbolo de Ponce de León + + + Óbolo de Ponce de León + + + Óbolo de Herodotus + + + Óbolo de Herodotus + + + Óbolo del traidor + + + Óbolo del traidor + + + Anillo de Hyperión + + + Botas de Hermes + + + Botas de Hermes + + + Maldición del erizo + + + Maldición del erizo + + + Óbolo de Charon + + + Óbolo de Charon + + + Brújula de Calipso + + + Brújula de Calipso + + + Bendición de Helios + + + Bendición de Helios + + + Gafas de empollón + + + Gafas de empollón + + + Óbolo de Khidr + + + Óbolo de Khidr + + + Óbolo de Alejandro + + + Óbolo de Alejandro + + + Lanza una daga directamente delante de ti. + + + Aparece en tu defensa una gran catana. + + + Aparece en tu defensa una gran catana. + + + Te rodea de un fuego protector. + + + Te rodea de un fuego protector. + + + Lanza esferas que rebotan por todas partes. + + + Lanza esferas que rebotan por todas partes. + + + Dispara un láser que hace estallar todo lo que toca. + + + Dispara un láser que hace estallar todo lo que toca. + + + Lanza bolas de fuego contra tus enemigos. + + + Lanza bolas de fuego contra tus enemigos. + + + Dispara una lluvia de dagas. + + + Dispara una lluvia de dagas. + + + Lanza una daga directamente delante de ti. + + + Lanza un hacha gigante en arco. + + + Lanza un hacha gigante en arco. + + + Produce una bomba que estalla pasado un rato. + + + Produce una bomba que estalla pasado un rato. + + + Activa la congelación de todos los enemigos en pantalla. + + + Activa la congelación de todos los enemigos en pantalla. + + + Impacta contra todos los enemigos en pantalla. Costosa. + + + Impacta contra todos los enemigos en pantalla. Costosa. + + + Suelta tu sombra y te permite teletransportarte hasta ella. + + + Suelta tu sombra y te permite teletransportarte hasta ella. + + + Lanza un marcador que te teletransporta. + + + Lanza un marcador que te teletransporta. + + + Lanza un chakram que vuelve a ti. + + + Lanza un chakram que vuelve a ti. + + + Lanza guadañas volando por encima de ti. + + + Lanza guadañas volando por encima de ti. + + + Daga + + + Espada muro + + + Espada muro + + + Barrera de fuego + + + Barrera de fuego + + + Conflux + + + Conflux + + + R.A.Y.O. + + + R.A.Y.O. + + + Fuego de dragón + + + Fuego de dragón + + + Daga rápida + + + Daga rápida + + + Daga + + + Hacha + + + Hacha + + + Bomba + + + Bomba + + + Detención del tiempo + + + Detención del tiempo + + + Tormenta de cuervos + + + Tormenta de cuervos + + + Teletransporte cuántico + + + Teletransporte cuántico + + + Traslación + + + Traslación + + + Chakram + + + Chakram + + + Guadaña + + + Guadaña + + + ... Cargando + + + ... Cargando + + + Herrero + + + Antes era una encantadora muy poderosa, pero un día los monstruos de este castillo invadieron mis sueños y me robaron todos mis conocimientos. + + + Sin sonido + + + Sin sonido + + + Cofre enigmático + + + Cofre enigmático + + + El suelo es lava. + + + El suelo es lava. + + + Booyan + + + Booyan + + + ¡Hola! ¿Te gustaría poner a prueba tu destreza?\n¡Solo tienes una oportunidad, pero es gratis! ¡Si lo consigues, te daré una recompensa muy jugosa! + + + ¡Hola! ¿Te gustaría poner a prueba tu destreza?\n¡Solo tienes una oportunidad, pero es gratis! ¡Si lo consigues, te daré una recompensa muy jugosa! + + + 10 dagas para destruir 8 objetivos. ¿Quieres intentarlo? + + + 10 dagas para destruir 8 objetivos. ¿Quieres intentarlo? + + + Booyan + + + Booyan + + + Vale, ya te has divertido un poco. ¡Para ya! + + + Vale, ya te has divertido un poco. ¡Para ya! + + + Booyan + + + Booyan + + + Antes era una encantadora muy poderosa, pero un día los monstruos de este castillo invadieron mis sueños y me robaron todos mis conocimientos. + + + Los metieron en runas y, sin esas runas, no puedo hacer mi trabajo como dios manda. + + + No había visto tanta bebida junta desde mi última visita a la taberna (ayer). ¡Tengo un premio para ti por haber destruido todos los objetivos! + + + No había visto tanta bebida junta desde mi última visita a la taberna (ayer). ¡Tengo un premio para ti por haber destruido todos los objetivos! + + + Booyan + + + Booyan + + + ¿Ni siquiera les has podido dar a 8 objetivos?\nUf... Suerte con el resto del castillo. + + + ¿Ni siquiera les has podido dar a 8 objetivos?\nUf... Suerte con el resto del castillo. + + + Booyan + + + Booyan + + + ¡Hola! Vamos a ver lo hábil que eres.\n¡Solo tienes una oportunidad, pero es gratis! ¡Si lo consigues, te daré una recompensa muy jugosa! + + + ¡Hola! Vamos a ver lo hábil que eres.\n¡Solo tienes una oportunidad, pero es gratis! ¡Si lo consigues, te daré una recompensa muy jugosa! + + + Tienes 5 hachas para destruir todos los objetivos que puedas. Si dejas menos de 10 en pie, te daré una recompensa especial. ¿Quieres intentarlo? + + + Tienes 5 hachas para destruir todos los objetivos que puedas. Si dejas menos de 10 en pie, te daré una recompensa especial. ¿Quieres intentarlo? + + + Booyan + + + Booyan + + + ¡Fabuloso! ¡Has conseguido no dejar más de 10 objetivos! Como no me quedan objetivos para este espectáculo, he decidido regalarte mi alijo. + + + ¡Fabuloso! ¡Has conseguido no dejar más de 10 objetivos! Como no me quedan objetivos para este espectáculo, he decidido regalarte mi alijo. + + + Los metieron en runas y, sin esas runas, no puedo hacer mi trabajo como dios manda. + + + Por favor, héroe, si encuentras runas tráemelas. ¡Te las venderé! Eso sí, me llevaré mi parte del negocio... + + + Booyan + + + Booyan + + + Has dejado más de 10 objetivos.\nSupongo que no te interesa el premio... ¡Snif! + + + Has dejado más de 10 objetivos.\nSupongo que no te interesa el premio... ¡Snif! + + + ??? + + + ??? + + + Saludos, aventurero. ¡Vengo para ofrecerte la ocasión de tu vida! + + + Saludos, aventurera. ¡Vengo para ofrecerte la ocasión de tu vida! + + + Elfo miserable + + + Elfo miserable + + + Por la módica cantidad del 25 % de tu oro actual, te daré la oportunidad de abrir uno de los tres cofres. + + + Por la módica cantidad del 25 % de tu oro actual, te daré la oportunidad de abrir uno de los tres cofres. + + + Un cofre triplicará lo que has pagado, pero los otros dos están vacíos. + + + Un cofre triplicará lo que has pagado, pero los otros dos están vacíos. + + + Elfo tacaño + + + Elfo tacaño + + + ¿Te apetece intentarlo? + + + ¿Te apetece intentarlo? + + + Por favor, heroína, si encuentras runas tráemelas. ¡Te las venderé! Eso sí, me llevaré mi parte del negocio... + + + Arquitecto + + + ??? + + + ??? + + + Saludos, aventurero. ¡Vengo para ofrecerte la ocasión de tu vida! + + + Saludos, aventurera. ¡Vengo para ofrecerte la ocasión de tu vida! + + + Elfo miserable + + + Elfo miserable + + + Por la módica cantidad del 50 % de tu oro actual, te daré la oportunidad de abrir uno de los tres cofres. + + + Por la módica cantidad del 50 % de tu oro actual, te daré la oportunidad de abrir uno de los tres cofres. + + + Un cofre triplicará lo que has pagado, pero los otros dos están vacíos. + + + Un cofre triplicará lo que has pagado, pero los otros dos están vacíos. + + + Elfo tacaño + + + Elfo tacaño + + + ¿Te apetece intentarlo? + + + ¿Te apetece intentarlo? + + + ??? + + + ??? + + + Saludos, aventurero. ¡Vengo para ofrecerte la ocasión de tu vida! + + + Saludos, aventurera. ¡Vengo para ofrecerte la ocasión de tu vida! + + + Elfo miserable + + + Elfo miserable + + + Arquitecto + + + ¡Hola, chaval! + + + Por la módica cantidad del 75 % de tu oro actual, te daré la oportunidad de abrir uno de los tres cofres. + + + Por la módica cantidad del 75 % de tu oro actual, te daré la oportunidad de abrir uno de los tres cofres. + + + Un cofre triplicará lo que has pagado, pero los otros dos están vacíos. + + + Un cofre triplicará lo que has pagado, pero los otros dos están vacíos. + + + Elfo tacaño + + + Elfo tacaño + + + ¿Te apetece intentarlo? + + + ¿Te apetece intentarlo? + + + Elfo tacaño + + + Elfo tacaño + + + ¿No tienes suficiente dinero? Menuda birria. + + + ¿No tienes suficiente dinero? Menuda birria. + + + Elfo mal ganador + + + Elfo mal ganador + + + ¿Qué hay en la caja? + + + ¿Qué hay en la caja? + + + ¡NADA! + + + ¡NADA! + + + ¡Qué estúpido eres! ¡Pero qué estúúúúpido! + + + ¡Qué estúpida eres! ¡Pero qué estúúúúpida! + + + ¡Hola, chavala! + + + ¿Te cuento un secrrrreto? ¡Estoy como una cabrrrrra! + + + Elfo mal perdedor + + + Elfo mal perdedor + + + ¡Bah! La suerte del principiante. + + + ¡Bah! La suerte del principiante. + + + Elfo impaciente + + + Elfo impaciente + + + ¡Venga, abre un cofre! + + + ¡Venga, abre un cofre! + + + Elfo tacaño + + + Elfo tacaño + + + Lo siento chaval, un cofre por persona. + + + Lo siento chavala, un cofre por persona. + + + Desarrolladores + + + Desarrolladores + + + Don't **** Your Pants\nTiempo de desarrollo: 2 días.\nFecha de lanzamiento: 16 de febrero de 2009. + + + Don't **** Your Pants\nTiempo de desarrollo: 2 días.\nFecha de lanzamiento: 16 de febrero de 2009. + + + ¿Te cuento un secrrrreto? ¡Estoy como una cabrrrrra! + + + ¿Ves esta palanca? Con solo tirrrar de ella, puedo evitarrrr que cambie el castillo. + + + Este fue el primer juego que creamos y, por aquel entonces, nos llamábamos Decade Studios. Consiste en impedir que un hombre se haga caca usando únicamente entradas de texto. + + + Este fue el primer juego que creamos y, por aquel entonces, nos llamábamos Decade Studios. Consiste en impedir que un hombre se haga caca usando únicamente entradas de texto. + + + Originalmente, se diseñó en un autobús, y decidimos crearlo durante el fin de semana. Fue bastante bien. + + + Originalmente, se diseñó en un autobús, y decidimos crearlo durante el fin de semana. Fue bastante bien. + + + En el juego aparece una palabrota, y estábamos pensando en cambiar el título para que fuera más cordial, pero nos salió el macho que llevamos dentro y nos mantuvimos en nuestros trece. + + + En el juego aparece una palabrota, y estábamos pensando en cambiar el título para que fuera más cordial, pero nos salió el macho que llevamos dentro y nos mantuvimos en nuestros trece. + + + Una parte importante del juego consistía en crear una aventura de texto que permitiera a la gente escribir lo que quisiera. Para resolverlo, tuvimos que anticipar lo que pensábamos que la gente iba a escribir. + + + Una parte importante del juego consistía en crear una aventura de texto que permitiera a la gente escribir lo que quisiera. Para resolverlo, tuvimos que anticipar lo que pensábamos que la gente iba a escribir. + + + Lo hicimos de dos maneras: primero, redujimos el número de opciones que tenía el jugador (un hombre y una puerta), y después construimos un sistema de logros que se usaba para orientar al jugador. + + + Lo hicimos de dos maneras: primero, redujimos el número de opciones que tenía el jugador (un hombre y una puerta), y después construimos un sistema de logros que se usaba para orientar al jugador. + + + El juego giraba hasta tal punto alrededor del sistema de logros que se colocó en el juego sobre la progresión en pantalla. Fue un cambio pequeño pero vital. + + + El juego giraba hasta tal punto alrededor del sistema de logros que se colocó en el juego sobre la progresión en pantalla. Fue un cambio pequeño pero vital. + + + Desarrolladores + + + Desarrolladores + + + Band of Bears\nTiempo de desarrollo: 4 meses.\nFecha de lanzamiento: 6 de agosto de 2009. + + + Band of Bears\nTiempo de desarrollo: 4 meses.\nFecha de lanzamiento: 6 de agosto de 2009. + + + ¿Ves esta palanca? Con solo tirrrar de ella, puedo evitarrrr que cambie el castillo. + + + Así podrrrás pasar exactamente por lo mismo que tus antepasados. ¿Imprrrresionado? Deberías estarrrlo. + + + Este es el segundo juego que intentamos crear; fue para el concurso DreamBuildPlay 2009. Nos enteramos bastante tarde, así que tuvimos que ponernos las pilas para ponernos a la altura de los demás. + + + Este es el segundo juego que intentamos crear; fue para el concurso DreamBuildPlay 2009. Nos enteramos bastante tarde, así que tuvimos que ponernos las pilas para ponernos a la altura de los demás. + + + Animados por el éxito de DSYP, decidimos lanzarnos a lo grande... hasta el límite de la estupidez. Y así fue como nació Cellar Door Games. + + + Animados por el éxito de DSYP, decidimos lanzarnos a lo grande... hasta el límite de la estupidez. Y así fue como nació Cellar Door Games. + + + Además de iniciar un proyecto que nos venía muy grande, tanto por recursos como por experiencia, teníamos que combinarlo con trabajos a jornada completa para poner el juego en marcha. Fue bastante absorbente. + + + Además de iniciar un proyecto que nos venía muy grande, tanto por recursos como por experiencia, teníamos que combinarlo con trabajos a jornada completa para poner el juego en marcha. Fue bastante absorbente. + + + El juego presenta el sistema B.E.A.R.S (Bare Effort Adaptable Room System), que cambia las salas dependiendo del número de jugadores que están participando. + + + El juego presenta el sistema B.E.A.R.S (Bare Effort Adaptable Room System), que cambia las salas dependiendo del número de jugadores que están participando. + + + El sistema BEARS no solo jugaba con los números, sino también con los puzles. Acabamos entre los 20 mejores: un buen resultado, pero no lo bastante bueno como para ganar algo. + + + El sistema BEARS no solo jugaba con los números, sino también con los puzles. Acabamos entre los 20 mejores: un buen resultado, pero no lo bastante bueno como para ganar algo. + + + Al final acabamos recuperando el sentido de la realidad (y el sentido común), y nos dimos cuenta de que teníamos que abandonar el proyecto o, por lo menos, ponerlo en pausa de forma indefinida. + + + Al final acabamos recuperando el sentido de la realidad (y el sentido común), y nos dimos cuenta de que teníamos que abandonar el proyecto o, por lo menos, ponerlo en pausa de forma indefinida. + + + El jefe de la demo era una pasada. + + + El jefe de la demo era una pasada. + + + Desarrolladores + + + Desarrolladores + + + Tribal Tallies\nTiempo de desarrollo: 3 meses.\nFecha de lanzamiento: 23 de noviembre de 2009 + + + Tribal Tallies\nTiempo de desarrollo: 3 meses.\nFecha de lanzamiento: 23 de noviembre de 2009 + + + Así podrrrás pasar exactamente por lo mismo que tus antepasados. ¿Imprrrresionada? Deberías estarrrlo. + + + ¿Que cómo he construido este fantásticoooo sistema? ¡Pues con la ciencia, por supuesssssto! Y con magia. + + + Tribal Tallies fue el primer proyecto en el que estuvimos meses trabajando tras la terrible experiencia de Band of Bears. + + + Tribal Tallies fue el primer proyecto en el que estuvimos meses trabajando tras la terrible experiencia de Band of Bears. + + + Era una especie de proyecto de prueba para aventurarnos en el mundo de los juegos para iOS, ya que nunca habíamos intentado hacer algo para plataformas móviles. + + + Era una especie de proyecto de prueba para aventurarnos en el mundo de los juegos para iOS, ya que nunca habíamos intentado hacer algo para plataformas móviles. + + + El concepto del juego era sencillo: consistía en pulsar secuencias de números lo más rápido posible. + + + El concepto del juego era sencillo: consistía en pulsar secuencias de números lo más rápido posible. + + + Para animar las cosas implementamos varios modos de juego, como pulsar al revés, números ocultos y coincidencias. + + + Para animar las cosas implementamos varios modos de juego, como pulsar al revés, números ocultos y coincidencias. + + + Pensábamos que el objetivo era razonable, pero tardamos en crearlo mucho más de lo que esperábamos. No nos ayudó mucho el hecho de que todo se codificara en un hackintosh. + + + Pensábamos que el objetivo era razonable, pero tardamos en crearlo mucho más de lo que esperábamos. No nos ayudó mucho el hecho de que todo se codificara en un hackintosh. + + + Era un juego bastante simple. Podríamos haberlo hecho mejor pero, después de Band of Bears, preferíamos no correr riesgos. + + + Era un juego bastante simple. Podríamos haberlo hecho mejor pero, después de Band of Bears, preferíamos no correr riesgos. + + + Desarrolladores + + + Desarrolladores + + + Q\nTiempo de desarrollo: 1 mes.\nFecha de lanzamiento: 18 de marzo de 2010 + + + Q\nTiempo de desarrollo: 1 mes.\nFecha de lanzamiento: 18 de marzo de 2010 + + + ¿Que cómo he construido este fantásticoooo sistema? ¡Pues con la ciencia, por supuesssssto! Y con magia. + + + ... Sobre todo, con magia. + + + Nuestro cuarto proyecto. Después de Tribal Tallies estuvimos descansando unos meses y nos centramos en nuestros trabajos de diario. Pero nos volvió a picar el gusanillo y decidimos lanzarnos a un juego de puzle. + + + Nuestro cuarto proyecto. Después de Tribal Tallies estuvimos descansando unos meses y nos centramos en nuestros trabajos de diario. Pero nos volvió a picar el gusanillo y decidimos lanzarnos a un juego de puzle. + + + Llegados a este punto, la mayoría de los fundadores originales de Cellar Door Games se habían marchado para aprovechar otras oportunidades; los no elegidos componemos la compañía tal y como es hoy. + + + Llegados a este punto, la mayoría de los fundadores originales de Cellar Door Games se habían marchado para aprovechar otras oportunidades; los no elegidos componemos la compañía tal y como es hoy. + + + El juego utilizaba un mecanismo de colas de combos para obligar a los jugadores a pensar en cómo caerían las fichas para construir combos enormes. + + + El juego utilizaba un mecanismo de colas de combos para obligar a los jugadores a pensar en cómo caerían las fichas para construir combos enormes. + + + Era gratis, pero nadie lo seleccionó. Tras los fracasos de Band of Bears, Tribal Tallies y Q, nos hicimos a la idea de tirar la toalla y cerrar la empresa. + + + Era gratis, pero nadie lo seleccionó. Tras los fracasos de Band of Bears, Tribal Tallies y Q, nos hicimos a la idea de tirar la toalla y cerrar la empresa. + + + Desarrolladores + + + Desarrolladores + + + My First Quantum Translocator\nTiempo de desarrollo: 1 mes.\nFecha de lanzamiento: 13 de octubre de 2010 + + + My First Quantum Translocator\nTiempo de desarrollo: 1 mes.\nFecha de lanzamiento: 13 de octubre de 2010 + + + My First Quantum Translocator llegó cuando nuestra empresa estaba en su peor momento. Después del fracaso de tres juegos, mentalmente habíamos cerrado el chiringuito e hicimos este diminuto juego flash por diversión. + + + My First Quantum Translocator llegó cuando nuestra empresa estaba en su peor momento. Después del fracaso de tres juegos, mentalmente habíamos cerrado el chiringuito e hicimos este diminuto juego flash por diversión. + + + ... Sobre todo, con magia. + + + Herrero + + + Bienvenido, héroe. + + + Pero mi habilidad tieneee un prrrrecio. ¡Si te bloqueo este castillo, me quedarrré con el 40 % de todo el oro que consigas! + + + Durante el desarrollo no teníamos ninguna expectativa; lo hicimos, sobre todo, por pasarlo bien. + + + Durante el desarrollo no teníamos ninguna expectativa; lo hicimos, sobre todo, por pasarlo bien. + + + No hace falta decir que el juego tuvo una respuesta brutal; es la única razón por la que Cellar Door Games sigue existiendo hoy en día. Cuando lanzamos MFQT, supimos que no habría vuelta atrás. + + + No hace falta decir que el juego tuvo una respuesta brutal; es la única razón por la que Cellar Door Games sigue existiendo hoy en día. Cuando lanzamos MFQT, supimos que no habría vuelta atrás. + + + Resulta interesante que la mayoría de la gente piense que el juego está inspirado en Portal, pero el parecido era pura coincidencia. + + + Resulta interesante que la mayoría de la gente piense que el juego está inspirado en Portal, pero el parecido era pura coincidencia. + + + En realidad el juego nació a partir de un personaje que habíamos pensado para el juego League of Legends. + + + En realidad el juego nació a partir de un personaje que habíamos pensado para el juego League of Legends. + + + La verdad es que las similitudes entre Portal y MFQT solo empezaron a aparecer cuando añadimos el trabajo artístico y la historia final al juego. + + + La verdad es que las similitudes entre Portal y MFQT solo empezaron a aparecer cuando añadimos el trabajo artístico y la historia final al juego. + + + De cualquier modo, estábamos muy orgullosos del juego. Se jugaba muy bien y tenía un final estupendo. + + + De cualquier modo, estábamos muy orgullosos del juego. Se jugaba muy bien y tenía un final estupendo. + + + Desarrolladores + + + Desarrolladores + + + I Have 1 Day\nTiempo de desarrollo: 1,5 meses.\nFecha de lanzamiento: 15 de abril de 2011 + + + I Have 1 Day\nTiempo de desarrollo: 1,5 meses.\nFecha de lanzamiento: 15 de abril de 2011 + + + Pero mi habilidad tieneee un prrrrecio. ¡Si te bloqueo este castillo, me quedarrré con el 40 % de todo el oro que consigas! + + + + + + Si nos preguntaran cuál de los juegos que hemos creado es nuestro favorito, responderíamos unánimemente que es I Have 1 Day. + + + Si nos preguntaran cuál de los juegos que hemos creado es nuestro favorito, responderíamos unánimemente que es I Have 1 Day. + + + De niños, nos hemos criado con clásicos juegos de aventuras como Kings Quest y Monkey Island; este era nuestro homenaje a algunas de las mejores experiencias que hemos vivido jugando. + + + De niños, nos hemos criado con clásicos juegos de aventuras como Kings Quest y Monkey Island; este era nuestro homenaje a algunas de las mejores experiencias que hemos vivido jugando. + + + El juego gira en torno a un puzle metatemporal donde el jugador solo tiene 24 horas para completarlo. + + + El juego gira en torno a un puzle metatemporal donde el jugador solo tiene 24 horas para completarlo. + + + Cada puzle tenía múltiples soluciones con repercusiones de tiempo, lo que obligaba a los jugadores a pensar en cuál era la mejor manera de proceder. + + + Cada puzle tenía múltiples soluciones con repercusiones de tiempo, lo que obligaba a los jugadores a pensar en cuál era la mejor manera de proceder. + + + Un dato interesante: el segundo final se añadió prácticamente en el último minuto y, sin él, el juego habría sido un desastre. + + + Un dato interesante: el segundo final se añadió prácticamente en el último minuto y, sin él, el juego habría sido un desastre. + + + Desarrolladores + + + Desarrolladores + + + Villainous\nTiempo de desarrollo: 3 meses.\nFecha de lanzamiento: 15 de abril de 2011 + + + Villainous\nTiempo de desarrollo: 3 meses.\nFecha de lanzamiento: 15 de abril de 2011 + + + Villainous fue uno de los proyectos más arriesgados que hemos emprendido. + + + Villainous fue uno de los proyectos más arriesgados que hemos emprendido. + + + + + + ¿Quieres bloquear el castillo y recibir solo el 60 % del oro? + + + El concepto inicial era un juego de defensa de torres inverso; parecía que podría ser una buena idea, pero nos costó mucho pasar del «podría ser» al «es». + + + El concepto inicial era un juego de defensa de torres inverso; parecía que podría ser una buena idea, pero nos costó mucho pasar del «podría ser» al «es». + + + La mayoría de la gente que ha jugado piensa que el proceso era evidente, pero en este proyecto pasamos por muchas fases de estrés y discusiones. + + + La mayoría de la gente que ha jugado piensa que el proceso era evidente, pero en este proyecto pasamos por muchas fases de estrés y discusiones. + + + La idea entera se desechó tres o cuatro veces antes de decidir cuál sería la versión final. + + + La idea entera se desechó tres o cuatro veces antes de decidir cuál sería la versión final. + + + Resulta irónico que, hasta la fecha, Villainous sea, con diferencia, uno de nuestros títulos de mayor éxito. Fue también el más duro. + + + Resulta irónico que, hasta la fecha, Villainous sea, con diferencia, uno de nuestros títulos de mayor éxito. Fue también el más duro. + + + Desarrolladores + + + Desarrolladores + + + Bullet Audyssey\nTiempo de desarrollo: 3,5 meses.\nFecha de lanzamiento: 29 de noviembre de 2011 + + + Bullet Audyssey\nTiempo de desarrollo: 3,5 meses.\nFecha de lanzamiento: 29 de noviembre de 2011 + + + Bullet Audyssey fue el último juego que creamos antes de trabajar en Rogue Legacy. + + + Bullet Audyssey fue el último juego que creamos antes de trabajar en Rogue Legacy. + + + Al tratarse de un juego «infierno de balas» basado en el ritmo y en los tiempos, Bullet Audyssey fue el juego más complicado desde el punto de vista técnico de todos los que hemos creado (sí, incluso más que Rogue Legacy). + + + Al tratarse de un juego «infierno de balas» basado en el ritmo y en los tiempos, Bullet Audyssey fue el juego más complicado desde el punto de vista técnico de todos los que hemos creado (sí, incluso más que Rogue Legacy). + + + ¿Quieres bloquear el castillo y recibir solo el 60 % del oro? + + + + + + Solo para poder crear un escenario, tres editores tenían que trabajar al unísono. + + + Solo para poder crear un escenario, tres editores tenían que trabajar al unísono. + + + El desarrollo de este juego también fue un poco más tradicional; se necesitó una gran cantidad de planificación previa para asegurarnos de que todo encajara bien. + + + El desarrollo de este juego también fue un poco más tradicional; se necesitó una gran cantidad de planificación previa para asegurarnos de que todo encajara bien. + + + La verdad es que no somos nada partidarios de la documentación; por eso, todo esto nos costó mucho, tuvimos que sentarnos y debatir el juego entero durante, por lo menos, medio día. + + + La verdad es que no somos nada partidarios de la documentación; por eso, todo esto nos costó mucho, tuvimos que sentarnos y debatir el juego entero durante, por lo menos, medio día. + + + En el juego, el jugador absorbe balas enemigas para volver a lanzarlas, y la absorción se hacía siguiendo un ritmo que coincidía con la música que se escuchaba en el juego. + + + En el juego, el jugador absorbe balas enemigas para volver a lanzarlas, y la absorción se hacía siguiendo un ritmo que coincidía con la música que se escuchaba en el juego. + + + Las pruebas de juego iniciales fueron una verdadera catástrofe porque el juego era demasiado difícil y la gente se frustraba en el primer minuto. + + + Las pruebas de juego iniciales fueron una verdadera catástrofe porque el juego era demasiado difícil y la gente se frustraba en el primer minuto. + + + Las pruebas de juego consistían en un tipo jugando al que ni siquiera le gustan los juegos de tipo «infierno de balas». Es decir, un grupo de testers más grande de lo que solemos tener. + + + Las pruebas de juego consistían en un tipo jugando al que ni siquiera le gustan los juegos de tipo «infierno de balas». Es decir, un grupo de testers más grande de lo que solemos tener. + + + El juego no tuvo una gran respuesta tras su lanzamiento, ¡lo que nos dio la confianza para crear Rogue Legacy! + + + El juego no tuvo una gran respuesta tras su lanzamiento, ¡lo que nos dio la confianza para crear Rogue Legacy! + + + Confirmar + + + Confirmar + + + Cancelar + + + Cancelar + + + ¡Cuidado! + + + ¡Cuidado! + + + + + + ¿Quieres bloquear el castillo y recibir solo el 60 % del oro? + + + ¿Seguro que quieres empezar una partida nueva? Se borrarán todos los datos guardados anteriores. + + + ¿Seguro que quieres empezar una partida nueva? Se borrarán todos los datos guardados anteriores. + + + Restablecer controles + + + Restablecer controles + + + ¿Seguro que quieres restablecer el sistema de control predeterminado? + + + ¿Seguro que quieres restablecer el sistema de control predeterminado? + + + + + + + + + ¿Seguro que quieres comenzar una nueva aventura con el héroe que has elegido? + + + ¿Seguro que quieres comenzar una nueva aventura con la heroína que has elegido? + + + Resolución cambiada + + + Resolución cambiada + + + ¿Seguro que quieres jugar con esta resolución?\n(Se restablecerá la resolución anterior pasados 10 segundos). + + + ¿Seguro que quieres jugar con esta resolución?\n(Se restablecerá la resolución anterior pasados 10 segundos). + + + Borrar archivo guardado + + + Borrar archivo guardado + + + ¿Seguro que quieres borrar el archivo guardado?\n(Se borrarán PARA SIEMPRE todas las habilidades, rasgos, linajes y equipamiento). + + + ¿Seguro que quieres borrar el archivo guardado?\n(Se borrarán PARA SIEMPRE todas las habilidades, rasgos, linajes y equipamiento). + + + ¿Quieres bloquear el castillo y recibir solo el 60 % del oro? + + + Arquitecto + + + Borrar archivo guardado + + + Borrar archivo guardado + + + ¿SEGURO que sí? (No vale cambiar de opinión).\n(Se borrarán PARA SIEMPRE todas las habilidades, rasgos, linajes y equipamiento). + + + ¿SEGURO que sí? (No vale cambiar de opinión).\n(Se borrarán PARA SIEMPRE todas las habilidades, rasgos, linajes y equipamiento). + + + + + + + + + ¿Seguro que quieres salir al menú principal? (Se guardará tu estatus actual) + + + ¿Seguro que quieres salir al menú principal? (Se guardará tu estatus actual) + + + + + + + + + ¿Seguro que quieres dejar de jugar a Rogue Legacy? (Se guardará tu estatus actual) + + + ¿Seguro que quieres dejar de jugar a Rogue Legacy? (Se guardará tu estatus actual) + + + Error al guardar + + + Error al guardar + + + ¡Oh, no! ¡Tu archivo guardado está dañado! + + + ¡Oh, no! ¡Tu archivo guardado está dañado! + + + Arquitecto + + + Lo siento chaval, en este momentooo no se puede constrrrruir ningún castillo. Este tornillo solo es de pega. + + + Vamos a intentar cargar una versión de copia de seguridad de la partida. ¡Esperamos que no te retrase demasiado! + + + Vamos a intentar cargar una versión de copia de seguridad de la partida. ¡Esperamos que no te retrase demasiado! + + + Error al guardar + + + Error al guardar + + + Parece que la copia de seguridad tampoco funciona. Por favor, póngase en contacto con: support@cellardoorgames.com + Parece que la copia de seguridad tampoco funciona. Me temo que vamos a tener que volver a empezar la partida. + + + Parece que la copia de seguridad tampoco funciona. Por favor, póngase en contacto con: support@cellardoorgames.com + Parece que la copia de seguridad tampoco funciona. Me temo que vamos a tener que volver a empezar la partida. + + + Error al guardar + + + Error al guardar + + + Se han producido tres errores seguidos al intentar guardar la partida. + + + Se han producido tres errores seguidos al intentar guardar la partida. + + + El software de antivirus y los programas de copiado de seguridad manual podrían interferir con los archivos guardados. Desactiva estos programas antes de ejecutar el juego. + + + El software de antivirus y los programas de copiado de seguridad manual podrían interferir con los archivos guardados. Desactiva estos programas antes de ejecutar el juego. + + + Lo siento chavala, en este momentooo no se puede constrrrruir ningún castillo. Este tornillo solo es de pega. + + + Arquitecto + + + Arquitecto + + + Mendrrrrugo, el castillo ya está bloqueado. + + + Mendrrrruga, el castillo ya está bloqueado. + + + Arquitecto + + + Arquitecto + + + Bienvenida, heroína. + + + A lo mejor me puedes ayudar: antes era el mejor herrero de todas las tierras, pero un día los monstruos de este castillo atacaron mi forja y me robaron todos los planos. + + + ¡Disfrútalooo! ¡A lo mejor encuentras tesorrrros que se dejaron tus antepasadooos! + + + ¡Disfrútalooo! ¡A lo mejor encuentras tesorrrros que se dejaron tus antepasadooos! + + + Charon + + + Charon + + + ... Hay que pagar el peaje. + + + ... Hay que pagar el peaje. + + + + + + + + + (¿Quieres darle a Charon todo tu dinero y entrar en el castillo?) + + + (¿Quieres darle a Charon todo tu dinero y entrar en el castillo?) + + + + + + + + + (¿Quieres darle a Charon todo tu dinero y entrar en el castillo?) + + + (¿Quieres darle a Charon todo tu dinero y entrar en el castillo?) + + + + + + + + + (¿Quieres darle a Charon el 90 % de tu dinero y entrar en el castillo?) + + + (¿Quieres darle a Charon el 90 % de tu dinero y entrar en el castillo?) + + + + + + + + + A lo mejor me puedes ayudar: antes era el mejor herrero de todas las tierras, pero un día los monstruos de este castillo atacaron mi forja y me robaron todos los planos. + + + Y sin los planos, solo puedo fabricar cubiertos y otras cosas sencillas. + + + (¿Quieres darle a Charon el 80 % de tu dinero y entrar en el castillo?) + + + (¿Quieres darle a Charon el 80 % de tu dinero y entrar en el castillo?) + + + + + + + + + (¿Quieres darle a Charon el 70 % de tu dinero y entrar en el castillo?) + + + (¿Quieres darle a Charon el 70 % de tu dinero y entrar en el castillo?) + + + + + + + + + (¿Quieres darle a Charon el 60 % de tu dinero y entrar en el castillo?) + + + (¿Quieres darle a Charon el 60 % de tu dinero y entrar en el castillo?) + + + + + + + + + (¿Quieres darle a Charon el 50 % de tu dinero y entrar en el castillo?) + + + (¿Quieres darle a Charon el 50 % de tu dinero y entrar en el castillo?) + + + Charon + + + Charon + + + ¡Ojojó! Así que tienes mi óbolo. Te voy a dejar pasar gratis, pero solo esta vez. + + + ¡Ojojó! Así que tienes mi óbolo. Te voy a dejar pasar gratis, pero solo esta vez. + + + Charon + + + Charon + + + Y sin los planos, solo puedo fabricar cubiertos y otras cosas sencillas. + + + Tráeme todos los planos que encuentres para que pueda fabricar el equipo más bestial que has visto en tu vida. EN TODA TU VIDA. + + + ¡Ojojó! Este óbolo es muy especial. + + + ¡Ojojó! Este óbolo es muy especial. + + + Dámelo y dejaré que tu alma atraviese las otras puertas. + + + Dámelo y dejaré que tu alma atraviese las otras puertas. + + + (¿Quieres darle el óbolo a Charon y pagarle el peaje?) + + + (¿Quieres darle el óbolo a Charon y pagarle el peaje?) + + + Charon + + + Charon + + + ¡Ojojó! Este óbolo es muy especial. + + + ¡Ojojó! Este óbolo es muy especial. + + + Dámelo y dejaré que tu alma atraviese las otras puertas. + + + Dámelo y dejaré que tu alma atraviese las otras puertas. + + + (¿Quieres darle el óbolo a Charon y pagarle el peaje?) + + + (¿Quieres darle el óbolo a Charon y pagarle el peaje?) + + + Charon + + + Charon + + + ¡Ojojó! Este óbolo es muy especial. + + + ¡Ojojó! Este óbolo es muy especial. + + + Dámelo y dejaré que tu alma atraviese las otras puertas. + + + Dámelo y dejaré que tu alma atraviese las otras puertas. + + + Tráeme todos los planos que encuentres para que pueda fabricar el equipo más bestial que has visto en tu vida. EN TODA TU VIDA. + + + ... Pagando su precio, por supuesto. + + + (¿Quieres darle el óbolo a Charon y pagarle el peaje?) + + + (¿Quieres darle el óbolo a Charon y pagarle el peaje?) + + + Charon + + + Charon + + + ¡Ojojó! Este óbolo es muy especial. + + + ¡Ojojó! Este óbolo es muy especial. + + + Dámelo y dejaré que tu alma atraviese las otras puertas. + + + Dámelo y dejaré que tu alma atraviese las otras puertas. + + + (¿Quieres darle el óbolo a Charon y pagarle el peaje?) + + + (¿Quieres darle el óbolo a Charon y pagarle el peaje?) + + + Charon + + + Charon + + + Oh... No deberías haber cogido este óbolo. + + + Oh... No deberías haber cogido este óbolo. + + + Prepárate. + + + Prepárate. + + + (¿Quieres darle el óbolo a Charon y pagarle el peaje?) + + + (¿Quieres darle el óbolo a Charon y pagarle el peaje?) + + + Santuario espiritual + + + Santuario espiritual + + + ... Pagando su precio, por supuesto. + + + Encantadora + + + ¿Quieres rezar para recibir ayuda? + + + ¿Quieres rezar para recibir ayuda? + + + Último jefe + + + Último jefe + + + ¡Bienvenido, héroe! Es increíble que hayas llegado tan lejos. ¡Por desgracia, no vas a avanzar más! + + + ¡Bienvenida, heroína! Es increíble que hayas llegado tan lejos. ¡Por desgracia, no vas a avanzar más! + + + Cofre enigmático - Nada + + + Cofre enigmático - Nada + + + NO TEXT + + + NO TEXT + + + Derrota a todos los enemigos + + + Derrota a todos los enemigos + + + + + + + + + Nivel de salud bajo + + + Nivel de salud bajo + + + + + + + + + Sin mirar + + + Sin mirar + + + Encantadora + + + Hola, héroe. + + + + + + + + + Sin saltar + + + Sin saltar + + + + + + + + + Sin ruido + + + Sin ruido + + + + + + + + + No toques el suelo + + + No toques el suelo + + + + + + + + + Sin luchar + + + Sin luchar + + + + + + + + + Llega hasta mí a tiempo + + + Llega hasta mí a tiempo + + + Hola, heroína. + + + ¿Puedo hablar contigo un momento? Necesito que me eches una mano. + + + + + + + + + No sufras daños + + + No sufras daños + + + + + + + + + Encuéntrame + + + Encuéntrame + + + + + + + + + Cofre enigmático + + + Cofre enigmático + + + ¡No me mires! + + + ¡No me mires! + + + Cofre enigmático + + + Cofre enigmático + + + Sin saltar + + + Sin saltar + + + Cofre enigmático + + + Cofre enigmático + + + ¿Puedo hablar contigo un momento? Necesito que me eches una mano. + + + Pulsa [Input:12] para atacar + + + Pulsa [Input:12] para atacar + + + Continúa tu misión + + + Continúa tu misión + + + Elige a tu heredero + + + Elige a tu heredera + + + Inicia tu legado + + + Inicia tu legado + + + Muñeco + + + ¡DUELE! + + + ¡DUELE! + + + Uy + + + Uy + + + Ay + + + Ay + + + PUPAAA + + + PUPAAA + + + ¡Me rindo! + + + ¡Me rindo! + + + ¿Te entrenas? + + + ¿Te entrenas? + + + Eso ha dolido. + + + Eso ha dolido. + + + ¡Ja, ja, ja! + + + ¡Ja, ja, ja! + + + ¿Eso es todo? + + + ¿Eso es todo? + + + ¿Haces pesas? + + + ¿Haces pesas? + + + Muñeco + + + ¡Dios mío! + + + Buen intento. + + + Buen intento. + + + Débil. + + + Débil. + + + Repite. + + + Repite. + + + ¡Dios mío! + + + ¡Qué dolor! + + + ¡Qué dolor! + + + Duele muchísimo. + + + Duele muchísimo. + + + ¡¡BASTA!! + + + ¡¡BASTA!! + + + ¿Por qué? + + + ¿Por qué? + + + ¿¿¿POR QUÉ??? + + + ¿¿¿POR QUÉ??? + + + Para. + + + Para. + + + Pero ¿por qué? + + + Pero ¿por qué? + + + No distingues los colores con tu visión monocromática. + + + Eres un fideo y al menor roce sales volando. + + + Eres un fideo y al menor roce sales volando. + + + Te cuesta recordar dónde estás. + + + Te cuesta recordar dónde estás. + + + Tus PM y tus PV se intercambian. ¿Quién lo iba a decir? + + + Tus PM y tus PV se intercambian. ¿Quién lo iba a decir? + + + ¡%#&@! + + + ¡%#&@! + + + ¡Qué energía! Te mueves más rápido. + + + ¡Qué energía! Te mueves más rápido. + + + Tengo que recoger. Limpiar la casa. La casa. Rompe cosas y recupera PM. + + + Tengo que recoger. Limpiar la casa. La casa. Rompe cosas y recupera PM. + + + Eres un mastodonte. Tus ataques lanzan a los enemigos más lejos. + + + Eres un mastodonte. Tus ataques lanzan a los enemigos más lejos. + + + Las extremidades te flojean. No puedes derribar a los enemigos. + + + Las extremidades te flojean. No puedes derribar a los enemigos. + + + Eres incapaz de ver en 3D. + + + Eres incapaz de ver en 3D. + + + Hasta a los héroes más valientes se les irrita el intestino. + + + Hasta a los héroes más valientes se les irrita el intestino. + + + No distingues los colores con tu visión monocromática. + + + Te gustan las damas. + + + Bienvenido al mundo de las angustias. + + + Bienvenida al mundo de las angustias. + + + No tienes visión periférica. + + + No tienes visión periférica. + + + Tienes dos manos zurdas y no puedes lanzar bien los hechizos. + + + Tienes dos manos zurdas y no puedes lanzar bien los hechizos. + + + Padeces una enfermedad arterial periférica. No tienes pulso en los pies. + + + Padeces una enfermedad arterial periférica. No tienes pulso en los pies. + + + Los pollos te aterran. + + + Los pollos te aterran. + + + Tienes tendencia a la EXAGERACIÓN. + + + Tienes tendencia a la EXAGERACIÓN. + + + Estás como una cabra. + + + Estás como una cabra. + + + Eres muy flexible. + + + Eres muy flexible. + + + Lo recuerdas todo con gran claridad. + + + Lo recuerdas todo con gran claridad. + + + Echas de menos los viejos tiempos. + + + Echas de menos los viejos tiempos. + + + Eres fan de los chicos. + + + Eres fan de los chicos. + + + Te gustan las damas. + + + Ves borroso de lejos. + + + Insensibilidad congénita al dolor. No sabes lo que es el dolor. + + + Insensibilidad congénita al dolor. No sabes lo que es el dolor. + + + Tienes grandes talentos, aunque eres un poco tiquismiquis. + + + Tienes grandes talentos, aunque eres un poco tiquismiquis. + + + La cuchara no existe. + + + La cuchara no existe. + + + Rompes muchas cosas. + + + Rompes muchas cosas. + + + Conduces la electricidad estupendamente. + + + Conduces la electricidad estupendamente. + + + Está muy oscuro. + + + Está muy oscuro. + + + Ves borroso de lejos. + + + Ves borroso de cerca. + + + Ves borroso de cerca. + + + Te cuesta leer. + + + Te cuesta leer. + + + Naciste para jugar al baloncesto. + + + Naciste para jugar al baloncesto. + + + Nunca puedes subir a la montaña rusa. + + + Nunca puedes subir a la montaña rusa. + + + La calva es bella. + + + La calva es bella. + + + Pesas tanto que a los enemigos les resulta imposible derribarte. + + + Pesas tanto que a los enemigos les resulta imposible derribarte. + + + No puedes ver en color. + + + Si te golpean, sales volando. + + + Si te golpean, sales volando. + + + ¿Dónde estás? + + + ¿Dónde estás? + + + Se intercambian PM y PV. + + + Se intercambian PM y PV. + + + ¡%#&@! + + + ¡%#&@! + + + Te mueves más rápido. + + + Te mueves más rápido. + + + Rompe cosas y recupera PM. + + + Rompe cosas y recupera PM. + + + Derribas a los enemigos. + + + Derribas a los enemigos. + + + No puedes derribar a los enemigos. + + + No puedes derribar a los enemigos. + + + Eres incapaz de ver en 3D. + + + Eres incapaz de ver en 3D. + + + Te tiras muchos pedos. + + + Te tiras muchos pedos. + + + No puedes ver en color. + + + Te gustan las damas. + + + Todo está cabeza abajo. + + + Todo está cabeza abajo. + + + Sin indicadores previos. + + + Sin indicadores previos. + + + Te salen hechizos por detrás. + + + Te salen hechizos por detrás. + + + No tienes pulso en los pies. + + + No tienes pulso en los pies. + + + Los pollos te dan miedo. + + + Los pollos te dan miedo. + + + Exageras el daño que recibes. + + + Exageras el daño que recibes. + + + Ves cosas que no están. + + + Ves cosas que no están. + + + Giras mientras luchas. + + + Giras mientras luchas. + + + Recuerdas la situación del enemigo. + + + Recuerdas la situación del enemigo. + + + Todo es un poco vetusto. + + + Todo es un poco vetusto. + + + Eres fan de los chicos. + + + Eres fan de los chicos. + + + Te gustan las damas. + + + Ves borroso de lejos. + + + La barra de salud no está visible. + + + La barra de salud no está visible. + + + Hechizos aleatorios. + + + Hechizos aleatorios. + + + La cuchara no existe. + + + La cuchara no existe. + + + Rompes cosas y no tienes equilibrio. + + + Rompes cosas y no tienes equilibrio. + + + Las plataformas se mantienen abiertas. + + + Las plataformas se mantienen abiertas. + + + Está muy oscuro. + + + Está muy oscuro. + + + Ves borroso de lejos. + + + Ves borroso de cerca. + + + Ves borroso de cerca. + + + Te cuesta leer. + + + Te cuesta leer. + + + Eres gigante. + + + Eres gigante. + + + Eres muy poca cosa. + + + Eres muy poca cosa. + + + No tienes pelo. + + + No tienes pelo. + + + No te pueden derribar. + + + No te pueden derribar. + + + Daltonismo + + + Ectomorfismo + + + Ectomorfismo + + + Alzheimer + + + Alzheimer + + + Dextrocardia + + + Dextrocardia + + + Coprolalia + + + Coprolalia + + + Hiperactividad + + + Hiperactividad + + + Obsesión compulsiva + + + Obsesión compulsiva + + + Hipergonadismo + + + Hipergonadismo + + + Debilidad muscular + + + Debilidad muscular + + + Ceguera estéreo + + + Ceguera estéreo + + + Colon irritable + + + Colon irritable + + + Daltonismo + + + Gay + + + Vértigo + + + Vértigo + + + Visión en túnel + + + Visión en túnel + + + Torpeza + + + Torpeza + + + Pulso letárgico + + + Pulso letárgico + + + Alectrofobia + + + Alectrofobia + + + Hipocondría + + + Hipocondría + + + Demencia + + + Demencia + + + Flexibilidad + + + Flexibilidad + + + Memoria fotográfica + + + Memoria fotográfica + + + Nostalgia + + + Nostalgia + + + Gay + + + Miopía + + + Inmunidad al dolor + + + Inmunidad al dolor + + + Sabiduría + + + Sabiduría + + + El elegido + + + El elegido + + + Torpe + + + Torpe + + + Conductor + + + Conductor + + + Glaucoma + + + Glaucoma + + + Miopía + + + Hipermetropía + + + Hipermetropía + + + Dislexia + + + Dislexia + + + Gigantismo + + + Gigantismo + + + Enanismo + + + Enanismo + + + Calvicie + + + Calvicie + + + Endomorfismo + + + Endomorfismo + + + Desarrollado por + + + Desarrollado por + + + Diseño + + + Diseño + + + Programación + + + Programación + + + Producción + + + Producción + + + Arte + + + Arte + + + Diseño de sonido y música + + + Diseño de sonido y música + + + Música + + + Música + + + + + + + + + Ataca hacia abajo a esto + + + Ataca hacia abajo a esto + + + Pulsa [Input:11] para saltar + + + Pulsa [Input:11] para saltar + + + Mantén pulsado [Input:11] para saltar más alto + + + Mantén pulsado [Input:11] para saltar más alto + + + Pulsa [Input:12] para atacar + + + Pulsa [Input:12] para atacar + + + Mantén pulsado [Input:19] y pulsa [Input:11] para\ndejarte caer + + + Mantén pulsado [Input:19] y pulsa [Input:11] para\ndejarte caer + + + (Aire) Mantén pulsado [Input:19] y pulsa [Input:12] para atacar\nhacia abajo + + + (Aire) Mantén pulsado [Input:19] y pulsa [Input:12] para atacar\nhacia abajo + + + Pulsa [Input:10] para saltar + + + Pulsa [Input:10] para saltar + + + Mantén pulsado [Input:10] para saltar más alto + + + Mantén pulsado [Input:10] para saltar más alto + + + Pulsa [Input:12] para atacar + + + Pulsa [Input:12] para atacar + + + Mantén pulsado [Input:18] y pulsa [Input:10] para dejarte caer + + + Mantén pulsado [Input:18] y pulsa [Input:10] para dejarte caer + + + (Aire) Mantén pulsado [Input:18] y pulsa [Input:12] para atacar\nhacia abajo + + + (Aire) Mantén pulsado [Input:18] y pulsa [Input:12] para atacar\nhacia abajo + + + Programación adicional + + + Adaptación de + + + ¿Donar {0} de oro y potenciar permanentemente a tu espectro para este jefe?\nVeces potenciado: {1} + + + La caja de donaciones está llena hasta los topes. Tu espectro no se puede potenciar más. Gracias por el dinero, colega. + + + No puedes permitirte donar. Vuelve cuando hayas ganado más oro. + + + ¡Tu espectro se ha vuelto más fuerte! + + + Caja de donaciones + + + {1} {0} + + + Desbloquear traidor + + + Cripta + + + Maldición + + + Gracia + + + Tarifa del arquitecto + + + Bonificación NP+ + + + Aceleración + + + Vampiro + + + Celestial + + + Sifón + + + Equilibrio + + + Contraataque + + + Botín + + + Velocidad + + + {1} {0} + + + Localización al japonés y producción + + + Control de calidad + + + Te dan espasmos musculares. + + + No eres capaz de distinguir a las personas. + + + Clonus + + + Prosopagnosia + + + Maldición + + + Gracia + + + Tarifa del arquitecto + + + Bonificación NP+ + + + Cripta + + + Aceleración + + + Vampiro + + + Celestial + + + Sifón + + + Equilibrio + + + Contraataque + + + Botín + + + Velocidad + + + Te dan espasmos musculares. + + + No eres capaz de distinguir a las personas. + + + Clonus + + + Prosopagnosia + + + Consigue un 60% del oro + + + Consigue un 60% del oro + + + Desbloquear traidor + + + Full Metal Furies\nTiempo de desarrollo: 4 años.\nFecha de lanzamiento: 17 de enero de 2018 + + + ¡Full Metal Furies viene del futuro! Es nuestro siguiente juego tras Rogue Legacy y el décimo que desarrollamos. + + + Tras RL, nos prometimos que jamás volveríamos a desarrollar un juego sin planificarlo previamente. Mentira. ¡Malditos yoes del pasado! + + + El juego acabó siendo uno de nuestros proyectos más ambiciosos y al final resultó en una mezcla entre brawler, juego multijugador, metapuzle e ideas sobre la madurez que cambiaba por completo el concepto general en torno al género brawler. + + + Tras 4 años, FMF se ha convertido en el título que más tiempo nos ha llevado desarrollar y, por desgracia, en uno de los menos rentables. (Eso sin contar aquellos juegos de iOS que generaron ingresos negativos...) + + + Sin embargo, estamos muy orgullosos de nuestro juego y más aun de los AMIGOS QUE HICIMOS DURANTE SU DESARROLLO. ¡¡¡QUÉ PRIMORES!!! + + + Copyright (C) 2013-2018, Cellar Door Games Inc. + + + {0} es una marca registrada de Cellar Door Games Inc. Todos los derechos reservados. + + \ No newline at end of file diff --git a/RogueCastle/Resources/LocStrings.fr.resx b/RogueCastle/Resources/LocStrings.fr.resx new file mode 100644 index 0000000..e280413 --- /dev/null +++ b/RogueCastle/Resources/LocStrings.fr.resx @@ -0,0 +1,8366 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Retour à l'écran titre + + + Retour à l'écran titre + + + Retour à l'écran titre (passer didacticiel) + + + Retour à l'écran titre (passer didacticiel) + + + [Input:25] pour changer de profil ({0}) + + + [Input:25] pour changer de profil ({0}) + + + Vie + + + Touches directionnelles pour parcourir + + + Touches directionnelles pour parcourir + + + [Button:LeftStick] pour parcourir + + + [Button:LeftStick] pour parcourir + + + Sélectionnez une catégorie + + + Sélectionnez une catégorie + + + Plan nécessaire + + + Plan nécessaire + + + Info Achat ici + + + Info Achat ici + + + Aucun + + + Aucun + + + {0} pour déverrouiller + + + {0} pour déverrouiller + + + Vie + + + Mana + + + Mana + + + Dégâts + + + Dégâts + + + Magie + + + Magie + + + Armure + + + Armure + + + Poids + + + Poids + + + Propriétés supplémentaires : + + + Propriétés supplémentaires : + + + [Input:0] sélectionner/équiper + + + [Input:0] sélectionner/équiper + + + [Input:2] annuler/fermer menu + + + [Input:2] annuler/fermer menu + + + Cibles détruites + + + Cibles détruites + + + Cibles restantes + + + Cibles restantes + + + Récompense + + + Récompense + + + or + + + or + + + afficher la carte à tout moment + + + afficher la carte à tout moment + + + Modifier commandes + + + Accélération droite + + + Accélération droite + + + Jeter sort + + + Jeter sort + + + Réinitialiser commandes + + + Réinitialiser commandes + + + Appuyez sur une touche + + + Appuyez sur une touche + + + Modifier commandes + + + Haut + + + Haut + + + Bas + + + Bas + + + Gauche + + + Gauche + + + Droite + + + Droite + + + Attaque + + + Attaque + + + Sauter + + + Sauter + + + Spécial + + + Spécial + + + Accélération gauche + + + Accélération gauche + + + Votre héros de base. Bon dans tous les domaines. + + + Un char sur pattes. Ce héros est un dur à cuire.\nSPÉCIAL : Cri barbare. + + + Un char sur pattes. Cette héroïne est une dure à cuire.\nSPÉCIAL : Cri barbare. + + + Un héros rapide. Inflige de lourds dégâts mais pas d'attaques critiques. + + + Une héroïne rapide. Inflige de lourds dégâts mais pas d'attaques critiques. + + + Un héros rapide. Inflige de lourds dégâts mais pas d'attaques critiques.\nSPÉCIAL : Technique de substitution. + + + Une héroïne rapide. Inflige de lourds dégâts mais pas d'attaques critiques.\nSPÉCIAL : Technique de substitution. + + + Un héros pour les pros. Touchez l'ennemi pour récupérer de la mana. + + + Une héroïne pour les pros. Touchez l'ennemi pour récupérer de la mana. + + + Un héros pour les pros. Touchez l'ennemi pour récupérer de la mana.\nSPÉCIAL : Sort augmenté. + + + Une héroïne pour les pros. Touchez l'ennemi pour récupérer de la mana.\nSPÉCIAL : Sort augmenté. + + + Se nourrit de la mort. Gagnez de la vie permanente pour chaque victime jusqu'à un certain niveau. Extrêmement intelligent. + + + Se nourrit de la mort. Gagnez de la vie permanente pour chaque victime jusqu'à un certain niveau. Extrêmement intelligente. + + + Se nourrit de la mort. Gagnez de la vie permanente pour chaque victime jusqu'à un certain niveau. Extrêmement intelligent.\nSPÉCIAL : Conversion PV. + + + Se nourrit de la mort. Gagnez de la vie permanente pour chaque victime jusqu'à un certain niveau. Extrêmement intelligente.\nSPÉCIAL : Conversion PV. + + + Du sang de dragon coule dans vos veines. + + + Du sang de dragon coule dans vos veines. + + + ????? + + + ????? + + + Votre héroïne de base. Bonne dans tous les domaines. + + + Votre héros de base. Bon dans tous les domaines.\nSPÉCIAL : Bouclier du garde. + + + Votre héroïne de base. Bonne dans tous les domaines.\nSPÉCIAL : Bouclier du garde. + + + Un héros audacieux. Statistiques faibles, mais peut infliger des attaques critiques dévastatrices. + + + Une héroïne audacieuse. Statistiques faibles, mais peut infliger des attaques critiques dévastatrices. + + + Un héros audacieux. Statistiques faibles, mais peut infliger des attaques critiques dévastatrices.\nSPÉCIAL : Forme de brume. + + + Une héroïne audacieuse. Statistiques faibles, mais peut infliger des attaques critiques dévastatrices.\nSPÉCIAL : Forme de brume. + + + Un héros pour les économes. Très faible, mais dispose d'un énorme bonus d'or. + + + Une héroïne pour les économes. Très faible, mais dispose d'un énorme bonus d'or. + + + Un héros pour les économes. Très faible, mais dispose d'un énorme bonus d'or.\nSPÉCIAL : Lampe frontale. + + + Une héroïne pour les économes. Très faible, mais dispose d'un énorme bonus d'or.\nSPÉCIAL : Lampe frontale. + + + Un puissant jeteur de sorts. Chaque victime vous offre de la mana. + + + Une puissante jeteuse de sorts. Chaque victime vous offre de la mana. + + + Un puissant jeteur de sorts. Chaque victime vous offre de la mana.\nSPÉCIAL : Tour de sorts. + + + Une puissante jeteuse de sorts. Chaque victime vous offre de la mana.\nSPÉCIAL : Tour de sorts. + + + Un char sur pattes. Ce héros est un dur à cuire. + + + Un char sur pattes. Cette héroïne est une dure à cuire. + + + Reine des barbares + + + Reine des barbares + + + Roi des barbares + + + Roi des barbares + + + Ninja + + + Ninja + + + Hokage + + + Hokage + + + Kleptomage + + + Kleptomage + + + Kleptomage + + + Kleptomage + + + Magelame + + + Magelame + + + Magelame + + + Magelame + + + Liche + + + Liche + + + Reine liche + + + Reine liche + + + Roi liche + + + Roi liche + + + Dracène + + + Dracène + + + Dragon + + + Dragon + + + Traîtresse + + + Traîtresse + + + Traître + + + Traître + + + Chevalière + + + Chevalière + + + Chevalier + + + Chevalier + + + Paladin + + + Paladin + + + Paladin + + + Paladin + + + Canaille + + + Canaille + + + Canaille + + + Canaille + + + Assassine + + + Assassine + + + Assassin + + + Assassin + + + Mineuse + + + Mineuse + + + Mineur + + + Mineur + + + Spéléologue + + + Spéléologue + + + Spéléologue + + + Spéléologue + + + Mage + + + Mage + + + Mage + + + Mage + + + Archimage + + + Archimage + + + Archimage + + + Archimage + + + Barbare + + + Barbare + + + Barbare + + + Barbare + + + Merci d'avoir joué ! + + + Graphismes + + + Graphismes + + + Conception audio et musique + + + Conception audio et musique + + + Musique + + + Musique + + + Marketing et scénario + + + Marketing et scénario + + + Conception audio supplémentaire + + + Conception audio supplémentaire + + + Graphismes d'arrière-plan + + + Graphismes d'arrière-plan + + + Étude commerciale + + + Étude commerciale + + + Remerciements particuliers : Turbo Edition + + + Remerciements particuliers : Turbo Edition + + + Remerciements + + + Remerciements + + + Remerciements supplémentaires + + + Remerciements supplémentaires + + + Merci d'avoir joué ! + + + Total d'enfants + + + Adaptation Mac/Linux par + + + Adaptation Mac/Linux par + + + Équipe d'assurance qualité Mac/Linux + + + Équipe d'assurance qualité Mac/Linux + + + Merci à tous nos fans pour leur soutien ! + + + Merci à tous nos fans pour leur soutien ! + + + Localisation principale par + + + Localisation principale par + + + Localisation supplémentaire et en chinois par + + + Localisation supplémentaire et en chinois par + + + Total d'enfants + + + Temps de jeu + + + Temps de jeu + + + Appuyez sur [Input:0] pour quitter + + + Appuyez sur [Input:0] pour quitter + + + Développé par + + + Développé par + + + Conception et scénario + + + Conception et scénario + + + Programmation + + + Programmation + + + Production + + + Production + + + Zone morte joystick + + + Zone morte joystick + + + Supprimer sauvegarde + + + Supprimer sauvegarde + + + Journal du prince + + + Bien que je sois l'aîné, je ne suis pas l'enfant préféré de mon père. J'ai toujours su qu'il ne me laisserait rien. + + + ... et si je les avais pris pour des monstres ? + + + ... et si je les avais pris pour des monstres ? + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°17 + + + Entrée du journal n°17 + + + J'ai impression de devenir fou. Je suis tombé sur un carnaval dans le château. Avec un clown triste, et tout ! + + + J'ai impression de devenir fou. Je suis tombé sur un carnaval dans le château. Avec un clown triste, et tout ! + + + Un naze, mais j'imagine qu'il ne faut pas être trop exigeant avec ses amis dans un endroit comme celui-ci. + + + Un naze, mais j'imagine qu'il ne faut pas être trop exigeant avec ses amis dans un endroit comme celui-ci. + + + J'ai encore faim. Quelle chance, j'ai encore trouvé des cuisses de poulet ! Dans un lustre ! + + + J'ai encore faim. Quelle chance, j'ai encore trouvé des cuisses de poulet ! Dans un lustre ! + + + Ce château... Parfois je me demande si ce n'est pas juste une grosse blague. + + + Ce château... Parfois je me demande si ce n'est pas juste une grosse blague. + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°18 + + + Entrée du journal n°18 + + + J'ai vaincu la bête de la tour et une fois de plus, j'ai pu sentir la salle du trône perdre une partie de sa puissance. + + + J'ai vaincu la bête de la tour et une fois de plus, j'ai pu sentir la salle du trône perdre une partie de sa puissance. + + + Bien que je sois l'aîné, je ne suis pas l'enfant préféré de mon père. J'ai toujours su qu'il ne me laisserait rien. + + + Mais si je trouve le remède, tout sera différent. + + + Je deviens accro à ce sentiment de victoire ! Je ne me suis jamais senti aussi confiant, aussi fort, aussi... à la maison ! Encore un petit effort et je pourrai remporter ma récompense ! + + + Je deviens accro à ce sentiment de victoire ! Je ne me suis jamais senti aussi confiant, aussi fort, aussi... à la maison ! Encore un petit effort et je pourrai remporter ma récompense ! + + + Je suis si près ! Mon père va être fier ! + + + Je suis si près ! Mon père va être fier ! + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°19 + + + Entrée du journal n°19 + + + Je suis resté devant la porte du donjon plus longtemps que je n'ose l'avouer. + + + Je suis resté devant la porte du donjon plus longtemps que je n'ose l'avouer. + + + Mon courage a fini par me faire défaut quand j'ai aperçu les monstres en dessous. À côté, mes premiers combats étaient de la rigolade. + + + Mon courage a fini par me faire défaut quand j'ai aperçu les monstres en dessous. À côté, mes premiers combats étaient de la rigolade. + + + Je dois être plus fort et me concentrer. Il fait si sombre là-dedans, j'ai peur de me perdre. + + + Je dois être plus fort et me concentrer. Il fait si sombre là-dedans, j'ai peur de me perdre. + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°20 + + + Entrée du journal n°20 + + + Je pensais connaître les ténèbres, mais ici dans le donjon, les ténèbres ont une voix. + + + Je pensais connaître les ténèbres, mais ici dans le donjon, les ténèbres ont une voix. + + + Mais si je trouve le remède, tout sera différent. + + + À sa mort, le vainqueur ne remportera pas moins que le trône ! + + + Elles m'appellent à travers les grilles et dans les moindres recoins. Elles me narguent. + + + Elles m'appellent à travers les grilles et dans les moindres recoins. Elles me narguent. + + + Les ténèbres sont si épaisses qu'on pourrait presque les toucher. Les bêtes y ont élu domicile et se faufilent à travers les couloirs. Je n'ai jamais rien vu d'aussi terrifiant. + + + Les ténèbres sont si épaisses qu'on pourrait presque les toucher. Les bêtes y ont élu domicile et se faufilent à travers les couloirs. Je n'ai jamais rien vu d'aussi terrifiant. + + + Je dois rester prudent et choisir soigneusement mes batailles. Mon esprit belliqueux pourrait me coûter la vie. + + + Je dois rester prudent et choisir soigneusement mes batailles. Mon esprit belliqueux pourrait me coûter la vie. + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°21 + + + Entrée du journal n°21 + + + J'ai réussi ! J'ai vaincu le maître du donjon ! Il ne me reste plus qu'à accéder à la salle du trône ! + + + J'ai réussi ! J'ai vaincu le maître du donjon ! Il ne me reste plus qu'à accéder à la salle du trône ! + + + Après ça, le roi me récompensera pour mon courage et me désignera digne héritier au trône ! + + + Après ça, le roi me récompensera pour mon courage et me désignera digne héritier au trône ! + + + Et pas mes frères et sœurs insipides ! + + + Et pas mes frères et sœurs insipides ! + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°22 + + + Entrée du journal n°22 + + + À sa mort, le vainqueur ne remportera pas moins que le trône ! + + + Quand j'accéderai au sommet, ma femme et mes enfants retrouveront les quartiers royaux, la cité royale où nous serons de nouveau traités avec le respect que nous méritons ! + + + Je m'assieds ici pour les derniers préparatifs. Tout ce qui me sépare du maître de ce château désormais sont les portes dorées. + + + Je m'assieds ici pour les derniers préparatifs. Tout ce qui me sépare du maître de ce château désormais sont les portes dorées. + + + J'ai du mal à réfréner toute cette nervosité qui parcourt mon corps ! Est-ce de la peur ou de l'excitation ? Tout ce que je sais, c'est que mon voyage touche enfin à sa fin ! + + + J'ai du mal à réfréner toute cette nervosité qui parcourt mon corps ! Est-ce de la peur ou de l'excitation ? Tout ce que je sais, c'est que mon voyage touche enfin à sa fin ! + + + J'avais presque oublié pourquoi je suis entré dans ce château à l'origine. Je me souviens maintenant. + + + J'avais presque oublié pourquoi je suis entré dans ce château à l'origine. Je me souviens maintenant. + + + J'ai été plus fort que mes frères et sœurs, je vais sauver le roi et quitter le château grandi. Ma famille recevra les honneurs qu'elle mérite. + + + J'ai été plus fort que mes frères et sœurs, je vais sauver le roi et quitter le château grandi. Ma famille recevra les honneurs qu'elle mérite. + + + Maintenant, je vais pénétrer dans la salle du trône. + + + Maintenant, je vais pénétrer dans la salle du trône. + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°23 + + + Entrée du journal n°23 + + + Je n'ai jamais su quel trésor abritait ce château. Je savais seulement qu'il guérirait le roi. + + + Je n'ai jamais su quel trésor abritait ce château. Je savais seulement qu'il guérirait le roi. + + + Qui aurait cru qu'il s'agirait de la Fontaine de jouvence ? + + + Qui aurait cru qu'il s'agirait de la Fontaine de jouvence ? + + + Je m'attendais à ce qu'un monstre m'accueille sur son perchoir, un ennemi à la force inimaginable ! Il m'aurait fallu puiser toute mon énergie pour le vaincre. + + + Je m'attendais à ce qu'un monstre m'accueille sur son perchoir, un ennemi à la force inimaginable ! Il m'aurait fallu puiser toute mon énergie pour le vaincre. + + + Quand j'accéderai au sommet, ma femme et mes enfants retrouveront les quartiers royaux, la cité royale où nous serons de nouveau traités avec le respect que nous méritons ! + + + Nous n'aurons plus à subir les calomnies et les attaques mesquines de mes cousins ! Les autres ducs devront s'incliner devant notre passage ! Mais bon, je m'emporte... + + + Mais quand je suis entré dans le château, j'ai vu mon père, le roi, sur l'estrade, une coupe à la main. J'ai compris que tout était fini. + + + Mais quand je suis entré dans le château, j'ai vu mon père, le roi, sur l'estrade, une coupe à la main. J'ai compris que tout était fini. + + + Il ne mourrait jamais... + + + Il ne mourrait jamais... + + + ... et je n'hériterais jamais. + + + ... et je n'hériterais jamais. + + + Il n'y a pas de mot pour exprimer ce que je ressens. + + + Il n'y a pas de mot pour exprimer ce que je ressens. + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°24 + + + Entrée du journal n°24 + + + .............................. + + + .............................. + + + .... + + + .... + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°25 + + + Entrée du journal n°25 + + + Nous n'aurons plus à subir les calomnies et les attaques mesquines de mes cousins ! Les autres ducs devront s'incliner devant notre passage ! Mais bon, je m'emporte... + + + Je dois rester concentrer sur mes priorités : conquérir le château. Trouver le remède. Récupérer ma récompense. + + + Ce jour marque le début du reste de l'éternité. + + + Ce jour marque le début du reste de l'éternité. + + + Je n'ai jamais su quel trésor abritait ce château. Je savais seulement qu'il guérirait le roi. + + + Je n'ai jamais su quel trésor abritait ce château. Je savais seulement qu'il guérirait le roi. + + + ... Qui aurait cru qu'il s'agissait de la Fontaine de jouvence ? Le mythe de la vie éternelle. + + + ... Qui aurait cru qu'il s'agissait de la Fontaine de jouvence ? Le mythe de la vie éternelle. + + + Alors que je regardais le corps du roi, je réalisais une chose inévitable : les enfants répondent toujours des péchés de leur père. + + + Alors que je regardais le corps du roi, je réalisais une chose inévitable : les enfants répondent toujours des péchés de leur père. + + + Je suis entré dans ce château comme un épéiste, comme un sauveur... + + + Je suis entré dans ce château comme un épéiste, comme un sauveur... + + + Et tout ce dont j'ai hérité, ce sont des souvenirs d'aventure. + + + Et tout ce dont j'ai hérité, ce sont des souvenirs d'aventure. + + + Je comprends ta colère, mais sache que ce n'est pas moi qui ai ruiné ta famille. + + + Je comprends ta colère, mais sache que ce n'est pas moi qui ai ruiné ta famille. + + + Quand le roi a mis les pieds dans ce château, les coffres royaux ont été vidés par Charon. Ma famille, toutes les familles, avaient perdu l'espoir d'une vie meilleure. + + + Quand le roi a mis les pieds dans ce château, les coffres royaux ont été vidés par Charon. Ma famille, toutes les familles, avaient perdu l'espoir d'une vie meilleure. + + + Et dans mon esprit, seuls le désespoir et la pauvreté ravageraient notre pays. Nous ne pourrions pas retrouver notre vie d'avant. + + + Et dans mon esprit, seuls le désespoir et la pauvreté ravageraient notre pays. Nous ne pourrions pas retrouver notre vie d'avant. + + + À mes enfants et mes petits-enfants, je suis assis ici, impassible, immortel, et je vous attends. + + + À mes enfants et mes petits-enfants, je suis assis ici, impassible, immortel, et je vous attends. + + + Je dois rester concentrer sur mes priorités : conquérir le château. Trouver le remède. Récupérer ma récompense. + + + Journal du prince + + + Johannes + + + Johannes + + + Qu'est-ce que...? C'est une plaisanterie ? + + + Qu'est-ce que...? C'est une plaisanterie ? + + + Des générations et des générations d'ancêtres ont sacrifié leur vie pour être où vous vous trouvez, dernières étapes d'une justice qu'ils voulaient rendre. Et vous arrivez et vous vous moquez de moi ? + + + Des générations et des générations d'ancêtres ont sacrifié leur vie pour être où vous vous trouvez, dernières étapes d'une justice qu'ils voulaient rendre. Et vous arrivez et vous vous moquez de moi ? + + + Très bien, je vais épargner votre ignorance. Commençons ! + + + Très bien, je vais épargner votre ignorance. Commençons ! + + + Johannes + + + Johannes + + + Pourquoi voulez-vous m'affronter ? Combien de fils et de filles ont perdu la vie à cause de votre pathétique soif de vengeance ? + + + Pourquoi voulez-vous m'affronter ? Combien de fils et de filles ont perdu la vie à cause de votre pathétique soif de vengeance ? + + + C'est le roi qui a ruiné votre pays, pas moi ! + + + C'est le roi qui a ruiné votre pays, pas moi ! + + + Il nous a menti. Il disait être blessé, mais seul le temps était une menace pour lui ! + + + Il nous a menti. Il disait être blessé, mais seul le temps était une menace pour lui ! + + + Il a monté ses enfants les uns contre les autres, tout sacrifié pour satisfaire ses désirs les plus égoïstes. Et au bout du compte, il nous a laissés seuls et sans le sou. + + + Il a monté ses enfants les uns contre les autres, tout sacrifié pour satisfaire ses désirs les plus égoïstes. Et au bout du compte, il nous a laissés seuls et sans le sou. + + + J'ai donc choisi la seule option qu'il me restait : j'ai rejeté le roi et mon pays. + + + J'ai donc choisi la seule option qu'il me restait : j'ai rejeté le roi et mon pays. + + + Journal du prince + + + Entrée du journal n°3 + + + Et j'ai choisi une nouvelle famille ! + + + Et j'ai choisi une nouvelle famille ! + + + Johannes + + + Johannes + + + Vous pensez que vous m'avez tué ? + + + Vous pensez que vous m'avez tué ? + + + Je vis depuis plus de mille ans et je vais vivre dix mille ans de plus ! + + + Je vis depuis plus de mille ans et je vais vivre dix mille ans de plus ! + + + Alexandre... Khidr... Ponce de León... + + + Alexandre... Khidr... Ponce de León... + + + Je ne suis pas le premier héros à avoir atteint la Fontaine... + + + Je ne suis pas le premier héros à avoir atteint la Fontaine... + + + Mais je serai le dernier ! + + + Mais je serai le dernier ! + + + Fontaine de jouvence + + + Fontaine de jouvence + + + ... + + + ... + + + Vous m'avez vaincu, mais à quel prix ? + + + Vous m'avez vaincu, mais à quel prix ? + + + Entrée du journal n°3 + + + J'ai payé mon dû et pénétré comme il faut dans le château. Ce diable de Charon m'a pris tout ce que j'avais en guise de paiement. + + + J'ai peut-être tué le roi, mais après qu'il ait trahi son peuple. + + + J'ai peut-être tué le roi, mais après qu'il ait trahi son peuple. + + + Vous vous demandez où se situe la justice ? + + + Vous vous demandez où se situe la justice ? + + + Au final, nous sommes tous coupables de la même faute. Regardez vos ancêtres. Tel est le prix à payer pour obtenir une loyauté incontestable. + + + Au final, nous sommes tous coupables de la même faute. Regardez vos ancêtres. Tel est le prix à payer pour obtenir une loyauté incontestable. + + + ... + + + ... + + + ... + + + ... + + + Le soleil... + + + Le soleil... + + + J'avais oublié ce que ça faisait... + + + J'avais oublié ce que ça faisait... + + + J'ai payé mon dû et pénétré comme il faut dans le château. Ce diable de Charon m'a pris tout ce que j'avais en guise de paiement. + + + Il a même pillé mes coffres personnels ! Ma femme, mes enfants et moi-même n'avons plus rien ! + + + Il a même pillé mes coffres personnels ! Ma femme, mes enfants et moi-même n'avons plus rien ! + + + Journal du prince + + + Entrée du journal n°1 + + + Il affirme que c'est le prix à payer pour tous ceux qui osent s'aventurer dans les profondeurs du château. Rien de plus juste selon lui. + + + Il affirme que c'est le prix à payer pour tous ceux qui osent s'aventurer dans les profondeurs du château. Rien de plus juste selon lui. + + + C'est juste car tous ceux qui y sont entrés n'en sont jamais ressortis. Je vais changer ça. + + + C'est juste car tous ceux qui y sont entrés n'en sont jamais ressortis. Je vais changer ça. + + + Je serai victorieux ! Personne ne manie l'épée aussi bien que moi, pas même mes frères et sœurs. + + + Je serai victorieux ! Personne ne manie l'épée aussi bien que moi, pas même mes frères et sœurs. + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°4 + + + Entrée du journal n°4 + + + Tout est bizarre dans ce château. Je ne sais pas dans quelle direction aller. Et il n'y a ni étoiles ni soleil pour me guider. + + + Tout est bizarre dans ce château. Je ne sais pas dans quelle direction aller. Et il n'y a ni étoiles ni soleil pour me guider. + + + Je reviens sans cesse sur mes pas et je dois rigoureusement noter ma progression de peur de tourner en rond. + + + Je reviens sans cesse sur mes pas et je dois rigoureusement noter ma progression de peur de tourner en rond. + + + Les cartes que j'ai volées aux cadavres des aventures précédentes sont incroyablement imprécises. On dirait qu'elles décrivent un autre château ! + + + Les cartes que j'ai volées aux cadavres des aventures précédentes sont incroyablement imprécises. On dirait qu'elles décrivent un autre château ! + + + C'est comme si cet endroit agissait sur les esprits... + + + C'est comme si cet endroit agissait sur les esprits... + + + Ou est-ce que les pierres bougent vraiment sous mes pieds ? + + + Ou est-ce que les pierres bougent vraiment sous mes pieds ? + + + Entrée du journal n°1 + + + Traître ! Un assassin a blessé mon père, le roi ! + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°5 + + + Entrée du journal n°5 + + + Je ne peux pas sortir par la porte de devant, mais ce n'est pas grave. Je suis déterminé à défendre ma cause et je ne baisserai pas les bras ! + + + Je ne peux pas sortir par la porte de devant, mais ce n'est pas grave. Je suis déterminé à défendre ma cause et je ne baisserai pas les bras ! + + + Jusqu'ici, aucune des cartes que j'ai trouvées ne correspond à la mienne. + + + Jusqu'ici, aucune des cartes que j'ai trouvées ne correspond à la mienne. + + + Mais en les comparant dans leur ensemble, je pense avoir découvert une sorte de modèle. Il semblerait que la forêt soit toujours à droite, la tour au-dessus... + + + Mais en les comparant dans leur ensemble, je pense avoir découvert une sorte de modèle. Il semblerait que la forêt soit toujours à droite, la tour au-dessus... + + + Et dessous ? J'espère ne pas avoir à le découvrir... + + + Et dessous ? J'espère ne pas avoir à le découvrir... + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°6 + + + Entrée du journal n°6 + + + Je n'ai jamais aimé l'obscurité. Je préfère rencontrer mes ennemis à l'extérieur, en plein jour. + + + Je n'ai jamais aimé l'obscurité. Je préfère rencontrer mes ennemis à l'extérieur, en plein jour. + + + Et pourtant aujourd'hui je dois affronter ces tristes potences à tâtons avec une main tendue et l'autre sur la poignée de mon arme. Qui sait quelle atrocité se cache au détour d'un coin de mur. + + + Et pourtant aujourd'hui je dois affronter ces tristes potences à tâtons avec une main tendue et l'autre sur la poignée de mon arme. Qui sait quelle atrocité se cache au détour d'un coin de mur. + + + Traître ! Un assassin a blessé mon père, le roi ! + + + Pour ramener l'ordre dans le royaume, il a envoyé mes frères et sœurs et moi dans une quête pour le sauver ! Ensemble, nous allons traverser les bois hantés et pénétrer dans le Château Hamson. + + + Je suis le meilleur épéiste de la région mais j'ai du mal à tenir ces démons éloignés. + + + Je suis le meilleur épéiste de la région mais j'ai du mal à tenir ces démons éloignés. + + + Mes frères et sœurs devraient me remercier de les avoir précédés. C'est du pain béni pour eux. Ils n'auraient jamais eu le courage d'affronter ces salles. + + + Mes frères et sœurs devraient me remercier de les avoir précédés. C'est du pain béni pour eux. Ils n'auraient jamais eu le courage d'affronter ces salles. + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°7 + + + Entrée du journal n°7 + + + Il fait encore nuit. Une lune mélancolique se reflète dans toutes les fenêtres, pourtant je suis sûr d'être ici depuis plus d'un jour. + + + Il fait encore nuit. Une lune mélancolique se reflète dans toutes les fenêtres, pourtant je suis sûr d'être ici depuis plus d'un jour. + + + Ça doit venir de l'adrénaline. Je ne me suis jamais senti aussi fort ni paradoxalement aussi en danger. C'est grisant de charger à travers ces pièces et d'anéantir les ennemis les uns après les autres. + + + Ça doit venir de l'adrénaline. Je ne me suis jamais senti aussi fort ni paradoxalement aussi en danger. C'est grisant de charger à travers ces pièces et d'anéantir les ennemis les uns après les autres. + + + Les ennemis de ce château ont l'air d'être faits pour moi. Ils m'entraînent, me guident, me regardent. + + + Les ennemis de ce château ont l'air d'être faits pour moi. Ils m'entraînent, me guident, me regardent. + + + Ça peut sembler dément, mais si ce château peut sentir les gens qui l'occupent, j'ai peur qu'il n'ait aussi de mauvaises intentions. Si mes suppositions sont avérées, ces salles pourraient constituer un piège et se refermer sur moi. + + + Ça peut sembler dément, mais si ce château peut sentir les gens qui l'occupent, j'ai peur qu'il n'ait aussi de mauvaises intentions. Si mes suppositions sont avérées, ces salles pourraient constituer un piège et se refermer sur moi. + + + Je dois rester attentif. + + + Je dois rester attentif. + + + Journal du prince + + + Journal du prince + + + Pour ramener l'ordre dans le royaume, il a envoyé mes frères et sœurs et moi dans une quête pour le sauver ! Ensemble, nous allons traverser les bois hantés et pénétrer dans le Château Hamson. + + + Ce château hanté se dresse à l'orée de la forêt depuis des temps immémoriaux. Il renfermerait un objet capable de soigner tous les maux. + + + Entrée du journal n°8 + + + Entrée du journal n°8 + + + Au vu du nombre d'aventuriers morts que j'ai croisés dans ces salles, j'en arrive aux conclusions suivantes : + + + Au vu du nombre d'aventuriers morts que j'ai croisés dans ces salles, j'en arrive aux conclusions suivantes : + + + 1 : beaucoup n'ont pas pris assez de provisions avec eux et on dû mourir de faim. Je commence moi-même à en manquer et je vais devoir en trouver de nouvelles. + + + 1 : beaucoup n'ont pas pris assez de provisions avec eux et on dû mourir de faim. Je commence moi-même à en manquer et je vais devoir en trouver de nouvelles. + + + 2 : beaucoup n'ont plus d'habits, ce qui explique que les zombies soient vêtus. + + + 2 : beaucoup n'ont plus d'habits, ce qui explique que les zombies soient vêtus. + + + 3 : personne n'est allé aussi loin que moi car je n'ai croisé aucun cadavre depuis une heure. + + + 3 : personne n'est allé aussi loin que moi car je n'ai croisé aucun cadavre depuis une heure. + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°9 + + + Entrée du journal n°9 + + + La porte qui mène à la salle du trône me rend fou ! C'est derrière elle que repose le salut du roi et ma récompense, mais elle se tient au milieu de l'entrée du château, en silence, à me narguer. + + + La porte qui mène à la salle du trône me rend fou ! C'est derrière elle que repose le salut du roi et ma récompense, mais elle se tient au milieu de l'entrée du château, en silence, à me narguer. + + + J'ai essayé de la pousser, de frapper, de crier "Sésame, ouvre-toi !", rien ne marche. + + + J'ai essayé de la pousser, de frapper, de crier "Sésame, ouvre-toi !", rien ne marche. + + + Les portes sont ornées d'icônes. L'une d'elles ressemble à une bête que j'ai esquivée dans les profondeurs du château. Il y a peut-être un lien... + + + Les portes sont ornées d'icônes. L'une d'elles ressemble à une bête que j'ai esquivée dans les profondeurs du château. Il y a peut-être un lien... + + + Ce château hanté se dresse à l'orée de la forêt depuis des temps immémoriaux. Il renfermerait un objet capable de soigner tous les maux. + + + Ce soir, je prendrai de l'avance sur mes frères et sœurs et entamerai ma quête pendant qu'ils dorment encore. + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°10 + + + Entrée du journal n°10 + + + Les emblèmes sur les portes du château constituent un indice ! J'ai tué la bête géante qui correspond à l'une des icônes, et j'ai senti quelque chose bouger derrière les portes de la salle du trône. + + + Les emblèmes sur les portes du château constituent un indice ! J'ai tué la bête géante qui correspond à l'une des icônes, et j'ai senti quelque chose bouger derrière les portes de la salle du trône. + + + Comme dans un rêve, je pouvais voir l'emblème sur la porte briller dans l'œil de mon esprit. + + + Comme dans un rêve, je pouvais voir l'emblème sur la porte briller dans l'œil de mon esprit. + + + Une expérience extra-corporelle assez incroyable. + + + Une expérience extra-corporelle assez incroyable. + + + Au moins, je sais que je suis sur le bon chemin. Mais je dois accélérer le rythme ou le roi risque à tout moment de succomber à ses blessures... + + + Au moins, je sais que je suis sur le bon chemin. Mais je dois accélérer le rythme ou le roi risque à tout moment de succomber à ses blessures... + + + Toutefois, je dois d'abord me reposer. Demain, je pénètre dans la Forêt. + + + Toutefois, je dois d'abord me reposer. Demain, je pénètre dans la Forêt. + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°11 + + + Entrée du journal n°11 + + + Cette forêt ne ressemble à rien de ce que j'ai vu avant. Elle est à la fois paisible et effrayante. L'herbe sur laquelle je me tiens est abondante, mais à côté de moi s'ouvre un gouffre si gigantesque et si profond que j'ai peur qu'il m'aspire ! + + + Cette forêt ne ressemble à rien de ce que j'ai vu avant. Elle est à la fois paisible et effrayante. L'herbe sur laquelle je me tiens est abondante, mais à côté de moi s'ouvre un gouffre si gigantesque et si profond que j'ai peur qu'il m'aspire ! + + + Ce soir, je prendrai de l'avance sur mes frères et sœurs et entamerai ma quête pendant qu'ils dorment encore. + + + Échouer lors de cette quête serait faire honte à mon nom. + + + Je n'ai toujours pas entendu l'écho de la pierre que j'y ai jetée plus tôt. Un seul faux pas et ma chute serait éternelle. Cette pensée fait froid dans le dos ! + + + Je n'ai toujours pas entendu l'écho de la pierre que j'y ai jetée plus tôt. Un seul faux pas et ma chute serait éternelle. Cette pensée fait froid dans le dos ! + + + Passer l'éternité dans les ténèbres me semble bien plus effrayant que n'importe quelle bête que j'ai affrontée jusqu'ici. Si je tombe, qu'est-ce qui me tuerait en premier ? La faim ou moi-même ? + + + Passer l'éternité dans les ténèbres me semble bien plus effrayant que n'importe quelle bête que j'ai affrontée jusqu'ici. Si je tombe, qu'est-ce qui me tuerait en premier ? La faim ou moi-même ? + + + Aparté : désormais j'utilise la faille de la Forêt comme toilettes personnelles. Je me demande si je fais caca dans une autre dimension... + + + Aparté : désormais j'utilise la faille de la Forêt comme toilettes personnelles. Je me demande si je fais caca dans une autre dimension... + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°12 + + + Entrée du journal n°12 + + + J'ai trouvé une solution à mon problème de faim. La Forêt abrite un tas de délicieux champignons. + + + J'ai trouvé une solution à mon problème de faim. La Forêt abrite un tas de délicieux champignons. + + + Et au milieu de ces champignons, des cuisses de poulet ! Mais aussi des pièces d'or et des fioles d'eau pétillante... J'ai tranché un tronc d'arbre plus tôt, et un sac rempli d'argent en est tombé ! + + + Et au milieu de ces champignons, des cuisses de poulet ! Mais aussi des pièces d'or et des fioles d'eau pétillante... J'ai tranché un tronc d'arbre plus tôt, et un sac rempli d'argent en est tombé ! + + + Parfois, j'ai l'impression de devenir fou... + + + Parfois, j'ai l'impression de devenir fou... + + + ... Et... que se passe-t-il avec la lune ? Elle est ÉNORME ! + + + ... Et... que se passe-t-il avec la lune ? Elle est ÉNORME ! + + + Journal du prince + + + Journal du prince + + + Échouer lors de cette quête serait faire honte à mon nom. + + + Journal du prince + + + Entrée du journal n°13 + + + Entrée du journal n°13 + + + J'ai tué la bête de la Forêt, et j'ai senti que la salle du trône faiblissait de nouveau. + + + J'ai tué la bête de la Forêt, et j'ai senti que la salle du trône faiblissait de nouveau. + + + Jusqu'ici mon instinct s'est révélé exact. Chaque aile du château abrite sa propre bête qui la garde. Est-ce pour tester la motivation des visiteurs ? Si c'est le cas, je ne peux pas échouer ! Plus je prends de risques, plus je m'endurcis ! + + + Jusqu'ici mon instinct s'est révélé exact. Chaque aile du château abrite sa propre bête qui la garde. Est-ce pour tester la motivation des visiteurs ? Si c'est le cas, je ne peux pas échouer ! Plus je prends de risques, plus je m'endurcis ! + + + Demain je ratisse la tour ! Je suis lancé ! + + + Demain je ratisse la tour ! Je suis lancé ! + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°14 + + + Entrée du journal n°14 + + + J'ai méthodiquement éliminé les démons de ces pièces lors de ma quête pour tuer le prochain garde, mais je perds la notion du temps... entre autres... + + + J'ai méthodiquement éliminé les démons de ces pièces lors de ma quête pour tuer le prochain garde, mais je perds la notion du temps... entre autres... + + + Quand je suis entré dans la tour, j'ai senti que le temps s'immobilisait. Ou peut-être était-ce à cause du vertige ? Je n'ai jamais aimé prendre de la hauteur... + + + Quand je suis entré dans la tour, j'ai senti que le temps s'immobilisait. Ou peut-être était-ce à cause du vertige ? Je n'ai jamais aimé prendre de la hauteur... + + + J'ai beaucoup de mal à me souvenir de mon passé... + + + J'ai beaucoup de mal à me souvenir de mon passé... + + + Journal du prince + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°2 + + + Entrée du journal n°15 + + + Entrée du journal n°15 + + + Je me souviens avoir été un aventurier célèbre. Je dépassais tous mes frères avec mes prouesses en arts martiaux. Ça, j'en suis sûr. Ils passaient leurs journées la tête plongée dans les livres quand moi je tuais des brigands et des monstres. + + + Je me souviens avoir été un aventurier célèbre. Je dépassais tous mes frères avec mes prouesses en arts martiaux. Ça, j'en suis sûr. Ils passaient leurs journées la tête plongée dans les livres quand moi je tuais des brigands et des monstres. + + + Je me suis toujours demandé pourquoi mon père les préférait à moi. Ce n'est pas plutôt l'inverse dans les contes de fées ? + + + Je me suis toujours demandé pourquoi mon père les préférait à moi. Ce n'est pas plutôt l'inverse dans les contes de fées ? + + + La fortune sourit aux audacieux, pas aux intellectuels insipides... ou quelque chose comme ça. + + + La fortune sourit aux audacieux, pas aux intellectuels insipides... ou quelque chose comme ça. + + + J'adorerais voir mes frères essayer de se montrer plus malins avec mon épée dans la figure ! + + + J'adorerais voir mes frères essayer de se montrer plus malins avec mon épée dans la figure ! + + + Journal du prince + + + Journal du prince + + + Entrée du journal n°16 + + + Entrée du journal n°16 + + + Et si plusieurs années avaient passé depuis que j'ai pénétré ces murs ? J'ai de plus en plus de facilité à tuer les monstres, mais on dirait qu'une éternité s'est écoulée. + + + Et si plusieurs années avaient passé depuis que j'ai pénétré ces murs ? J'ai de plus en plus de facilité à tuer les monstres, mais on dirait qu'une éternité s'est écoulée. + + + Je ne sais même plus à quoi ressemblent mes proches... + + + Je ne sais même plus à quoi ressemblent mes proches... + + + Et s'ils croient que j'ai échoué ? Et si l'un de mes frères avait trouvé le remède avant moi ? + + + Et s'ils croient que j'ai échoué ? Et si l'un de mes frères avait trouvé le remède avant moi ? + + + Entrée du journal n°2 + + + Entrée n° + + + Entrée n° + + + Château Hamson + + + Château Hamson + + + Terre des Ténèbres + + + Terre des Ténèbres + + + Forêt Abkhazia + + + Forêt Abkhazia + + + Le Maya + + + Le Maya + + + Sélectionnez une catégorie + + + Rune nécessaire + + + Rune nécessaire + + + Info Achat ici + + + Info Achat ici + + + {0} pour déverrouiller + + + {0} pour déverrouiller + + + Rune + + + Rune + + + Sélectionnez une catégorie + + + Instructions + + + Instructions + + + [Input:0] sélectionner/équiper + + + [Input:0] sélectionner/équiper + + + [Input:2] annuler/fermer menu + + + [Input:2] annuler/fermer menu + + + Touches directionnelles pour parcourir + + + Touches directionnelles pour parcourir + + + [Button:LeftStick] pour parcourir + + + [Button:LeftStick] pour parcourir + + + Tué + + + Tué + + + Appuyez sur [Input:0] pour quitter + + + Appuyez sur [Input:0] pour quitter + + + Squelette + + + Bidule + + + Papa Éclair + + + Papa Éclair + + + Grand Éclair, roi d'Éclairance + + + Grand Éclair, roi d'Éclairance + + + Crocoffre + + + Crocoffre + + + Mangecoffre + + + Mangecoffre + + + Miacoffre + + + Miacoffre + + + Coffre suprême + + + Coffre suprême + + + Barbatos + + + Barbatos + + + Stolas + + + Stolas + + + Berith + + + Berith + + + Amon + + + Amon + + + Bidule + + + Hérodote + + + Focalor + + + Focalor + + + Halphas + + + Halphas + + + Néo Khidr + + + Néo Khidr + + + Alexandre IV + + + Alexandre IV + + + Astrodote + + + Astrodote + + + Ponce de Fréon + + + Ponce de Fréon + + + Les Frèrohannes + + + Les Frèrohannes + + + Lance-feu + + + Lance-feu + + + Le Gardien + + + Le Gardien + + + L'Infini + + + L'Infini + + + Hérodote + + + Ferri + + + L'Oublié + + + L'Oublié + + + Le Maudit + + + Le Maudit + + + Le Factionnaire + + + Le Factionnaire + + + Le Traître + + + Le Traître + + + La Fontaine + + + La Fontaine + + + Berith et Halphas + + + Berith et Halphas + + + Barbatos et Amon + + + Barbatos et Amon + + + Stolas et Focalor + + + Stolas et Focalor + + + Ferri + + + Ferrus + + + Ferrus + + + Ferror + + + Ferror + + + Panthéon + + + Panthéon + + + Sorterre + + + Sorterre + + + Graviterre + + + Graviterre + + + Terrasaure + + + Terrasaure + + + Flammi + + + Flammi + + + Squelette + + + M. Os + + + Incendor + + + Incendor + + + Brasar + + + Brasar + + + Magisol + + + Magisol + + + Glaçar + + + Glaçar + + + Congélor + + + Congélor + + + Picaglace + + + Picaglace + + + Magiscure + + + Magiscure + + + Sentinelle + + + Sentinelle + + + Pupille + + + Pupille + + + Visionnaire + + + Visionnaire + + + M. Os + + + M. Carcasse + + + Khidr + + + Khidr + + + Fureur + + + Fureur + + + Rage + + + Rage + + + Colère + + + Colère + + + Alexandre + + + Alexandre + + + Garde balèze + + + Garde balèze + + + Garde mastoc + + + Garde mastoc + + + Grand garde + + + Grand garde + + + Guetteur + + + Guetteur + + + Picpic + + + Picpic + + + M. Carcasse + + + Chevalier noir + + + Pico + + + Pico + + + Picdur + + + Picdur + + + Gropic + + + Gropic + + + Chevalier gris + + + Chevalier gris + + + Baron gris + + + Baron gris + + + Gridiator + + + Gridiator + + + Gripion + + + Gripion + + + Louvo + + + Louvo + + + Louvar + + + Louvar + + + Grolou + + + Grolou + + + Chevalier noir + + + Gardien noir + + + Lousaure + + + Lousaure + + + Zombie + + + Zombie + + + Zombar + + + Zombar + + + Zombishnu + + + Zombishnu + + + Mégazombie + + + Mégazombie + + + Énergon + + + Énergon + + + Mastertron + + + Mastertron + + + Voltron + + + Voltron + + + Prime + + + Prime + + + Ninjo + + + Ninjo + + + Gardien noir + + + Seigneur noir + + + Ninpo + + + Ninpo + + + Ninpojo + + + Ninpojo + + + Maître ninja + + + Maître ninja + + + Bouton + + + Bouton + + + Miniplante + + + Miniplante + + + Fleurone + + + Fleurone + + + Charite + + + Charite + + + Pyrite + + + Pyrite + + + Infernite + + + Infernite + + + Ponce de León + + + Ponce de León + + + Seigneur noir + + + Botis + + + Piège à pointes + + + Piège à pointes + + + Archer + + + Archer + + + Rôdeur + + + Rôdeur + + + Sniper + + + Sniper + + + Tireur d'élite + + + Tireur d'élite + + + Johannes + + + Johannes + + + La Fontaine + + + La Fontaine + + + Fontaine de jouvence + + + Fontaine de jouvence + + + Maudivas + + + Maudivas + + + Mauditrait + + + Mauditrait + + + Botis + + + Truc + + + Maudichappe + + + Maudichappe + + + Sallos + + + Sallos + + + Starlo + + + Starlo + + + Starlite + + + Starlite + + + Starmax + + + Starmax + + + Mégastar + + + Mégastar + + + Kentucky + + + Kentucky + + + Frit + + + Frit + + + Poulet + + + Poulet + + + Poulet ultime + + + Poulet ultime + + + Truc + + + Machin + + + Abri de garde + + + Abri de garde + + + Abri de garde XL + + + Abri de garde XL + + + Abri-garde 2000 + + + Abri-garde 2000 + + + Méga abri + + + Méga abri + + + Cheval sans tête + + + Cheval sans tête + + + Hu dada + + + Hu dada + + + Doux bijou + + + Doux bijou + + + Mon petit poney + + + Mon petit poney + + + Bribri + + + Bribri + + + M. Éclair + + + M. Éclair + + + Machin + + + Saut + + + Malédiction + + + Malédiction + + + Grâce + + + Grâce + + + Frais d'architecte + + + Frais d'architecte + + + NP + Bonus + + + NP + Bonus + + + Saut + + + Course + + + Course + + + Vampire + + + Vampire + + + Ciel + + + Ciel + + + Siphon + + + Siphon + + + Équilibre + + + Équilibre + + + Vengeance + + + Vengeance + + + Cagnotte + + + Cagnotte + + + Accélération + + + Accélération + + + de l'écuyer + + + de l'assassin + + + de l'assassine + + + du sage + + + de la sage + + + de sang + + + de sang + + + de punition + + + de punition + + + des saints + + + des saints + + + des ténèbres + + + des ténèbres + + + de l'écuyère + + + en argent + + + en argent + + + du garde + + + du garde + + + de l'empire + + + de l'empire + + + du roi + + + de la reine + + + du chevalier + + + de la chevalière + + + du rôdeur + + + de la rôdeuse + + + du ciel + + + du ciel + + + du dragon + + + de la dracène + + + Épée + + + Épée + + + Cape + + + Cape + + + Bracelets + + + Bracelets + + + Heaume + + + Heaume + + + Plastron + + + Plastron + + + Aucun + + + Aucun + + + Épée + + + Épée + + + Cape + + + Cape + + + Bracelets + + + Bracelets + + + Heaume + + + Heaume + + + Poitrine + + + Poitrine + + + Aucun + + + Aucun + + + Vous offre la capacité de sauter en l'air. Cumulez les runes pour effectuer des sauts multiples. + + + Plus les ennemis sont forts, plus le butin est important. Cumulez les runes pour affronter des ennemis encore plus forts. + + + Plus les ennemis sont forts, plus le butin est important. Cumulez les runes pour affronter des ennemis encore plus forts. + + + Les ennemis sont plus faibles, mais le butin est moindre. Cumulez les runes pour ralentir encore plus l'évolution des ennemis. + + + Les ennemis sont plus faibles, mais le butin est moindre. Cumulez les runes pour ralentir encore plus l'évolution des ennemis. + + + Vous offre la capacité de sauter en l'air. Cumulez les runes pour effectuer des sauts multiples. + + + Obtenez la capacité d'accélérer pendant de courtes distances. Cumulez les runes pour effectuer des accélérations multiples. + + + Obtenez la capacité d'accélérer pendant de courtes distances. Cumulez les runes pour effectuer des accélérations multiples. + + + Tuer des ennemis permet d'absorber leur vie. Cumulez les runes pour absorber plus de vie. + + + Tuer des ennemis permet d'absorber leur vie. Cumulez les runes pour absorber plus de vie. + + + Obtenez le pouvoir de voler. Cumulez les runes pour voler plus longtemps. + + + Obtenez le pouvoir de voler. Cumulez les runes pour voler plus longtemps. + + + Volez de la mana aux ennemis tués. Cumulez les runes pour obtenir plus de mana. + + + Volez de la mana aux ennemis tués. Cumulez les runes pour obtenir plus de mana. + + + Tuer des ennemis octroie des PV et des MP. Cumulez les runes pour obtenir plus de PV/MP. + + + Tuer des ennemis octroie des PV et des MP. Cumulez les runes pour obtenir plus de PV/MP. + + + Permet de renvoyer les dégâts infligés par les ennemis. Cumulez les runes pour renvoyer plus de dégâts. + + + Permet de renvoyer les dégâts infligés par les ennemis. Cumulez les runes pour renvoyer plus de dégâts. + + + Augmentez la quantité d'or obtenue grâce aux pièces. Cumulez les runes pour obtenir encore plus d'or. + + + Augmentez la quantité d'or obtenue grâce aux pièces. Cumulez les runes pour obtenir encore plus d'or. + + + Augmentez votre vitesse de déplacement de base. Cumulez les runes pour aller encore plus vite. + + + Augmentez votre vitesse de déplacement de base. Cumulez les runes pour aller encore plus vite. + + + Les ennemis sont plus redoutables. + + + Les ennemis sont plus redoutables. + + + Les ennemis sont plus faibles. + + + Les ennemis sont plus faibles. + + + Appuyez sur [Input:10] une fois en l'air. + + + Appuyez sur [Input:10] une fois en l'air. + + + [Input:14] ou [Input:15] pour accélérer. + + + [Input:14] ou [Input:15] pour accélérer. + + + Tuez des ennemis pour récupérer de la vie. + + + Tuez des ennemis pour récupérer de la vie. + + + Appuyez sur [Input:10] une fois en l'air. + + + Appuyez sur [Input:10] une fois en l'air. + + + Tuez des ennemis pour récupérer de la mana. + + + Tuez des ennemis pour récupérer de la mana. + + + Tuez des ennemis pour récupérer de la vie et de la mana. + + + Tuez des ennemis pour récupérer de la vie et de la mana. + + + Dégâts renvoyés à l'ennemi. + + + Dégâts renvoyés à l'ennemi. + + + Les pièces donnent plus d'or. + + + Les pièces donnent plus d'or. + + + Déplacez-vous plus vite. + + + Déplacez-vous plus vite. + + + Chance de critique + + + Accélération aérienne + + + Accélération aérienne + + + Blocage + + + Blocage + + + Lévitation + + + Lévitation + + + Peut attaquer les projectiles + + + Peut attaquer les projectiles + + + Vol + + + Vol + + + Vitesse de déplacement + + + Vitesse de déplacement + + + Aucun + + + Aucun + + + Chance de critique + + + Dégâts critiques + + + Dégâts critiques + + + Vampirisme + + + Vampirisme + + + Bonus d'or + + + Bonus d'or + + + Siphon + + + Siphon + + + Bonus d'EXP + + + Bonus d'EXP + + + Attaque aérienne + + + Attaque aérienne + + + Saut aérien + + + Saut aérien + + + Renvoi des dégâts + + + Renvoi des dégâts + + + Cagnotte augmentée de {0} % + + + Cagnotte augmentée de {0} % + + + Les ennemis démarrent {0} niveaux au-dessus + + + Les ennemis démarrent {0} niveaux au-dessus + + + Évolution des ennemis plus lente de {0} unités + + + Évolution des ennemis plus lente de {0} unités + + + Évolution des ennemis plus lente d' {0} unité + + + Évolution des ennemis plus lente d' {0} unité + + + Sautez en l'air {0} fois + + + Sautez en l'air {0} fois + + + Sautez en l'air {0} fois + + + Sautez en l'air {0} fois + + + Accélérez {0} fois + + + Accélérez {0} fois + + + Accélérez {0} fois + + + Accélérez {0} fois + + + Récupérez {0} PV par victime + + + Récupérez {0} PV par victime + + + Volez pendant {0} secondes + + + Volez pendant {0} secondes + + + Volez pendant {0} seconde + + + Volez pendant {0} seconde + + + Récupérez {0} MP par victime + + + Récupérez {0} MP par victime + + + PV mana + + + PV mana + + + Renvoyez {0} % de dégâts par coup reçu + + + Renvoyez {0} % de dégâts par coup reçu + + + L'or trouvé vaut {0} % de plus + + + L'or trouvé vaut {0} % de plus + + + Déplacez-vous {0} % plus vite + + + Déplacez-vous {0} % plus vite + + + Quitter Rogue Legacy + + + Quitter Rogue Legacy + + + Appuyez sur [Input:0] pour continuer + + + Appuyez sur [Input:0] pour continuer + + + Le soleil... J'avais oublié ce que ça faisait... + + + Le soleil... J'avais oublié ce que ça faisait... + + + {0} a été tué par {1} + + + {0} a été tuée par {1} + + + Appuyez sur [Input:0] pour continuer + + + Appuyez sur [Input:0] pour continuer + + + {0} a été tué par {1} + + + {0} a été tuée par {1} + + + {0} a été tué par un {1} + + + {0} a été tuée par un {1} + + + {0} a été liquidé par un projectile + + + {0} a été liquidée par un projectile + + + {0} a glissé et s'est empalé sur des pics + + + {0} a glissé et s'est empalée sur des pics + + + {0} a été tué + + + {0} a été tuée + + + {0}, dernières paroles + + + {0}, dernières paroles + + + [Input:0] pour continuer + + + [Input:0] pour continuer + + + PV augmentés + + + PV augmentés + + + MP augmentés + + + MP augmentés + + + Force augmentée + + + Force augmentée + + + Dégâts magiques augmentés + + + Dégâts magiques augmentés + + + Armure augmentée + + + Armure augmentée + + + Capacité de transport augmentée + + + Capacité de transport augmentée + + + Médaillon obtenu ! + + + Médaillon obtenu ! + + + Vous avez obtenu un médaillon ! + + + Vous avez obtenu un médaillon ! + + + La Forêt est toujours à droite du château. + + + Sky runes let you fly by pressing + + + while in the air. + + + Les runes Ciel permettent de voler en appuyant sur [Input:10] une fois en l'air. + + + Les runes Ciel permettent de voler en appuyant sur [Input:10] une fois en l'air. + + + Les runes Vampirisme et Siphon sont très puissantes quand elles sont associées. + + + Les runes Vampirisme et Siphon sont très puissantes quand elles sont associées. + + + Maîtriser les runes de mobilité rend très fort. + + + Maîtriser les runes de mobilité rend très fort. + + + Agrandissez le manoir. On ne sait jamais quelles nouvelles capacités pourraient apparaître. + + + Agrandissez le manoir. On ne sait jamais quelles nouvelles capacités pourraient apparaître. + + + Toutes les classes peuvent être améliorées grâce à des capacités de classe uniques. + + + Toutes les classes peuvent être améliorées grâce à des capacités de classe uniques. + + + Unlocked class abilities can be activated with + + + Les capacités de classe peuvent être activées avec [Input:13] + + + Les capacités de classe peuvent être activées avec [Input:13] + + + Améliorez vos classes rapidement pour obtenir des capacités de classe puissantes. + + + Améliorez vos classes rapidement pour obtenir des capacités de classe puissantes. + + + Si une pièce pose problème, essayez de la contourner. + + + Si une pièce pose problème, essayez de la contourner. + + + Acheter de l'équipement améliore rapidement vos statistiques. + + + Acheter de l'équipement améliore rapidement vos statistiques. + + + Acheter de l'équipement coûte moins cher que d'améliorer vos stats de base. + + + Acheter de l'équipement coûte moins cher que d'améliorer vos stats de base. + + + La Forêt est toujours à droite du château. + + + Le Maya est toujours en haut du château. + + + Vous auriez dû choisir l'autre enfant. + + + Vous auriez dû choisir l'autre enfant. + + + Les runes sont puissantes. Équipez-les avec l'enchanteresse et n'oubliez pas de les utiliser ! + + + Les runes sont puissantes. Équipez-les avec l'enchanteresse et n'oubliez pas de les utiliser ! + + + Apprenez les nuances de vos sorts pour maximiser leur potentiel. + + + Apprenez les nuances de vos sorts pour maximiser leur potentiel. + + + Essayez de frapper les ennemis du bout de votre hache pour les toucher plusieurs fois. + + + Essayez de frapper les ennemis du bout de votre hache pour les toucher plusieurs fois. + + + Évitez de ramasser les orbes multidirectionnels lancés pour maximiser les dégâts. + + + Évitez de ramasser les orbes multidirectionnels lancés pour maximiser les dégâts. + + + Évitez les chakrams quand ils reviennent vers vous pour maximiser leurs dégâts. + + + Évitez les chakrams quand ils reviennent vers vous pour maximiser leurs dégâts. + + + Utilisez la mana pour tuer les ennemis plutôt que pour subir des dégâts inutiles. + + + Utilisez la mana pour tuer les ennemis plutôt que pour subir des dégâts inutiles. + + + Connaître les tics des ennemis est essentiel pour survivre dans le château. + + + Connaître les tics des ennemis est essentiel pour survivre dans le château. + + + Les pièges à pointes distinguent les morts des vivants. + + + Les pièges à pointes distinguent les morts des vivants. + + + Appuyez sur [Input:9] pour afficher la carte. + + + Appuyez sur [Input:9] pour afficher la carte. + + + Le Maya est toujours en haut du château. + + + Les Ténèbres sont toujours en bas du château. + + + Les coffres magiques renferment les runes. Les runes sont extrêmement utiles. + + + Les coffres magiques renferment les runes. Les runes sont extrêmement utiles. + + + Si vous ratez un coffre magique, l'architecte peut vous offrir une seconde chance. + + + Si vous ratez un coffre magique, l'architecte peut vous offrir une seconde chance. + + + L'architecte fait payer cher ses services. + + + L'architecte fait payer cher ses services. + + + Les boss libèrent de grandes quantités d'or quand ils meurent. + + + Les boss libèrent de grandes quantités d'or quand ils meurent. + + + Enterrez-moi avec mon argent. + + + Enterrez-moi avec mon argent. + + + En cas de problème, équipez des runes Grâce. + + + En cas de problème, équipez des runes Grâce. + + + Vous pouvez activer la descente rapide dans les options pour attaquer en descendant d'une plateforme avec [Input:18] + + + Vous pouvez activer la descente rapide dans les options pour attaquer en descendant d'une plateforme avec [Input:18] + + + L'architecte est très utile pour s'entraîner contre les boss. + + + L'architecte est très utile pour s'entraîner contre les boss. + + + La troisième rangée d'équipements présente souvent des différences. Soyez attentif. + + + La troisième rangée d'équipements présente souvent des différences. Soyez attentive. + + + Certaines runes fonctionnent mieux avec certains boss. + + + Certaines runes fonctionnent mieux avec certains boss. + + + Les Ténèbres sont toujours en bas du château. + + + Si un boss pose problème, essayez d'utiliser différentes runes. + + + N'hésitez pas à vous entraîner contre les boss en utilisant l'architecte. + + + N'hésitez pas à vous entraîner contre les boss en utilisant l'architecte. + + + La vie est une statistique très importante à augmenter. + + + La vie est une statistique très importante à augmenter. + + + Les runes Punition peuvent endommager les objets invulnérables. + + + Les runes Punition peuvent endommager les objets invulnérables. + + + Les capacités de classe sont très puissantes quand elles sont utilisées correctement. + + + Les capacités de classe sont très puissantes quand elles sont utilisées correctement. + + + Certaines classes ont des avantages contre certains boss. + + + Certaines classes ont des avantages contre certains boss. + + + Si un boss pose problème, essayez d'utiliser différentes runes. + + + Vault runes let you to jump in the air with + + + Les runes Saut permettent de sauter en l'air avec [Input:10] + + + Les runes Saut permettent de sauter en l'air avec [Input:10] + + + Les runes Course permettent d'accélérer avec [Input:PLAYER_DASHLEFT] ou [Input:PLAYER_DASHRIGHT] + + + Les runes Course permettent d'accélérer avec [Input:PLAYER_DASHLEFT] ou [Input:PLAYER_DASHRIGHT] + + + Chaque classe a ses avantages et ses inconvénients. Adaptez votre jeu en conséquence. + + + Chaque classe a ses avantages et ses inconvénients. Adaptez votre jeu en conséquence. + + + Explorer et trouver des coffres est la meilleure façon de gagner de l'or. + + + Explorer et trouver des coffres est la meilleure façon de gagner de l'or. + + + Plus la zone parcourue est difficile, plus la récompense est importante. + + + Plus la zone parcourue est difficile, plus la récompense est importante. + + + J'ai des devoirs envers ma famille... + + + J'ai des devoirs envers ma famille... + + + Mais je ne suis fidèle qu'à moi-même. + + + Mais je ne suis fidèle qu'à moi-même. + + + or + + + or + + + PV récupérés + + + PV récupérés + + + MP récupérés + + + MP récupérés + + + Armure + + + + Armure + + + + Santé max. + + + + Santé max. + + + + Mana max. + + + + Mana max. + + + + Attaque + + + + Attaque + + + + Magie + + + + Magie + + + + Poids max. + + + + Poids max. + + + + Lecture en cours... + + + Lecture en cours... + + + Vous entrez dans... + + + Vous entrez dans... + + + Objectif Coffre magique : + + + Objectif Coffre magique : + + + Atteindre le coffre en 15 secondes : + + + Atteindre le coffre en 15 secondes : + + + Temps restant : + + + Temps restant : + + + Objectif atteint ! + + + Objectif atteint ! + + + Objectif échoué + + + Objectif échoué + + + Aucun caractère + + + {0} héroïque + + + {0} héroïque + + + {0} céleste + + + {0} céleste + + + Sieur {0} {1} + + + Sieur {0} {1} + + + Sieur héros + + + Sieur héros + + + Dame {0} {1} + + + Dame {0} {1} + + + Dame héroïne + + + Dame héroïne + + + Aucun caractère + + + the + + + the + + + {0} légendaire + + + {0} légendaire + + + {0} futile + + + {0} futile + + + {0} faible + + + {0} faible + + + {0} casse-cou + + + {0} casse-cou + + + {0} solide + + + {0} solide + + + {0} brave + + + {0} brave + + + {0} téméraire + + + {0} téméraire + + + [Input:0] pour sélectionner un enfant + + + [Input:0] pour sélectionner un enfant + + + [Button:LeftStick] pour afficher l'arbre généalogique + + + [Button:LeftStick] pour afficher l'arbre généalogique + + + Touches directionnelles pour afficher l'arbre généalogique + + + Touches directionnelles pour afficher l'arbre généalogique + + + [Input:9] pour relancer une fois + + + [Input:9] pour relancer une fois + + + Classe + + + Classe + + + Traits + + + Traits + + + Traits – Aucun + + + Traits – Aucun + + + Sort + + + Sort + + + En construction + + + En construction + + + En épilation + + + En épilation + + + En remémoration + + + En remémoration + + + En connexion + + + En connexion + + + Coffre ouvert + + + Coffre ouvert + + + Téléporteur + + + Téléporteur + + + Pièce bonus + + + Pièce bonus + + + [Input:9] pour fermer la carte + + + [Input:9] pour fermer la carte + + + [Input:0] pour recentrer sur le joueur + + + [Input:0] pour recentrer sur le joueur + + + Utiliser les touches directionnelles pour bouger la carte + + + Utiliser les touches directionnelles pour bouger la carte + + + [Button:LeftStick] pour bouger la carte + + + [Button:LeftStick] pour bouger la carte + + + Légende + + + Légende + + + Vous êtes ici + + + Vous êtes ici + + + Position du boss + + + Position du boss + + + Coffre à ouvrir + + + Coffre à ouvrir + + + Coffre magique + + + Coffre magique + + + Volume musique + + + Volume musique + + + Chinois + + + Chinois + + + Anglais + + + Anglais + + + Français + + + Français + + + Allemand + + + Allemand + + + Polonais + + + Polonais + + + Portugais brésilien + + + Portugais brésilien + + + Russe + + + Russe + + + Espagnol + + + Espagnol + + + Langue + + + Langue + + + *La descente rapide permet de descendre d'une plateforme et placer\ndes attaques basses une fois en l'air en appuyant sur la touche BAS. + + + Résolution + + + Résolution + + + Plein écran + + + Plein écran + + + Réduire la qualité des nuances + + + Réduire la qualité des nuances + + + Utiliser les manettes Dinput + + + Utiliser les manettes Dinput + + + Activer le cloud sur Steam + + + Activer le cloud sur Steam + + + *La descente rapide permet de descendre d'une plateforme et placer\ndes attaques basses une fois en l'air en appuyant sur la touche BAS. + + + [Button:LeftStick] pour parcourir les options + + + [Button:LeftStick] pour parcourir les options + + + Touches directionnelles pour parcourir les options + + + Touches directionnelles pour parcourir les options + + + [Input:0] pour sélectionner une option + + + [Input:0] pour sélectionner une option + + + [Input:2] pour quitter les options + + + [Input:2] pour quitter les options + + + *Vous devez redémarrer le jeu pour appliquer cette modification. + + + *Vous devez redémarrer le jeu pour appliquer cette modification. + + + *Vous devez aussi activer la compatibilité avec le cloud\nsur la plateforme Steam pour utiliser cette fonctionnalité. + + + *Vous devez aussi activer la compatibilité avec le cloud\nsur la plateforme Steam pour utiliser cette fonctionnalité. + + + Classe : + + + Classe : + + + Force : + + + Force : + + + Magie : + + + Magie : + + + Armure : + + + Armure : + + + Niveau : + + + Niveau : + + + Vie : + + + Vie : + + + Manette sans fil Xbox One déconnectée. Reconnectez la manette. + + + ????? + + + ????? + + + or + + + or + + + MP max. + + + MP max. + + + PV max. + + + PV max. + + + MP max. convertis. Niveau supérieur nécessaire. + + + MP max. convertis. Niveau supérieur nécessaire. + + + Vie + + + Enchantements + + + Enchantements + + + [Input:2] pour quitter + + + [Input:2] pour quitter + + + Niv. + + + Niv. + + + Vie + + + Mana + + + Mana + + + Armure + + + Armure + + + Poids + + + Poids + + + Force + + + Force + + + Intelligence + + + Intelligence + + + Chance de crit. + + + Chance de crit. + + + Dégâts crit. + + + Dégâts crit. + + + Équipement + + + Équipement + + + 100 % statistiques de base. + + + SPÉCIAL : Cri barbare.\nPV énormes. Force et MP faibles. + + + SPÉCIAL : Cri barbare.\nPV énormes. Force et MP faibles. + + + Force énorme, mais pas d'attaques critiques.\n+{0} % de vitesse de déplacement. PV et MP faibles. + + + Force énorme, mais pas d'attaques critiques.\n+{0} % de vitesse de déplacement. PV et MP faibles. + + + SPÉCIAL : Technique de substitution.\nForce énorme, mais pas d'attaques critiques.\n+{0} % de vitesse de déplacement. PV et MP faibles. + + + SPÉCIAL : Technique de substitution.\nForce énorme, mais pas d'attaques critiques.\n+{0} % de vitesse de déplacement. PV et MP faibles. + + + {0} % des dégâts infligés sont convertis en mana.\nForce, PV et MP faibles. + + + {0} % des dégâts infligés sont convertis en mana.\nForce, PV et MP faibles. + + + SPÉCIAL : Sort augmenté.\n{0} % des dégâts infligés sont convertis en mana.\nForce, PV et MP faibles. + + + SPÉCIAL : Sort augmenté.\n{0} % des dégâts infligés sont convertis en mana.\nForce, PV et MP faibles. + + + Les victimes sont converties en PV max.\nForce, PV et MP très faibles. Intell. élevée. + + + Les victimes sont converties en PV max.\nForce, PV et MP très faibles. Intell. élevée. + + + SPÉCIAL : Conversion PV.\nLes victimes sont converties en PV max.\nForce, PV et MP très faibles. Intell. élevée. + + + SPÉCIAL : Conversion PV.\nLes victimes sont converties en PV max.\nForce, PV et MP très faibles. Intell. élevée. + + + Du sang de dragon coule dans vos veines. + + + Du sang de dragon coule dans vos veines. + + + ????? + + + ????? + + + 100 % statistiques de base. + + + SPÉCIAL : Bouclier du garde.\n100 % statistiques de base. + + + SPÉCIAL : Bouclier du garde.\n100 % statistiques de base. + + + +{0} % de chance de crit., +{1} % de dégâts crit.\nPV, MP et Force faibles. + + + +{0} % de chance de crit., +{1} % de dégâts crit.\nPV, MP et Force faibles. + + + SPÉCIAL : Forme de brume\n+{0} % chance de crit., +{1} % de dégâts crit.\nPV, MP et Force faibles. + + + SPÉCIAL : Forme de brume\n+{0} % chance de crit., +{1} % de dégâts crit.\nPV, MP et Force faibles. + + + +{0} % de gain d'or.\nTrès faible dans toutes les autres statistiques. + + + +{0} % de gain d'or.\nTrès faible dans toutes les autres statistiques. + + + SPÉCIAL : Lampe frontale.\n+{0} % de gain d'or.\nTrès faible dans toutes les autres statistiques. + + + SPÉCIAL : Lampe frontale.\n+{0} % de gain d'or.\nTrès faible dans toutes les autres statistiques. + + + Chaque victime vous offre {0} de mana.\nForce et PV faibles. Intell. et MP élevés. + + + Chaque victime vous offre {0} de mana.\nForce et PV faibles. Intell. et MP élevés. + + + SPÉCIAL : Tour de sorts.\nChaque victime vous offre {0} de mana.\nForce et PV faibles. Intell. et MP élevés. + + + SPÉCIAL : Tour de sorts.\nChaque victime vous offre {0} de mana.\nForce et PV faibles. Intell. et MP élevés. + + + PV énormes. Force et MP faibles. + + + PV énormes. Force et MP faibles. + + + - PRÉPARER UN NOUVEL HÉRITAGE - + + + NP + + + + NP + + + + - PRÉPARER UN NOUVEL HÉRITAGE - + + + [Button:LeftStick] pour parcourir + + + [Button:LeftStick] pour parcourir + + + Touches directionnelles pour parcourir les profils + + + Touches directionnelles pour parcourir les profils + + + [Input:0] pour sélectionner + + + [Input:0] pour sélectionner + + + [Input:2] pour quitter + + + [Input:2] pour quitter + + + [Input:26] pour supprimer + + + [Input:26] pour supprimer + + + {0} la {1} + + + {0} la {1} + + + {0} le {1} + + + {0} le {1} + + + {0}, la défunte + + + {0}, la défunte + + + {0}, le défunt + + + {0}, le défunt + + + Niv. + + + Niv. + + + Activer descente rapide + + + Activer descente rapide + + + Non + + + Non + + + Oui + + + Oui + + + Volume effets sonores + + + Volume effets sonores + + + Améliorez votre endurance cardiaque. Un meilleur cœur signifie une meilleure santé. + + + Déverrouillez la forge et accédez à des objets de folie. + + + Déverrouillez la forge et accédez à des objets de folie. + + + Déverrouillez l'enchanteresse et accédez à ses runes et pouvoirs magiques. + + + Déverrouillez l'enchanteresse et accédez à ses runes et pouvoirs magiques. + + + Déverrouillez l'architecte et obtenez les pouvoirs nécessaires pour verrouiller le château. + + + Déverrouillez l'architecte et obtenez les pouvoirs nécessaires pour verrouiller le château. + + + Améliorer votre capacité de transport vous permettra de porter une armure meilleure et plus lourde. + + + Améliorer votre capacité de transport vous permettra de porter une armure meilleure et plus lourde. + + + Renforcez vos tripes avec des moyens naturels pour réduire les dégâts subis. + + + Renforcez vos tripes avec des moyens naturels pour réduire les dégâts subis. + + + Améliorez vos capacités de pillage et soyez davantage récompensé pour vos efforts. + + + Améliorez vos capacités de pillage et soyez davantage récompensée pour vos efforts. + + + Réduisez le coût de Charon en apprenant à négocier avec la mort elle-même. + + + Réduisez le coût de Charon en apprenant à négocier avec la mort elle-même. + + + Le nettoyage des intestins améliore considérablement les effets des potions et de la viande. + + + Le nettoyage des intestins améliore considérablement les effets des potions et de la viande. + + + Utilisez le pouvoir de la science pour concevoir un tas de nouveaux bébés. Pas besoin de vous faire un dessin... + + + Utilisez le pouvoir de la science pour concevoir un tas de nouveaux bébés. Pas besoin de vous faire un dessin... + + + Libérez le pouvoir de la liche, un être au potentiel incroyable ! + + + Libérez le pouvoir de la liche, un être au potentiel incroyable ! + + + Améliorez votre endurance cardiaque. Un meilleur cœur signifie une meilleure santé. + + + Renforcez vos glandes surrénales et devenez invulnérable comme Hulk ! C'est parti ! + + + Déverrouillez les capacités de minage et augmentez la fortune de votre famille. + + + Déverrouillez les capacités de minage et augmentez la fortune de votre famille. + + + Déverrouillez la kleptomagie et devenez un mage armé. + + + Déverrouillez le kleptomage et devenez une mage armée. + + + Déverrouillez le ninja, le plus rapide des combattants. + + + Déverrouillez le ninja, le plus rapide des combattants. + + + Révisez vos bases pour réduire le coût en mana quand vous jetez des sorts. + + + Révisez vos bases pour réduire le coût en mana quand vous jetez des sorts. + + + Transformez vos chevaliers en paladins, de terribles combattants de première ligne. + + + Transformez vos chevalières en paladins, de terribles combattantes de première ligne. + + + Déverrouillez les pouvoirs cachés des mages et transformez-les en archimages tout-puissants. + + + Déverrouillez les pouvoirs cachés des mages et transformez-les en archimages toutes-puissantes. + + + Apprenez les arts obscurs et transformez les canailles en assassins. + + + Apprenez les arts obscurs et transformez les canailles en assassines. + + + Obtenez votre diplôme en géologie et passez de mineur à spéléologue. La classe ! + + + Obtenez votre diplôme en géologie et passez de mineuse à spéléologue. La classe ! + + + Devenez un roi barbare, le roi des hommes libres... ou pas. + + + Devenez une reine barbare, la reine des hommes libres... ou pas. + + + Promouvez vos liches toutes-puissantes en rois liches. + + + Promouvez vos liches toutes-puissantes en rois liches. + + + Renforcez vos glandes surrénales et devenez invulnérable comme Hulk ! C'est parti ! + + + Laissez s'exprimer le félin qui est en vous et évitez la mort... parfois. + + + Devenez le chef de votre village et transformez vos ninjas en hokages. Incroyable ! + + + Devenez la chef de votre village et transformez vos ninjas en hokages. Incroyable ! + + + Parcourez les méandres de la magie et transformez vos kleptomages en magelames. + + + Parcourez les méandres de la magie et transformez vos kleptomages en magelames. + + + Moitié homme, moitié ******, parfait. + + + Moitié femme, moitié ******, parfait. + + + SOUFFLE COURT \nVous avez du mal à reprendre votre souffle. La poursuite n'est pas votre truc, mais vous pouvez marcher ! \n\nAugmente votre récupération naturelle d'endurance. + + + SOUFFLE COURT \nVous avez du mal à reprendre votre souffle. La poursuite n'est pas votre truc, mais vous pouvez marcher ! \n\nAugmente votre récupération naturelle d'endurance. + + + Vous avez reçu du sang de tigre dès votre plus jeune âge. Vous avez maintenant le pouvoir d'en libérer quand vous êtes poignardé. \nCourir vous demande moins d'endurance. + + + Vous avez reçu du sang de tigre dès votre plus jeune âge. Vous avez maintenant le pouvoir d'en libérer quand vous êtes poignardée. \nCourir vous demande moins d'endurance. + + + Vous avez des ancêtres vikings. \n\nVotre endurance de départ est plus importante. + + + Vous avez des ancêtres vikings. \n\nVotre endurance de départ est plus importante. + + + Vous vous levez tôt. C'est une métaphore pour expliquer que vous progressez rapidement. \nGagnez des bonus de PV et de MP à chaque fois que vous franchissez un niveau. + + + Vous vous levez tôt. C'est une métaphore pour expliquer que vous progressez rapidement. \nGagnez des bonus de PV et de MP à chaque fois que vous franchissez un niveau. + + + Vous avez le pouvoir absolu au bout des doigts depuis votre naissance. \nTous vos sorts infligent plus de dégâts. + + + Vous avez le pouvoir absolu au bout des doigts depuis votre naissance. \nTous vos sorts infligent plus de dégâts. + + + L'énergie des ténèbres coule dans vos veines depuis votre naissance. \nVos sorts vous coûtent moins cher. + + + L'énergie des ténèbres coule dans vos veines depuis votre naissance. \nVos sorts vous coûtent moins cher. + + + Vos TOC vous sont enfin utiles ! \nGagnez plus d'or. + + + Vos TOC vous sont enfin utiles ! \nGagnez plus d'or. + + + Laissez s'exprimer le félin qui est en vous et évitez la mort... parfois. + + + Entraînez-vous comme il faut pour véritablement renforcer vos muscles des bras et des fesses. + + + Selon la loi, vous êtes désormais le meilleur des hommes. \nDonnez naissance à plus d'enfants. + + + Selon la loi, vous êtes désormais la meilleure des femmes \nDonnez naissance à plus d'enfants. + + + Vos parents disaient qu'un fermier n'a pas besoin d'apprendre à se servir d'un tamis pour trouver de l'or. Aujourd'hui, personne ne se moque plus de vous. \nAffichez les salles aux trésors au début du jeu. + + + Vos parents disaient qu'un fermier n'a pas besoin d'apprendre à se servir d'un tamis pour trouver de l'or. Aujourd'hui, personne ne se moque plus de vous. \nAffichez les salles aux trésors au début du jeu. + + + La guerre est un enfer. Heureusement vous n'en avez jamais connu. \nTirez plus d'obus. + + + La guerre est un enfer. Heureusement vous n'en avez jamais connu. \nTirez plus d'obus. + + + Enfant, vous aimiez faire éclater les choses. \nLes bombes ont un champ d'action plus important. + + + Enfant, vous aimiez faire éclater les choses. \nLes bombes ont un champ d'action plus important. + + + Votre arrière-grand-père était un bonhomme de neige. Il ne vous a rien appris. \nLes glaçons transpercent plus d'ennemis. + + + Votre arrière-grand-père était un bonhomme de neige. Il ne vous a rien appris. \nLes glaçons transpercent plus d'ennemis. + + + Vous êtes de nature tranquille. \nVous récupérez plus vite de l'endurance quand vous êtes immobile. + + + Vous êtes de nature tranquille. \nVous récupérez plus vite de l'endurance quand vous êtes immobile. + + + CAPACITÉ de base. Augmentez votre endurance totale. + + + CAPACITÉ de base. Augmentez votre endurance totale. + + + Vous combattez avec élégance. \nLes attaques absorbent X % en moins d'endurance. + + + Vous combattez avec élégance. \nLes attaques absorbent X % en moins d'endurance. + + + CAPACITÉ de base. Augmentez votre vie + + + CAPACITÉ de base. Augmentez votre vie + + + Vous sucez... du sang. \nRécupérez une petite quantité de vie à chaque coup. + + + Vous sucez... du sang. \nRécupérez une petite quantité de vie à chaque coup. + + + Entraînez-vous comme il faut pour véritablement renforcer vos muscles des bras et des fesses. + + + Une salle d'entraînement aux sauts a ses avantages. Infligez plus de dégâts avec vos attaques basses consécutives. + + + Revenez à la vie tel Jésus. Mais vous n'êtes toujours pas Jésus. \nRessuscitez une fois après être mort. + + + Revenez à la vie tel Jésus. Mais vous n'êtes toujours pas Jésus. \nRessuscitez une fois après être morte. + + + Nettoyer une pièce, c'est comme s'éclaircir les idées. Je ne sais pas faire. \nRécupérez de la vie pour chaque pièce entièrement nettoyée. + + + Nettoyer une pièce, c'est comme s'éclaircir les idées. Je ne sais pas faire. \nRécupérez de la vie pour chaque pièce entièrement nettoyée. + + + Cartographie \n Chaque pourcentage de carte dévoilé confère 0,1 point de dégâts supplémentaire. + + + Cartographie \n Chaque pourcentage de carte dévoilé confère 0,1 point de dégâts supplémentaire. + + + CAPACITÉ de base. Augmentez les dégâts d'attaque. + + + CAPACITÉ de base. Augmentez les dégâts d'attaque. + + + Vous êtes très très mauvais perdant. \nInfligez des dégâts massifs à tous les ennemis à l'écran si vous mourez. + + + Vous êtes très très mauvaise perdante. \nInfligez des dégâts massifs à tous les ennemis à l'écran si vous mourez. + + + Vous avez compris que les coups bas infligeaient des dégâts massifs. \nLes attaques critiques infligent encore plus de dégâts. + + + Vous avez compris que les coups bas infligeaient des dégâts massifs. \nLes attaques critiques infligent encore plus de dégâts. + + + CAPACITÉ DE BASE. + + + CAPACITÉ DE BASE. + + + Oh, elles étaient dans ma poche arrière ! \nGagnez 2 clés supplémentaires. + + + Oh, elles étaient dans ma poche arrière ! \nGagnez 2 clés supplémentaires. + + + Tel le phœnix, vous renaissez de vos cendres. \nRécupérez tous vos PV et MP. + + + Tel le phœnix, vous renaissez de vos cendres. \nRécupérez tous vos PV et MP. + + + Prenez votre retraite et placez sagement votre argent. Terminez votre jeu tôt et gagnez un bonus à l'or trouvé. + + + Prenez votre retraite et placez sagement votre argent. Terminez votre jeu tôt et gagnez un bonus à l'or trouvé. + + + Une salle d'entraînement aux sauts a ses avantages. Infligez plus de dégâts avec vos attaques basses consécutives. + + + Découvrez les faiblesses de vos ennemis pour faire preuve d'une efficacité impitoyable ! + + + GLOUP GLOUP GLOUP ! \nBuvez les potions instantanément. + + + GLOUP GLOUP GLOUP ! \nBuvez les potions instantanément. + + + Découvrez les faiblesses de vos ennemis pour faire preuve d'une efficacité impitoyable ! + + + Entraînez-vous aux attaques mortelles pour être encore plus redoutable. Vos ennemis connaîtront une mort des plus définitives. + + + Entraînez-vous aux attaques mortelles pour être encore plus redoutable. Vos ennemis connaîtront une mort des plus définitives. + + + Découvrez les secrets de l'univers pour mieux tuer grâce aux sorts. + + + Découvrez les secrets de l'univers pour mieux tuer grâce aux sorts. + + + Renforcez votre force mentale pour augmenter votre réserve de mana. + + + Renforcez votre force mentale pour augmenter votre réserve de mana. + + + Appuyez sur [Input:9] pour choisir vos enfants de façon aléatoire. + + + Appuyez sur [Input:9] pour choisir vos enfants de façon aléatoire. + + + Appuyez sur [Input:13] pour bloquer tous les dégâts. + + + Appuyez sur [Input:13] pour bloquer tous les dégâts. + + + Appuyez sur [Input:13] pour changer de sort. + + + Appuyez sur [Input:13] pour changer de sort. + + + Appuyez sur [Input:13] pour vous transformer en brume. + + + Appuyez sur [Input:13] pour vous transformer en brume. + + + Appuyez sur [Input:13] pour allumer votre lampe frontale. + + + Appuyez sur [Input:13] pour allumer votre lampe frontale. + + + Appuyez sur [Input:13] pour pousser un cri assourdissant qui repousse presque tout. + + + Appuyez sur [Input:13] pour pousser un cri assourdissant qui repousse presque tout. + + + Appuyez sur [Input:13] pour convertir les PV max en MP max. + + + Appuyez sur [Input:13] pour convertir les PV max en MP max. + + + Appuyez sur [Input:13] pour vous téléporter. + + + Appuyez sur [Input:13] pour vous téléporter. + + + Appuyez sur [Input:13] pour jeter des sorts augmentés. + + + Appuyez sur [Input:13] pour jeter des sorts augmentés. + + + Appuyez sur [Input:10] pour être extraordinaire. + + + Appuyez sur [Input:10] pour être extraordinaire. + + + + + + + + + Santé + + + + Forgeron + + + Forgeron + + + Enchanteresse + + + Enchanteresse + + + Architecte + + + Architecte + + + Équipement + + + + Équipement + + + + Armure + + + + Armure + + + + Gain or + + + + Gain or + + + + Marchandage + + + Marchandage + + + Potion + + + + Potion + + + + Enfants aléatoires + + + Enfants aléatoires + + + Déverrouiller Liche + + + Déverrouiller Liche + + + Santé + + + + Temps invuln. + + + + Déverrouiller Mineur + + + Déverrouiller Mineuse + + + Déverrouiller Kleptomage + + + Déverrouiller Kleptomage + + + Déverrouiller Ninja + + + Déverrouiller Ninja + + + Baisse Coût mana + + + Baisse Coût mana + + + Amélioration Chevalier + + + Amélioration Chevalière + + + Amélioration Mage + + + Amélioration Mage + + + Amélioration Canaille + + + Amélioration Canaille + + + Amélioration Mineur + + + Amélioration Mineuse + + + Amélioration Barbare + + + Amélioration Barbare + + + Amélioration Liche + + + Amélioration Liche + + + Temps invuln. + + + + Même pas peur + + + Amélioration Ninja + + + Amélioration Ninja + + + Amélioration Kleptomage + + + Amélioration Kleptomage + + + Bestialité + + + Bestialité + + + Récupération rapide + + + Récupération rapide + + + Coureur né + + + Coureuse née + + + Cœur solide + + + Cœur solide + + + Tête brûlée + + + Tête brûlée + + + Magelame + + + Magelame + + + Sorcier + + + Sorcière + + + Perfectionniste + + + Perfectionniste + + + Même pas peur + + + Attaque + + + + Bien doté + + + Bien dotée + + + Chasseur de trésors + + + Chasseuse de trésors + + + Maître artilleur + + + Maîtresse artilleur + + + Expert en explosifs + + + Experte en explosifs + + + Glaçon + + + Glaçon + + + Gourou + + + Gourou + + + Poumons d'acier + + + Poumons d'acier + + + Maître d'armes + + + Maîtresse d'armes + + + Char + + + Char + + + Vampire + + + Vampire + + + Attaque + + + + Attaque basse + + + + Seconde chance + + + Seconde chance + + + Tranquillité + + + Tranquillité + + + Cartographie ninja + + + Cartographie ninja + + + Homme fort + + + Femme forte + + + Fragile + + + Fragile + + + Barbare critique + + + Barbare critique + + + Magicien + + + Magicienne + + + Gardien des clés + + + Gardienne des clés + + + Une seule fois + + + Une seule fois + + + Partir à temps + + + Partir à temps + + + Attaque basse + + + + Chance de crit. + + + + Ivrogne + + + Ivrogne + + + Chance de crit. + + + + Dégâts crit. + + + + Dégâts crit. + + + + Dégâts magiques + + + + Dégâts magiques + + + + Mana + + + + Mana + + + + {0} d'or pour {1} + + + {0} d'or pour {1} + + + Déverrouiller + + + Déverrouiller + + + Améliorer + + + Améliorer + + + Poids + + + Poids + + + pv + + + pv + + + mp + + + mp + + + for + + + for + + + int + + + int + + + pv/mp + + + pv/mp + + + Max + + + Max + + + [Input:0] pour acheter / améliorer vos traits + + + [Input:0] pour acheter / améliorer vos traits + + + Armure + + + Armure + + + sec + + + sec + + + [Input:9] pour désactiver des icônes + + + [Input:9] pour désactiver des icônes + + + [Input:2] pour quitter le manoir + + + [Input:2] pour quitter le manoir + + + [Button:LeftStick] pour parcourir les capacités + + + [Button:LeftStick] pour parcourir les capacités + + + Touches directionnelles pour parcourir les capacités + + + Touches directionnelles pour parcourir les capacités + + + [Input:9] pour activer des icônes + + + [Input:9] pour activer des icônes + + + Actuel + + + Actuel + + + Amélioration + + + Amélioration + + + Niveau + + + Niveau + + + Le forgeron peut fabriquer de l'équipement extrêmement sophistiqué et ainsi faire de vous un chasseur de voyous hors pair.\nRassemblez des plans pour lui offrir un éventail encore plus large d'armements de toutes sortes pour votre arsenal. + + + Transformez vos barbares en ROIS barbares ! Apprenez le cri secret des ours et criez sur les choses jusqu'à ce qu'elles explosent. + + + Transformez vos barbares en ROIS barbares ! Apprenez le cri secret des ours et criez sur les choses jusqu'à ce qu'elles explosent. + + + Transformez vos simples ninjas en tout-puissants hokages ! Apprenez l'art de se transformer en bûche avant d'être touché. Ça tombe bien, car vous transportez un tas de bûches sur vous ! + + + Transformez vos simples ninjas en tout-puissants hokages ! Apprenez l'art de se transformer en bûche avant d'être touché. Ça tombe bien, car vous transportez un tas de bûches sur vous ! + + + Entraînez vos canailles pour qu'elles deviennent des assassins à part entière. Utilisez le pouvoir des ombres pour passer secrètement à travers les rangs ennemis. + + + Entraînez vos canailles pour qu'elles deviennent des assassins à part entière. Utilisez le pouvoir des ombres pour passer secrètement à travers les rangs ennemis. + + + À force de creuser, vos mineurs se sont transformés en spéléologues ! Cette lampe frontale va enfin vous servir à quelque chose ! (Enfin peut-être...) + + + À force de creuser, vos mineuses se sont transformées en spéléologues ! Cette lampe frontale va enfin vous servir à quelque chose ! (Enfin peut-être...) + + + Transformez vos kleptomages en magelames et obtenez ainsi la possibilité de lancer des sorts augmentés.\nVous appelez ça une hache ? ÇA c'est une hache ! + + + Transformez vos kleptomages en magelames et obtenez ainsi la possibilité de lancer des sorts augmentés.\nVous appelez ça une hache ? ÇA c'est une hache ! + + + Transformez vos liches en rois liches et obtenez ainsi le pouvoir de l'esprit ET de la matière ! Appuyez une seule fois et convertissez votre santé permanente en mana permanente. + + + Transformez vos liches en rois liches et obtenez ainsi le pouvoir de l'esprit ET de la matière ! Appuyez une seule fois et convertissez votre santé permanente en mana permanente. + + + Vous avez découvert l'art oublié des dragons. Vous ne pouvez pas sauter mais vous pouvez voler indéfiniment et lancer des boules de feu sur vos ennemis. + + + Vous avez découvert l'art oublié des dragons. Vous ne pouvez pas sauter mais vous pouvez voler indéfiniment et lancer des boules de feu sur vos ennemis. + + + Vous avez découvert les arts cachés connus uniquement de Johannes le traître. Personne ne saurait résister à votre pouvoir ! + + + Vous avez découvert les arts cachés connus uniquement de Johannes le traître. Personne ne saurait résister à votre pouvoir ! + + + Le forgeron peut fabriquer de l'équipement extrêmement sophistiqué et ainsi faire de vous une chasseuse de voyous hors pair.\nRassemblez des plans pour lui offrir un éventail encore plus large d'armements de toutes sortes pour votre arsenal. + + + L'enchanteresse peut renforcer vos capacités physiques grâce à des runes magiques, et ainsi vous rendre meilleur, plus fort, plus rapide et plus agile.\nTrouvez des runes pour compléter les talents de modification de vos capacités physiques de l'enchanteresse.\nSa boule de cristal est factice. + + + L'enchanteresse peut renforcer vos capacités physiques grâce à des runes magiques, et ainsi vous rendre meilleure, plus forte, plus rapide et plus agile.\nTrouvez des runes pour compléter les talents de modification de vos capacités physiques de l'enchanteresse.\n\nSa boule de cristal est factice. + + + L'architecte peut verrouiller un château et l'empêcher d'évoluer.\n\nVous aimez la disposition d'un château ?\nVERROUILLEZ-LE !\nMais assurez-vous d'abord d'en avoir les moyens ! + + + L'architecte peut verrouiller un château et l'empêcher d'évoluer.\n\nVous aimez la disposition d'un château ?\nVERROUILLEZ-LE !\nMais assurez-vous d'abord d'en avoir les moyens ! + + + Le ninja. Un guerrier très rapide et très redoutable qui porte un super bandeau ! Ne peut pas encaisser un très grand nombre d'attaques mais sait faire très mal ! + + + Le ninja. Un guerrier très rapide et très redoutable qui porte un super bandeau ! Ne peut pas encaisser un très grand nombre d'attaques mais sait faire très mal ! + + + Davantage formés à ramener de l'argent qu'à tuer des ennemis, les mineurs sont particulièrement utiles pour débusquer les coffres dans le château et pour éviter les affrontements. + + + Davantage formés à ramener de l'argent qu'à tuer des ennemis, les mineurs sont particulièrement utiles pour débusquer les coffres dans le château et pour éviter les affrontements. + + + Le kleptomage draine la mana des ennemis qu'il touche et se constitue ainsi une réserve de mana illimitée pour la bataille. La classe ! + + + Le kleptomage draine la mana des ennemis qu'il touche et se constitue ainsi une réserve de mana illimitée pour la bataille. La classe ! + + + Maître de la vie et de la mort, la liche a un potentiel exceptionnel. Chaque victime lui octroie de la vie permanente (jusque dans une certaine mesure), ce qui fait d'elle un être terriblement dangereux. + + + Maître de la vie et de la mort, la liche a un potentiel exceptionnel. Chaque victime lui octroie de la vie permanente (jusque dans une certaine mesure), ce qui fait d'elle un être terriblement dangereux. + + + Faites de vos chevaliers de puissants paladins. Grâce à un entraînement rigoureux, les paladins ont appris à bloquer les coups provenant de toutes les directions. + + + Faites de vos chevaliers de puissants paladins. Grâce à un entraînement rigoureux, les paladins ont appris à bloquer les coups provenant de toutes les directions. + + + Transformez vos simples mages en archimages. Maîtrisez tous les arts obscurs et changez instantanément tous vos sorts à la volée. + + + Transformez vos simples mages en archimages. Maîtrisez tous les arts obscurs et changez instantanément tous vos sorts à la volée. + + + Anneau d'Hypérion + + + Obole de Ponce de León + + + Obole de Ponce de León + + + Obole d'Hérodote + + + Obole d'Hérodote + + + Obole du traître + + + Obole du traître + + + Anneau d'Hypérion + + + Bottes d'Hermès + + + Bottes d'Hermès + + + Malédiction du hérisson + + + Malédiction du hérisson + + + Obole de Charon + + + Obole de Charon + + + Boussole de Calypso + + + Boussole de Calypso + + + Bénédiction d'Hélios + + + Bénédiction d'Hélios + + + Lunettes de geek + + + Lunettes de geek + + + Obole de Khidr + + + Obole de Khidr + + + Obole d'Alexandre + + + Obole d'Alexandre + + + Lance un poignard directement face à vous. + + + Invoque une grande lame pour vous défendre. + + + Invoque une grande lame pour vous défendre. + + + Vous encercle de feu pour vous protéger. + + + Vous encercle de feu pour vous protéger. + + + Envoie des orbes qui rebondissent partout. + + + Envoie des orbes qui rebondissent partout. + + + Tire un rayon laser qui fait exploser tout ce qu'il touche. + + + Tire un rayon laser qui fait exploser tout ce qu'il touche. + + + Tire des boules de feu sur vos ennemis. + + + Tire des boules de feu sur vos ennemis. + + + Lance un barrage de poignards. + + + Lance un barrage de poignards. + + + Lance un poignard directement face à vous. + + + Lance une hache géante en arc. + + + Lance une hache géante en arc. + + + Fait apparaître une bombe qui finit par exploser. + + + Fait apparaître une bombe qui finit par exploser. + + + Fige tous les ennemis à l'écran. + + + Fige tous les ennemis à l'écran. + + + Touche tous les ennemis à l'écran. Coûteux. + + + Touche tous les ennemis à l'écran. Coûteux. + + + Descend et se téléporte jusqu'à votre ombre. + + + Descend et se téléporte jusqu'à votre ombre. + + + Envoie une balise qui vous téléporte. + + + Envoie une balise qui vous téléporte. + + + Envoie un chakram qui revient vers vous. + + + Envoie un chakram qui revient vers vous. + + + Envoie des faux qui s'envolent au-dessus de vous. + + + Envoie des faux qui s'envolent au-dessus de vous. + + + Poignard + + + Mur de lame + + + Mur de lame + + + Barrière de flammes + + + Barrière de flammes + + + Orbes multidirectionnels + + + Orbes multidirectionnels + + + Faisceau + + + Faisceau + + + Souffle du dragon + + + Souffle du dragon + + + Poignard véloce + + + Poignard véloce + + + Poignard + + + Hache + + + Hache + + + Bombe + + + Bombe + + + Arrêt sur image + + + Arrêt sur image + + + Nuée d'oiseaux + + + Nuée d'oiseaux + + + Transducteur quantique + + + Transducteur quantique + + + Déplaceur + + + Déplaceur + + + Chakram + + + Chakram + + + Faux + + + Faux + + + ... chargement en cours + + + ... chargement en cours + + + Forgeron + + + J'étais autrefois une enchanteresse très puissante. Mais un jour, les monstres du château ont fait irruption dans mes rêves et ont volé mon savoir. + + + Pas de son + + + Pas de son + + + Coffre magique + + + Coffre magique + + + Le sol est recouvert de lave + + + Le sol est recouvert de lave + + + Booyan + + + Booyan + + + Salut ! Envie de tester votre dextérité ?\nVous n'avez qu'un essai, mais il est gratuit ! Si vous réussissez, je vous donnerai une belle récompense ! + + + Salut ! Envie de tester votre dextérité ?\nVous n'avez qu'un essai, mais il est gratuit ! Si vous réussissez, je vous donnerai une belle récompense ! + + + 10 poignards pour détruire 8 cibles. Envie d'essayer ? + + + 10 poignards pour détruire 8 cibles. Envie d'essayer ? + + + Booyan + + + Booyan + + + Fini la récréation ! Foutez le camp ! + + + Fini la récréation ! Foutez le camp ! + + + Booyan + + + Booyan + + + J'étais autrefois une enchanteresse très puissante. Mais un jour, les monstres du château ont fait irruption dans mes rêves et ont volé mon savoir. + + + Ils ont enfermé ce savoir dans des runes et sans elles, je ne sais plus rien faire. + + + Je n'ai pas vu autant de coups depuis ma dernière visite à la taverne (hier). Puisque vous avez détruit toutes les cibles, j'ai une petite récompense pour vous ! + + + Je n'ai pas vu autant de coups depuis ma dernière visite à la taverne (hier). Puisque vous avez détruit toutes les cibles, j'ai une petite récompense pour vous ! + + + Booyan + + + Booyan + + + Vous n'avez pas réussi à toucher les 8 cibles ?\nPfff ! Bonne chance avec le reste du château. + + + Vous n'avez pas réussi à toucher les 8 cibles ?\nPfff ! Bonne chance avec le reste du château. + + + Booyan + + + Booyan + + + Salut ! Voyons un peu quelles sont vos capacités !\nVous n'avez qu'un essai, mais il est gratuit ! Si vous réussissez, je vous donnerai une belle récompense ! + + + Salut ! Voyons un peu quelles sont vos capacités !\nVous n'avez qu'un essai, mais il est gratuit ! Si vous réussissez, je vous donnerai une belle récompense ! + + + Vous disposez de 5 haches pour détruire autant de cibles que possible. Si vous en laissez moins de 10 debout, je vous offrirai un prix spécial. Envie d'essayer ? + + + Vous disposez de 5 haches pour détruire autant de cibles que possible. Si vous en laissez moins de 10 debout, je vous offrirai un prix spécial. Envie d'essayer ? + + + Booyan + + + Booyan + + + Génial ! Vous avez réussi à ne pas laisser plus de 10 cibles debout ! Je n'ai plus assez de cibles pour cette mission, je vais vous donner mon stock. + + + Génial ! Vous avez réussi à ne pas laisser plus de 10 cibles debout ! Je n'ai plus assez de cibles pour cette mission, je vais vous donner mon stock. + + + Ils ont enfermé ce savoir dans des runes et sans elles, je ne sais plus rien faire. + + + Je vous en prie, héros, si vous trouvez des runes, ramenez-les-moi et je vous les revendrai pour votre plus grand bénéfice ! + + + Booyan + + + Booyan + + + Vous avez laissé plus de 10 cibles.\nJ'imagine que vous ne voulez pas du prix. Pfff ! + + + Vous avez laissé plus de 10 cibles.\nJ'imagine que vous ne voulez pas du prix. Pfff ! + + + ??? + + + ??? + + + Félicitations, l'aventurier ! Je suis ici pour t'offrir la chance de ta vie ! + + + Félicitations, l'aventurière ! Je suis ici pour t'offrir la chance de ta vie ! + + + Elfe misérable + + + Elfe misérable + + + Pour seulement 25 % de ton or actuel, je te donne la possibilité d'ouvrir l'un des trois coffres. + + + Pour seulement 25 % de ton or actuel, je te donne la possibilité d'ouvrir l'un des trois coffres. + + + L'un des coffres triple la somme dépensée, les deux autres sont vides. + + + L'un des coffres triple la somme dépensée, les deux autres sont vides. + + + Elfe avare + + + Elfe avare + + + Envie d'essayer ? + + + Envie d'essayer ? + + + Je vous en prie, héroïne, si vous trouvez des runes, ramenez-les-moi et je vous les revendrai pour votre plus grand bénéfice ! + + + Architecte + + + ??? + + + ??? + + + Félicitations, l'aventurier ! Je suis ici pour t'offrir la chance de ta vie ! + + + Félicitations, l'aventurière ! Je suis ici pour t'offrir la chance de ta vie ! + + + Elfe misérable + + + Elfe misérable + + + Pour seulement 50 % de ton or actuel, je te donne la possibilité d'ouvrir l'un des trois coffres. + + + Pour seulement 50 % de ton or actuel, je te donne la possibilité d'ouvrir l'un des trois coffres. + + + L'un des coffres triple la somme dépensée, les deux autres sont vides. + + + L'un des coffres triple la somme dépensée, les deux autres sont vides. + + + Elfe avare + + + Elfe avare + + + Envie d'essayer ? + + + Envie d'essayer ? + + + ??? + + + ??? + + + Félicitations, l'aventurier ! Je suis ici pour t'offrir la chance de ta vie ! + + + Félicitations, l'aventurière ! Je suis ici pour t'offrir la chance de ta vie ! + + + Elfe misérable + + + Elfe misérable + + + Architecte + + + Enchanté, mon garçon ! + + + Pour seulement 75 % de ton or actuel, je te donne la possibilité d'ouvrir l'un des trois coffres. + + + Pour seulement 75 % de ton or actuel, je te donne la possibilité d'ouvrir l'un des trois coffres. + + + L'un des coffres triple la somme dépensée, les deux autres sont vides. + + + L'un des coffres triple la somme dépensée, les deux autres sont vides. + + + Elfe avare + + + Elfe avare + + + Envie d'essayer ? + + + Envie d'essayer ? + + + Elfe avare + + + Elfe avare + + + Vous n'avez pas assez d'argent. Vous êtes moisi. + + + Vous n'avez pas assez d'argent. Vous êtes moisie. + + + Elfe fanfaron + + + Elfe fanfaron + + + Qu'y a-t-il dans la boîte ? + + + Qu'y a-t-il dans la boîte ? + + + RIEN ! + + + RIEN ! + + + Mais quel imbécile ! Quel imbécile ! + + + Mais quelle imbécile ! Quelle imbécile ! + + + Enchanté, ma petite ! + + + Tu veux que je te dise un truc incroyable ? Je suis diiiingue ! + + + Elfe mauvais perdant + + + Elfe mauvais perdant + + + Pfiouuu ! Vous avez eu de la chance, cette fois ! + + + Pfiouuu ! Vous avez eu de la chance, cette fois ! + + + Elfe impatient + + + Elfe impatient + + + Allez, ouvrez un coffre ! + + + Allez, ouvrez un coffre ! + + + Elfe avare + + + Elfe avare + + + Désolé, mec, c'est un coffre par personne. + + + Désolé, ma pauvre, c'est un coffre par personne. + + + Développeurs + + + Développeurs + + + Don't **** Your Pants.\nDurée de développement : 2 jours.\nDate de sortie : 16 février 2009 + + + Don't **** Your Pants.\nDurée de développement : 2 jours.\nDate de sortie : 16 février 2009 + + + Tu veux que je te dise un truc incroyable ? Je suis diiiingue ! + + + Ce levier, là ? Il suffit que je tire dessus pour empêcher le château de se modifier. + + + Il s'agit du premier jeu que nous avons créé quand nous nous appelions encore Decade Studios. Dans ce jeu, le joueur doit empêcher le personnage de déféquer en saisissant les instructions à l'écran. + + + Il s'agit du premier jeu que nous avons créé quand nous nous appelions encore Decade Studios. Dans ce jeu, le joueur doit empêcher le personnage de déféquer en saisissant les instructions à l'écran. + + + Nous avons eu l'idée lors d'un voyage en bus et nous l'avons conçu en un week-end. Ça nous a plutôt réussi ! + + + Nous avons eu l'idée lors d'un voyage en bus et nous l'avons conçu en un week-end. Ça nous a plutôt réussi ! + + + Le jeu contient un mot grossier, nous avons donc pensé changer le titre pour le rendre plus sympathique. Mais on a eu le courage de prendre ce risque ! + + + Le jeu contient un mot grossier, nous avons donc pensé changer le titre pour le rendre plus sympathique. Mais on a eu le courage de prendre ce risque ! + + + Le jeu repose en grande partie sur le principe du jeu d'aventure textuel où le joueur saisit ce dont il a envie. Il nous a donc fallu anticiper ce que le joueur saisirait comme texte. + + + Le jeu repose en grande partie sur le principe du jeu d'aventure textuel où le joueur saisit ce dont il a envie. Il nous a donc fallu anticiper ce que le joueur saisirait comme texte. + + + Nous nous y sommes pris de deux façons. Tout d'abord, nous avons réduit la quantité d'options qui s'offraient au joueur (un homme, une porte), puis nous avons élaboré un système de succès pour orienter le joueur. + + + Nous nous y sommes pris de deux façons. Tout d'abord, nous avons réduit la quantité d'options qui s'offraient au joueur (un homme, une porte), puis nous avons élaboré un système de succès pour orienter le joueur. + + + Le jeu repose tellement sur le système des succès qu'il apparaît en jeu, à l'écran de progression. C'est un changement mineur mais déterminant. + + + Le jeu repose tellement sur le système des succès qu'il apparaît en jeu, à l'écran de progression. C'est un changement mineur mais déterminant. + + + Développeurs + + + Développeurs + + + Band of Bears\nDurée de développement : 4 mois.\nDate de sortie : 6 août 2009 + + + Band of Bears\nDurée de développement : 4 mois.\nDate de sortie : 6 août 2009 + + + Ce levier, là ? Il suffit que je tire dessus pour empêcher le château de se modifier. + + + Vous pourrez ainsi vivre exactement ce que vos ancêtres ont vécu. Imprrrrressionnant, non ? + + + Il s'agit de notre deuxième jeu et nous l'avons présenté au concours DreamBuildPlay 2009. Comme tout s'est fait relativement tard, nous avons dû cravacher pour rattraper tous les autres. + + + Il s'agit de notre deuxième jeu et nous l'avons présenté au concours DreamBuildPlay 2009. Comme tout s'est fait relativement tard, nous avons dû cravacher pour rattraper tous les autres. + + + Forts du succès de DSYP, nous avons décidé de devenir grands... très grands ! Et c'est ainsi qu'est né Cellar Door Games. + + + Forts du succès de DSYP, nous avons décidé de devenir grands... très grands ! Et c'est ainsi qu'est né Cellar Door Games. + + + En plus de démarrer un projet qui nécessitait bien plus que nos ressources et notre expertise, nous avons dû jongler avec des emplois à plein temps pour créer ce jeu. On peut dire qu'on en a bavé ! + + + En plus de démarrer un projet qui nécessitait bien plus que nos ressources et notre expertise, nous avons dû jongler avec des emplois à plein temps pour créer ce jeu. On peut dire qu'on en a bavé ! + + + Le jeu utilise le système B.E.A.R.S (Bare Effort Adaptable Room System), qui permet de changer les pièces en fonction du nombre de joueurs actifs. + + + Le jeu utilise le système B.E.A.R.S (Bare Effort Adaptable Room System), qui permet de changer les pièces en fonction du nombre de joueurs actifs. + + + Le système B.E.A.R.S n'ajuste pas simplement les chiffres, il modifiait aussi les puzzles. Nous avons fini dans le top 20, ce qui était très bien mais pas assez pour obtenir la moindre récompense. + + + Le système B.E.A.R.S n'ajuste pas simplement les chiffres, il modifiait aussi les puzzles. Nous avons fini dans le top 20, ce qui était très bien mais pas assez pour obtenir la moindre récompense. + + + Nous avons alors dû faire face à la réalité et au bon sens et abandonner le projet, du moins pour une durée indéterminée. + + + Nous avons alors dû faire face à la réalité et au bon sens et abandonner le projet, du moins pour une durée indéterminée. + + + Le boss de la démo était vraiment cool ! + + + Le boss de la démo était vraiment cool ! + + + Développeurs + + + Développeurs + + + Tribal Tallies\nDurée de développement : 3 mois.\nDate de sortie : 23 mars 2009 + + + Tribal Tallies\nDurée de développement : 3 mois.\nDate de sortie : 23 mars 2009 + + + Vous pourrez ainsi vivre exactement ce que vos ancêtres ont vécu. Imprrrrressionnant, non ? + + + Comment j'ai fabriqué ce fabuleux engin ? Grâce à la sciiiiiiience, bien sûr ! Et à la magie. + + + Tribal Tallies était le premier projet sur lequel nous avons travaillé après la terrible expérience avec Band of Bears. + + + Tribal Tallies était le premier projet sur lequel nous avons travaillé après la terrible expérience avec Band of Bears. + + + C'était un projet-test pour nous essayer à l'univers des jeux iOS car nous n'avions jamais créé quoi que ce soit pour les plates-formes mobiles. + + + C'était un projet-test pour nous essayer à l'univers des jeux iOS car nous n'avions jamais créé quoi que ce soit pour les plates-formes mobiles. + + + Ce jeu repose sur un concept simple dans la mesure où il faut taper des séquences de chiffres aussi vite que possible. + + + Ce jeu repose sur un concept simple dans la mesure où il faut taper des séquences de chiffres aussi vite que possible. + + + Pour corser un peu les choses, nous avons implémenté plusieurs modes, comme la saisie inversée, les chiffres cachés et les associations. + + + Pour corser un peu les choses, nous avons implémenté plusieurs modes, comme la saisie inversée, les chiffres cachés et les associations. + + + Les objectifs nous semblaient raisonnables, mais nous avons mis beaucoup plus de temps à faire le jeu que prévu. Et cela ne nous a pas aidés que tout ait été encodé sur un hackintosh. + + + Les objectifs nous semblaient raisonnables, mais nous avons mis beaucoup plus de temps à faire le jeu que prévu. Et cela ne nous a pas aidés que tout ait été encodé sur un hackintosh. + + + C'est un jeu un peu simple. Nous aurions pu faire mieux, mais nous n'avons pas voulu prendre de risques après Band of Bears. + + + C'est un jeu un peu simple. Nous aurions pu faire mieux, mais nous n'avons pas voulu prendre de risques après Band of Bears. + + + Développeurs + + + Développeurs + + + Q\nDurée de développement : 1 mois.\nDate de sortie : 18 mars 2010 + + + Q\nDurée de développement : 1 mois.\nDate de sortie : 18 mars 2010 + + + Comment j'ai fabriqué ce fabuleux engin ? Grâce à la sciiiiiiience, bien sûr ! Et à la magie. + + + ... surtout la magie. + + + Notre 4e projet. Après Tribal Tallies, nous avons arrêté de concevoir des jeux pour nous concentrer sur nos emplois à temps plein. Et puis ça nous a démangé à nouveau, et nous avons décidé de créer un jeu de puzzles. + + + Notre 4e projet. Après Tribal Tallies, nous avons arrêté de concevoir des jeux pour nous concentrer sur nos emplois à temps plein. Et puis ça nous a démangé à nouveau, et nous avons décidé de créer un jeu de puzzles. + + + À cette époque, la plupart des fondateurs de Cellar Door Games ont quitté l'aventure, séduits par de nouvelles opportunités. Les survivants composent l'équipe actuelle. + + + À cette époque, la plupart des fondateurs de Cellar Door Games ont quitté l'aventure, séduits par de nouvelles opportunités. Les survivants composent l'équipe actuelle. + + + Le jeu consistait à empiler les cases en forçant le joueur à anticiper leur chute pour créer d'énormes chaînes. + + + Le jeu consistait à empiler les cases en forçant le joueur à anticiper leur chute pour créer d'énormes chaînes. + + + Le jeu était gratuit, ce qui n'a rien changé à son succès ! Après les échecs de Band of Bears, Tribal Tallies et Q, nous étions prêts à faire nos cartons et à mettre la clé sous la porte. + + + Le jeu était gratuit, ce qui n'a rien changé à son succès ! Après les échecs de Band of Bears, Tribal Tallies et Q, nous étions prêts à faire nos cartons et à mettre la clé sous la porte. + + + Développeurs + + + Développeurs + + + My First Quantum Translocator\nDurée de développement : 1 mois.\nDate de sortie : 13 octobre 2010 + + + My First Quantum Translocator\nDurée de développement : 1 mois.\nDate de sortie : 13 octobre 2010 + + + My First Quantum Translocator est arrivé quand la société était au plus mal. Après l'échec de trois jeux, nous avions déjà renoncé dans nos esprits et décidé de faire ce titre simplement pour nous faire plaisir. + + + My First Quantum Translocator est arrivé quand la société était au plus mal. Après l'échec de trois jeux, nous avions déjà renoncé dans nos esprits et décidé de faire ce titre simplement pour nous faire plaisir. + + + ... surtout la magie. + + + Forgeron + + + Bienvenue, héros ! + + + Hélas, mes capacités ne sont pas grrrrrrratuites ! Si je verrouille ce château, 40 % de votre or sera prélevé ! + + + Nous n'avions formulé aucune attente durant le développement et nous faisions ça pour nous amuser. + + + Nous n'avions formulé aucune attente durant le développement et nous faisions ça pour nous amuser. + + + Inutile de dire que l'accueil du jeu a été énorme, et Cellar Door Games doit sa survie uniquement à cet événement. Quand nous avons sorti MFQT, nous étions convaincus que c'était la fin. + + + Inutile de dire que l'accueil du jeu a été énorme, et Cellar Door Games doit sa survie uniquement à cet événement. Quand nous avons sorti MFQT, nous étions convaincus que c'était la fin. + + + Ce qui est amusant, c'est que la plupart des gens pensent que le jeu est inspiré de Portal alors que les similarités relèvent d'un pur hasard ! + + + Ce qui est amusant, c'est que la plupart des gens pensent que le jeu est inspiré de Portal alors que les similarités relèvent d'un pur hasard ! + + + Le jeu s'inspire en réalité d'un personnage que nous avions imaginé pour le titre League of Legends. + + + Le jeu s'inspire en réalité d'un personnage que nous avions imaginé pour le titre League of Legends. + + + Et les points communs entre Portal et MFQT ne se sont révélés que lorsque nous avons ajouté la dernière touche graphique et l'histoire au jeu. + + + Et les points communs entre Portal et MFQT ne se sont révélés que lorsque nous avons ajouté la dernière touche graphique et l'histoire au jeu. + + + Quoi qu'il en soit, nous sommes assez fiers de ce jeu. Il se jouait bien, et sa fin était sympa. + + + Quoi qu'il en soit, nous sommes assez fiers de ce jeu. Il se jouait bien, et sa fin était sympa. + + + Développeurs + + + Développeurs + + + I Have 1 Day\nDurée de développement : 1,5 mois.\nDate de sortie : 15 avril 2011 + + + I Have 1 Day\nDurée de développement : 1,5 mois.\nDate de sortie : 15 avril 2011 + + + Hélas, mes capacités ne sont pas grrrrrrratuites ! Si je verrouille ce château, 40 % de votre or sera prélevé ! + + + + + + Si vous nous demandiez quel est notre jeu préféré, nous répondrions sans hésiter et à l'unanimité : I Have 1 Day ! + + + Si vous nous demandiez quel est notre jeu préféré, nous répondrions sans hésiter et à l'unanimité : I Have 1 Day ! + + + Enfants, nous avons grandi avec les grands classiques du jeu d'aventure comme Kings Quest et Monkey Island. C'était donc notre hommage à ces titres, qui nous ont offert nos meilleures heures de jeu. + + + Enfants, nous avons grandi avec les grands classiques du jeu d'aventure comme Kings Quest et Monkey Island. C'était donc notre hommage à ces titres, qui nous ont offert nos meilleures heures de jeu. + + + Ce jeu est un puzzle ancré en temps réel. Le joueur dispose de 24 heures pour terminer le jeu. + + + Ce jeu est un puzzle ancré en temps réel. Le joueur dispose de 24 heures pour terminer le jeu. + + + Chaque puzzle a plusieurs solutions avec des répercussions temporelles, ce qui pousse le joueur à trouver la meilleure façon de résoudre les énigmes. + + + Chaque puzzle a plusieurs solutions avec des répercussions temporelles, ce qui pousse le joueur à trouver la meilleure façon de résoudre les énigmes. + + + Une chose intéressante : la seconde fin a été ajoutée quasiment à la dernière minute et sans elle, le jeu aurait juste été nul ! + + + Une chose intéressante : la seconde fin a été ajoutée quasiment à la dernière minute et sans elle, le jeu aurait juste été nul ! + + + Développeurs + + + Développeurs + + + Villainous\nDurée de développement : 3 mois.\nDate de sortie : 15 avril 2011 + + + Villainous\nDurée de développement : 3 mois.\nDate de sortie : 15 avril 2011 + + + Villainous est l'un des projets les plus audacieux que nous ayons entrepris. + + + Villainous est l'un des projets les plus audacieux que nous ayons entrepris. + + + + + + Voulez-vous verrouiller le château et conserver seulement 60 % de votre or ? + + + À l'origine, nous voulions concevoir un tower defense inversé. Cela nous semblait être une bonne idée, que nous avons eu du mal à concrétiser. + + + À l'origine, nous voulions concevoir un tower defense inversé. Cela nous semblait être une bonne idée, que nous avons eu du mal à concrétiser. + + + La plupart des gens qui ont joué à ce jeu pensent que son principe est évident, mais ce titre a vu le jour après beaucoup de stress et de discussions ! + + + La plupart des gens qui ont joué à ce jeu pensent que son principe est évident, mais ce titre a vu le jour après beaucoup de stress et de discussions ! + + + Nous avons retravaillé trois ou quatre fois le projet avant de trouver sa version finale. + + + Nous avons retravaillé trois ou quatre fois le projet avant de trouver sa version finale. + + + C'est donc assez amusant que, jusqu'à ce jour, Villainous soit de loin le jeu qui a rencontré le plus de succès car c'est celui qui nous a donné le plus de fil à retordre. + + + C'est donc assez amusant que, jusqu'à ce jour, Villainous soit de loin le jeu qui a rencontré le plus de succès car c'est celui qui nous a donné le plus de fil à retordre. + + + Développeurs + + + Développeurs + + + Bullet Audyssey\nDurée de développement : 3,5 mois.\nDate de sortie : 29 novembre 2011 + + + Bullet Audyssey\nDurée de développement : 3,5 mois.\nDate de sortie : 29 novembre 2011 + + + Bullet Audyssey est notre tout dernier jeu avant Rogue Legacy. + + + Bullet Audyssey est notre tout dernier jeu avant Rogue Legacy. + + + Bullet Audyssey est un bullet hell qui se joue au rythme de morceaux de musique. C'est le plus grand défi technique que nous ayons eu à relever (oui, plus grand encore que Rogue Legacy). + + + Bullet Audyssey est un bullet hell qui se joue au rythme de morceaux de musique. C'est le plus grand défi technique que nous ayons eu à relever (oui, plus grand encore que Rogue Legacy). + + + Voulez-vous verrouiller le château et conserver seulement 60 % de votre or ? + + + + + + La simple création d'un niveau nécessitait le travail simultané de trois éditeurs. + + + La simple création d'un niveau nécessitait le travail simultané de trois éditeurs. + + + Le développement de ce jeu était également atypique. En effet, la préconception a été importante pour s'assurer que tout fonctionnait. + + + Le développement de ce jeu était également atypique. En effet, la préconception a été importante pour s'assurer que tout fonctionnait. + + + La documentation n'étant pas notre fort, nous avons dû discuter du projet dans les moindres détails pendant une bonne demi-journée. + + + La documentation n'étant pas notre fort, nous avons dû discuter du projet dans les moindres détails pendant une bonne demi-journée. + + + Dans ce titre, le joueur absorbe les balles ennemies pour les renvoyer et cette absorption se produit au rythme de la chanson jouée. + + + Dans ce titre, le joueur absorbe les balles ennemies pour les renvoyer et cette absorption se produit au rythme de la chanson jouée. + + + Les premiers essais ont été désastreux. Le jeu était trop dur, et les joueurs s'énervaient dès la première minute ! + + + Les premiers essais ont été désastreux. Le jeu était trop dur, et les joueurs s'énervaient dès la première minute ! + + + Enfin, le test c'était un seul joueur, pas spécialement fan des jeux de type bullet hell. Mais cela reste plus large que notre groupe de test habituel. + + + Enfin, le test c'était un seul joueur, pas spécialement fan des jeux de type bullet hell. Mais cela reste plus large que notre groupe de test habituel. + + + Le jeu n'a pas très bien marché à sa sortie. Cela nous a encouragés à faire Rogue Legacy ! + + + Le jeu n'a pas très bien marché à sa sortie. Cela nous a encouragés à faire Rogue Legacy ! + + + Confirmer + + + Confirmer + + + Annuler + + + Annuler + + + Attention ! + + + Attention ! + + + + + + Voulez-vous verrouiller le château et conserver seulement 60 % de votre or ? + + + Voulez-vous vraiment commencer une nouvelle partie ? Toutes les données de jeu précédentes sauvegardées seront supprimées. + + + Voulez-vous vraiment commencer une nouvelle partie ? Toutes les données de jeu précédentes sauvegardées seront supprimées. + + + Restaurer les commandes + + + Restaurer les commandes + + + Voulez-vous vraiment restaurer le schéma de commandes par défaut ? + + + Voulez-vous vraiment restaurer le schéma de commandes par défaut ? + + + + + + + + + Voulez-vous vraiment commencer une nouvelle aventure avec ce héros ? + + + Voulez-vous vraiment commencer une nouvelle aventure avec cette héroïne ? + + + Modification de la résolution + + + Modification de la résolution + + + Voulez-vous vraiment passer à cette résolution ?\n(La résolution précédente sera rétablie dans 10 secondes) + + + Voulez-vous vraiment passer à cette résolution ?\n(La résolution précédente sera rétablie dans 10 secondes) + + + Supprimer fichier de sauvegarde + + + Supprimer fichier de sauvegarde + + + Voulez-vous vraiment supprimer votre fichier de sauvegarde ?\n(Toutes les capacités, tous les caractères, toutes les lignées et tous les équipements seront DÉFINITIVEMENT supprimés) + + + Voulez-vous vraiment supprimer votre fichier de sauvegarde ?\n(Toutes les capacités, tous les caractères, toutes les lignées et tous les équipements seront DÉFINITIVEMENT supprimés) + + + Voulez-vous verrouiller le château et conserver seulement 60 % de votre or ? + + + Architecte + + + Supprimer fichier de sauvegarde + + + Supprimer fichier de sauvegarde + + + Confirmer ? (retour en arrière impossible)\n(Toutes les capacités, tous les caractères, toutes les lignées et tous les équipements seront DÉFINITIVEMENT supprimés) + + + Confirmer ? (retour en arrière impossible)\n(Toutes les capacités, tous les caractères, toutes les lignées et tous les équipements seront DÉFINITIVEMENT supprimés) + + + + + + + + + Voulez-vous vraiment quitter et revenir au menu principal ? (votre statut actuel sera sauvegardé) + + + Voulez-vous vraiment quitter et revenir au menu principal ? (votre statut actuel sera sauvegardé) + + + + + + + + + Voulez-vous vraiment arrêter de jouer à Rogue Legacy ? (votre statut actuel sera sauvegardé) + + + Voulez-vous vraiment arrêter de jouer à Rogue Legacy ? (votre statut actuel sera sauvegardé) + + + Erreur de sauvegarde + + + Erreur de sauvegarde + + + Oh non ! Votre fichier de sauvegarde a été corrompu ! + + + Oh non ! Votre fichier de sauvegarde a été corrompu ! + + + Architecte + + + Désolé, mon garçon, il n'y a aucun château à construire pour le moment. Cette vis est là pour faire joli. + + + Tentative de chargement d'une version de secours du jeu... Espérons que cela ne vous ramène pas trop loin en arrière ! + + + Tentative de chargement d'une version de secours du jeu... Espérons que cela ne vous ramène pas trop loin en arrière ! + + + Erreur de sauvegarde + + + Erreur de sauvegarde + + + Il semblerait que votre version de secours ne fonctionne pas non plus. S'il vous plaît contacter: support@cellardoorgames.com + Il semblerait que votre version de secours ne fonctionne pas non plus. J'ai bien peur qu'il faille redémarrer le jeu. + + + Il semblerait que votre version de secours ne fonctionne pas non plus. S'il vous plaît contacter: support@cellardoorgames.com + Il semblerait que votre version de secours ne fonctionne pas non plus. J'ai bien peur qu'il faille redémarrer le jeu. + + + Erreur de sauvegarde + + + Erreur de sauvegarde + + + Votre partie n'a pas pu être sauvegardée trois fois de suite. + + + Votre partie n'a pas pu être sauvegardée trois fois de suite. + + + Votre logiciel anti-virus et les programmes de sauvegarde manuelle de secours peuvent entrer en conflit avec des fichiers de sauvegarde. Veuillez désactiver ces programmes avant de lancer le jeu. + + + Votre logiciel anti-virus et les programmes de sauvegarde manuelle de secours peuvent entrer en conflit avec des fichiers de sauvegarde. Veuillez désactiver ces programmes avant de lancer le jeu. + + + Désolé, ma petite, il n'y a aucun château à construire pour le moment. Cette vis est là pour faire joli. + + + Architecte + + + Architecte + + + Le château est déjà verrouillé, mec ! + + + Le château est déjà verrouillé, mec ! + + + Architecte + + + Architecte + + + Bienvenue, héroïne ! + + + Vous pouvez peut-être m'aider. J'étais le plus grand forgeron de toute la région. Mais un jour, les monstres de ce château ont attaqué ma forge et volé mes plans. + + + Amuuuuusez-vous bien ! Vous trouverez peut-être des trrrrrésors qui ont échappé à vos ancêtres ! + + + Amuuuuusez-vous bien ! Vous trouverez peut-être des trrrrrésors qui ont échappé à vos ancêtres ! + + + Charon + + + Charon + + + ... Il faut payer le droit de passage ! + + + ... Il faut payer le droit de passage ! + + + + + + + + + (Donner à Charon tout votre argent et pénétrer dans le château ?) + + + (Donner à Charon tout votre argent et pénétrer dans le château ?) + + + + + + + + + (Donner à Charon tout votre argent et pénétrer dans le château ?) + + + (Donner à Charon tout votre argent et pénétrer dans le château ?) + + + + + + + + + (Donner à Charon 90 % de votre argent et pénétrer dans le château ?) + + + (Donner à Charon 90 % de votre argent et pénétrer dans le château ?) + + + + + + + + + Vous pouvez peut-être m'aider. J'étais le plus grand forgeron de toute la région. Mais un jour, les monstres de ce château ont attaqué ma forge et volé mes plans. + + + Sans ces plans, je ne peux faire que des couverts ou ce genre de choses. + + + (Donner à Charon 80 % de votre argent et pénétrer dans le château ?) + + + (Donner à Charon 80 % de votre argent et pénétrer dans le château ?) + + + + + + + + + (Donner à Charon 70 % de votre argent et pénétrer dans le château ?) + + + (Donner à Charon 70 % de votre argent et pénétrer dans le château ?) + + + + + + + + + (Donner à Charon 60 % de votre argent et pénétrer dans le château ?) + + + (Donner à Charon 60 % de votre argent et pénétrer dans le château ?) + + + + + + + + + (Donner à Charon 50 % de votre argent et pénétrer dans le château ?) + + + (Donner à Charon 50 % de votre argent et pénétrer dans le château ?) + + + Charon + + + Charon + + + Oh oh oh ! Vous avez donc mon obole ! Je vais vous laisser passer gratuitement, mais seulement pour cette fois ! + + + Oh oh oh ! Vous avez donc mon obole ! Je vais vous laisser passer gratuitement, mais seulement pour cette fois ! + + + Charon + + + Charon + + + Sans ces plans, je ne peux faire que des couverts ou ce genre de choses. + + + Ramenez-moi tous les plans que vous trouverez ! Je pourrai ainsi fabriquer le matériel le plus incroyable qu'on ait jamais vu ! + + + Hé hé ! Mais c'est mon obole à moi ! + + + Hé hé ! Mais c'est mon obole à moi ! + + + Donnez-la-moi ! Et je laisserai passer votre âme de l'autre côté des portes. + + + Donnez-la-moi ! Et je laisserai passer votre âme de l'autre côté des portes. + + + (Donner l'obole à Charon et payer son droit de passage ?) + + + (Donner l'obole à Charon et payer son droit de passage ?) + + + Charon + + + Charon + + + Hé hé ! Mais c'est mon obole à moi ! + + + Hé hé ! Mais c'est mon obole à moi ! + + + Donnez-la-moi ! Et je laisserai passer votre âme de l'autre côté des portes. + + + Donnez-la-moi ! Et je laisserai passer votre âme de l'autre côté des portes. + + + (Donner l'obole à Charon et payer son droit de passage ?) + + + (Donner l'obole à Charon et payer son droit de passage ?) + + + Charon + + + Charon + + + Hé hé ! Mais c'est mon obole à moi ! + + + Hé hé ! Mais c'est mon obole à moi ! + + + Donnez-la-moi ! Et je laisserai passer votre âme de l'autre côté des portes. + + + Donnez-la-moi ! Et je laisserai passer votre âme de l'autre côté des portes. + + + Ramenez-moi tous les plans que vous trouverez ! Je pourrai ainsi fabriquer le matériel le plus incroyable qu'on ait jamais vu ! + + + ... moyennant un certain prix, bien sûr. + + + (Donner l'obole à Charon et payer son droit de passage ?) + + + (Donner l'obole à Charon et payer son droit de passage ?) + + + Charon + + + Charon + + + Hé hé ! Mais c'est mon obole à moi ! + + + Hé hé ! Mais c'est mon obole à moi ! + + + Donnez-la-moi ! Et je laisserai passer votre âme de l'autre côté des portes. + + + Donnez-la-moi ! Et je laisserai passer votre âme de l'autre côté des portes. + + + (Donner l'obole à Charon et payer son droit de passage ?) + + + (Donner l'obole à Charon et payer son droit de passage ?) + + + Charon + + + Charon + + + Oh... Vous n'auriez pas dû prendre cette obole. + + + Oh... Vous n'auriez pas dû prendre cette obole. + + + Préparez-vous. + + + Préparez-vous. + + + (Donner l'obole à Charon et payer son droit de passage ?) + + + (Donner l'obole à Charon et payer son droit de passage ?) + + + Temple spirituel + + + Temple spirituel + + + ... moyennant un certain prix, bien sûr. + + + Enchanteresse + + + Vous allez prier pour demander de l'aide ? + + + Vous allez prier pour demander de l'aide ? + + + Dernier boss + + + Dernier boss + + + Bienvenue, héros ! Félicitations pour être parvenu jusqu'ici. Malheureusement vous n'irez pas plus loin ! + + + Bienvenue, héroïne ! Félicitations pour être parvenue jusqu'ici. Malheureusement vous n'irez pas plus loin ! + + + Coffre magique - Rien + + + Coffre magique - Rien + + + PAS DE TEXTE + + + PAS DE TEXTE + + + Vaincre tous les ennemis + + + Vaincre tous les ennemis + + + + + + + + + Vie basse + + + Vie basse + + + + + + + + + Ne pas regarder + + + Ne pas regarder + + + Enchanteresse + + + Salut, héros ! + + + + + + + + + Ne pas sauter + + + Ne pas sauter + + + + + + + + + Ne pas faire de bruit + + + Ne pas faire de bruit + + + + + + + + + Ne pas toucher le sol + + + Ne pas toucher le sol + + + + + + + + + Ne pas se battre + + + Ne pas se battre + + + + + + + + + Arriver jusqu'à moi à temps + + + Arriver jusqu'à moi à temps + + + Salut, héroïne ! + + + Puis-je attirer votre attention un instant ? J'ai besoin de votre aide. + + + + + + + + + Ne subir aucun dégât + + + Ne subir aucun dégât + + + + + + + + + Me trouver + + + Me trouver + + + + + + + + + Coffre magique + + + Coffre magique + + + Ne pas me regarder ! + + + Ne pas me regarder ! + + + Coffre magique + + + Coffre magique + + + Ne pas sauter + + + Ne pas sauter + + + Coffre magique + + + Coffre magique + + + Puis-je attirer votre attention un instant ? J'ai besoin de votre aide. + + + Appuyez sur [Input:12] pour attaquer + + + Appuyez sur [Input:12] pour attaquer + + + Continuer votre quête + + + Continuer votre quête + + + Choisir votre héritier + + + Choisir votre héritier + + + Préparer votre héritage + + + Préparer votre héritage + + + Mannequin + + + ÇA FAIT MAL ! + + + ÇA FAIT MAL ! + + + Ouille ! + + + Ouille ! + + + Aïe ! + + + Aïe ! + + + ARGH ! + + + ARGH ! + + + J'abandonne ! + + + J'abandonne ! + + + Ça va pas, non ? + + + Ça va pas, non ? + + + Ça fait mal. + + + Ça fait mal. + + + Ça chatouille. + + + Ça chatouille. + + + C'est tout ? + + + C'est tout ? + + + Du nerf ! + + + Du nerf ! + + + Mannequin + + + Mon dieu ! + + + Bien tenté. + + + Bien tenté. + + + Lavette. + + + Lavette. + + + Essayez encore. + + + Essayez encore. + + + Mon dieu ! + + + Quel calvaire ! + + + Quel calvaire ! + + + Ça fait mal ! + + + Ça fait mal ! + + + STOOOOP ! + + + STOOOOP ! + + + Bon sang ! + + + Bon sang ! + + + POURQUOI !? + + + POURQUOI !? + + + Arrêtez ! + + + Arrêtez ! + + + Vous êtes fou ? + + + Vous êtes fou ? + + + Vous ne voyez pas certaines couleurs en raison d'une dyschromatopsie. + + + Vous êtes si mince que vous volez à chaque coup que vous prenez. + + + Vous êtes si mince que vous volez à chaque coup que vous prenez. + + + Vous ne savez jamais où vous êtes. + + + Vous ne savez jamais où vous êtes. + + + Vos réserves de MP et de PV sont inversées. Qui l'eût cru ? + + + Vos réserves de MP et de PV sont inversées. Qui l'eût cru ? + + + %#&@ ! + + + %#&@ ! + + + Quelle énergie ! Vous vous déplacez plus vite. + + + Quelle énergie ! Vous vous déplacez plus vite. + + + Tout. Briser. Cassez des choses pour récupérer des MP. + + + Tout. Briser. Cassez des choses pour récupérer des MP. + + + Vous êtes gonflé à bloc ! Les attaques repoussent les ennemis encore plus loin. + + + Vous êtes gonflée à bloc ! Les attaques repoussent les ennemis encore plus loin. + + + Vos membres sont faibles. Vous ne pouvez pas projeter vos ennemis. + + + Vos membres sont faibles. Vous ne pouvez pas projeter vos ennemis. + + + Vous ne voyez pas en 3D. + + + Vous ne voyez pas en 3D. + + + Même les héros les plus vaillants peuvent souffrir d'un côlon irritable. + + + Même les héroïnes les plus vaillantes peuvent souffrir d'un côlon irritable. + + + Vous ne voyez pas certaines couleurs en raison d'une dyschromatopsie. + + + Vous aimez les femmes. + + + Préparez vos sacs en papier ! + + + Préparez vos sacs en papier ! + + + Vous n'avez aucune vision périphérique. + + + Vous n'avez aucune vision périphérique. + + + Vous avez deux mains gauches et vous êtes incapable de jeter des sorts correctement. + + + Vous avez deux mains gauches et vous êtes incapable de jeter des sorts correctement. + + + Maladie artérielle périphérique. Absence de pouls dans le pied. + + + Maladie artérielle périphérique. Absence de pouls dans le pied. + + + Vous avez peur des poulets. + + + Vous avez peur des poulets. + + + VOUS AVEZ TENDANCE À EXAGÉRER. + + + VOUS AVEZ TENDANCE À EXAGÉRER. + + + Vous êtes fou. + + + Vous êtes folle. + + + Vous êtes très souple. + + + Vous êtes très souple. + + + Vous vous souvenez des choses avec beaucoup de précision. + + + Vous vous souvenez des choses avec beaucoup de précision. + + + Vous regrettez le passé. + + + Vous regrettez le passé. + + + Vous aimez les hommes. + + + Vous aimez les hommes. + + + Vous aimez les femmes. + + + Votre vision de loin est trouble. + + + Insensibilité congénitale à la douleur. Vous ne connaissez pas la douleur. + + + Insensibilité congénitale à la douleur. Vous ne connaissez pas la douleur. + + + Vous êtes très doué... mais vous avez quelques problèmes. + + + Vous êtes très douée... mais vous avez quelques problèmes. + + + Il n'y a pas de fuillère. + + + Il n'y a pas de fuillère. + + + Vous cassez beaucoup de choses. + + + Vous cassez beaucoup de choses. + + + Vous êtes un bon conducteur d'électricité. + + + Vous êtes un bon conducteur d'électricité. + + + Il fait si sombre ! + + + Il fait si sombre ! + + + Votre vision de loin est trouble. + + + Votre vision de près est trouble. + + + Votre vision de près est trouble. + + + Vous avze du mla à lrie. + + + Vous avze du mla à lrie. + + + Vous êtes né pour faire du basketball. + + + Vous êtes née pour faire du basketball. + + + On vous refuse toujours l'accès des montagnes russes. + + + On vous refuse toujours l'accès des montagnes russes. + + + La belle et le chauve. + + + La chauve et la bête. + + + Vous êtes trop lourd pour que vos ennemis puissent vous repousser. + + + Vous êtes trop lourde pour que vos ennemis puissent vous repousser. + + + Vous ne voyez pas les couleurs. + + + Vous volez quand on vous touche. + + + Vous volez quand on vous touche. + + + Où êtes-vous ? + + + Où êtes-vous ? + + + Réserves MP + PV inversées. + + + Réserves MP + PV inversées. + + + %#&@ ! + + + %#&@ ! + + + Vous vous déplacez plus vite. + + + Vous vous déplacez plus vite. + + + Cassez des choses pour récupérer des MP. + + + Cassez des choses pour récupérer des MP. + + + Vous repoussez les ennemis hors du parc. + + + Vous repoussez les ennemis hors du parc. + + + Vous ne pouvez pas repousser les ennemis. + + + Vous ne pouvez pas repousser les ennemis. + + + Vous ne voyez pas en 3D. + + + Vous ne voyez pas en 3D. + + + Vous souffrez de flatulences. + + + Vous souffrez de flatulences. + + + Vous ne voyez pas les couleurs. + + + Vous aimez les femmes. + + + Tout est à l'envers. + + + Tout est à l'envers. + + + Aucun indicateur. + + + Aucun indicateur. + + + Vous lancez les sorts derrière vous. + + + Vous lancez les sorts derrière vous. + + + Absence de pouls dans le pied. + + + Absence de pouls dans le pied. + + + Vous avez peur des poulets. + + + Vous avez peur des poulets. + + + Vous exagérez les dégâts que vous subissez. + + + Vous exagérez les dégâts que vous subissez. + + + Vous voyez des choses qui n'existent pas. + + + Vous voyez des choses qui n'existent pas. + + + Vous vous retournez quand vous vous battez. + + + Vous vous retournez quand vous vous battez. + + + Mémorisez où se trouvent les ennemis. + + + Mémorisez où se trouvent les ennemis. + + + Tout est vieilli. + + + Tout est vieilli. + + + Vous aimez les hommes. + + + Vous aimez les hommes. + + + Vous aimez les femmes. + + + Vous voyez mal de loin. + + + Aucune barre de vie visible. + + + Aucune barre de vie visible. + + + Sorts aléatoires. + + + Sorts aléatoires. + + + Il n'y a pas de fuillère. + + + Il n'y a pas de fuillère. + + + Vous cassez des choses et n'avez aucun équilibre. + + + Vous cassez des choses et n'avez aucun équilibre. + + + Les plates-formes restent ouvertes. + + + Les plates-formes restent ouvertes. + + + Il fait si sombre ! + + + Il fait si sombre ! + + + Vous voyez mal de loin. + + + Vous voyez mal de près. + + + Vous voyez mal de près. + + + Vous avze du mla à lrie. + + + Vous avze du mla à lrie. + + + Vous êtes énorme. + + + Vous êtes énorme. + + + Vous êtes minuscule. + + + Vous êtes minuscule. + + + Vous êtes chauve. + + + Vous êtes chauve. + + + On ne peut pas vous repousser. + + + On ne peut pas vous repousser. + + + Daltonisme + + + Ectomorphie + + + Ectomorphie + + + Alzheimer + + + Alzheimer + + + Dextrocardie + + + Dextrocardie + + + Coprolalie + + + Coprolalie + + + TDAH + + + TDAH + + + TOC + + + TOC + + + Hypergonadisme + + + Hypergonadisme + + + Faiblesse musculaire + + + Faiblesse musculaire + + + Cécité stéréo. + + + Cécité stéréo. + + + Côlon irritable + + + Côlon irritable + + + Daltonisme + + + Homosexualité + + + Vertige + + + Vertige + + + Vision tunnellaire + + + Vision tunnellaire + + + Gaucherie + + + Gaucherie + + + AOMI + + + AOMI + + + Alektorophobie + + + Alektorophobie + + + Hypochondrie + + + Hypochondrie + + + Démence + + + Démence + + + Souplesse + + + Souplesse + + + Mémoire eidétique + + + Mémoire eidétique + + + Nostalgie + + + Nostalgie + + + Homosexualité + + + Myopie + + + ICD + + + ICD + + + Génie + + + Génie + + + L'Élu + + + L'Élu + + + Maladresse + + + Maladresse + + + HSEM + + + HSEM + + + Glaucome + + + Glaucome + + + Myopie + + + Hypermétropie + + + Hypermétropie + + + Dyslexie + + + Dyslexie + + + Gigantisme + + + Gigantisme + + + Nanisme + + + Nanisme + + + Calvitie + + + Calvitie + + + Endomorphie + + + Endomorphie + + + Développé par + + + Développé par + + + Conception + + + Conception + + + Programmation + + + Programmation + + + Production + + + Production + + + Graphismes + + + Graphismes + + + Conception audio et musique + + + Conception audio et musique + + + Musique + + + Musique + + + + + + + + + Attaque basse ici + + + Attaque basse ici + + + Appuyez sur [Input:11] pour sauter + + + Appuyez sur [Input:11] pour sauter + + + Maintenez [Input:11] pour sauter plus haut + + + Maintenez [Input:11] pour sauter plus haut + + + Appuyez sur [Input:12] pour attaquer + + + Appuyez sur [Input:12] pour attaquer + + + Maintenez [Input:19] et appuyez sur [Input:11]\npour descendre + + + Maintenez [Input:19] et appuyez sur [Input:11]\npour descendre + + + (en l'air) Maintenez [Input:19] et appuyez sur [Input:12]\npour une attaque basse + + + (en l'air) Maintenez [Input:19] et appuyez sur [Input:12]\npour une attaque basse + + + Appuyez sur [Input:10] pour sauter + + + Appuyez sur [Input:10] pour sauter + + + Maintenez [Input:10] pour sauter plus haut + + + Maintenez [Input:10] pour sauter plus haut + + + Appuyez sur [Input:12] pour attaquer + + + Appuyez sur [Input:12] pour attaquer + + + Maintenez [Input:18] et appuyez sur [Input:10]\npour descendre + + + Maintenez [Input:18] et appuyez sur [Input:10]\npour descendre + + + (en l'air) Maintenez [Input:18] et appuyez sur [Input:12]\npour une attaque basse + + + (en l'air) Maintenez [Input:18] et appuyez sur [Input:12]\npour une attaque basse + + + Programmation additionnelle + + + Adaptation par + + + Donner {0} d'or pour augmenter définitivement votre spectre pour ce boss ?\nAugmentations : {1} + + + La caissette de dons est pleine à craquer. Votre spectre ne peut plus être augmenté. Merci pour tout cet argent. + + + Vous n'avez pas les moyens de faire un don. Revenez quand vous aurez gagné plus d'or. + + + Votre spectre est devenu plus fort ! + + + Caissette de dons + + + {1} {0} + + + Débloquer traître + + + Saut + + + Maudite + + + Bénie + + + Frais d'architecte + + + NP + Bonus + + + Course + + + Vampire + + + Ciel + + + Siphon + + + Équilibre + + + Vengeance + + + Cagnotte + + + Accélération + + + {1} {0} + + + Localisation & Production du japonais pour + + + Assurance Qualité + + + Vous souffrez de spasmes musculaires incontrôlés. + + + Vous êtes incapable de distinguer les gens. + + + Clonus + + + Prosopagnosia + + + Maudite + + + Bénie + + + Frais d'architecte + + + NP + Bonus + + + Saut + + + Course + + + Vampire + + + Ciel + + + Siphon + + + Équilibre + + + Vengeance + + + Cagnotte + + + Accélération + + + Vous souffrez de spasmes musculaires incontrôlés. + + + Vous êtes incapable de distinguer les gens. + + + Clonus + + + Prosopagnosia + + + Gagnez 60% de l'or total dans le château. + + + Gagnez 60% de l'or total dans le château. + + + Débloquer traître + + + Full Metal Furies\nDurée de développement : 4 ans.\nDate de sortie : 17 janvier 2018 + + + Full Metal Furies vient du futur ! Il s'agit de notre nouveau jeu qui suit Rogue Legacy, le dixième que nous ayons créé. + + + Après RL, nous nous étions promis de ne plus jamais refaire de jeu sans planning préalable. C'était un mensonge. Maudits soient nos nous-du-passé ! + + + Au final, le jeu est devenu notre projet le plus ambitieux, un mélange d'idées de combat/multijoueurs/méta-casse-tête/initiation à la disco qui bouleverserait la vision du jeu de combat traditionnel au fil de la partie. + + + Au bout de 4 ans, FMF représente la plus longue durée que nous ayons jamais passée en développement et, malheureusement, les revenus les plus bas générés par un de nos jeux. (Sauf ces jeux IOS qui nous avaient fait perdre de l'argent.) + + + Néanmoins, nous sommes tout de même immensément fiers de ce que vous avons créé, et encore plus fiers des AMIS QUE NOUS NOUS SOMMES FAITS EN CHEMIN. OOOOOHHHHHH !!! + + + Copyright (C) 2013-2018, Cellar Door Games Inc. + + + {0} est une marque commerciale de Cellar Door Games Inc. Tous droits réservés. + + \ No newline at end of file diff --git a/RogueCastle/Resources/LocStrings.pl.resx b/RogueCastle/Resources/LocStrings.pl.resx new file mode 100644 index 0000000..b9fe47e --- /dev/null +++ b/RogueCastle/Resources/LocStrings.pl.resx @@ -0,0 +1,8349 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Wyjdź na ekran tytułowy + + + Wyjdź na ekran tytułowy + + + Wyjdź na ekran tytułowy (pomiń samouczek) + + + Wyjdź na ekran tytułowy (pomiń samouczek) + + + [Input:25], aby zmienić profil ({0}) + + + [Input:25], aby zmienić profil ({0}) + + + Zdrowie + + + Klawisze ze strzałkami do przemieszczania się + + + Klawisze ze strzałkami do przemieszczania się + + + [Button:LeftStick], aby nawigować + + + [Button:LeftStick], aby nawigować + + + Wybierz kategorię + + + Wybierz kategorię + + + Potrzebne szablony + + + Potrzebne szablony + + + Informacje o zakupie + + + Informacje o zakupie + + + Brak + + + Brak + + + {0}, aby odblokować + + + {0}, aby odblokować + + + Zdrowie + + + Mana + + + Mana + + + Uszkodz. + + + Uszkodz. + + + Magia + + + Magia + + + Zbroja + + + Zbroja + + + Waga + + + Waga + + + Dodatkowe właściwości: + + + Dodatkowe właściwości: + + + [Input:0] Wybierz/wyposaż + + + [Input:0] Wybierz/wyposaż + + + [Input:2] Anuluj/zamknij menu + + + [Input:2] Anuluj/zamknij menu + + + Zniszczone cele + + + Zniszczone cele + + + Pozostałe cele + + + Pozostałe cele + + + Nagroda + + + Nagroda + + + złoto + + + złoto + + + zobacz mapę w dowolnej chwili + + + zobacz mapę w dowolnej chwili + + + Zmień sterowanie + + + Pęd w prawo + + + Pęd w prawo + + + Rzuć zaklęcie + + + Rzuć zaklęcie + + + Zresetuj sterowanie + + + Zresetuj sterowanie + + + Naciśnij dowolny klawisz + + + Naciśnij dowolny klawisz + + + Zmień sterowanie + + + W górę + + + W górę + + + W dół + + + W dół + + + W lewo + + + W lewo + + + W prawo + + + W prawo + + + Atak + + + Atak + + + Skok + + + Skok + + + Specjalne + + + Specjalne + + + Pęd w lewo + + + Pęd w lewo + + + Twoja standardowa postać. Umie wszystko po trochu. + + + Chodzący czołg. Ta postać może wytrzymać niezłe lanie.\nSPECJALNOŚĆ: Barbarzyński okrzyk. + + + Chodzący czołg. Ta postać może wytrzymać niezłe lanie.\nSPECJALNOŚĆ: Barbarzyński okrzyk. + + + Szybkościowiec. Wyrządza ogromne uszkodzenia, ale bez krytycznych. + + + Szybkościówka. Wyrządza ogromne uszkodzenia, ale bez krytycznych. + + + Szybkościowiec. Wyrządza potężne szkody, ale bez krytycznych.\nSPECJALNOŚĆ: Wymiana. + + + Szybkościówka. Wyrządza potężne szkody, ale bez krytycznych.\nSPECJALNOŚĆ: Wymiana. + + + Postać dla zaawansowanych. Trafiając wroga, przywraca manę. + + + Postać dla zaawansowanych. Trafiając wroga, przywraca manę. + + + Postać dla zaawansowanych. Trafiając wroga, przywraca manę.\nSPECJALNOŚĆ: Wzmocniony atak. + + + Postać dla zaawansowanych. Trafiając wroga, przywraca manę.\nSPECJALNOŚĆ: Wzmocniony atak. + + + Nakarm się śmiercią. Zdobądź wieczne życie za każdego zabitego wroga. Niesamowicie inteligentny. + + + Nakarm się śmiercią. Zdobądź wieczne życie za każdego zabitego wroga. Niesamowicie inteligentna. + + + Nakarm się śmiercią. Zdobądź wieczne życie za każdego zabitego wroga. Niesamowicie inteligentny.\nSPECJALNOŚĆ: Przemiana PZ. + + + Nakarm się śmiercią. Zdobądź wieczne życie za każdego zabitego wroga. Niesamowicie inteligentna.\nSPECJALNOŚĆ: Przemiana PZ. + + + Jesteś człowiekiem-smokiem. + + + Jesteś człowiekiem-smoczycą. + + + ????? + + + ????? + + + Twoja standardowa postać. Umie wszystko po trochu. + + + Twoja standardowa postać. Umie wszystko po trochu.\nSPECJALNOŚĆ: Tarcza strażnika. + + + Twoja standardowa postać. Umie wszystko po trochu.\nSPECJALNOŚĆ: Tarcza strażnika. + + + Ryzykant. Ma kiepskie statystyki, ale może zadawać niszczycielskie i krytyczne ciosy. + + + Ryzykantka. Ma kiepskie statystyki, ale może zadawać niszczycielskie i krytyczne ciosy. + + + Ryzykant. Ma kiepskie statystyki, ale może zadawać niszczycielskie i krytyczne ciosy.\nSPECJALNOŚĆ: Mgiełka. + + + Ryzykantka. Ma kiepskie statystyki, ale może zadawać niszczycielskie i krytyczne ciosy.\nSPECJALNOŚĆ: Mgiełka. + + + Postać dla ciułaczy. Bardzo słaby, ale ma ogromne parcie na złoto. + + + Postać dla ciułaczy. Bardzo słaba, ale ma ogromne parcie na złoto. + + + Postać dla ciułaczy. Bardzo słaby, ale ma ogromne parcie na złoto.\nSPECJALNOŚĆ: Czołówka. + + + Postać dla ciułaczy. Bardzo słaba, ale ma ogromne parcie na złoto.\nSPECJALNOŚĆ: Czołówka. + + + Potężny czarodziej. Otrzymasz manę za każdego zabitego wroga. + + + Potężna czarodziejka. Otrzymasz manę za każdego zabitego wroga. + + + Potężny czarodziej. Otrzymujesz manę za każdego zabitego wroga.\nSPECJALNOŚĆ: Cykl zaklęć. + + + Potężna czarodziejka. Otrzymujesz manę za każdego zabitego wroga.\nSPECJALNOŚĆ: Cykl zaklęć. + + + Chodzący czołg. Ta postać może wytrzymać niezłe lanie. + + + Chodzący czołg. Ta postać może wytrzymać niezłe lanie. + + + Królowa Barbarzyńców + + + Królowa Barbarzyńców + + + Król Barbarzyńców + + + Król Barbarzyńców + + + Shinobi + + + Shinobi + + + Hokage + + + Hokage + + + Złodziejka + + + Złodziejka + + + Złodziejaszek + + + Złodziejaszek + + + czarnoksiężnica + + + czarnoksiężnica + + + Czarnoksiężnik + + + Czarnoksiężnik + + + Licz + + + Liczka + + + Królowa Liczów + + + Królowa Liczów + + + Król Liczów + + + Król Liczów + + + Smoczyca + + + Smoczyca + + + Smok + + + Smok + + + Zdrajczyni + + + Zdrajczyni + + + Zdrajca + + + Zdrajca + + + Rycerka + + + Rycerka + + + Rycerz + + + Rycerz + + + Paladyn + + + Paladyn + + + Paladyn + + + Paladyn + + + Szelma + + + Szelma + + + Szelma + + + Szelma + + + Zabójczyni + + + Zabójczyni + + + Zabójca + + + Zabójca + + + Górniczka + + + Górniczka + + + Górnik + + + Górnik + + + Grotołazka + + + Grotołazka + + + Grotołaz + + + Grotołaz + + + Mag + + + Mag + + + Mag + + + Mag + + + Arcymag + + + Arcymag + + + Arcymag + + + Arcymag + + + Barbarzyńca + + + Barbarzyńca + + + Barbarzyńca + + + Barbarzyńca + + + Dziękujemy za grę! + + + Grafika + + + Grafika + + + Muzyka i udźwiękowienie + + + Muzyka i udźwiękowienie + + + Muzyka + + + Muzyka + + + Marketing i fabuła + + + Marketing i fabuła + + + Dodatkowe udźwiękowienie + + + Dodatkowe udźwiękowienie + + + Dodatkowe grafika tła + + + Dodatkowe grafika tła + + + Wsparcie biznesowe + + + Wsparcie biznesowe + + + Super specjalne podziękowania: Turbo Edition + + + Super specjalne podziękowania: Turbo Edition + + + Specjalne podziękowania + + + Specjalne podziękowania + + + Dodatkowe podziękowania + + + Dodatkowe podziękowania + + + Dziękujemy za grę! + + + Dzieci łącznie + + + Adaptacja wersji Mac/Linux + + + Adaptacja wersji Mac/Linux + + + Dział kontroli jakości wersji Mac/Linux + + + Dział kontroli jakości wersji Mac/Linux + + + Wszystkim naszym fanom dziękujemy za wsparcie! + + + Wszystkim naszym fanom dziękujemy za wsparcie! + + + Pierwotna lokalizacja + + + Pierwotna lokalizacja + + + Lokalizacja wersji chińskiej oraz dodatkowe prace lokalizacyjne + + + Lokalizacja wersji chińskiej oraz dodatkowe prace lokalizacyjne + + + Dzieci łącznie + + + Czas gry + + + Czas gry + + + Naciśnij [Input:0], aby wyjść + + + Naciśnij [Input:0], aby wyjść + + + Autorzy + + + Autorzy + + + Projekt i fabuła + + + Projekt i fabuła + + + Programowanie + + + Programowanie + + + Produkcja + + + Produkcja + + + Martwa strefa drążka + + + Martwa strefa drążka + + + Usuń zapis + + + Usuń zapis + + + Dziennik księcia + + + Chociaż jestem najstarszy, nie jestem ulubieńcem mojego ojca. Zawsze wiedziałem, że planował pozostawić mnie z niczym. + + + ...a co, jeśli się pomyliłem i wziąłem któregoś z nich za potwora? + + + ...a co, jeśli się pomyliłem i wziąłem któregoś z nich za potwora? + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 17 + + + Wpis w dzienniku nr 17 + + + Chyba oszalałem. W zamku natknąłem się na karnawał. No i był tam jeszcze smutny klaun. + + + Chyba oszalałem. W zamku natknąłem się na karnawał. No i był tam jeszcze smutny klaun. + + + Głupek z niego. Ale chyba w takim miejscu nie można mieć wymagań co do przyjaciół. + + + Głupek z niego. Ale chyba w takim miejscu nie można mieć wymagań co do przyjaciół. + + + Znowu robię się głodny. Dobrze, że uzupełniłem zapasy nóżek z kurczaka. Znalazłem je w kandelabrze. + + + Znowu robię się głodny. Dobrze, że uzupełniłem zapasy nóżek z kurczaka. Znalazłem je w kandelabrze. + + + Ten zamek... Czasem się zastanawiam, czy to wszystko nie jest jednym wielkim żartem. + + + Ten zamek... Czasem się zastanawiam, czy to wszystko nie jest jednym wielkim żartem. + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 18 + + + Wpis w dzienniku nr 18 + + + Pokonałem bestię z wieży i znów poczułem, że sala tronowa utraciła część swojej mocy. + + + Pokonałem bestię z wieży i znów poczułem, że sala tronowa utraciła część swojej mocy. + + + Chociaż jestem najstarszy, nie jestem ulubieńcem mojego ojca. Zawsze wiedziałem, że planował pozostawić mnie z niczym. + + + Ale jeśli znajdę lekarstwo, wszystko się zmieni. + + + Moc, którą poczułem po tym zwycięstwie, jest odurzająca! Nigdy wcześniej nie czułem się tak pewny siebie, tak potężny, tak... na właściwym miejscu. Jeszcze tylko trochę i zdobędę moją nagrodę! + + + Moc, którą poczułem po tym zwycięstwie, jest odurzająca! Nigdy wcześniej nie czułem się tak pewny siebie, tak potężny, tak... na właściwym miejscu. Jeszcze tylko trochę i zdobędę moją nagrodę! + + + Jestem tak blisko! Mój ojciec będzie ze mnie dumny! + + + Jestem tak blisko! Mój ojciec będzie ze mnie dumny! + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 19 + + + Wpis w dzienniku nr 19 + + + Stoję przed bramą lochów dłużej, niż mógłbym przyznać. + + + Stoję przed bramą lochów dłużej, niż mógłbym przyznać. + + + Gdy podejrzałem potwory tam na dole, moja odwaga w końcu się wyczerpała. Przy nich moje wcześniejsze zmagania wydają się śmiechu warte. + + + Gdy podejrzałem potwory tam na dole, moja odwaga w końcu się wyczerpała. Przy nich moje wcześniejsze zmagania wydają się śmiechu warte. + + + Muszę wziąć się w garść. Muszę się skoncentrować. Na dole jest tak mało światła. Boję się, że mogę się zgubić. + + + Muszę wziąć się w garść. Muszę się skoncentrować. Na dole jest tak mało światła. Boję się, że mogę się zgubić. + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 20 + + + Wpis w dzienniku nr 20 + + + Myślałem, że wiem, co to ciemność, ale tu w tych lochach ciemność mówi własnym głosem. + + + Myślałem, że wiem, co to ciemność, ale tu w tych lochach ciemność mówi własnym głosem. + + + Ale jeśli znajdę lekarstwo, wszystko się zmieni. + + + Zwycięzca otrzyma tron po jego śmierci! + + + Woła do mnie zza krat, zza rogów. Drażni się ze mną. + + + Woła do mnie zza krat, zza rogów. Drażni się ze mną. + + + Ciemność jest taka nieprzenikniona, prawie namacalna, a bestie czują się tu jak w domu. Poruszają się zwinnie korytarzami i przerażają mnie bardziej niż cokolwiek do tej pory. + + + Ciemność jest taka nieprzenikniona, prawie namacalna, a bestie czują się tu jak w domu. Poruszają się zwinnie korytarzami i przerażają mnie bardziej niż cokolwiek do tej pory. + + + Muszę być rozważny i ostrożnie wybierać, kiedy walczyć. Niepotrzebne potyczki mogą kosztować mnie życie. + + + Muszę być rozważny i ostrożnie wybierać, kiedy walczyć. Niepotrzebne potyczki mogą kosztować mnie życie. + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 21 + + + Wpis w dzienniku nr 21 + + + Udało się! Właśnie pokonałem władcę lochów! Teraz pozostaje już tylko wejść do sali tronowej. + + + Udało się! Właśnie pokonałem władcę lochów! Teraz pozostaje już tylko wejść do sali tronowej. + + + Teraz król nagrodzi moje męstwo i uzna mnie za prawowitego następcę tronu. + + + Teraz król nagrodzi moje męstwo i uzna mnie za prawowitego następcę tronu. + + + Nie moje rodzeństwo! + + + Nie moje rodzeństwo! + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 22 + + + Wpis w dzienniku nr 22 + + + Zwycięzca otrzyma tron po jego śmierci! + + + Wtedy moja żona i moje dzieci przeniosą się z powrotem do komnat królewskich. Wrócimy do królewskiego miasta, gdzie – tak jak dawniej – będą nas traktować z należytym szacunkiem! + + + Siedzę i robię ostatnie przygotowania. Wszystko, co stoi pomiędzy mną i panem tego zamku, to złote drzwi. + + + Siedzę i robię ostatnie przygotowania. Wszystko, co stoi pomiędzy mną i panem tego zamku, to złote drzwi. + + + Moje ciało ogarnęła nerwowość, której nie umiem opanować. Czy to strach, czy także podekscytowanie? Wszystko, co wiem, to że moja podróż wreszcie zbliża się do końca. + + + Moje ciało ogarnęła nerwowość, której nie umiem opanować. Czy to strach, czy także podekscytowanie? Wszystko, co wiem, to że moja podróż wreszcie zbliża się do końca. + + + Już prawie zapomniałem, po co właściwie przybyłem do tego zamku, ale teraz mi się przypomniało. + + + Już prawie zapomniałem, po co właściwie przybyłem do tego zamku, ale teraz mi się przypomniało. + + + Wyprzedziłem moje rodzeństwo, ocalę króla i wyjdę z tego zamku jako człowiek wspanialszy od tego, którym byłem, gdy tu wchodziłem. Moja rodzina zdobędzie honor, na który zasługuje. + + + Wyprzedziłem moje rodzeństwo, ocalę króla i wyjdę z tego zamku jako człowiek wspanialszy od tego, którym byłem, gdy tu wchodziłem. Moja rodzina zdobędzie honor, na który zasługuje. + + + Cóż, wchodzę do sali tronowej. + + + Cóż, wchodzę do sali tronowej. + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 23 + + + Wpis w dzienniku nr 23 + + + Nie miałem pojęcia, jaki skarb znajduje się w tym zamku. Wiedziałem tylko, że uzdrowi króla. + + + Nie miałem pojęcia, jaki skarb znajduje się w tym zamku. Wiedziałem tylko, że uzdrowi króla. + + + Kto by się spodziewał, że to będzie fontanna młodości? + + + Kto by się spodziewał, że to będzie fontanna młodości? + + + Spodziewałem się czekającego na mnie potwora. Wroga o niewyobrażalnej sile. Wyobrażałem sobie, że pokonanie go będzie mnie wiele kosztować. + + + Spodziewałem się czekającego na mnie potwora. Wroga o niewyobrażalnej sile. Wyobrażałem sobie, że pokonanie go będzie mnie wiele kosztować. + + + Wtedy moja żona i moje dzieci przeniosą się z powrotem do komnat królewskich. Wrócimy do królewskiego miasta, gdzie – tak jak dawniej – będą nas traktować z należytym szacunkiem! + + + Nie będziemy już musieli znosić plotek i oszczerstw ze strony moich kuzynów. Inni książęta będą musieli nam się kłaniać. Ale wybiegam za bardzo do przodu. + + + Ale gdy wszedłem do zamku i zobaczyłem mojego ojca – króla – siedzącego ze złotym kielichem w ręku, wiedziałem, że wszystko przepadło. + + + Ale gdy wszedłem do zamku i zobaczyłem mojego ojca – króla – siedzącego ze złotym kielichem w ręku, wiedziałem, że wszystko przepadło. + + + On nigdy nie umrze... + + + On nigdy nie umrze... + + + ...i nigdy nie zostanę jego następcą. + + + ...i nigdy nie zostanę jego następcą. + + + Brak mi słów, by opisać, co czuję. + + + Brak mi słów, by opisać, co czuję. + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 24 + + + Wpis w dzienniku nr 24 + + + .............................. + + + .............................. + + + .... + + + .... + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 25 + + + Wpis w dzienniku nr 25 + + + Nie będziemy już musieli znosić plotek i oszczerstw ze strony moich kuzynów. Inni książęta będą musieli nam się kłaniać. Ale wybiegam za bardzo do przodu. + + + Muszę wyraźnie określić swoje priorytety. Zdobyć zamek. Znaleźć lekarstwo. Odebrać nagrodę. + + + Dzisiaj kończy się wieczność. + + + Dzisiaj kończy się wieczność. + + + Nie miałem pojęcia, jaki skarb znajduje się w tym zamku. Wiedziałem tylko, że wyleczy króla z choroby. + + + Nie miałem pojęcia, jaki skarb znajduje się w tym zamku. Wiedziałem tylko, że wyleczy króla z choroby. + + + ... Kto by się spodziewał, że to będzie fontanna młodości? Mit dający wieczne życie. + + + ... Kto by się spodziewał, że to będzie fontanna młodości? Mit dający wieczne życie. + + + Gdy spoglądam na ciało króla, wiem, że to nieuniknione. Dzieci zawsze odpowiedzą za grzechy ojca. + + + Gdy spoglądam na ciało króla, wiem, że to nieuniknione. Dzieci zawsze odpowiedzą za grzechy ojca. + + + Wszedłem do zamku jako wojownik, wybawca... + + + Wszedłem do zamku jako wojownik, wybawca... + + + A zostało mi tylko moje dziedzictwo. + + + A zostało mi tylko moje dziedzictwo. + + + Czuję Twój gniew, ale wiem, że to nie ja zrujnowałem Twoją rodzinę. + + + Czuję Twój gniew, ale wiem, że to nie ja zrujnowałem Twoją rodzinę. + + + W momencie, w którym król przekroczył próg tego zamku, królewskie kufry zostały opróżnione przez Charona. Moja rodzina – wszystkie rodziny – utraciły nadzieję na lepsze życie. + + + W momencie, w którym król przekroczył próg tego zamku, królewskie kufry zostały opróżnione przez Charona. Moja rodzina – wszystkie rodziny – utraciły nadzieję na lepsze życie. + + + A oczami duszy widziałem tylko desperację i biedę wyniszczające kraj. Nie miałem do czego wracać. + + + A oczami duszy widziałem tylko desperację i biedę wyniszczające kraj. Nie miałem do czego wracać. + + + Do moich dzieci, dzieci moich dzieci, oto tu siedzę, niewzruszony, nieśmiertelny, i czekam na Was. + + + Do moich dzieci, dzieci moich dzieci, oto tu siedzę, niewzruszony, nieśmiertelny, i czekam na Was. + + + Muszę wyraźnie określić swoje priorytety. Zdobyć zamek. Znaleźć lekarstwo. Odebrać nagrodę. + + + Dziennik księcia + + + Johanes + + + Johanes + + + Co to ma być? Czy Ty... drwisz ze mnie?! + + + Co to ma być? Czy Ty... drwisz ze mnie?! + + + Po tym, jak niezliczone pokolenia Twoich przodków poświęciły życie, by dotrzeć tu, gdzie Ty teraz jesteś, wykonać te ostatnie kroki. A Ty przybywasz i drwisz ze mnie? + + + Po tym, jak niezliczone pokolenia Twoich przodków poświęciły życie, by dotrzeć tu, gdzie Ty teraz jesteś, wykonać te ostatnie kroki. A Ty przybywasz i drwisz ze mnie? + + + Bardzo dobrze, daruję sobie Twoją ignorancję. Zaczynajmy! + + + Bardzo dobrze, daruję sobie Twoją ignorancję. Zaczynajmy! + + + Johanes + + + Johanes + + + Dlaczego chcesz ze mną walczyć? Ilu synów i ile córek zostało straconych w Twoich żałosnych próbach zemsty? + + + Dlaczego chcesz ze mną walczyć? Ilu synów i ile córek zostało straconych w Twoich żałosnych próbach zemsty? + + + To król zrujnował Twoje królestwo, nie ja! + + + To król zrujnował Twoje królestwo, nie ja! + + + Okłamał nas. Powiedział, że jest ranny, a tymczasem jedynym zagrożeniem był dla niego czas. + + + Okłamał nas. Powiedział, że jest ranny, a tymczasem jedynym zagrożeniem był dla niego czas. + + + Podburzał swoje dzieci jedno przeciw drugiemu, poświęcił wszystko, by zaspokoić swoje egoistyczne żądze, a w końcu zostawił nas samych, bez grosza. + + + Podburzał swoje dzieci jedno przeciw drugiemu, poświęcił wszystko, by zaspokoić swoje egoistyczne żądze, a w końcu zostawił nas samych, bez grosza. + + + Dlatego zrobiłem jedyną rzecz, która mi pozostała. Wyrzekłem się króla i kraju... + + + Dlatego zrobiłem jedyną rzecz, która mi pozostała. Wyrzekłem się króla i kraju... + + + Dziennik księcia + + + Wpis w dzienniku nr 3 + + + I wybrałem nową rodzinę! + + + I wybrałem nową rodzinę! + + + Johanes + + + Johanes + + + Myślisz, że mnie zgładziłeś? + + + Myślisz, że mnie zgładziłeś? + + + Żyłem przez ponad tysiąc lat i będę żył przez kolejny tysiąc! + + + Żyłem przez ponad tysiąc lat i będę żył przez kolejny tysiąc! + + + Aleksander... Khidr... Leon... + + + Aleksander... Khidr... Leon... + + + Nie byłem pierwszym bohaterem, który dotarł do fontanny... + + + Nie byłem pierwszym bohaterem, który dotarł do fontanny... + + + Ale będę ostatnim! + + + Ale będę ostatnim! + + + Fontanna młodości + + + Fontanna młodości + + + ... + + + ... + + + Udało Ci się mnie pokonać... Ale za jaką cenę? + + + Udało Ci się mnie pokonać... Ale za jaką cenę? + + + Wpis w dzienniku nr 3 + + + Zapracowałem sobie na to i dostałem się do zamku. Ten diabeł Charon zabrał wszystko, co miałem, jako swoją zapłatę. + + + Może i zgładziłem króla, ale on wcześniej zdradził swoich ludzi. + + + Może i zgładziłem króla, ale on wcześniej zdradził swoich ludzi. + + + Sam siebie zapytaj, jaka to sprawiedliwość? + + + Sam siebie zapytaj, jaka to sprawiedliwość? + + + Tak naprawdę wszyscy jesteśmy winni popełnienia tego samego grzechu. Spójrz na swoich przodków – taki jest koszt niekwestionowanej lojalności. + + + Tak naprawdę wszyscy jesteśmy winni popełnienia tego samego grzechu. Spójrz na swoich przodków – taki jest koszt niekwestionowanej lojalności. + + + ... + + + ... + + + ... + + + ... + + + Słońce... + + + Słońce... + + + Już nie pamiętam, jakie to uczucie. + + + Już nie pamiętam, jakie to uczucie. + + + Zapracowałem sobie na to i dostałem się do zamku. Ten diabeł Charon zabrał wszystko, co miałem, jako swoją zapłatę. + + + Zwędził nawet moje prywatne kufry! Moja żona i dzieci zostaną z niczym. + + + Zwędził nawet moje prywatne kufry! Moja żona i dzieci zostaną z niczym. + + + Dziennik księcia + + + Wpis w dzienniku nr 1 + + + Mówi, że to cena, jaką muszą zapłacić ci, którzy ośmielają się zejść do głębin zamku. Mówi, że to jest sprawiedliwe. + + + Mówi, że to cena, jaką muszą zapłacić ci, którzy ośmielają się zejść do głębin zamku. Mówi, że to jest sprawiedliwe. + + + To jest sprawiedliwe, bo ze wszystkich, którzy weszli, nikt nie wrócił. Ale ja to zmienię. + + + To jest sprawiedliwe, bo ze wszystkich, którzy weszli, nikt nie wrócił. Ale ja to zmienię. + + + Będę zwycięzcą! Nikt nie włada mieczem lepiej ode mnie, nawet wśród mojego rodzeństwa. + + + Będę zwycięzcą! Nikt nie włada mieczem lepiej ode mnie, nawet wśród mojego rodzeństwa. + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 4 + + + Wpis w dzienniku nr 4 + + + Ten zamek jest okropny. Nie za bardzo wiem, gdzie idę. No i nie ma słońca i gwiazd, które by mnie poprowadziły. + + + Ten zamek jest okropny. Nie za bardzo wiem, gdzie idę. No i nie ma słońca i gwiazd, które by mnie poprowadziły. + + + Cały czas muszę się cofać i dokładnie zaznaczać moje postępy, żeby nie chodzić w kółko. + + + Cały czas muszę się cofać i dokładnie zaznaczać moje postępy, żeby nie chodzić w kółko. + + + Mapy, które zabrałem trupom innych poszukiwaczy przygód, są straszliwie niedokładne. Jakby opisywały zupełnie inny zamek! + + + Mapy, które zabrałem trupom innych poszukiwaczy przygód, są straszliwie niedokładne. Jakby opisywały zupełnie inny zamek! + + + Może to miejsce szkodzi na głowę... + + + Może to miejsce szkodzi na głowę... + + + Czy te kamienie pode mną rzeczywiście się przesuwają? + + + Czy te kamienie pode mną rzeczywiście się przesuwają? + + + Wpis w dzienniku nr 1 + + + Zdrada! Zabójca zranił mojego ojca, króla! + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 5 + + + Wpis w dzienniku nr 5 + + + Nie mogę wyjść przez główną bramę, ale to niewielkie zmartwienie. Jestem oddany mojej sprawie i nie wycofam się! + + + Nie mogę wyjść przez główną bramę, ale to niewielkie zmartwienie. Jestem oddany mojej sprawie i nie wycofam się! + + + Do tej pory żadna z map, które tu znalazłem, nie pokrywa się z moją własną. + + + Do tej pory żadna z map, które tu znalazłem, nie pokrywa się z moją własną. + + + Jednak porównując je całościowo, wydaje mi się, że mam jakiś zarys. Wygląda na to, że las jest zawsze po prawej stronie, a wieża na górze... + + + Jednak porównując je całościowo, wydaje mi się, że mam jakiś zarys. Wygląda na to, że las jest zawsze po prawej stronie, a wieża na górze... + + + A na dole? Cóż, mam nadzieję, że się nie dowiem. + + + A na dole? Cóż, mam nadzieję, że się nie dowiem. + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 6 + + + Wpis w dzienniku nr 6 + + + Nigdy nie lubiłem ciemności. Wolę spotykać moich wrogów na otwartej przestrzeni, gdzie dobrze ich widzę. + + + Nigdy nie lubiłem ciemności. Wolę spotykać moich wrogów na otwartej przestrzeni, gdzie dobrze ich widzę. + + + Ale teraz muszę przemierzać te ciemne korytarze z jedną ręką przy rękojeści mojego miecza i drugą w pozycji obronnej. Tutaj nigdy nie wiadomo, co czai się za następnym rogiem. + + + Ale teraz muszę przemierzać te ciemne korytarze z jedną ręką przy rękojeści mojego miecza i drugą w pozycji obronnej. Tutaj nigdy nie wiadomo, co czai się za następnym rogiem. + + + Zdrada! Zabójca zranił mojego ojca, króla! + + + Aby przywrócić pokój w królestwie, król wysłał mnie i moje rodzeństwo na misję, by go ocalić. Razem udamy się do przeklętego lasu i wejdziemy do Zamku Hamson. + + + Władam mieczem najlepiej ze wszystkich na tych terenach, ale nawet ja mam kłopot z powstrzymywaniem tych demonów. + + + Władam mieczem najlepiej ze wszystkich na tych terenach, ale nawet ja mam kłopot z powstrzymywaniem tych demonów. + + + Moje rodzeństwo powinno być wdzięczne, że wyruszyłem przed nimi. Dla nich to szczęście w nieszczęściu. Nie udałoby im się przeżyć w tym zamku. + + + Moje rodzeństwo powinno być wdzięczne, że wyruszyłem przed nimi. Dla nich to szczęście w nieszczęściu. Nie udałoby im się przeżyć w tym zamku. + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 7 + + + Wpis w dzienniku nr 7 + + + Wciąż jest noc. Za każdym oknem ten sam melancholijny księżyc, ale przysięgam, że spędziłem tu przynajmniej jeden pełny dzień. + + + Wciąż jest noc. Za każdym oknem ten sam melancholijny księżyc, ale przysięgam, że spędziłem tu przynajmniej jeden pełny dzień. + + + To na pewno adrenalina. Nigdy nie czułem się tak potężny, a jednocześnie nie stało przede mną tyle wyzwań. To takie podniecające móc przedzierać się przez te komnaty, pokonując wroga za wrogiem. + + + To na pewno adrenalina. Nigdy nie czułem się tak potężny, a jednocześnie nie stało przede mną tyle wyzwań. To takie podniecające móc przedzierać się przez te komnaty, pokonując wroga za wrogiem. + + + Przeciwnicy w tym zamku wydają się być w pewien sposób do mnie dopasowani. Uczyli mnie, prowadzili, obserwowali. + + + Przeciwnicy w tym zamku wydają się być w pewien sposób do mnie dopasowani. Uczyli mnie, prowadzili, obserwowali. + + + To zabrzmi jak szaleństwo, ale jeśli ten zamek wyczuwa czyjąś obecność, obawiam się, że może też mieć niecne zamiary. Jeśli moje założenia są właściwe, układ tych korytarzy może być podstępem, żeby wciągnąć mnie w pułapkę. + + + To zabrzmi jak szaleństwo, ale jeśli ten zamek wyczuwa czyjąś obecność, obawiam się, że może też mieć niecne zamiary. Jeśli moje założenia są właściwe, układ tych korytarzy może być podstępem, żeby wciągnąć mnie w pułapkę. + + + Muszę być ostrożny. + + + Muszę być ostrożny. + + + Dziennik księcia + + + Dziennik księcia + + + Aby przywrócić pokój w królestwie, król wysłał mnie i moje rodzeństwo na misję, by go ocalić. Razem udamy się do przeklętego lasu i wejdziemy do Zamku Hamson. + + + Ten przeklęty zamek stoi od niepamiętnych czasów na skraju lasu. Plotki głoszą, że znajduje się w nim przedmiot, który może uleczyć każdą dolegliwość. + + + Wpis w dzienniku nr 8 + + + Wpis w dzienniku nr 8 + + + Patrząc na to, ilu martwych śmiałków minąłem w tych korytarzach, doszedłem do następujących wniosków: + + + Patrząc na to, ilu martwych śmiałków minąłem w tych korytarzach, doszedłem do następujących wniosków: + + + 1: Wielu z nich nie wzięło ze sobą dość zapasów. Zakładam, że mogli umrzeć \nz głodu. Sam mam już niewiele i będę musiał znaleźć coś do jedzenia. + + + 1: Wielu z nich nie wzięło ze sobą dość zapasów. Zakładam, że mogli umrzeć \nz głodu. Sam mam już niewiele i będę musiał znaleźć coś do jedzenia. + + + 2: Wielu z nich nie ma ubrań, co wyjaśnia, czemu zombie chodzą w spodniach. + + + 2: Wielu z nich nie ma ubrań, co wyjaśnia, czemu zombie chodzą w spodniach. + + + 3: Nikt nie dotarł tak daleko jak ja, ponieważ nie minąłem żadnego ciała od ponad godziny. + + + 3: Nikt nie dotarł tak daleko jak ja, ponieważ nie minąłem żadnego ciała od ponad godziny. + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 9 + + + Wpis w dzienniku nr 9 + + + Drzwi do sali tronowej doprowadzają mnie do szaleństwa! Za nimi znajduje się wybawienie dla króla i moja nagroda, ale stoją głucho w środku zamkowego holu, prześladując mnie. + + + Drzwi do sali tronowej doprowadzają mnie do szaleństwa! Za nimi znajduje się wybawienie dla króla i moja nagroda, ale stoją głucho w środku zamkowego holu, prześladując mnie. + + + Próbowałem je popychać, kopać, krzyczeć: „Sezamie, otwórz się”, ale nic nie działa. + + + Próbowałem je popychać, kopać, krzyczeć: „Sezamie, otwórz się”, ale nic nie działa. + + + Drzwi są ozdobione obrazkami, jeden z nich wygląda jak bestia, której umknąłem tam głębiej w zamku. Może jest tu jakiś związek? + + + Drzwi są ozdobione obrazkami, jeden z nich wygląda jak bestia, której umknąłem tam głębiej w zamku. Może jest tu jakiś związek? + + + Ten przeklęty zamek stoi od niepamiętnych czasów na skraju lasu. Plotki głoszą, że znajduje się w nim przedmiot, który może uleczyć każdą dolegliwość. + + + Wieczorem, by zdobyć przewagę nad moimi braćmi i siostrami, wyruszę na wyprawę, gdy oni będą jeszcze spać. + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 10 + + + Wpis w dzienniku nr 10 + + + Symbole na zamkowych drzwiach to wskazówka! Zgładziłem tę wielką bestię, która pasowała do jednego z obrazków i czułem, że coś się poruszyło za drzwiami sali tronowej. + + + Symbole na zamkowych drzwiach to wskazówka! Zgładziłem tę wielką bestię, która pasowała do jednego z obrazków i czułem, że coś się poruszyło za drzwiami sali tronowej. + + + Tak jak we śnie, oczami duszy widziałem, jak symbol na drzwiach błyszczy. + + + Tak jak we śnie, oczami duszy widziałem, jak symbol na drzwiach błyszczy. + + + Prawdziwie nieziemskie przeżycie. + + + Prawdziwie nieziemskie przeżycie. + + + Przynajmniej wiem, że zmierzam w dobrym kierunku... Muszę się pospieszyć, bo król może w każdej chwili umrzeć od odniesionych ran. + + + Przynajmniej wiem, że zmierzam w dobrym kierunku... Muszę się pospieszyć, bo król może w każdej chwili umrzeć od odniesionych ran. + + + Ale najpierw muszę odpocząć. Jutro wchodzę do lasu. + + + Ale najpierw muszę odpocząć. Jutro wchodzę do lasu. + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 11 + + + Wpis w dzienniku nr 11 + + + Ten las nie przypomina niczego, co do tej pory widziałem. Jest i spokojny, \ni przerażający. Stoję na bujnej trawie, a tuż obok zieje przerażająca otchłań, tak szeroka i głęboka, jakby chciała mnie pochłonąć w całości. + + + Ten las nie przypomina niczego, co do tej pory widziałem. Jest i spokojny, \ni przerażający. Stoję na bujnej trawie, a tuż obok zieje przerażająca otchłań, tak szeroka i głęboka, jakby chciała mnie pochłonąć w całości. + + + Wieczorem, by zdobyć przewagę nad moimi braćmi i siostrami, wyruszę na wyprawę, gdy oni będą jeszcze spać. + + + Niepowodzenie w tej misji okryłoby hańbą moje imię. + + + Nadal nie słyszałem dźwięku kamienia, który wcześniej wrzuciłem. Jeden fałszywy krok, a zszedłbym na wieki. To naprawdę przerażająca myśl. + + + Nadal nie słyszałem dźwięku kamienia, który wcześniej wrzuciłem. Jeden fałszywy krok, a zszedłbym na wieki. To naprawdę przerażająca myśl. + + + Wieczność w ciemności jest bardziej przerażająca niż każda z bestii, z którymi do tej pory walczyłem. Gdybym spadł, co by mnie zabiło najpierw? Umarłbym\nz głodu czy zginął z własnej ręki? + + + Wieczność w ciemności jest bardziej przerażająca niż każda z bestii, z którymi do tej pory walczyłem. Gdybym spadł, co by mnie zabiło najpierw? Umarłbym\nz głodu czy zginął z własnej ręki? + + + Z drugiej strony, używam tej leśnej rozpadliny jako prywatnej ubikacji. Ciekawe, czy moja kupa leci do innego wymiaru... + + + Z drugiej strony, używam tej leśnej rozpadliny jako prywatnej ubikacji. Ciekawe, czy moja kupa leci do innego wymiaru... + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 12 + + + Wpis w dzienniku nr 12 + + + Znalazłem sposób na mój głód. Las ma nieograniczone zapasy przepysznych grzybów. + + + Znalazłem sposób na mój głód. Las ma nieograniczone zapasy przepysznych grzybów. + + + A pomiędzy tymi grzybami leżą nóżki z kurczaka! A także złote monety i butelki czystej wody... Wcześniej uderzyłem w pień drzewa i wypadł z niego worek pieniędzy. + + + A pomiędzy tymi grzybami leżą nóżki z kurczaka! A także złote monety i butelki czystej wody... Wcześniej uderzyłem w pień drzewa i wypadł z niego worek pieniędzy. + + + Czasami wydaje mi się, że zwariowałem. + + + Czasami wydaje mi się, że zwariowałem. + + + ... Poza tym, co się stało z księżycem? Jest OGROMNY! + + + ... Poza tym, co się stało z księżycem? Jest OGROMNY! + + + Dziennik księcia + + + Dziennik księcia + + + Niepowodzenie w tej misji okryłoby hańbą moje imię. + + + Dziennik księcia + + + Wpis w dzienniku nr 13 + + + Wpis w dzienniku nr 13 + + + Zgładziłem leśną bestię i poczułem, że sala tronowa znów straciła część swojej mocy. + + + Zgładziłem leśną bestię i poczułem, że sala tronowa znów straciła część swojej mocy. + + + Do tej pory moje założenia się sprawdziły. Każde skrzydło zamku ma swoją opiekuńczą bestię. Czy to było pomyślane jako test woli? Jeśli tak, nie mogę go oblać, gdyż im dalej idę, tym odważniejszy się staję! + + + Do tej pory moje założenia się sprawdziły. Każde skrzydło zamku ma swoją opiekuńczą bestię. Czy to było pomyślane jako test woli? Jeśli tak, nie mogę go oblać, gdyż im dalej idę, tym odważniejszy się staję! + + + Jutro przeszukam wieżę. Nieźle mi idzie. + + + Jutro przeszukam wieżę. Nieźle mi idzie. + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 14 + + + Wpis w dzienniku nr 14 + + + Systematycznie pozbywam się demonów z tych komnat, by zgładzić następnego opiekuna, ale tracę poczucie czasu... i nie tylko... + + + Systematycznie pozbywam się demonów z tych komnat, by zgładzić następnego opiekuna, ale tracę poczucie czasu... i nie tylko... + + + Gdy wszedłem do wieży, poczułem, jakby czas się zatrzymał. A może to był zawrót głowy? Nigdy nie przepadałem za wysokością... A może tak? + + + Gdy wszedłem do wieży, poczułem, jakby czas się zatrzymał. A może to był zawrót głowy? Nigdy nie przepadałem za wysokością... A może tak? + + + Coraz trudniej mi przypomnieć sobie przeszłość... + + + Coraz trudniej mi przypomnieć sobie przeszłość... + + + Dziennik księcia + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 2 + + + Wpis w dzienniku nr 15 + + + Wpis w dzienniku nr 15 + + + Pamiętam, że byłem słynnym poszukiwaczem przygód. Moje bojowe męstwo przewyższało męstwo moich braci. Tak było. Kiedy oni spędzali czas wśród ksiąg, ja zabijałem bandytów i potwory. + + + Pamiętam, że byłem słynnym poszukiwaczem przygód. Moje bojowe męstwo przewyższało męstwo moich braci. Tak było. Kiedy oni spędzali czas wśród ksiąg, ja zabijałem bandytów i potwory. + + + Zawsze się zastanawiałem, dlaczego ojciec wolał ich ode mnie? Czy w bajkach zwykle nie jest inaczej? + + + Zawsze się zastanawiałem, dlaczego ojciec wolał ich ode mnie? Czy w bajkach zwykle nie jest inaczej? + + + Los sprzyja odważnym. Nie nudnym intelektualistom... Czy jakoś tak. + + + Los sprzyja odważnym. Nie nudnym intelektualistom... Czy jakoś tak. + + + Rany, chciałbym zobaczyć moich braci, jak myślą z mieczem przystawionym do gardła! + + + Rany, chciałbym zobaczyć moich braci, jak myślą z mieczem przystawionym do gardła! + + + Dziennik księcia + + + Dziennik księcia + + + Wpis w dzienniku nr 16 + + + Wpis w dzienniku nr 16 + + + A co, jeśli od mojego wejścia w te mury minęły już lata? To prawda, że nabieram biegłości w zwalczaniu potworów, ale wydaje mi się, że minęły już całe wieki. + + + A co, jeśli od mojego wejścia w te mury minęły już lata? To prawda, że nabieram biegłości w zwalczaniu potworów, ale wydaje mi się, że minęły już całe wieki. + + + Zapomniałem już nawet, jak wygląda moja rodzina. + + + Zapomniałem już nawet, jak wygląda moja rodzina. + + + A co, jeśli myślą, że mi się nie udało? Co, jeśli jeden z moich braci wyprzedził mnie i zdobył lekarstwo? + + + A co, jeśli myślą, że mi się nie udało? Co, jeśli jeden z moich braci wyprzedził mnie i zdobył lekarstwo? + + + Wpis w dzienniku nr 2 + + + Wpis nr + + + Wpis nr + + + Zamek Hamson + + + Zamek Hamson + + + Kraina Mroku + + + Kraina Mroku + + + Las Abchaski + + + Las Abchaski + + + Maya + + + Maya + + + Wybierz kategorię + + + Potrzeba run + + + Potrzeba run + + + Informacje o zakupie + + + Informacje o zakupie + + + {0}, aby odblokować + + + {0}, aby odblokować + + + Runa + + + Runa + + + Wybierz kategorię + + + Instrukcje + + + Instrukcje + + + [Input:0] Wybierz/wyposaż + + + [Input:0] Wybierz/wyposaż + + + [Input:2] Anuluj/zamknij menu + + + [Input:2] Anuluj/zamknij menu + + + Klawisze ze strzałkami do przemieszczania się + + + Klawisze ze strzałkami do przemieszczania się + + + [Button:LeftStick], aby nawigować + + + [Button:LeftStick], aby nawigować + + + Zabity + + + Zabita + + + Naciśnij [Input:0], aby wyjść + + + Naciśnij [Input:0], aby wyjść + + + Szkielet + + + Kleksaurus Rex + + + Dziadek Iskierka + + + Dziadek Iskierka + + + Lord Iskierka, król Iskrolandii + + + Lord Iskra, król Iskrolandii + + + Mim + + + Mimka + + + Imitator + + + Imitatorka + + + Mimitor + + + Mimitorka + + + Szachek + + + Szacheczka + + + Barbatos + + + Barbatoska + + + Stolas + + + Stolaska + + + Beryt + + + Berytka + + + Amon + + + Amonka + + + Kleksaurus Rex + + + Herodotek + + + Fokalor + + + Fokalorka + + + Halpas + + + Halpassa + + + Neo Khidr + + + Neo Khidr + + + Aleksander IV + + + Aleksandra IV + + + Astrodotus + + + Astrodotutka + + + Ponce de Freon + + + Ponce de Freon + + + Brohannowie + + + Brohannowie + + + Wieżyczka + + + Wieżyczka + + + Strażnik + + + Strażnik + + + Nieskończony + + + Nieskończona + + + Herodotek + + + Szantor + + + Zapomniany + + + Zapomniana + + + Porzucony + + + Porzucona + + + Wartownik + + + Wartowniczka + + + Zdrajca + + + Zdrajczyni + + + Fontanna + + + Fontanna + + + Beryt i Halpas + + + Beryt i Halpas + + + Barbatos i Amon + + + Barbatos i Amon + + + Stolas i Fokalor + + + Stolas i Fokalor + + + Szantora + + + Szanteks + + + Szanteksa + + + Szantus + + + Szantuska + + + Panteon + + + Panteonka + + + Zimnar + + + Zimnara + + + Gravitor + + + Gravitorka + + + Terrator + + + Terratorka + + + Flamelok + + + Flameloksa + + + Szkieletka + + + Pan Żeberko + + + Blazelok + + + Blazeloksa + + + Solok + + + Soloka + + + Magsol + + + Magsola + + + Szronek + + + Szronka + + + Lodek + + + Lodzia + + + Mrozek + + + Mrozia + + + Łunnik + + + Łunniczka + + + Szperacz + + + Szperaczka + + + Uczeń + + + Uczenica + + + Wizjoner + + + Wizjonerka + + + Pan Żeberko + + + Kościotrup + + + Khidr + + + Khidra + + + Furor + + + Furora + + + Złośnik + + + Złośnica + + + Piekielnik + + + Piekielnica + + + Aleksander + + + Aleksandra + + + Strażnik-gigant + + + Strażniczka-gigantka + + + Strażnik statku + + + Strażniczka statku + + + Strażnik z wieży + + + Strażniczka z wieży + + + Wartownik + + + Wartowniczka + + + Kolczak + + + Kolczaka + + + Kościotrupka + + + Zły rycerz + + + Kolcowski + + + Kolcowska + + + Zadrzyński + + + Zadrzyńska + + + Bolecki + + + Bolecka + + + Szary rycerz + + + Szara rycerka + + + Szary baron + + + Szara baronowa + + + Szarminator + + + Szarminatorka + + + Grajpion + + + Grajpionia + + + Wilkogad + + + Wilkogadzina + + + Wilkowolf + + + Wilkowolfina + + + Wilkoborg + + + Wilkoborga + + + Zła rycerka + + + Zepsuty rycerzyk + + + Zorg + + + Zorgia + + + Zombie + + + Zombie + + + Zomboner + + + Zombonera + + + Zombisz + + + Zombiszka + + + Zomg + + + Zomga + + + Energetyk + + + Energetyka + + + Masteretyk + + + Masteretyczka + + + Voltron + + + Voltronia + + + Lider + + + Liderka + + + Ninjo + + + Ninjo + + + Zepsuty rycerzyk + + + Fałszywy magnat + + + Ninpo + + + Ninpo + + + Ninpolo + + + Ninpolo + + + Mistrz Ninja + + + Mistrzyni Ninja + + + Pączek + + + Pączusia + + + Pąk + + + Pączka + + + Kwiatol + + + Kwiatolla + + + Czaryt + + + Czarytia + + + Piryt + + + Pirytia + + + Inferyt + + + Inferytia + + + Ponce de Leon + + + Ponce de Leon + + + Fałszywa magnatka + + + Botek + + + Kolczatka + + + Kolczatka + + + Łucznik + + + Łuczniczka + + + Strażnik + + + Strażniczka + + + Snajper + + + Snajperka + + + Strzelec + + + Strzelczyni + + + Johanes + + + Johanes + + + Fontanna + + + Fontanna + + + Fontanna młodości + + + Fontanna młodości + + + Drewnias + + + Drewnialka + + + Domalek + + + Domalka + + + Botka + + + Kleks + + + Patrzałek + + + Patrzałka + + + Salos + + + Salosia + + + Plinky + + + Plinky + + + Planky + + + Planky + + + Plonky + + + Plonky + + + Pluk + + + Pluka + + + Kentaki + + + Kentaczka + + + Smażyk + + + Smażyłka + + + Kurczak + + + Kurczak + + + Pyszałek + + + Pyszałeczka + + + Kleksa + + + Kleksik + + + Dozorca + + + Dozorczyni + + + Dozorca XL + + + Dozorczyni XL + + + Dozorca 2000 + + + Dozorczyni 2000 + + + Gigazorca + + + Gigazorczyni + + + Bezgłowy koń + + + Bezgłowy koń + + + Śniady ogier + + + Śniady ogier + + + Nocna klacz + + + Nocna klacz + + + Mój mały kucyk + + + Mój mały kucyk + + + Sparky + + + Sparky + + + Pan Iskierka + + + Pan Iskierka + + + Kleksia + + + Skoczek + + + Klątwa + + + Klątwa + + + Wdzięk + + + Wdzięk + + + Zapłata dla Architekta + + + Zapłata dla Architekta + + + Bonus NG+ + + + Bonus NG+ + + + Skoczek + + + Sprint + + + Sprint + + + Wampir + + + Wampirzyca. + + + Niebo + + + Niebo + + + Syfon + + + Syfon + + + Równowaga + + + Równowaga + + + Odwet + + + Odwet + + + Zdobycz + + + Zdobycz + + + Pośpiech + + + Pośpiech + + + Ostry + + + Zabójczy + + + Zabójczy + + + Mądry + + + Mądry + + + Krwawy + + + Krwawy + + + Odwetowy + + + Odwetowy + + + Święty + + + Święty + + + Ciemny + + + Ciemny + + + Ostry + + + Srebrny + + + Srebrny + + + Opiekuńczy + + + Opiekuńczy + + + Imperialny + + + Imperialny + + + Królewski + + + Królewski + + + Rycerski + + + Rycerski + + + Strażniczy + + + Strażniczy + + + Niebiański + + + Niebiański + + + Smoczy + + + Smoczy + + + Miecz + + + Miecz + + + Płaszcz + + + Płaszcz + + + Naramiennik + + + Naramiennik + + + Hełm + + + Hełm + + + Pancerz + + + Pancerz + + + Brak + + + Brak + + + Miecz + + + Miecz + + + Płaszcz + + + Płaszcz + + + Naram. + + + Naram. + + + Hełm + + + Hełm + + + Pancerz + + + Pancerz + + + Brak + + + Brak + + + Daje Ci moc skakania\nw górę. Zgromadzenie wielu run umożliwia wykonywanie wielokrotnych skoków. + + + Trudniejsi wrogowie, ale większe nagrody. Zgromadzenie wielu run sprawia, że wrogowie stają się jeszcze bardziej wymagający. + + + Trudniejsi wrogowie, ale większe nagrody. Zgromadzenie wielu run sprawia, że wrogowie stają się jeszcze bardziej wymagający. + + + Słabsi i wolniejsi wrogowie, ale mniejsze nagrody. Zgromadzenie wielu run osłabia wrogów jeszcze bardziej. + + + Słabsi i wolniejsi wrogowie, ale mniejsze nagrody. Zgromadzenie wielu run osłabia wrogów jeszcze bardziej. + + + Daje Ci moc skakania\nw górę. Zgromadzenie wielu run umożliwia wykonywanie wielokrotnych skoków. + + + Zdobądź moc szybkiego biegu na krótkich odcinkach. Zgromadzenie wielu run umożliwia wielokrotne użycie pędu. + + + Zdobądź moc szybkiego biegu na krótkich odcinkach. Zgromadzenie wielu run umożliwia wielokrotne użycie pędu. + + + Zabijanie wrogów wysysa z nich zdrowie. Zgromadzenie wielu run zwiększa ilość wysysanego życia. + + + Zabijanie wrogów wysysa z nich zdrowie. Zgromadzenie wielu run zwiększa ilość wysysanego życia. + + + Zdobądź moc latania. Zgromadzenie wielu run wydłuża czas trwania lotu. + + + Zdobądź moc latania. Zgromadzenie wielu run wydłuża czas trwania lotu. + + + Wykrada manę \nz uśmierconych wrogów. Zgromadzenie wielu run zwiększa ilość odbieranej many. + + + Wykrada manę \nz uśmierconych wrogów. Zgromadzenie wielu run zwiększa ilość odbieranej many. + + + Zabijanie daje Ci PZ \ni MP. Zgromadzenie wielu run pozwala na pozyskiwanie większej liczby PZ i MP. + + + Zabijanie daje Ci PZ \ni MP. Zgromadzenie wielu run pozwala na pozyskiwanie większej liczby PZ i MP. + + + Oddaje uszkodzenia wyrządzone przez wrogów. Zgromadzenie wielu run zwiększa ilość oddawanych uszkodzeń. + + + Oddaje uszkodzenia wyrządzone przez wrogów. Zgromadzenie wielu run zwiększa ilość oddawanych uszkodzeń. + + + Zwiększ ilość złota pozyskiwanego z monet. Zgromadzenie wielu run zwiększa ilość pozyskiwanego złota. + + + Zwiększ ilość złota pozyskiwanego z monet. Zgromadzenie wielu run zwiększa ilość pozyskiwanego złota. + + + Zwiększa Twoją bazową szybkość ruchu. Zgromadzenie wielu run zapewnia jeszcze większą szybkość. + + + Zwiększa Twoją bazową szybkość ruchu. Zgromadzenie wielu run zapewnia jeszcze większą szybkość. + + + Wrogowie są trudniejsi. + + + Wrogowie są trudniejsi. + + + Wrogowie są wolniejsi. + + + Wrogowie są wolniejsi. + + + Naciśnij [Input:10], będąc\nw powietrzu. + + + Naciśnij [Input:10], będąc w powietrzu. + + + Sprint: użyj [Input:14] lub [Input:15] + + + Sprint: użyj [Input:14] lub [Input:15] + + + Zabij wrogów, by odzyskać zdrowie. + + + Zabij wrogów, by odzyskać zdrowie. + + + Naciśnij [Input:10], będąc\nw powietrzu. + + + Naciśnij [Input:10], będąc\nw powietrzu. + + + Zabij wrogów, by odzyskać manę. + + + Zabij wrogów, by odzyskać manę. + + + Zabij wrogów, by odzyskać zdrowie \ni manę. + + + Zabij wrogów, by odzyskać zdrowie \ni manę. + + + Uszkodzenia oddane wrogom. + + + Uszkodzenia oddane wrogom. + + + Monety dają więcej złota. + + + Monety dają więcej złota. + + + Poruszaj się szybciej. + + + Poruszaj się szybciej. + + + Krytyczna szansa + + + Pęd + + + Pęd + + + Blok + + + Blok + + + Płyń + + + Płyń + + + Może atakować pociski + + + Może atakować pociski + + + Lot + + + Lot + + + Szybkość ruchu + + + Szybkość ruchu + + + Brak + + + Brak + + + Krytyczna szansa + + + Krytyczne uszkodzenie + + + Krytyczne uszkodzenie + + + Wampiryzm + + + Wampiryzm + + + Bonus złota + + + Bonus złota + + + Syfon + + + Syfon + + + Bonus PD + + + Bonus PD + + + Atak powietrzny + + + Atak powietrzny + + + Skok + + + Skok + + + Oddawanie uszkodzeń + + + Oddawanie uszkodzeń + + + Zdobycz zwiększona o {0}% + + + Zdobycz zwiększona o {0}% + + + Przeciwnicy zaczynają {0} poz. wyżej + + + Przeciwnicy zaczynają {0} poz. wyżej + + + Przeciwnicy są {0} jedn. wolniejsi + + + Przeciwnicy są {0} jedn. wolniejsi + + + Przeciwnicy są {0} jedn. wolniejsi + + + Przeciwnicy są {0} jedn. wolniejsi + + + Wykonaj {0} razy skok + + + Wykonaj {0} razy skok + + + Wykonaj {0} raz skok + + + Wykonaj {0} raz skok + + + Wykonaj {0} razy sprint + + + Wykonaj {0} razy sprint + + + Wykonaj {0} raz sprint + + + Wykonaj {0} raz sprint + + + Odzyskaj {0} PZ za każdego zabitego przeciwnika + + + Odzyskaj {0} PZ za każdego zabitego przeciwnika + + + Leć przez {0} sekund + + + Leć przez {0} sekund + + + Leć przez {0} sekundę + + + Leć przez {0} sekundę + + + Odzyskaj {0} MP za każde zabicie przeciwnika + + + Odzyskaj {0} MP za każde zabicie przeciwnika + + + PZ many + + + PZ many + + + Odzyskaj {0}% szkód po trafieniu przez przeciwnika + + + Odzyskaj {0}% szkód po trafieniu przez przeciwnika + + + Każdy łup w złocie jest {0}% cenniejszy + + + Każdy łup w złocie jest {0}% cenniejszy + + + Poruszaj się {0} %szybciej + + + Poruszaj się {0} %szybciej + + + Wyjdź z gry Rogue Legacy + + + Wyjdź z gry Rogue Legacy + + + Naciśnij [Input:0], aby kontynuować + + + Naciśnij [Input:0], aby kontynuować + + + Słońce... Już nie pamiętam, jakie to uczucie. + + + Słońce... Już nie pamiętam, jakie to uczucie. + + + {0} zginął z ręki: {1} + + + {0} zginęła z ręki: {1} + + + Naciśnij [Input:0], aby kontynuować + + + Naciśnij [Input:0], aby kontynuować + + + {0} zginął z ręki: {1} + + + {0} zginęła z ręki: {1} + + + {0} zginął z ręki: {1} + + + {0} zginęła z ręki: {1} + + + {0} zginął od pocisku + + + {0} zginęła od pocisku + + + {0} potknął się i nadział na szpikulce + + + {0} potknęła się i nadziała na szpikulce + + + {0} został zabity + + + {0} została zabita + + + -{0} wygłasił pożegnalne słowa + + + -{0} wygłosiła pożegnalne słowa + + + [Input:0], aby kontynuować + + + [Input:0], aby kontynuować + + + Więcej PZ + + + Więcej PZ + + + Więcej MP + + + Więcej MP + + + Więcej mocy + + + Więcej mocy + + + Więcej magicznego uszkodzenia + + + Więcej magicznego uszkodzenia + + + Mocniejsza zbroja + + + Mocniejsza zbroja + + + Większa waga maks. ładunku + + + Większa waga maks. ładunku + + + Ukończono medalion! + + + Ukończono medalion! + + + Znalazłeśkawałek medalionu! + + + Znalazłaś kawałek medalionu! + + + Las jest zawsze po prawej stronie zamku. + + + Runa niebiańska umożliwia latanie za pomocą [Input:10] + + + Runa niebiańska umożliwia latanie za pomocą [Input:10] + + + Wampiryzm i runa wodna mają ogromną moc dla każdego, kto je posiądzie. + + + Wampiryzm i runa wodna mają ogromną moc dla każdego, kto je posiądzie. + + + Opanowanie run ruchu spowoduje, że będziesz niesamowity. + + + Opanowanie run ruchu spowoduje, że będziesz niesamowita. + + + Postaraj się rozbudować swoją posiadłość. Nie wiadomo, jakie umiejętności odkryjesz. + + + Postaraj się rozbudować swoją posiadłość. Nie wiadomo, jakie umiejętności odkryjesz. + + + Wszystkie klasy mogą być ulepszone unikalnymi zdolnościami. + + + Wszystkie klasy mogą być ulepszone unikalnymi zdolnościami. + + + Odblokowane zdolności klasy można aktywować za pomocą [Input:13] + + + Odblokowane zdolności klasy można aktywować za pomocą [Input:13] + + + Ulepszaj zawczasu swoje klasy, aby zdobyć potężne zdolności klasy. + + + Ulepszaj zawczasu swoje klasy, aby zdobyć potężne zdolności klasy. + + + Jeżeli masz problem z jakimś pomieszczeniem, spróbuj je ominąć. + + + Jeżeli masz problem z jakimś pomieszczeniem, spróbuj je ominąć. + + + Zakup ekwipunku to najszybszy sposób na poprawienie statystyk. + + + Zakup ekwipunku to najszybszy sposób na poprawienie statystyk. + + + Kupowanie ekwipunku jest tańsze i bardziej elastyczne od podnoszenia statystyk bazowych. + + + Kupowanie ekwipunku jest tańsze i bardziej elastyczne od podnoszenia statystyk bazowych. + + + Las jest zawsze po prawej stronie zamku. + + + Maya jest zawsze w górnej części zamku. + + + Powinieneś był wybrać to drugie dziecko. + + + Powinnaś była wybrać to drugie dziecko. + + + Runy mają ogromną moc. Wyposaż się w nie u Czarodziejki i nie zapomnij ich używać! + + + Runy mają ogromną moc. Wyposaż się w nie u Czarodziejki i nie zapomnij ich używać! + + + Opanuj zaklęcia w każdym detalu, by zmaksymalizować ich potencjał. + + + Opanuj zaklęcia w każdym detalu, by zmaksymalizować ich potencjał. + + + Staraj się uderzać wroga czubkiem łuku topora, by zadać wiele ciosów. + + + Staraj się uderzać wroga czubkiem łuku topora, by zadać wiele ciosów. + + + Nie zbieraj kul po rzuceniu zaklęcia, aby zmaksymalizować wyrządzane szkody. + + + Nie zbieraj kul po rzuceniu zaklęcia, aby zmaksymalizować wyrządzane szkody. + + + Uchylaj się przed powracającymi czakrami, by zmaksymalizować wyrządzane szkody. + + + Uchylaj się przed powracającymi czakrami, by zmaksymalizować wyrządzane szkody. + + + Zamiast odnosić niepotrzebne szkody, lepiej używać many do zabijania wrogów. + + + Zamiast odnosić niepotrzebne szkody, lepiej używać many do zabijania wrogów. + + + Nauczenie się „mowy” wroga jest konieczne, by przetrwać w zamku. + + + Nauczenie się „mowy” wroga jest konieczne, by przetrwać w zamku. + + + Kolczatka sprawdzi puls i pomoże odróżnić żywych od umarłych. + + + Kolczatka sprawdzi puls i pomoże odróżnić żywych od umarłych. + + + Naciśnij [Input:9], aby otworzyć mapę. + + + Naciśnij [Input:9], aby otworzyć mapę. + + + Maya jest zawsze w górnej części zamku. + + + Mrok jest zawsze w dolnych partiach zamku. + + + Magiczne skrzynie zawierają wszystkie runy w grze. Runy są niezmiernie pomocne. + + + Magiczne skrzynie zawierają wszystkie runy w grze. Runy są niezmiernie pomocne. + + + Jeśli ominiesz pomieszczenie z magiczną skrzynią, Architekt może dać Ci drugą szansę. + + + Jeśli ominiesz pomieszczenie z magiczną skrzynią, Architekt może dać Ci drugą szansę. + + + Architekt nieźle sobie liczy za swoje usługi. + + + Architekt nieźle sobie liczy za swoje usługi. + + + Zabijani bossowie zostawiają po sobie duże ilości złota. + + + Zabijani bossowie zostawiają po sobie duże ilości złota. + + + Zakop mnie w moich pieniądzach. + + + Zakop mnie w moich pieniądzach. + + + Jeśli masz kłopoty, doposaż się w runy gracji. + + + Jeśli masz kłopoty, doposaż się w runy gracji. + + + W opcjach możesz włączyć zeskok, aby móc atakować z góry i spadać, naciskając [Input:18] + + + W opcjach możesz włączyć zeskok, aby móc atakować z góry i spadać, naciskając [Input:18] + + + Architekt bardzo się przydaje podczas walki przeciwko bossom. + + + Architekt bardzo się przydaje podczas walki przeciwko bossom. + + + W trzecim rzędzie ekwipunku dochodzi zazwyczaj do wielkich zamian. Uważaj. + + + W trzecim rzędzie ekwipunku dochodzi zazwyczaj do wielkich zamian. Uważaj. + + + Pewne runy działają lepiej na niektórych bossów. + + + Pewne runy działają lepiej na niektórych bossów. + + + Mrok jest zawsze w dolnych partiach zamku. + + + Jeżeli masz problemy z bossem, spróbuj użyć innych run. + + + Musisz poćwiczyć walkę z bossami przy pomocy Architekta. + + + Musisz poćwiczyć walkę z bossami przy pomocy Architekta. + + + Zdrowie to ważna statystyka, którą należy poprawiać. + + + Zdrowie to ważna statystyka, którą należy poprawiać. + + + Runy odwetu mogą uszkadzać odporne przedmioty. + + + Runy odwetu mogą uszkadzać odporne przedmioty. + + + Zdolności klasowe są naprawdę potężne, jeśli tylko używa się ich właściwie. + + + Zdolności klasowe są naprawdę potężne, jeśli tylko używa się ich właściwie. + + + Pewne klasy mają przewagę nad niektórymi bossami. + + + Pewne klasy mają przewagę nad niektórymi bossami. + + + Jeżeli masz problemy z bossem, spróbuj użyć innych run. + + + Runa skoczka pozwala Ci skakać wysoko w powietrze za pomocą [Input:10] + + + Runa skoczka pozwala Ci skakać wysoko w powietrze za pomocą [Input:10] + + + Runa sprintera umożliwia bardzo szybki bieg za pomocą [Input:PLAYER_DASHLEFT] lub [Input:PLAYER_DASHRIGHT] + + + Runa sprintera umożliwia bardzo szybki bieg za pomocą [Input:PLAYER_DASHLEFT] lub [Input:PLAYER_DASHRIGHT] + + + Każda klasa ma swoje zalety i wady. Pamiętaj o nich podczas rozgrywki. + + + Każda klasa ma swoje zalety i wady. Pamiętaj o nich podczas rozgrywki. + + + Eksploracja i znajdowanie skrzyń to najlepszy sposób na zdobycie złota. + + + Eksploracja i znajdowanie skrzyń to najlepszy sposób na zdobycie złota. + + + Im trudniejszy teren, tym większe nagrody. + + + Im trudniejszy teren, tym większe nagrody. + + + Mam zobowiązania względem rodziny... + + + Mam zobowiązania względem rodziny... + + + Ale jestem lojalny tylko wobec siebie. + + + Ale jestem lojalna tylko wobec siebie. + + + złoto + + + złoto + + + PZ odzyskane + + + PZ odzyskane + + + MP odzyskane + + + MP odzyskane + + + Ulepszenie zbroi + + + Ulepszenie zbroi + + + Poprawa maks. zdrowia + + + Poprawa maks. zdrowia + + + Poprawa maks. many + + + Poprawa maks. many + + + Poprawa ataku + + + Poprawa ataku + + + Poprawa magii + + + Poprawa magii + + + Poprawa maks. wagi + + + Poprawa maks. wagi + + + Odtwarzane: + + + Odtwarzane: + + + Wejście: + + + Wejście: + + + Cel magicznej skrzyni: + + + Cel magicznej skrzyni: + + + Dotrzyj do skrzyni w 15 sekund: + + + Dotrzyj do skrzyni w 15 sekund: + + + Pozostały czas: + + + Pozostały czas: + + + Zadanie wykonane! + + + Zadanie wykonane! + + + Zadanie niewykonane + + + Zadanie niewykonane + + + Brak cech + + + Bohaterski {0} + + + Bohaterska {0} + + + Boski {0} + + + Boska {0} + + + Sir {0} {1} + + + Sir {0} {1} + + + Bohater + + + Bohater + + + Lady {0} {1} + + + Lady {0} {1} + + + Bohaterka + + + Bohaterka + + + Brak cech + + + to + + + to + + + Legendarny {0} + + + Legendarna {0} + + + Bezużyteczny {0} + + + Bezużyteczna {0} + + + Słaby {0} + + + Słaba {0} + + + Zdeterminowany {0} + + + Zdeterminowana {0} + + + Niezłomny {0} + + + Niezłomna {0} + + + Waleczny {0} + + + Waleczna {0} + + + Mężny {0} + + + Mężna {0} + + + [Input:0], aby wybrać dziecko + + + [Input:0], aby wybrać dziecko + + + [Button:LeftStick], aby wyświetlić drzewo genealogiczne + + + [Button:LeftStick], aby wyświetlić drzewo genealogiczne + + + Klawisze ze strzałkami do pokazywania drzewa genealogicznego + + + Klawisze ze strzałkami do pokazywania drzewa genealogicznego + + + [Input:9], aby jeden raz ponownie wybrać dzieci + + + [Input:9], aby jeden raz ponownie wybrać dzieci + + + Klasa + + + Klasa + + + Cecha + + + Cecha + + + Cechy – brak + + + Cechy – brak + + + Zaklęcie + + + Zaklęcie + + + Budowanie + + + Budowanie + + + Wczesywanie + + + Wczesywanie + + + Przypominanie + + + Przypominanie + + + Wrzucanie + + + Wrzucanie + + + Otwarta skrzynia + + + Otwarta skrzynia + + + Teleport + + + Teleport + + + Dodatkowy pokój + + + Dodatkowy pokój + + + [Input:9], aby zamknąć mapę + + + [Input:9], aby zamknąć mapę + + + [Input:0], aby wyśrodkować na graczu + + + [Input:0], aby wyśrodkować na graczu + + + Użyj klawiszy ze strzałkami, by przesunąć mapę + + + Użyj klawiszy ze strzałkami, by przesunąć mapę + + + [Button:LeftStick], aby przesunąć mapę + + + [Button:LeftStick], aby przesunąć mapę + + + Legenda + + + Legenda + + + Jesteś tutaj + + + Jesteś tutaj + + + Lokalizacja bossa + + + Lokalizacja bossa + + + Zamknięta skrzynia + + + Zamknięta skrzynia + + + Magiczna skrzynia + + + Magiczna skrzynia + + + Głośność muzyki + + + Głośność muzyki + + + Chiński + + + Chiński + + + Angielski + + + Angielski + + + Francuski + + + Francuski + + + Niemiecki + + + Niemiecki + + + Polski + + + Polski + + + Portugalski (brazylijski) + + + Portugalski (brazylijski) + + + Rosyjski + + + Rosyjski + + + Hiszpański + + + Hiszpański + + + Język + + + Język + + + *Zeskok pozwala Ci na szybkie zejście na niższą półkę i wykonanie \nataku z powietrza poprzez wciśnięcie przycisku „W DÓŁ” + + + Rozdzielczość + + + Rozdzielczość + + + Pełny ekran + + + Pełny ekran + + + Obniż jakość shadera + + + Obniż jakość shadera + + + Użyj kontrolerów typu DInput + + + Użyj kontrolerów typu DInput + + + Włącz chmurę Steam + + + Włącz chmurę Steam + + + *Zeskok pozwala Ci na szybkie zejście na niższą półkę i wykonanie \nataku z powietrza poprzez wciśnięcie przycisku „W DÓŁ” + + + [Button:LeftStick], aby nawigować wśród opcji + + + [Button:LeftStick], aby nawigować wśród opcji + + + Klawisze ze strzałkami do przemieszczania się + + + Klawisze ze strzałkami do przemieszczania się + + + [Input:0], aby wybrać opcję + + + [Input:0], aby wybrać opcję + + + [Input:2], aby wyjść z opcji + + + [Input:2], aby wyjść z opcji + + + *Aby zmiana została wprowadzona, należy ponownie uruchomić grę. + + + *Aby zmiana została wprowadzona, należy ponownie uruchomić grę. + + + *Aby ta funkcja działała, należy również włączyć obsługę chmury\nna platformie Steam. + + + *Aby ta funkcja działała, należy również włączyć obsługę chmury\nna platformie Steam. + + + Klasa: + + + Klasa: + + + Moc: + + + Moc: + + + Magia: + + + Magia: + + + Zbroja: + + + Zbroja: + + + Poziom: + + + Poziom: + + + Zdrowie: + + + Zdrowie: + + + ????? + + + ????? + + + złoto + + + złoto + + + maks. MP + + + maks. MP + + + maks. PZ + + + maks. PZ + + + Maks. MP przemienione. Potrzebny wyższy poziom. + + + Maks. MP przemienione. Potrzebny wyższy poziom. + + + Zdrowie + + + Czary + + + Czary + + + [Input:2], aby wyjść + + + [Input:2], aby wyjść + + + Lv. + + + Lv. + + + Zdrowie + + + Mana + + + Mana + + + Zbroja + + + Zbroja + + + Waga + + + Waga + + + Moc + + + Moc + + + Inteligencja + + + Inteligencja + + + Kryt. szansa + + + Kryt. szansa + + + Kryt. Uszkodz. + + + Kryt. Uszkodz. + + + Ekwipunek + + + Ekwipunek + + + 100% statystyk bazowych. + + + SPECJALNOŚĆ: Barbarzyński okrzyk\nBardzo dużo PZ. Mało mocy i MP. + + + SPECJALNOŚĆ: Barbarzyński okrzyk\nBardzo dużo PZ. Mało mocy i MP. + + + Mnóstwo mocy, ale brak krytycznych ciosów.\n+{0}% szybkości ruchu. Mało PZ i MP. + + + Mnóstwo mocy, ale brak krytycznych ciosów.\n+{0}% szybkości ruchu. Mało PZ i MP. + + + SPECJALNOŚĆ: Wymiana.\nMnóstwo mocy, ale brak krytycznych ciosów.\n+{0}% szybkości ruchu. Mało PZ i MP. + + + SPECJALNOŚĆ: Wymiana.\nMnóstwo mocy, ale brak krytycznych ciosów.\n+{0}% szybkości ruchu. Mało PZ i MP. + + + {0}% % zadanych szkód zmienia się w manę.\nMało mocy, PZ i MP. + + + {0}% % zadanych szkód zmienia się w manę.\nMało mocy, PZ i MP. + + + SPECJALNOŚĆ: Wzmocniony atak.\n{0}% zadanych szkód zmienia się w manę.\nMało mocy, PZ i MP. + + + SPECJALNOŚĆ: Wzmocniony atak.\n{0}% zadanych szkód zmienia się w manę.\nMało mocy, PZ i MP. + + + Zabici wrogowie są zamieniani na PZ.\nBardzo mało mocy, PZ i MP. Dużo Int. + + + Zabici wrogowie są zamieniani na PZ.\nBardzo mało mocy, PZ i MP. Dużo Int. + + + SPECJALNOŚĆ: Przemiana PZ.\nZabici wrogowie są zamieniani na PZ.\n\nBardzo mało mocy, PZ i MP. Dużo Int. + + + SPECJALNOŚĆ: Przemiana PZ.\nZabici wrogowie są zamieniani na PZ.\n\nBardzo mało mocy, PZ i MP. Dużo Int. + + + Jesteś człowiekiem-smokiem. + + + Jesteś człowiekiem-smokiem. + + + ????? + + + ????? + + + 100% statystyk bazowych. + + + SPECJALNOŚĆ: Tarcza strażnika.\n100% statystyk bazowych. + + + SPECJALNOŚĆ: Tarcza strażniczki.\n100% statystyk bazowych. + + + +{0}% kryt. szansy, +{1}% kryt. szkód.\nMało PZ, MP i mocy. + + + +{0}% kryt. szansy, +{1}% kryt. szkód.\nMało PZ, MP i mocy. + + + SPECJALNOŚĆ: Mgiełka\n+{0}% kryt. szansy, +{1}% kryt. szkód.\nMało PZ, MP i mocy. + + + SPECJALNOŚĆ: Mgiełka\n+{0}% kryt. szansy, +{1}% kryt. szkód.\nMało PZ, MP i mocy. + + + +{0}% złota.\nBardzo słabe pozostałe statystyki. + + + +{0}% złota.\nBardzo słabe pozostałe statystyki. + + + SPECJALNOŚĆ: Czołówka.\n+{0}% złota.\nBardzo słabe pozostałe statystyki. + + + SPECJALNOŚĆ: Czołówka.\n+{0}% złota.\nBardzo słabe pozostałe statystyki. + + + Każdy zabity przeciwnik zapewnia {0} pkt many.\nMało mocy i PZ. Dużo Int i MP. + + + Każdy zabity przeciwnik zapewnia {0} pkt many.\nMało mocy i PZ. Dużo Int i MP. + + + SPECJALNOŚĆ: Cykl zaklęć.\nKażde zabicie przeciwnik zapewnia {0} pkt many.\nMało mocy i PZ. Dużo Int i MP. + + + SPECJALNOŚĆ: Cykl zaklęć.\nKażde zabicie przeciwnik zapewnia {0} pkt many.\nMało mocy i PZ. Dużo Int i MP. + + + Bardzo dużo PZ. Mało mocy i MP. + + + Bardzo dużo PZ. Mało mocy i MP. + + + - ROZPOCZNIJ DZIEDZICTWO - + + + NG+ + + + NG+ + + + - ROZPOCZNIJ DZIEDZICTWO - + + + [Button:LeftStick], aby nawigować + + + [Button:LeftStick], aby nawigować + + + Klawisze ze strzałkami do przemieszczania się + + + Klawisze ze strzałkami do przemieszczania się + + + [Input:0], aby wybrać + + + [Input:0], aby wybrać + + + [Input:2], aby wyjść + + + [Input:2], aby wyjść + + + [Input:26], aby usunąć + + + [Input:26], aby usunąć + + + {0} {1} + + + {0} {1} + + + {0} {1} + + + {0} {1} + + + {0} Umarła + + + {0} Umarła + + + {0} Umarły + + + {0} Umarły + + + Lvl. + + + Lvl. + + + Umożliw zeskok + + + Umożliw zeskok + + + Nie + + + Nie + + + Tak + + + Tak + + + Głośność efektów + + + Głośność efektów + + + Popraw ćwiczenia kardiologiczne. Lepsze serce to lepsze zdrowie. + + + Odblokuj Kowala i uzyskaj dostęp do zdobyczy. + + + Odblokuj Kowala i uzyskaj dostęp do zdobyczy. + + + Odblokuj Czarodziejkę \ni uzyskaj dostęp do jej magicznych run i mocy. + + + Odblokuj Czarodziejkę \ni uzyskaj dostęp do jej magicznych run i mocy. + + + Odblokuj Architekta i zdobądź moce, by zabezpieczyć zamek. + + + Odblokuj Architekta i zdobądź moce, by zabezpieczyć zamek. + + + Ulepszenie umiejętności noszenia pozwoli Ci zakładać lepsze i cięższe zbroje. + + + Ulepszenie umiejętności noszenia pozwoli Ci zakładać lepsze i cięższe zbroje. + + + Wzmocnij swoje wnętrzności naturalnymi sposobami, by zmniejszyć doznawane obrażenia. + + + Wzmocnij swoje wnętrzności naturalnymi sposobami, by zmniejszyć doznawane obrażenia. + + + Popraw umiejętności plądrowania i zdobądź więcej łupów. + + + Popraw umiejętności plądrowania i zdobądź więcej łupów. + + + Obniż opłatę Charona, ucząc się, jak dogadać się z samą śmiercią. + + + Obniż opłatę Charona, ucząc się, jak dogadać się z samą śmiercią. + + + Oczyszczenie wnętrzności przynosi zdecydowaną poprawę po spożywaniu mięsa \ni eliksirów. + + + Oczyszczenie wnętrzności przynosi zdecydowaną poprawę po spożywaniu mięsa \ni eliksirów. + + + Wykorzystaj potęgę nauki, by stworzyć gromadę nowych dzieci. Tylko... o nic nie pytaj. + + + Wykorzystaj potęgę nauki, by stworzyć gromadę nowych dzieci. Tylko... o nic nie pytaj. + + + Uwolnij moc Licza! To istota \no wielkim potencjale. + + + Uwolnij moc Licza! To istota \no wielkim potencjale. + + + Popraw ćwiczenia kardiologiczne. Lepsze serce to lepsze zdrowie. + + + Wzmocnij swoje nadnercza\ni bądź niezniszczalny jak Bane. Czas rozpocząć grę! + + + Odblokuj umiejętności Górnika i powiększ swój rodzinny majątek. + + + Odblokuj umiejętności Górnika i powiększ swój rodzinny majątek. + + + Odblokuj Złodziejaszka i stań się wojowniczym Magiem. + + + Odblokuj Złodziejaszka i stań się wojowniczym Magiem. + + + Odblokuj Shinobi, najszybszego ze wszystkich wojowników. + + + Odblokuj Shinobi, najszybszego ze wszystkich wojowników. + + + Ćwicz podstawowe umiejętności, by obniżyć koszty many podczas rzucania zaklęć. + + + Ćwicz podstawowe umiejętności, by obniżyć koszty many podczas rzucania zaklęć. + + + Zmień swoich Rycerzy\nw Paladynów. Zaciekłych wojowników stojących\nw pierwszej linii. + + + Zmień swoich Rycerzy\nw Paladynów. Zaciekłych wojowników stojących\nw pierwszej linii. + + + Odblokuj ukryte moce Maga \ni przemień go w potężnego Arcymaga. + + + Odblokuj ukryte moce Maga \ni przemień go w potężnego Arcymaga. + + + Poznaj sztukę czarnej magii \ni przemień Szelmę w Zabójcę. + + + Poznaj sztukę czarnej magii \ni przemień Szelmę w Zabójcę. + + + Ukończ studia z geologii\ni zamień Górnika w Grotołaza. Ślicznie. + + + Ukończ studia z geologii\ni zamień Górnika w Grotołaza. Ślicznie. + + + Zostań Królem barbarzyńców. Królem wolnych ludzi. To nie ma sensu. + + + Zostań Królem barbarzyńców. Królem wolnych ludzi. To nie ma sensu. + + + Niech Twój każdy Licz stanie się potężnym liczowym królem. + + + Niech Twój każdy Licz stanie się potężnym liczowym królem. + + + Wzmocnij swoje nadnercza\ni bądź niezniszczalny jak Bane. Czas rozpocząć grę! + + + Uwolnij swojego wewnętrznego kota i wymknij się śmierci. Czasem. + + + Zostań przywódcą swojej wioski i zmień swojego Shinobi w Hokage. Uwierz w to! + + + Zostań przywódczynią swojej wioski i zmień swojego Shinobi w Hokage. Uwierz w to! + + + Opanuj wiry magii i zmień swojego Złodziejaszka\nw Czarnoksiężnika. + + + Opanuj wiry magii i zmień swojego Złodziejaszka\nw Czarnoksiężnika. + + + Pół człowiek, pół ******, po prostu wspaniale. + + + Pół człowiek, pół ******, po prostu wspaniale. + + + SZYBKI ODDECH \nPotrafisz oddychać. Niepotrzebne w tropieniu, przydatne w chodzeniu! \n\nPopraw swoją naturalną regenerację wytrzymałości. + + + SZYBKI ODDECH \nPotrafisz oddychać. Niepotrzebne w tropieniu, przydatne w chodzeniu! \n\nPopraw swoją naturalną regenerację wytrzymałości. + + + Gdy byłeś młody, dostałeś zastrzyk z krwi tygrysa. A teraz masz moc wypuszczania tej krwi, gdy jesteś ranny. \nPodczas biegu tracisz mniej wytrzymałości. + + + Gdy byłeś młoda, dostałaś zastrzyk z krwi tygrysa. A teraz masz moc wypuszczania tej krwi, gdy jesteś ranna. \nPodczas biegu tracisz mniej wytrzymałości. + + + Twoimi przodkami byli Wikingowie. \n\nZwiększ swoją początkową wytrzymałość. + + + Twoimi przodkami byli Wikingowie. \n\nZwiększ swoją początkową wytrzymałość. + + + Jesteś rannym ptaszkiem. Gdyby tylko osiąganie wyższych poziomów było tak proste jak budzenie...\n Zdobywaj dodatkowe PZ i MP po osiągnięciu kolejnego poziomu. + + + Jesteś rannym ptaszkiem. Gdyby tylko osiąganie wyższych poziomów było tak proste jak budzenie...\n Zdobywaj dodatkowe PZ i MP po osiągnięciu kolejnego poziomu. + + + Urodziłeś się z nieograniczoną mocą w czubkach swoich palców. \nWszystkie Twoje zaklęcia powodują więcej szkód. + + + Urodziłaś się z nieograniczoną mocą w czubkach swoich palców. \nWszystkie Twoje zaklęcia powodują więcej szkód. + + + Urodziłeś się z sekretną energią płynącą w Twoich żyłach. Och. \nRzucanie zaklęć mniej Cię kosztuje. + + + Urodziłaś się z sekretną energią płynącą w Twoich żyłach. Och. \nRzucanie zaklęć mniej Cię kosztuje. + + + Nerwica natręctw wreszcie się przydaje. \nZdobądź więcej złota. + + + Nerwica natręctw wreszcie się przydaje. \nZdobądź więcej złota. + + + Uwolnij swojego wewnętrznego kota i wymknij się śmierci. Czasem. + + + Dzięki odpowiednim ćwiczeniom na siłowni naprawdę wzmocnisz mięśnie ramion i pośladków. + + + Według prawa jesteś teraz najlepszy. \nPowołaj do życia więcej dzieci. + + + Według prawa jesteś teraz najlepsza. \nPowołaj do życia więcej dzieci. + + + Twoi rodzice powiedzieli, że nauka używania sita w poszukiwaniu złota jest nieprzydatna dla rolnika. I kto się śmieje ostatni? \n Pokaż komnaty ze skarbami na początku gry. + + + Twoi rodzice powiedzieli, że nauka używania sita w poszukiwaniu złota jest nieprzydatna dla rolnika. I kto się śmieje ostatni? \n Pokaż komnaty ze skarbami na początku gry. + + + Wojna to piekło. Na szczęście nie brałeś udziału w żadnej. \n Używaj więcej moździerzy. + + + Wojna to piekło. Na szczęście nie brałaś udziału w żadnej. \n Używaj więcej moździerzy. + + + Jako dziecko miałeś pociąg do wysadzania rzeczy w powietrze. \n Bomby mają większy zasięg. + + + Jako dziecko miałaś pociąg do wysadzania rzeczy w powietrze. \n Bomby mają większy zasięg. + + + Twój pradziadek był bałwanem. Niczego Cię nie nauczył. \n Sople przebijają więcej wrogów. + + + Twój pradziadek był bałwanem. Niczego Cię nie nauczył. \n Sople przebijają więcej wrogów. + + + Jesteś jak Zen. \n Szybciej odzyskujesz wytrzymałość w bezruchu. + + + Jesteś jak Zen. \n Szybciej odzyskujesz wytrzymałość w bezruchu. + + + Standardowa UMIEJĘTNOŚĆ. Zwiększa ogólną wytrzymałość. + + + Standardowa UMIEJĘTNOŚĆ. Zwiększa ogólną wytrzymałość. + + + Walczysz z finezją.\n Ataki wyczerpują X% mniej wytrzymałości. + + + Walczysz z finezją.\n Ataki wyczerpują X% mniej wytrzymałości. + + + Standardowa UMIEJĘTNOŚĆ. Zwiększa zdrowie + + + Standardowa UMIEJĘTNOŚĆ. Zwiększa zdrowie + + + Wysysasz... krew. \n Z każdym trafieniem odzyskujesz odrobinę życia. + + + Wysysasz... krew. \n Z każdym trafieniem odzyskujesz odrobinę życia. + + + Dzięki odpowiednim ćwiczeniom na siłowni naprawdę wzmocnisz mięśnie ramion i pośladków. + + + Pokój do pogowania ma swoje plusy. Wyrządzaj większe szkody dzięki następującym po sobie uderzeniom. + + + Powstań z martwych, tak jak Jezus. Ale Ty nie jesteś Jezusem. \n Wróć do życia jeden raz po śmierci. + + + Powstań z martwych, tak jak Jezus. Ale Ty nie jesteś Jezusem. \n Wróć do życia jeden raz po śmierci. + + + Oczyszczanie pomieszczeń przypomina oczyszczanie umysłu. Nie wiem dlaczego. \nOdzyskaj zdrowie za każde całkowicie oczyszczone pomieszczenie. + + + Oczyszczanie pomieszczeń przypomina oczyszczanie umysłu. Nie wiem dlaczego. \nOdzyskaj zdrowie za każde całkowicie oczyszczone pomieszczenie. + + + Kartografia /n Każdy odkryty procent mapy dodaje 0,1 do uszkodzeń. + + + Kartografia /n Każdy odkryty procent mapy dodaje 0,1 do uszkodzeń. + + + Standardowa UMIEJĘTNOŚĆ. Zwiększa siłę ataku. + + + Standardowa UMIEJĘTNOŚĆ. Zwiększa siłę ataku. + + + Jesteś bardzo, bardzo obolały i przegrany. \n Po śmierci wyrządź wszystkim wrogom na ekranie ogromne szkody. + + + Jesteś bardzo, bardzo obolała i przegrana. \n Po śmierci wyrządź wszystkim wrogom na ekranie ogromne szkody. + + + Już wiesz, że uderzanie kul powoduje wielkie uszkodzenia. \n Szkody krytyczne powodują większe zniszczenia. + + + Już wiesz, że uderzanie kul powoduje wielkie uszkodzenia. \n Szkody krytyczne powodują większe zniszczenia. + + + STANDARDOWA UMIEJĘTNOŚĆ. + + + STANDARDOWA UMIEJĘTNOŚĆ. + + + Och. Były w mojej tylnej kieszeni. \nZdobądź 2 dodatkowe klucze. + + + Och. Były w mojej tylnej kieszeni. \nZdobądź 2 dodatkowe klucze. + + + Tak jak feniks odradzasz się z tych byle jakich popiołów. \n Odzyskaj wszystkie PZ i MP. + + + Tak jak feniks odradzasz się z tych byle jakich popiołów. \n Odzyskaj wszystkie PZ i MP. + + + Przejdź na emeryturę i mądrze zainwestuj swoje pieniądze. Skończ grę wcześnie i zdobądź premię od znalezionego złota. + + + Przejdź na emeryturę i mądrze zainwestuj swoje pieniądze. Skończ grę wcześnie i zdobądź premię od znalezionego złota. + + + Pokój do pogowania ma swoje plusy. Wyrządzaj większe szkody dzięki następującym po sobie uderzeniom. + + + Jeżeli poznasz słabości wroga, będziesz atakował ze śmiertelną skutecznością. + + + GUL GUL GUL! \n Natychmiast wypij eliksiry. + + + GUL GUL GUL! \n Natychmiast wypij eliksiry. + + + Jeżeli poznasz słabości wroga, będziesz atakowała ze śmiertelną skutecznością. + + + Ćwicz zabójcze ciosy, by były jeszcze groźniejsze. Wrogowie będą całkowicie martwi. + + + Ćwicz zabójcze ciosy, by były jeszcze groźniejsze. Wrogowie będą całkowicie martwi. + + + Poznaj tajemnice wszechświata i wykorzystuj je, by lepiej zabijać przy pomocy zaklęć. + + + Poznaj tajemnice wszechświata i wykorzystuj je, by lepiej zabijać przy pomocy zaklęć. + + + Popraw swoje duchowe męstwo, by zwiększyć pulę many. + + + Popraw swoje duchowe męstwo, by zwiększyć pulę many. + + + Naciśnij [Input:9], aby wylosować swoje dzieci + + + Naciśnij [Input:9], aby wylosować swoje dzieci + + + Naciśnij [Input:13], aby zablokować wszystkie kolejne szkody. + + + Naciśnij [Input:13], aby zablokować wszystkie kolejne szkody. + + + Naciśnij [Input:13], aby zamienić zaklęcia + + + Naciśnij [Input:13], aby zamienić zaklęcia + + + Press [Input:13], aby włączyć mgłę + + + Press [Input:13], aby włączyć mgłę + + + Naciśnij [Input:13], aby włączyć czołówkę + + + Naciśnij [Input:13], aby włączyć czołówkę + + + Naciśnij [Input:13], aby wydać bohaterski okrzyk, który powali dosłownie wszystko. + + + Naciśnij [Input:13], aby wydać bohaterski okrzyk, który powali dosłownie wszystko. + + + Naciśnij [Input:13], aby przemienić maks. PZ w maks. MP + + + Naciśnij [Input:13], aby przemienić maks. PZ w maks. MP + + + Naciśnij [Input:13], aby się teleportować + + + Naciśnij [Input:13], aby się teleportować + + + Naciśnij [Input:13], aby rzucić wzmocnione zaklęcia + + + Naciśnij [Input:13], aby rzucić wzmocnione zaklęcia + + + Naciśnij [Input:10], aby stać się kimś niesamowitym. + + + Naciśnij [Input:10], aby stać się kimś niesamowitym. + + + + + + + + + Poprawa zdrowia + + + Kowal + + + Kowal + + + Czarodziejka + + + Czarodziejka + + + Architekt + + + Architektka + + + Doposaż + + + Doposaż + + + Ulepszenie zbroi + + + Ulepszenie zbroi + + + Zwiększenie złota + + + Zwiększenie złota + + + Targ + + + Targ + + + Ulepszenie eliksirów + + + Ulepszenie eliksirów + + + Losowanie dzieci + + + Losowanie dzieci + + + Odblokuj Licza + + + Odblokuj Licza + + + Poprawa zdrowia + + + Niezniszczalność + + + Odblokuj Górnika + + + Odblokuj Górniczkę + + + Odblok. Złodziejaszka + + + Odblok. Złodziejkę + + + Odblokuj Shinobi + + + Odblokuj Shinobi + + + Zniżka many + + + Zniżka many + + + Ulepszenie Rycerza + + + Ulepszenie Rycerki + + + Ulepszenie Maga + + + Ulepszenie Maga + + + Ulepszenie Szelmy + + + Ulepszenie Szelmy + + + Ulepszenie Górnika + + + Ulepszenie Górniczki + + + Ulepsz. Barbarzyńcy + + + Ulepsz. Barbarzyńcy + + + Ulepszenie Licza + + + Ulepszenie Licza + + + Niezniszczalność + + + Wskrzeszenie + + + Ulepszenie Shinobi + + + Ulepszenie Shinobi + + + Ulepsz. Złodziejaszka + + + Ulepsz. Złodziejki + + + Bestialstwo + + + Bestialstwo + + + Szybki oddech + + + Szybki oddech + + + Biegacz + + + Biegaczka + + + Szczodre serce + + + Szczodre serce + + + Bramownik + + + Bramowniczka + + + Czarnoksiężnik + + + Czarnoksiężniczka + + + Czarownik + + + Czarownica + + + Perfekcjonista + + + Perfekcjonistka + + + Wskrzeszenie + + + Poprawa ataku + + + Obdarzony + + + Obdarzona + + + Poszukiwacz skarbów + + + Poszukiwaczka skarbów + + + Mistrz moździerza + + + Mistrzyni moździerza + + + Ekspert od wybuchów + + + Ekspertka od wybuchów + + + Sopel + + + Sopel + + + Guru + + + Guru + + + Żelazne płuca + + + Żelazne płuca + + + Mistrz miecza + + + Mistrzyni miecza + + + Czołg + + + Tankietka + + + Wampir + + + Wampirzyca + + + Poprawa ataku + + + Poprawa uderzenia + + + Druga szansa + + + Druga szansa + + + Spokój umysłu + + + Spokój umysłu + + + Ninja kartografii + + + Ninja kartografii + + + Siłacz + + + Siłaczka + + + Samobójca + + + Samobójcczyni + + + Wielki barbarzyńca + + + Wielki barbarzyńca + + + Magik + + + Magiczka + + + Klucznik + + + Kluczniczka + + + Unikat + + + Unikat + + + Wcześniak + + + Wcześniak + + + Poprawa uderzenia + + + Poprawa kryt. szansy + + + Pijus + + + Pijaczka + + + Poprawa kryt. szansy + + + Poprawa kryt. uszk. + + + Poprawa kryt. uszk. + + + Poprawa ataku mag. + + + Poprawa ataku mag. + + + Zwiększenie many + + + Zwiększenie many + + + {0} szt. złota, by {1} + + + {0} szt. złota, by {1} + + + odblokować + + + odblokować + + + ulepszyć + + + ulepszyć + + + waga + + + waga + + + pz + + + pz + + + mp + + + mp + + + moc + + + moc + + + int + + + int + + + pz/mp + + + pz/mp + + + Maks. + + + Maks. + + + [Input:0], aby kupić/ulepszyć cechę + + + [Input:0], aby kupić/ulepszyć cechę + + + zbroja + + + zbroja + + + sek. + + + sek. + + + [Input:9], aby wyłączyć ikony + + + [Input:9], aby wyłączyć ikony + + + [Input:2], aby opuścić posiadłość + + + [Input:2], aby opuścić posiadłość + + + [Button:LeftStick], aby się przemieszczać + + + [Button:LeftStick], aby się przemieszczać + + + Klawisze ze strzałkami do przemieszczania się + + + Klawisze ze strzałkami do przemieszczania się + + + [Input:9], aby włączyć ikony + + + [Input:9], aby włączyć ikony + + + Aktualne + + + Aktualne + + + Ulepsz + + + Ulepsz + + + Poziom + + + Poziom + + + Kowal może stworzyć najwspanialszy ekwipunek na świecie, robiąc z Ciebie prawdziwego pogromcę brutalnych niegodziwców.\nZgromadzenie szablonów da mu jeszcze większy wybór różnorodnej broni do Twojego arsenału. + + + Przemień swoich Barbarzyńców\nw Barbarzyńskich KRÓLÓW! Poznaj sekretne niedźwiedzie okrzyki i krzycz na przedmioty, aż wybuchną. + + + Przemień swoich Barbarzyńców\nw Barbarzyńskich KRÓLÓW! Poznaj sekretne niedźwiedzie okrzyki i krzycz na przedmioty, aż wybuchną. + + + Niech nędzny Shinobi stanie się potężnym Hokage! Naucz się udawać trafionego, w ostatniej chwili zmieniając się w kłodę. Dobrze, że nosisz przy sobie wiele kłód. + + + Niech nędzny Shinobi stanie się potężnym Hokage! Naucz się udawać trafionego, w ostatniej chwili zmieniając się w kłodę. Dobrze, że nosisz przy sobie wiele kłód. + + + Wyszkól swoje Szelmy i zamień ich \nw Zabójców pełną gębą. Użyj mocy cieni, by bezszelestnie przemykać przez szeregi wroga. + + + Wyszkól swoje Szelmy i zamień ich \nw Zabójców pełną gębą. Użyj mocy cieni, by bezszelestnie przemykać przez szeregi wroga. + + + Całe to kopanie zmieniło Twoich Górników w Grotołazów! Teraz to śliczne światełko na Twojej głowie rzeczywiście się na coś przydaje! (Nie do końca). + + + Całe to kopanie zmieniło Twoich Górników w Grotołazów! Teraz to śliczne światełko na Twojej głowie rzeczywiście się na coś przydaje! (Nie do końca). + + + Zmień swoich Złodziejaszków \nw Czarnoksiężników i uzyskaj moc rzucania potężnych zaklęć.\nNazywasz to toporem? TO jest topór. + + + Zmień swoich Złodziejaszków \nw Czarnoksiężników i uzyskaj moc rzucania potężnych zaklęć.\nNazywasz to toporem? TO jest topór. + + + Niech Twoi Liczowie staną się Królewskimi Liczami; uzyskaj moc umysłu ORAZ materii. Jednym naciśnięciem przemień swoje zdrowie w stałą manę. + + + Niech Twoi Liczowie staną się Królewskimi Liczami; uzyskaj moc umysłu ORAZ materii. Jednym naciśnięciem przemień swoje zdrowie w stałą manę. + + + Odkryłeś utraconą smoczą umiejętność. Chociaż nie możesz skakać, masz nieograniczone możliwości latania i możesz rzucać potężnymi kulami ognia w swoich wrogów. + + + Odkryłaś utraconą smoczą umiejętność. Chociaż nie możesz skakać, masz nieograniczone możliwości latania i możesz rzucać potężnymi kulami ognia w swoich wrogów. + + + Odkryłeś ukrytą sztukę znaną tylko Johanesowi Zdrajcy. Niech wszyscy się kłaniają przed Twoją potęgą! + + + Odkryłaś ukrytą sztukę znaną tylko Johanesowi Zdrajcy. Niech wszyscy się kłaniają przed Twoją potęgą! + + + Kowal może stworzyć najwspanialszy ekwipunek na świecie, robiąc z Ciebie prawdziwą pogromczynię brutalnych niegodziwców.\nZgromadzenie szablonów da mu jeszcze większy wybór różnorodnej broni do Twojego arsenału. + + + Czarodziejka może wyposażyć Twoje ciało w magiczne runy, dzięki czemu będziesz lepszy, silniejszy, szybszy \ni bardziej skoczny.\nZnajdź runy, aby poszerzyć wachlarz jej umiejętności modyfikowania ciała.\n\nJej kryształowa kula jest wyłącznie na pokaz. + + + Czarodziejka może wyposażyć Twoje ciało w magiczne runy, dzięki czemu będziesz lepsza, silniejsza, szybsza \ni bardziej skoczna.\nZnajdź runy, aby poszerzyć wachlarz jej umiejętności modyfikowania ciała.\n\nJej kryształowa kula jest wyłącznie na pokaz. + + + Architekt może zamknąć zamek, aby ochronić go przed zmianami.\n\nPodoba Ci się układ zamku?\nZAMKNIJ GO!\nTylko upewnij się, że Cię na to stać. + + + Architekt może zamknąć zamek, aby ochronić go przed zmianami.\n\nPodoba Ci się układ zamku?\nZAMKNIJ GO!\nTylko upewnij się, że Cię na to stać. + + + Shinobi. Super szybki, super zabójczy wojownik z superową opaską na głowie. Nie może przyjąć zbyt wielu ciosów, ale może rozsiewać ból. Uwierz w to! + + + Shinobi. Super szybki, super zabójczy wojownik z superową opaską na głowie. Nie może przyjąć zbyt wielu ciosów, ale może rozsiewać ból. Uwierz w to! + + + Wyszkoleni raczej w zarabianiu pieniędzy, a nie w zabijaniu wrogów. Górników najlepiej używać do szukania skrzyń ze skarbami w zamku oraz unikania konfrontacji. + + + Wyszkoleni raczej w zarabianiu pieniędzy, a nie w zabijaniu wrogów. Górników najlepiej używać do szukania skrzyń ze skarbami w zamku oraz unikania konfrontacji. + + + Złodziejaszek wyciąga manę \nz wrogów, których uderza. To daje mu nieskończone zapasy many w czasie walki. Do boju! + + + Złodziejaszek wyciąga manę \nz wrogów, których uderza. To daje mu nieskończone zapasy many w czasie walki. Do boju! + + + Mistrz życia i śmierci. Licz ma potencjał mamuta. Każda śmierć daje Liczowi trwałe zdrowie, co sprawia, że jest bardzo niebezpieczną istotą. + + + Mistrz życia i śmierci. Licz ma potencjał mamuta. Każda śmierć daje Liczowi trwałe zdrowie, co sprawia, że jest bardzo niebezpieczną istotą. + + + Przemień swoich Rycerzy \nw Paladynów. Dzięki rygorystycznemu treningowi Paladyni nauczyli się, jak blokować ciosy z każdej strony. + + + Przemień swoich Rycerzy \nw Paladynów. Dzięki rygorystycznemu treningowi Paladyni nauczyli się, jak blokować ciosy z każdej strony. + + + Przemień swoich nędznych Magów \nw Arcymagów. Opanuj wszystkie arkana sztuki i na bieżąco zmieniaj wszystkie zaklęcia. + + + Przemień swoich nędznych Magów \nw Arcymagów. Opanuj wszystkie arkana sztuki i na bieżąco zmieniaj wszystkie zaklęcia. + + + Pierścień Hyperiona + + + Obol Leona + + + Obol Leona + + + Obol Herodotka + + + Obol Herodotka + + + Obol Zdrajcy + + + Obol Zdrajcy + + + Pierścień Hyperiona + + + Buty Hermesa + + + Buty Hermesa + + + Klątwa jeża + + + Klątwa jeża + + + Obol Charona + + + Obol Charona + + + Kompas Kalypso + + + Kompas Kalypso + + + Błogosławieństwo Heliosa + + + Błogosławieństwo Heliosa + + + Dziwne okulary + + + Dziwne okulary + + + Obol Khidra + + + Obol Khidra + + + Obol Aleksandra + + + Obol Aleksandra + + + Rzuca sztylet tuż przed Tobą. + + + Przywołuje Wielkie ostrze do Twojej obrony. + + + Przywołuje Wielkie ostrze do Twojej obrony. + + + Otacza Cię ochronnym ogniem. + + + Otacza Cię ochronnym ogniem. + + + Rzuca kule, które wszędzie skaczą. + + + Rzuca kule, które wszędzie skaczą. + + + Wystrzeliwuje laser, który wysadza w powietrze wszystko, czego dotknie. + + + Wystrzeliwuje laser, który wysadza w powietrze wszystko, czego dotknie. + + + Wystrzeliwuje kule ognia we wrogów. + + + Wystrzeliwuje kule ognia we wrogów. + + + Atakuj zestawem sztyletów. + + + Atakuj zestawem sztyletów. + + + Rzuca sztylet tuż przed Tobą. + + + Rzuca gigantycznym toporem w łuk. + + + Rzuca gigantycznym toporem w łuk. + + + Przywołuje bombę, która po chwili wybucha. + + + Przywołuje bombę, która po chwili wybucha. + + + Włącza zamrażanie wszystkich wrogów na ekranie. + + + Włącza zamrażanie wszystkich wrogów na ekranie. + + + Uderza wszystkich wrogów na ekranie. Kosztowny. + + + Uderza wszystkich wrogów na ekranie. Kosztowny. + + + Rzuca cień i teleportuje Cię do niego. + + + Rzuca cień i teleportuje Cię do niego. + + + Wysyła znak, który Cię teleportuje. + + + Wysyła znak, który Cię teleportuje. + + + Rzuca czakrę, która do Ciebie wraca. + + + Rzuca czakrę, która do Ciebie wraca. + + + Wysyła Kosy, które latają nad Tobą. + + + Wysyła Kosy, które latają nad Tobą. + + + Sztylet + + + Ściana noży + + + Ściana noży + + + Ściana ognia + + + Ściana ognia + + + Konflux + + + Konflux + + + Laser + + + Laser + + + Smoczy ogień + + + Smoczy ogień + + + Szybki sztylet + + + Szybki sztylet + + + Sztylet + + + Topór + + + Topór + + + Bomba + + + Bomba + + + Zatrzymanie czasu + + + Zatrzymanie czasu + + + Kruk + + + Kruk + + + Translokator kwantowy + + + Translokator kwantowy + + + Wypieracz + + + Wypieracz + + + Czakra + + + Czakra + + + Kosa + + + Kosa + + + ...Ładowanie + + + ...Ładowanie + + + Kowal + + + Byłam kiedyś bardzo potężną Czarodziejką. Ale pewnego dnia potwory z tego zamku zaatakowały moje sny i skradły moją wiedzę. + + + Brak dźwięku + + + Brak dźwięku + + + Magiczna skrzynia + + + Magiczna skrzynia + + + Podłoże jest z lawy. + + + Podłoże jest z lawy. + + + Klaun + + + Klaun + + + Hej! Chcesz sprawdzić swoją zręczność?\nMasz tylko jeden strzał, ale za to darmowy! Jeśli Ci się uda, dam Ci nagrodę. + + + Hej! Chcesz sprawdzić swoją zręczność?\nMasz tylko jeden strzał, ale za to darmowy! Jeśli Ci się uda, dam Ci nagrodę. + + + 10 sztyletów, by zniszczyć 8 celów. Chcesz spróbować? + + + 10 sztyletów, by zniszczyć 8 celów. Chcesz spróbować? + + + Klaun + + + Klaun + + + OK, miałeś swoją porcję zabawy. Spadaj! + + + OK, miałaś swoją porcję zabawy. Spadaj! + + + Klaun + + + Klaun + + + Byłam kiedyś bardzo potężną Czarodziejką. Ale pewnego dnia potwory z tego zamku zaatakowały moje sny i skradły moją wiedzę. + + + Ukryły wiedzę w runach, a bez tych run jestem do niczego. + + + Nie widziałem tylu strzałów od czasu mojej ostatniej wizyty w piwiarni (wczoraj). Mam dla Ciebie małą nagrodę za zniszczenie wszystkich celów. + + + Nie widziałam tylu strzałów od czasu mojej ostatniej wizyty w piwiarni (wczoraj). Mam dla Ciebie małą nagrodę za zniszczenie wszystkich celów. + + + Klaun + + + Klaun + + + Nie udało Ci się nawet trafić 8 celów?\nPffft. Powodzenia z resztą zamku. + + + Nie udało Ci się nawet trafić 8 celów?\nPffft. Powodzenia z resztą zamku. + + + Klaun + + + Klaun + + + Hej! Przekonajmy się, jakie są twoje umiejętności.\nMasz tylko jeden strzał, ale za to darmowy! Jeśli Ci się uda, dam Ci nagrodę. + + + Hej! Przekonajmy się, jakie są twoje umiejętności.\nMasz tylko jeden strzał, ale za to darmowy! Jeśli Ci się uda, dam Ci nagrodę. + + + Dostajesz 5 toporów, by zniszczyć jak najwięcej celów. Niech zostanie ich mniej niż 10, a dostaniesz specjalną nagrodę. Chcesz spróbować? + + + Dostajesz 5 toporów, by zniszczyć jak najwięcej celów. Niech zostanie ich mniej niż 10, a dostaniesz specjalną nagrodę. Chcesz spróbować? + + + Klaun + + + Klaun + + + Niesamowite! Nie zostawiłeś więcej niż 10 celów! A ponieważ nie mam już więcej celów, by kontynuować tę zabawę, mogę równie dobrze dać Ci moje zapasy. + + + Niesamowite! Nie zostawiłaś więcej niż 10 celów! A ponieważ nie mam już więcej celów, by kontynuować tę zabawę, mogę równie dobrze dać Ci moje zapasy. + + + Ukryły wiedzę w runach, a bez tych run jestem do niczego. + + + Proszę, bohaterko, jeśli znajdziesz jakieś runy, przynieś je do mnie, a wtedy odsprzedam Ci je za odpowiednią sumę! + + + Klaun + + + Klaun + + + Pozostało ponad 10 celów.\nChyba wcale nie chcesz tej nagrody. Pach! + + + Pozostało ponad 10 celów.\nChyba wcale nie chcesz tej nagrody. Pach! + + + ??? + + + ??? + + + Witaj, poszukiwaczu przygód. Jestem tu, by dać Ci szansę Twojego życia! + + + Witaj, poszukiwaczu przygód. Jestem tu, by dać Ci szansę Twojego życia! + + + Chytry elf + + + Chytry elf + + + Za marne 25% Twojego aktualnego złota pozwolę Ci otworzyć 1 z 3 skrzyń. + + + Za marne 25% Twojego aktualnego złota pozwolę Ci otworzyć 1 z 3 skrzyń. + + + Jedna skrzynia potroi to, co zapłaciłeś, dwie pozostałe są puste. + + + Jedna skrzynia potroi to, co zapłaciłaś, dwie pozostałe są puste. + + + Elf-skąpiec + + + Elf-skąpiec + + + Chcesz spróbować? + + + Chcesz spróbować? + + + Proszę, bohaterko, jeśli znajdziesz jakieś runy, przynieś je do mnie, a wtedy odsprzedam Ci je za odpowiednią sumę! + + + Architekt + + + ??? + + + ??? + + + Witaj, poszukiwaczu przygód. Jestem tu, by dać Ci szansę Twojego życia! + + + Witaj, poszukiwaczko przygód. Jestem tu, by dać Ci szansę Twojego życia! + + + Chytry elf + + + Chytry elf + + + Za marne 50% Twojego aktualnego złota pozwolę Ci otworzyć 1 z 3 skrzyń. + + + Za marne 50% Twojego aktualnego złota pozwolę Ci otworzyć 1 z 3 skrzyń. + + + Jedna skrzynia potroi to, co zapłaciłeś, dwie pozostałe są puste. + + + Jedna skrzynia potroi to, co zapłaciłaś, dwie pozostałe są puste. + + + Elf-skąpiec + + + Elf-skąpiec + + + Chcesz spróbować? + + + Chcesz spróbować? + + + ??? + + + ??? + + + Witaj, poszukiwaczu przygód. Jestem tu, by dać Ci szansę Twojego życia! + + + Witaj, poszukiwaczko przygód. Jestem tu, by dać Ci szansę Twojego życia! + + + Chytry elf + + + Chytry elf + + + Architekt + + + Wiiiiitaaaaaj chłopcze! + + + Za marne 75% Twojego aktualnego złota pozwolę Ci otworzyć 1 z 3 skrzyń. + + + Za marne 75% Twojego aktualnego złota pozwolę Ci otworzyć 1 z 3 skrzyń. + + + Jedna skrzynia potroi to, co zapłaciłeś, dwie pozostałe są puste. + + + Jedna skrzynia potroi to, co zapłaciłeś, dwie pozostałe są puste. + + + Elf-skąpiec + + + Elf-skąpiec + + + Chcesz spróbować? + + + Chcesz spróbować? + + + Elf-skąpiec + + + Elf-skąpiec + + + Masz za mało pieniędzy? Kiepsko. + + + Masz za mało pieniędzy? Kiepsko. + + + Elf-zwycięzca + + + Elf-zwycięzca + + + Co jest w tym pudle? + + + Co jest w tym pudle? + + + NIC! + + + NIC! + + + Jesteś głupi! Strasznie głupi! + + + Jesteś głupia! Strasznie głupia! + + + Wiiiiitaaaaaj chłopcze! + + + Chcesz usłyszeć coś fajnego? Jestem szaloooony! + + + Elf-zwycięzca + + + Elf-zwycięzca + + + Css! Tym razem miałeś szczęście. + + + Css! Tym razem miałaś szczęście. + + + Niecierpliwy elf + + + Niecierpliwy elf + + + Otwórz już skrzynię! + + + Otwórz już skrzynię! + + + Elf-skąpiec + + + Elf-skąpiec + + + Sorki, kolego, jedna skrzynia na osobę. + + + Sorki, koleżanko, jedna skrzynia na osobę. + + + Autorzy + + + Autorzy + + + Don't **** Your Pants.\nCzas tworzenia: 2 dni.\nData wydania: 16 lutego 2009 + + + Don't **** Your Pants.\nCzas tworzenia: 2 dni.\nData wydania: 16 lutego 2009 + + + Chcesz usłyszeć coś fajnego? Jestem szaloooony! + + + Ta dźwignia tutaj? Jednym pociągnięciem mogę zabezpieczyć zamek przed zmianą. + + + To była pierwsza gra, jaką zrobiliśmy, i wtedy nazywaliśmy się Decade Studios. Musisz w niej powstrzymać człowieka przed zrobieniem kupy w majtki, mogąc jedynie wpisywać tekst. + + + To była pierwsza gra, jaką zrobiliśmy, i wtedy nazywaliśmy się Decade Studios. Musisz w niej powstrzymać człowieka przed zrobieniem kupy w majtki, mogąc jedynie wpisywać tekst. + + + Została pierwotnie zaprojektowana w autobusie i pewnego weekendu postanowiliśmy ją stworzyć. Była całkiem niezła. + + + Została pierwotnie zaprojektowana w autobusie i pewnego weekendu postanowiliśmy ją stworzyć. Była całkiem niezła. + + + W tytule gry jest przekleństwo, więc chcieliśmy zmienić go na coś przyjemniejszego. Ale wtedy do głosu doszły nasze ambicje i postanowiliśmy iść na całość. + + + W tytule gry jest przekleństwo, więc chcieliśmy zmienić go na coś przyjemniejszego. Ale wtedy do głosu doszły nasze ambicje i postanowiliśmy iść na całość. + + + Duża część gry obejmowała tekstową grę przygodową, w której ludzie mogli wpisywać, co tylko chcieli. Aby gra działała, musieliśmy przewidzieć, co ludzie będą pisać. + + + Duża część gry obejmowała tekstową grę przygodową, w której ludzie mogli wpisywać, co tylko chcieli. Aby gra działała, musieliśmy przewidzieć, co ludzie będą pisać. + + + Robiliśmy to na 2 sposoby. Najpierw zmniejszyliśmy liczbę opcji dla gracza (człowiek i drzwi), a po drugie zbudowaliśmy system osiągnięć, który był używany do wskazywania graczowi kierunku. + + + Robiliśmy to na 2 sposoby. Najpierw zmniejszyliśmy liczbę opcji dla gracza (człowiek i drzwi), a po drugie zbudowaliśmy system osiągnięć, który był używany do wskazywania graczowi kierunku. + + + Gra tak się rozrosła wokół tego systemu osiągnięć, że został on umieszczony na ekranie postępów na zakończenie gry. To była niewielka, ale istotna zmiana. + + + Gra tak się rozrosła wokół tego systemu osiągnięć, że został on umieszczony na ekranie postępów na zakończenie gry. To była niewielka, ale istotna zmiana. + + + Autorzy + + + Autorzy + + + Band of Bears\nCzas tworzenia: 4 miesiące.\nData wydania: 6 sierpnia 2009 + + + Band of Bears\nCzas tworzenia: 4 miesiące.\nData wydania: 6 sierpnia 2009 + + + Ta dźwignia tutaj? Jednym pociągnięciem mogę zabezpieczyć zamek przed zmianą. + + + W ten sposób możesz przejść dokładnie przez to, co Twoi przodkowie. Jesteś pod wrażeeeeniem? I słusznie. + + + To była nasza druga próba stworzenia gry, a było to przy okazji konkursu DreamBuildPlay, który odbył się w 2009 roku. Dowiedzieliśmy się o nim dość późno, więc musieliśmy dogonić pozostałych uczestników. + + + To była nasza druga próba stworzenia gry, a było to przy okazji konkursu DreamBuildPlay, który odbył się w 2009 roku. Dowiedzieliśmy się o nim dość późno, więc musieliśmy dogonić pozostałych uczestników. + + + Świeżo po sukcesie DSYP postanowiliśmy zrobić coś dużego... obłędnie dużego. I tak powstało Cellar Door Games. + + + Świeżo po sukcesie DSYP postanowiliśmy zrobić coś dużego... obłędnie dużego. I tak powstało Cellar Door Games. + + + Oprócz rozpoczęcia projektu, który zdecydowanie przekraczał nasze możliwości i wiedzę, musieliśmy pracować na pełen etat, żeby udało się ostatecznie stworzyć tę grę. Wyglądało to dosyć kiepsko. + + + Oprócz rozpoczęcia projektu, który zdecydowanie przekraczał nasze możliwości i wiedzę, musieliśmy pracować na pełen etat, żeby udało się ostatecznie stworzyć tę grę. Wyglądało to dosyć kiepsko. + + + Gra zawierała system B.E.A.R.S (Bare Effort Adaptable Room System), który mógł zmieniać pokoje w zależności od liczby graczy. + + + Gra zawierała system B.E.A.R.S (Bare Effort Adaptable Room System), który mógł zmieniać pokoje w zależności od liczby graczy. + + + System BEARS zmieniał nie tylko numerki, ale także puzzle. Ukończyliśmy konkurs w pierwszej 20, co było niezłym wynikiem, ale nie na tyle dobrym, by coś wygrać. + + + System BEARS zmieniał nie tylko numerki, ale także puzzle. Ukończyliśmy konkurs w pierwszej 20, co było niezłym wynikiem, ale nie na tyle dobrym, by coś wygrać. + + + W końcu dopadła nas rzeczywistość (i zdrowy rozsądek) i zdaliśmy sobie sprawę, że musimy zrezygnować z tego projektu albo przynajmniej zrobić sobie przerwę na jakiś czas. + + + W końcu dopadła nas rzeczywistość (i zdrowy rozsądek) i zdaliśmy sobie sprawę, że musimy zrezygnować z tego projektu albo przynajmniej zrobić sobie przerwę na jakiś czas. + + + Demówka była dość odlotowa. + + + Demówka była dość odlotowa. + + + Autorzy + + + Autorzy + + + Tribal Tallies\nCzas tworzenia: 3 miesiące.\nData wydania: 23 listopada 2009 + + + Tribal Tallies\nCzas tworzenia: 3 miesiące.\nData wydania: 23 listopada 2009 + + + W ten sposób możesz przejść dokładnie przez to, co Twoi przodkowie. Jesteś pod wrażeeeeniem? I słusznie. + + + Jak zbudowałem to fantastyczne urządzeeenie? Przy pomocy nauuuuki, oczywiście! I magii. + + + Tribal Tallies to pierwszy projekt, nad którym pracowaliśmy po paru miesiącach od czasu tego okropnego doświadczenia z Band of Bears. + + + Tribal Tallies to pierwszy projekt, nad którym pracowaliśmy po paru miesiącach od czasu tego okropnego doświadczenia z Band of Bears. + + + To był taki trochę próbny projekt, chcieliśmy spróbować naszych sił w grach na system iOS, bo nigdy wcześniej nie robiliśmy niczego na platformy mobilne. + + + To był taki trochę próbny projekt, chcieliśmy spróbować naszych sił w grach na system iOS, bo nigdy wcześniej nie robiliśmy niczego na platformy mobilne. + + + Gra była prosta w swoim założeniu, po prostu wpisywało się kolejne liczby w jak najszybszym tempie. + + + Gra była prosta w swoim założeniu, po prostu wpisywało się kolejne liczby w jak najszybszym tempie. + + + Aby dodać trochę smaczku, wprowadziliśmy kilka trybów, takich jak wpisywanie do tyłu, ukryte liczby oraz naciskanie z dopasowaniem. + + + Aby dodać trochę smaczku, wprowadziliśmy kilka trybów, takich jak wpisywanie do tyłu, ukryte liczby oraz naciskanie z dopasowaniem. + + + Uważaliśmy, że to było do zrobienia, ale okazało się, że stworzenie gry zabiera dużo więcej czasu niż się spodziewaliśmy. To, że wszystko było zakodowane na hackintoshu, wcale nie pomagało. + + + Uważaliśmy, że to było do zrobienia, ale okazało się, że stworzenie gry zabiera dużo więcej czasu niż się spodziewaliśmy. To, że wszystko było zakodowane na hackintoshu, wcale nie pomagało. + + + To była całkiem zwyczajna gra. Mogliśmy zrobić to dużo lepiej, ale po doświadczeniu z Band of Bears woleliśmy uważać. + + + To była całkiem zwyczajna gra. Mogliśmy zrobić to dużo lepiej, ale po doświadczeniu z Band of Bears woleliśmy uważać. + + + Autorzy + + + Autorzy + + + Q\nCzas tworzenia: 1 miesiąc.\nData wydania: 18 marca 2010 + + + Q\nCzas tworzenia: 1 miesiąc.\nData wydania: 18 marca 2010 + + + Jak zbudowałem to fantastyczne urządzeeenie? Przy pomocy nauuuuki, oczywiście! I magii. + + + ... Głównie magii. + + + Nasz czwarty projekt. Po grze Tribal Tallies zrobiliśmy sobie parę miesięcy wolnego od tworzenia gier i skupiliśmy się na naszych pełnoetatowych pracach. Potem znów zaczęło nas nosić, więc postanowiliśmy stworzyć grę logiczną. + + + Nasz czwarty projekt. Po grze Tribal Tallies zrobiliśmy sobie parę miesięcy wolnego od tworzenia gier i skupiliśmy się na naszych pełnoetatowych pracach. Potem znów zaczęło nas nosić, więc postanowiliśmy stworzyć grę logiczną. + + + W tamtym czasie większość pierwszych założycieli Cellar Door Games odeszła, by szukać innych możliwości, a niechciane niedobitki tworzą dzisiaj firmę. + + + W tamtym czasie większość pierwszych założycieli Cellar Door Games odeszła, by szukać innych możliwości, a niechciane niedobitki tworzą dzisiaj firmę. + + + Gra używała mechanizmu ustawiania w kolejce kombinacji i miała zmusić graczy do zastanowienia się, jak spadną płytki, aby stworzyć jak największe kombinacje. + + + Gra używała mechanizmu ustawiania w kolejce kombinacji i miała zmusić graczy do zastanowienia się, jak spadną płytki, aby stworzyć jak największe kombinacje. + + + Gra była darmowa, ale i tak nikt się nią nie zainteresował. Po porażkach Band of Bears, Tribal Tallies i Q przygotowywaliśmy się do zamknięcia firmy. + + + Gra była darmowa, ale i tak nikt się nią nie zainteresował. Po porażkach Band of Bears, Tribal Tallies i Q przygotowywaliśmy się do zamknięcia firmy. + + + Autorzy + + + Autorzy + + + My First Quantum Translocator\nCzas tworzenia: 1 miesiąc.\nData wydania: 13 października 2010 + + + My First Quantum Translocator\nCzas tworzenia: 1 miesiąc.\nData wydania: 13 października 2010 + + + My First Quantum Translocator pojawił się, gdy nasza firma przeżywała najgorsze chwile. Po 3 nieudanych grach mentalnie już daliśmy sobie spokój, ale postanowiliśmy zrobić tę niewielką grę flash tak dla śmiechu. + + + My First Quantum Translocator pojawił się, gdy nasza firma przeżywała najgorsze chwile. Po 3 nieudanych grach mentalnie już daliśmy sobie spokój, ale postanowiliśmy zrobić tę niewielką grę flash tak dla śmiechu. + + + ... Głównie magii. + + + Kowal + + + Witaj, bohaterze. + + + Ale moje umiejętności mają swoją cenę. Jeśli zamknę ten zamek, wezmę 40% złota, które zdobędziesz! + + + W czasie jej tworzenia nie mieliśmy żadnych oczekiwań i robiliśmy ją przede wszystkim dla zabawy. + + + W czasie jej tworzenia nie mieliśmy żadnych oczekiwań i robiliśmy ją przede wszystkim dla zabawy. + + + Nie trzeba nawet mówić, że odzew był ogromny i ta gra jest jedynym powodem tego, że firma Cellar Door Games nadal istnieje. W chwili, gdy wydaliśmy MFQT, wiedzieliśmy, że nie ma powrotu. + + + Nie trzeba nawet mówić, że odzew był ogromny i ta gra jest jedynym powodem tego, że firma Cellar Door Games nadal istnieje. W chwili, gdy wydaliśmy MFQT, wiedzieliśmy, że nie ma powrotu. + + + Wielu ludzi uważa, że gra została zainspirowana przez Portal, ale podobieństwa były zupełnie przypadkowe. + + + Wielu ludzi uważa, że gra została zainspirowana przez Portal, ale podobieństwa były zupełnie przypadkowe. + + + Gra zrodziła się z pomysłu na bohatera, którego wymyśliliśmy do gry League of Legends. + + + Gra zrodziła się z pomysłu na bohatera, którego wymyśliliśmy do gry League of Legends. + + + Tak naprawdę podobieństwa pomiędzy grami Portal i MFQT pojawiły się dopiero wtedy, gdy dodaliśmy końcową grafikę i fabułę. + + + Tak naprawdę podobieństwa pomiędzy grami Portal i MFQT pojawiły się dopiero wtedy, gdy dodaliśmy końcową grafikę i fabułę. + + + Tak czy inaczej, byliśmy dość dumni z gry. Dobrze się w nią grało i miała fajne zakończenie. + + + Tak czy inaczej, byliśmy dość dumni z gry. Dobrze się w nią grało i miała fajne zakończenie. + + + Autorzy + + + Autorzy + + + I Have 1 Day\nCzas tworzenia: 1,5 miesiąca.\nData wydania: 15 kwietnia 2011 + + + I Have 1 Day\nCzas tworzenia: 1,5 miesiąca.\nData wydania: 15 kwietnia 2011 + + + Ale moje umiejętności mają swoją cenę. Jeśli zamknę ten zamek, wezmę 40% złota, które zdobędziesz! + + + + + + Gdyby ktoś nas zapytał, jaka jest nasza ulubiona gra z tych, które zrobiliśmy, jednogłośnie wybralibyśmy I Have 1 Day. + + + Gdyby ktoś nas zapytał, jaka jest nasza ulubiona gra z tych, które zrobiliśmy, jednogłośnie wybralibyśmy I Have 1 Day. + + + Jako dzieci wychowywaliśmy się na klasycznych grach, takich jak Kings Quest i Monkey Island, więc to było naszym ukłonem w stronę naszych najlepszych gierkowych doświadczeń. + + + Jako dzieci wychowywaliśmy się na klasycznych grach, takich jak Kings Quest i Monkey Island, więc to było naszym ukłonem w stronę naszych najlepszych gierkowych doświadczeń. + + + Gra toczy się wokół meta-czasowej łamigłówki, a gracz ma tylko 24 godziny na przejście gry. + + + Gra toczy się wokół meta-czasowej łamigłówki, a gracz ma tylko 24 godziny na przejście gry. + + + Każda łamigłówka miała wiele rozwiązań z różnymi skutkami czasowymi, a gracze byli zmuszeni do wymyślania najlepszych rozwiązań. + + + Każda łamigłówka miała wiele rozwiązań z różnymi skutkami czasowymi, a gracze byli zmuszeni do wymyślania najlepszych rozwiązań. + + + Jedna ciekawostka. Drugie zakończenie zostało dodane dosłownie w ostatniej chwili, a bez niego cała gra byłaby do niczego. + + + Jedna ciekawostka. Drugie zakończenie zostało dodane dosłownie w ostatniej chwili, a bez niego cała gra byłaby do niczego. + + + Autorzy + + + Autorzy + + + Podbij wioskę (Villainous)\nCzas tworzenia: 3 miesiące\nData wydania: 15 kwietnia 2011 + + + Podbij wioskę (Villainous)\nCzas tworzenia: 3 miesiące\nData wydania: 15 kwietnia 2011 + + + Gra Podbij wioskę to jedno z naszych najbardziej ryzykownych przedsięwzięć. + + + Gra Podbij wioskę to jedno z naszych najbardziej ryzykownych przedsięwzięć. + + + + + + Czy chcesz zamknąć zamek i mieć tylko 60% złota? + + + Mieliśmy pomysł, by odwrócić gry typu obrona wieży – naszym zdaniem mogło to być interesujące, ale trudno było sprawić, żeby to nie tylko „mogło być”, ale „naprawdę było”. + + + Mieliśmy pomysł, by odwrócić gry typu obrona wieży – naszym zdaniem mogło to być interesujące, ale trudno było sprawić, żeby to nie tylko „mogło być”, ale „naprawdę było”. + + + Większość ludzi grających w grę uważała ten proces za oczywisty, ale nas kosztowało to dużo stresu i kłótni. + + + Większość ludzi grających w grę uważała ten proces za oczywisty, ale nas kosztowało to dużo stresu i kłótni. + + + Cały pomysł lądował w koszu 3 czy 4 razy, zanim w końcu uzgodniliśmy wersję ostateczną. + + + Cały pomysł lądował w koszu 3 czy 4 razy, zanim w końcu uzgodniliśmy wersję ostateczną. + + + To dość ironiczne, że gra Podbij wioskę odniosła największy sukces ze wszystkich naszych gier. Nas kosztowała ona najwięcej bólu. + + + To dość ironiczne, że gra Podbij wioskę odniosła największy sukces ze wszystkich naszych gier. Nas kosztowała ona najwięcej bólu. + + + Autorzy + + + Autorzy + + + Bullet Audyssey\nCzas tworzenia: 3,5 miesiąca.\nData wydania: 29 listopada 2011 + + + Bullet Audyssey\nCzas tworzenia: 3,5 miesiąca.\nData wydania: 29 listopada 2011 + + + Bullet Audyssey to nasza ostatnia gra przed Rogue Legacy. + + + Bullet Audyssey to nasza ostatnia gra przed Rogue Legacy. + + + Pociski dopasowane do rytmu, czyli Bullet Audyssey, to gra, która pod względem technicznym była największym wyzwaniem, nad którym kiedykolwiek pracowaliśmy (tak, nawet większym niż Rogue Legacy). + + + Pociski dopasowane do rytmu, czyli Bullet Audyssey, to gra, która pod względem technicznym była największym wyzwaniem, nad którym kiedykolwiek pracowaliśmy (tak, nawet większym niż Rogue Legacy). + + + Czy chcesz zamknąć zamek i mieć tylko 60% złota? + + + + + + Samo stworzenie sceny wymagało jednoczesnej pracy 3 redaktorów. + + + Samo stworzenie sceny wymagało jednoczesnej pracy 3 redaktorów. + + + Tworzenie tej gry nie było całkowicie typowe, potrzeba było dużo planowania z wyprzedzeniem, by wszystko grało. + + + Tworzenie tej gry nie było całkowicie typowe, potrzeba było dużo planowania z wyprzedzeniem, by wszystko grało. + + + Ponieważ jesteśmy wielkimi przeciwnikami wszelkich dokumentacji, gra ta nie była dla nas zbyt wygodna, więc musieliśmy ją dokładnie omówić, co zajęło nam jakieś pół dnia. + + + Ponieważ jesteśmy wielkimi przeciwnikami wszelkich dokumentacji, gra ta nie była dla nas zbyt wygodna, więc musieliśmy ją dokładnie omówić, co zajęło nam jakieś pół dnia. + + + W grze gracz pochłaniał pociski wroga, by wystrzeliwać je z powrotem, a pochłanianie następowało w rytmie dopasowanym do granej piosenki. + + + W grze gracz pochłaniał pociski wroga, by wystrzeliwać je z powrotem, a pochłanianie następowało w rytmie dopasowanym do granej piosenki. + + + Pierwsze testy były jedną wielką katastrofą. Gra była zbyt trudna, co frustrowało graczy od samego początku. + + + Pierwsze testy były jedną wielką katastrofą. Gra była zbyt trudna, co frustrowało graczy od samego początku. + + + Mówiąc o testach gry mamy na myśli jednego gościa, który nawet nie lubi Bullet Hells. Chociaż to i tak więcej niż zwyczajowy zakres naszych testów. + + + Mówiąc o testach gry mamy na myśli jednego gościa, który nawet nie lubi Bullet Hells. Chociaż to i tak więcej niż zwyczajowy zakres naszych testów. + + + Po premierze gra nie radziła sobie zbyt dobrze. To utwierdziło nas w zamiarze stworzenia Rogue Legacy! + + + Po premierze gra nie radziła sobie zbyt dobrze. To utwierdziło nas w zamiarze stworzenia Rogue Legacy! + + + Potwierdź + + + Potwierdź + + + Anuluj + + + Anuluj + + + Ostrzeżenie! + + + Ostrzeżenie! + + + + + + Czy chcesz zamknąć zamek i mieć tylko 60% złota? + + + Czy na pewno chcesz zacząć nową grę? Wszystkie wcześniej zapisane dane zostaną skasowane. + + + Czy na pewno chcesz zacząć nową grę? Wszystkie wcześniej zapisane dane zostaną skasowane. + + + Przywróć sterowanie + + + Przywróć sterowanie + + + Czy na pewno chcesz powrócić do domyślnego schematu sterowania? + + + Czy na pewno chcesz powrócić do domyślnego schematu sterowania? + + + + + + + + + Czy na pewno chcesz rozpocząć nową przygodę z wybraną postacią? + + + Czy na pewno chcesz rozpocząć nową przygodę z wybraną postacią? + + + Nastąpiła zmiana rozdzielczości + + + Nastąpiła zmiana rozdzielczości + + + Czy na pewno chcesz korzystać z tej rozdzielczości?\n(W ciągu 10 sekund nastąpi powrót do poprzedniej rozdzielczości) + + + Czy na pewno chcesz korzystać z tej rozdzielczości?\n(W ciągu 10 sekund nastąpi powrót do poprzedniej rozdzielczości) + + + Usuń plik ze stanem gry + + + Usuń plik ze stanem gry + + + Czy na pewno chcesz usunąć plik ze stanem gry?\n(Wszystkie umiejętności, cechy, rodowody i ekwipunek zostaną usunięte NA ZAWSZE) + + + Czy na pewno chcesz usunąć plik ze stanem gry?\n(Wszystkie umiejętności, cechy, rodowody i ekwipunek zostaną usunięte NA ZAWSZE) + + + Czy chcesz zamknąć zamek i mieć tylko 60% złota? + + + Architekt + + + Usuń plik ze stanem gry + + + Usuń plik ze stanem gry + + + Czy jesteś CAŁKOWICIE pewny? (Nie będzie powrotu)\n(Wszystkie umiejętności, cechy, rodowody i ekwipunek zostaną usunięte NA ZAWSZE) + + + Czy jesteś CAŁKOWICIE pewna? (Nie będzie powrotu)\n(Wszystkie umiejętności, cechy, rodowody i ekwipunek zostaną usunięte NA ZAWSZE) + + + + + + + + + Czy na pewno chcesz przejść do menu głównego? (Twój aktualny status zostanie zapisany) + + + Czy na pewno chcesz przejść do menu głównego? (Twój aktualny status zostanie zapisany) + + + + + + + + + Czy na pewno chcesz skończyć grać w Rogue Legacy? (Twój aktualny status zostanie zapisany) + + + Czy na pewno chcesz skończyć grać w Rogue Legacy? (Twój aktualny status zostanie zapisany) + + + Błąd zapisywania + + + Błąd zapisywania + + + O nie! Twój plik ze stanem gry został uszkodzony! + + + O nie! Twój plik ze stanem gry został uszkodzony! + + + Architekt + + + Przykro mi, chłopcze, nie ma teraz zamku do wybudowania. Ta wielka śruba jest tylko na pokaz. + + + Próba załadowania zapasowego stanu gry. Mamy nadzieję, że to nie cofnie Cię za bardzo. + + + Próba załadowania zapasowego stanu gry. Mamy nadzieję, że to nie cofnie Cię za bardzo. + + + Błąd zapisywania + + + Błąd zapisywania + + + Wygląda na to, że kopia zapasowa również nie działa. Prosimy o kontakt: support@cellardoorgames.com + Wygląda na to, że kopia zapasowa również nie działa. Niestety, musimy zrestartować grę. + + + Wygląda na to, że kopia zapasowa również nie działa. Prosimy o kontakt: support@cellardoorgames.com + Wygląda na to, że kopia zapasowa również nie działa. Niestety, musimy zrestartować grę. + + + Błąd zapisywania + + + Błąd zapisywania + + + Nie udało się zapisać Twojej gry 3 razy z rzędu. + + + Nie udało się zapisać Twojej gry 3 razy z rzędu. + + + Programy antywirusowe i ręczne programy do tworzenia kopii zapasowych mogą powodować konflikty z plikami ze stanem gry. Przed uruchomieniem gry wyłącz te programy. + + + Programy antywirusowe i ręczne programy do tworzenia kopii zapasowych mogą powodować konflikty z plikami ze stanem gry. Przed uruchomieniem gry wyłącz te programy. + + + Przykro mi, chłopcze, nie ma teraz zamku do wybudowania. Ta wielka śruba jest tylko na pokaz. + + + Architekt + + + Architekt + + + Hej, ten zamek jest już zamknięty. + + + Hej, ten zamek jest już zamknięty. + + + Architekt + + + Architekt + + + Witaj, bohaterze. + + + Może mógłbyś mi pomóc. Byłem kiedyś najlepszym kowalem na tych ziemiach. Ale pewnego dnia potwory z tego zamku zaatakowały moją kuźnię i ukradły wszystkie moje szablony. + + + Baw się dooobrze! Może trafisz na jakieś skarrrrby, które przegapili Twoi przodkowie! + + + Baw się dooobrze! Może trafisz na jakieś skarrrrby, które przegapili Twoi przodkowie! + + + Charon + + + Charon + + + ... Trzeba uiścić opłatę. + + + ... Trzeba uiścić opłatę. + + + + + + + + + (Dać Charonowi wszystkie Twoje pieniądze i wejść do zamku?) + + + (Dać Charonowi wszystkie Twoje pieniądze i wejść do zamku?) + + + + + + + + + (Dać Charonowi wszystkie Twoje pieniądze i wejść do zamku?) + + + (Dać Charonowi wszystkie Twoje pieniądze i wejść do zamku?) + + + + + + + + + (Dać Charonowi 90% Twoich pieniędzy i wejść do zamku?) + + + (Dać Charonowi 90% Twoich pieniędzy i wejść do zamku?) + + + + + + + + + Może mógłbyś mi pomóc. Byłem kiedyś najlepszym kowalem na tych ziemiach. Ale pewnego dnia potwory z tego zamku zaatakowały moją kuźnię i ukradły wszystkie moje szablony. + + + Bez tych szablonów mogę tylko robić sztućce i takie tam. + + + (Dać Charonowi 80% Twoich pieniędzy i wejść do zamku?) + + + (Dać Charonowi 80% Twoich pieniędzy i wejść do zamku?) + + + + + + + + + (Dać Charonowi 70% Twoich pieniędzy i wejść do zamku?) + + + (Dać Charonowi 70% Twoich pieniędzy i wejść do zamku?) + + + + + + + + + (Dać Charonowi 60% Twoich pieniędzy i wejść do zamku?) + + + (Dać Charonowi 60% Twoich pieniędzy i wejść do zamku?) + + + + + + + + + (Dać Charonowi 50% Twoich pieniędzy i wejść do zamku?) + + + (Dać Charonowi 50% Twoich pieniędzy i wejść do zamku?) + + + Charon + + + Charon + + + O, ho, ho! Więc masz mojego obola. Pozwolę Ci przejść za darmo, ale tylko ten jeden raz. + + + O, ho, ho! Więc masz mojego obola. Pozwolę Ci przejść za darmo, ale tylko ten jeden raz. + + + Charon + + + Charon + + + Bez tych szablonów mogę tylko robić sztućce i takie tam. + + + Proszę, przynieś mi każdy szablon, jaki znajdziesz, a będę mógł tworzyć najwspanialsze wyposażenie na świecie. NA CAŁYM ŚWIECIE. + + + Oho! To bardzo wyjątkowy obol. + + + Oho! To bardzo wyjątkowy obol. + + + Daj mi go, a pozwolę Twojej duszy przejść przez inne bramy. + + + Daj mi go, a pozwolę Twojej duszy przejść przez inne bramy. + + + (Dać Charonowi obola i uiścić opłatę?) + + + (Dać Charonowi obola i uiścić opłatę?) + + + Charon + + + Charon + + + Oho! To bardzo wyjątkowy obol. + + + Oho! To bardzo wyjątkowy obol. + + + Daj mi go, a pozwolę Twojej duszy przejść przez inne bramy. + + + Daj mi go, a pozwolę Twojej duszy przejść przez inne bramy. + + + (Dać Charonowi obola i uiścić opłatę?) + + + (Dać Charonowi obola i uiścić opłatę?) + + + Charon + + + Charon + + + Oho! To bardzo wyjątkowy obol. + + + Oho! To bardzo wyjątkowy obol. + + + Daj mi go, a pozwolę Twojej duszy przejść przez inne bramy. + + + Daj mi go, a pozwolę Twojej duszy przejść przez inne bramy. + + + Proszę, przynieś mi każdy szablon, jaki znajdziesz, a będę mógł tworzyć najwspanialsze wyposażenie na świecie. NA CAŁYM ŚWIECIE. + + + ... Za odpowiednią cenę, oczywiście. + + + (Dać Charonowi obola i uiścić opłatę?) + + + (Dać Charonowi obola i uiścić opłatę?) + + + Charon + + + Charon + + + Oho! To bardzo wyjątkowy obol. + + + Oho! To bardzo wyjątkowy obol. + + + Daj mi go, a pozwolę Twojej duszy przejść przez inne bramy. + + + Daj mi go, a pozwolę Twojej duszy przejść przez inne bramy. + + + (Dać Charonowi obola i uiścić opłatę?) + + + (Dać Charonowi obola i uiścić opłatę?) + + + Charon + + + Charon + + + Och. Nie powinieneś był brać tego obola. + + + Och. Nie powinnaś była brać tego obola. + + + Przygotuj się. + + + Przygotuj się. + + + (Dać Charonowi obola i uiścić opłatę?) + + + (Dać Charonowi obola i uiścić opłatę?) + + + Kapliczka + + + Kapliczka + + + ... Za odpowiednią cenę, oczywiście. + + + Czarodziejka + + + Pomodlisz się o pomoc? + + + Pomodlisz się o pomoc? + + + Ostatni boss + + + Ostatni boss + + + Witaj, bohaterze! To całkiem imponujące, że dotarłeś tak daleko. Niestety, dalej już nie pójdziesz. + + + Witaj, bohaterko! To całkiem imponujące, że dotarłaś tak daleko. Niestety, dalej już nie pójdziesz. + + + Magiczna skrzynia – nic + + + Magiczna skrzynia – nic + + + BRAK TEKSTU + + + BRAK TEKSTU + + + Pokonaj wszystkich wrogów + + + Pokonaj wszystkich wrogów + + + + + + + + + Mało zdrowia + + + Mało zdrowia + + + + + + + + + Nie patrzeć + + + Nie patrzeć + + + Czarodziejka + + + Witaj, bohaterko. + + + + + + + + + Nie skakać + + + Nie skakać + + + + + + + + + Nie hałasować + + + Nie hałasować + + + + + + + + + Nie dotykać podłogi + + + Nie dotykać podłogi + + + + + + + + + Nie walczyć + + + Nie walczyć + + + + + + + + + Dotrzyj do mnie w porę + + + Dotrzyj do mnie w porę + + + Witaj, bohaterko. + + + Czy możesz poświęcić mi minutkę? Potrzebuję Twojej pomocy. + + + + + + + + + Nie doznawaj obrażeń + + + Nie doznawaj obrażeń + + + + + + + + + Znajdź mnie + + + Znajdź mnie + + + + + + + + + Magiczna skrzynia + + + Magiczna skrzynia + + + Nie patrz na mnie! + + + Nie patrz na mnie! + + + Magiczna skrzynia + + + Magiczna skrzynia + + + Nie skakać + + + Nie skakać + + + Magiczna skrzynia + + + Magiczna skrzynia + + + Czy możesz poświęcić mi minutkę? Potrzebuję Twojej pomocy. + + + Naciśnij [Input:12], aby zaatakować + + + Naciśnij [Input:12], aby zaatakować + + + Kontynuuj swoją misję + + + Kontynuuj swoją misję + + + Wybierz swojego sukcesora + + + Wybierz swojego sukcesora + + + Rozpocznij swoje dziedzictwo + + + Rozpocznij swoje dziedzictwo + + + Manekin + + + TO BOOOOLI + + + TO BOOOOLI + + + Uf + + + Uf + + + Ałć + + + Ałć + + + BLA + + + BLA + + + Poddaję się! + + + Poddaję się! + + + Pakujesz? + + + Pakujesz? + + + OK, to bolało + + + OK, to bolało + + + To łaskotało + + + To łaskotało + + + Czy to wszystko? + + + Czy to wszystko? + + + Pakuj trochę + + + Pakuj trochę + + + Manekin + + + O Boże! + + + Nieźle + + + Nieźle + + + Słabo + + + Słabo + + + Jeszcze raz + + + Jeszcze raz + + + O Boże! + + + Co za ból! + + + Co za ból! + + + Tak bardzo boli + + + Tak bardzo boli + + + PRZESTAŃ! + + + PRZESTAŃ! + + + Co Ci zrobiłem? + + + Co Ci zrobiłam? + + + DLACZEGO??? + + + DLACZEGO??? + + + Nie bij mnie + + + Nie bij mnie + + + Czemuż to? + + + Czemuż to? + + + Nie widzisz kolorów z powodu monochoomatyzmu. + + + Jesteś taki chudy, że wszyscy Tobą rzucają. + + + Jesteś taki chuda, że wszyscy Tobą rzucają. + + + Ciężko Ci przypomnieć sobie, gdzie jesteś. + + + Ciężko Ci przypomnieć sobie, gdzie jesteś. + + + Twoje pule MP i PZ są zamienione. Kto by pomyślał? + + + Twoje pule MP i PZ są zamienione. Kto by pomyślał? + + + %#&@! + + + %#&@! + + + Co za energia! Poruszasz się szybciej. + + + Co za energia! Poruszasz się szybciej. + + + Trzeba. Posprzątać. Dom. Niszczy rzeczy, by odbudować MP. + + + Trzeba. Posprzątać. Dom. Niszczy rzeczy, by odbudować MP. + + + Jesteś na sterydach. Twoje ataki jeszcze mocniej odrzucają wrogów. + + + Jesteś na sterydach. Twoje ataki jeszcze mocniej odrzucają wrogów. + + + Masz słabe kończyny. Nie możesz przewracać wrogów. + + + Masz słabe kończyny. Nie możesz przewracać wrogów. + + + Nie widzisz trójwymiarowo. + + + Nie widzisz trójwymiarowo. + + + Nawet najwięksi śmiałkowie mogą cierpieć na zespół jelita drażliwego. + + + Nawet najwięksi śmiałkowie mogą cierpieć na zespół jelita drażliwego. + + + Nie widzisz kolorów z powodu monochromatyzmu. + + + Lubisz panie. + + + Witaj w Rzygolandii. + + + Witaj w Rzygolandii. + + + Brak widzenia obwodowego. + + + Brak widzenia obwodowego. + + + Masz dwie lewe ręce, nie możesz prawidłowo rzucać zaklęć. + + + Masz dwie lewe ręce, nie możesz prawidłowo rzucać zaklęć. + + + Choroba tętnic obwodowych. Brak krążenia w stopach. + + + Choroba tętnic obwodowych. Brak krążenia w stopach. + + + Przerażają Cię kurczaki. + + + Przerażają Cię kurczaki. + + + Masz tendencję do PRZESADZANIA. + + + Masz tendencję do PRZESADZANIA. + + + Jesteś obłąkany. + + + Jesteś obłąkana. + + + Jesteś bardzo elastyczny. + + + Jesteś bardzo elastyczna. + + + Pamiętasz wszystko niezwykle dokładnie. + + + Pamiętasz wszystko niezwykle dokładnie. + + + Tęsknisz za starymi dobrymi czasami. + + + Tęsknisz za starymi dobrymi czasami. + + + Lubisz mężczyzn. + + + Lubisz mężczyzn. + + + Lubisz panie. + + + Wszystko, co jest daleko, rozmazuje się. + + + Wrodzona obojętność na ból. Ból? A co to? + + + Wrodzona obojętność na ból. Ból? A co to? + + + Masz spory talent. I parę problemów. + + + Masz spory talent. I parę problemów. + + + Brak łyżkowidelca. + + + Brak łyżkowidelca. + + + Psujesz mnóstwo rzeczy. + + + Psujesz mnóstwo rzeczy. + + + Bardzo dobrze przewodzisz elektryczność. + + + Bardzo dobrze przewodzisz elektryczność. + + + Jest tak ciemno. + + + Jest tak ciemno. + + + Wszystko, co jest daleko, rozmazuje się. + + + Wszystko, co jest blisko, rozmazuje się. + + + Wszystko, co jest blisko, rozmazuje się. + + + Mazs prbolemy z cyztaneim. + + + Mazs prbolemy z cyztaneim. + + + Jesteś stworzony do bycia koszykarzem. + + + Jesteś stworzona do bycia koszykarką. + + + Nigdy nie pojeździsz górskimi kolejkami. + + + Nigdy nie pojeździsz górskimi kolejkami. + + + Łysy i piękny. + + + Łysa i piękna. + + + Jesteś taki ciężki, że wrogowie nie mogą Cię przewrócić. + + + Jesteś taki ciężka, że wrogowie nie mogą Cię przewrócić. + + + Nie widzisz kolorów. + + + Jedno trafienie i leeeecisz. + + + Jedno trafienie i leeeecisz. + + + Gdzie jesteś? + + + Gdzie jesteś? + + + Pule MP + PZ zamienione. + + + Pule MP + PZ zamienione. + + + %#&@! + + + %#&@! + + + Poruszasz się szybciej. + + + Poruszasz się szybciej. + + + Niszcz rzeczy, by odbudować MP. + + + Niszcz rzeczy, by odbudować MP. + + + Potrafisz solidnie trafić wroga. + + + Potrafisz solidnie trafić wroga. + + + Nie możesz przewracać wrogów. + + + Nie możesz przewracać wrogów. + + + Nie widzisz trójwymiarowo. + + + Nie widzisz trójwymiarowo. + + + Ciągle puszczasz bąki. + + + Ciągle puszczasz bąki. + + + Nie widzisz kolorów. + + + Lubisz damy. + + + Wszystko jest do góry nogami. + + + Wszystko jest do góry nogami. + + + Brak wczesnych wskazówek. + + + Brak wczesnych wskazówek. + + + Rzucanie zaklęć to dla Ciebie łatwizna. + + + Rzucanie zaklęć to dla Ciebie łatwizna. + + + Brak krążenia w stopach. + + + Brak krążenia w stopach. + + + Przeraźliwie boisz się kurczaków. + + + Przeraźliwie boisz się kurczaków. + + + Wyolbrzymiasz odnoszone obrażenia. + + + Wyolbrzymiasz odnoszone obrażenia. + + + Widzisz rzeczy, których nie ma. + + + Widzisz rzeczy, których nie ma. + + + Robisz obroty podczas walki. + + + Robisz obroty podczas walki. + + + Pamiętaj o położeniu wroga. + + + Pamiętaj o położeniu wroga. + + + Wszystko jak za dawnych czasów. + + + Wszystko jak za dawnych czasów. + + + Lubisz mężczyzn. + + + Lubisz mężczyzn. + + + Lubisz damy. + + + Wszystko, co jest daleko, się rozmazuje. + + + Niewidoczny pasek zdrowia. + + + Niewidoczny pasek zdrowia. + + + Losowe zaklęcia. + + + Losowe zaklęcia. + + + Brak łyżkowidelca. + + + Brak łyżkowidelca. + + + Psujesz przedmioty i nie masz równowagi. + + + Psujesz przedmioty i nie masz równowagi. + + + Platformy pozostają otwarte. + + + Platformy pozostają otwarte. + + + Jest tak ciemno. + + + Jest tak ciemno. + + + Wszystko, co jest daleko, się rozmazuje. + + + Wszystko, co jest blisko, się rozmazuje. + + + Wszystko, co jest blisko, się rozmazuje. + + + Mazs prbolemy z cyztaneim. + + + Mazs prbolemy z cyztaneim. + + + Jesteś wielki. + + + Jesteś wielka. + + + Jesteś maleńki. + + + Jesteś maleńka. + + + Jesteś łysy. + + + Jesteś łysa. + + + Nie można Cię przewrócić. + + + Nie można Cię przewrócić. + + + Wzrok 2D + + + Ektomorfik + + + Ektomorfik + + + Alzheimer + + + Alzheimer + + + Dekstrokardia + + + Dekstrokardia + + + Koprolalia + + + Koprolalia + + + ADHD + + + ADHD + + + Nerwica natręctw + + + Nerwica natręctw + + + Hipergonadyzm + + + Hipergonadyzm + + + Słabość mięśni + + + Słabość mięśni + + + Stępiony wzrok + + + Stępiony wzrok + + + Prukanie + + + Prukanie + + + Wzrok 2D + + + Homo + + + Zawrót głowy + + + Zawrót głowy + + + Widzenie tunelowe + + + Widzenie tunelowe + + + Dwie lewe ręce + + + Dwie lewe ręce + + + Stalowe stopy + + + Stalowe stopy + + + Kurczakofobia + + + Kurczakofobia + + + Hipochondria + + + Hipochondria + + + Demencja + + + Demencja + + + Elastyczność + + + Elastyczność + + + Fotograficzna pamięć + + + Fotograficzna pamięć + + + Nostalgia + + + Nostalgia + + + Homo + + + Krótkowzroczność + + + Niewrażliwość + + + Niewrażliwość + + + Talenciak + + + Talenciara + + + Jedyny + + + Jedyna + + + Niezdarny + + + Niezdarna + + + EHS + + + EHS + + + Jaskra + + + Jaskra + + + Krótkowzroczność + + + Dalekowzroczność + + + Dalekowzroczność + + + Dysleksja + + + Dysleksja + + + Gigantyzm + + + Gigantyzm + + + Karłowatość + + + Karłowatość + + + Śmiałość + + + Śmiałość + + + Endomorfik + + + Endomorfik + + + Autorzy + + + Autorzy + + + Projekt + + + Projekt + + + Programowanie + + + Programowanie + + + Produkcja + + + Produkcja + + + Grafika + + + Grafika + + + Udźwiękowienie i muzyka + + + Udźwiękowienie i muzyka + + + Muzyka + + + Muzyka + + + + + + + + + Zaatakuj z góry + + + Zaatakuj z góry + + + Naciśnij [Input:11], aby skoczyć + + + Naciśnij [Input:11], aby skoczyć + + + Przytrzymaj [Input:11], aby skoczyć wyżej + + + Przytrzymaj [Input:11], aby skoczyć wyżej + + + Naciśnij [Input:12], aby zaatakować + + + Naciśnij [Input:12], aby zaatakować + + + Przytrzymaj [Input:19] i naciśnij [Input:11],\naby zeskakiwać z półek + + + Przytrzymaj [Input:19] i naciśnij [Input:11],\naby zeskakiwać z półek + + + Przytrzymaj (w powietrzu) [Input:19] i naciśnij [Input:12],\n aby zaatakować z góry + + + Przytrzymaj (w powietrzu) [Input:19] i naciśnij [Input:12],\n aby zaatakować z góry + + + Naciśnij [Input:10], aby skoczyć + + + Naciśnij [Input:10], aby skoczyć + + + Przytrzymaj [Input:10], aby skoczyć wyżej + + + Przytrzymaj [Input:10], aby skoczyć wyżej + + + Naciśnij [Input:12], aby zaatakować + + + Naciśnij [Input:12], aby zaatakować + + + Przytrzymaj [Input:18] i naciśnij [Input:10], \naby zeskakiwać z półek + + + Przytrzymaj [Input:18] i naciśnij [Input:10], \naby zeskakiwać z półek + + + Przytrzymaj (w powietrzu) [Input:18] i naciśnij [Input:12],\n aby zaatakować z góry + + + Przytrzymaj (w powietrzu) [Input:18] i naciśnij [Input:12],\n aby zaatakować z góry + + + Dodatkowe programowanie + + + Adaptacja: + + + Chcesz przekazać {0} szt. złota, aby na stałe wzmocnić swojego bohatera w starciu z tym bossem?\nLiczba wzmocnień: {1} + + + Skrzynia darowizny jest wypełniona po brzegi. Bohatera nie można już bardziej wzmocnić. Dzięki za wsparcie. + + + Nie masz pieniędzy, aby dokonać darowizny. Wróć, kiedy zdobędziesz więcej złota. + + + Twój bohater stał się silniejszy! + + + Skrzynia darowizny + + + {0} {1} + + + Odblokuj Zdrajcę + + + Skoczek + + + Klątwa + + + Wdzięk + + + Zapłata dla Architekta + + + Bonus NG+ + + + Sprint + + + Wampir + + + Niebo + + + Syfon + + + Równowaga + + + Odwet + + + Zdobycz + + + Pośpiech + + + Przygotowanie i produkcja wersji japońskiej + + + Kontrola jakości + + + Masz mimowolne skurcze mięśni. + + + Nie rozpoznajesz twarzy. + + + Klonus + + + Prozopagnozja + + + Klątwa + + + Wdzięk + + + Zapłata dla Architekta + + + Bonus NG+ + + + Skoczek + + + Sprint + + + Wampir + + + Niebo + + + Syfon + + + Równowaga + + + Odwet + + + Zdobycz + + + Pośpiech + + + Masz mimowolne skurcze mięśni. + + + Nie rozpoznajesz twarzy. + + + Klonus + + + Prozopagnozja + + + Zdobądź 60% całego złota z zamku. + + + Zdobądź 60% całego złota z zamku. + _F + + + Odblokuj Zdrajcę + + + Full Metal Furies\nCzas tworzenia gry: 4 lata.\nData premiery: 17 stycznia 2018 r. + + + Full Metal Furies pochodzi z przyszłości! Jest to kontynuacja gry Rogue Legacy i dziesiąta gra, jaką kiedykolwiek stworzyliśmy. + + + Po Rogue Legacy obiecaliśmy sobie, że nigdy więcej nie stworzymy żadnej gry bez dokładnego jej zaplanowania. Skłamaliśmy. Do diabła z naszymi dawnymi pomysłami! + + + Gra stała się jednym z naszych najambitniejszych projektów i stanowiła melanż bijatyki/gry wielooobowej/wielopoziomowej łamigłowki/pomysłów jak na dyskotece z okazji osiemnastki. + + + Praca trwała 4 lata. To najdłuższy czas, jaki kiedykolwiek poświęciliśmy na przygotowanie gry. Niestety jest to też jedna z tych gier, które przyniosły nam najmniejszy dochód. + + + Ale wciąż jesteśmy ogromnie dumni z tego, co stworzyliśmy, a jeszcze bardziej dumni z PRZYJACIÓŁ, KTÓRYCH POZNALIŚMY PO DRODZE. AWWWWWWW!!! + + + Copyright (C) 2013-2018, Cellar Door Games Inc. + + + {0} jest znakiem towarowym firmy Cellar Door Games Inc. Wszystkie prawa zastrzeżone. + + \ No newline at end of file diff --git a/RogueCastle/Resources/LocStrings.pt.resx b/RogueCastle/Resources/LocStrings.pt.resx new file mode 100644 index 0000000..b5f2c09 --- /dev/null +++ b/RogueCastle/Resources/LocStrings.pt.resx @@ -0,0 +1,8353 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Sair para tela inicial + + + Sair para tela inicial + + + Sair para tela inicial (pular tutorial) + + + Sair para tela inicial (pular tutorial) + + + [Input:25] para alterar perfil ({0}) + + + [Input:25] para alterar perfil ({0}) + + + Vida + + + Setas para navegar + + + Setas para navegar + + + [Button:LeftStick] para navegar + + + [Button:LeftStick] para navegar + + + Selecione uma categoria + + + Selecione uma categoria + + + Precisa de projeto + + + Precisa de projeto + + + Compre informações aqui + + + Compre informações aqui + + + Nenhum + + + Nenhum + + + {0} para liberar + + + {0} para liberar + + + Vida + + + Mana + + + Mana + + + Dano + + + Dano + + + Magia + + + Magia + + + Armad. + + + Armad. + + + Peso + + + Peso + + + Propriedades Adicionais: + + + Propriedades Adicionais: + + + [Input:0] para selecionar/equipar + + + [Input:0] para selecionar/equipar + + + [Input:2] para cancelar/fechar menu + + + [Input:2] para cancelar/fechar menu + + + Alvos destruídos + + + Alvos destruídos + + + Alvos restantes + + + Alvos restantes + + + Recompensa + + + Recompensa + + + ouro + + + ouro + + + ver mapa a qualquer momento + + + ver mapa a qualquer momento + + + Mudar controles + + + Avançar p/ direita + + + Avançar p/ direita + + + Lançar feitiço + + + Lançar feitiço + + + Redefinir controles + + + Redefinir controles + + + Pressione qualquer tecla + + + Pressione qualquer tecla + + + Mudar controles + + + Cima + + + Cima + + + Baixo + + + Baixo + + + Esquerda + + + Esquerda + + + Direita + + + Direita + + + Atacar + + + Atacar + + + Saltar + + + Saltar + + + Especial + + + Especial + + + Avançar p/ esquerda + + + Avançar p/ esquerda + + + Herói padrão. Muito bom em tudo. + + + Um tanque ambulante. Este herói aguenta levar uma surra.\nESPECIAL: Grito Bárbaro. + + + Um tanque ambulante. Esta heroína aguenta levar uma surra.\nESPECIAL: Grito Bárbaro. + + + Um herói rápido. Causa bastante dano, mas você não pode causar crítico. + + + Uma heroína rápida. Causa bastante dano, mas você não pode causar crítico. + + + Um herói rápido. Causa bastante dano, mas você não pode causar crítico.\nESPECIAL: Técnica de Substituição. + + + Uma heroína rápida. Causa bastante dano, mas você não pode causar crítico.\nESPECIAL: Técnica de Substituição. + + + Um herói para os especialistas. Acerte os inimigos para restaurar mana. + + + Uma heroína para os especialistas. Acerte os inimigos para restaurar mana. + + + Um herói para os especialistas. Acerte os inimigos para restaurar mana.\nESPECIAL: Magia Fortalecida. + + + Uma heroína para os especialistas. Acerte os inimigos para restaurar mana.\nESPECIAL: Magia Fortalecida. + + + Alimente-se dos mortos. Ganhe vida permanente para cada morte até um limite. Extremamente inteligente. + + + Alimente-se dos mortos. Ganhe vida permanente para cada morte até um limite. Extremamente inteligente. + + + Alimente-se dos mortos. Ganhe vida permanente para cada morte até um limite. Extremamente inteligente.\nESPECIAL: Conversão de HP. + + + Alimente-se dos mortos. Ganhe vida permanente para cada morte até um limite. Extremamente inteligente.\nESPECIAL: Conversão de HP. + + + Você é um homem-dragão + + + Você é uma mulher-dragão + + + ????? + + + ????? + + + Heroína padrão. Muito boa em tudo. + + + Herói padrão. Muito bom em tudo.\nESPECIAL: Escudo dos Guardiões + + + Heroína padrão. Muito boa em tudo.\nESPECIAL: Escudo dos Guardiões + + + Um herói arriscado. Baixas estatísticas, mas pode lançar ataques críticos devastadores. + + + Uma heroína arriscada. Baixas estatísticas, mas pode lançar ataques críticos devastadores. + + + Um herói arriscado. Baixas estatísticas, mas pode lançar ataques críticos devastadores.\nESPECIAL: Forma Nebulosa + + + Uma heroína arriscada. Baixas estatísticas, mas pode lançar ataques críticos devastadores.\nESPECIAL: Forma Nebulosa + + + Um herói para os acumuladores. Muito fraco, mas tem um enorme bônus para o ouro. + + + Uma heroína para os acumuladores. Muito fraca, mas tem um enorme bônus para o ouro. + + + Um herói para os acumuladores. Muito fraco, mas tem um enorme bônus para o ouro.\nESPECIAL: Lanterna Simples. + + + Uma heroína para os acumuladores. Muito fraca, mas tem um enorme bônus para o ouro.\nESPECIAL: Lanterna Simples. + + + Um feiticeiro poderoso. Cada morte te fornece mana. + + + Uma feiticeira poderosa. Cada morte te fornece mana. + + + Um feiticeiro poderoso. Cada morte te fornece mana.\nESPECIAL: Ciclo de Magia. + + + Uma feiticeira poderosa. Cada morte te fornece mana.\nESPECIAL: Ciclo de Magia. + + + Um tanque ambulante. Este herói aguenta levar uma surra. + + + Um tanque ambulante. Esta heroína aguenta levar uma surra. + + + Rainha Bárbara + + + Rainha Bárbara + + + Rei Bárbaro + + + Rei Bárbaro + + + Shinobi + + + Shinobi + + + Hokage + + + Hokage + + + Ladra de Feitiço + + + Ladra de Feitiço + + + Ladrão de Feitiço + + + Ladrão de Feitiço + + + Maga de Espada + + + Maga de Espada + + + Mago de Espada + + + Mago de Espada + + + Lich + + + Lich + + + Rainha Lich + + + Rainha Lich + + + Rei Lich + + + Rei Lich + + + Dragão-fêmea + + + Dragão-fêmea + + + Dragão + + + Dragão + + + Traidora + + + Traidora + + + Traidor + + + Traidor + + + Cavaleira + + + Cavaleira + + + Cavaleiro + + + Cavaleiro + + + Paladina + + + Paladina + + + Paladino + + + Paladino + + + Valete + + + Valete + + + Valete + + + Valete + + + Assassina + + + Assassina + + + Assassino + + + Assassino + + + Mineradora + + + Mineradora + + + Minerador + + + Minerador + + + Espeleologista + + + Espeleologista + + + Espeleologista + + + Espeleologista + + + Maga + + + Maga + + + Mago + + + Mago + + + Arquimaga + + + Arquimaga + + + Arquimago + + + Arquimago + + + Bárbara + + + Bárbara + + + Bárbaro + + + Bárbaro + + + Obrigado por jogar! + + + Arte + + + Arte + + + Design de áudio e música + + + Design de áudio e música + + + Música + + + Música + + + Marketing e enredo + + + Marketing e enredo + + + Design de áudio adicional + + + Design de áudio adicional + + + Arte de fundo adicional + + + Arte de fundo adicional + + + Suporte comercial + + + Suporte comercial + + + Agradecimentos extremamente especiais: Turbo Edition + + + Agradecimentos extremamente especiais: Turbo Edition + + + Agradecimentos especiais + + + Agradecimentos especiais + + + Agradecimentos adicionais + + + Agradecimentos adicionais + + + Obrigado por jogar! + + + Total de herdeiros + + + Adaptação para Mac/Linux por + + + Adaptação para Mac/Linux por + + + Equipe de CQ de Mac/Linux + + + Equipe de CQ de Mac/Linux + + + Agradecemos a todos os nossos fãs pelo apoio deles! + + + Agradecemos a todos os nossos fãs pelo apoio deles! + + + Localização principal por + + + Localização principal por + + + Localização adicional e chinesa por + + + Localização adicional e chinesa por + + + Total de herdeiros + + + Tempo de jogo + + + Tempo de jogo + + + Pressione [Input:0] para sair + + + Pressione [Input:0] para sair + + + Desenvolvido por + + + Desenvolvido por + + + Design e enredo + + + Design e enredo + + + Programação + + + Programação + + + Produção + + + Produção + + + Controle - zona morta + + + Controle - zona morta + + + Apagar jogo salvo + + + Apagar jogo salvo + + + Diário do Príncipe + + + Embora eu seja o filho mais velho, eu não sou o favorito do meu pai. Eu sempre soube que ele planejava me deixar sem nada. + + + ... E se eu os confundi com um monstro? + + + ... E se eu os confundi com um monstro? + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #17 + + + Registro #17 + + + Eu devo estar ficando louco. Me deparei com um carnaval dentro deste castelo. Com um palhaço triste e tudo mais. + + + Eu devo estar ficando louco. Me deparei com um carnaval dentro deste castelo. Com um palhaço triste e tudo mais. + + + Ele é meio que um idiota. Mas acho que não dá pra ser exigente na escolha de amigos num lugar como esse. + + + Ele é meio que um idiota. Mas acho que não dá pra ser exigente na escolha de amigos num lugar como esse. + + + Estou ficando com fome novamente. Ainda bem que peguei mais pés de galinha. Achei esses num lustre. + + + Estou ficando com fome novamente. Ainda bem que peguei mais pés de galinha. Achei esses num lustre. + + + Este castelo... Às vezes me pergunto se tudo não passa de uma grande piada. + + + Este castelo... Às vezes me pergunto se tudo não passa de uma grande piada. + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #18 + + + Registro #18 + + + Eu venci a fera da torre e mais uma vez eu pude sentir a sala do trono perder um pouco mais do seu poder. + + + Eu venci a fera da torre e mais uma vez eu pude sentir a sala do trono perder um pouco mais do seu poder. + + + Embora eu seja o filho mais velho, eu não sou o favorito do meu pai. Eu sempre soube que ele planejava me deixar sem nada. + + + Mas se eu encontrar a cura, tudo irá mudar. + + + A euforia que sinto dessa vitória é inebriante! Nunca me senti tão confiante, tão poderoso, tão... em casa. Apenas um pouco mais e serei capaz de ganhar a minha recompensa! + + + A euforia que sinto dessa vitória é inebriante! Nunca me senti tão confiante, tão poderoso, tão... em casa. Apenas um pouco mais e serei capaz de ganhar a minha recompensa! + + + Estou tão perto! Irei deixar meu pai orgulhoso! + + + Estou tão perto! Irei deixar meu pai orgulhoso! + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #19 + + + Registro #19 + + + Estou plantado do lado de fora do portão do calabouço por mais tempo que gostaria de admitir. + + + Estou plantado do lado de fora do portão do calabouço por mais tempo que gostaria de admitir. + + + Minha coragem finalmente foi enfraquecida, pois dei uma olhada nos monstros abaixo e eles fazem minhas lutas anteriores serem ridículas se comparadas. + + + Minha coragem finalmente foi enfraquecida, pois dei uma olhada nos monstros abaixo e eles fazem minhas lutas anteriores serem ridículas se comparadas. + + + Não devo ter medo. Preciso me concentrar. Há tão pouca luz aqui embaixo, temo que eu possa me perder. + + + Não devo ter medo. Preciso me concentrar. Há tão pouca luz aqui embaixo, temo que eu possa me perder. + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #20 + + + Registro #20 + + + Eu achava que sabia o que a escuridão era, mas aqui no calabouço, a escuridão tem uma voz. + + + Eu achava que sabia o que a escuridão era, mas aqui no calabouço, a escuridão tem uma voz. + + + Mas se eu encontrar a cura, tudo irá mudar. + + + O vencedor irá ganhar nada menos do que o trono após sua morte! + + + Ela me chama através das grades e pelos cantos. Me provoca. + + + Ela me chama através das grades e pelos cantos. Me provoca. + + + A escuridão é tão densa que é quase palpável, e as feras fizeram daqui a sua moradia. Elas se movem rapidamente pelos corredores e são mais aterrorizantes do que qualquer coisa que lutei antes. + + + A escuridão é tão densa que é quase palpável, e as feras fizeram daqui a sua moradia. Elas se movem rapidamente pelos corredores e são mais aterrorizantes do que qualquer coisa que lutei antes. + + + Eu devo ser prudente e escolher minhas batalhas com cuidado. Ser confrontado agora pode custar a minha vida. + + + Eu devo ser prudente e escolher minhas batalhas com cuidado. Ser confrontado agora pode custar a minha vida. + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #21 + + + Registro #21 + + + Eu consegui! Eu derrotei o mestre da masmorra! Tudo o que falta é entrar na sala do trono. + + + Eu consegui! Eu derrotei o mestre da masmorra! Tudo o que falta é entrar na sala do trono. + + + Depois disso, o rei irá me honrar pelo meu valor e irá me reconhecer como o legítimo sucessor do trono! + + + Depois disso, o rei irá me honrar pelo meu valor e irá me reconhecer como o legítimo sucessor do trono! + + + E não meus irmãos sem noção! + + + E não meus irmãos sem noção! + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #22 + + + Registro #22 + + + O vencedor irá ganhar nada menos do que o trono após sua morte! + + + Após a minha ascensão, minha esposa e meus filhos se mudarão de volta para os aposentos reais. Voltaremos para a cidade real, onde mais uma vez seremos tratados com o respeito que merecemos! + + + Inicio meus preparativos finais. Tudo o que resta entre mim e o senhor deste castelo são as portas douradas. + + + Inicio meus preparativos finais. Tudo o que resta entre mim e o senhor deste castelo são as portas douradas. + + + Há um nervosismo no meu corpo que eu não posso reprimir. Isto é medo ou excitação? Tudo o que sei é que minha viagem está finalmente chegando ao fim. + + + Há um nervosismo no meu corpo que eu não posso reprimir. Isto é medo ou excitação? Tudo o que sei é que minha viagem está finalmente chegando ao fim. + + + Quase esqueci o porquê de ter entrado neste castelo, mas eu me lembro agora. + + + Quase esqueci o porquê de ter entrado neste castelo, mas eu me lembro agora. + + + Eu superei meus irmãos, irei salvar o rei e sairei deste castelo um homem melhor do que quando entrei. Minha família terá a honra que tão justamente merece. + + + Eu superei meus irmãos, irei salvar o rei e sairei deste castelo um homem melhor do que quando entrei. Minha família terá a honra que tão justamente merece. + + + Agora, eu entrarei na sala do trono. + + + Agora, eu entrarei na sala do trono. + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #23 + + + Registro #23 + + + Eu nunca soube que tesouro estava no castelo. Eu só sabia que ele iria curar o rei. + + + Eu nunca soube que tesouro estava no castelo. Eu só sabia que ele iria curar o rei. + + + Quem poderia imaginar que seria a fonte da juventude? + + + Quem poderia imaginar que seria a fonte da juventude? + + + Eu estava esperando que um monstro me cumprimentasse no trono; um inimigo de força inimaginável. Imaginei que seria necessário toda a minha força para matá-lo. + + + Eu estava esperando que um monstro me cumprimentasse no trono; um inimigo de força inimaginável. Imaginei que seria necessário toda a minha força para matá-lo. + + + Após a minha ascensão, minha esposa e meus filhos se mudarão de volta para os aposentos reais. Voltaremos para a cidade real, onde mais uma vez seremos tratados com o respeito que merecemos! + + + Não iremos mais aturar as fofocas e calúnias mesquinhas dos meus primos. Os outros duques se curvarão quando passarmos! Mas estou pensando muito à frente. + + + Mas quando entrei no castelo e vi o meu pai, o rei, sentado no trono com uma taça na mão, eu sabia que tudo estava perdido. + + + Mas quando entrei no castelo e vi o meu pai, o rei, sentado no trono com uma taça na mão, eu sabia que tudo estava perdido. + + + Ele nunca iria morrer... + + + Ele nunca iria morrer... + + + ... e eu nunca seria herdeiro. + + + ... e eu nunca seria herdeiro. + + + Não há palavras para expressar o que sinto. + + + Não há palavras para expressar o que sinto. + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #24 + + + Registro #24 + + + .............................. + + + .............................. + + + .... + + + .... + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #25 + + + Registro #25 + + + Não iremos mais aturar as fofocas e calúnias mesquinhas dos meus primos. Os outros duques se curvarão quando passarmos! Mas estou pensando muito à frente. + + + Devo manter minhas prioridades claras: Conquistar o castelo. Encontrar a cura. Coletar minha recompensa. + + + Hoje marca o resto da eternidade. + + + Hoje marca o resto da eternidade. + + + Eu nunca soube que tesouro estava no castelo. Somente que ele iria curar o rei de sua doença. + + + Eu nunca soube que tesouro estava no castelo. Somente que ele iria curar o rei de sua doença. + + + ... Quem poderia imaginar que seria a fonte da juventude? Um mito, que concede vida eterna a alguém. + + + ... Quem poderia imaginar que seria a fonte da juventude? Um mito, que concede vida eterna a alguém. + + + Ao olhar sobre o corpo do rei, percebo que é inevitável: os filhos sempre responderão pelos pecados dos pais. + + + Ao olhar sobre o corpo do rei, percebo que é inevitável: os filhos sempre responderão pelos pecados dos pais. + + + Entrei neste castelo um mestre de espadas, um salvador... + + + Entrei neste castelo um mestre de espadas, um salvador... + + + Mas tudo o que tenho é o legado de um invasor. + + + Mas tudo o que tenho é o legado de um invasor. + + + Eu posso sentir a sua raiva, mas saiba que não fui eu quem enviou sua família à ruína. + + + Eu posso sentir a sua raiva, mas saiba que não fui eu quem enviou sua família à ruína. + + + No momento em que o rei pôs os pés dentro deste castelo, os cofres reais foram esvaziados pelo Caronte. Minha família, todas as famílias, perderam toda a esperança de uma vida melhor. + + + No momento em que o rei pôs os pés dentro deste castelo, os cofres reais foram esvaziados pelo Caronte. Minha família, todas as famílias, perderam toda a esperança de uma vida melhor. + + + E, em minha mente, eu previ apenas o desespero e a pobreza devastando o país. Não havia nada para o qual voltar. + + + E, em minha mente, eu previ apenas o desespero e a pobreza devastando o país. Não havia nada para o qual voltar. + + + Para os meus filhos e filhos dos meus filhos, aqui eu sento, impassível, imortal e espero por ti. + + + Para os meus filhos e filhos dos meus filhos, aqui eu sento, impassível, imortal e espero por ti. + + + Devo manter minhas prioridades claras: Conquistar o castelo. Encontrar a cura. Coletar minha recompensa. + + + Diário do Príncipe + + + Johannes + + + Johannes + + + O que é isso? Você está... me zombando?! + + + O que é isso? Você está... me zombando?! + + + Depois de incontáveis gerações de seus antepassados sacrificarem suas vidas para estarem onde você está agora, os passos finais para conseguir sua justiça. E você chega e zomba de mim? + + + Depois de incontáveis gerações de seus antepassados sacrificarem suas vidas para estarem onde você está agora, os passos finais para conseguir sua justiça. E você chega e zomba de mim? + + + Muito bem, eu pouparei sua ignorância. Vamos começar! + + + Muito bem, eu pouparei sua ignorância. Vamos começar! + + + Johannes + + + Johannes + + + Por que você quer lutar comigo? Quantos filhos e filhas foram perdidos em suas tentativas patéticas de vingança? + + + Por que você quer lutar comigo? Quantos filhos e filhas foram perdidos em suas tentativas patéticas de vingança? + + + Foi o rei que trouxe a ruína para o seu país e não eu! + + + Foi o rei que trouxe a ruína para o seu país e não eu! + + + Ele mentiu para nós. Ele disse que estava ferido, mas era só o tempo que o ameaçava! + + + Ele mentiu para nós. Ele disse que estava ferido, mas era só o tempo que o ameaçava! + + + Ele colocou seus filhos um contra o outro, sacrificou tudo para satisfazer seus próprios desejos egoístas, e no final, nos deixou sem um tostão e sozinhos. + + + Ele colocou seus filhos um contra o outro, sacrificou tudo para satisfazer seus próprios desejos egoístas, e no final, nos deixou sem um tostão e sozinhos. + + + Então, peguei a única opção que me restava. Rejeitei o rei e o país... + + + Então, peguei a única opção que me restava. Rejeitei o rei e o país... + + + Diário do Príncipe + + + Registro #3 + + + E escolhi uma nova família em vez disso! + + + E escolhi uma nova família em vez disso! + + + Johannes + + + Johannes + + + Você acha que me matou? + + + Você acha que me matou? + + + Faz mais de mil anos que vivo, e viverei por dez mil mais! + + + Faz mais de mil anos que vivo, e viverei por dez mil mais! + + + Alexander... Khidr... Ponce de Leon... + + + Alexander... Khidr... Ponce de Leon... + + + Eu não fui o primeiro herói a encontrar a fonte... + + + Eu não fui o primeiro herói a encontrar a fonte... + + + Mas eu serei o último! + + + Mas eu serei o último! + + + Fonte da Juventude + + + Fonte da Juventude + + + ... + + + ... + + + Você me derrotou... Mas a que preço? + + + Você me derrotou... Mas a que preço? + + + Registro #3 + + + Eu paguei o que era devido e entrei no castelo adequadamente. Aquele Caronte pegou tudo o que eu tinha como pagamento. + + + Eu posso ter matado o rei, mas só depois dele ter traído seu povo. + + + Eu posso ter matado o rei, mas só depois dele ter traído seu povo. + + + Pergunte a si mesmo que justiça foi cumprida? + + + Pergunte a si mesmo que justiça foi cumprida? + + + No fim, todos nós somos culpados do mesmo pecado. Olhe para os seus antepassados, tal é o custo de uma lealdade inquestionável. + + + No fim, todos nós somos culpados do mesmo pecado. Olhe para os seus antepassados, tal é o custo de uma lealdade inquestionável. + + + ... + + + ... + + + ... + + + ... + + + O sol... + + + O sol... + + + Eu tinha me esquecido de como era... + + + Eu tinha me esquecido de como era... + + + Eu paguei o que era devido e entrei no castelo adequadamente. Aquele Caronte pegou tudo o que eu tinha como pagamento. + + + Ele até mesmo afanou meus cofres particulares! Deixei minha esposa e filhos sem nada. + + + Ele até mesmo afanou meus cofres particulares! Deixei minha esposa e filhos sem nada. + + + Diário do Príncipe + + + Registro #1 + + + Ele diz que é o preço para todos que se arriscam nas profundezas do castelo. Diz que é justo. + + + Ele diz que é o preço para todos que se arriscam nas profundezas do castelo. Diz que é justo. + + + É justo por que de todos os que entraram, nenhum retornou. Mas eu irei mudar isso. + + + É justo por que de todos os que entraram, nenhum retornou. Mas eu irei mudar isso. + + + Eu serei vitorioso! Não existe ninguém melhor na espada do que eu, nem mesmo meus irmãos. + + + Eu serei vitorioso! Não existe ninguém melhor na espada do que eu, nem mesmo meus irmãos. + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #4 + + + Registro #4 + + + Este castelo é muito estranho. Eu não consigo me localizar, e não há sol nem estrelas para me guiar. + + + Este castelo é muito estranho. Eu não consigo me localizar, e não há sol nem estrelas para me guiar. + + + Encontro-me seguindo a direção errada constantemente e eu preciso mapear meticulosamente o meu progresso para que eu não ande em círculos. + + + Encontro-me seguindo a direção errada constantemente e eu preciso mapear meticulosamente o meu progresso para que eu não ande em círculos. + + + Os mapas que roubei dos cadáveres de outros aventureiros são impressionantemente imprecisos. É quase como se eles estivessem descrevendo um castelo completamente diferente! + + + Os mapas que roubei dos cadáveres de outros aventureiros são impressionantemente imprecisos. É quase como se eles estivessem descrevendo um castelo completamente diferente! + + + Talvez este lugar mexa com nossa mente... + + + Talvez este lugar mexa com nossa mente... + + + Ou as pedras realmente estão se deslocando sob meus pés? + + + Ou as pedras realmente estão se deslocando sob meus pés? + + + Registro #1 + + + Traição! Um assassino feriu meu pai, o rei! + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #5 + + + Registro #5 + + + Eu não posso sair pelo portão da frente, mas isso pouco importa. Estou comprometido à minha causa e não irei desistir! + + + Eu não posso sair pelo portão da frente, mas isso pouco importa. Estou comprometido à minha causa e não irei desistir! + + + Até agora nenhum dos mapas que encontrei coincide com o meu. + + + Até agora nenhum dos mapas que encontrei coincide com o meu. + + + No entanto, ao compará-los como um todo, acredito que encontrei um ligeiro padrão. Parece que a floresta está sempre à direita, a torre acima... + + + No entanto, ao compará-los como um todo, acredito que encontrei um ligeiro padrão. Parece que a floresta está sempre à direita, a torre acima... + + + E abaixo? Bem, espero que eu não tenha de descobrir. + + + E abaixo? Bem, espero que eu não tenha de descobrir. + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #6 + + + Registro #6 + + + Eu nunca gostei do escuro. Prefiro encontrar meus inimigos em um campo aberto, à vista de todos. + + + Eu nunca gostei do escuro. Prefiro encontrar meus inimigos em um campo aberto, à vista de todos. + + + Mas agora eu me encontro enfrentando essas forças sombrias com uma mão estendida e a outra no punho da espada. Eu nunca sei quais horrores estarão me aguardando depois de cada esquina. + + + Mas agora eu me encontro enfrentando essas forças sombrias com uma mão estendida e a outra no punho da espada. Eu nunca sei quais horrores estarão me aguardando depois de cada esquina. + + + Traição! Um assassino feriu meu pai, o rei! + + + Para trazer a ordem de volta ao reino, ele enviou meus irmãos e eu em uma missão para salvá-lo. Juntos, vamos nos aventurar na floresta amaldiçoada e adentraremos no Castelo Hamson. + + + Não existe ninguém, em todas as terras, melhor na espada do que eu, mas ainda estou tendo problemas para manter esses demônios longe. + + + Não existe ninguém, em todas as terras, melhor na espada do que eu, mas ainda estou tendo problemas para manter esses demônios longe. + + + Meus irmãos deveriam ficar agradecidos por eu ter saído na frente deles. Há males que vêm para o bem. Eles não teriam a coragem para sobreviver nestes corredores. + + + Meus irmãos deveriam ficar agradecidos por eu ter saído na frente deles. Há males que vêm para o bem. Eles não teriam a coragem para sobreviver nestes corredores. + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #7 + + + Registro #7 + + + Ainda é noite. Por cada janela é possível ver a mesma lua melancólica e tenho certeza que deve fazer pelo menos um dia inteiro que estou aqui. + + + Ainda é noite. Por cada janela é possível ver a mesma lua melancólica e tenho certeza que deve fazer pelo menos um dia inteiro que estou aqui. + + + Deve ser a adrenalina. Eu nunca me senti tão poderoso e também simultaneamente desafiado. É emocionante adentrar esses quartos e trucidar inimigo após inimigo. + + + Deve ser a adrenalina. Eu nunca me senti tão poderoso e também simultaneamente desafiado. É emocionante adentrar esses quartos e trucidar inimigo após inimigo. + + + Em alguns aspectos, os inimigos neste castelo parecem sob medida para mim. Me treinando, me guiando, me observando. + + + Em alguns aspectos, os inimigos neste castelo parecem sob medida para mim. Me treinando, me guiando, me observando. + + + Isso pode parecer loucura, mas se este castelo sente aqueles dentro dele, temo que possa ter intenções maliciosas também. Se eu estiver correto, a posição dos corredores pode ser um truque, me encurralando ainda mais a uma armadilha. + + + Isso pode parecer loucura, mas se este castelo sente aqueles dentro dele, temo que possa ter intenções maliciosas também. Se eu estiver correto, a posição dos corredores pode ser um truque, me encurralando ainda mais a uma armadilha. + + + Devo ficar alerta. + + + Devo ficar alerta. + + + Diário do Príncipe + + + Diário do Príncipe + + + Para trazer a ordem de volta ao reino, ele enviou meus irmãos e eu em uma missão para salvá-lo. Juntos, vamos nos aventurar na floresta amaldiçoada e adentraremos no Castelo Hamson. + + + Este castelo amaldiçoado se estende na borda da floresta desde os tempos imemoriais, mas rumores dizem que dentro dela existe um item que irá curar qualquer doença. + + + Registro #8 + + + Registro #8 + + + Pelo número de aventureiros mortos que encontrei nesses corredores, cheguei às seguintes conclusões: + + + Pelo número de aventureiros mortos que encontrei nesses corredores, cheguei às seguintes conclusões: + + + 1: Muitos não trouxeram mantimentos suficientes com eles. Presumo que muitos morreram de fome. Eu mesmo estou ficando sem e terei de encontrar mais suprimentos. + + + 1: Muitos não trouxeram mantimentos suficientes com eles. Presumo que muitos morreram de fome. Eu mesmo estou ficando sem e terei de encontrar mais suprimentos. + + + 2: Muitos estão com peças de roupa faltando, o que explica os zumbis vestindo calças. + + + 2: Muitos estão com peças de roupa faltando, o que explica os zumbis vestindo calças. + + + 3: Ninguém chegou tão longe quanto eu, já que não encontrei nenhum outro cadáver faz mais de uma hora. + + + 3: Ninguém chegou tão longe quanto eu, já que não encontrei nenhum outro cadáver faz mais de uma hora. + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #9 + + + Registro #9 + + + A porta para a sala do trono está me deixando louco! Além dela, está a salvação do rei e a minha recompensa, mas ela jaz em silêncio no meio do saguão do castelo, me provocando. + + + A porta para a sala do trono está me deixando louco! Além dela, está a salvação do rei e a minha recompensa, mas ela jaz em silêncio no meio do saguão do castelo, me provocando. + + + Eu tentei empurrá-la, chutá-la, gritar "Abre-te Sésamo", mas nada funciona. + + + Eu tentei empurrá-la, chutá-la, gritar "Abre-te Sésamo", mas nada funciona. + + + Há ícones estampados nas portas, e um deles parece uma fera que evitei nas profundezas do castelo. Talvez haja algum tipo de correlação? + + + Há ícones estampados nas portas, e um deles parece uma fera que evitei nas profundezas do castelo. Talvez haja algum tipo de correlação? + + + Este castelo amaldiçoado se estende na borda da floresta desde os tempos imemoriais, mas rumores dizem que dentro dela existe um item que irá curar qualquer doença. + + + Hoje à noite eu sairei na frente dos meus irmãos e irmãs, e avançarei em minha busca enquanto eles dormem. + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #10 + + + Registro #10 + + + Os emblemas na porta do castelo são uma pista! Matei a fera gigante que correspondia a um dos ícones e senti algo se deslocar por trás das portas da sala do trono. + + + Os emblemas na porta do castelo são uma pista! Matei a fera gigante que correspondia a um dos ícones e senti algo se deslocar por trás das portas da sala do trono. + + + Como se fosse um sonho, eu podia ver um emblema na porta brilhando no olho da minha mente. + + + Como se fosse um sonho, eu podia ver um emblema na porta brilhando no olho da minha mente. + + + Uma verdadeira experiência extracorpórea. + + + Uma verdadeira experiência extracorpórea. + + + Pelo menos sei que estou no caminho certo. Mas preciso apressar o passo, pois o rei pode sucumbir aos seus ferimentos a qualquer momento... + + + Pelo menos sei que estou no caminho certo. Mas preciso apressar o passo, pois o rei pode sucumbir aos seus ferimentos a qualquer momento... + + + Mas primeiro, tenho que descansar. Eu entrarei na floresta amanhã. + + + Mas primeiro, tenho que descansar. Eu entrarei na floresta amanhã. + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #11 + + + Registro #11 + + + Esta floresta é diferente de tudo que já vi antes. É ao mesmo tempo serena e aterrorizante. Eu caminho sobre uma grama exuberante, mas ao meu lado há um abismo tão largo e profundo que ameaça me engolir completamente. + + + Esta floresta é diferente de tudo que já vi antes. É ao mesmo tempo serena e aterrorizante. Eu caminho sobre uma grama exuberante, mas ao meu lado há um abismo tão largo e profundo que ameaça me engolir completamente. + + + Hoje à noite eu sairei na frente dos meus irmãos e irmãs, e avançarei em minha busca enquanto eles dormem. + + + Fracassar esta missão seria uma vergonha para o meu nome. + + + Eu ainda não ouvi uma resposta da rocha que joguei mais cedo. Um único passo em falso e minha descida seria eterna. É verdadeiramente um pensamento horrível. + + + Eu ainda não ouvi uma resposta da rocha que joguei mais cedo. Um único passo em falso e minha descida seria eterna. É verdadeiramente um pensamento horrível. + + + Uma eternidade de escuridão é mais assustadora do que qualquer fera que eu já lutei. Se eu caísse, o que me mataria primeiro? A fome ou eu mesmo? + + + Uma eternidade de escuridão é mais assustadora do que qualquer fera que eu já lutei. Se eu caísse, o que me mataria primeiro? A fome ou eu mesmo? + + + Como um comentário adicional, agora estou usando a fenda da floresta como o meu próprio banheiro pessoal. Eu me pergunto se estou fazendo minhas necessidades em outra dimensão... + + + Como um comentário adicional, agora estou usando a fenda da floresta como o meu próprio banheiro pessoal. Eu me pergunto se estou fazendo minhas necessidades em outra dimensão... + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #12 + + + Registro #12 + + + Eu encontrei uma solução para o meu problema com a fome. A floresta tem uma generosidade infinita de deliciosos cogumelos. + + + Eu encontrei uma solução para o meu problema com a fome. A floresta tem uma generosidade infinita de deliciosos cogumelos. + + + E dentro destes cogumelos jazem pés de galinha! Há também moedas de ouro e frascos de água com gás... Mais cedo, eu abri um tronco de árvore, e um saco de dinheiro caiu dele. + + + E dentro destes cogumelos jazem pés de galinha! Há também moedas de ouro e frascos de água com gás... Mais cedo, eu abri um tronco de árvore, e um saco de dinheiro caiu dele. + + + Às vezes eu sinto como se eu tivesse enlouquecido. + + + Às vezes eu sinto como se eu tivesse enlouquecido. + + + ... Além disso, o que está acontecendo com a lua? Ela está ENORME! + + + ... Além disso, o que está acontecendo com a lua? Ela está ENORME! + + + Diário do Príncipe + + + Diário do Príncipe + + + Fracassar esta missão seria uma vergonha para o meu nome. + + + Diário do Príncipe + + + Registro #13 + + + Registro #13 + + + Eu matei a fera da floresta e senti a sala do trono se enfraquecer mais uma vez. + + + Eu matei a fera da floresta e senti a sala do trono se enfraquecer mais uma vez. + + + Minhas suposições estavam corretas. Cada ala do castelo abriga sua própria fera guardiã. Isso foi concebido como um teste de vontade? Se sim, não posso falhar, pois quanto mais me arrisco, mais corajoso me torno! + + + Minhas suposições estavam corretas. Cada ala do castelo abriga sua própria fera guardiã. Isso foi concebido como um teste de vontade? Se sim, não posso falhar, pois quanto mais me arrisco, mais corajoso me torno! + + + Amanhã eu vasculharei a torre. Estou numa maré de sorte. + + + Amanhã eu vasculharei a torre. Estou numa maré de sorte. + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #14 + + + Registro #14 + + + Eu venho metodicamente matando os demônios nestes aposentos em minha busca para matar o próximo guardião, mas estou perdendo a noção do tempo... E outras coisas... + + + Eu venho metodicamente matando os demônios nestes aposentos em minha busca para matar o próximo guardião, mas estou perdendo a noção do tempo... E outras coisas... + + + Ao entrar na torre, eu senti o tempo parar. Ou talvez era só uma vertigem? Eu nunca fui fã de lugares altos... ou fui? + + + Ao entrar na torre, eu senti o tempo parar. Ou talvez era só uma vertigem? Eu nunca fui fã de lugares altos... ou fui? + + + Estou cada vez com mais dificuldade para lembrar o meu passado... + + + Estou cada vez com mais dificuldade para lembrar o meu passado... + + + Diário do Príncipe + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #2 + + + Registro #15 + + + Registro #15 + + + Lembro-me de ser um aventureiro famoso. Minhas proezas marciais superavam as de meus irmãos. Disso, tenho certeza. Enquanto eles passavam dias com as caras afundadas nos livros, eu matava bandidos e monstros. + + + Lembro-me de ser um aventureiro famoso. Minhas proezas marciais superavam as de meus irmãos. Disso, tenho certeza. Enquanto eles passavam dias com as caras afundadas nos livros, eu matava bandidos e monstros. + + + Eu sempre me perguntei por que meu pai os favoreceu em vez de mim? Não é sempre o oposto em contos de fadas? + + + Eu sempre me perguntei por que meu pai os favoreceu em vez de mim? Não é sempre o oposto em contos de fadas? + + + Ao homem ousado, a fortuna estende a mão. Não ao intelectual insípido... Ou algo assim. + + + Ao homem ousado, a fortuna estende a mão. Não ao intelectual insípido... Ou algo assim. + + + Nossa, eu adoraria ver meus irmãos tentarem superar intelectualmente a minha espada na cara deles! + + + Nossa, eu adoraria ver meus irmãos tentarem superar intelectualmente a minha espada na cara deles! + + + Diário do Príncipe + + + Diário do Príncipe + + + Registro #16 + + + Registro #16 + + + E se já se passaram anos desde que adentrei pela primeira vez essas paredes? É verdade que estou me tornando mais proficiente em matar monstros, mas parece que já passou um século. + + + E se já se passaram anos desde que adentrei pela primeira vez essas paredes? É verdade que estou me tornando mais proficiente em matar monstros, mas parece que já passou um século. + + + Eu até esqueci a fisionomia dos meu familiares. + + + Eu até esqueci a fisionomia dos meu familiares. + + + E se eles acharem que falhei? E se um dos meus irmãos achou a cura antes de mim? + + + E se eles acharem que falhei? E se um dos meus irmãos achou a cura antes de mim? + + + Registro #2 + + + Registro # + + + Registro # + + + Castelo Hamson + + + Castelo Hamson + + + A Terra da Escuridão + + + A Terra da Escuridão + + + Floresta Abecásia + + + Floresta Abecásia + + + Os Maia + + + Os Maia + + + Selecione uma categoria + + + Precisa de runa + + + Precisa de runa + + + Compre informações aqui + + + Compre informações aqui + + + {0} para liberar + + + {0} para liberar + + + Runa + + + Runa + + + Selecione uma categoria + + + Instruções + + + Instruções + + + [Input:0] para selecionar/equipar + + + [Input:0] para selecionar/equipar + + + [Input:2] para cancelar/fechar menu + + + [Input:2] para cancelar/fechar menu + + + Setas para navegar + + + Setas para navegar + + + [Button:LeftStick] para navegar + + + [Button:LeftStick] para navegar + + + Morto + + + Morto + + + Pressione [Input:0] para sair + + + Pressione [Input:0] para sair + + + Esqueleto + + + Bloobasauro Rex + + + Vovô Faísca + + + Vovô Faísca + + + Lorde Faísca, Rei da Faiscolândia + + + Lorde Faísca, Rei da Faiscolândia + + + Mímico + + + Mímico + + + Mimicante + + + Mimicante + + + Mimicrocante + + + Mimicrocante + + + Cestículos + + + Cestículos + + + Barbatos + + + Barbatos + + + Estolas + + + Estolas + + + Berith + + + Berith + + + Amon + + + Amon + + + Bloobasauro Rex + + + Heródoto + + + Focalor + + + Focalor + + + Halfas + + + Halfas + + + Neo Khidr + + + Neo Khidr + + + Alexander IV + + + Alexander IV + + + Astrodotus + + + Astrodotus + + + Ponce de Freon + + + Ponce de Freon + + + Os Brohannes + + + Os Brohannes + + + Torre Blindada + + + Torre Blindada + + + O Guardião + + + O Guardião + + + O Infinito + + + O Infinito + + + Heródoto + + + Chaintor + + + O Esquecido + + + O Esquecido + + + O Desertor + + + O Desertor + + + O Sentinela + + + O Sentinela + + + O Traidor + + + O Traidor + + + A Fonte + + + A Fonte + + + Berith e Halphas + + + Berith e Halphas + + + Barbatos e Amon + + + Barbatos e Amon + + + Stolas e Focalor + + + Stolas e Focalor + + + Chaintor + + + Chaintex + + + Chaintex + + + Chaintus + + + Chaintus + + + Panteão + + + Panteão + + + Earthsor + + + Earthsor + + + Gravisor + + + Gravisor + + + Terrasor + + + Terrasor + + + Flamelock + + + Flamelock + + + Esqueleto + + + Sr. Ossos + + + Blazelock + + + Blazelock + + + Sollock + + + Sollock + + + Mago Sol + + + Mago Sol + + + Frosten + + + Frosten + + + Icen + + + Icen + + + Glacien + + + Glacien + + + Mago Luna + + + Mago Luna + + + Batedor + + + Batedor + + + Pupila + + + Pupila + + + Visionário + + + Visionário + + + Sr. Ossos + + + Sr. Costela + + + Khidr + + + Khidr + + + Fúria + + + Fúria + + + Raiva + + + Raiva + + + Ira + + + Ira + + + Alexander + + + Alexander + + + Guarda Alto + + + Guarda Alto + + + Guarda Hulk + + + Guarda Hulk + + + Torre de Guarda + + + Torre de Guarda + + + Sentinela + + + Sentinela + + + Spiketor + + + Spiketor + + + Sr. Costela + + + Caval. Corrupto + + + Spiketex + + + Spiketex + + + Spiketus + + + Spiketus + + + Spiker + + + Spiker + + + Cavaleiro Gray + + + Cavaleiro Gray + + + Barão Gray + + + Barão Gray + + + Graydiador + + + Graydiador + + + Graypião + + + Graypião + + + Warg + + + Warg + + + Wargen + + + Wargen + + + Wargenflorgen + + + Wargenflorgen + + + Caval. Corrupto + + + Guarda Corrupta + + + Warg Zorg + + + Warg Zorg + + + Zumbi + + + Zumbi + + + Zumbiner + + + Zumbiner + + + Zumbishnu + + + Zumbishnu + + + Zomg + + + Zomg + + + Energon + + + Energon + + + Mastertron + + + Mastertron + + + Voltron + + + Voltron + + + Prime + + + Prime + + + Ninjo + + + Ninjo + + + Guarda Corrupta + + + Lorde Corrupto + + + Ninpo + + + Ninpo + + + Ninpojo + + + Ninpojo + + + Ninja Mestre + + + Ninja Mestre + + + Broto + + + Broto + + + Plantite + + + Plantite + + + Flormon + + + Flormon + + + Charite + + + Charite + + + Pirita + + + Pirita + + + Infernite + + + Infernite + + + Ponce de Leon + + + Ponce de Leon + + + Lorde Corrupto + + + Botis + + + Armad. Estacas + + + Armad. Estacas + + + Arqueiro + + + Arqueiro + + + Ranger + + + Ranger + + + Sniper + + + Sniper + + + Atirador Especial + + + Atirador Especial + + + Johannes + + + Johannes + + + A Fonte + + + A Fonte + + + Fonte da Juventude + + + Fonte da Juventude + + + Doomtela + + + Doomtela + + + Doomtrato + + + Doomtrato + + + Botis + + + Bloob + + + Doomisagem + + + Doomisagem + + + Sallos + + + Sallos + + + Plinky + + + Plinky + + + Planky + + + Planky + + + Plonky + + + Plonky + + + Plu + + + Plu + + + Kentucky + + + Kentucky + + + Frito + + + Frito + + + Frango + + + Frango + + + Delicioso + + + Delicioso + + + Bloob + + + Bloobite + + + Canhão + + + Canhão + + + Canhão GG + + + Canhão GG + + + Canhão 2000 + + + Canhão 2000 + + + Canhão Gigasauro + + + Canhão Gigasauro + + + Cav. s/ Cabeça + + + Cav. s/ Cabeça + + + Garanhão Negro + + + Garanhão Negro + + + Puro Sanguinário + + + Puro Sanguinário + + + Querido Pônei + + + Querido Pônei + + + Faisqueiro + + + Faisqueiro + + + Sr. Faísca + + + Sr. Faísca + + + Bloobite + + + Cofre + + + Maldição + + + Maldição + + + Graças + + + Graças + + + Taxa do arquiteto + + + Taxa do arquiteto + + + Bônus NG+ + + + Bônus NG+ + + + Cofre + + + Arrancada + + + Arrancada + + + Vampiro + + + Vampiro + + + Céu + + + Céu + + + Sifão + + + Sifão + + + Equilíbrio + + + Equilíbrio + + + Retaliação + + + Retaliação + + + Recompensa + + + Recompensa + + + Aceleração + + + Aceleração + + + de novato + + + de matador + + + de matador + + + de sábio + + + de sábio + + + de sangue + + + de sangue + + + retribuir + + + retribuir + + + sagrado(a) + + + sagrado(a) + + + sombrio(a) + + + sombrio(a) + + + de novato + + + de prata + + + de prata + + + de guarda + + + de guarda + + + imperial + + + imperial + + + real + + + real + + + de cavaleiro + + + de cavaleiro + + + de ranger + + + de ranger + + + celestial + + + celestial + + + de dragão + + + de dragão + + + Espada + + + Espada + + + Capa + + + Capa + + + Luva + + + Luva + + + Elmo + + + Elmo + + + Tórax + + + Tórax + + + Nenhum + + + Nenhum + + + Espada + + + Espada + + + Capa + + + Capa + + + Luva + + + Luva + + + Elmo + + + Elmo + + + Tórax + + + Tórax + + + Nenhum + + + Nenhum + + + Te concede o poder de saltar no ar. Junte várias runas para ter vários saltos. + + + Inimigos mais difíceis têm recompensas melhores. Junte várias runas para torná-los ainda mais difíceis. + + + Inimigos mais difíceis têm recompensas melhores. Junte várias runas para torná-los ainda mais difíceis. + + + Inimigos evoluem mais devagar, mas você recebe menos ouro. Junte várias runas p/ os inimigos evoluírem ainda mais lentamente. + + + Inimigos evoluem mais devagar, mas você recebe menos ouro. Junte várias runas p/ os inimigos evoluírem ainda mais lentamente. + + + Te concede o poder de saltar no ar. Junte várias runas para ter vários saltos. + + + Ganhe o poder de correr distâncias curtas. Junte várias runas para poder correr várias vezes. + + + Ganhe o poder de correr distâncias curtas. Junte várias runas para poder correr várias vezes. + + + Matar inimigos irá drená-los de sua vida. Junte várias runas para aumentar a drenagem de vida. + + + Matar inimigos irá drená-los de sua vida. Junte várias runas para aumentar a drenagem de vida. + + + Ganhe o poder de voar. Junte várias runas para voar por mais tempo. + + + Ganhe o poder de voar. Junte várias runas para voar por mais tempo. + + + Rouba mana de inimigos mortos. Junte várias runas para aumentar a drenagem de mana. + + + Rouba mana de inimigos mortos. Junte várias runas para aumentar a drenagem de mana. + + + Matar inimigos concede HP e MP. Junte várias runas para aumentar a drenagem de hp/mp. + + + Matar inimigos concede HP e MP. Junte várias runas para aumentar a drenagem de hp/mp. + + + Devolve o dano recebido de inimigos. Junte várias runas para aumentar o retorno de dano. + + + Devolve o dano recebido de inimigos. Junte várias runas para aumentar o retorno de dano. + + + Aumente a quantidade de ouro que você ganha de moedas. Junte várias runas para aumentar o ganho de ouro. + + + Aumente a quantidade de ouro que você ganha de moedas. Junte várias runas para aumentar o ganho de ouro. + + + Aumente sua velocidade de movimento base. Junte várias runas para ficar ainda mais rápido. + + + Aumente sua velocidade de movimento base. Junte várias runas para ficar ainda mais rápido. + + + Inimigos são mais difíceis. + + + Inimigos são mais difíceis. + + + Inimigos evoluem mais lentamente. + + + Inimigos evoluem mais lentamente. + + + Pressione [Input:10] enquanto estiver no ar. + + + Pressione [Input:10] enquanto estiver no ar. + + + [Input:14] ou [Input:15] para correr em disparada. + + + [Input:14] ou [Input:15] para correr em disparada. + + + Mate inimigos para recuperar vida. + + + Mate inimigos para recuperar vida. + + + Pressione [Input:10] enquanto estiver no ar. + + + Pressione [Input:10] enquanto estiver no ar. + + + Mate inimigos para recuperar mana. + + + Mate inimigos para recuperar mana. + + + Mate inimigos para recuperar vida e mana. + + + Mate inimigos para recuperar vida e mana. + + + Dano devolvido aos inimigos. + + + Dano devolvido aos inimigos. + + + Moedas dão mais ouro. + + + Moedas dão mais ouro. + + + Mova-se mais rápido. + + + Mova-se mais rápido. + + + Chance de Crítico + + + Avanço no ar + + + Avanço no ar + + + Bloqueio + + + Bloqueio + + + Flutuação + + + Flutuação + + + Pode atacar projéteis + + + Pode atacar projéteis + + + Voo + + + Voo + + + Vel. Movimento + + + Vel. Movimento + + + Nenhum + + + Nenhum + + + Chance de Crítico + + + Dano Crítico + + + Dano Crítico + + + Vampirismo + + + Vampirismo + + + Bônus de ouro + + + Bônus de ouro + + + Sifão + + + Sifão + + + Bônus de XP + + + Bônus de XP + + + Ataque no ar + + + Ataque no ar + + + Salto no ar + + + Salto no ar + + + Retorno de dano + + + Retorno de dano + + + Recompensa aumentada em {0}% + + + Recompensa aumentada em {0}% + + + Inimigos iniciam fases com nível {0} mais alto + + + Inimigos iniciam fases com nível {0} mais alto + + + Inimigos evoluem {0} unidades mais lentamente + + + Inimigos evoluem {0} unidades mais lentamente + + + Inimigos evoluem {0} unidade mais lentamente + + + Inimigos evoluem {0} unidade mais lentamente + + + Salte no ar {0} vezes + + + Salte no ar {0} vezes + + + Salte no ar {0} vez + + + Salte no ar {0} vez + + + Corra em disparada {0} vezes + + + Corra em disparada {0} vezes + + + Corra em disparada {0} vez + + + Corra em disparada {0} vez + + + Retome {0} HP por cada morte + + + Retome {0} HP por cada morte + + + Voe por {0} segundos + + + Voe por {0} segundos + + + Voe por {0} segundo + + + Voe por {0} segundo + + + Retome {0} MP por cada morte + + + Retome {0} MP por cada morte + + + Mana HP + + + Mana HP + + + Retorne {0}% de dano depois de ser atingido + + + Retorne {0}% de dano depois de ser atingido + + + Cada queda de ouro é {0}% mais valiosa + + + Cada queda de ouro é {0}% mais valiosa + + + Mova-se {0}% mais rápido. + + + Mova-se {0}% mais rápido. + + + Sair do Rogue Legacy + + + Sair do Rogue Legacy + + + Pressione [Input:0] para continuar + + + Pressione [Input:0] para continuar + + + O sol... eu tinha me esquecido de como era... + + + O sol... eu tinha me esquecido de como era... + + + {0} foi morto por {1} + + + {0} foi morto por {1} + + + Pressione [Input:0] para continuar + + + Pressione [Input:0] para continuar + + + {0} foi morto por {1} + + + {0} foi morta por {1} + + + {0} foi morto por um(a) {1} + + + {0} foi morta por um(a) {1} + + + {0} foi finalizado por um projétil + + + {0} foi finalizada por um projétil + + + {0} escorregou e foi empalado por estacas + + + {0} escorregou e foi empalada por estacas + + + {0} foi morto + + + {0} foi morta + + + - Palavras de despedida de {0} + + + - Palavras de despedida de {0} + + + [Input:0] para continuar + + + [Input:0] para continuar + + + HP aumentado + + + HP aumentado + + + MP aumentado + + + MP aumentado + + + Força aumentada + + + Força aumentada + + + Dano Mágico aumentado + + + Dano Mágico aumentado + + + Armadura reforçada + + + Armadura reforçada + + + Carga de Peso Máx. Aumentada + + + Carga de Peso Máx. Aumentada + + + Medalhão concluído! + + + Medalhão concluído! + + + Você coletou uma parte do medalhão! + + + Você coletou uma parte do medalhão! + + + A Floresta está sempre ao lado direito do castelo. + + + As runas celestes te permitem voar ao pressionar [Input:10] enquanto estiver no ar. + + + As runas celestes te permitem voar ao pressionar [Input:10] enquanto estiver no ar. + + + As runas vampirismo e sifão são muito poderosas quando usadas em conjunto. + + + As runas vampirismo e sifão são muito poderosas quando usadas em conjunto. + + + Dominar as runas de mobilidade te torna incrível. + + + Dominar as runas de mobilidade te torna incrível. + + + Expanda a sua mansão. Você nunca sabe que habilidades novas podem ser reveladas. + + + Expanda a sua mansão. Você nunca sabe que habilidades novas podem ser reveladas. + + + Todas as classes podem ser melhoradas com habilidades únicas. + + + Todas as classes podem ser melhoradas com habilidades únicas. + + + Habilidades de classe liberadas podem ser ativadas com [Input:13] + + + Habilidades de classe liberadas podem ser ativadas com [Input:13] + + + Melhore suas classes mais cedo para obter habilidades poderosas. + + + Melhore suas classes mais cedo para obter habilidades poderosas. + + + Se você está tendo problemas com um salão, veja se pode pulá-lo. + + + Se você está tendo problemas com um salão, veja se pode pulá-lo. + + + Comprar equipamentos é a maneira mais rápida de aumentar suas estatísticas. + + + Comprar equipamentos é a maneira mais rápida de aumentar suas estatísticas. + + + Comprar equipamentos é mais barato e flexível do que aumentar suas estatísticas de base. + + + Comprar equipamentos é mais barato e flexível do que aumentar suas estatísticas de base. + + + A Floresta está sempre ao lado direito do castelo. + + + Os Maia estão sempre no topo do castelo. + + + Você deveria ter escolhido a outra criança. + + + Você deveria ter escolhido a outra criança. + + + As runas são muito poderosas. Equipe as runas na Feiticeira e não se esqueça de usá-las! + + + As runas são muito poderosas. Equipe as runas na Feiticeira e não se esqueça de usá-las! + + + Aprenda sobre as particularidades do seu feitiço para maximizar seu potencial. + + + Aprenda sobre as particularidades do seu feitiço para maximizar seu potencial. + + + Acerte os inimigos perto do ápice do arco do machado para atingi-los várias vezes. + + + Acerte os inimigos perto do ápice do arco do machado para atingi-los várias vezes. + + + Evite pegar as esferas de confluência após lançá-las para maximizar o dano. + + + Evite pegar as esferas de confluência após lançá-las para maximizar o dano. + + + Desvie do retorno dos chakrams, a fim de maximizar seu dano. + + + Desvie do retorno dos chakrams, a fim de maximizar seu dano. + + + É melhor usar mana para matar os inimigos do que tomar danos desnecessários. + + + É melhor usar mana para matar os inimigos do que tomar danos desnecessários. + + + Aprender os "sinais" do inimigo é essencial para sobreviver ao castelo. + + + Aprender os "sinais" do inimigo é essencial para sobreviver ao castelo. + + + As armadilhas de estacas checam o pulso para distinguir os mortos dos vivos. + + + As armadilhas de estacas checam o pulso para distinguir os mortos dos vivos. + + + Pressione [Input:9] para abrir o mapa. + + + Pressione [Input:9] para abrir o mapa. + + + Os Maia estão sempre no topo do castelo. + + + A Escuridão está sempre embaixo do castelo. + + + Os baús encantados guardam todas as runas no jogo. As runas te ajudarão bastante. + + + Os baús encantados guardam todas as runas no jogo. As runas te ajudarão bastante. + + + Se você falhar um salão com baú encantado o arquiteto pode te dar outra chance. + + + Se você falhar um salão com baú encantado o arquiteto pode te dar outra chance. + + + O arquiteto possui uma taxa alta para aqueles que usam seu serviço. + + + O arquiteto possui uma taxa alta para aqueles que usam seu serviço. + + + Os chefões liberam grandes quantidades de ouro em sua morte. + + + Os chefões liberam grandes quantidades de ouro em sua morte. + + + Enterre-me com meu dinheiro. + + + Enterre-me com meu dinheiro. + + + Se você está tendo problemas, tente se equipar com runas das graças. + + + Se você está tendo problemas, tente se equipar com runas das graças. + + + Nas opções, você pode ativar Queda Rápida para cair golpeando com [Input:18] + + + Nas opções, você pode ativar Queda Rápida para cair golpeando com [Input:18] + + + O arquiteto é muito útil para praticar contra os chefões. + + + O arquiteto é muito útil para praticar contra os chefões. + + + A terceira fileira de equipamentos traz grandes perdas e ganhos. Seja cuidadoso. + + + A terceira fileira de equipamentos traz grandes perdas e ganhos. Seja cuidadoso. + + + Certas runas funcionam melhor com certos chefões. + + + Certas runas funcionam melhor com certos chefões. + + + A Escuridão está sempre embaixo do castelo. + + + Se você está tendo problemas com um chefão, tente usar runas diferentes. + + + Você deveria usar o arquiteto para praticar o combate contra chefões. + + + Você deveria usar o arquiteto para praticar o combate contra chefões. + + + A vida é algo muito importante de se aumentar. + + + A vida é algo muito importante de se aumentar. + + + As runas de retribuição podem danificar objetos invulneráveis. + + + As runas de retribuição podem danificar objetos invulneráveis. + + + As habilidades de classe são muito poderosas se usadas corretamente. + + + As habilidades de classe são muito poderosas se usadas corretamente. + + + Algumas classes têm vantagens sobre certos chefões. + + + Algumas classes têm vantagens sobre certos chefões. + + + Se você está tendo problemas com um chefão, tente usar runas diferentes. + + + As runas do salto te permitem saltar no ar com [Input:10] + + + As runas do salto te permitem saltar no ar com [Input:10] + + + As runas da arrancada te permitem avançar com [Input:PLAYER_DASHLEFT] ou [Input:PLAYER_DASHRIGHT] + + + As runas da arrancada te permitem avançar com [Input:PLAYER_DASHLEFT] ou [Input:PLAYER_DASHRIGHT] + + + Cada classe tem prós e contras. Não se esqueça de alterar seu estilo de jogo de acordo. + + + Cada classe tem prós e contras. Não se esqueça de alterar seu estilo de jogo de acordo. + + + Explorar e encontrar baús é a melhor maneira de ganhar ouro. + + + Explorar e encontrar baús é a melhor maneira de ganhar ouro. + + + As áreas mais difíceis oferecem recompensas maiores. + + + As áreas mais difíceis oferecem recompensas maiores. + + + Meus deveres são com a minha família... + + + Meus deveres são com a minha família... + + + Mas sou leal apenas a mim. + + + Mas sou leal apenas a mim. + + + ouro + + + ouro + + + hp recuperado + + + hp recuperado + + + mp recuperado + + + mp recuperado + + + Mais Armadura + + + Mais Armadura + + + Mais Vida Máx. + + + Mais Vida Máx. + + + Mais Mana Máx. + + + Mais Mana Máx. + + + Mais Ataque + + + Mais Ataque + + + Mais Magia + + + Mais Magia + + + Mais Peso Máx. + + + Mais Peso Máx. + + + Tocando + + + Tocando + + + Agora entrando + + + Agora entrando + + + Objetivo Baú Encantado: + + + Objetivo Baú Encantado: + + + Alcance o baú em 15 segundos: + + + Alcance o baú em 15 segundos: + + + Tempo Restante: + + + Tempo Restante: + + + Objetivo concluído! + + + Objetivo concluído! + + + Falha no objetivo + + + Falha no objetivo + + + Sem Aspectos + + + {0} Heróico + + + {0} Heróica + + + {0} Divino + + + {0} Divina + + + Sir {0} {1} + + + Sir {0} {1} + + + Sir Herói + + + Sir Herói + + + Madame {0} {1} + + + Madame {0} {1} + + + Lady Heroine + + + Lady Heroine + + + Sem Aspectos + + + the + + + the + + + {0} Lendário + + + {0} Lendária + + + {0} Inútil + + + {0} Inútil + + + {0} Fracote + + + {0} Fracote + + + {0} Determinado + + + {0} Determinada + + + {0} Forte + + + {0} Forte + + + {0} Corajoso + + + {0} Corajosa + + + {0} Valente + + + {0} Valente + + + [Input:0] para selecionar um herdeiro + + + [Input:0] para selecionar um herdeiro + + + [Button:LeftStick] para ver a árvore genealógica + + + [Button:LeftStick] para ver a árvore genealógica + + + Setas para ver a árvore genealógica + + + Setas para ver a árvore genealógica + + + [Input:9] para recriar seus herdeiros + + + [Input:9] para recriar seus herdeiros + + + Classe + + + Classe + + + Aspecto + + + Aspecto + + + Aspecto – Nenhum + + + Aspecto – Nenhum + + + Feitiço + + + Feitiço + + + Construindo + + + Construindo + + + Deixando careca + + + Deixando careca + + + Lembrando + + + Lembrando + + + Conectando + + + Conectando + + + Baú aberto + + + Baú aberto + + + Teletransportador + + + Teletransportador + + + Salão Bônus + + + Salão Bônus + + + [Input:9] para fechar o mapa + + + [Input:9] para fechar o mapa + + + [Input:0] para centralizar no jogador + + + [Input:0] para centralizar no jogador + + + Use as setas para mover o mapa + + + Use as setas para mover o mapa + + + [Button:LeftStick] para mover o mapa + + + [Button:LeftStick] para mover o mapa + + + Legenda + + + Legenda + + + Você está aqui + + + Você está aqui + + + Localiz. do chefão + + + Localiz. do chefão + + + Baú fechado + + + Baú fechado + + + Baú encantado + + + Baú encantado + + + Volume da música + + + Volume da música + + + Chinês + + + Chinês + + + Inglês + + + Inglês + + + Francês + + + Francês + + + Alemão + + + Alemão + + + Polonês + + + Polonês + + + Português (Brasil) + + + Português (Brasil) + + + Russo + + + Russo + + + Espanhol (Espanha) + + + Espanhol (Espanha) + + + Idioma + + + Idioma + + + *A Queda Rápida permite que você pule das bordas e faça ataques para \nbaixo no ar apertando o botão PARA BAIXO + + + Resolução + + + Resolução + + + Tela cheia + + + Tela cheia + + + Reduza a qualidade do sombreador + + + Reduza a qualidade do sombreador + + + Use Dinput Gamepads + + + Use Dinput Gamepads + + + Ative o Steam Cloud + + + Ative o Steam Cloud + + + *A Queda Rápida permite que você pule das bordas e faça ataques para \nbaixo no ar apertando o botão PARA BAIXO + + + [Button:LeftStick] para navegar pelas opções + + + [Button:LeftStick] para navegar pelas opções + + + Setas para navegar pelas opções + + + Setas para navegar pelas opções + + + [Input:0] para selecionar a opção + + + [Input:0] para selecionar a opção + + + [Input:2] para sair das opções + + + [Input:2] para sair das opções + + + *O jogo deve ser reiniciado para esta alteração entrar em vigor. + + + *O jogo deve ser reiniciado para esta alteração entrar em vigor. + + + *O suporte da nuvem também deve estar ativado na plataforma Steam\npara este recurso funcionar. + + + *O suporte da nuvem também deve estar ativado na plataforma Steam\npara este recurso funcionar. + + + Classe: + + + Classe: + + + Força: + + + Força: + + + Magia: + + + Magia: + + + Armadura: + + + Armadura: + + + Nível: + + + Nível: + + + Vida: + + + Vida: + + + ????? + + + ????? + + + ouro + + + ouro + + + mp máx. + + + mp máx. + + + hp máx. + + + hp máx. + + + MP máximo convertido. Precisa de nível mais alto. + + + MP máximo convertido. Precisa de nível mais alto. + + + Vida + + + Encantamentos + + + Encantamentos + + + [Input:2] para sair + + + [Input:2] para sair + + + Nv. + + + Nv. + + + Vida + + + Mana + + + Mana + + + Armad. + + + Armad. + + + Peso + + + Peso + + + Força + + + Força + + + Inteligência + + + Inteligência + + + Prob. crítico + Chance de Dano crítico + + + Prob. crítico + Chance de Dano crítico + + + Dano crítico + + + Dano crítico + + + Equipamento + + + Equipamento + + + 100% estatísticas de base. + + + ESPECIAL: Grito Bárbaro.\nHP imenso. Força e MP baixos. + + + ESPECIAL: Grito Bárbaro.\nHP imenso. Força e MP baixos. + + + Força imensa, mas não realiza ataques críticos.\n+{0}% Vel. Movimento. HP e MP baixos. + + + Força imensa, mas não realiza ataques críticos.\n+{0}% Vel. Movimento. HP e MP baixos. + + + ESPECIAL: Técnica de Substituição.\nForça imensa, mas não realiza ataques críticos.\n+{0}% Vel. Movimento. HP e MP baixos. + + + ESPECIAL: Técnica de Substituição.\nForça imensa, mas não realiza ataques críticos.\n+{0}% Vel. Movimento. HP e MP baixos. + + + {0}% do dano causado é convertido em mana.\nForça, HP e MP baixos. + + + {0}% do dano causado é convertido em mana.\nForça, HP e MP baixos. + + + ESPECIAL: Magia Fortalecida.\n{0}% do dano causado é convertido em mana.\nForça, HP e MP baixos. + + + ESPECIAL: Magia Fortalecida.\n{0}% do dano causado é convertido em mana.\nForça, HP e MP baixos. + + + As mortes são convertidas em HP máximo.\nForça, HP e MP bem baixos. Inteligência alta. + + + As mortes são convertidas em HP máximo.\nForça, HP e MP bem baixos. Inteligência alta. + + + ESPECIAL: Conversão de HP.\nAs mortes são convertidas em HP máximo.\nForça, HP e MP bem baixos. Inteligência alta. + + + ESPECIAL: Conversão de HP.\nAs mortes são convertidas em HP máximo.\nForça, HP e MP bem baixos. Inteligência alta. + + + Você é um homem-dragão + + + Você é uma mulher-dragão + + + ????? + + + ????? + + + 100% estatísticas de base. + + + ESPECIAL: Escudo dos Guardiões.\n100% estatísticas de base. + + + ESPECIAL: Escudo dos Guardiões.\n100% estatísticas de base. + + + +{0}% Chance Crítica, +{1}% Dano Crítico.\nHP. MP e Força baixos. + + + +{0}% Chance Crítica, +{1}% Dano Crítico.\nHP. MP e Força baixos. + + + ESPECIAL: Forma Nebulosa\n+{0}% Chance Crítica, +{1}% Dano Crítico.\nHP. MP e Força baixos. + + + ESPECIAL: Forma Nebulosa\n+{0}% Chance Crítica, +{1}% Dano Crítico.\nHP. MP e Força baixos. + + + +{0}% ganho de ouro.\nMuito fraco em todas as outras estatísticas. + + + +{0}% ganho de ouro.\nMuito fraco em todas as outras estatísticas. + + + ESPECIAL: Lanterna Simples.\n+{0}% ganho de ouro.\nMuito fraco em todas as outras estatísticas. + + + ESPECIAL: Lanterna Simples.\n+{0}% ganho de ouro.\nMuito fraco em todas as outras estatísticas. + + + Cada morte te fornece {0} mana.\nHP e força baixos. Inteligência e MP altos. + + + Cada morte te fornece {0} mana.\nHP e força baixos. Inteligência e MP altos. + + + ESPECIAL: Ciclo de Magia.\nCada morte te fornece {0} mana.\nHP e Força baixos. Inteligência e MP altos. + + + ESPECIAL: Ciclo de Magia.\nCada morte te fornece {0} mana.\nHP e Força baixos. Inteligência e MP altos. + + + HP imenso. Força e MP baixos. + + + HP imenso. Força e MP baixos. + + + - INICIAR NOVO LEGADO - + + + NG++ + + + NG++ + + + - INICIAR NOVO LEGADO - + + + [Button:LeftStick] para navegar + + + [Button:LeftStick] para navegar + + + Setas para navegar pelos perfis + + + Setas para navegar pelos perfis + + + [Input:0] para selecionar + + + [Input:0] para selecionar + + + [Input:2] para sair + + + [Input:2] para sair + + + [Input:26] para excluir + + + [Input:26] para excluir + + + {0}, a {1} + + + {0}, a {1} + + + {0}, o {1} + + + {0}, o {1} + + + {0}, a Falecida + + + {0}, a Falecida + + + {0}, o Falecido + + + {0}, o Falecido + + + Nvl. + + + Nvl. + + + Habilitar queda rápida + + + Habilitar queda rápida + + + Não + + + Não + + + Sim + + + Sim + + + Volume dos efeitos + + + Volume dos efeitos + + + Melhore seu condicionamento físico. Um coração melhor significa uma saúde melhor. + + + Libere o ferreiro e ganhe acesso a ótimas recompensas. + + + Libere o ferreiro e ganhe acesso a ótimas recompensas. + + + Libere a feiticeira e ganhe acesso às suas runas mágicas e poderes. + + + Libere a feiticeira e ganhe acesso às suas runas mágicas e poderes. + + + Libere o arquiteto e ganhe os poderes para bloquear o castelo. + + + Libere o arquiteto e ganhe os poderes para bloquear o castelo. + + + Melhorar sua capacidade de carga permitirá que você use armaduras melhores e mais pesadas. + + + Melhorar sua capacidade de carga permitirá que você use armaduras melhores e mais pesadas. + + + Fortaleça suas entranhas por meios naturais para reduzir os danos que recebe. + + + Fortaleça suas entranhas por meios naturais para reduzir os danos que recebe. + + + Melhore suas habilidades de pilhagem e faça mais grana. + + + Melhore suas habilidades de pilhagem e faça mais grana. + + + Diminua as taxas do Caronte ao aprender a negociar com a própria morte. + + + Diminua as taxas do Caronte ao aprender a negociar com a própria morte. + + + Limpar o intestino proporciona melhorias perceptíveis em poções e carnes. + + + Limpar o intestino proporciona melhorias perceptíveis em poções e carnes. + + + Use o poder da ciência para fazer uma nova leva de bebês. Humm... nem pergunte. + + + Use o poder da ciência para fazer uma nova leva de bebês. Humm... nem pergunte. + + + Libere o poder do Lich! Um ser com potencial massivo. + + + Libere o poder do Lich! Um ser com potencial massivo. + + + Melhore seu condicionamento físico. Um coração melhor significa uma saúde melhor. + + + Fortaleça suas glândulas suprarrenais e seja invulnerável como o Bane. Que comecem os jogos! + + + Libere as habilidades do Minerador e aumente a fortuna da sua família. + + + Libere as habilidades da Mineradora e aumente a fortuna da sua família. + + + Libere o Ladrão de Feitiços e se torne um mago marcial. + + + Libere a Ladra de Feitiços e se torne uma maga marcial. + + + Libere o Shinobi, o mais veloz dos lutadores. + + + Libere a Shinobi, a mais veloz das lutadoras. + + + Pratique o básico para reduzir os custos de mana quando lançar feitiços. + + + Pratique o básico para reduzir os custos de mana quando lançar feitiços. + + + Transforme seus Cavaleiros em Paladinos. Ferozes lutadores de vanguarda. + + + Transforme suas Cavaleiras em Paladinas. Ferozes lutadoras de vanguarda. + + + Libere os poderes ocultos do Mago e transforme-o no todo poderoso Arquimago. + + + Libere os poderes ocultos da Maga e transforme-a na toda poderosa Arquimaga. + + + Aprenda as artes das trevas e transforme o Valete em um Assassino. + + + Aprenda as artes das trevas e transforme a Valete em uma Assassina. + + + Consiga seu diploma em geologia e passe de Minerador para Espeleologista. Sofisticado. + + + Consiga seu diploma em geologia e passe de Mineradora para Espeleologista. Sofisticada. + + + Torne-se um Rei Bárbaro. O rei dos homens livres. Isto não faz sentido. + + + Torne-se uma Rainha Bárbara. A rainha dos homens livres. Isto não faz sentido. + + + Faça seus Liches todo-poderosos parte da realeza e transforme-os em Reis Lich. + + + Faça suas Liches todo-poderosas parte da realeza e transforme-as em Rainhas Lich. + + + Fortaleça suas glândulas suprarrenais e seja invulnerável como o Bane. Que comecem os jogos! + + + Libere seu gato interior e evite a morte. Às vezes. + + + Torne-se o líder de sua aldeia e transforme seu Shinobi em um Hokage. Pode acreditar! + + + Torne-se a líder de sua aldeia e transforme sua Shinobi em uma Hokage. Pode acreditar! + + + Cavalgue os vórtices de magia e transforme seus Ladrões de Feitiços em Magos de Espada. + + + Cavalgue os vórtices de magia e transforme suas Ladras de Feitiços em Magas de Espada. + + + Meio homem, meio ****** e incrível por inteiro. + + + Meio mulher, meio ****** e incrível por inteiro. + + + RESPIRAÇÃO RÁPIDA \nSeu fôlego não é lá essas coisas. É ruim para perseguir mas bom para andar! \n\nAumenta sua regeneração de resistência natural. + + + RESPIRAÇÃO RÁPIDA \nSeu fôlego não é lá essas coisas. É ruim para perseguir mas bom para andar! \n\nAumenta sua regeneração de resistência natural. + + + Sangue de tigre foi infundido em você quando jovem. Você recebeu o poder de liberar sangue de tigre quando esfaqueado. \nCorrer drena menos resistência. + + + Sangue de tigre foi infundido em você quando jovem. Você recebeu o poder de liberar sangue de tigre quando esfaqueado. \nCorrer drena menos resistência. + + + Você tem ascendência viking. \n\nAumenta sua resistência inicial. + + + Você tem ascendência viking. \n\nAumenta sua resistência inicial. + + + Você gosta de acordar cedo. Quem dera se subir de nível fosse como acordar.\n Ganhe HP e MP bônus todas as vezes que sobe de nível. + + + Você gosta de acordar cedo. Quem dera se subir de nível fosse como acordar.\n Ganhe HP e MP bônus todas as vezes que sobe de nível. + + + Você nasceu com poder absoluto em suas mãos. \nTodos os feitiços causam mais dano. + + + Você nasceu com poder absoluto em suas mãos. \nTodos os feitiços causam mais dano. + + + Você nasceu com energia arcana percorrendo pelas suas veias. Ai. \nFeitiços custam menos para serem lançados. + + + Você nasceu com energia arcana percorrendo pelas suas veias. Ai. \nFeitiços custam menos para serem lançados. + + + Finalmente ter TOC é algo útil. \nGanhe mais ouro. + + + Finalmente ter TOC é algo útil. \nGanhe mais ouro. + + + Libere seu gato interior e evite a morte. Às vezes. + + + Uma academia adequada permitirá que você realmente fortaleça seus braços e músculos do bumbum. + + + Por lei, agora você é o melhor homem. \nDê à luz a mais crianças. + + + Por lei, agora você é a melhor mulher. \nDê à luz a mais crianças. + + + Seus pais diziam que aprender a garimpar ouro era algo inútil para um fazendeiro. Quem está rindo agora? \n Exibe os salões de tesouro no início do jogo. + + + Seus pais diziam que aprender a garimpar ouro era algo inútil para uma fazendeira. Quem está rindo agora? \n Exibe os salões de tesouro no início do jogo. + + + A guerra é um inferno. Por sorte você nunca esteve em uma. \n Lance mais morteiros. + + + A guerra é um inferno. Por sorte você nunca esteve em uma. \n Lance mais morteiros. + + + Quando criança, você mostrou afinidade em explodir coisas. \n As bombas possuem um alcance maior. + + + Quando criança, você mostrou afinidade em explodir coisas. \n As bombas possuem um alcance maior. + + + Seu bisavô era um boneco de neve. Ele te ensinou nada. \n As estacas de gelo perfuram mais inimigos. + + + Seu bisavô era um boneco de neve. Ele te ensinou nada. \n As estacas de gelo perfuram mais inimigos. + + + Você é um cara tranquilo. \n Ganhe resistência mais rápido quando imóvel. + + + Você é uma pessoa tranquila. \n Ganhe resistência mais rápido quando imóvel. + + + HABILIDADE GENÉRICA. Aumenta a resistência total. + + + HABILIDADE GENÉRICA. Aumenta a resistência total. + + + Você luta com elegância \n Os ataques drenam X% menos de resistência. + + + Você luta com elegância \n Os ataques drenam X% menos de resistência. + + + HABILIDADE GENÉRICA. Aumenta a vida + + + HABILIDADE GENÉRICA. Aumenta a vida + + + Você chupa... Sangue. \n Restaure uma pequena quantidade de vida em cada golpe. + + + Você chupa... Sangue. \n Restaure uma pequena quantidade de vida em cada golpe. + + + Uma academia adequada permitirá que você realmente fortaleça seus braços e músculos do bumbum. + + + Praticar pula-pula tem seus benefícios. Cause mais dano com ataques para baixo consecutivos. + + + Volte à vida, assim como Jesus. Mas ainda assim você não é Jesus. \n Reviva uma vez após morrer. + + + Volte à vida, assim como Jesus. Mas ainda assim você não é Jesus. \n Reviva uma vez após morrer. + + + Esvaziar salões é como esvaziar sua mente. Eu não sei como. \nRecupere vida para cada salão totalmente esvaziado. + + + Esvaziar salões é como esvaziar sua mente. Eu não sei como. \nRecupere vida para cada salão totalmente esvaziado. + + + Cartografia /n Cada percentual de mapa revelado acrescenta 0,1 de dano. + + + Cartografia /n Cada percentual de mapa revelado acrescenta 0,1 de dano. + + + HABILIDADE GENÉRICA. Aumenta o dano de ataque. + + + HABILIDADE GENÉRICA. Aumenta o dano de ataque. + + + Você é um péssimo perdedor. \n Cause dano massivo a todos os inimigos na tela após sua morte. + + + Você é uma péssima perdedora. \n Cause dano massivo a todos os inimigos na tela após sua morte. + + + Você aprendeu que acertar as bolas causa dano massivo. \n Críticos causam mais dano. + + + Você aprendeu que acertar as bolas causa dano massivo. \n Críticos causam mais dano. + + + HABILIDADE GENÉRICA. + + + HABILIDADE GENÉRICA. + + + Ah. Elas estavam no meu bolso. \nGanhe 2 chaves extra. + + + Ah. Elas estavam no meu bolso. \nGanhe 2 chaves extra. + + + Como uma Fénix, você renasce das suas cinzas medíocres. \n Recupere todo HP e MP. + + + Como uma Fénix, você renasce das suas cinzas medíocres. \n Recupere todo HP e MP. + + + Aposente-se e invista seu dinheiro com sabedoria. Termina seu jogo mais cedo e ganha um bônus de ouro encontrado. + + + Aposente-se e invista seu dinheiro com sabedoria. Termina seu jogo mais cedo e ganha um bônus de ouro encontrado. + + + Praticar pula-pula tem seus benefícios. Cause mais dano com ataques para baixo consecutivos. + + + Aprender sobre os pontos fracos dos inimigos permite atacar com eficiência mortal. + + + VIRA VIRA VIRA! \n Beba poções instantaneamente. + + + VIRA VIRA VIRA! \n Beba poções instantaneamente. + + + Aprender sobre os pontos fracos dos inimigos permite atacar com eficiência mortal. + + + Pratique os golpes mortais para ser ainda mais mortal. Os inimigos ficarão tão mortos. + + + Pratique os golpes mortais para ser ainda mais mortal. Os inimigos ficarão tão mortos. + + + Aprenda os segredos do universo para que possa usá-los para matar melhor com feitiços. + + + Aprenda os segredos do universo para que possa usá-los para matar melhor com feitiços. + + + Aumente sua força mental a fim de aumentar a sua reserva de mana. + + + Aumente sua força mental a fim de aumentar a sua reserva de mana. + + + Pressione [Input:9] para escolher seus herdeiros aleatoriamente + + + Pressione [Input:9] para escolher seus herdeiros aleatoriamente + + + Pressione [Input:13] para bloquear todo o dano recebido. + + + Pressione [Input:13] para bloquear todo o dano recebido. + + + Pressione [Input:13] para alternar os feitiços + + + Pressione [Input:13] para alternar os feitiços + + + Pressione [Input:13] para se transformar em névoa + + + Pressione [Input:13] para se transformar em névoa + + + Pressione [Input:13] para ligar sua lanterna + + + Pressione [Input:13] para ligar sua lanterna + + + Pressione [Input:13] para lançar um grito épico que derruba praticamente tudo. + + + Pressione [Input:13] para lançar um grito épico que derruba praticamente tudo. + + + Pressione [Input:13] para converter HP máximo em MP máximo + + + Pressione [Input:13] para converter HP máximo em MP máximo + + + Pressione [Input:13] para flash + + + Pressione [Input:13] para flash + + + Pressione [Input:13] para lançar magias fortalecidas + + + Pressione [Input:13] para lançar magias fortalecidas + + + Pressione [Input:10] para se tornar incrível. + + + Pressione [Input:10] para se tornar incrível. + + + + + + + + + Mais Vida + + + Forja + + + Forja + + + Feiticeira + + + Feiticeira + + + Arquiteto + + + Arquiteto + + + Mais Equip. + + + Mais Equip. + + + Mais Armadura + + + Mais Armadura + + + Mais Ganho de Ouro + + + Mais Ganho de Ouro + + + Barganha + + + Barganha + + + Mais Poção + + + Mais Poção + + + Gerar Herdeiros + + + Gerar Herdeiros + + + Liberar Lich + + + Liberar Lich + + + Mais Vida + + + Mais Tempo Invuln. + + + Liberar Minerador + + + Liberar Mineradora + + + Lib. Ladrão de Feitiços + + + Lib. Ladra de Feitiços + + + Liberar Shinobi + + + Liberar Shinobi + + + Reduzir Custo de Mana + + + Reduzir Custo de Mana + + + Melhorar Cavaleiro + + + Melhorar Cavaleira + + + Melhorar Mago + + + Melhorar Maga + + + Melhorar Valete + + + Melhorar Valete + + + Melhorar Minerador + + + Melhorar Mineradora + + + Melhorar Bárbaro + + + Melhorar Bárbara + + + Melhorar Lich + + + Melhorar Lich + + + Mais Tempo Invuln. + + + Desafia a Morte + + + Melhorar Shinobi + + + Melhorar Shinobi + + + Melh. Ladrão de Feitiços + + + Melh. Ladra de Feitiços + + + Bestialidade + + + Bestialidade + + + Respiração Rápida + + + Respiração Rápida + + + Nascido para Correr + + + Nascida para Correr + + + Coração Forte + + + Coração Forte + + + Portão Afora + + + Portão Afora + + + Mago de Espada + + + Maga de Espada + + + Feiticeiro + + + Feiticeira + + + Perfeccionista + + + Perfeccionista + + + Desafia a Morte + + + Mais Ataque + + + Bem Equipado + + + Bem Equipada + + + Caçador de Tesouro + + + Caçadora de Tesouro + + + Mestre de Morteiro + + + Mestre de Morteiro + + + Perito em Explosivos + + + Perita em Explosivos + + + Estaca de Gelo + + + Estaca de Gelo + + + Guru + + + Guru + + + Pulmão de Ferro + + + Pulmão de Ferro + + + Mestre das Espadas + + + Mestre das Espadas + + + Tanque + + + Tanque + + + Vampiro + + + Vampira + + + Mais Ataque + + + Mais Ataque p/ Baixo + + + Segunda Chance + + + Segunda Chance + + + Paz de Espírito + + + Paz de Espírito + + + Ninja dos Mapas + + + Ninja dos Mapas + + + Homem Forte + + + Mulher Forte + + + Suicidalista + + + Suicidalista + + + Bárbaro Crítico + + + Bárbara Crítica + + + Mágico + + + Mágica + + + Mestre das Chaves + + + Mestre das Chaves + + + Apenas Uma Vez + + + Apenas Uma Vez + + + Saindo Mais Cedo + + + Saindo Mais Cedo + + + Mais Ataque p/ Baixo + + + Chance de Crítico + + + Engolidor + + + Engolidora + + + Chance de Crítico + + + Mais Dano Crítico + + + Mais Dano Crítico + + + Mais Dano Mágico + + + Mais Dano Mágico + + + Mais Mana + + + Mais Mana + + + {0} ouro para {1} + + + {0} ouro para {1} + + + liberar + + + liberar + + + melhorar + + + melhorar + + + peso + + + peso + + + hp + + + hp + + + mp + + + mp + + + for + + + for + + + int + + + int + + + hp/mp + + + hp/mp + + + Máx + + + Máx + + + [Input:0] para comprar/melhorar aspecto + + + [Input:0] para comprar/melhorar aspecto + + + Armadura + + + Armadura + + + seg. + + + seg. + + + [Input:9] para desligar ícones + + + [Input:9] para desligar ícones + + + [Input:2] para sair da mansão + + + [Input:2] para sair da mansão + + + [Button:LeftStick] para navegar pelas habilidades + + + [Button:LeftStick] para navegar pelas habilidades + + + Setas para navegar pelas habilidades + + + Setas para navegar pelas habilidades + + + [Input:9] para ligar ícones + + + [Input:9] para ligar ícones + + + Atual + + + Atual + + + Melhoria + + + Melhoria + + + Nível + + + Nível + + + O Ferreiro consegue construir os melhores equipamentos do mundo, transformando você num virtuoso exterminador de vilões violentos.\nJuntar projetos dará a ele uma gama ainda maior de armamentos variados para adicionar ao seu arsenal. + + + Converta seus Bárbaros em REIS Bárbaros! Aprenda os gritos secretos dos ursos e grite nas coisas até que elas explodam. + + + Converta suas Bárbaras em RAINHAS Bárbaras! Aprenda os gritos secretos dos ursos e grite nas coisas até que elas explodam. + + + Vá de um mísero Shinobi, para o todo poderoso Hokage! Domine a arte de parecer que está sendo atingido, mas secretamente transforme-se em uma tora no último minuto. Que bom que você carrega várias toras com você. + + + Vá de uma mísera Shinobi, para a todo poderosa Hokage! Domine a arte de parecer que está sendo atingida, mas secretamente transforme-se em uma tora no último minuto. Que bom que você carrega várias toras com você. + + + Treine seus Valetes para se tornarem Assassinos. Use o poder das sombras para passar secretamente por postos inimigos. + + + Treine suas Valetes para se tornarem Assassinas. Use o poder das sombras para passar secretamente por postos inimigos. + + + Toda essa escavação transformou seus Mineradores em Espeleologistas! Agora essa luz bacana na sua cabeça serve pra alguma coisa! (Na verdade, não). + + + Toda essa escavação transformou suas Mineradoras em Espeleologistas! Agora essa luz bacana na sua cabeça serve pra alguma coisa! (Na verdade, não). + + + Transforme seus Ladrões de Feitiço em Magos de Espada e conceda a si mesmo o poder de invocar feitiços fortalecidos.\nVocê chama isso de machado? ISTO é um machado. + + + Transforme suas Ladras de Feitiço em Magas de Espada e conceda a si mesma o poder de invocar feitiços fortalecidos.\nVocê chama isso de machado? ISTO é um machado. + + + Transforme seus Liches em Reis Lich e conceda a si mesmo o poder da mente E da matéria! Com um único toque, converta sua vida permanente em mana permanente. + + + Transforme suas Liches em Rainhas Lich e conceda a si mesma o poder da mente E da matéria! Com um único toque, converta sua vida permanente em mana permanente. + + + Você descobriu a arte perdida dos dragões. Embora você não possa pular, você tem voo ilimitado e pode lançar bolas de fogo poderosas em seus inimigos. + + + Você descobriu a arte perdida dos dragões. Embora você não possa pular, você tem voo ilimitado e pode lançar bolas de fogo poderosas em seus inimigos. + + + Você descobriu as artes ocultas conhecidas apenas por Johannes, o Traidor. Todos se curvarão perante seu poder! + + + Você descobriu as artes ocultas conhecidas apenas por Johannes, o Traidor. Todos se curvarão perante seu poder! + + + O Ferreiro consegue construir os melhores equipamentos do mundo, transformando você numa virtuosa exterminadora de vilões violentos.\nJuntar projetos dará a ele uma gama ainda maior de armamentos variados para adicionar ao seu arsenal. + + + A Feiticeira consegue fortalecer seu corpo com runas mágicas, tornando-o melhor, mais forte, mais rápido e um melhor saltador.\nEncontre runas para aumentar seu repertório de talentos modificadores de corpo.\n\nA bola de cristal dela é apenas decoração. + + + A Feiticeira consegue fortalecer seu corpo com runas mágicas, tornando-a melhor, mais forte, mais rápida e uma melhor saltadora.\nEncontre runas para aumentar seu repertório de talentos modificadores de corpo.\n\nA bola de cristal dela é apenas decoração. + + + O Arquiteto consegue bloquear um castelo e impedir que ele mude.\n\nGosta do layout de um castelo?\nBLOQUEIE-O!\nApenas se certifique de que pode pagar o salário dele. + + + O Arquiteto consegue bloquear um castelo e impedir que ele mude.\n\nGosta do layout de um castelo?\nBLOQUEIE-O!\nApenas se certifique de que pode pagar o salário dele. + + + O Shinobi. Um guerreiro super-rápido e mortal, que usa uma superfaixa na cabeça. Eles não aguentam muitos golpes, mas conseguem distribuir a dor. Pode acreditar! + + + Shinobi. Tipo de guerreiro super-rápido e mortal, que usa uma superfaixa na cabeça. Eles não aguentam muitos golpes, mas conseguem distribuir a dor. Pode acreditar! + + + Treinados mais na arte de fazer dinheiro do que matar inimigos. Os mineradores são mais aproveitados quando usados para vasculhar o castelo em busca de baús de tesouro - e evitar confrontos. + + + Treinadas mais na arte de fazer dinheiro do que matar inimigos. As mineradoras são mais aproveitadas quando usadas para vasculhar o castelo em busca de baús de tesouro - e evitar confrontos. + + + O Ladrão de Feitiços drena mana dos inimigos que ele atinge. Isto concede acesso a um suprimento infinito de mana em uma batalha. Demais! + + + A Ladra de Feitiços drena mana dos inimigos que ela atinge. Isto concede acesso a um suprimento infinito de mana em uma batalha. Demais! + + + Mestres da vida e da morte. Os lich possuem um potencial gigantesco. Cada morte concede vida permanente aos Lich (até um limite), tornando-os seres verdadeiramente perigosos. + + + Mestres da vida e da morte. Os lich possuem um potencial gigantesco. Cada morte concede vida permanente aos Lich (até um limite), tornando-os seres verdadeiramente perigosos. + + + Promova seus Cavaleiros para Paladinos. Através de um treinamento rigoroso, os Paladinos aprenderam a bloquear golpes de qualquer direção. + + + Promova suas Cavaleiras para Paladinas. Através de um treinamento rigoroso, as Paladinas aprenderam a bloquear golpes de qualquer direção. + + + Transforme seus míseros Magos em Arquimagos. Domine todas as artes arcanas e mude rapidamente qualquer feitiço que tiver. + + + Transforme suas míseras Magas em Arquimagas. Domine todas as artes arcanas e mude rapidamente qualquer feitiço que tiver. + + + Anel da Hipérion + + + Óbolo de Ponce de Leon + + + Óbolo de Ponce de Leon + + + Óbolo de Heródoto + + + Óbolo de Heródoto + + + Óbolo do Traidor + + + Óbolo do Traidor + + + Anel da Hipérion + + + Botas de Hermes + + + Botas de Hermes + + + Maldição do Ouriço + + + Maldição do Ouriço + + + Óbolo de Caronte + + + Óbolo de Caronte + + + Bússola de Calipso + + + Bússola de Calipso + + + Bênção de Hélio + + + Bênção de Hélio + + + Óculos Nerd + + + Óculos Nerd + + + Óbolo de Khidr + + + Óbolo de Khidr + + + Óbolo de Alexander + + + Óbolo de Alexander + + + Atira um punhal diretamente na sua frente. + + + Invoca uma Grande Lâmina para defendê-lo. + + + Invoca uma Grande Lâmina para defendê-lo. + + + Cerca-o com fogo de proteção. + + + Cerca-a com fogo de proteção. + + + Lança esferas que pulam por toda parte. + + + Lança esferas que pulam por toda parte. + + + Dispara um laser que explode todos que toca. + + + Dispara um laser que explode todos que toca. + + + Lança bolas de fogo em seus inimigos. + + + Lança bolas de fogo em seus inimigos. + + + Dispare uma barragem de punhais. + + + Dispare uma barragem de punhais. + + + Atira um punhal diretamente na sua frente. + + + Lança um machado gigante em um arco. + + + Lança um machado gigante em um arco. + + + Invoca uma bomba que explode depois de um tempo. + + + Invoca uma bomba que explode depois de um tempo. + + + Congela todos os inimigos na tela. + + + Congela todos os inimigos na tela. + + + Atinge todos os inimigos na tela. Caro. + + + Atinge todos os inimigos na tela. Caro. + + + Surge e teletransporta para sua sombra. + + + Surge e teletransporta para sua sombra. + + + Envia um marcador que te teletransporta. + + + Envia um marcador que te teletransporta. + + + Lança um chakram que volta para você. + + + Lança um chakram que volta para você. + + + Envia foices voando por cima de você. + + + Envia foices voando por cima de você. + + + Punhal + + + Parede de Lâminas + + + Parede de Lâminas + + + Barreira de Chamas + + + Barreira de Chamas + + + Confluência + + + Confluência + + + B.E.A.M + + + B.E.A.M + + + Fogo de Dragão + + + Fogo de Dragão + + + Punhal Rápido + + + Punhal Rápido + + + Punhal + + + Machado + + + Machado + + + Bomba + + + Bomba + + + Para Tempo + + + Para Tempo + + + Tempestade de Corvos + + + Tempestade de Corvos + + + Translocador Quantum + + + Translocador Quantum + + + Deslocador + + + Deslocador + + + Chakram + + + Chakram + + + Foice + + + Foice + + + ...Carregando + + + ...Carregando + + + Ferreiro + + + Eu costumava ser uma poderosa feiticeira. Mas, um dia, os monstros deste castelo invadiram meus sonhos e roubaram meu conhecimento. + + + Sem som + + + Sem som + + + Baú encantado + + + Baú encantado + + + O chão é de lava. + + + O chão é de lava. + + + Booyan + + + Booyan + + + Olá! Gostaria de testar sua destreza?\nVocê só tem uma chance, mas é de graça! Se você conseguir, eu vou te dar uma boa recompensa! + + + Olá! Gostaria de testar sua destreza?\nVocê só tem uma chance, mas é de graça! Se você conseguir, eu vou te dar uma boa recompensa! + + + 10 punhais para destruir 8 alvos. Quer tentar? + + + 10 punhais para destruir 8 alvos. Quer tentar? + + + Booyan + + + Booyan + + + Ok, você já se divertiu. Cai fora! + + + Ok, você já se divertiu. Cai fora! + + + Booyan + + + Booyan + + + Eu costumava ser uma poderosa feiticeira. Mas, um dia, os monstros deste castelo invadiram meus sonhos e roubaram meu conhecimento. + + + Eles aprisionaram esse conhecimento em runas, e sem essas runas, sou péssima no meu trabalho. + + + Não vejo esse tanto de rodadas desde ontem na taberna. Como você destruiu todos os alvos, tenho uma pequena recompensa pra você! + + + Não vejo esse tanto de rodadas desde ontem na taberna. Como você destruiu todos os alvos, tenho uma pequena recompensa pra você! + + + Booyan + + + Booyan + + + Você não conseguiu acertar nem 8 alvos?\nPffft. Boa sorte com o resto do castelo. + + + Você não conseguiu acertar nem 8 alvos?\nPffft. Boa sorte com o resto do castelo. + + + Booyan + + + Booyan + + + Olá! Vamos ver o quão boas as suas habilidades são.\nVocê só tem uma chance, mas é de graça! Se você conseguir, eu vou te dar uma boa recompensa! + + + Olá! Vamos ver o quão boas as suas habilidades são.\nVocê só tem uma chance, mas é de graça! Se você conseguir, eu vou te dar uma boa recompensa! + + + Você tem 5 machados para destruir o máximo de alvos possíveis. Deixe menos de 10 em pé e te darei um prêmio especial. Quer tentar? + + + Você tem 5 machados para destruir o máximo de alvos possíveis. Deixe menos de 10 em pé e te darei um prêmio especial. Quer tentar? + + + Booyan + + + Booyan + + + Demais! Você conseguiu deixar menos de 10 alvos! Já que não tenho alvos suficientes para continuar com este trabalho, eu poderia muito bem te dar meu baú de tesouro. + + + Demais! Você conseguiu deixar menos de 10 alvos! Já que não tenho alvos suficientes para continuar com este trabalho, eu poderia muito bem te dar meu baú de tesouro. + + + Eles aprisionaram esse conhecimento em runas, e sem essas runas, sou péssima no meu trabalho. + + + Por favor, Herói, se você encontrar alguma runa, traga-a de volta para mim e então eu a venderei de volta para você com lucro! + + + Booyan + + + Booyan + + + Você deixou mais de 10 alvos em pé.\nAcho que você não quer o prêmio. Ora bolas! + + + Você deixou mais de 10 alvos em pé.\nAcho que você não quer o prêmio. Ora bolas! + + + ??? + + + ??? + + + Saudações, aventureiro. Estou aqui para dar a você a chance de uma vida! + + + Saudações, aventureira. Estou aqui para dar a você a chance de uma vida! + + + Elfo Mesquinho + + + Elfo Mesquinho + + + Pela soma desprezível de 25% do seu ouro atual, te darei a chance de abrir 1 dentre 3 baús. + + + Pela soma desprezível de 25% do seu ouro atual, te darei a chance de abrir 1 dentre 3 baús. + + + Um baú irá triplicar o que você pagou, mas os outros dois estão vazios. + + + Um baú irá triplicar o que você pagou, mas os outros dois estão vazios. + + + Elfo Pão-duro + + + Elfo Pão-duro + + + Quer tentar? + + + Quer tentar? + + + Por favor, Heroína, se você encontrar alguma runa, traga-a de volta para mim e então eu a venderei de volta para você com lucro! + + + Arquiteto + + + ??? + + + ??? + + + Saudações, aventureiro. Estou aqui para dar a você a chance de uma vida! + + + Saudações, aventureira. Estou aqui para dar a você a chance de uma vida! + + + Elfo Mesquinho + + + Elfo Mesquinho + + + Pela soma desprezível de 50% do seu ouro atual, te darei a chance de abrir 1 dentre 3 baús. + + + Pela soma desprezível de 50% do seu ouro atual, te darei a chance de abrir 1 dentre 3 baús. + + + Um baú irá triplicar o que você pagou, mas os outros dois estão vazios. + + + Um baú irá triplicar o que você pagou, mas os outros dois estão vazios. + + + Elfo Pão-duro + + + Elfo Pão-duro + + + Quer tentar? + + + Quer tentar? + + + ??? + + + ??? + + + Saudações, aventureiro. Estou aqui para dar a você a chance de uma vida! + + + Saudações, aventureira. Estou aqui para dar a você a chance de uma vida! + + + Elfo Mesquinho + + + Elfo Mesquinho + + + Arquiteto + + + Sauuudações rapaz! + + + Pela soma desprezível de 75% do seu ouro atual, te darei a chance de abrir 1 dentre 3 baús. + + + Pela soma desprezível de 75% do seu ouro atual, te darei a chance de abrir 1 dentre 3 baús. + + + Um baú irá triplicar o que você pagou, mas os outros dois estão vazios. + + + Um baú irá triplicar o que você pagou, mas os outros dois estão vazios. + + + Elfo Pão-duro + + + Elfo Pão-duro + + + Quer tentar? + + + Quer tentar? + + + Elfo Pão-duro + + + Elfo Pão-duro + + + Você não tem dinheiro suficiente? Você não presta. + + + Você não tem dinheiro suficiente? Você não presta. + + + Elfo Mau Vencedor + + + Elfo Mau Vencedor + + + O que tem na caixa? + + + O que tem na caixa? + + + NADA! + + + NADA! + + + Seu estúpido! Tãããão estúpido! + + + Sua estúpida! Tãããão estúpida! + + + Sauuudações moça! + + + Quer saber uma coisa legal? Eu sou maluuuco! + + + Elfo Mau Perdedor + + + Elfo Mau Perdedor + + + Ha! Você teve sorte desta vez. + + + Ha! Você teve sorte desta vez. + + + Elfo Impaciente + + + Elfo Impaciente + + + Abra logo um baú! + + + Abra logo um baú! + + + Elfo Pão-duro + + + Elfo Pão-duro + + + Desculpe cara, um baú por pessoa. + + + Desculpe moça, um baú por pessoa. + + + Desenvolvedores + + + Desenvolvedores + + + Don't **** Your Pants.\nTempo de desenvolvimento: 2 dias.\nData de lançamento: 16 de fevereiro, 2009 + + + Don't **** Your Pants.\nTempo de desenvolvimento: 2 dias.\nData de lançamento: 16 de fevereiro, 2009 + + + Quer saber uma coisa legal? Eu sou maluuuco! + + + Esta alavanca aqui? Com um simples puxão, eu posso evitar que o castelo mude. + + + Este foi o primeiro jogo que fizemos e naquela época nosso nome era Decade Studios. Nele você tem que impedir um homem de fazer cocô digitando apenas textos. + + + Este foi o primeiro jogo que fizemos e naquela época nosso nome era Decade Studios. Nele você tem que impedir um homem de fazer cocô digitando apenas textos. + + + Ele foi originalmente projetado em um ônibus e decidimos fazê-lo no fim de semana. Tudo rolou muito bem. + + + Ele foi originalmente projetado em um ônibus e decidimos fazê-lo no fim de semana. Tudo rolou muito bem. + + + O nome do jogo tem um palavrão e estávamos pensando em mudá-lo para ser mais amigável. Mas, então, vimos que somos extremamente machos e mantivemos o nome. + + + O nome do jogo tem um palavrão e estávamos pensando em mudá-lo para ser mais amigável. Mas, então, vimos que somos extremamente machos e mantivemos o nome. + + + Uma grande parte do jogo girava em torno de fazer uma aventura textual que permitia que as pessoas digitassem o que quisessem. Para resolver isso, tivemos que antecipar o que nós achávamos que as pessoas iriam escrever. + + + Uma grande parte do jogo girava em torno de fazer uma aventura textual que permitia que as pessoas digitassem o que quisessem. Para resolver isso, tivemos que antecipar o que nós achávamos que as pessoas iriam escrever. + + + Fizemos isso de 2 maneiras. Primeiro, reduzimos a quantidade de opções que um jogador tinha (um homem e uma porta), e em segundo, nós construímos um sistema de conquistas que foi usado para dar direção ao jogador. + + + Fizemos isso de 2 maneiras. Primeiro, reduzimos a quantidade de opções que um jogador tinha (um homem e uma porta), e em segundo, nós construímos um sistema de conquistas que foi usado para dar direção ao jogador. + + + O jogo girava tanto em torno do sistema de conquistas, que foi colocado no jogo através de progressão de tela. Essa foi uma mudança pequena, mas muito importante. + + + O jogo girava tanto em torno do sistema de conquistas, que foi colocado no jogo através de progressão de tela. Essa foi uma mudança pequena, mas muito importante. + + + Desenvolvedores + + + Desenvolvedores + + + Band of Bears\nTempo de desenvolvimento: 4 meses.\nData de lançamento: 6 de agosto, 2009 + + + Band of Bears\nTempo de desenvolvimento: 4 meses.\nData de lançamento: 6 de agosto, 2009 + + + Esta alavanca aqui? Com um simples puxão, eu posso evitar que o castelo mude. + + + Desta forma, você pode passar por exatamente o que seus ancestrais passaram. Impreeeeessionado? Deveria estar. + + + Este foi o segundo jogo que tentamos fazer e era para o concurso DreamBuildPlay 2009. Descobrimos isso muito tarde, por isso tivemos que correr atrás. + + + Este foi o segundo jogo que tentamos fazer e era para o concurso DreamBuildPlay 2009. Descobrimos isso muito tarde, por isso tivemos que correr atrás. + + + Logo depois do sucesso de DSYP, decidimos pensar grande... estupidamente grande. E assim, Cellar Door Games se formou. + + + Logo depois do sucesso de DSYP, decidimos pensar grande... estupidamente grande. E assim, Cellar Door Games se formou. + + + Além de começar um projeto muito além dos nossos recursos e conhecimentos, também tentamos conciliar nossos empregos de tempo integral para conseguir fazer este jogo. Foi mega difícil. + + + Além de começar um projeto muito além dos nossos recursos e conhecimentos, também tentamos conciliar nossos empregos de tempo integral para conseguir fazer este jogo. Foi mega difícil. + + + O jogo apresentava o sistema BEARS (Bare Effort Adaptable Room System), que mudaria os salões dependendo do número de jogadores. + + + O jogo apresentava o sistema BEARS (Bare Effort Adaptable Room System), que mudaria os salões dependendo do número de jogadores. + + + O sistema BEARS não apenas ajustava os números, mas os puzzles também. Acabamos atingindo o Top 20, que era bom, mas não bom o suficiente para ganhar alguma coisa. + + + O sistema BEARS não apenas ajustava os números, mas os puzzles também. Acabamos atingindo o Top 20, que era bom, mas não bom o suficiente para ganhar alguma coisa. + + + Eventualmente, voltamos à realidade (e bom senso) e percebemos que tínhamos de acabar com o projeto, ou no mínimo, colocá-lo em pausa indefinidamente. + + + Eventualmente, voltamos à realidade (e bom senso) e percebemos que tínhamos de acabar com o projeto, ou no mínimo, colocá-lo em pausa indefinidamente. + + + O chefão de demo era super maneiro. + + + O chefão de demo era super maneiro. + + + Desenvolvedores + + + Desenvolvedores + + + Tribal Tallies\nTempo de desenvolvimento: 3 meses.\nData de lançamento: 23 de novembro, 2009 + + + Tribal Tallies\nTempo de desenvolvimento: 3 meses.\nData de lançamento: 23 de novembro, 2009 + + + Desta forma, você pode passar por exatamente o que seus ancestrais passaram. Impreeeeessionada? Deveria estar. + + + Como é que eu construí esta fantástica ennngenhoca? Com ciêêêêência, claro! E magia. + + + Tribal Tallies foi o primeiro projeto no qual trabalhamos após a experiência horrível com Band of Bears. + + + Tribal Tallies foi o primeiro projeto no qual trabalhamos após a experiência horrível com Band of Bears. + + + Foi meio que um projeto de teste, para nos familiarizarmos com jogos iOS, já que nunca tínhamos tentado fazer algo em plataformas móveis antes. + + + Foi meio que um projeto de teste, para nos familiarizarmos com jogos iOS, já que nunca tínhamos tentado fazer algo em plataformas móveis antes. + + + O jogo era simples no conceito, você tocava nos números em sequência o mais rápido que podia. + + + O jogo era simples no conceito, você tocava nos números em sequência o mais rápido que podia. + + + Para apimentar as coisas, implementamos vários modos, como tocar de trás pra frente, números escondidos e combinações. + + + Para apimentar as coisas, implementamos vários modos, como tocar de trás pra frente, números escondidos e combinações. + + + Nós achávamos que a ideia era razoável, mas o jogo acabou levando muito mais tempo para ser feito do que esperávamos. Não ajudou muito tudo ser codificado em um "hackintosh". + + + Nós achávamos que a ideia era razoável, mas o jogo acabou levando muito mais tempo para ser feito do que esperávamos. Não ajudou muito tudo ser codificado em um "hackintosh". + + + Era um jogo bem simples. Poderíamos ter feito melhor, mas estávamos meio inseguros depois de Band of Bears. + + + Era um jogo bem simples. Poderíamos ter feito melhor, mas estávamos meio inseguros depois de Band of Bears. + + + Desenvolvedores + + + Desenvolvedores + + + Q\nTempo de desenvolvimento: 1 mês.\nData de lançamento: 18 de março, 2010 + + + Q\nTempo de desenvolvimento: 1 mês.\nData de lançamento: 18 de março, 2010 + + + Como é que eu construí esta fantástica ennngenhoca? Com ciêêêêência, claro! E magia. + + + ... Magia, principalmente. + + + Nosso quarto projeto. Após Tribal Tallies, tiramos alguns meses de férias dessa história de jogos e focamos apenas em nossos trabalhos de tempo integral. Mas ficamos novamente ansiosos, então decidimos fazer um jogo de puzzle. + + + Nosso quarto projeto. Após Tribal Tallies, tiramos alguns meses de férias dessa história de jogos e focamos apenas em nossos trabalhos de tempo integral. Mas ficamos novamente ansiosos, então decidimos fazer um jogo de puzzle. + + + Nesta altura, a maioria dos fundadores da Cellar Door Games foram em busca de outras oportunidades e os que ficaram são os que compõem a empresa hoje. + + + Nesta altura, a maioria dos fundadores da Cellar Door Games foram em busca de outras oportunidades e os que ficaram são os que compõem a empresa hoje. + + + O jogo usava um mecanismo de enfileiramento de combos para forçar os jogadores a pensarem sobre como os blocos cairiam para formar combos enormes. + + + O jogo usava um mecanismo de enfileiramento de combos para forçar os jogadores a pensarem sobre como os blocos cairiam para formar combos enormes. + + + Ele era gratuito, mas ninguém o baixava também. Após os fracassos de Band of Bears, Tribal Tallies e Q, nos preparamos para fechar a empresa. + + + Ele era gratuito, mas ninguém o baixava também. Após os fracassos de Band of Bears, Tribal Tallies e Q, nos preparamos para fechar a empresa. + + + Desenvolvedores + + + Desenvolvedores + + + My First Quantum Translocator\nTempo de desenvolvimento: 1 mês.\nData de lançamento: 13 de outubro, 2010 + + + My First Quantum Translocator\nTempo de desenvolvimento: 1 mês.\nData de lançamento: 13 de outubro, 2010 + + + My First Quantum Translocator surgiu quando nossa empresa estava em sua pior fase. Depois de 3 jogos fracassados, já estávamos mentalmente exaustos e decidimos fazer este pequeno jogo em flash apenas pela diversão. + + + My First Quantum Translocator surgiu quando nossa empresa estava em sua pior fase. Depois de 3 jogos fracassados, já estávamos mentalmente exaustos e decidimos fazer este pequeno jogo em flash apenas pela diversão. + + + ... Magia, principalmente. + + + Ferreiro + + + Bem-vindo Herói. + + + Mas as minhas habilidades não são grááátis. Se eu bloquear este castelo, vou ficar com 40% de tooodo o ouro que você ganhar! + + + Não tínhamos absolutamente nenhuma expectativa durante o desenvolvimento e foi algo que fizemos mais por diversão do que por qualquer outro motivo. + + + Não tínhamos absolutamente nenhuma expectativa durante o desenvolvimento e foi algo que fizemos mais por diversão do que por qualquer outro motivo. + + + Não é preciso dizer que o jogo fez um enorme sucesso e é a única razão pela qual a Cellar Door Jogos ainda existe. No momento em que lançamos MFQT nós sabíamos que não havia como voltar atrás. + + + Não é preciso dizer que o jogo fez um enorme sucesso e é a única razão pela qual a Cellar Door Jogos ainda existe. No momento em que lançamos MFQT nós sabíamos que não havia como voltar atrás. + + + Curiosamente, a maioria das pessoas acreditam que o jogo foi inspirado em Portal, mas suas semelhanças eram completamente coincidência. + + + Curiosamente, a maioria das pessoas acreditam que o jogo foi inspirado em Portal, mas suas semelhanças eram completamente coincidência. + + + O jogo na verdade, surgiu a partir de um personagem que tínhamos sonhado para o jogo League of Legends. + + + O jogo na verdade, surgiu a partir de um personagem que tínhamos sonhado para o jogo League of Legends. + + + Na verdade, as semelhanças entre Portal e MFQT só começaram a surgir quando adicionamos a arte final e a história no jogo. + + + Na verdade, as semelhanças entre Portal e MFQT só começaram a surgir quando adicionamos a arte final e a história no jogo. + + + De qualquer forma, estávamos muito orgulhosos do jogo. Ele fluía bem e tinha um final agradável. + + + De qualquer forma, estávamos muito orgulhosos do jogo. Ele fluía bem e tinha um final agradável. + + + Desenvolvedores + + + Desenvolvedores + + + I Have 1 Day\nTempo de desenvolvimento: 1,5 mês.\nData de lançamento: 15 de abril, 2011 + + + I Have 1 Day\nTempo de desenvolvimento: 1,5 mês.\nData de lançamento: 15 de abril, 2011 + + + Mas as minhas habilidades não são grááátis. Se eu bloquear este castelo, vou ficar com 40% de tooodo o ouro que você ganhar! + + + + + + Se você nos perguntasse, de todos os jogos que já fizemos, qual seria o nosso favorito, haveria uma escolha unânime do 'I Have 1 Day'. + + + Se você nos perguntasse, de todos os jogos que já fizemos, qual seria o nosso favorito, haveria uma escolha unânime do 'I Have 1 Day'. + + + Nós crescemos jogando clássicos jogos de aventura como Kings Quest e Monkey Island, então isso foi realmente a nossa homenagem a algumas das melhores experiências que já tivemos em jogos. + + + Nós crescemos jogando clássicos jogos de aventura como Kings Quest e Monkey Island, então isso foi realmente a nossa homenagem a algumas das melhores experiências que já tivemos em jogos. + + + O jogo gira em torno de um puzzle de meta-tempo onde o jogador tem apenas 24 horas para vencer o jogo. + + + O jogo gira em torno de um puzzle de meta-tempo onde o jogador tem apenas 24 horas para vencer o jogo. + + + Cada puzzle tinha várias soluções com repercussões de tempo, o que obrigava os jogadores a pensarem na melhor maneira de resolver as coisas. + + + Cada puzzle tinha várias soluções com repercussões de tempo, o que obrigava os jogadores a pensarem na melhor maneira de resolver as coisas. + + + Um fato interessante. O segundo final foi adicionado praticamente no último minuto e sem ele o jogo inteiro teria sido uma porcaria. + + + Um fato interessante. O segundo final foi adicionado praticamente no último minuto e sem ele o jogo inteiro teria sido uma porcaria. + + + Desenvolvedores + + + Desenvolvedores + + + Villainous\nTempo de desenvolvimento: 3 meses.\nData de lançamento: 15 de abril, 2011 + + + Villainous\nTempo de desenvolvimento: 3 meses.\nData de lançamento: 15 de abril, 2011 + + + Villainous foi um dos empreendimentos mais arriscados com o qual nos comprometemos. + + + Villainous foi um dos empreendimentos mais arriscados com o qual nos comprometemos. + + + + + + Você quer bloquear o castelo e ganhar apenas 60% do ouro? + + + O conceito inicial era um jogo de torre de defesa reversa e isso poderia ser uma boa ideia, mas tivemos dificuldade em converter o 'poderia' para 'seria'. + + + O conceito inicial era um jogo de torre de defesa reversa e isso poderia ser uma boa ideia, mas tivemos dificuldade em converter o 'poderia' para 'seria'. + + + A maioria das pessoas que jogaram o jogo acharam que o processo de construção foi algo simples, mas muito estresse e discussões estavam envolvidos neste projeto. + + + A maioria das pessoas que jogaram o jogo acharam que o processo de construção foi algo simples, mas muito estresse e discussões estavam envolvidos neste projeto. + + + Toda a ideia foi abandonada 3 ou 4 vezes antes de nós decidirmos sua versão final. + + + Toda a ideia foi abandonada 3 ou 4 vezes antes de nós decidirmos sua versão final. + + + É irônico que, atualmente, Villainous é de longe um dos nossos jogos de maior sucesso. Ele também foi o mais doloroso. + + + É irônico que, atualmente, Villainous é de longe um dos nossos jogos de maior sucesso. Ele também foi o mais doloroso. + + + Desenvolvedores + + + Desenvolvedores + + + Bullet Audyssey\nTempo de desenvolvimento: 3,5 meses.\nData de lançamento: 29 de novembro, 2009 + + + Bullet Audyssey\nTempo de desenvolvimento: 3,5 meses.\nData de lançamento: 29 de novembro, 2009 + + + Bullet Audyssey foi nosso último jogo antes de trabalharmos em Rogue Legacy. + + + Bullet Audyssey foi nosso último jogo antes de trabalharmos em Rogue Legacy. + + + Por ser um inferno de tiros baseado em ritmos e batidas, Bullet Audyssey foi o jogo mais tecnicamente desafiador com o qual já havíamos trabalhado (sim, ainda mais do que Rogue Legacy). + + + Por ser um inferno de tiros baseado em ritmos e batidas, Bullet Audyssey foi o jogo mais tecnicamente desafiador com o qual já havíamos trabalhado (sim, ainda mais do que Rogue Legacy). + + + Você quer bloquear o castelo e ganhar apenas 60% do ouro? + + + + + + Apenas para criar uma fase foi necessário três editores trabalhando em sincronia. + + + Apenas para criar uma fase foi necessário três editores trabalhando em sincronia. + + + O desenvolvimento deste jogo também foi um pouco não-tradicional, pois bastante pré-planejamento foi necessário para garantir que tudo funcionasse. + + + O desenvolvimento deste jogo também foi um pouco não-tradicional, pois bastante pré-planejamento foi necessário para garantir que tudo funcionasse. + + + Como não somos muito de documentação, não funcionou tão bem pra gente, então tivemos que conversar sobre todo o jogo durante quase metade de um dia. + + + Como não somos muito de documentação, não funcionou tão bem pra gente, então tivemos que conversar sobre todo o jogo durante quase metade de um dia. + + + No jogo, o jogador absorvia tiros inimigos a fim de lançá-los de volta e a absorção acontecia em um ritmo que combinava com a música sendo tocada. + + + No jogo, o jogador absorvia tiros inimigos a fim de lançá-los de volta e a absorção acontecia em um ritmo que combinava com a música sendo tocada. + + + Os testes iniciais foram desastrosos, pois o jogo era muito difícil e as pessoas ficavam incrivelmente frustradas logo no primeiro minuto. + + + Os testes iniciais foram desastrosos, pois o jogo era muito difícil e as pessoas ficavam incrivelmente frustradas logo no primeiro minuto. + + + E por testes, queremos dizer um cara que nem gosta de 'Bullet Hells'. Mas isso já é melhor do que nossos testes de costume. + + + E por testes, queremos dizer um cara que nem gosta de 'Bullet Hells'. Mas isso já é melhor do que nossos testes de costume. + + + O jogo não se saiu muito bem quando foi lançado. Isto nos deu a confiança para fazer o Rogue Legacy! + + + O jogo não se saiu muito bem quando foi lançado. Isto nos deu a confiança para fazer o Rogue Legacy! + + + Confirmar + + + Confirmar + + + Cancelar + + + Cancelar + + + Aviso! + + + Aviso! + + + + + + Você quer bloquear o castelo e ganhar apenas 60% do ouro? + + + Tem certeza que quer iniciar um novo jogo? Todos os dados salvos anteriormente serão apagados. + + + Tem certeza que quer iniciar um novo jogo? Todos os dados salvos anteriormente serão apagados. + + + Restaurar Controles + + + Restaurar Controles + + + Tem certeza de que deseja restaurar de volta para a configurão padrão? + + + Tem certeza de que deseja restaurar de volta para a configurão padrão? + + + + + + + + + Tem certeza de que deseja iniciar uma nova aventura com este herói escolhido? + + + Tem certeza de que deseja iniciar uma nova aventura com este herói escolhido? + + + Resolução alterada + + + Resolução alterada + + + Tem certeza de que deseja jogar nesta resolução?\n(A resolução será revertida em 10 segundos) + + + Tem certeza de que deseja jogar nesta resolução?\n(A resolução será revertida em 10 segundos) + + + Apagar jogo salvo + + + Apagar jogo salvo + + + Tem certeza de que deseja apagar o jogo salvo?\n(Todas as habilidades, aspectos, linhagens e equipamentos serão apagados para SEMPRE) + + + Tem certeza de que deseja apagar o jogo salvo?\n(Todas as habilidades, aspectos, linhagens e equipamentos serão apagados para SEMPRE) + + + Você quer bloquear o castelo e ganhar apenas 60% do ouro? + + + Arquiteto + + + Apagar jogo salvo + + + Apagar jogo salvo + + + Tem certeza ABSOLUTA? (Não pode voltar atrás)\n(Todas as habilidades, aspectos, linhagens e equipamentos serão apagados para SEMPRE) + + + Tem certeza ABSOLUTA? (Não pode voltar atrás)\n(Todas as habilidades, aspectos, linhagens e equipamentos serão apagados para SEMPRE) + + + + + + + + + Tem certeza de que deseja sair e voltar para o menu principal? (Seu status atual será salvo) + + + Tem certeza de que deseja sair e voltar para o menu principal? (Seu status atual será salvo) + + + + + + + + + Tem certeza de que deseja sair do Rogue Legacy? (Seu status atual será salvo) + + + Tem certeza de que deseja sair do Rogue Legacy? (Seu status atual será salvo) + + + Erro no salvamento + + + Erro no salvamento + + + Ah, não! De alguma forma o seu jogo salvo foi corrompido! + + + Ah, não! De alguma forma o seu jogo salvo foi corrompido! + + + Arquiteto + + + Desculpe rapaz, não há castelo para construir neste momento. Este parafuso é apenas parte do cenário. + + + Tentando carregar uma versão de backup do jogo. Esperemos que isto não retroceda muito seu jogo! + + + Tentando carregar uma versão de backup do jogo. Esperemos que isto não retroceda muito seu jogo! + + + Erro no salvamento + + + Erro no salvamento + + + Parece que seu backup também não está funcionando. Por favor entre em contato: support@cellardoorgames.com + Parece que seu backup também não está funcionando. Acredito que teremos que reiniciar o jogo. + + + Parece que seu backup também não está funcionando. Por favor entre em contato: support@cellardoorgames.com + Parece que seu backup também não está funcionando. Acredito que teremos que reiniciar o jogo. + + + Erro no salvamento + + + Erro no salvamento + + + Seu jogo não conseguiu salvar por três vezes seguidas. + + + Seu jogo não conseguiu salvar por três vezes seguidas. + + + Softwares de anti-vírus e programas de backup manual podem entrar em conflito com jogos salvos. Desative qualquer um desses programas antes de executar o jogo. + + + Softwares de anti-vírus e programas de backup manual podem entrar em conflito com jogos salvos. Desative qualquer um desses programas antes de executar o jogo. + + + Desculpe moça, não há castelo para construir neste momento. Este parafuso é apenas parte do cenário. + + + Arquiteto + + + Arquiteto + + + Cara, o castelo já está bloqueado. + + + Moça, o castelo já está bloqueado. + + + Arquiteto + + + Arquiteto + + + Bem-vinda Heroína. + + + Talvez você possa me ajudar. Eu costumava ser o maior ferreiro de toda a região. Mas, um dia, os monstros deste castelo atacaram minha forja e roubaram todos os meus projetos. + + + Diviiiirta-se! Talvez você possa encontrar alguns tesoouros que seus antepassados não viram! + + + Diviiiirta-se! Talvez você possa encontrar alguns tesoouros que seus antepassados não viram! + + + Caronte + + + Caronte + + + ... É necessário pagar o preço. + + + ... É necessário pagar o preço. + + + + + + + + + (Dar ao Caronte todo o seu dinheiro e entrar no castelo?) + + + (Dar ao Caronte todo o seu dinheiro e entrar no castelo?) + + + + + + + + + (Dar ao Caronte todo o seu dinheiro e entrar no castelo?) + + + (Dar ao Caronte todo o seu dinheiro e entrar no castelo?) + + + + + + + + + (Dar ao Caronte 90% do seu dinheiro e entrar no castelo?) + + + (Dar ao Caronte 90% do seu dinheiro e entrar no castelo?) + + + + + + + + + Talvez você possa me ajudar. Eu costumava ser o maior ferreiro de toda a região. Mas, um dia, os monstros deste castelo atacaram minha forja e roubaram todos os meus projetos. + + + Sem esses projetos, só consigo fazer talheres e outras coisinhas. + + + (Dar ao Caronte 80% do seu dinheiro e entrar no castelo?) + + + (Dar ao Caronte 80% do seu dinheiro e entrar no castelo?) + + + + + + + + + (Dar ao Caronte 70% do seu dinheiro e entrar no castelo?) + + + (Dar ao Caronte 70% do seu dinheiro e entrar no castelo?) + + + + + + + + + (Dar ao Caronte 60% do seu dinheiro e entrar no castelo?) + + + (Dar ao Caronte 60% do seu dinheiro e entrar no castelo?) + + + + + + + + + (Dar ao Caronte 50% do seu dinheiro e entrar no castelo?) + + + (Dar ao Caronte 50% do seu dinheiro e entrar no castelo?) + + + Caronte + + + Caronte + + + Ah ha ha! Então você tem meu óbolo. Vou deixá-lo passar de graça, mas só desta vez. + + + Ah ha ha! Então você tem meu óbolo. Vou deixá-la passar de graça, mas só desta vez. + + + Caronte + + + Caronte + + + Sem esses projetos, só consigo fazer talheres e outras coisinhas. + + + Por favor, traga de volta os projetos que você encontrar para que eu possa construir os equipamentos mais incríveis. DE TODA A HISTÓRIA. + + + Ah ha! Este é um óbolo muito especial. + + + Ah ha! Este é um óbolo muito especial. + + + Me dê o mesmo e deixarei sua alma passar pelos outros portões. + + + Me dê o mesmo e deixarei sua alma passar pelos outros portões. + + + (Dar o óbolo para Caronte e pagar sua taxa?) + + + (Dar o óbolo para Caronte e pagar sua taxa?) + + + Caronte + + + Caronte + + + Ah ha! Este é um óbolo muito especial. + + + Ah ha! Este é um óbolo muito especial. + + + Me dê o mesmo e deixarei sua alma passar pelos outros portões. + + + Me dê o mesmo e deixarei sua alma passar pelos outros portões. + + + (Dar o óbolo para Caronte e pagar sua taxa?) + + + (Dar o óbolo para Caronte e pagar sua taxa?) + + + Caronte + + + Caronte + + + Ah ha! Este é um óbolo muito especial. + + + Ah ha! Este é um óbolo muito especial. + + + Me dê o mesmo e deixarei sua alma passar pelos outros portões. + + + Me dê o mesmo e deixarei sua alma passar pelos outros portões. + + + Por favor, traga de volta os projetos que você encontrar para que eu possa construir os equipamentos mais incríveis. DE TODA A HISTÓRIA. + + + ... Por um preço, lógico. + + + (Dar o óbolo para Caronte e pagar sua taxa?) + + + (Dar o óbolo para Caronte e pagar sua taxa?) + + + Caronte + + + Caronte + + + Ah ha! Este é um óbolo muito especial. + + + Ah ha! Este é um óbolo muito especial. + + + Me dê o mesmo e deixarei sua alma passar pelos outros portões. + + + Me dê o mesmo e deixarei sua alma passar pelos outros portões. + + + (Dar o óbolo para Caronte e pagar sua taxa?) + + + (Dar o óbolo para Caronte e pagar sua taxa?) + + + Caronte + + + Caronte + + + Ah... Você não deveria ter pego este óbolo. + + + Ah... Você não deveria ter pego este óbolo. + + + Prepare-se. + + + Prepare-se. + + + (Dar o óbolo para Caronte e pagar sua taxa?) + + + (Dar o óbolo para Caronte e pagar sua taxa?) + + + Santuário Espiritual + + + Santuário Espiritual + + + ... Por um preço, lógico. + + + Feiticeira + + + Você irá orar por ajuda? + + + Você irá orar por ajuda? + + + Último Chefão + + + Último Chefão + + + Bem-vindo herói! Fiquei muito impressionado por você ter chegado tão longe. Infelizmente, este será o mais longe que chegará! + + + Bem-vinda heroina! Fiquei muito impressionado por você ter chegado tão longe. Infelizmente, este será o mais longe que chegará! + + + Baú encantado - Nada + + + Baú encantado - Nada + + + SEM TEXTO + + + SEM TEXTO + + + Derrote todos os inimigos + + + Derrote todos os inimigos + + + + + + + + + Vida baixa + + + Vida baixa + + + + + + + + + Sem olhar + + + Sem olhar + + + Feiticeira + + + Olá Herói. + + + + + + + + + Sem saltar + + + Sem saltar + + + + + + + + + Sem barulho + + + Sem barulho + + + + + + + + + Não toque no chão + + + Não toque no chão + + + + + + + + + Sem lutar + + + Sem lutar + + + + + + + + + Alcance-me a tempo + + + Alcance-me a tempo + + + Olá Heroína. + + + Eu poderia falar com você um instante? Estou precisando da sua ajuda. + + + + + + + + + Não receba dano + + + Não receba dano + + + + + + + + + Me encontre + + + Me encontre + + + + + + + + + Baú encantado + + + Baú encantado + + + Não olhe para mim! + + + Não olhe para mim! + + + Baú encantado + + + Baú encantado + + + Sem saltar + + + Sem saltar + + + Baú encantado + + + Baú encantado + + + Eu poderia falar com você um instante? Estou precisando da sua ajuda. + + + Pressione [Input:12] para atacar + + + Pressione [Input:12] para atacar + + + Continue sua busca + + + Continue sua busca + + + Escolha seu herdeiro + + + Escolha seu herdeiro + + + Inicie seu legado + + + Inicie seu legado + + + Treine comigo! + + + ISSO DÓIIII + + + ISSO DÓIIII + + + Ui + + + Ui + + + Ai + + + Ai + + + AAAIIII + + + AAAIIII + + + Eu desisto! + + + Eu desisto! + + + Tá bombado! + + + Tá bombado! + + + Ok, essa doeu + + + Ok, essa doeu + + + Isso faz cócegas + + + Isso faz cócegas + + + E aí, acabou? + + + E aí, acabou? + + + Ei! Pega leve! + + + Ei! Pega leve! + + + Treine comigo! + + + Ai Deus! + + + Boa tentativa + + + Boa tentativa + + + Fraco + + + Fraco + + + Tente de novo + + + Tente de novo + + + Ai Deus! + + + Que dor! + + + Que dor! + + + Dói demais + + + Dói demais + + + PARE!! + + + PARE!! + + + O que te fiz? + + + O que te fiz? + + + POR QUÊ??? + + + POR QUÊ??? + + + Pare com isso! + + + Pare com isso! + + + Ainda te pego! + + + Ainda te pego! + + + Você não consegue ver cores devido à monocromacia. + + + Você é magrelo, então cada ataque te joga longe. + + + Você é magrela, então cada ataque te joga longe. + + + Você tem dificuldade para lembrar onde está. + + + Você tem dificuldade para lembrar onde está. + + + Seus valores de MP e HP estão invertidos. Quem imaginaria? + + + Seus valores de MP e HP estão invertidos. Quem imaginaria? + + + %#&@! + + + %#&@! + + + Tão energético! Você se move mais rápido. + + + Tão energética! Você se move mais rápido. + + + Preciso. Limpar. A casa. Quebra coisas para restaurar MP. + + + Preciso. Limpar. A casa. Quebra coisas para restaurar MP. + + + Você é ultra bombado. Os ataques nocauteiam ainda mais os inimigos. + + + Você é ultra bombada. Os ataques nocauteiam ainda mais os inimigos. + + + Você tem membros fracos. Você não conseguirá empurrar os inimigos. + + + Você tem membros fracos. Você não conseguirá empurrar os inimigos. + + + Você não consegue ver em 3D. + + + Você não consegue ver em 3D. + + + Até mesmo os heróis mais valentes podem sofrer de intestino irritável. + + + Até mesmo os heróis mais valentes podem sofrer de intestino irritável. + + + Você não consegue ver cores devido à monocromacia. + + + Você gosta das moças. + + + Bem-vindo à Vomitolândia. + + + Bem-vindo à Vomitolândia. + + + Sem visão periférica. + + + Sem visão periférica. + + + Você tem duas mãos esquerdas e não consegue lançar feitiços corretamente. + + + Você tem duas mãos esquerdas e não consegue lançar feitiços corretamente. + + + Doença arterial periférica. Sem pulso no pé. + + + Doença arterial periférica. Sem pulso no pé. + + + As galinhas te assustam. + + + As galinhas te assustam. + + + Você tende a EXAGERAR. + + + Você tende a EXAGERAR. + + + Você é louco. + + + Você é louca. + + + Você é bem flexível. + + + Você é bem flexível. + + + Você se lembra de coisas com extrema clareza. + + + Você se lembra de coisas com extrema clareza. + + + Você sente falta dos bons velhos tempos. + + + Você sente falta dos bons velhos tempos. + + + Você é fã dos homens. + + + Você é fã dos homens. + + + Você gosta das moças. + + + Qualquer coisa muito longe fica embaçada. + + + Insensibilidade congênita à dor. Não conhece dor alguma. + + + Insensibilidade congênita à dor. Não conhece dor alguma. + + + Você tem muito talento. Mas com alguns probleminhas. + + + Você tem muito talento. Mas com alguns probleminhas. + + + Não há colher. Nem garfo. + + + Não há colher. Nem garfo. + + + Você quebra muitas coisas. + + + Você quebra muitas coisas. + + + Você conduz eletricidade muito bem. + + + Você conduz eletricidade muito bem. + + + Está tão escuro. + + + Está tão escuro. + + + Qualquer coisa muito longe fica embaçada. + + + Qualquer coisa de perto fica embaçada. + + + Qualquer coisa de perto fica embaçada. + + + Você tme poblemra pra lre cosias. + + + Você tme poblemra pra lre cosias. + + + Você nasceu para ser um jogador de basquete. + + + Você nasceu para ser uma jogadora de basquete. + + + Você nunca consegue andar em montanhas-russas. + + + Você nunca consegue andar em montanhas-russas. + + + É do careca que elas gostam mais. + + + É das carecas que eles gostam mais. + + + Você é tão pesado que os inimigos não conseguem te empurrar. + + + Você é tão pesada que os inimigos não conseguem te empurrar. + + + Você não consegue ver as cores. + + + Os golpes te jogam longe. + + + Os golpes te jogam longe. + + + Onde está você? + + + Onde está você? + + + Valores de MP + HP invertidos. + + + Valores de MP + HP invertidos. + + + %#&@! + + + %#&@! + + + Você se move mais rápido. + + + Você se move mais rápido. + + + Quebra coisas para restaurar MP. + + + Quebra coisas para restaurar MP. + + + Você super nocauteia os inimigos. + + + Você super nocauteia os inimigos. + + + Você não consegue empurrar inimigos. + + + Você não consegue empurrar inimigos. + + + Você não consegue ver em 3D. + + + Você não consegue ver em 3D. + + + Você peida muito. + + + Você peida muito. + + + Você não consegue ver as cores. + + + Você gosta das moças. + + + Tudo está de cabeça para baixo. + + + Tudo está de cabeça para baixo. + + + Sem indicadores + + + Sem indicadores + + + Os feitiços saem das suas costas. + + + Os feitiços saem das suas costas. + + + Sem pulso no pé. + + + Sem pulso no pé. + + + Você tem medo de galinhas. + + + Você tem medo de galinhas. + + + Exagera o dano que você toma. + + + Exagera o dano que você toma. + + + Você vê coisas que não existem. + + + Você vê coisas que não existem. + + + Você se vira quando luta. + + + Você se vira quando luta. + + + Memoriza a localização do inimigo. + + + Memoriza a localização do inimigo. + + + Tudo tem cara de antiquado. + + + Tudo tem cara de antiquado. + + + Você é fã dos homens. + + + Você é fã dos homens. + + + Você gosta das moças. + + + Qualquer coisa muito longe fica embaçada. + + + Barra de vida não visível. + + + Barra de vida não visível. + + + Feitiços randomizados. + + + Feitiços randomizados. + + + Não há colher. Nem garfo. + + + Não há colher. Nem garfo. + + + Você quebra coisas e não tem equilíbrio. + + + Você quebra coisas e não tem equilíbrio. + + + As plataformas ficam abertas. + + + As plataformas ficam abertas. + + + Está tão escuro. + + + Está tão escuro. + + + Qualquer coisa muito longe fica embaçada. + + + Qualquer coisa de perto fica embaçada. + + + Qualquer coisa de perto fica embaçada. + + + Você tme poblemra pra lre cosias. + + + Você tme poblemra pra lre cosias. + + + Você é enorme. + + + Você é enorme. + + + Você é minúsculo. + + + Você é minúscula. + + + Você é careca. + + + Você é careca. + + + Não pode ser empurrado. + + + Não pode ser empurrada. + + + Daltônico + + + Ectomorfo + + + Ectomorfa + + + Alzheimer + + + Alzheimer + + + Dextrocardia + + + Dextrocardia + + + Coprolalia + + + Coprolalia + + + TDAH + + + TDAH + + + TOC + + + TOC + + + Hipergonad. + + + Hipergonad. + + + Fraq. Muscular + + + Fraq. Muscular + + + Ceg. Estéreo + + + Ceg. Estéreo + + + SCI + + + SCI + + + Daltônica + + + Gay + + + Vertigem + + + Vertigem + + + Visão de Túnel + + + Visão de Túnel + + + Ambiesquerdo + + + Ambiesquerda + + + P.A.D. + + + P.A.D. + + + Aletrorofobia + + + Aletrorofobia + + + Hipocondria + + + Hipocondria + + + Demência + + + Demência + + + Flexível + + + Flexível + + + Memória Fotográfica + + + Memória Fotográfica + + + Nostálgico + + + Nostálgica + + + Gay + + + Míope + + + C.I.P. + + + C.I.P. + + + Sábio + + + Sábia + + + O Escolhido + + + A Escolhida + + + Desajeitado + + + Desajeitada + + + EHS + + + EHS + + + Glaucoma + + + Glaucoma + + + Míope + + + Hipermétrope + + + Hipermétrope + + + Dislexia + + + Dislexia + + + Gigantismo + + + Gigantismo + + + Nanismo + + + Nanismo + + + Calvície + + + Calvície + + + Endomorfo + + + Endomorfa + + + Desenvolvido por + + + Desenvolvido por + + + Design + + + Design + + + Programação + + + Programação + + + Produção + + + Produção + + + Arte + + + Arte + + + Música e design de som + + + Música e design de som + + + Música + + + Música + + + + + + + + + Ataque para baixo este + + + Ataque para baixo este + + + Toque em [Input:11] para saltar + + + Toque em [Input:11] para saltar + + + Segure [Input:11] para saltar mais alto + + + Segure [Input:11] para saltar mais alto + + + Toque em [Input:12] para atacar + + + Toque em [Input:12] para atacar + + + Segure [Input:19] e toque em [Input:11] para\ndescer das bordas + + + Segure [Input:19] e toque em [Input:11] para\ndescer das bordas + + + (Ar) Segure [Input:19] e toque em [Input:12] para\natacar para baixo + + + (Ar) Segure [Input:19] e toque em [Input:12] para\natacar para baixo + + + Toque em [Input:10] para saltar + + + Toque em [Input:10] para saltar + + + Segure [Input:10] para saltar mais alto + + + Segure [Input:10] para saltar mais alto + + + Toque em [Input:12] para atacar + + + Toque em [Input:12] para atacar + + + Segure [Input:18] e toque em [Input:10] para descer das bordas + + + Segure [Input:18] e toque em [Input:10] para descer das bordas + + + (Ar) Segure [Input:18] e toque em [Input:12] para atacar para baixo + + + (Ar) Segure [Input:18] e toque em [Input:12] para atacar para baixo + + + Programação adicional + + + Adaptação por + + + Doar {0} de ouro e fortalecer permanentemente o seu espectro contra este chefão?\nVezes fortalecido: {1} + + + Esta caixa de doação está cheia até a borda.  Não é possível fortalecer o seu espectro ainda mais.  Obrigado pela contribuição. + + + Você não pode doar. Volte quando tiver obtido mais ouro. + + + O seu espectro ficou mais forte! + + + Caixa de doação + + + {1} {0} + + + Desbloquear traidor + + + Cofre + + + Maldição + + + Graças + + + Taxa do arquiteto + + + Bônus NG+ + + + Arrancada + + + Vampiro + + + Céu + + + Sifão + + + Equilíbrio + + + Retaliação + + + Recompensa + + + Aceleração + + + {1} {0} + + + Produção e localização japonesa por + + + Garantia de qualidade + + + Você tem espasmos musculares aleatórios. + + + Você não consegue distinguir as pessoas. + + + Clonus + + + Prosopagnosia + + + Maldição + + + Graças + + + Taxa do arquiteto + + + Bônus NG+ + + + Cofre + + + Arrancada + + + Vampiro + + + Céu + + + Sifão + + + Equilíbrio + + + Retaliação + + + Recompensa + + + Aceleração + + + Você tem espasmos musculares aleatórios. + + + Você não consegue distinguir as pessoas. + + + Clonus + + + Prosopagnosia + + + Ganhe 60% de ouro total no castelo. + + + Ganhe 60% de ouro total no castelo. + + + Desbloquear traidor + + + Full Metal Furies\nTempo de desenvolvimento: 4 anos.\nData de lançamento: 17 de janeiro de 2018 + + + Full Metal Furies é do futuro! É nosso jogo de sequência após Rogue Legacy e o décimo jogo já feito por nós. + + + Depois de RL, nós nos prometemos que nunca mais faríamos um jogo sem planejamento de novo. E a gente mentiu. Culpa dos seus eus passados! + + + O jogo acabou se tornando um dos nossos projetos mais ambiciosos, e foi um misto de ideias de luta/multiplayer/meta-puzzle/disco adulto que virou a visão tradicional do combate de cabeça para baixo quanto mais se jogava. + + + Com 4 anos, o FMF é o maior tempo que já passamos desenvolvendo, e infelizmente também um dos menores retornos que já vimos dos nossos jogos. (Exceto aqueles jogos de iOS que geraram grana negativa.) + + + Mas mesmo assim temos imenso orgulho do que criamos e ainda mais orgulho dos AMIGOS QUE FIZEMOS PELO CAMINHO! OOOOHHHHHH!!! + + + Direitos autorais (C) 2013-2018, Cellar Door Games Inc. + + + {0} é uma marca registrada Cellar Door Games Inc. Todos os direitos reservados. + + \ No newline at end of file diff --git a/RogueCastle/Resources/LocStrings.resx b/RogueCastle/Resources/LocStrings.resx new file mode 100644 index 0000000..8bda305 --- /dev/null +++ b/RogueCastle/Resources/LocStrings.resx @@ -0,0 +1,4978 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + The castle has been conquered [x] times worldwide. + + + [x] monsters have been slain worldwide. + + + has slain [x] monsters + + + [x] clowns have been bested worldwide. + + + [x] farts have been farted worldwide. + + + has sent [x] [y] into the castle. + + + [x] random castles have been generated worldwide. + + + has conquered the castle [x] times. + + + [x] gold has been given to Charon worldwide. + + + has have given [x] gold to Charon. + + + [x] heroes have fallen to the Castle worldwide. + + + [x] heroes have been slain by [y] worldwide. + + + [x] has been defeated [y] times worldwide. + + + greatest family defeated [x] with [y] children + + + greatest family conquered the castle with [x] children + + + Quit to Title Screen + + + Quit to Title Screen (skip tutorial) + + + to Change Profile + + + Health + + + Arrow keys to navigate + + + to navigate + + + [Button:LeftStick] to navigate + + + Select a category + + + Blueprint needed + + + Purchase Info Here + + + None + + + to unlock + + + Mana + + + Damage + + + Magic + + + Armor + + + Weight + + + Additional Properties: + + + select/equip + + + [Input:0] select/equip + + + cancel/close menu + + + [Input:2] cancel/close menu + + + Targets Destroyed + + + Targets Remaining + + + Reward + + + gold + + + view map any time + + + Change Controls + + + Dash Right + + + Cast Spell + + + Reset Controls + + + Press Any Button + + + Press Any Key + + + Up + + + Down + + + Left + + + Right + + + Attack + + + Jump + + + Special + + + Dash Left + + + Your standard hero. Pretty good at everything. + + + A walking tank. This hero can take a beating.\nSPECIAL: Barbarian Shout. + + + A fast hero. Deal massive damage, but you cannot crit. + + + A fast hero. Deal massive damage, but you cannot crit.\nSPECIAL: Replacement Technique. + + + A hero for experts. Hit enemies to restore mana. + + + A hero for experts. Hit enemies to restore mana.\nSPECIAL: Empowered Spell. + + + Feed off the dead. Gain permanent life for every kill up to a cap. Extremely intelligent. + + + Feed off the dead. Gain permanent life for every kill up to a cap. Extremely intelligent.\nSPECIAL: HP Conversion. + + + You are a man-dragon + + + ????? + + + Your standard hero. Pretty good at everything.\nSPECIAL: Guardians Shield. + + + A risky hero. Low stats but can land devastating critical strikes. + + + A risky hero. Low stats but can land devastating critical strikes.\nSPECIAL: Mist Form. + + + A hero for hoarders. Very weak, but has a huge bonus to gold. + + + A hero for hoarders. Very weak, but has a huge bonus to gold.\nSPECIAL: Ordinary Headlamp. + + + A powerful spellcaster. Every kill gives you mana. + + + A powerful spellcaster. Every kill gives you mana.\nSPECIAL: Spell Cycle. + + + A walking tank. This hero can take a beating. + + + Barbarian Queen + + + Barbarian King + + + Shinobi + + + Hokage + + + Spellthief + + + Spellthief + + + Spellsword + + + Spellsword + + + Lich + + + Lich Queen + + + Lich King + + + Dragon + + + Dragon + + + Traitor + + + Traitor + + + Knight + + + Knight + + + Paladin + + + Paladin + + + Knave + + + Knave + + + Assassin + + + Assassin + + + Miner + + + Miner + + + Spelunkette + + + Spelunker + + + Mage + + + Mage + + + Archmage + + + Archmage + + + Barbarian + + + Barbarian + + + Connection to "PSN" lost, Cross-Save will be unavailable. + + + You are currently not connected to "PSN". Cross-Save data will not be synced online until you reconnect. + + + Your local save data is older than the currently uploaded Cross-Save data. Do you wish to upload save data? If you select ''NO'' the currently uploaded Cross-Save data will be downloaded. + + + Your local save data is newer than the currently uploaded Cross-Save data. Do you wish to download the Cross-Save data? If you select ''NO'' your local save data will be uploaded as your Cross-Save data. + + + Cross-Save is disabled on your Sony Entertainment Network account due to parental control restrictions + + + Cross-Save synchronization is disabled on your Sony Entertainment Network account due to parental control restrictions. + + + Sync Cross-Save data now + + + Cross-Save succeeded + + + Automatic Cross-Save Sync + + + Thanks for playing! + + + Art + + + Music & Audio Design + + + Music + + + Marketing & Story + + + Additional Audio Design + + + Additional Background Art + + + Business Support + + + Super Special Thanks: Turbo Edition + + + Special Thanks + + + Additional Thanks + + + Total Children + + + Mac/Linux Adaptation by + + + Mac/Linux QA Team + + + Thanks to all our fans for their support! + + + Time Played + + + Press + + + Press [Input:0] to exit + + + to exit + + + Developed By + + + Design & Story + + + Programming + + + Production + + + Joystick Dead Zone + + + Delete Save + + + Yes + + + No + + + Prince's Journal + + + Although I am the eldest child, I am not my father's favorite. I have always known he planned to leave me with nothing. + + + ...And what if I mistook them for a monster? + + + Prince's Journal + + + Journal Entry #17 + + + I must be going insane. I stumbled across a carnival inside this castle. Complete with a sad clown and everything. + + + He's sort of an ass. But I guess you can't be picky with your friends in a place like this. + + + I'm getting hungry again. Good thing I topped up on chicken legs. I found these in a chandelier. + + + This castle... Sometimes I wonder if it's all just a big joke. + + + Prince's Journal + + + Journal Entry #18 + + + I have bested the beast of the tower, and once again I could feel the throne room give up some of its power. + + + But if I find the cure, everything will change. + + + The rush I feel from this victory is intoxicating! Never have I felt so confident, so powerful, so...at home. Just a little further and I will be able to earn my reward! + + + I'm so close! I will make my father proud! + + + Prince's Journal + + + Journal Entry #19 + + + I have been standing outside the dungeon gate for longer then I care to admit. + + + My courage has finally been sapped, for I have spied the monsters below, and they make my previous struggles laughable in comparison. + + + I must steel myself. I must focus. There is so little light down there, I fear that I may lose myself. + + + Prince's Journal + + + Journal Entry #20 + + + I thought I knew what darkness was, but here in the dungeon, the darkness has a voice. + + + The victor will earn nothing less than the throne upon his passing! + + + It calls at me through grates, and around corners. It taunts me. + + + The darkness is so thick, it is almost tangible, and the beasts here have made it their home. They move swiftly through the corridors, and are more terrifying then anything I've fought before. + + + I must be prudent and choose my battles carefully. Being confrontational now may cost me my life. + + + Prince's Journal + + + Journal Entry #21 + + + I have done it! I have defeated the dungeon's master! All that remains is to enter the throne room. + + + After this, the king will honor me for my valor and acknowledge me as rightful successor to the throne! + + + Not my faceless siblings! + + + Prince's Journal + + + Journal Entry #22 + + + Upon my ascension, my wife and my children shall move back into the royal quarters. Back to the royal city, where we once again will be treated with the respect we deserve! + + + I sit here making my final preparations. All that lays between me and the lord of this castle is the golden doors. + + + There is an nervousness in my body that I cannot quell. Is this fear, or fearcitement? All I know is that my journey is finally reaching an end. + + + I have almost forgotten why I entered this castle in the first place, but I remember now. + + + I have bested my siblings, I will save the king, and leave this castle a greater man then when I entered. My family will get the honor they so rightfully deserve. + + + Now, I enter the throne room. + + + Prince's Journal + + + Journal Entry #23 + + + I never knew what treasure lay in this castle. I knew only that it would cure the king. + + + Who could have suspected it would be the fountain of youth? + + + I expected a monster to greet me at the dias; a foe of unimaginable strength. I imagined it would take all my strength to best him. + + + No longer will we stand for the gossip and petty slander of my cousins. The other dukes shall bow as we pass! But I am getting ahead of myself. + + + But when I entered the castle and saw my father - the king - sitting atop the dias with goblet in hand, I knew all was lost. + + + He would never die... + + + ...and I would never be heir. + + + There are no words to express what I feel. + + + Prince's Journal + + + Journal Entry #24 + + + .............................. + + + .... + + + Prince's Journal + + + Journal Entry #25 + + + I must keep my priorities clear: Conquer the castle. Find the cure. Collect my reward. + + + Today marks the rest of eternity. + + + I never knew what treasure lay in this castle. Just that it would cure the king of his illness. + + + ... Who would have known it would have been the fountain of youth? A myth, which grants one eternal life. + + + As I look down on the body of the king I realize that it is inevitable: children will always answer for their father's sins. + + + I entered this castle a swordsman, a savior... + + + But all I have left is a rogue's legacy. + + + I can feel your anger, but know it was not I who sent your family to ruin. + + + The moment the king set foot within this castle, the royal coffers were emptied by Charon. My family - all families - had lost all hope for a better life. + + + And in my mind's eye, I foresaw only desperation and poverty ravage the country. There was nothing for me to go back to. + + + To my children, and my children's children, here I sit, impassive, immortal, and await thee. + + + Prince's Journal + + + Johannes + + + What is this? Are you... mocking me?! + + + After countless generations of your ancestors sacrificed their lives to be where you are now, the final steps to achieving their hollow justice. And you arrive and mock me? + + + Very well, I will spare your ignorance. Let us begin! + + + Johannes + + + Why do you wish to fight me? How many sons and daughters have been lost in your pathetic attempts at revenge? + + + It was the king who brought ruin to your country, not I! + + + He lied to us. He said he was wounded, yet it was only time that threatened him! + + + He pitted his children against one another, sacrificed everything to satisfy his own selfish desires, and in the end, left us penniless and alone. + + + So I took the only option left to me. I rejected king and country... + + + Journal Entry #3 + + + And chose a new family instead! + + + Johannes + + + You think you have slain me? + + + I have lived for over a thousand years, and I will live for ten thousand more! + + + Alexander... Khidr... Ponce De Leon... + + + I was not the first hero to reach the fountain... + + + But I will be the last! + + + Fountain of Youth + + + ... + + + You have defeated me... But at what price? + + + I have paid my dues, and entered the castle proper. That devil Charon has taken all that I own as payment. + + + I may have slain the king, but only after he betrayed his people. + + + Ask yourself what justice has been met? + + + In the end we are all guilty of the same sin. Look to your forefathers - such is the cost for unquestioned loyalty. + + + ... + + + ... + + + The sun... + + + I had forgotten how it feels... + + + He has even pilfered my private coffers! I have left my wife and children with nothing. + + + Journal Entry #1 + + + He says it's the price for any and all who hazard the depths of the castle. He says it is fair. + + + It is fair because of all who have entered, none have returned. But I will change that. + + + I will be victorious! There is no greater swordsman than I, even amongst my siblings. + + + Prince's Journal + + + Journal Entry #4 + + + Everything about this castle is off. I can't seem to keep track of my headings, and there is no sun or stars to guide me. + + + I find myself backtracking constantly, and I must painstakingly map out my progress lest I go in circles. + + + The maps I have pilfered off the corpses of other adventurers are breathtakingly inaccurate. It is almost as if they were describing a different castle altogether! + + + Perhaps this place does something to the mind... + + + Or are the stones truly shifting beneath my feet? + + + Treason! An assassin has wounded my father, the king! + + + Prince's Journal + + + Journal Entry #5 + + + I cannot exit through the front gate, but that is of little concern. I am committed to my cause and will not back out! + + + So far none of the maps I've found coincide with my own. + + + Yet upon comparing them as a whole, I believe I have unearthed a slight pattern. It seems the forest is always to the right; the tower above... + + + And below? Well, hopefully I won't have to find out. + + + Prince's Journal + + + Journal Entry #6 + + + I have never liked the dark. I prefer to meet my enemies on an open field in plain sight. + + + But now I find myself braving these darkened gallows with one gauntlet outstreched, the other by my hilt. I can never tell what horror lies beyond each corner. + + + To bring order back to the kingdom, he has sent my siblings and I on a quest to save him. Together, we will venture into the cursed woods, and enter Castle Hamson. + + + I am the greatest swordsman in all the lands, yet even I am having trouble keeping these demons at bay. + + + My siblings should be grateful that I rushed ahead of them. For them it was a blessing in disguise. They would not have the fortitude to survive these halls. + + + Prince's Journal + + + Journal Entry #7 + + + It is still night. Past every window stares back the same melancholic moon, but I swear I have been here for at least a whole waking day. + + + It must be the adrenaline. I have never felt so powerful, yet simultaneously challenged. It is exhilarating to charge through these rooms, cutting down enemy after enemy. + + + In some ways the foes in this castle feel tailored to me. Training me, guiding me, watching me. + + + This may sound crazy, but if this castle can somehow sense those within it, I fear it may hold malicious intent as well. If my assumptions are correct, the design of these halls could all be a ploy, culling me down further into a trap. + + + I must stay alert. + + + Prince's Journal + + + This cursed castle has stood on the edge of the woods since time immemorial, but rumors say that within it dwells an item which will cure any ailment. + + + Journal Entry #8 + + + From the number of dead adventurers I have passed in these halls, I have come to the following conclusions: + + + 1: Many did not take enough provisions with them. I assume many died of hunger. I myself am running low and will have to find more supplies. + + + 2: Many are missing clothes, which explains the pant-wearing zombies. + + + 3: No one has made it as far as I, since I haven't passed any corpses in over an hour. + + + Prince's Journal + + + Journal Entry #9 + + + The door to the throne room is driving me mad! Beyond it lies the king's salvation, and my reward, but it stands silent in the middle of the castle foyer, taunting me. + + + I've tried pushing it, kicking it, yelling "Open Sesame", but nothing works. + + + There are icons emblazoned into the doors, and one of them looks like a beast I avoided deeper in the castle. Perhaps there is some sort of correlation? + + + Tonight I will get a headstart over my brothers and sisters, and set forth on my quest while they lay asleep. + + + Prince's Journal + + + Journal Entry #10 + + + The emblems on the castle door are a clue! I slew the giant beast that matched one of the icons, and I sensed something shift behind the throne room doors. + + + As if in a dream, I could see an emblem on the door glowing in my mind's eye. + + + A truly out of body experience. + + + At least I know I'm on the right track. But I must hasten my pace, for the king could succumb to his injuries at any moment... + + + But first I must rest. Tomorrow, I enter the Forest. + + + Prince's Journal + + + Journal Entry #11 + + + This forest is unlike anything I've ever seen before. It is both serene and terrifying. I stand on lush grass, but beside me yawns open a chasm so wide and deep, it threatens to swallow me whole. + + + To fail this quest would be an embarrassment to my name. + + + I still have not heard a response from the rock I tossed in earlier. A single misstep, and my descent would be eternal. It is truly a horrifying thought. + + + An eternity of darkness is more frightening than any beast I have fought thus far. If I fell, what would kill me first? The hunger, or myself? + + + On a side note, I am now using the forest fissure as my own personal lavatory. I wonder if I am pooping into another dimension... + + + Prince's Journal + + + Journal Entry #12 + + + I have found a solution to my hunger problem. The forest holds an endless bounty of delicious mushrooms. + + + And within these mushrooms lie chicken legs! Also gold coins, and vials of sparkling water... I broke open a tree trunk earlier, and a bag of money fell out. + + + Sometimes I feel like I have gone insane. + + + ... Plus, what is up with the moon? It's HUGE! + + + Prince's Journal + + + Prince's Journal + + + Journal Entry #13 + + + I slew the beast of the forest, and I have felt the throne room weaken once more. + + + So far my assumptions have proven correct. Each wing of the castle houses its own guardian beast. Was this designed as a test of will? If so, then I cannot fail, for the further I venture, the more bold I become! + + + Tomorrow I scour the tower. I am on a roll. + + + Prince's Journal + + + Journal Entry #14 + + + I have been methodically clearing the demons in these rooms in my quest to slay the next guardian, but I am losing track of time... and other things... + + + As I entered the tower, I felt time stand still. Or perhaps that is the vertigo talking? I was never keen on heights...or was I? + + + I am finding it increasingly difficult to remember my past... + + + Prince's Journal + + + Journal Entry #2 + + + Journal Entry #15 + + + I remember being a famous adventurer. My martial prowress surpassed all of my brothers. That, I am sure of. While they spent their days buried in their bookish studies, I was out killing brigands and monsters. + + + I always wondered why my father favoured them over me? Isn't it always the opposite in fairytales? + + + Fortune favors the bold. Not the insipid intellectual... Or something like that. + + + Man, I would love to see my brothers try to out think my sword in their face! + + + Prince's Journal + + + Journal Entry #16 + + + What if years have passed since I first entered these walls? It is true that I am becoming more proficient in clearing monsters, but it feels like an age has passed. + + + I have even forgotten what my own kin look like. + + + What if they think I have failed? What if one of my brothers has beaten me to the cure? + + + Entry # + + + Castle Hamson + + + The Land of Darkness + + + Forest Abkhazia + + + The Maya + + + Select a category + + + Rune needed + + + Purchase Info Here + + + to unlock + + + Rune + + + to close map + + + to re-center on player + + + to move map + + + Instructions + + + select/equip + + + [Input:0] select/equip + + + cancel/close menu + + + [Input:2] cancel/close menu + + + Arrow keys to navigate + + + to navigate + + + [Button:LeftStick] to navigate + + + Slain + + + Press + + + Press [Input:0] to exit + + + to exit + + + Skeleton + + + Bloobasaurus Rex + + + Grandpa Spark + + + Lord Spark, King of Sparkatonia + + + Mimic + + + Mimicant + + + Mimicrunch + + + Chesticles + + + Barbatos + + + Stolas + + + Berith + + + Amon + + + Herodotus + + + Focalor + + + Halphas + + + Neo Khidr + + + Alexander the IV + + + Astrodotus + + + Ponce de Freon + + + The Brohannes + + + Wall Turret + + + The Gatekeeper + + + The Infinite + + + Chaintor + + + The Forgotten + + + The Forsaken + + + The Sentinel + + + The Traitor + + + The Fountain + + + Berith & Halphas + + + Barbatos & Amon + + + Stolas & Focalor + + + Chaintex + + + Chaintus + + + Pantheon + + + Earthsor + + + Gravisor + + + Terrasor + + + Flamelock + + + Mr Bones + + + Blazelock + + + Sollock + + + Sol Mage + + + Frosten + + + Icen + + + Glacien + + + Luna Mage + + + Scout + + + Pupil + + + Visionary + + + McRib + + + Khidr + + + Fury + + + Rage + + + Wrath + + + Alexander + + + Tall Guard + + + Hulk Guard + + + Tower Guard + + + Sentinel + + + Spiketor + + + Corrupt Knight + + + Spiketex + + + Spiketus + + + Spiker + + + Gray Knight + + + Gray Baron + + + Graydiator + + + Graypion + + + Warg + + + Wargen + + + Wargenflorgen + + + Corrupt Vanguard + + + Zorg Warg + + + Zombie + + + Zomboner + + + Zombishnu + + + Zomg + + + Energon + + + Mastertron + + + Voltron + + + Prime + + + Ninjo + + + Corrupt Lord + + + Ninpo + + + Ninpojo + + + Master Ninja + + + Bud + + + Plantite + + + Flowermon + + + Charite + + + Pyrite + + + Infernite + + + Ponce de Leon + + + Botis + + + Spike Trap + + + Archer + + + Ranger + + + Sniper + + + Sharpshooter + + + Johannes + + + The Fountain + + + Fountain of Youth + + + Doomvas + + + Doomtrait + + + Bloob + + + Doomscape + + + Sallos + + + Plinky + + + Planky + + + Plonky + + + Ploo + + + Kentucky + + + Fried + + + Chicken + + + Delicious + + + Bloobite + + + GuardBox + + + GuardBox XL + + + GuardBox 2000 + + + GuardBox Gigasaur + + + Headless Horse + + + Dark Stallion + + + Night Mare + + + My Little Pony + + + Sparky + + + Mr. Spark + + + Vault + + + Curse + + + Grace + + + Architect's Fee + + + NG+ Bonus + + + Sprint + + + Vampire + + + Sky + + + Siphon + + + Balance + + + Retaliation + + + Bounty + + + Haste + + + Squire + + + Slayer + + + Sage + + + Blood + + + Retribution + + + Holy + + + Dark + + + Silver + + + Guardian + + + Imperial + + + Royal + + + Knight + + + Ranger + + + Sky + + + Dragon + + + Sword + + + Cape + + + Bracers + + + Helm + + + Chestplate + + + None + + + Sword + + + Cape + + + Limbs + + + Helm + + + Chest + + + None + + + Grants you the power to jump in the air. Multiple runes stack, allowing for multiple jumps. + + + Harder enemies, but greater rewards. Multiple runes stack making enemies even harder. + + + Enemies scale slower, easier but lesser rewards. Multiple runes stack slowing enemy scaling more. + + + Gain the power to dash short distances. Multiple runes stack allowing for multiple dashes. + + + Killing enemies will drain them of their health. Multiple runes stack for increased life drain. + + + Gain the power of flight. Multiple runes stack for longer flight duration. + + + Steals mana from slain enemies. Multiple runes stack for increased mana drain. + + + Slaying enemies grants both HP and MP. Multiple runes stack for increased hp/mp drain. + + + Returns damage taken from enemies. Multiple runes stack increasing the damage return + + + Increase the amount of gold you get from coins. Multiple runes stack for increased gold gain. + + + Increase your base move speed. Multiple runes stack making you even faster. + + + Press + + + Enemies are harder. + + + Enemies scale slower. + + + while in air. + + + Press [Input:10] while in air. + + + or + + + to dash. + + + [Input:14] or [Input:15] to dash. + + + Kill enemies to regain health. + + + Press + + + while in air. + + + Press [Input:10] while in air. + + + Kill enemies to regain mana. + + + Kill enemies to regain health and mana. + + + Damage returned to enemies. + + + Coins give more gold. + + + Move faster. + + + Critical Chance + + + Air Dash + + + Block + + + Float + + + Can attack projectiles + + + Flight + + + Move Speed + + + None + + + Critical Damage + + + Vampirism + + + Gold Bonus + + + Siphon + + + XP Bonus + + + AirAttack + + + Air Jump + + + Damage Return + + + Air jump + + + Earn 60% total gold in the castle. + + + Bounty increased by + + + Bounty increased by {0}% + + + Enemies start + + + levels higher + + + Enemies start {0} levels higher + + + Enemies scale + + + units slower + + + unit slower + + + Enemies scale {0} units slower + + + Enemies scale {0} unit slower + + + times + + + time + + + Air jump {0} times + + + Air jump {0} time + + + Dash up to + + + times + + + time + + + Dash up to {0} times + + + Dash up to {0} time + + + Gain back + + + hp for every kill + + + Gain back {0} HP for every kill + + + Fly for + + + seconds + + + second + + + Fly for {0} seconds + + + Fly for {0} second + + + Gain back + + + mp for every kill + + + Gain back {0} MP for every kill + + + Mana HP + + + Return + + + % damage after getting hit + + + Return {0}% damage after getting hit + + + Each gold drop is + + + % more valuable + + + Each gold drop is {0}% more valuable + + + Move + + + % faster + + + Move {0} % faster + + + Quit Rogue Legacy + + + Press + + + Press [Input:0] to move on + + + to move on + + + The sun... I had forgotten how it feels... + + + s Parting Words + + + has been slain by + + + Press + + + Press [Input:0] to move on + + + to move on + + + has been slain by + + + has been slain by a + + + was done in by a projectile + + + slipped and was impaled by spikes + + + has been slain + + + 's Parting Words + + + to continue + + + [Input:0] to continue + + + HP Increased + + + MP Increased + + + Strength Increased + + + Magic Damage Increased + + + Armor Increased + + + Max Weight Load Increased + + + Medallion completed! + + + You've collected a medallion piece! + + + The Forest is always to the right side of the Castle. + + + Sky runes let you fly by pressing + + + while in the air. + + + Sky runes let you fly by pressing [Input:10] while in the air. + + + Vampirism and Siphon runes are very powerful when stacked. + + + Mastering mobility runes makes you awesome. + + + Make sure to expand your manor. You never know what new skills can be revealed. + + + All classes can be upgraded with unique class abilities. + + + Unlocked class abilities can be activated with + + + Unlocked class abilities can be activated with [Input:13] + + + Upgrade your classes early to obtain powerful class abilities. + + + If you are having trouble with a room, see if you can bypass it instead. + + + Buying equipment is the fastest way to raise your stats. + + + Purchasing equipment is cheaper and more flexible than raising your base stats. + + + The Maya is always at the top of the Castle. + + + You should have picked the other child. + + + Runes are very powerful. Equip runes at the Enchantress, and don't forget to use them! + + + Learn the nuances of your spell to maximize their potential. + + + Try to hit enemies near the apex of the axe's arc in order to hit them multiple times. + + + Avoid picking up the conflux orbs after casting it to maximize damage. + + + Dodge the chakrams return trip in order to maximize its damage. + + + Better to use mana to kill enemies than to take unnecessary damage. + + + Learning enemy 'tells' is integral to surviving the castle. + + + Spike traps check for a pulse to tell the dead from the living. + + + Press + + + to open the map. + + + Press [Input:9] to open the map. + + + The Darkness is always at the bottom of the Castle. + + + Fairy chests hold all the runes in the game. Runes will help you immensely. + + + If you fail a Fairy chest room, the Architect can give you a second chance. + + + The Architect has a hefty fee for those who use his service. + + + Bosses drop large amounts of gold on their death. + + + Bury me with my money. + + + If you are having trouble, try equipping Grace runes. + + + In options you can enable Quick Drop to downstrike and drop with + + + In options you can enable Quick Drop to downstrike and drop with [Input:18] + + + The architect is very useful for practicing against bosses. + + + The third row of equipment usually has major tradeoffs. Be careful. + + + Certain runes work better with certain bosses. + + + If you're having trouble with a boss, try using different runes. + + + You should practice fighting bosses using the architect. + + + Health is a very important stat to raise. + + + Retribution runes can damage invulnerable objects. + + + Class abilities are very powerful if used correctly. + + + Some classes have advantages over certain bosses. + + + Vault runes let you to jump in the air with + + + Vault runes let you to jump in the air with [Input:10] + + + Sprint runes let you dash with [Input:PLAYER_DASHLEFT] or [Input:PLAYER_DASHRIGHT] + + + or + + + Each class has pros and cons. Make sure to change your playstyle accordingly. + + + Exploring and finding chests is the best way to earn gold. + + + Harder areas offer greater rewards. + + + My duties are to my family... + + + But I am loyal only to myself. + + + gold + + + hp recovered + + + mp recovered + + + Armor Up + + + Max Health Up + + + Max Mana Up + + + Attack Up + + + Magic Up + + + Max Weight Up + + + Now Playing + + + Now Entering + + + Fairy Chest Objective: + + + Reach the chest in 15 seconds: + + + Time Remaining: + + + Objective Complete! + + + Objective Failed + + + No Traits + + + Heroic + + + Divine + + + Sir + + + Sir Hero + + + Lady + + + Lady Heroine + + + the + + + the + + + Legendary + + + Useless + + + Feeble + + + Determined + + + Stout + + + Gallant + + + Valiant + + + to select a child + + + [Input:0] to select a child + + + to view family tree + + + [Button:LeftStick] to view family tree + + + Arrow keys to view family tree + + + to re-roll your children once + + + [Input:9] to re-roll your children once + + + Class + + + Trait + + + Traits – None + + + Spell + + + Building + + + Balding + + + Reminiscing + + + Jacking In + + + to close map + + + Opened chest + + + Teleporter + + + Bonus Room + + + [Input:9] to close map + + + to center on player + + + [Input:0] to center on player + + + Use arrow keys to move map + + + to move map + + + [Button:LeftStick] to move map + + + Legend + + + You are here + + + Boss location + + + Unopened chest + + + Fairy chest + + + Music Volume + + + Chinese + + + English + + + French + + + German + + + Polish + + + Portuguese (Brazil) + + + Russian + + + Spanish (Spain) + + + Language + + + *Quick drop allows you to drop down ledges and down-attack in \nthe air by pressing the DOWN button + + + Resolution + + + Fullscreen + + + Reduce Shader Quality + + + Use Dinput Gamepads + + + Enable Steam Cloud + + + to navigate options + + + [Button:LeftStick] to navigate options + + + Arrow keys to navigate options + + + to select option + + + [Input:0] to select option + + + to exit options + + + [Input:2] to exit options + + + Screen Size + + + Help + + + *The game must be restarted for this change to come into effect. + + + *Cloud support must be enabled on the Steam platform as well for\nthis feature to work. + + + Class: + + + Strength: + + + Magic: + + + Armor: + + + Level: + + + Health: + + + Xbox One Wireless Controller disconnected. Reconnect it. + + + ????? + + + gold + + + max mp + + + max hp + + + Max MP Converted. Need higher level. + + + Is choosing an heir. + + + has gas. + + + Is bald. + + + Is exploring the Castle + + + Is exploring the Tower + + + Is exploring the Forest + + + Is exploring the Dungeon + + + Is fighting [x] + + + Is in a climactic final battle + + + Is watching the ending. + + + Is afraid of chickens. + + + Health + + + Enchantments + + + to exit + + + [Input:2] to exit + + + Lv. + + + Mana + + + Armor + + + Weight + + + Strength + + + Intelligence + + + Crit. Chance + + + Crit. Damage + + + Equipment + + + 100% Base stats. + + + SPECIAL: Barbarian Shout.\nHuge HP. Low Str and MP. + + + Huge Str, but you cannot land critical strikes. + + + % Move Speed. Low HP and MP. + + + Huge Str, but you cannot land critical strikes.\n+{0}% Move Speed. Low HP and MP. + + + SPECIAL: Replacement Technique.\nHuge Str, but you cannot land critical strikes. + + + % Move Speed. Low HP and MP. + + + SPECIAL: Replacement Technique.\nHuge Str, but you cannot land critical strikes.\n+{0}% Move Speed. Low HP and MP. + + + % of damage dealt is converted into mana.\nLow Str, HP, and MP. + + + {0}% of damage dealt is converted into mana.\nLow Str, HP, and MP. + + + SPECIAL: Empowered Spell. + + + % of damage dealt is converted into mana.\nLow Str, HP, and MP. + + + SPECIAL: Empowered Spell.\n{0}% of damage dealt is converted into mana.\nLow Str, HP, and MP. + + + Kills are coverted into max HP.\nVery low Str, HP and MP. High Int. + + + SPECIAL: HP Conversion.\nKills are coverted into max HP.\nVery low Str, HP and MP. High Int. + + + You are a man-dragon + + + ????? + + + SPECIAL: Guardian's Shield.\n100% Base stats. + + + % Crit. Chance + + + % Crit. Damage.\nLow HP, MP, and Str. + + + +{0}% Crit. Chance, +{1}% Crit. Damage.\nLow HP, MP, and Str. + + + SPECIAL: Mist Form + + + % Crit. Chance + + + % Crit. Damage.\nLow HP, MP, and Str. + + + SPECIAL: Mist Form\n+{0}% Crit.Chance, +{1}% Crit. Damage.\nLow HP, MP, and Str. + + + % Gold gain.\nVery weak in all other stats. + + + +{0}% Gold gain.\nVery weak in all other stats. + + + SPECIAL: Ordinary Headlamp. + + + % Gold gain.\nVery weak in all other stats. + + + SPECIAL: Ordinary Headlamp.\n+{0}% Gold gain.\nVery weak in all other stats. + + + Every kill gives you + + + mana.\nLow Str and HP. High Int and MP. + + + Every kill gives you {0} mana.\nLow Str and HP. High Int and MP. + + + SPECIAL: Spell Cycle.\nEvery kill gives you + + + mana.\nLow Str and HP. High Int and MP. + + + SPECIAL: Spell Cycle.\nEvery kill gives you {0} mana.\nLow Str and HP. High Int and MP. + + + Huge HP. Low Str and MP. + + + - START NEW LEGACY - + + + NG+ + + + to navigate + + + [Button:LeftStick] to navigate + + + Arrow keys to navigate profiles + + + to select + + + [Input:0] to select + + + to exit + + + [Input:2] to exit + + + to delete + + + [Input:26] to delete + + + the + + + the + + + the Deceased + + + the Deceased + + + Lvl. + + + Enable Quick Drop + + + No + + + Yes + + + Save data is corrupted. The save data will now be deleted. + + + Save data ownership conflict. Save data will be reset and game progress will be lost. + + + There is not enough free space on the system storage. At least %i KB more free space is needed. Delete other save data and retry? + + + Do you want to retry saving? + + + Do not turn off the PlayStation®Vita system while the following icon is displayed on screen + + + Do not turn off the PlayStation®3 system while the following icon is displayed on screen + + + Do not turn off the PlayStation®4 system while the following icon is displayed on screen + + + + + + Your progress will not be saved unless you sign-in. + + + SFX Volume + + + Improve your cardio workout. A better heart means better health. + + + Unlock the smithy and gain access to phat loot. + + + Unlock the enchantress and gain access to her magical runes and powers. + + + Unlock the architect and gain the powers to lock down the castle. + + + Upgrading your carry capacity will allow you to wear better and heavier armor. + + + Strengthen your innards through natural means to reduce incoming damage. + + + Improve your looting skills, and get more bang for your buck. + + + Lower Charon's toll by learning how to barter with death itself. + + + Gut cleansing leads to noticable improvements from both potions and meat. + + + Use the power of science to make a whole new batch of babies. Just... don't ask. + + + Release the power of the Lich! A being of massive potential. + + + Strengthen your adrenal glands and be invulnerable like Bane. Let the games begin! + + + Unlock the skills of the Miner and raise your family fortune. + + + Unlock the Spellthief, and become a martial mage. + + + Unlock the Shinobi, the fleetest of fighters. + + + Practice your basics to reduce mana costs when casting spells. + + + Turn your knights into Paladins. A ferocious forefront fighter. + + + Unlock the latent powers of the Mage and transform them into the all powerful Archmage. + + + Learn the dark arts, and turn the Knave into an Assassin. + + + Earn your geology degree and go from Miner to Spelunker. Spiffy. + + + Become a Barbarian King. The king of freemen. That makes no sense. + + + Royalize your all-powerful Liches, and turn them into Lich Kings. + + + Release your inner cat, and avoid death. Sometimes. + + + Become the leader of your village, and turn your Shinobi into a Hokage. Believe it! + + + Ride the vortexes of magic, and turn your Spellthiefs into Spellswords. + + + Half man, half ******, all awesome. + + + QUICK OF BREATH \nYou're a heavy breather. Bad for stalking, good for walking! \n\nIncrease your natural endurance regeneration. + + + You were infused with tiger blood at a young age. You have now been infused with the power to release tiger blood when stabbed. \nRunning drains less endurance. + + + Your have viking ancestry. \n\nIncrease your starting endurance. + + + You're an early waker. If leveling was like waking up.\n Gain bonus HP and MP every time you level. + + + You were born with absolute power in your fingertips. \nAll spells deal more damage. + + + You were born with arcane energy coarsing through your veins. Ow. \nSpells cost less to cast. + + + OCD finally comes in handy. \nGain more gold. + + + A proper gym will allow you to really strengthen your arms and butt muscles. + + + By law, you are now the best man. \nGive birth to more children. + + + Your parents said learning how to sift for gold was useless for a farmer. Whose laughing now? \n Display treasure rooms at the start of the game. + + + War is hell. Luckily you were never in one. \n Fire more mortars. + + + As a child, you showed an affinity for blowing things up. \n Bombs have a larger radius. + + + You're great grandfather was a snowman. He taught you nothing. \n Icicles pierce through more enemies. + + + You are Zen-like. \n Regain endurance faster while still. + + + Generic SKILL. Increase total Endurance. + + + You fight with finesse \n Attacks Drain X% less endurance. + + + Generic SKILL. Increase Health + + + You suck... Blood. \n Restore a small amount of life with every hit. + + + A pogo practice room has its benefits. Deal more damage with consecutive down strikes. + + + Come back to life, just like Jesus. But you're still not jesus. \n Revive once after dying. + + + Clearing a room is like clearing your mind. I don't know how. \nRegain health for every room fully cleared. + + + Cartography /n Each percentage of map revealed adds 0.1 damage. + + + Generic SKILL. Increase Attack Damage. + + + You're a very, very sore loser. \n Deal massive damage to all enemies on screen upon death. + + + You have learned that hitting the balls deals massive damage. \n Crits deal more damage. + + + GENERIC SKILL. + + + Oh. They were in my back pocket. \nGain 2 extra keys. + + + Like a pheonix you are reborn from your crappy ashes. \n Regain all HP and MP. + + + Retire, and invest your money wisely. End your game early, and gain a bonus to gold found. + + + Teaching yourself about the weaknesses of enemies allows you to strike with deadly efficiency. + + + CHUG CHUG CHUG! \n Drink potions instantly. + + + Practice the deadly strikes to be even deadlier. Enemies will be so dead. + + + Learn the secrets of the universe, so you can use it to kill with spells better. + + + Increase your mental fortitude in order to increase your mana pool. + + + Press + + + to cast empowered spells + + + to awesome. + + + Press [Input:9] to randomize your children + + + to randomize your children + + + Press [Input:13] to block all incoming damage. + + + Press [Input:13] to switch spells + + + Press [Input:13] to turn to mist + + + Press [Input:13] to turn on your headlamp + + + Press [Input:13] to cast an epic shout that knocks virtually everything away. + + + Press [Input:13] to convert max hp into max mp + + + to block all incoming damage. + + + Press [Input:13] to flash + + + Press [Input:13] to cast empowered spells + + + Press [Input:10] to awesome. + + + to switch spells + + + to turn to mist + + + to turn on your headlamp + + + to cast an epic shout that knocks virtually everything away. + + + to convert max hp into max mp + + + to flash + + + + + + Health Up + + + Smithy + + + Enchantress + + + Architect + + + Equip Up + + + Armor Up + + + Gold Gain Up + + + Haggle + + + Potion Up + + + Randomize Children + + + Unlock Lich + + + Invuln Time Up + + + Unlock Miner + + + Unlock Spell Thief + + + Unlock Shinobi + + + Mana Cost Down + + + Upgrade Knight + + + Upgrade Mage + + + Upgrade Knave + + + Upgrade Miner + + + Upgrade Barbarian + + + Upgrade Lich + + + Death Defy + + + Upgrade Shinobi + + + Upgrade Spell Thief + + + Beastiality + + + Quick of Breath + + + Born to Run + + + Stout Heart + + + Out the Gate + + + Spellsword + + + Sorcerer + + + Perfectionist + + + Attack Up + + + Well Endowed + + + Treasure Hunter + + + Mortar Master + + + Explosive Expert + + + Icicle + + + Guru + + + Iron Lung + + + Sword Master + + + Tank + + + Vampire + + + Down Strike Up + + + Second Chance + + + Peace of Mind + + + Cartography Ninja + + + Strong Man + + + Suicidalist + + + Crit Barbarian + + + Magician + + + Keymaster + + + One Time Only + + + Cutting Out Early + + + Crit Chance Up + + + Quaffer + + + Crit Damage Up + + + Magic Damage Up + + + Mana Up + + + to purchase/upgrade trait + + + gold to + + + unlock + + + upgrade + + + weight + + + hp + + + mp + + + str + + + int + + + hp/mp + + + Max + + + [Input:0] to purchase/upgrade trait + + + to toggle icons off + + + armor + + + sec + + + [Input:9] to toggle icons off + + + to exit the manor + + + [Input:2] to exit the manor + + + to navigate skills + + + [Button:LeftStick] to navigate skills + + + Arrow keys to navigate skills + + + to toggle icons on + + + [Input:9] to toggle icons on + + + Current + + + Upgrade + + + Level + + + The Blacksmith can build the finest equipment in the world, turning you into a veritably virtuous violent-villain vaporizer.\nGathering blueprints will give him an even wider array of assorted armaments for your armory. + + + Convert your Barbarians into Barbarian KINGS! Learn the secret shouts of the bears, and shout at things until they explode. + + + Go from a measly Shinobi, to the all powerful Hokage! Master the art of looking like you're hit, but secretly turning into a log at the last minute. Good thing you carry a lot of logs on you. + + + Train your Knaves to become full fledged Assassins. Use the power of the shadows to slip secretly past enemy ranks. + + + All that digging has turned your Miners into Spelunkers! Now that spiffy light on your head actually does something! (Not really). + + + Turn your Spellthieves into Spellswords, and grant yourself the power of summoning empowered spells.\nYou call that an axe? THIS is an axe. + + + Raise your Liches into Lich Kings, and grant yourself the power of both mind AND matter! With a single press, convert your permanant health, into permanent mana. + + + You have discovered the lost art of the dragons. Though you cannot jump, you have unlimited flight, and can cast forth powerful fireballs at your foes. + + + You have discovered the hidden arts known only by Johannes the Traitor. All shall bow before your might! + + + The Enchantress can empower your body with magical runes, making you better, stronger, faster, jumpier.\nFind runes to increase her repertoire of body modifiying talents.\n\nHer crystal ball is just for show. + + + The Architect can lock a castle down and prevent it from changing.\n\nLike the layout of a castle?\nLOCK IT DOWN!\nJust make sure you can afford his fees. + + + The Shinobi. A super fast, super deadly warrior, who wears a super head band. They can't take a lot of hits, but they can dish out the pain. Believe it! + + + Trained more in the art of making money then killing enemies. Miners are best used for scouring the castle for treasure chests, and avoiding confrontation. + + + The Spellthief drains mana from the enemies they hit. This grants them access to an infinite supply of mana in the heat of a battle. Rock on! + + + Masters of life and death. The lich has mammoth potential. Every kill grants the Lich permanent health (to a cap), making them truly dangerous beings. + + + Promote your Knights into Paladins. Through rigorous training, Paladins have learned how to block blows from any direction. + + + Transform your measly Mages into Archmages. Master all of the arcane arts, and change whatever spells you have on the fly. + + + Hyperion's Ring + + + Ponce De Leon's Obol + + + Herodotus' Obol + + + Traitor's Obol + + + Hermes' Boots + + + Hedgehog's Curse + + + Charon's Obol + + + Calypso's Compass + + + Helios' Blessing + + + Nerdy Glasses + + + Khidr's Obol + + + Alexander's Obol + + + Fires a dagger directly in front of you. + + + Summon a Grand Blade to defend you. + + + Encircles you with protective fire. + + + Launches orbs that bounce everywhere. + + + Fire a laser that blasts everyone it touches. + + + Shoot fireballs at your enemies. + + + Fire a barrage of daggers. + + + Throws a giant axe in an arc. + + + Summons a bomb that explodes after a while. + + + Toggles freezing all enemies on-screen. + + + Hits all enemies on screen. Costly. + + + Drops and teleports to your shadow. + + + Sends out a marker which teleports you. + + + Throws a chakram which comes back to you. + + + Send Scythes flying out from above you. + + + Axe + + + Katana + + + Leaf + + + Chaos + + + Laser + + + Dragon Fire + + + Rapid Dagger + + + Dragon Fire Neo + + + Dagger + + + Runic Trigger + + + Stop Watch + + + Nuke + + + Quantum Translocater + + + Displacer + + + Cross + + + Spark + + + Dagger + + + Blade Wall + + + Flame Barrier + + + Conflux + + + B.E.A.M + + + Dragon Fire + + + Rapid Dagger + + + Axe + + + Bomb + + + Time Stop + + + Crow Storm + + + Quantum Translocator + + + Displacer + + + Chakram + + + Scythe + + + ...Loading + + + Blacksmith + + + I used to be a very powerful Enchantress. But one day, the monsters of this castle invaded my dreams and stole my knowledge. + + + No sound + + + Fairy Chest + + + The floor is lava. + + + Booyan + + + Hi there! Care to test your dexterity?\nYou only get one shot, but it's free of charge! If you succeed, I'll give you a nice reward! + + + You only get one shot, but it's free of charge! If you succeed, I'll give you a nice reward! + + + 10 daggers to destroy 8 targets. Care to give it a try? + + + Booyan + + + Ok, you had your fun. Beat it! + + + Booyan + + + They encased that knowledge in runes, and without those runes, I suck at my job. + + + I haven't seen that many shots since my last visit to the alehouse (yesterday). For destroying all the targets, I've got a little reward for you! + + + Booyan + + + You couldn't even hit 8 targets?\nPffft. Good luck with the rest of the castle. + + + Pffft. Good luck with the rest of the castle. + + + Booyan + + + Hi there! Let's see how good you are at your skills.\nYou only get one shot, but it's free of charge! If you succeed, I'll give you a nice reward! + + + You only get one shot, but it's free of charge! If you succeed, I'll give you a nice reward! + + + You get 5 axes to destroy as many targets as possible. Leave less than 10 standing, and I'll give you a special prize. Care to give it a try? + + + Booyan + + + Smashing! You managed to leave no more than 10 targets! Since I no longer have enough targets to run this gig, I might as well give you my stash. + + + Please Hero, if you find any runes, bring them back to me, and then I'll sell it back to you at a profit! + + + Booyan + + + You left more than 10 targets remaining.\nI guess you don't want the prize. Snarf! + + + I guess you don't want the prize. Snarf! + + + ??? + + + Greetings adventurer. I am here to give you a chance of a lifetime! + + + Miserly Elf + + + For the measly sum of 25% your current gold, I will give you a chance to open 1 of 3 chests. + + + One chest will triple what you paid, but the other two are empty. + + + Cheapskate Elf + + + Care to give it a shot? + + + Architect + + + ??? + + + Greetings adventurer. I am here to give you a chance of a lifetime! + + + Miserly Elf + + + For the measly sum of 50% your current gold, I will give you a chance to open 1 of 3 chests. + + + One chest will triple what you paid, but the other two are empty. + + + Cheapskate Elf + + + Care to give it a shot? + + + ??? + + + Greetings adventurer. I am here to give you a chance of a lifetime! + + + Miserly Elf + + + Grrrrreeeeetings Boy! + + + For the measly sum of 75% your current gold, I will give you a chance to open 1 of 3 chests. + + + One chest will triple what you paid, but the other two are empty. + + + Cheapskate Elf + + + Care to give it a shot? + + + Cheapskate Elf + + + You don't have enough money? You suck. + + + Sore Winner Elf + + + What's in the box? + + + NOTHING! + + + You stupid! Soooo stupid! + + + Wanna know a cool fact? I'm crrrrrrrazy! + + + Sore Loser Elf + + + Tch! You were lucky this time. + + + Impatient Elf + + + Open a chest already! + + + Cheapskate Elf + + + Sorry dude, one chest per person. + + + Developers + + + Don't **** Your Pants.\nDevelopment Time: 2 days.\nRelease Date: February 16, 2009 + + + Development Time: 2 days. + + + Release Date: February 16, 2009 + + + This lever here? With a simple pull, I can prevent the castle from changing. + + + This was the first game we ever made, and back then we used to be called Decade Studios. In it you must stop a man from pooping himself using only text input. + + + It was originally designed on a bus, and we decided to make it on the weekend. It did pretty well. + + + The game has a swear word in it, and we were thinking about changing the title to be more friendly. But then our balls grew back and we stuck to our guns. + + + A big part of the game revolved around making a text adventure that allowed people to input whatever they wanted. To solve this we had to pre-empt what we thought people would type. + + + We did this in 2 ways. First, we reduced the amount of options a player had (A man and a door), and secondly, we built an achievement system which was used to give the player direction. + + + The game revolved around the achievement system so heavily that it was placed into the game over screen progression. That was a small but very vital change. + + + Developers + + + Band of Bears\nDevelopment Time: 4 months.\nRelease Date: August 6, 2009 + + + Development Time: 4 months. + + + Release Date: August 6, 2009 + + + This way you can go through exactly what your ancestors went through. Impreeeessed? You should be. + + + This was our second game we ever attempted, and it was for the 2009 DreamBuildPlay contest. We found out about it pretty late, so we had to play catch up with everyone else. + + + Fresh off the success of DSYP we decided to go big... stupidly big. And thus, Cellar Door Games was formed. + + + On top of starting a project well beyond our resources and expertise, we also juggled full-time jobs to get this game running. It was pretty sucky. + + + The game featured the B.E.A.R.S system (Bare Effort Adaptable Room System), which would change rooms depending on the number of players playing. + + + The BEARS system didn't just tweak numbers, it tweaked puzzles as well. We ended up in the Top 20 which was good but not high enough to win anything. + + + Eventually reality (and common sense) came back to us and we realized we had to scrap the project, or in the very least put it on indefinite hiatus. + + + The demo boss was pretty frickin cool. + + + Developers + + + Tribal Tallies\nDevelopment Time: 3 months.\nRelease Date: November 23rd, 2009 + + + Development Time: 3 months. + + + How did I build this fantastic connnnnnnntraption? With sccccccience of course! And magic. + + + Release Date: November 23rd, 2009 + + + Tribal Tallies was the first project we had worked on months after the horrible experience with Band of Bears. + + + It was a bit of a test project, to dabble our feet in water of iOS gaming since we had never tried making something on mobile platforms before. + + + The game was simple in concept, as you tapped numbers in sequence as fast as you could. + + + To spice things up we implemented several modes, like tap backwards, hidden numbers, and tap matching. + + + We thought the scope was reasonable, but the game ended up taking much more time to make than expected. It didn't help it was all coded on a hackintosh. + + + It was a pretty plain game. We could have done better, but we were all playing it safe after Band of Bears. + + + Developers + + + Q\nDevelopment Time: 1 month.\nRelease Date: March 18th, 2010 + + + Development Time: 1 month. + + + ... Mostly magic. + + + Release Date: March 18th, 2010 + + + Our fourth project. After Tribal Tallies we took a few months off from making games and just focused on our full-time jobs. We got angsty again, so we decided to make a puzzle game. + + + At this point most of the original founders of Cellar Door Games left to pursue other opportunities, and the unwanted remnants are what compose the company today. + + + The game used a queuing combo mechanism to force players to think about how the tiles would fall in order to build massive combos. + + + We made it free but nobody picked it up either. After the failures of Band of Bears, Tribal Tallies, and Q, we prepped ourselves to pack it in and close the company. + + + Developers + + + My First Quantum Translocator\nDevelopment Time: 1 month.\nRelease Date: October 13th, 2010 + + + Development Time: 1 month. + + + Release Date: October 13th, 2010 + + + My First Quantum Translocator came about when our company was at its lowest point. After 3 failed games we had already mentally checked out, and decided to make this tiny flash game for kicks. + + + Welcome Hero. + + + But my skills aren't freeeeee. If I lock this castle, I will take 40% of allll the gold you earn! + + + Absolutely no expectations were made during development, and it was more of something we did for fun than anything else. + + + Needless to say, response to the game was huge and it is the sole reason that Cellar Door Games exists today. The moment we released MFQT we knew there was no going back. + + + Interestingly enough, most people believe the game was inspired by Portal, but their similarities were completely coincidental. + + + The game actually spawned from a character we had dreamt up for the game, League of Legends. + + + In truth the commonalities between Portal and MFQT only started to come up once we added final art and story to the game. + + + Either way, we were pretty proud of the game. It played well and it had a nice ending. + + + Developers + + + I Have 1 Day\nDevelopment Time: 1.5 months.\nRelease Date: April 15th, 2011 + + + Development Time: 1.5 months. + + + Release Date: April 15th, 2011 + + + + + + If you ever asked us, of all the game we made which one would be our favourite, there would be a unanimous agreement with I Have 1 Day. + + + As children we were raised on the adventure game classics like Kings Quest and Monkey Island, so this was really our homage to some of the best experiences we ever had in gaming. + + + The game revolves around a meta-time puzzle where the player had only 24 hours to beat the game. + + + Every puzzle had multiple solutions with time repercussions, which forced players to think of the best way to go about solving things. + + + One interesting fact. The second ending was added at virtually the last minute, and without it the entire game would have sucked. + + + Developers + + + Villainous\nDevelopment Time: 3 months.\nRelease Date: April 15th, 2011 + + + Development Time: 3 months. + + + Release Date: April 15th, 2011 + + + Villainous was one of the more risky endeavours we undertook. + + + Do you want to lock the castle and get only 60% gold? + + + The initial concept was a reverse tower defense, which sounded like it could be a good idea, but we had a hard time converting the 'could' to 'would'. + + + Most people who have played the game thinks the process was an obvious one, but lots of stress and arguments were involved in this project. + + + The entire idea was scrapped 3 or 4 times before we settled on its final version. + + + It is ironic then, that to-date Villainous is far and away one of our most successful titles. It was also the most painful. + + + Developers + + + Bullet Audyssey\nDevelopment Time: 3.5 months.\nRelease Date: November 29th, 2011 + + + Development Time: 3.5 months. + + + Release Date: November 29th, 2011 + + + Bullet Audyssey was our very last game prior to working on Rogue Legacy. + + + Being a bullet hell that was based on rhythm and beat charts, Bullet Audyssey was the most technically challenging game we had ever worked on (yes, even moreso than Rogue Legacy). + + + + + + Just to create a stage required 3 editors running in unison. + + + Development for this game was also a little non-traditional, as a lot of pre-planning was required to make sure everything clicked. + + + Being heavy advocates against documentation, this didn't settle well with us, so we had to talk out the whole game, for like, half a day. + + + The game had the player absorbing enemy bullets in order to fire them back and absorption happened on a beat which matched the song being played. + + + Initial playtests were disastrous, as the game was too hard and people became incredibly frustrated in the very first minute. + + + By playtests, we mean 1 dude who doesn't even like Bullet Hells. But that's larger then our usual test pool. + + + The game didn't perform very well when it released. That gave us the confidence to make Rogue Legacy! + + + Confirm + + + Cancel + + + Warning! + + + Do you want to lock the castle and get only 60% gold? + + + Are you sure you want to start a new game? All previous save game data will be erased. + + + Restore Controls + + + Are you sure you want to restore back to the default control scheme? + + + + + + Are you sure you want to begin a new adventure with this chosen hero? + + + Resolution Changed + + + Are you sure you want to run at this resolution?\n(The resolution will revert back in 10 seconds) + + + + + + Delete Save File + + + Are you sure you want to delete your save file?\n(All skills, traits, lineages, and equipment will be erased FOREVER) + + + Architect + + + (All skills, traits, lineages, and equipment will be erased FOREVER) + + + Delete Save File + + + Are you ABSOLUTELY sure? (No Backsies)\n(All skills, traits, lineages, and equipment will be erased FOREVER) + + + (All skills, traits, lineages, and equipment will be erased FOREVER) + + + + + + Are you sure you want to quit to main menu? (Your current status will be saved) + + + + + + Are you sure you want to quit playing Rogue Legacy? (Your current status will be saved) + + + Save Error + + + Oh no! Somehow your save file got corrupted! + + + Sorry boy, there's no castle to build right now. This screw is just for show. + + + Attempting to load a backup version of the game. Hopefully it doesn't set you too far back! + + + Save Error + + + It doesn't look like your back up is working either. Please contact: support@cellardoorgames.com + It doesn't look like your back up is working either. I'm afraid we're going to have to restart the game. + + + Save Error + + + Your game has failed to save 3 times in a row. + + + Anti-virus software and manual backup saving programs can conflict with save files. Please disable any of these programs before running the game. + + + Architect + + + Dood, the castle's already locked. + + + Architect + + + Maybe you can help me. I used to be the greatest blacksmith in all the lands. But one day, the monsters of this castle attacked my smithy and stole all my blueprints. + + + Enjooooy! Maybe you can reach some trrrreasures your ancestors missed! + + + Charon + + + ... One must pay the toll. + + + + + + (Give Charon all of your money and enter the castle?) + + + + + + (Give Charon all of your money and enter the castle?) + + + + + + (Give Charon 90% of your money and enter the castle?) + + + + + + Without those blueprints, I can only make cutlery and stuff. + + + (Give Charon 80% of your money and enter the castle?) + + + + + + (Give Charon 70% of your money and enter the castle?) + + + + + + (Give Charon 60% of your money and enter the castle?) + + + + + + (Give Charon 50% of your money and enter the castle?) + + + Charon + + + Oh ho ho! So you have my obol. I will let you pass for free, but only this one time. + + + Charon + + + Please bring back any blueprints you find, and I can build the most amazing equipment ever. EVER. + + + Oh ho! This is a very special obol. + + + Give it to me, and I shall let your soul pass through the other gates. + + + (Give Charon the Obol, and pay his toll?) + + + Charon + + + Oh ho! This is a very special obol. + + + Give it to me, and I shall let your soul pass through the other gates. + + + (Give Charon the Obol, and pay his toll?) + + + Charon + + + Oh ho! This is a very special obol. + + + Give it to me, and I shall let your soul pass through the other gates. + + + ... At a price of course. + + + (Give Charon the Obol, and pay his toll?) + + + Charon + + + Oh ho! This is a very special obol. + + + Give it to me, and I shall let your soul pass through the other gates. + + + (Give Charon the Obol, and pay his toll?) + + + Charon + + + Oh... You should not have taken this obol. + + + Prepare yourself. + + + (Give Charon the Obol, and pay his toll?) + + + Spiritual Shrine + + + Enchantress + + + Will you pray for assistance? + + + Last Boss + + + Welcome Hero! It was quite impressive for you to get this far. Unfortunately however, this shall be as far as you go! + + + Fairy Chest - Nothing + + + NO TEXT + + + Defeat All Enemies + + + + + + Low Health + + + + + + No Looking + + + Hello Hero. + + + + + + No Jumping + + + + + + No Noise + + + + + + Don't Touch The Floor + + + + + + No Fighting + + + + + + Reach Me In Time + + + Could I borrow your ear for a moment, I'm in need of your help. + + + + + + Take No Damage + + + + + + Find Me + + + + + + Fairy Chest + + + Don't look at me! + + + Fairy Chest + + + No Jumping + + + Fairy Chest + + + Press + + + Press [Input:12] to Attack + + + to Attack + + + to Change Slot + + + Continue Your Quest + + + Choose Your Heir + + + Start Your Legacy + + + Training Dummy + + + IT HUURRRTS + + + Oof + + + Ouch + + + BLARGH + + + I give up! + + + Do you even lift? + + + Ok, that one hurt + + + That tickled + + + That all you got? + + + Dost thou even hoist? + + + Oh god! + + + Nice try + + + Weak + + + Try again + + + The pain! + + + It hurts so much + + + STOP IT!! + + + What'd I do to you? + + + WHY??? + + + Stop hitting me + + + Why you do this? + + + You can't see colors due to monochromacy. + + + You're skinny, so every hit sends you flying. + + + You have trouble remembering where you are. + + + Your MP and HP pools are swapped. Who knew? + + + %#&@! + + + So energetic! You move faster. + + + Must. Clear. House. Break stuff to restore MP. + + + You're perma-roided. Attacks knock enemies further. + + + You have weak limbs. Enemies won't get knocked back. + + + You can't see in 3D. + + + Even the most valiant heroes can suffer from irritable bowels. + + + You like the ladies. + + + Welcome to Barfs-ville. + + + No peripheral vision. + + + You've got two left hands, and can't cast spells properly. + + + Peripheral Arterial Disease. No foot pulse. + + + Chickens freak you out. + + + You tend to EXAGGERATE. + + + You are insane. + + + You are very flexible. + + + You remember things with extreme clarity. + + + You miss the good old days. + + + You are a fan of the man. + + + Anything far away is blurry. + + + Congenital Insensitivity to Pain. Know no pain. + + + You're very talented. With a few issues. + + + There is no spork. + + + You break a lot of things. + + + You conduct electricity really well. + + + It's so dark. + + + You have random muscle spasms. + + + You can't tell people apart. + + + Anything close-up is blurry. + + + You hvae trboule raednig tinhgs. + + + You were born to be a basketball player. + + + You never get to ride rollercoasters. + + + The bald and the beautiful. + + + You're so heavy, enemies can't knock you back. + + + You can't see colors. + + + Hits send you flying. + + + Where are you? + + + MP + HP pools swapped. + + + %#&@! + + + You move faster. + + + Break stuff to restore MP. + + + You knock enemies out of the park. + + + You can't knock enemies back. + + + You can't see in 3D. + + + You fart a lot. + + + You like the ladies. + + + Everything is upside down. + + + No early indicators. + + + Spells come out your back. + + + No foot pulse. + + + You are scared of chickens. + + + Exaggerate the damage you take. + + + You see things that aren't there. + + + You turn while fighting. + + + Remember enemy placement. + + + Everything is old-timey. + + + You are a fan of the man. + + + Anything far away is blurry. + + + No visible health bar. + + + Randomized spells. + + + There is no spork. + + + You break stuff and have no balance. + + + Platforms stay open. + + + It's so dark. + + + You have random muscle spasms. + + + You can't tell people apart. + + + Anything close-up is blurry. + + + You hvae trboule raednig tinhgs. + + + You are huge. + + + You are tiny. + + + You are bald. + + + Can't get knocked back. + + + Color Blind + + + Ectomorph + + + Alzheimers + + + Dextrocardia + + + Coprolalia + + + ADHD + + + O.C.D. + + + Hypergonadism + + + Muscle Wk. + + + Stereo Blind + + + I.B.S. + + + Gay + + + Vertigo + + + Tunnel Vision + + + Ambilevous + + + P.A.D. + + + Alektorophobia + + + Hypochondriac + + + Dementia + + + Flexible + + + Eid. Mem. + + + Nostalgic + + + Near-Sighted + + + C.I.P. + + + Savant + + + The One + + + Clumsy + + + EHS + + + Glaucoma + + + Clonus + + + Prosopagnosia + + + Far-Sighted + + + Dyslexia + + + Gigantism + + + Dwarfism + + + Baldness + + + Endomorph + + + Developed by + + + Design + + + Programming + + + Production + + + Art + + + Sound Design & Music + + + Music + + + + + + Tap + + + Down Attack this + + + Tap [Input:11] to Jump + + + Hold [Input:11] to Jump Higher + + + Tap [Input:12] to Attack + + + Hold [Input:19] and Tap [Input:11] to Drop Ledges + + + (Air) Hold [Input:19] and Tap [Input:12] to Attack Down + + + Tap [Input:10] to Jump + + + Hold [Input:10] to Jump Higher + + + Tap [Input:12] to Attack + + + Hold [Input:18] and Tap [Input:10] to Drop Ledges + + + to Jump + + + (Air) Hold [Input:18] and Tap [Input:12] to Attack Down + + + Hold + + + to Jump Higher + + + to Attack + + + and Tap + + + to Drop Ledges + + + (Air) Hold + + + to Attack Down + + + [Input:25] to Change Profile ({0}) + + + {0} to unlock + + + {0} to unlock + + + {0} has been slain by {1} + + + {0} has been slain by {1} + + + {0} has been slain by a {1} + + + {0} was done in by a projectile + + + {0} slipped and was impaled by spikes + + + {0} has been slain + + + -{0}'s Parting Words + + + Primary Localization by + + + Chinese & Add'l Localization by + + + Heroic {0} + + + Divine {0} + + + Sir {0} {1} + + + Lady {0} {1} + + + Legendary {0} + + + Useless {0} + + + Feeble {0} + + + Determined {0} + + + Stout {0} + + + Gallant {0} + + + Valiant {0} + + + {0} the {1} + + + {0} the {1} + + + {0} the Deceased + + + {0} the Deceased + + + {0} gold to {1} + + + Unlock Traitor + + + Donate {0} gold and permanently empower your specter for this boss?\nTimes Empowered: {1} + + + Donation Box + + + The donation box is filled to the brim. Your specter cannot be empowered any further. Thanks for the money dood. + + + You cannot afford to donate. Come back when you've earned more gold. + + + Your specter has become stronger! + + + Additional Programming + + + Adaptation By + + + {0} {1} + + + Vault + + + Curse + + + Grace + + + Architect's Fee + + + NG+ Bonus + + + Sprint + + + Vampire + + + Sky + + + Siphon + + + Balance + + + Retaliation + + + Bounty + + + Haste + + + Japanese Localization & Production By + + + Quality Assurance + + + {0} {1} + + + Unlock Traitor + + + Full Metal Furies\nDevelopment Time: 4 years.\nRelease Date: January 17, 2018 + + + Full Metal Furies is from the future! It’s our follow-up game after Rogue Legacy, and the tenth game we’ve ever made. + + + After RL, we promised ourselves we would never make a game without planning it out ever again. We lied. Curse you past-selves! + + + The game ended up becoming one of our most ambitious projects ever, and was a mishmash of a brawler/multiplayer/meta-puzzle/coming-of-age disco ideas that turned the traditional view a brawler on its head the longer you played. + + + At 4 years, FMF is the longest time we’ve ever spent on development, and sadly also has some of lowest returns we've seen for our games. (Excluding those iOS games which generated negative bucks, curse you past-selves!) + + + But we’re still immensely proud of what we created, and even more proud of the FRIENDS WE MADE ALONG THE WAY. AWWWWWWW!!! + + + Copyright (C) 2013-2018, Cellar Door Games Inc. + + + {0} is a trademark of Cellar Door Games Inc. All Right Reserved. + + \ No newline at end of file diff --git a/RogueCastle/Resources/LocStrings.ru.resx b/RogueCastle/Resources/LocStrings.ru.resx new file mode 100644 index 0000000..3ffef66 --- /dev/null +++ b/RogueCastle/Resources/LocStrings.ru.resx @@ -0,0 +1,8351 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Выйти в главное меню + + + Выйти в главное меню + + + Главное меню (пропустить обучение) + + + Главное меню (пропустить обучение) + + + [Input:25] для смены профиля ({0}) + + + [Input:25] для смены профиля ({0}) + + + Здор-е + + + Стрелки = перемещение в меню + + + Стрелки = перемещение в меню + + + [Button:LeftStick] для перемещения. + + + [Button:LeftStick] для перемещения. + + + Выберите категорию + + + Выберите категорию + + + Нужен чертеж + + + Нужен чертеж + + + Сведения о покупке + + + Сведения о покупке + + + Нет + + + Нет + + + {0} для открытия + + + {0} для открытия + + + Здор-е + + + Мана + + + Мана + + + Урон + + + Урон + + + Магия + + + Магия + + + Броня + + + Броня + + + Вес + + + Вес + + + Прочие свойства: + + + Прочие свойства: + + + [Input:0] чтобы выбрать/надеть. + + + [Input:0] чтобы выбрать/надеть. + + + [Input:2] для отмены/закрытия меню. + + + [Input:2] для отмены/закрытия меню. + + + Разбито + + + Разбито + + + Осталось + + + Осталось + + + Награда + + + Награда + + + золотых + + + золотых + + + Просмотр карты + + + Просмотр карты + + + Изменить раскладку + + + Бросок вправо + + + Бросок вправо + + + Заклинание + + + Заклинание + + + Сброс раскладки + + + Сброс раскладки + + + Нажмите любую кнопку + + + Нажмите любую кнопку + + + Изменить раскладку + + + Вверх + + + Вверх + + + Вниз + + + Вниз + + + Влево + + + Влево + + + Вправо + + + Вправо + + + Атака + + + Атака + + + Прыжок + + + Прыжок + + + Умение + + + Умение + + + Бросок влево + + + Бросок влево + + + Обычный герой с довольно приличными параметрами. + + + Ходячий танк. Этого героя просто так не убьешь!\nУМЕНИЕ: Вопль варвара. + + + Ходячий танк. Эту героиню просто так не убьешь!\nУМЕНИЕ: Вопль варвара. + + + Быстрый герой. Серьезный урон, но без критических ударов. + + + Быстрая героиня. Серьезный урон, но без критических ударов. + + + Быстрый герой. Серьезный урон, но без критических ударов.\nУМЕНИЕ: Бросок ниндзя. + + + Быстрая героиня. Серьезный урон, но без критических ударов.\nУМЕНИЕ: Бросок ниндзя. + + + Герой для мастеров. Удары, наносимые врагу, восстанавливают ману. + + + Героиня для мастеров. Удары, наносимые врагу, восстанавливают ману. + + + Герой для мастеров. Удары, наносимые врагу, восстанавливают ману.\nУМЕНИЕ: Усиление чар. + + + Героиня для мастеров. Удары, наносимые врагу, восстанавливают ману.\nУМЕНИЕ: Усиление чар. + + + Трупоед. Каждый убитый враг добавляет здоровья (прирост ограничен). Могучий интеллект. + + + Трупоедка. Каждый убитый враг добавляет здоровья (прирост ограничен). Могучий интеллект. + + + Трупоед. Каждый убитый враг добавляет здоровья (прирост ограничен). Могучий интеллект.\nУМЕНИЕ: Трансформация HP. + + + Трупоедка. Каждый убитый враг добавляет здоровья (прирост ограничен). Могучий интеллект.\nУМЕНИЕ: Трансформация HP. + + + Вы получеловек, полудракон. + + + Вы получеловек, полудракон. + + + ????? + + + ????? + + + Обычная героиня с довольно приличными параметрами. + + + Обычный герой с довольно приличными параметрами.\nУМЕНИЕ: Щит стража. + + + Обычная героиня с довольно приличными параметрами.\nУМЕНИЕ: Щит стража. + + + Герой для любителей риска. Низкие параметры и убойные критические удары. + + + Героиня для любителей риска. Низкие параметры и убойные критические удары. + + + Герой для любителей риска. Низкие параметры и убойные критические удары.\nУМЕНИЕ: Уход в тень. + + + Героиня для любителей риска. Низкие параметры и убойные критические удары.\nУМЕНИЕ: Уход в тень. + + + Герой для тех, кто любит деньги. Хилый, но находит намного больше золота. + + + Героиня для тех, кто любит деньги. Хилая, но находит намного больше золота. + + + Герой для тех, кто любит деньги. Хилый, но находит намного больше золота.\nУМЕНИЕ: Фонарь на шлеме. + + + Героиня для тех, кто любит деньги. Хилая, но находит намного больше золота.\nУМЕНИЕ: Фонарь на шлеме. + + + Могучий волшебник. Вы получаете ману за каждого убитого врага. + + + Могучая волшебница. Вы получаете ману за каждого убитого врага. + + + Могучий волшебник. Вы получаете ману за каждого убитого врага.\nУМЕНИЕ: Цикл чар. + + + Могучая волшебница. Вы получаете ману за каждого убитого врага.\nУМЕНИЕ: Цикл чар. + + + Ходячий танк. Этого героя просто так не убьешь! + + + Ходячий танк. Эту героиню просто так не убьешь! + + + Королева варваров + + + Королева варваров + + + Вождь варваров + + + Вождь варваров + + + Шиноби + + + Шиноби + + + Хокаге + + + Хокаге + + + Воровка-маг + + + Воровка-маг + + + Вор-маг + + + Вор-маг + + + Воительница-маг + + + Воительница-маг + + + Воин-маг + + + Воин-маг + + + Лич + + + Лич + + + Королева-Лич + + + Королева-Лич + + + Король-Лич + + + Король-Лич + + + Дракониха + + + Дракониха + + + Дракон + + + Дракон + + + Изменница + + + Изменница + + + Изменник + + + Изменник + + + Рыцарь + + + Рыцарь + + + Рыцарь + + + Рыцарь + + + Паладин + + + Паладин + + + Паладин + + + Паладин + + + Плутовка + + + Плутовка + + + Плут + + + Плут + + + Убийца + + + Убийца + + + Убийца + + + Убийца + + + Шахтер + + + Шахтер + + + Шахтер + + + Шахтер + + + Спелеолог + + + Спелеолог + + + Спелеолог + + + Спелеолог + + + Маг + + + Маг + + + Маг + + + Маг + + + Архимаг + + + Архимаг + + + Архимаг + + + Архимаг + + + Варварша + + + Варварша + + + Варвар + + + Варвар + + + Спасибо за игру! + + + Графика + + + Графика + + + Музыкальный и звуковой дизайн + + + Музыкальный и звуковой дизайн + + + Музыка + + + Музыка + + + Маркетинг и сюжет + + + Маркетинг и сюжет + + + Дополнительный звуковой дизайн + + + Дополнительный звуковой дизайн + + + Дополнительная графика фона + + + Дополнительная графика фона + + + Деловая поддержка + + + Деловая поддержка + + + Суперская благодарность: Turbo Edition + + + Суперская благодарность: Turbo Edition + + + Особая благодарность + + + Особая благодарность + + + Дополнительная благодарность + + + Дополнительная благодарность + + + Спасибо за игру! + + + Всего детей + + + Адаптация для Mac/Linux + + + Адаптация для Mac/Linux + + + Команда по контролю качества (Mac/Linux) + + + Команда по контролю качества (Mac/Linux) + + + Благодарим всех наших поклонников за поддержку! + + + Благодарим всех наших поклонников за поддержку! + + + Основная локализация + + + Основная локализация + + + Локализация на китайский и другие языки + + + Локализация на китайский и другие языки + + + Всего детей + + + Время игры + + + Время игры + + + Нажмите [Input:0] для выхода. + + + Нажмите [Input:0] для выхода. + + + Разработка + + + Разработка + + + Дизайн и сюжет + + + Дизайн и сюжет + + + Программирование + + + Программирование + + + Производство + + + Производство + + + Мертвая зона + + + Мертвая зона + + + Удалить сохранение + + + Удалить сохранение + + + Дневник принца + + + Хотя я и старший сын, я никогда не был любимчиком отца. Я всегда знал, что он собирается оставить меня ни с чем. + + + ...А вдруг я принял их за монстров? + + + ...А вдруг я приняла их за монстров? + + + Дневник принца + + + Дневник принцессы + + + Запись 17 + + + Запись 17 + + + Я, должно быть, сошел с ума. Сегодня я наткнулся на карнавал прямо в замке. Карнавал с грустным клоуном. + + + Я, должно быть, сошла с ума. Сегодня я наткнулась на карнавал прямо в замке. Карнавал с грустным клоуном. + + + Этот клоун — порядочный наглец, но в таком месте перебирать друзьями не приходится. + + + Этот клоун — порядочный наглец, но в таком месте перебирать друзьями не приходится. + + + Я снова проголодался. К счастью, у меня солидный запас куриных ножек. Я нашел их в канделябре. + + + Я снова проголодалась. К счастью, у меня солидный запас куриных ножек. Я нашла их в канделябре. + + + Этот замок... Иногда мне кажется, что это просто розыгрыш. + + + Этот замок... Иногда мне кажется, что это просто розыгрыш. + + + Дневник принца + + + Дневник принцессы + + + Запись 18 + + + Запись 18 + + + Я одолел стража башни, и дверь тронного зала снова передала мне часть своей силы. + + + Я одолела стража башни, и дверь тронного зала снова передала мне часть своей силы. + + + Хотя я и старшая дочь, я никогда не была любимицей отца. Я всегда знала, что он собирается оставить меня ни с чем. + + + Но если я найду лекарство, все изменится. + + + Эта победа просто окрыляет меня! Никогда еще я не чувствовал себя настолько уверенно, настолько решительно... как дома. Еще немного, и я смогу получить желанную награду! + + + Эта победа просто окрыляет меня! Никогда еще я не чувствовала себя настолько уверенно, настолько решительно... как дома. Еще немного, и я смогу получить желанную награду! + + + Я так близок к цели! Мой отец будет гордиться мной! + + + Я так близка к цели! Мой отец будет гордиться мной! + + + Дневник принца + + + Дневник принцессы + + + Запись 19 + + + Запись 19 + + + Я простоял перед воротами подземелья дольше, чем хотелось бы. + + + Я простояла перед воротами подземелья дольше, чем хотелось бы. + + + Мое мужество испарилось: я видел обитающих под землей чудовищ, и по сравнению с ними мои прежние противники кажутся детской игрой. + + + Мое мужество испарилось: я видела обитающих под землей чудовищ, и по сравнению с ними мои прежние противники кажутся детской игрой. + + + Я должен собраться с духом, собраться с силами. В подземелье так темно... Я боюсь заблудиться. + + + Я должна собраться с духом, собраться с силами. В подземелье так темно... Я боюсь заблудиться. + + + Дневник принца + + + Дневник принцессы + + + Запись 20 + + + Запись 20 + + + Я думал, что знаю, что такое темнота, но здесь, в подземелье, у темноты есть голос. + + + Я думала, что знаю, что такое темнота, но здесь, в подземелье, у темноты есть голос. + + + Но если я найду лекарство, все изменится. + + + После смерти отца победитель наверняка унаследует трон! + + + Она зовет меня через решетки, дразнит меня из-за угла. + + + Она зовет меня через решетки, дразнит меня из-за угла. + + + Тьма кажется настолько плотной, почти осязаемой, и в ней обитают чудовища. Они быстро перемещаются по коридорам и выглядят ужаснее, чем все, что я видел до этого. + + + Тьма кажется настолько плотной, почти осязаемой, и в ней обитают чудовища. Они быстро перемещаются по коридорам и выглядят ужаснее, чем все, что я видела до этого. + + + Нужно быть благоразумным, и не лезть на рожон. Атака в лоб может стоить мне жизни. + + + Нужно быть благоразумной, и не лезть на рожон. Атака в лоб может стоить мне жизни. + + + Дневник принца + + + Дневник принцессы + + + Запись 21 + + + Запись 21 + + + Получилось! Я победил хозяина подземелья! Мне осталось лишь войти в тронный зал. + + + Получилось! Я победила хозяина подземелья! Мне осталось лишь войти в тронный зал. + + + После этого король вознаградит меня за доблесть и признает наследником трона! + + + После этого король вознаградит меня за доблесть и признает наследницей трона! + + + Меня, а не моих безликих братьев! + + + Меня, а не моих безликих братьев! + + + Дневник принца + + + Дневник принцессы + + + Запись 22 + + + Запись 22 + + + После смерти отца победитель наверняка унаследует трон! + + + После моего возвращения моя семья вернется в королевские палаты в столице, где к нам вновь начнут относиться с должным почтением! + + + Я заканчиваю приготовления. От властелина этого замка меня отделяет лишь золотая дверь. + + + Я заканчиваю приготовления. От властелина этого замка меня отделяет лишь золотая дверь. + + + Мое тело пронизывает нервная дрожь. Кто знает, страх это или волнение? Я знаю одно: мои приключения наконец подходят к концу. + + + Мое тело пронизывает нервная дрожь. Кто знает, страх это или волнение? Я знаю одно: мои приключения наконец подходят к концу. + + + Я почти уже забыл, зачем явился в этот замок, но теперь вспомнил. + + + Я почти уже забыла, зачем явилась в этот замок, но теперь вспомнила. + + + Я превзошел своих братьев! Я спасу короля и выйду из этого замка великим героем. Моя семья удостоится давно заслуженных почестей. + + + Я превзошла своих братьев! Я спасу короля и выйду из этого замка великой героиней. Моя семья удостоится давно заслуженных почестей. + + + Сейчас я войду в тронный зал. + + + Сейчас я войду в тронный зал. + + + Дневник принца + + + Дневник принцессы + + + Запись 23 + + + Запись 23 + + + Я понятия не имел, какое сокровище хранится в этом замке. Я знал лишь, что оно способно исцелить короля. + + + Я понятия не имела, какое сокровище хранится в этом замке. Я знала лишь, что оно способно исцелить короля. + + + Кто мог подумать, что это фонтан юности? + + + Кто мог подумать, что это фонтан юности? + + + Я думал, что у фонтана меня встретит невообразимо страшное чудовище. Я думал, что для победы над ним мне потребуется вся моя сила. + + + Я думала, что у фонтана меня встретит невообразимо страшное чудовище. Я думала, что для победы над ним мне потребуется вся моя сила. + + + После моего возвращения моя семья вернется в королевские палаты в столице, где к нам вновь начнут относиться с должным почтением! + + + Мы не станем больше терпеть сплетни и клевету моих братьев. Другие герцоги будут склонять головы перед нами! Но я забегаю вперед. + + + Но когда я вступил в тронный зал и увидел своего отца, короля, сидящим на помосте с кубком в руке, я понял, что все пропало. + + + Но когда я вступила в тронный зал и увидела своего отца, короля, сидящим на помосте с кубком в руке, я поняла, что все пропало. + + + Он никогда не умрет... + + + Он никогда не умрет... + + + ...и мне никогда не стать наследником трона. + + + ...и мне никогда не стать наследницей трона. + + + Мои чувства невозможно описать. + + + Мои чувства невозможно описать. + + + Дневник принца + + + Дневник принцессы + + + Запись 24 + + + Запись 24 + + + .............................. + + + .............................. + + + .... + + + .... + + + Дневник принца + + + Дневник принцессы + + + Запись 25 + + + Запись 25 + + + Мы не станем больше терпеть сплетни и клевету моих братьев. Другие герцоги будут склонять головы перед нами! Но я забегаю вперед. + + + Я должен помнить о своих целях: покорить замок, найти лекарство, получить награду. + + + Сегодняшний день ― первый день ожидающей меня вечности. + + + Сегодняшний день ― первый день ожидающей меня вечности. + + + Я понятия не имел, какое сокровище хранится в этом замке. Я знал лишь, что оно способно исцелить короля от его недуга. + + + Я понятия не имела, какое сокровище хранится в этом замке. Я знала лишь, что оно способно исцелить короля от его недуга. + + + ... Кто бы мог подумать, что это фонтан юности? Легенда, которая дарит вечную жизнь. + + + ... Кто бы мог подумать, что это фонтан юности? Легенда, которая дарит вечную жизнь. + + + И когда я смотрел на тело короля у своих ног, я понял, что это неизбежно: дети всегда расплачиваются за грехи отцов. + + + И когда я смотрела на тело короля у своих ног, я поняла, что это неизбежно: дети всегда расплачиваются за грехи отцов. + + + Я вошел в этот замок с мечом в руках, героем, спасителем... + + + Я вошла в этот замок с мечом в руках, героиней, спасительницей... + + + Но все, что останется после меня, это наследство мошенника. + + + Но все, что останется после меня, это наследство мошенника. + + + Я чувствую твой гнев, но пойми: твою семью разорил вовсе не я. + + + Я чувствую твой гнев, но пойми: твою семью разорила вовсе не я. + + + Как только король вошел в этот замок, королевскую казну забрал Харон. Моя семья и все наши семьи лишились надежды на лучшую жизнь. + + + Как только король вошел в этот замок, королевскую казну забрал Харон. Моя семья и все наши семьи лишились надежды на лучшую жизнь. + + + И я предвижу лишь отчаяние и нищету, в которые погрузится королевство. Мне некуда было возвращаться. + + + И я предвижу лишь отчаяние и нищету, в которые погрузится королевство. Мне некуда было возвращаться. + + + Во имя своих детей и детей моих детей я сижу здесь, бесстрастный и бессмертный, и жду тебя. + + + Во имя своих детей и детей моих детей я сижу здесь, бесстрастная и бессмертная, и жду тебя. + + + Я должна помнить о своих целях: покорить замок, найти лекарство, получить награду. + + + Дневник принца + + + Иоганн + + + Иоганн + + + Что это? Ты издеваешься надо мной?! + + + Что это? Ты издеваешься надо мной?! + + + Бесчисленные поколения твоих предков пожертвовали своими жизнями, чтобы попасть сюда и свершить свое бессмысленное правосудие. И вот ты здесь и издеваешься надо мной? + + + Бесчисленные поколения твоих предков пожертвовали своими жизнями, чтобы попасть сюда и свершить свое бессмысленное правосудие. И вот ты здесь и издеваешься надо мной? + + + Что же, пусть так. Забудем твое невежество. Начнем! + + + Что же, пусть так. Забудем твое невежество. Начнем! + + + Иоганн + + + Иоганн + + + Зачем тебе драться со мной? Сколько сыновей и дочерей погибло в твоих жалких попытках отомстить? + + + Зачем тебе драться со мной? Сколько сыновей и дочерей погибло в твоих жалких попытках отомстить? + + + Твою страну погубил не я, а король! + + + Твою страну погубила не я, а король! + + + Он лгал нам. Он утверждал, что ранен, но на самом деле ему угрожало время! + + + Он лгал нам. Он утверждал, что ранен, но на самом деле ему угрожало время! + + + Он стравил своих детей между собой, пожертвовал всем во имя своих эгоистичных желаний и наконец оставил нас одних и без единого гроша. + + + Он стравил своих детей между собой, пожертвовал всем во имя своих эгоистичных желаний и наконец оставил нас одних и без единого гроша. + + + И я выбрал то, что оставалось. Я отказался от короля и своей страны... + + + И я выбрала то, что оставалось. Я отказалась от короля и своей страны… + + + Дневник принцессы + + + Запись 3 + + + И выбрал новую семью! + + + И выбрала новую семью! + + + Иоганн + + + Иоганн + + + Думаешь, тебе удалось меня убить? + + + Думаешь, тебе удалось меня убить? + + + Я прожил больше тысячи лет... и проживу еще десять тысяч! + + + Я прожила больше тысячи лет... и проживу еще десять тысяч! + + + Александр... Хидр... Понсе де Леон... + + + Александр... Хидр... Понсе де Леон... + + + Я оказался далеко не первым, кому удалось добраться до фонтана... + + + Я оказалась далеко не первой, кому удалось добраться до фонтана... + + + Но я стану последним! + + + Но я стану последней! + + + Фонтан юности + + + Фонтан юности + + + ... + + + ... + + + Тебе удалось победить меня... Но какой ценой? + + + Тебе удалось победить меня... Но какой ценой? + + + Запись 3 + + + Я заплатил за вход и вошел в замок. В качестве платы проклятый Харон забрал все мое золото. + + + Да, я убил короля, но лишь после того, как он предал своих подданных. + + + Да, я убила короля, но лишь после того, как он предал своих подданных. + + + Спроси себя: какое правосудие свершилось? + + + Спроси себя: какое правосудие свершилось? + + + В конечном счете, все мы повинны в одном и том же грехе. Вспомни своих предков ― такова цена беспрекословной верности. + + + В конечном счете, все мы повинны в одном и том же грехе. Вспомни своих предков ― такова цена беспрекословной верности. + + + ... + + + ... + + + ... + + + ... + + + Солнце... + + + Солнце... + + + Я уже забыл, какое оно... + + + Я уже забыла, какое оно... + + + Я заплатила за вход и вошла в замок. В качестве платы проклятый Харон забрал все мое золото. + + + Он опустошил даже мои личные сундуки! Я оставил жену и детей без единого гроша. + + + Он опустошил даже мои личные сундуки! Я оставила мужа и детей без единого гроша. + + + Дневник принцессы + + + Запись 1 + + + Он сказал, что такую цену платят все, кто хочет попасть в замок, и это справедливо. + + + Он сказал, что такую цену платят все, кто хочет попасть в замок, и это справедливо. + + + Это справедливо потому, что из тех, кто вошел в этот замок, еще никто не вернулся. Но со мной все будет по-другому. + + + Это справедливо потому, что из тех, кто вошел в этот замок, еще никто не вернулся. Но со мной все будет по-другому. + + + Я одержу победу! Во владении мечом мне нет равных, даже среди моих братьев. + + + Я одержу победу! Во владении мечом мне нет равных, даже среди моих братьев. + + + Дневник принца + + + Дневник принцессы + + + Запись 4 + + + Запись 4 + + + В этом замке все не как у людей. Я то и дело сбиваюсь с пути и не могу определить направление по солнцу или звездам. + + + В этом замке все не как у людей. Я то и дело сбиваюсь с пути и не могу определить направление по солнцу или звездам. + + + Я то и дело вынужден возвращаться назад и составлять карту, чтобы не бегать кругами. + + + Я то и дело вынуждена возвращаться назад и составлять карту, чтобы не бегать кругами. + + + Карты, найденные мной на трупах других героев, на удивление неточные. Такое впечатление, что это вообще карты другого замка! + + + Карты, найденные мной на трупах других героев, на удивление неточные. Такое впечатление, что это вообще карты другого замка! + + + Возможно, это место способно затуманить мозги... + + + Возможно, это место способно затуманить мозги... + + + Или камни пола действительно двигаются у меня под ногами? + + + Или камни пола действительно двигаются у меня под ногами? + + + Запись 1 + + + Измена! Наемный убийца нанес рану моему отцу, королю! + + + Дневник принца + + + Дневник принцессы + + + Запись 5 + + + Запись 5 + + + Я не могу выйти через главные ворота, но это не имеет значения. Я полон решимости и назад не поверну! + + + Я не могу выйти через главные ворота, но это не имеет значения. Я полна решимости и назад не поверну! + + + Пока что ни одна из найденных мной карт не совпала с моей. + + + Пока что ни одна из найденных мной карт не совпала с моей. + + + Однако сравнивая их, я обнаружил кое-какие общие черты. Лес, похоже, всегда справа, а башня сверху... + + + Однако сравнивая их, я обнаружила кое-какие общие черты. Лес, похоже, всегда справа, а башня сверху... + + + А что внизу? Надеюсь, я этого никогда не узнаю. + + + А что внизу? Надеюсь, я этого никогда не узнаю. + + + Дневник принца + + + Дневник принцессы + + + Запись 6 + + + Запись 6 + + + Я никогда не любил темноту. Предпочитаю видеть лицо врага. + + + Я никогда не любила темноту. Предпочитаю видеть лицо врага. + + + Но сейчас мне приходится пробираться по этим темным коридорам почти на ощупь, держа одну руку на рукояти меча. Тут никогда не угадаешь, что ждет тебя за углом. + + + Но сейчас мне приходится пробираться по этим темным коридорам почти на ощупь, держа одну руку на рукояти меча. Тут никогда не угадаешь, что ждет тебя за углом. + + + Измена! Наемный убийца нанес рану моему отцу, королю! + + + Чтобы навести порядок в королевстве, король послал меня и моих братьев найти способ исцелить его. Вместе мы отправимся в проклятый лес и войдем в Замок Хэмсон. + + + Я лучший боец в стране, однако даже мне непросто сдерживать натиск этих демонов. + + + Я лучший боец в стране, однако даже мне непросто сдерживать натиск этих демонов. + + + Мои братья должны радоваться тому, что я опередил их. Братьям повезло, потому что эти коридоры и монстры им не по зубам. + + + Мои братья должны радоваться тому, что я опередила их. Братьям повезло, потому что эти коридоры и монстры им не по зубам. + + + Дневник принца + + + Дневник принцессы + + + Запись 7 + + + Запись 7 + + + По-прежнему ночь. Из каждого окна видна одна и та же равнодушная луна, но, готов поклясться, я провел здесь уже целый день. + + + По-прежнему ночь. Из каждого окна видна одна и та же равнодушная луна, но, готова поклясться, я провела здесь уже целый день. + + + Видимо, все дело в адреналине. Я чувствую себя невероятно могучим и противостою столь же могучим врагам. С боем прорываясь через эти комнаты, убивая одного врага за другим, я чувствую себя героем! + + + Видимо, все дело в адреналине. Я чувствую себя невероятно могучей и противостою столь же могучим врагам. С боем прорываясь через эти комнаты, убивая одного врага за другим, я чувствую себя героиней! + + + Враги, обитающие в этом замке, словно созданы для меня. Такое ощущение, что они обучают меня, показывают мне дорогу и следят за мной. + + + Враги, обитающие в этом замке, словно созданы для меня. Такое ощущение, что они обучают меня, показывают мне дорогу и следят за мной. + + + Это звучит дико, но если этот замок способен ощущать присутствие чужаков, он может питать и зловещие планы. Если я прав, все эти залы и коридоры заманивают меня в ловушку. + + + Это звучит дико, но если этот замок способен ощущать присутствие чужаков, он может питать и зловещие планы. Если я права, все эти залы и коридоры заманивают меня в ловушку. + + + Нужно быть начеку. + + + Нужно быть начеку. + + + Дневник принца + + + Дневник принцессы + + + Чтобы навести порядок в королевстве, король послал меня и моих братьев найти способ исцелить его. Вместе мы отправимся в проклятый лес и войдем в Замок Хэмсон. + + + Этот проклятый замок стоит на опушке леса с незапамятных времен, однако по слухам в нем спрятан предмет, способный излечить любой недуг или рану. + + + Запись 8 + + + Запись 8 + + + Осмотрев трупы героев, найденные мной в замке, я пришел к следующим выводам: + + + Осмотрев трупы героев, найденные мной в замке, я пришла к следующим выводам: + + + 1: Многие из них не запаслись провизией. Думаю, многие из них умерли от голода. Мои запасы тоже на исходе. Нужно срочно их пополнить. + + + 1: Многие из них не запаслись провизией. Думаю, многие из них умерли от голода. Мои запасы тоже на исходе. Нужно срочно их пополнить. + + + 2: Многие герои раздеты. Этим объясняется то, почему местные зомби все поголовно в штанах. + + + 2: Многие герои раздеты. Этим объясняется то, почему местные зомби все поголовно в штанах. + + + 3: Я прошел дальше всех, поскольку я за целый час не встретил ни одного трупа. + + + 3: Я прошла дальше всех, поскольку я за целый час не встретила ни одного трупа. + + + Дневник принца + + + Дневник принцессы + + + Запись 9 + + + Запись 9 + + + Дверь, ведущая в тронный зал, сводит меня с ума! За ней меня ждет лекарство для короля и моя награда, однако дверь остается недвижима, словно издеваясь надо мной. + + + Дверь, ведущая в тронный зал, сводит меня с ума! За ней меня ждет лекарство для короля и моя награда, однако дверь остается недвижима, словно издеваясь надо мной. + + + Я пытался нажать на нее плечом, выбить ногой, кричал "Сезам, откройся!", но все бесполезно. + + + Я пыталась нажать на нее плечом, выбить ногой, кричала "Сезам, откройся!", но все бесполезно. + + + Дверь расписана странными знаками. Один из них напоминает чудовище, с которым я чуть не столкнулся в глубине замка. Возможно, это не случайное сходство... + + + Дверь расписана странными знаками. Один из них напоминает чудовище, с которым я чуть не столкнулась в глубине замка. Возможно, это не случайное сходство… + + + Этот проклятый замок стоит на опушке леса с незапамятных времен, однако по слухам в нем спрятан предмет, способный излечить любой недуг или рану. + + + Сегодня ночью я опережу своих братьев и отправлюсь в путь, пока они будут спать. + + + Дневник принца + + + Дневник принцессы + + + Запись 10 + + + Запись 10 + + + Знаки на двери замка были подсказкой! Я убил огромное чудовище, похожее на один из знаков, и услышал, как за дверями тронного зала что-то сдвинулось. + + + Знаки на двери замка были подсказкой! Я убила огромное чудовище, похожее на один из знаков, и услышала, как за дверями тронного зала что-то сдвинулось. + + + Словно во сне, я отчетливо видел мысленным взором знак на двери. + + + Словно во сне, я отчетливо видела мысленным взором знак на двери. + + + Это было невероятное чувство. + + + Это было невероятное чувство. + + + По крайней мере, я знаю, что я на верном пути. Однако нужно торопиться, король может скончаться от ран в любой момент... + + + По крайней мере, я знаю, что я на верном пути. Однако нужно торопиться, король может скончаться от ран в любой момент... + + + Но сначала мне надо отдохнуть. Завтра я отправлюсь в лес. + + + Но сначала мне надо отдохнуть. Завтра я отправлюсь в лес. + + + Дневник принца + + + Дневник принцессы + + + Запись 11 + + + Запись 11 + + + Этот лес не похож ни на один из виденных мной. Он выглядит тихим и в то же время внушает ужас. Я стою на свежей траве, но рядом зияет пропасть, способная, судя по размерам, поглотить меня. + + + Этот лес не похож ни на один из виденных мной. Он выглядит тихим и в то же время внушает ужас. Я стою на свежей траве, но рядом зияет пропасть, способная, судя по размерам, поглотить меня. + + + Сегодня ночью я опережу своих братьев и отправлюсь в путь, пока они будут спать. + + + Если я не выполню просьбу отца, то опозорю свое имя. + + + Я до сих пор не услышал звука падения камешка, который я туда бросил. Один неосторожный шаг, и меня ждет бесконечный полет вниз. Эта мысль вселяет в меня страх. + + + Я до сих пор не услышала звука падения камешка, который я туда бросила. Один неосторожный шаг, и меня ждет бесконечный полет вниз. Эта мысль вселяет в меня страх. + + + Eine Ewigkeit aus Dunkelheit ist beängstigender als jede Bestie, die ich bis jetzt bekämpft habe. Was würde mich zuerst töten, wenn ich fallen würde? Der Hunger oder ich selbst? + + + Eine Ewigkeit aus Dunkelheit ist beängstigender als jede Bestie, die ich bis jetzt bekämpft habe. Was würde mich zuerst töten, wenn ich fallen würde? Der Hunger oder ich selbst? + + + Кстати, я использую эту расщелину в лесу, чтобы справлять нужду. Не исключено, что я посылаю свои экскременты в другое измерение... + + + Кстати, я использую эту расщелину в лесу, чтобы справлять нужду. Не исключено, что я посылаю свои экскременты в другое измерение... + + + Дневник принца + + + Дневник принцессы + + + Запись 12 + + + Запись 12 + + + Я нашел решение проблемы голода. В этом лесу полно вкуснейших грибов. + + + Я нашла решение проблемы голода. В этом лесу полно вкуснейших грибов. + + + Помимо грибов, я нашел куриные ножки, а также золотые монеты и бутылочки с чистой водой... Недавно я расколол старый пень и нашел внутри мешок с монетами. + + + Помимо грибов, я нашла куриные ножки, а также золотые монеты и бутылочки с чистой водой... Недавно я расколола старый пень и нашла внутри мешок с монетами. + + + Иногда мне кажется, что я сошел с ума. + + + Иногда мне кажется, что я сошла с ума. + + + ...Кстати, что стало с луной? Она выглядит просто огромной! + + + ...Кстати, что стало с луной? Она выглядит просто огромной! + + + Дневник принца + + + Дневник принцессы + + + Если я не выполню просьбу отца, то опозорю свое имя. + + + Дневник принца + + + Запись 13 + + + Запись 13 + + + Я сразил лесное чудовище и вновь почувствовал, что дверь в тронный зал стала менее прочной. + + + Я сразила лесное чудовище и вновь почувствовала, что дверь в тронный зал стала менее прочной. + + + Пока мои предположения подтверждаются. Каждую часть замка охраняет свой страж. Неужели это испытание воли? Если так, я должен его выдержать! Чем глубже я забираюсь, тем большую отвагу ощущаю! + + + Пока мои предположения подтверждаются. Каждую часть замка охраняет свой страж. Неужели это испытание воли? Если так, я должна его выдержать! Чем глубже я забираюсь, тем большую отвагу ощущаю! + + + Завтра я отправлюсь в башню. Я явно в ударе! + + + Завтра я отправлюсь в башню. Я явно в ударе! + + + Дневник принца + + + Дневник принцессы + + + Запись 14 + + + Запись 14 + + + Я методично очищаю комнаты от демонов, готовясь к схватке с очередным стражем, но при этом утрачиваю чувство времени...и не только его... + + + Я методично очищаю комнаты от демонов, готовясь к схватке с очередным стражем, но при этом утрачиваю чувство времени...и не только его... + + + Когда я вошел в башню, время словно остановилось. Или у меня просто кружится голова? Никогда не любил высоту... кажется... + + + Когда я вошла в башню, время словно остановилось. Или у меня просто кружится голова? Никогда не любила высоту... кажется... + + + Мне все труднее вспоминать свое прошлое... + + + Мне все труднее вспоминать свое прошлое... + + + Дневник принца + + + Дневник принцессы + + + Дневник принцессы + + + Запись 2 + + + Запись 15 + + + Запись 15 + + + Я помню, что был знаменитым путешественником. Я был куда лучшим бойцом, чем мои братья. Это я помню точно. Пока они тратили время на чтение книг, я убивал разбойников и чудовищ. + + + Я помню, что была знаменитой путешественницей. Я была куда лучшим бойцом, чем мои братья. Это я помню точно. Пока они тратили время на чтение книг, я убивала разбойников и чудовищ. + + + Я никогда не мог понять, почему отец предпочитал их мне? В сказках все обычно наоборот. + + + Я никогда не могла понять, почему отец предпочитал их мне? В сказках все обычно наоборот. + + + Удача улыбается смелым, а не унылым умникам... Вроде так. + + + Я никогда не мог понять, почему отец предпочитал их мне? В сказках все обычно наоборот. + + + Хотел бы я посмотреть, как мои братья попытаются перехитрить мой меч! + + + Хотел бы я посмотреть, как мои братья попытаются перехитрить мой меч! + + + Дневник принца + + + Дневник принцессы + + + Запись 16 + + + Запись 16 + + + А что, если с того момента, когда я вошел в замок, прошли годы? Я становлюсь мастером в деле истребления монстров, но мне кажется, прошла целая вечность. + + + А что, если с того момента, когда я вошла в замок, прошли годы? Я становлюсь мастерицей в деле истребления монстров, но мне кажется, прошла целая вечность. + + + Я уже не помню, как выглядят другие люди. + + + Я уже не помню, как выглядят другие люди. + + + А вдруг они решили, что я потерпел неудачу? Вдруг один из моих братьев опередил меня и раздобыл лекарство? + + + А вдруг они решили, что я потерпела неудачу? Вдруг один из моих братьев опередил меня и раздобыл лекарство? + + + Запись 2 + + + Запись + + + Запись + + + Замок Хэмсон + + + Замок Хэмсон + + + Край Тьмы + + + Край Тьмы + + + Леса Абхазии + + + Леса Абхазии + + + Майя + + + Майя + + + Выберите категорию + + + Нужна руна + + + Нужна руна + + + Сведения о покупке + + + Сведения о покупке + + + {0} для открытия + + + {0} для открытия + + + Руна + + + Руна + + + Выберите категорию + + + Инструкции + + + Инструкции + + + [Input:0] чтобы выбрать/надеть. + + + [Input:0] чтобы выбрать/надеть. + + + [Input:2] для отмены/закрытия меню. + + + [Input:2] для отмены/закрытия меню. + + + Стрелки = перемещение в меню + + + Стрелки = перемещение в меню + + + [Button:LeftStick] для перемещения. + + + [Button:LeftStick] для перемещения. + + + Убито + + + Убито + + + Нажмите [Input:0] для выхода. + + + Нажмите [Input:0] для выхода. + + + Скелет + + + Мегаслизень + + + Искрища + + + Искрища + + + Искрец + + + Искрец + + + Мимик + + + Мимик + + + Мимяка + + + Мимяка + + + Мегамимик + + + Мегамимик + + + Сундук + + + Сундук + + + Барбатос + + + Барбатос + + + Столас + + + Столас + + + Берит + + + Берит + + + Амон + + + Амон + + + Мегаслизень + + + Геродот + + + Фокалор + + + Фокалор + + + Халфас + + + Халфас + + + Хидр + + + Хидр + + + Алекс IV + + + Алекс IV + + + Астродот + + + Астродот + + + Граф + + + Граф + + + Два Иоганна + + + Два Иоганна + + + Турель + + + Турель + + + Привратник + + + Привратник + + + Бессмертный + + + Бессмертный + + + Геродот + + + Цепняк + + + Забытый + + + Забытый + + + Покинутый + + + Покинутый + + + Караульный + + + Караульный + + + Изменник + + + Изменник + + + Фонтан + + + Фонтан + + + Берит и Хальфас + + + Берит и Хальфас + + + Барбатос и Амон + + + Барбатос и Амон + + + Столас и Фокалор + + + Столас и Фокалор + + + Цепняк + + + Цепень + + + Цепень + + + Цепеллин + + + Цепеллин + + + Пантеон + + + Пантеон + + + Землемет + + + Землемет + + + Летун + + + Летун + + + Планетоед + + + Планетоед + + + Огнеплюй + + + Огнеплюй + + + Скелет + + + Костяк + + + Жгун + + + Жгун + + + Солнцеед + + + Солнцеед + + + Маг + + + Маг + + + Холодок + + + Холодок + + + Морозко + + + Морозко + + + Ледок + + + Ледок + + + Мерзлота + + + Мерзлота + + + Шпион + + + Шпион + + + Зрачок + + + Зрачок + + + Надзор + + + Надзор + + + Костяк + + + Реброид + + + Хидр + + + Хидр + + + Злоба + + + Злоба + + + Ярость + + + Ярость + + + Гнев + + + Гнев + + + Александр + + + Александр + + + Страж + + + Страж + + + Стражник + + + Стражник + + + Боец + + + Боец + + + Гигант + + + Гигант + + + Шипастик + + + Шипастик + + + Реброид + + + Невольник + + + Шиполет + + + Шиполет + + + Шипострел + + + Шипострел + + + Шип смерти + + + Шип смерти + + + Доспехи + + + Доспехи + + + Барон + + + Барон + + + Крушила + + + Крушила + + + Гладиатор + + + Гладиатор + + + Волк + + + Волк + + + Варг + + + Варг + + + Варгун + + + Варгун + + + Невольник + + + Сторож + + + Суперварг + + + Суперварг + + + Зомби + + + Зомби + + + Зомбяка + + + Зомбяка + + + Зомбище + + + Зомбище + + + Зомбила + + + Зомбила + + + Энергон + + + Энергон + + + Мастертрон + + + Мастертрон + + + Вольтрон + + + Вольтрон + + + Мегавольтрон + + + Мегавольтрон + + + Ниндзюк + + + Ниндзюк + + + Сторож + + + Лорд + + + Ниндзяк + + + Ниндзяк + + + Ниндзец + + + Ниндзец + + + Ниндзя + + + Ниндзя + + + Бутон + + + Бутон + + + Семицвет + + + Семицвет + + + Цветок смерти + + + Цветок смерти + + + Уголек + + + Уголек + + + Огонек + + + Огонек + + + Огниво + + + Огниво + + + Понсе де Леон + + + Понсе де Леон + + + Лорд + + + Гад + + + Капкан + + + Капкан + + + Лучник + + + Лучник + + + Егерь + + + Егерь + + + Снайпер + + + Снайпер + + + Рукострел + + + Рукострел + + + Иоганн + + + Иоганн + + + Фонтан + + + Фонтан + + + Фонтан юности + + + Фонтан юности + + + Ужастик + + + Ужастик + + + Кошмарик + + + Кошмарик + + + Гад + + + Слизнюк + + + Пейзаж + + + Пейзаж + + + Холст + + + Холст + + + Звездун + + + Звездун + + + Звезда + + + Звезда + + + Звездища + + + Звездища + + + Звездец + + + Звездец + + + Окорок + + + Окорок + + + Цыпленок + + + Цыпленок + + + Курица + + + Курица + + + Наслаждец + + + Наслаждец + + + Слизнюк + + + Слизняк + + + Страж + + + Страж + + + Страж XL + + + Страж XL + + + Страж 2000 + + + Страж 2000 + + + Мегаробостраж + + + Мегаробостраж + + + Всадник + + + Всадник + + + Жеребец + + + Жеребец + + + Жуткобыла + + + Жуткобыла + + + Пони + + + Пони + + + Искорка + + + Искорка + + + Искра + + + Искра + + + Слизняк + + + Прыжок + + + Проклятие + + + Проклятие + + + Благодать + + + Благодать + + + Сбор архитектора + + + Сбор архитектора + + + Бонус НИ+ + + + Бонус НИ+ + + + Прыжок + + + Спринт + + + Спринт + + + Вампир + + + Вампир + + + Небо + + + Небо + + + Мана + + + Мана + + + Баланс + + + Баланс + + + Возмездие + + + Возмездие + + + Награда + + + Награда + + + Спешка + + + Спешка + + + Воинский + + + Убойный + + + Убойная + + + Доходный + + + Доходная + + + Кровавый + + + Кровавая + + + Зеркальный + + + Зеркальная + + + Святой + + + Святая + + + Темный + + + Темная + + + Воинская + + + Серебряный + + + Серебряная + + + Боевой + + + Боевая + + + Имперский + + + Имперская + + + Царский + + + Царская + + + Рыцарский + + + Рыцарская + + + Егерский + + + Егерская + + + Небесный + + + Небесная + + + Драконий + + + Драконья + + + Меч + + + Меч + + + Плащ + + + Плащ + + + Наруч + + + Наруч + + + Шлем + + + Шлем + + + Дублет + + + Дублет + + + Нет + + + Нет + + + Меч + + + Меч + + + Плащ + + + Плащ + + + Наруч + + + Наруч + + + Шлем + + + Шлем + + + Дублет + + + Дублет + + + Нет + + + Нет + + + Дает возможность прыгать в воздухе. Несколько рун = несколько прыжков. + + + Враги круче, но и награды больше. Чем больше рун, тем круче враги. + + + Враги круче, но и награды больше. Чем больше рун, тем круче враги. + + + Уровень врагов растет медленнее, но и награды меньше. Чем больше рун, тем медленнее рост. + + + Уровень врагов растет медленнее, но и награды меньше. Чем больше рун, тем медленнее рост. + + + Дает возможность прыгать в воздухе. Несколько рун = несколько прыжков. + + + Дает возможность делать бросок на короткое расстояние. Чем больше рун, тем больше бросков. + + + Дает возможность делать бросок на короткое расстояние. Чем больше рун, тем больше бросков. + + + Убивая врага, герой высасывает его здоровье. Чем больше рун, тем сильней эффект. + + + Убивая врага, героиня высасывает его здоровье. Чем больше рун, тем сильней эффект. + + + Позволяет летать. Чем больше рун, тем дольше продолжается полет. + + + Позволяет летать. Чем больше рун, тем дольше продолжается полет. + + + Герой получает ману за убитых врагов. Чем больше рун, тем больше маны. + + + Героиня получает ману за убитых врагов. Чем больше рун, тем больше маны. + + + Герой получает HP и MP за убитых врагов. Чем больше рун, тем сильней эффект. + + + Героиня получает HP и MP за убитых врагов. Чем больше рун, тем сильней эффект. + + + Наносит врагам урон, полученный героем. Чем больше рун, тем больше отражаемый урон. + + + Наносит врагам урон, полученный героиней. Чем больше рун, тем больше отражаемый урон. + + + Увеличивает стоимость монет. Чем больше рун, тем больше золота приносят монеты. + + + Увеличивает стоимость монет. Чем больше рун, тем больше золота приносят монеты. + + + Увеличивается скорость бега героя. Чем больше рун, тем больше скорость. + + + Увеличивается скорость бега героини. Чем больше рун, тем больше скорость. + + + Враги становятся круче. + + + Враги становятся круче. + + + Враги растут медленнее. + + + Враги растут медленнее. + + + Нажмите [Input:10], находясь в воздухе. + + + Нажмите [Input:10], находясь в воздухе. + + + [Input:14] или [Input:15] для броска. + + + [Input:14] или [Input:15] для броска. + + + Здоровье за убитых врагов. + + + Здоровье за убитых врагов. + + + Нажмите [Input:10], находясь в воздухе. + + + Нажмите [Input:10], находясь в воздухе. + + + Мана за убитых врагов. + + + Мана за убитых врагов. + + + Здоровье и мана за убитых врагов. + + + Здоровье и мана за убитых врагов. + + + Возврат полученного урона врагам. + + + Возврат полученного урона врагам. + + + Монеты стоят дороже. + + + Монеты стоят дороже. + + + Быстрый бег. + + + Быстрый бег. + + + Шанс крит. удара + + + Бросок + + + Бросок + + + Блок + + + Блок + + + Парение + + + Парение + + + Можно атаковать снаряды + + + Можно атаковать снаряды + + + Полет + + + Полет + + + Скорость + + + Скорость + + + Нет + + + Нет + + + Шанс крит. удара + + + Урон крит. удара + + + Урон крит. удара + + + Вампиризм + + + Вампиризм + + + Бонус к золоту + + + Бонус к золоту + + + Мана + + + Мана + + + Бонус к опыту + + + Бонус к опыту + + + Удар в воздухе + + + Удар в воздухе + + + Прыжок + + + Прыжок + + + Возврат урона + + + Возврат урона + + + Награды увеличиваются на {0} % + + + Награды увеличиваются на {0} % + + + Враги становятся на {0} ур. круче + + + Враги становятся на {0} ур. круче + + + Враги растут на {0} ед. медленнее + + + Враги растут на {0} ед. медленнее + + + Враги растут на {0} ед. медленнее + + + Враги растут на {0} ед. медленнее + + + Прыжок {0} раз(а) + + + Прыжок {0} раз(а) + + + Прыжок {0} раз + + + Прыжок {0} раз + + + Бросок до {0} раз(а) + + + Бросок до {0} раз(а) + + + Бросок до {0} раза + + + Бросок до {0} раза + + + Дает {0} HP за каждого убитого + + + Дает {0} HP за каждого убитого + + + Полет на {0} сек. + + + Полет на {0} сек. + + + Полет на {0} сек. + + + Полет на {0} сек. + + + Дает {0} MP за каждого убитого + + + Дает {0} MP за каждого убитого + + + Мана и HP + + + Мана и HP + + + Возврат {0} % полученного урона + + + Возврат {0} % полученного урона + + + Каждая монета стоит на {0} % больше + + + Каждая монета стоит на {0} % больше + + + Бег на {0} % быстрее + + + Бег на {0} % быстрее + + + Покинуть Rogue Legacy + + + Покинуть Rogue Legacy + + + Нажмите [Input:0] для продолжения. + + + Нажмите [Input:0] для продолжения. + + + Солнце... Я уже забыл, какое оно... + + + Солнце... Я уже забыла, какое оно... + + + {0} умирает, виновник гибели ― {1} + + + {0} умирает, виновник гибели ― {1} + + + Нажмите [Input:0] для продолжения. + + + Нажмите [Input:0] для продолжения. + + + {0} умирает, виновник гибели ― {1} + + + {0} умирает, виновник гибели ― {1} + + + {0} умирает, виновник гибели ― {1} + + + {0} умирает, виновник гибели ― {1} + + + {0} погибает от чужого снаряда + + + {0} погибает от чужого снаряда + + + {0} умирает, напоровшись на шипы + + + {0} умирает, напоровшись на шипы + + + {0} умирает + + + {0} умирает + + + {0} признался перед смертью + + + {0} призналась перед смертью + + + [Input:0], чтобы продолжить. + + + [Input:0], чтобы продолжить. + + + Запас HP возрос + + + Запас HP возрос + + + Запас MP возрос + + + Запас MP возрос + + + Сила возросла + + + Сила возросла + + + Маг. урон возрос + + + Маг. урон возрос + + + Броня усилена + + + Броня усилена + + + Макс. вес возрос + + + Макс. вес возрос + + + Медальон собран! + + + Медальон собран! + + + Найдена часть медальона! + + + Найдена часть медальона! + + + Лес всегда находится справа от замка. + + + Руны неба позволяют летать, если нажать [Input:10] в воздухе. + + + Руны неба позволяют летать, если нажать [Input:10] в воздухе. + + + Руны вампиризма и маны очень сильны, если их несколько. + + + Руны вампиризма и маны очень сильны, если их несколько. + + + Руны подвижности ― залог улетности. + + + Руны подвижности ― залог улетности. + + + Не забывайте расширять свое имение. Там можно изучить полезные навыки. + + + Не забывайте расширять свое имение. Там можно изучить полезные навыки. + + + Все классы могут быть улучшены, получая, при этом, уникальные умения. + + + Все классы могут быть улучшены, получая, при этом, уникальные умения. + + + Открытые умения класса можно использовать, нажав [Input:13]. + + + Открытые умения класса можно использовать, нажав [Input:13]. + + + Старайтесь побыстрее улучшить классы, чтобы заполучить полезные умения. + + + Старайтесь побыстрее улучшить классы, чтобы заполучить полезные умения. + + + Не можете пройти комнату? Поищите обходной путь. + + + Не можете пройти комнату? Поищите обходной путь. + + + Покупка снаряжения ― самый быстрый способ повысить параметры. + + + Покупка снаряжения ― самый быстрый способ повысить параметры. + + + Купить снаряжение дешевле и проще, чем повысить параметры героя. + + + Купить снаряжение дешевле и проще, чем повысить параметры героини. + + + Лес всегда находится справа от замка. + + + Майя всегда находится над замком. + + + Надо было выбирать другого наследника. + + + Надо было выбирать другую наследницу. + + + Руны нереально круты. Покупайте их у колдуньи и не забывайте применять! + + + Руны нереально круты. Покупайте их у колдуньи и не забывайте применять! + + + Чтобы применять чары с максимальной отдачей, изучите их тонкости. + + + Чтобы применять чары с максимальной отдачей, изучите их тонкости. + + + Если задеть врага топором на пике траектории, он получит несколько ударов. + + + Если задеть врага топором на пике траектории, он получит несколько ударов. + + + Старайтесь не ловить запущенные шары смерти, чтобы нанести максимум урона. + + + Старайтесь не ловить запущенные шары смерти, чтобы нанести максимум урона. + + + Уклоняйтесь от летящего обратно шакрама, чтобы нанести максимум урона. + + + Уклоняйтесь от летящего обратно шакрама, чтобы нанести максимум урона. + + + Лучше потратить ману и убить врага, чем получить ненужное ранение. + + + Лучше потратить ману и убить врага, чем получить ненужное ранение. + + + Чтобы выжить, важно научиться предугадывать действия врага. + + + Чтобы выжить, важно научиться предугадывать действия врага. + + + Шипастые ловушки реагируют на пульс жертвы. + + + Шипастые ловушки реагируют на пульс жертвы. + + + Нажмите [Input:9] для просмотра карты. + + + Нажмите [Input:9] для просмотра карты. + + + Майя всегда находится над замком. + + + Тьма всегда находится под замком. + + + В сундуках фей хранятся все руны в игре. Руны оказывают колоссальную помощь. + + + В сундуках фей хранятся все руны в игре. Руны оказывают колоссальную помощь. + + + Вы провалили задание сундука фей ― архитектор может дать второй шанс. + + + Вы провалили задание сундука фей ― архитектор может дать второй шанс. + + + Архитектор берет солидную сумму за свои услуги. + + + Архитектор берет солидную сумму за свои услуги. + + + Из убитого босса выпадает солидная сумма денег. + + + Из убитого босса выпадает солидная сумма денег. + + + Похороните меня за свой счет. + + + Похороните меня за свой счет. + + + Приходится несладко? Попробуйте использовать руны благодати. + + + Приходится несладко? Попробуйте использовать руны благодати. + + + Включите "Быстрое падение", чтобы бить вниз и спрыгивать нажатием [Input:18]. + + + Включите "Быстрое падение", чтобы бить вниз и спрыгивать нажатием [Input:18]. + + + Архитектор поможет вам тренироваться в боях с боссами. + + + Архитектор поможет вам тренироваться в боях с боссами. + + + Третий ряд снаряжения обычно имеет побочные эффекты. Внимательно! + + + Третий ряд снаряжения обычно имеет побочные эффекты. Внимательно! + + + Некоторые руны особенно эффективны против отдельных босов. + + + Некоторые руны особенно эффективны против отдельных босов. + + + Тьма всегда находится под замком. + + + Босс вам не по зубам? Попробуйте использовать другие руны! + + + Тренируйтесь побеждать боссов с помощью архитектора. + + + Тренируйтесь побеждать боссов с помощью архитектора. + + + Очень важно качать здоровье! + + + Очень важно качать здоровье! + + + Зеркальные руны позволяют наносить урон неуязвимым объектам. + + + Зеркальные руны позволяют наносить урон неуязвимым объектам. + + + При грамотном применении умения классов способны изменить ход игры. + + + При грамотном применении умения классов способны изменить ход игры. + + + Некоторые классы хорошо справляются с определенными боссами. + + + Некоторые классы хорошо справляются с определенными боссами. + + + Босс вам не по зубам? Попробуйте использовать другие руны! + + + Руны прыжка позволяют подпрыгнуть в воздухе, нажав [Input:10]. + + + Руны прыжка позволяют подпрыгнуть в воздухе, нажав [Input:10]. + + + Руны спринта позволяют совершить бросок с помощью [Input:PLAYER_DASHLEFT] или [Input:PLAYER_DASHRIGHT]. + + + Руны спринта позволяют совершить бросок с помощью [Input:PLAYER_DASHLEFT] или [Input:PLAYER_DASHRIGHT]. + + + У каждого класса есть свои преимущества и недостатки. Меняйте стиль соответствующим образом. + + + У каждого класса есть свои преимущества и недостатки. Меняйте стиль соответствующим образом. + + + Поиск сундуков ― лучший способ добыть золото. + + + Поиск сундуков ― лучший способ добыть золото. + + + Чем опаснее место, тем выше награда. + + + Чем опаснее место, тем выше награда. + + + Я отдаю долг семье... + + + Я отдаю долг семье... + + + Но сохраняю верность лишь себе. + + + Но сохраняю верность лишь себе. + + + золотых + + + золотых + + + HP восстановлено + + + HP восстановлено + + + MP восстановлено + + + MP восстановлено + + + Крепче броня + + + Крепче броня + + + Больше запас здоровья + + + Больше запас здоровья + + + Больше запас маны + + + Больше запас маны + + + Сила атаки + + + Сила атаки + + + Больше магии + + + Больше магии + + + Больше макс. вес + + + Больше макс. вес + + + Сейчас играет + + + Сейчас играет + + + Входим в + + + Входим в + + + Условие сундука фей: + + + Условие сундука фей: + + + Доберитесь до сундука за 15 сек.: + + + Доберитесь до сундука за 15 сек.: + + + Осталось: + + + Осталось: + + + Задание выполнено! + + + Задание выполнено! + + + Задание не выполнено + + + Задание не выполнено + + + Никаких черт + + + Былинный {0} + + + Былинная {0} + + + Великий {0} + + + Великая {0} + + + Сэр {0} {1} + + + Сэр {0} {1} + + + Славный сэр + + + Славный сэр + + + Леди {0} {1} + + + Леди {0} {1} + + + Славная леди + + + Славная леди + + + Никаких черт + + + + + + + + + Легендарный {0} + + + Легендарная {0} + + + Никчемный {0} + + + Никчемная {0} + + + Хилый {0} + + + Хилая {0} + + + Решительный {0} + + + Решительная {0} + + + Стойкий {0} + + + Стойкая {0} + + + Отважный {0} + + + Отважная {0} + + + Доблестный {0} + + + Доблестная {0} + + + [Input:0] для выбора ребенка. + + + [Input:0] для выбора ребенка. + + + [Button:LeftStick] для просмотра родословной. + + + [Button:LeftStick] для просмотра родословной. + + + Стрелки = просмотр родословной + + + Стрелки = просмотр родословной + + + [Input:9] для смены набора детей (1 раз). + + + [Input:9] для смены набора детей (1 раз). + + + Класс + + + Класс + + + Черта + + + Черта + + + Черты – нет + + + Черты – нет + + + Заклинание + + + Заклинание + + + Строим... + + + Строим... + + + Портируем... + + + Портируем... + + + Вспоминаем... + + + Вспоминаем... + + + Подключаем... + + + Подключаем... + + + Откр. сундук + + + Откр. сундук + + + Телепорт + + + Телепорт + + + Бонус-комната + + + Бонус-комната + + + [Input:9], чтобы закрыть карту. + + + [Input:9], чтобы закрыть карту. + + + [Input:0], чтобы сконцентрироваться на игроке. + + + [Input:0], чтобы сконцентрироваться на игроке. + + + Стрелки = перемещение карты + + + Стрелки = перемещение карты + + + [Button:LeftStick], чтобы сдвинуть карту. + + + [Button:LeftStick], чтобы сдвинуть карту. + + + Обозначения + + + Обозначения + + + Вы здесь + + + Вы здесь + + + Босс тут + + + Босс тут + + + Закр. сундук + + + Закр. сундук + + + Сундук фей + + + Сундук фей + + + Громкость музыки + + + Громкость музыки + + + 中文 + + + 中文 + + + English + + + English + + + Français + + + Français + + + Deutsche + + + Deutsche + + + Polski + + + Polski + + + Português (Brasil) + + + Português (Brasil) + + + Русский + + + Русский + + + Español (España) + + + Español (España) + + + Язык + + + Язык + + + *Быстрое падение позволяет спрыгивать и бить \n вниз в воздухе, нажимая кнопку "ВНИЗ". + + + Разрешение + + + Разрешение + + + Во весь экран + + + Во весь экран + + + Уменьшить качество шейдера + + + Уменьшить качество шейдера + + + Использовать другие геймпады + + + Использовать другие геймпады + + + Включить облако Steam + + + Включить облако Steam + + + *Быстрое падение позволяет спрыгивать и бить \n вниз в воздухе, нажимая кнопку "ВНИЗ". + + + [Button:LeftStick] для перемещения в меню. + + + [Button:LeftStick] для перемещения в меню. + + + Стрелки = перемещение в меню + + + Стрелки = перемещение в меню + + + [Input:0] для выбора пункта. + + + [Input:0] для выбора пункта. + + + [Input:2] для выхода из меню. + + + [Input:2] для выхода из меню. + + + *Для вступления данного изменения в силу игру следует перезапустить. + + + *Для вступления данного изменения в силу игру следует перезапустить. + + + *Для работы данной функции необходимо включить\nподдержку облака на платформе Steam. + + + *Для работы данной функции необходимо включить\nподдержку облака на платформе Steam. + + + Класс: + + + Класс: + + + Сила: + + + Сила: + + + Магия: + + + Магия: + + + Броня: + + + Броня: + + + Уровень: + + + Уровень: + + + Здор-е: + + + Здор-е: + + + ????? + + + ????? + + + золотых + + + золотых + + + макс. MP + + + макс. MP + + + макс. HP + + + макс. HP + + + Преобразовано макс. MP. Повысьте уровень. + + + Преобразовано макс. MP. Повысьте уровень. + + + Здор-е + + + Чары + + + Чары + + + [Input:2] для выхода. + + + [Input:2] для выхода. + + + Ур. + + + Ур. + + + Здор-е + + + Мана + + + Мана + + + Броня + + + Броня + + + Вес + + + Вес + + + Сила + + + Сила + + + Интеллект + + + Интеллект + + + Шанс крит. удара + + + Шанс крит. удара + + + Урон крит. удара + + + Урон крит. удара + + + Снаряжение + + + Снаряжение + + + 100 % базовые параметры. + + + УМЕНИЕ: Вопль варвара.\nМоре HP. Низкие сила и запас MP. + + + УМЕНИЕ: Вопль варвара.\nМоре HP. Низкие сила и запас MP. + + + Огромная сила, но не умеет наносить крит. удары.\n+{0} % к скорости. Низкий запас HP и MP. + + + Огромная сила, но не умеет наносить крит. удары.\n+{0} % к скорости. Низкий запас HP и MP. + + + УМЕНИЕ: Бросок ниндзя.\nОгромная сила, но не умеет наносить крит. удары.\n+{0} % к скорости. Низкий запас HP и MP. + + + УМЕНИЕ: Бросок ниндзя.\nОгромная сила, но не умеет наносить крит. удары.\n+{0} % к скорости. Низкий запас HP и MP. + + + {0} % урона превращается в ману.\nНизкие сила, запас HP и MP. + + + {0} % урона превращается в ману.\nНизкие сила, запас HP и MP. + + + УМЕНИЕ: Усиление чар.\n{0} % урона превращается в ману.\nНизкие сила, запас HP и MP. + + + УМЕНИЕ: Усиление чар.\n{0} % урона превращается в ману.\nНизкие сила, запас HP и MP. + + + Макс. запас HP растет с каждым трупом.\nОчень низкие сила, запас HP и MP. Высокий инт. + + + Макс. запас HP растет с каждым трупом.\nОчень низкие сила, запас HP и MP. Высокий инт. + + + УМЕНИЕ: Трансформация HP.\nМакс. запас HP растет с каждым трупом.\nОчень низкие сила, запас HP и MP. Высокий инт. + + + УМЕНИЕ: Трансформация HP.\nМакс. запас HP растет с каждым трупом.\nОчень низкие сила, запас HP и MP. Высокий инт. + + + Вы получеловек, полудракон. + + + Вы получеловек, полудракон. + + + ????? + + + ????? + + + 100 % базовые параметры. + + + УМЕНИЕ: Щит стража.\n100 % базовые параметры. + + + УМЕНИЕ: Щит стража.\n100 % базовые параметры. + + + +{0} % к шансу крит удара, +{1} % урона крит. удара.\nМало HP, MP и силы. + + + +{0} % к шансу крит удара, +{1} % урона крит. удара.\nМало HP, MP и силы. + + + УМЕНИЕ: Уход в тень\n+{0} % к шансу крит. удара, +{1} % урона крит. удара.\nМало HP, MP и силы. + + + УМЕНИЕ: Уход в тень\n+{0} % к шансу крит. удара, +{1} % урона крит. удара.\nМало HP, MP и силы. + + + +{0} % к найденному золоту.\nОчень низкие параметры. + + + +{0} % к найденному золоту.\nОчень низкие параметры. + + + УМЕНИЕ: Фонарь на шлеме.\n+{0} % к найденному золоту.\nОчень низкие параметры. + + + УМЕНИЕ: Фонарь на шлеме.\n+{0} % к найденному золоту.\nОчень низкие параметры. + + + {0} маны за каждого убитого.\nНизкие сила и HP. Высокие инт. и запас MP. + + + {0} маны за каждого убитого.\nНизкие сила и HP. Высокие инт. и запас MP. + + + УМЕНИЕ: Цикл чар.\n{0} маны за каждого убитого.\nНизкие сила и HP. Высокие инт. и запас МP. + + + УМЕНИЕ: Цикл чар.\n{0} маны за каждого убитого.\nНизкие сила и HP. Высокие инт. и запас MP. + + + Море HP. Низкие сила и запас MP. + + + Море HP. Низкие сила и запас MP. + + + НОВАЯ РОДОСЛОВНАЯ + + + НИ+ + + + НИ+ + + + НОВАЯ РОДОСЛОВНАЯ + + + [Button:LeftStick] для перемещения. + + + [Button:LeftStick] для перемещения. + + + Стрелки = перемещение + + + Стрелки = перемещение + + + [Input:0] для выбора. + + + [Input:0] для выбора. + + + [Input:2] для выхода. + + + [Input:2] для выхода. + + + [Input:26] для удаления. + + + [Input:26] для удаления. + + + {0}, {1} + + + {0}, {1} + + + {0}, {1} + + + {0}, {1} + + + Покойная {0} + + + Покойная {0} + + + Покойный {0} + + + Покойный {0} + + + Ур. + + + Ур. + + + Быстрое падение + + + Быстрое падение + + + Нет + + + Нет + + + Да + + + Да + + + Громкость звука + + + Громкость звука + + + Тренируйте сердце! Чем лучше работает сердце, тем крепче ваше здоровье. + + + Откройте кузницу и получите доступ к крутым железякам. + + + Откройте кузницу и получите доступ к крутым железякам. + + + Откройте дом колдуньи и получите доступ к ее волшебным рунам. + + + Откройте дом колдуньи и получите доступ к ее волшебным рунам. + + + Наймите архитектора и научитесь фиксировать положение комнат замка. + + + Наймите архитектора и научитесь фиксировать положение комнат замка. + + + Повышайте свою грузоподъемность, чтобы носить более тяжелую и прочную броню. + + + Повышайте свою грузоподъемность, чтобы носить более тяжелую и прочную броню. + + + Тренируйте тело, чтобы уменьшить получаемый урон. + + + Тренируйте тело, чтобы уменьшить получаемый урон. + + + Совершенствуйте навыки грабителя, чтобы получать больше золота. + + + Совершенствуйте навыки грабительницы, чтобы получать больше золота. + + + Снизьте размер входной платы Харона, научившись торговаться с самой смертью. + + + Снизьте размер входной платы Харона, научившись торговаться с самой смертью. + + + Очистительные клизмы резко повышают эффект зелий и мяса. + + + Очистительные клизмы резко повышают эффект зелий и мяса. + + + Используйте научные достижения, чтобы наделать новых детей. Не спрашивайте как! + + + Используйте научные достижения, чтобы наделать новых детей. Не спрашивайте как! + + + Откройте для себя силу лича! Это существо имеет огромный магический потенциал. + + + Откройте для себя силу лича! Это существо имеет огромный магический потенциал. + + + Тренируйте сердце! Чем лучше работает сердце, тем крепче ваше здоровье. + + + Закаляйтесь, чтобы стать неуязвимым как терминатор. Я вернусь! + + + Освойте профессию шахтера и принесите деньги в семью! + + + Освойте профессию шахтера и принесите деньги в семью! + + + Изучите путь вора-мага и вступите в магический спецназ. + + + Изучите путь воровки-мага и вступите в магический спецназ. + + + Откройте путь шиноби, самого быстрого из воинов. + + + Откройте путь шиноби, самой быстрой из воительниц. + + + Тренируйтесь, чтобы снизить расход маны при использовании магии. + + + Тренируйтесь, чтобы снизить расход маны при использовании магии. + + + Превратите рыцарей в паладинов, мастеров ближнего боя! + + + Превратите рыцарей в паладинов, мастериц ближнего боя! + + + Раскройте потенциал мага и превратите его в могущественного архимага. + + + Раскройте потенциал мага и превратите ее в могущественного архимага. + + + Изучите темные тайны и превратитесь из плута в убийцу. + + + Изучите темные тайны и превратитесь из плутовки в убийцу. + + + Получите ученую степень по геологии и поднимитесь в звании от шахтера до спелеолога. Шикарно. + + + Получите ученую степень по геологии и поднимитесь в звании от шахтера до спелеолога. Шикарно. + + + Станьте вождем варваров. Повелителем вольных людей. Бред какой-то. + + + Станьте королевой варваров. Повелительницей вольных людей. Бред какой-то. + + + Возведите своих личей на трон и сделайте королями-личами. + + + Возведите своих личей на трон и сделайте королевами-личами. + + + Закаляйтесь, чтобы стать неуязвимой как терминатор. Я вернусь! + + + Дайте волю своему внутреннему коту и научитесь избегать смерти. Иногда. + + + Станьте лидером своей деревни и превратите шиноби в хокаге! Это круто! + + + Станьте предводительницей своей деревни и превратите шиноби в хокаге! Это круто! + + + Изучите тайны магии и превратите вора-мага в воина-мага. + + + Изучите тайны магии и превратите воровку-мага в воительницу-мага. + + + Получеловек, полу... И обе половины круче некуда! + + + Получеловек, полу... И обе половины круче некуда! + + + ГЛУБОКОЕ ДЫХАНИЕ \nВы дышите с трудом. Красться неудобно, зато полезно для бега! \n\nСилы восстанавливаются ускоренными темпами. + + + ГЛУБОКОЕ ДЫХАНИЕ \nВы дышите с трудом. Красться неудобно, зато полезно для бега! \n\nСилы восстанавливаются ускоренными темпами. + + + Вас воспитала тигрица. В трудную минуту вы вспоминаете тигриные повадки. \nБег расходует меньше сил. + + + Вас воспитала тигрица. В трудную минуту вы вспоминаете тигриные повадки. \nБег расходует меньше сил. + + + У вас в роду были викинги. \n\nУвеличивается начальный запас жизненных сил. + + + У вас в роду были викинги. \n\nУвеличивается начальный запас жизненных сил. + + + Вы рано встаете. Если бы прокачка была похожа на сон!\nВы получаете больше HP и MP при каждом повышении уровня. + + + Вы рано встаете. Если бы прокачка была похожа на сон!\nВы получаете больше HP и MP при каждом повышении уровня. + + + Ваши руки наделены невероятной магической силой. \nВсе чары наносят больший урон. + + + Ваши руки наделены невероятной магической силой. \nВсе чары наносят больший урон. + + + В ваших жилах течет кровь великого мага. Круто. \nЧары расходуют меньше маны. + + + В ваших жилах течет кровь великого мага. Круто. \nЧары расходуют меньше маны. + + + От навязчивых идей бывает польза! \nВы получаете больше золота. + + + От навязчивых идей бывает польза! \nВы получаете больше золота. + + + Дайте волю своей внутренней кошке и научитесь избегать смерти. Иногда. + + + Хороший тренер поможет накачать руки и зад. + + + Вы настоящий жеребец-производитель. \nУ вас рождается больше детей. + + + Вы настоящая мать-героиня. \nУ вас рождается больше детей. + + + Родители говорили вам, что фермеру ни к чему учиться мыть золото. Ну, и кто оказался прав? \n Вы видите расположение комнат с сокровищами с самого начала игры. + + + Родители говорили вам, что фермерше ни к чему учиться мыть золото. Ну, и кто оказался прав? \n Вы видите расположение комнат с сокровищами с самого начала игры. + + + Война ― настоящий ад. Хорошо, что вы там не были. \n Больше минометов. + + + Война ― настоящий ад. Хорошо, что вы там не были. \n Больше минометов. + + + В детстве вы любили взрывы. \n Бомбы имеют больший радиус поражения. + + + В детстве вы любили взрывы. \n Бомбы имеют больший радиус поражения. + + + Ваш прадед был снежным человеком. Он ничему вас не научил. \n Сосульки пронзают больше врагов. + + + Ваш прадед был снежным человеком. Он ничему вас не научил. \n Сосульки пронзают больше врагов. + + + Вы постигли дзен. \n Стоя неподвижно, вы быстрее восстанавливаете силы. + + + Вы постигли дзен. \n Стоя неподвижно, вы быстрее восстанавливаете силы. + + + Общий НАВЫК. Увеличение общего запаса сил. + + + Общий НАВЫК. Увеличение общего запаса сил. + + + Вы не тратите силы попусту. \n Атаки расходуют на X % меньше сил. + + + Вы не тратите силы попусту. \n Атаки расходуют на X % меньше сил. + + + Общий НАВЫК. Увеличение здоровья + + + Общий НАВЫК. Увеличение здоровья + + + Вы просто кровосос. \n Каждый нанесенный удар восстанавливает немного здоровья. + + + Вы просто кровосос. \n Каждый нанесенный удар восстанавливает немного здоровья. + + + Хороший тренер поможет накачать руки и зад. + + + Грамотная тренировка позволит наносить больше урона серией ударов вниз. + + + Воскресните, словно Иисус. Впрочем, вы все равно не Иисус. \nВы воскресаете после смерти (1 раз). + + + Воскресните, словно Иисус. Впрочем, вы все равно не Иисус. \nВы воскресаете после смерти (1 раз). + + + Уборка прочищает мозги. Понятия не имею, почему. \nВы восстанавливаете часть здоровья за каждую зачищенную комнату. + + + Уборка прочищает мозги. Понятия не имею, почему. \nВы восстанавливаете часть здоровья за каждую зачищенную комнату. + + + Картография /n Вы наносите 0,1 урона за каждый открытый процент карты. + + + Картография /n Вы наносите 0,1 урона за каждый открытый процент карты. + + + Общий НАВЫК. Повышает урон от ваших атак. + + + Общий НАВЫК. Повышает урон от ваших атак. + + + Вы жалкий неудачник! \n Вы наносите серьезный урон всем врагам на экране после смерти. + + + Вы жалкая неудачница! \n Вы наносите серьезный урон всем врагам на экране после смерти. + + + Вы узнали, что удар ниже пояса наносит серьезный урон. \n Крит. удары наносят больше урона. + + + Вы узнали, что удар ниже пояса наносит серьезный урон. \n Крит. удары наносят больше урона. + + + ОБЩИЙ НАВЫК. + + + ОБЩИЙ НАВЫК. + + + Ой! Они были у меня в заднем кармане. \nВы нашли еще 2 ключа. + + + Ой! Они были у меня в заднем кармане. \nВы нашли еще 2 ключа. + + + Словно феникс, вы воскресаете из кучки пепла. \n Полное восстановление HP и MP. + + + Словно феникс, вы воскресаете из кучки пепла. \n Полное восстановление HP и MP. + + + Выйдите в отставку и разумно вложите свои денежки. Закончите игру побыстрее и получите бонус к найденному золоту. + + + Выйдите в отставку и разумно вложите свои денежки. Закончите игру побыстрее и получите бонус к найденному золоту. + + + Грамотная тренировка позволит наносить больше урона серией ударов вниз. + + + Изучайте слабые места врагов, чтобы наносить особо опасные удары. + + + БУЛЬ-БУЛЬ-БУЛЬ! \n Вы пьете зелья мгновенно. + + + БУЛЬ-БУЛЬ-БУЛЬ! \n Вы пьете зелья мгновенно. + + + Изучайте слабые места врагов, чтобы наносить особо опасные удары. + + + Отрабатывайте смертельные удары, чтобы сделать врагов совсем мертвыми! + + + Отрабатывайте смертельные удары, чтобы сделать врагов совсем мертвыми! + + + Откройте тайны вселенной, чтобы быстрее убивать врагов своими чарами. + + + Откройте тайны вселенной, чтобы быстрее убивать врагов своими чарами. + + + Развивайте интеллект, чтобы увеличить запас маны. + + + Развивайте интеллект, чтобы увеличить запас маны. + + + Нажмите [Input:9] для выбора новых детей. + + + Нажмите [Input:9] для выбора новых детей. + + + Нажмите [Input:13], чтобы блокировать весь урон. + + + Нажмите [Input:13], чтобы блокировать весь урон. + + + Нажмите [Input:13], чтобы сменить чары. + + + Нажмите [Input:13], чтобы сменить чары. + + + Нажмите [Input:13], чтобы уйти в тень. + + + Нажмите [Input:13], чтобы уйти в тень. + + + Нажмите [Input:13], чтобы включить фонарь. + + + Нажмите [Input:13], чтобы включить фонарь. + + + Нажмите [Input:13], чтобы издать дикий крик, сшибающий с ног. + + + Нажмите [Input:13], чтобы издать дикий крик, сшибающий с ног. + + + Нажмите [Input:13], чтобы превратить макс. HP в макс. MP. + + + Нажмите [Input:13], чтобы превратить макс. HP в макс. MP. + + + Нажмите [Input:13], чтобы перенестись в другое место. + + + Нажмите [Input:13], чтобы перенестись в другое место. + + + Нажмите [Input:13], чтобы использовать усиленные чары. + + + Нажмите [Input:13], чтобы использовать усиленные чары. + + + Нажмите [Input:10], чтобы стать круче. + + + Нажмите [Input:10], чтобы стать круче. + + + + + + + + + Больше здоровья + + + Кузница + + + Кузница + + + Колдунья + + + Колдунья + + + Архитектор + + + Архитектор + + + Больше вещей + + + Больше вещей + + + Крепче броня + + + Крепче броня + + + Больше золота + + + Больше золота + + + Торговля + + + Торговля + + + Сила зелья + + + Сила зелья + + + Новые дети + + + Новые дети + + + Путь лича + + + Путь лича + + + Больше здоровья + + + Неуязвимость + + + Путь шахтера + + + Путь шахтера + + + Путь вора-мага + + + Путь воровки-мага + + + Путь шиноби + + + Путь шиноби + + + Экономия маны + + + Экономия маны + + + Развитие рыцаря + + + Развитие рыцаря + + + Развитие мага + + + Развитие мага + + + Развитие плута + + + Развитие плутовки + + + Развитие шахтера + + + Развитие шахтера + + + Развитие варвара + + + Развитие варварши + + + Развитие лича + + + Развитие лича + + + Неуязвимость + + + Смерти вопреки + + + Развитие шиноби + + + Развитие шиноби + + + Развитие вора-мага + + + Развитие воровки-мага + + + Зверь внутри + + + Зверь внутри + + + Глубокое дыхание + + + Глубокое дыхание + + + Рожденный бегать + + + Рожденный бегать + + + Сердце воина + + + Сердце воительницы + + + Ранняя пташка + + + Ранняя пташка + + + Воин-маг + + + Воительница-маг + + + Чародей + + + Чародейка + + + Ученик мага + + + Ученица мага + + + Смерти вопреки + + + Сила атаки + + + Обеспеченный + + + Обеспеченная + + + Искатель сокровищ + + + Искательница сокровищ + + + Минометчик + + + Минометчица + + + Подрывник + + + Подрывница + + + Сосулька + + + Сосулька + + + Гуру + + + Гуру + + + Железные легкие + + + Железные легкие + + + Мастер меча + + + Мастерица меча + + + Танк + + + Танк + + + Вампир + + + Вампирша + + + Сила атаки + + + Сила удара вниз + + + Второй шанс + + + Второй шанс + + + Польза зачистки + + + Польза зачистки + + + Ниндзя-картограф + + + Ниндзя-картограф + + + Силач + + + Силачка + + + Самоубийца + + + Самоубийца + + + Слабое место + + + Слабое место + + + Волшебник + + + Волшебница + + + Ключник + + + Ключница + + + Раз в жизни + + + Раз в жизни + + + Опережая график + + + Опережая график + + + Сила удара вниз + + + Выс. шанс крит. удара + + + Мастер выпить + + + Мастерица выпить + + + Выс. шанс крит. удара + + + Сила урона крит. удара + + + Сила урона крит. удара + + + Сила маг. урона + + + Сила маг. урона + + + Больше маны + + + Больше маны + + + {0} монет, чтобы {1} + + + {0} монет, чтобы {1} + + + открыть + + + открыть + + + развить + + + развить + + + кг + + + кг + + + hp + + + hp + + + mp + + + mp + + + силы + + + силы + + + инт. + + + инт. + + + hp/mp + + + hp/mp + + + Макс. + + + Макс. + + + [Input:0] для покупки/развития черты. + + + [Input:0] для покупки/развития черты. + + + броня + + + броня + + + сек. + + + сек. + + + [Input:9], чтобы скрыть значки. + + + [Input:9], чтобы скрыть значки. + + + [Input:2] для выхода из имения. + + + [Input:2] для выхода из имения. + + + [Button:LeftStick] для перебора навыков. + + + [Button:LeftStick] для перебора навыков. + + + Стрелки = след. навык + + + Стрелки = след. навык + + + [Input:9], чтобы показать значки. + + + [Input:9], чтобы показать значки. + + + Сейчас + + + Сейчас + + + Развитие + + + Развитие + + + Уровень + + + Уровень + + + Кузнец способен создавать самое лучшее снаряжение в мире, благодаря чему вы станете поистине виртуозным и яростным истребителем злодеев.\nСобранные чертежи дадут возможность обеспечить ваш арсенал еще более многообразным вооружением. + + + Превратите варвара в ВОЖДЯ варваров! Ваш герой освоил тайны медвежьего рыка и способен валить врагов криком. + + + Превратите варваршу в КОРОЛЕВУ варваров! Ваша героиня освоила тайны медвежьего рыка и способна валить врагов криком. + + + Превратите простого шиноби в могучего хокаге! Теперь вы умеете подставить вместо себя бревно за мгновение до удара. Хорошо, что у вас с собой всегда есть бревна! + + + Превратите простую шиноби в могучую хокаге! Теперь вы умеете подставить вместо себя бревно за мгновение до удара. Хорошо, что у вас с собой всегда есть бревна! + + + Превратите своего плута в опытного убийцу. Используйте тени, чтобы незаметно проскользнуть мимо врага. + + + Превратите свою плутовку в опытную убийцу. Используйте тени, чтобы незаметно проскользнуть мимо врага. + + + Годы раскопок превратили шахтера в спелеолога! Теперь этот глупый фонарик на каске действительно полезен (но не слишком). + + + Годы раскопок превратили шахтера в спелеолога! Теперь этот глупый фонарик на каске действительно полезен (но не слишком). + + + Превратите вора-мага в воина-мага, обретя возможность усиливать свои чары.\nВы называете это топором? Вот настоящий топор! + + + Превратите воровку-мага в воительницу-мага, обретя возможность усиливать свои чары.\nВы называете это топором? Вот настоящий топор! + + + Превратите лича в короля-лича, которому подвластны духи и материя! Он способен одним нажатием превратить запас здоровья в запас маны. + + + Превратите лича в королеву-лича, которой подвластны духи и материя! Она способна одним нажатием превратить запас здоровья в запас маны. + + + Вы открыли древние секреты драконов. Герой разучился прыгать, зато может сколько угодно летать и посылать шары огня во врага. + + + Вы открыли древние секреты драконов. Героиня разучилась прыгать, зато может сколько угодно летать и посылать шары огня во врага. + + + Вы освоили навыки, прежде доступные лишь изменнику Иоганну. Теперь перед вашим могуществом склонятся все! + + + Вы освоили навыки, прежде доступные лишь изменнику Иоганну. Теперь перед вашим могуществом склонятся все! + + + Кузнец способен создавать самое лучшее снаряжение в мире, благодаря чему вы станете поистине виртуозным и яростным истребителем злодеев.\nСобранные чертежи дадут возможность обеспечить ваш арсенал еще более многообразным вооружением. + + + Колдунья усиливает тело героя волшебными рунами, делая его более сильным, быстрым, прыгучим.\nИщите руны, чтобы расширить ассортимент доступных чар.\n\nЕе хрустальный шар просто для показухи. + + + Колдунья усиливает тело героини волшебными рунами, делая его более сильным, быстрым, прыгучим.\nИщите руны, чтобы расширить ассортимент доступных чар.\n\nЕе хрустальный шар просто для показухи. + + + Архитектор способен закрепить замок, не давая ему изменяться.\n\nПонравилась текущая схема замка?\nЗАФИКСИРУЙТЕ ЕЕ!\nГлавное, чтобы у вас хватило денег. + + + Архитектор способна закрепить замок, не давая ему изменяться.\n\nПонравилась текущая схема замка?\nЗАФИКСИРУЙТЕ ЕЕ!\nГлавное, чтобы у вас хватило денег. + + + Шиноби. Быстрый и грозный воин в стильной повязке. Он не очень хорошо держит удар, зато если сам вломит, врагу мало не покажется! Это круто! + + + Шиноби. Быстрая и грозная воительница в стильной повязке. Она не очень хорошо держит удар, зато если сама вломит, врагу мало не покажется! Это круто! + + + Шахтеры предпочитают не убивать врагов, а зарабатывать деньги. Лучше всего им удается обшаривать замок в поисках сундуков, избегая боев. + + + Шахтеры предпочитают не убивать врагов, а зарабатывать деньги. Лучше всего им удается обшаривать замок в поисках сундуков, избегая боев. + + + Вор-маг высасывает ману у врагов с каждым ударом. Поэтому в разгар боя у него никогда не кончается мана. Полезное умение! + + + Воровка-маг высасывает ману у врагов с каждым ударом. Поэтому в разгар боя у нее никогда не кончается мана. Полезное умение! + + + Знаток тайн жизни и смерти. Лич обладает огромнейшим потенциалом. Его максимальный запас здоровья растет с каждым убитым врагом (прирост ограничен), делая его по-настоящему опасным существом. + + + Знаток тайн жизни и смерти. Лич обладает огромнейшим потенциалом. Его максимальный запас здоровья растет с каждым убитым врагом (прирост ограничен), делая его по-настоящему опасным существом. + + + Превратите рыцарей в паладинов. В ходе усердных тренировок паладины научились блокировать удары со всех сторон. + + + Превратите рыцарей в паладинов. В ходе усердных тренировок паладины научились блокировать удары со всех сторон. + + + Превратите хилого мага в могучего архимага. Освойте все магические науки и меняйте заклинания на ходу. + + + Превратите хилого мага в могучего архимага. Освойте все магические науки и меняйте заклинания на ходу. + + + Кольцо Гипериона + + + Обол Понсе де Леона + + + Обол Понсе де Леона + + + Обол Геродота + + + Обол Геродота + + + Обол изменника + + + Обол изменника + + + Кольцо Гипериона + + + Сандалии Гермеса + + + Сандалии Гермеса + + + Проклятие ежика + + + Проклятие ежика + + + Обол Харона + + + Обол Харона + + + Компас Калипсо + + + Компас Калипсо + + + Дар Гелиоса + + + Дар Гелиоса + + + Очки ботана + + + Очки ботана + + + Обол Хидра + + + Обол Хидра + + + Обол Александра + + + Обол Александра + + + Герой бросает кинжал прямо перед собой. + + + Вызывает огромный меч, защищающий героя. + + + Вызывает огромный меч, защищающий героиню. + + + Окружает героя огненным кольцом. + + + Окружает героиню огненным кольцом. + + + Запускает прыгающие шары. + + + Запускает прыгающие шары. + + + Создает луч, сжигающий всех, кого коснется. + + + Создает луч, сжигающий всех, кого коснется. + + + Посылает во врагов шары огня. + + + Посылает во врагов шары огня. + + + Выбрасывает пачку кинжалов. + + + Выбрасывает пачку кинжалов. + + + Героиня бросает кинжал прямо перед собой. + + + Герой бросает огромный топор по дуге. + + + Героиня бросает огромный топор по дуге. + + + Создает бомбу, которая взрывается немного спустя. + + + Создает бомбу, которая взрывается немного спустя. + + + Замораживает всех врагов на экране. + + + Замораживает всех врагов на экране. + + + Поражает всех врагов на экране. Жрет ману. + + + Поражает всех врагов на экране. Жрет ману. + + + Создает тень, к которой затем переносит героя. + + + Создает тень, к которой затем переносит героиню. + + + Создает маркер, который переносит героя. + + + Создает маркер, который переносит героиню. + + + Герой бросает шакрам, который возвращается. + + + Героиня бросает шакрам, который возвращается. + + + Разбрасывает косы над головой героя. + + + Разбрасывает косы над головой героини. + + + Кинжал + + + Меч-защитник + + + Меч-защитник + + + Огненный щит + + + Огненный щит + + + Шары смерти + + + Шары смерти + + + Луч смерти + + + Луч смерти + + + Пламя дракона + + + Пламя дракона + + + Быстрый кинжал + + + Быстрый кинжал + + + Кинжал + + + Топор + + + Топор + + + Бомба + + + Бомба + + + Стоять-бояться + + + Стоять-бояться + + + Воронья стая + + + Воронья стая + + + Квантовый перенос + + + Квантовый перенос + + + Перенос + + + Перенос + + + Шакрам + + + Шакрам + + + Коса + + + Коса + + + Загрузка... + + + Загрузка... + + + Кузнец + + + Когда-то я была великой колдуньей, но однажды монстры из замка проникли в мои сны и украли все мои знания. + + + Ни звука! + + + Ни звука! + + + Сундук фей + + + Сундук фей + + + На полу лава! + + + На полу лава! + + + Клоун + + + Клоун + + + Приветик. Хочешь показать чудеса ловкости?\nУ тебя всего одна попытка, зато бесплатная! Если справишься, получишь приз! + + + Приветик. Хочешь показать чудеса ловкости?\nУ тебя всего одна попытка, зато бесплатная! Если справишься, получишь приз! + + + У тебя 10 кинжалов и 8 мишеней. Рискнешь попробовать? + + + У тебя 10 кинжалов и 8 мишеней. Рискнешь попробовать? + + + Клоун + + + Клоун + + + У тебя был шанс. Проваливай! + + + У тебя был шанс. Проваливай! + + + Клоун + + + + + + Когда-то я была великой колдуньей, но однажды монстры из замка проникли в мои сны и украли все мои знания. + + + Они заключили эти знания в руны, и без этих рун я ни на что не гожусь. + + + Я не видел такого мастерства со времен моего последнего визита в пивную (это было вчера). Все мишени уничтожены! Тебе полагается приз! + + + Я не видел такого мастерства со времен моего последнего визита в пивную (это было вчера). Все мишени уничтожены! Тебе полагается приз! + + + Клоун + + + Клоун + + + Слабо разбить 8 мишеней?\nНу-ну. Успехов в покорении замка. + + + Слабо разбить 8 мишеней?\nНу-ну. Успехов в покорении замка. + + + Клоун + + + Клоун + + + Приветик. Давай посмотрим, что ты умеешь!\nУ тебя всего одна попытка, зато бесплатная! Если справишься, получишь приз! + + + Приветик. Давай посмотрим, что ты умеешь!\nУ тебя всего одна попытка, зато бесплатная! Если справишься, получишь приз! + + + У тебя 5 топоров, постарайся разбить как можно больше мишеней. Если уцелеет менее 10 мишеней, ты получишь особый приз. Рискнешь попробовать? + + + У тебя 5 топоров, постарайся разбить как можно больше мишеней. Если уцелеет менее 10 мишеней, ты получишь особый приз. Рискнешь попробовать? + + + Клоун + + + Клоун + + + Круто! Уцелело не более 10 мишеней! Поскольку теперь у меня все равно не хватает мишеней для аттракциона, можешь забрать и мой сундучок. + + + Круто! Уцелело не более 10 мишеней! Поскольку теперь у меня все равно не хватает мишеней для аттракциона, можешь забрать и мой сундучок. + + + Они заключили эти знания в руны, и без этих рун я ни на что не гожусь. + + + Прошу тебя, принеси мне найденные руны, а я потом продам их тебе по выгодной цене! + + + Клоун + + + Клоун + + + Уцелело более 10 мишеней.\nПохоже, приз тебя не интересует. Отвали! + + + Уцелело более 10 мишеней.\nПохоже, приз тебя не интересует. Отвали! + + + ??? + + + ??? + + + Приветствую, герой! Я хочу дать тебе шанс, который бывает раз в жизни! + + + Приветствую, герой! Я хочу дать тебе шанс, который бывает раз в жизни! + + + Жалкий эльф + + + Жалкий эльф + + + Всего за 25 % твоего золота я разрешу тебе открыть 1 из 3 сундуков. + + + Всего за 25 % твоего золота я разрешу тебе открыть 1 из 3 сундуков. + + + В одном сундуке втрое больше золота, чем уплачено тобой, а остальные два пусты. + + + В одном сундуке втрое больше золота, чем уплачено тобой, а остальные два пусты. + + + Жадный эльф + + + Жадный эльф + + + Не хочешь испытать удачу? + + + Не хочешь испытать удачу? + + + Прошу тебя, принеси мне найденные руны, а я потом продам их тебе по выгодной цене! + + + Архитектор + + + ??? + + + ??? + + + Приветствую, герой! Я хочу дать тебе шанс, который бывает раз в жизни! + + + Приветствую, герой! Я хочу дать тебе шанс, который бывает раз в жизни! + + + Жалкий эльф + + + Жалкий эльф + + + Всего за 50 % твоего золота я разрешу тебе открыть 1 из 3 сундуков. + + + Всего за 50 % твоего золота я разрешу тебе открыть 1 из 3 сундуков. + + + В одном сундуке втрое больше золота, чем уплачено тобой, а остальные два пусты. + + + В одном сундуке втрое больше золота, чем уплачено тобой, а остальные два пусты. + + + Жадный эльф + + + Жадный эльф + + + Не хочешь испытать удачу? + + + Не хочешь испытать удачу? + + + ??? + + + ??? + + + Приветствую, герой! Я хочу дать тебе шанс, который бывает раз в жизни! + + + Приветствую, герой! Я хочу дать тебе шанс, который бывает раз в жизни! + + + Жалкий эльф + + + Жалкий эльф + + + Архитектор + + + Здорово, чувааак! + + + Всего за 75 % твоего золота я разрешу тебе открыть 1 из 3 сундуков. + + + Всего за 75 % твоего золота я разрешу тебе открыть 1 из 3 сундуков. + + + В одном сундуке втрое больше золота, чем уплачено тобой, а остальные два пусты. + + + В одном сундуке втрое больше золота, чем уплачено тобой, а остальные два пусты. + + + Жадный эльф + + + Жадный эльф + + + Не хочешь испытать удачу? + + + Не хочешь испытать удачу? + + + Жадный эльф + + + Жадный эльф + + + У тебя не хватает денег? Нищеброд! + + + У тебя не хватает денег? Нищебродка! + + + Довольный эльф + + + Довольный эльф + + + Что в ящике? + + + Что в ящике? + + + НИЧЕГО! + + + НИЧЕГО! + + + И ты понимаешь, что пролетаешь! + + + И ты понимаешь, что пролетаешь! + + + Здорово, чувааак! + + + Хочешь, расскажу секрет? Я свихнулся! + + + Унылый эльф + + + Унылый эльф + + + Хм! На этот раз тебе повезло. + + + Хм! На этот раз тебе повезло. + + + Нетерпеливый эльф + + + Нетерпеливый эльф + + + Да открывай уже сундук! + + + Да открывай уже сундук! + + + Жадный эльф + + + Жадный эльф + + + Прости, но у тебя был твой шанс. + + + Прости, но у тебя был твой шанс. + + + Разработчики + + + Разработчики + + + Don't **** Your Pants.\nВремя создания: 2 дня.\nДата выхода: 16 февраля 2009 г. + + + Don't **** Your Pants.\nВремя создания: 2 дня.\nДата выхода: 16 февраля 2009 г. + + + Хочешь, расскажу секрет? Я свихнулся! + + + Видишь рычаг? Если его нажать, замок останется таким, как прежде. + + + Это была наша первая игра; тогда мы называли себя Decade Studios. В этой игре задача игрока заключалась в том, чтобы не дать мужику наложить в штаны, используя только текстовые команды. + + + Это была наша первая игра; тогда мы называли себя Decade Studios. В этой игре задача игрока заключалась в том, чтобы не дать мужику наложить в штаны, используя только текстовые команды. + + + Изначально игра была задумана в автобусе, и мы решили заняться ей на выходных. И у нас все получилось. + + + Изначально игра была задумана в автобусе, и мы решили заняться ей на выходных. И у нас все получилось. + + + В названии игры было нецензурное слово, и мы подумывали о том, чтобы сменить название на более приличное. Но потом мы окрепли духом и решили стоять на своем. + + + В названии игры было нецензурное слово, и мы подумывали о том, чтобы сменить название на более приличное. Но потом мы окрепли духом и решили стоять на своем. + + + Значительная часть игры заключалась в том, чтобы создать текстовую бродилку, в которой игрок мог вводить любой текст. Для этого нам надо было предугадать, какие команды будут скорее всего вводить люди. + + + Значительная часть игры заключалась в том, чтобы создать текстовую бродилку, в которой игрок мог вводить любой текст. Для этого нам надо было предугадать, какие команды будут скорее всего вводить люди. + + + Мы решили эту задачу двумя способами. Сначала мы сократили число доступных игроку вариантов (человек и дверь), а затем создали систему достижений, которая задавала игроку направление действий. + + + Мы решили эту задачу двумя способами. Сначала мы сократили число доступных игроку вариантов (человек и дверь), а затем создали систему достижений, которая задавала игроку направление действий. + + + Система достижений сыграла в игре столь важную роль, что мы добавили ее в игру вместо сменяющихся экранов. Это было небольшое, но важное изменение. + + + Система достижений сыграла в игре столь важную роль, что мы добавили ее в игру вместо сменяющихся экранов. Это было небольшое, но важное изменение. + + + Разработчики + + + Разработчики + + + Band of Bears\nВремя создания: 4 месяца.\nДата выхода: 6 августа 2009 г. + + + Band of Bears\nВремя создания: 4 месяца.\nДата выхода: 6 августа 2009 г. + + + Видишь рычаг? Если его нажать, замок останется таким, как прежде. + + + Ты сможешь пройти тем же путем, что и твой предок. Круто, да? По-моему, улетно! + + + Это была наша вторая игра, которая предназначалась для конкурса DreamBuildPlay, проходившего в 2009 году. Мы узнали о нем довольно поздно, поэтому нам пришлось спешно догонять остальных участников. + + + Это была наша вторая игра, которая предназначалась для конкурса DreamBuildPlay, проходившего в 2009 году. Мы узнали о нем довольно поздно, поэтому нам пришлось спешно догонять остальных участников. + + + Помня об успехе DSYP, мы решили сделать что-то большое... дури у нас хватало. Вот так была создана компания Cellar Door Games. + + + Помня об успехе DSYP, мы решили сделать что-то большое... дури у нас хватало. Вот так была создана компания Cellar Door Games. + + + Мало того, что мы взялись за проект, для которого у нас не хватало ни опыта, ни ресурсов, мы еще работали с полной занятостью, чтобы обеспечить себя, пока идет работа над игрой. Хреновое было время. + + + Мало того, что мы взялись за проект, для которого у нас не хватало ни опыта, ни ресурсов, мы еще работали с полной занятостью, чтобы обеспечить себя, пока идет работа над игрой. Хреновое было время. + + + В игре использовалась система B.E.A.R.S., которая меняла комнаты в зависимости от числа игроков. + + + В игре использовалась система B.E.A.R.S., которая меняла комнаты в зависимости от числа игроков. + + + Эта система меняла не только числа, она меняла целые головоломки. В итоге мы попали в число 20 лидеров ― неплохо, но недостаточно, чтобы хоть что-то выиграть. + + + Эта система меняла не только числа, она меняла целые головоломки. В итоге мы попали в число 20 лидеров ― неплохо, но недостаточно, чтобы хоть что-то выиграть. + + + В конце концов, чувство реальности (и здравый смысл) победили, и мы поняли, что нам придется забросить проект или, по крайней мере, отложить его на неопределенное время. + + + В конце концов, чувство реальности (и здравый смысл) победили, и мы поняли, что нам придется забросить проект или, по крайней мере, отложить его на неопределенное время. + + + Босс демо-версии был просто улетным. + + + Босс демо-версии был просто улетным. + + + Разработчики + + + Разработчики + + + Tribal Tallies\nВремя создания: 3 месяца.\nДата выхода: 23 ноября 2009 г. + + + Tribal Tallies\nВремя создания: 3 месяца.\nДата выхода: 23 ноября 2009 г. + + + Ты сможешь пройти тем же путем, что и твой предок. Круто, да? По-моему, улетно! + + + Как я сумел построить такую чудо-машину? Научные достижения и немного магии! + + + Tribal Tallies стала нашим первым проектом после неприятного опыта с Band of Bears; мы потратили на него несколько месяцев. + + + Tribal Tallies стала нашим первым проектом после неприятного опыта с Band of Bears; мы потратили на него несколько месяцев. + + + Этот проект был пробным; мы хотели немного освоиться с играми под iOS, поскольку до этого никогда не создавали программ для мобильных платформ. + + + Этот проект был пробным; мы хотели немного освоиться с играми под iOS, поскольку до этого никогда не создавали программ для мобильных платформ. + + + Принцип игры был прост: нужно было как можно быстрее выбирать числа в определенной последовательности. + + + Принцип игры был прост: нужно было как можно быстрее выбирать числа в определенной последовательности. + + + Чтобы сделать игру веселее, мы добавили несколько режимов, например выбор в обратном порядке, скрытые числа и подбор пар. + + + Чтобы сделать игру веселее, мы добавили несколько режимов, например выбор в обратном порядке, скрытые числа и подбор пар. + + + Мы думали, что поставили перед собой реальную задачу, однако на создание игры ушло куда больше времени, чем мы рассчитывали. Дело усугублялось тем, что весь код игры писался на Hackintosh. + + + Мы думали, что поставили перед собой реальную задачу, однако на создание игры ушло куда больше времени, чем мы рассчитывали. Дело усугублялось тем, что весь код игры писался на Hackintosh. + + + Игра вышла довольно посредственной. Можно было сделать и получше, но после Band of Bears мы предпочитали не рисковать. + + + Игра вышла довольно посредственной. Можно было сделать и получше, но после Band of Bears мы предпочитали не рисковать. + + + Разработчики + + + Разработчики + + + Q\nВремя создания: 1 месяц.\nДата выхода: 18 марта 2010 г. + + + Q\nВремя создания: 1 месяц.\nДата выхода: 18 марта 2010 г. + + + Как я сумел построить такую чудо-машину? Научные достижения и немного магии! + + + ... Много магии. + + + Наш четвертый проект. После Tribal Tallies мы решили передохнуть от игр и на несколько месяцев сосредоточились на своей основной работе. Мы вновь начали испытывать неуверенность в своих силах и решили сделать игру-головоломку. + + + Наш четвертый проект. После Tribal Tallies мы решили передохнуть от игр и на несколько месяцев сосредоточились на своей основной работе. Мы вновь начали испытывать неуверенность в своих силах и решили сделать игру-головоломку. + + + К этому времени большая часть основателей Cellar Door Games занялись другими делами, поэтому на сегодня компания состоит из никому не нужных неудачников. + + + К этому времени большая часть основателей Cellar Door Games занялись другими делами, поэтому на сегодня компания состоит из никому не нужных неудачников. + + + В этой игре использовался механизм очередей комбинаций, который вынуждал игроков заранее планировать, как будут падать фишки, чтобы создавать особо крутые комбинации. + + + В этой игре использовался механизм очередей комбинаций, который вынуждал игроков заранее планировать, как будут падать фишки, чтобы создавать особо крутые комбинации. + + + Игра была бесплатной, но ей тоже никто не заинтересовался. После неудач Band of Bears, Tribal Tallies и Q мы начали подумывать о том, чтобы собрать вещи и закрыть компанию. + + + Игра была бесплатной, но ей тоже никто не заинтересовался. После неудач Band of Bears, Tribal Tallies и Q мы начали подумывать о том, чтобы собрать вещи и закрыть компанию. + + + Разработчики + + + Разработчики + + + My First Quantum Translocator\nВремя создания: 1 месяц.\nДата выхода: 13 октября 2010 г. + + + My First Quantum Translocator\nВремя создания: 1 месяц.\nДата выхода: 13 октября 2010 г. + + + Игра My First Quantum Translocator вышла, когда наша компания переживала самые трудные дни за все время своего существования. После 3 неудачных игр мы махнули на все рукой и решили сделать эту небольшую flash-игрушку просто ради хохмы. + + + Игра My First Quantum Translocator вышла, когда наша компания переживала самые трудные дни за все время своего существования. После 3 неудачных игр мы махнули на все рукой и решили сделать эту небольшую flash-игрушку просто ради хохмы. + + + ... Много магии. + + + Кузнец + + + Здравствуй, герой. + + + Но мои услуги дорого стоят. Если я зафиксирую замок, ты заплатишь\nмне 40 % от всего найденного золота! + + + В ходе разработки мы не строили никаких планов. Эту игру мы делали скорее для забавы. + + + В ходе разработки мы не строили никаких планов. Эту игру мы делали скорее для забавы. + + + Нет нужды говорить, что игра произвела огромное впечатление на аудиторию и стала единственной причиной, по которой Cellar Door Games до сих пор существует. Когда она вышла, мы поняли, что назад дороги нет. + + + Нет нужды говорить, что игра произвела огромное впечатление на аудиторию и стала единственной причиной, по которой Cellar Door Games до сих пор существует. Когда она вышла, мы поняли, что назад дороги нет. + + + Интересно, что большинство людей считает, что источником вдохновения для нас послужил Portal, однако сходство этих игр является совершенно случайным. + + + Интересно, что большинство людей считает, что источником вдохновения для нас послужил Portal, однако сходство этих игр является совершенно случайным. + + + На самом деле источником вдохновения стал герой, придуманный нами для другой игры, League of Legends. + + + На самом деле источником вдохновения стал герой, придуманный нами для другой игры, League of Legends. + + + По правде говоря, сходство между Portal и MFQT начало всплывать только после того, как мы добавили в игру окончательный вариант графики и сюжет. + + + По правде говоря, сходство между Portal и MFQT начало всплывать только после того, как мы добавили в игру окончательный вариант графики и сюжет. + + + Как бы то ни было, мы очень гордимся этой игрой. В нее было весело играть, и у нее была отличная концовка. + + + Как бы то ни было, мы очень гордимся этой игрой. В нее было весело играть, и у нее была отличная концовка. + + + Разработчики + + + Разработчики + + + I Have 1 Day\nВремя создания: 1,5 месяца.\nДата выхода: 15 апреля 2011 г. + + + I Have 1 Day\nВремя создания: 1,5 месяца.\nДата выхода: 15 апреля 2011 г. + + + Но мои услуги дорого стоят. Если я зафиксирую замок, ты заплатишь\nмне 40 % от всего найденного золота! + + + + + + Если вы хотите знать, какая из созданных нами игр у нас любимая, мы дружно скажем: "I Have 1 Day." + + + Если вы хотите знать, какая из созданных нами игр у нас любимая, мы дружно скажем: "I Have 1 Day." + + + В детстве мы росли на таких классических квестах, как Kings Quest и Monkey Island, так что эта игра была своего рода данью благодарности за лучшие впечатления детства. + + + В детстве мы росли на таких классических квестах, как Kings Quest и Monkey Island, так что эта игра была своего рода данью благодарности за лучшие впечатления детства. + + + Основой этой игры была метаголоволомка на время; на прохождение всей игры отводилось 24 часа. + + + Основой этой игры была метаголоволомка на время; на прохождение всей игры отводилось 24 часа. + + + У каждой головоломки было несколько решений, причем время имело значение, поэтому игроки вынуждены были искать оптимальное решение. + + + У каждой головоломки было несколько решений, причем время имело значение, поэтому игроки вынуждены были искать оптимальное решение. + + + Интересная деталь: вторая концовка была добавлена буквально в последний момент, и без нее вся игра была бы отстоем. + + + Интересная деталь: вторая концовка была добавлена буквально в последний момент, и без нее вся игра была бы отстоем. + + + Разработчики + + + Разработчики + + + Villainous\nВремя создания: 3 месяца.\nДата выхода: 15 апреля 2011 г. + + + Villainous\nВремя создания: 3 месяца.\nДата выхода: 15 апреля 2011 г. + + + Villainous стала одним из наших авантюрных предприятий. + + + Villainous стала одним из наших авантюрных предприятий. + + + + + + Хочешь зафиксировать замок и получать всего 60 % золота? + + + Первоначальная задумка заключалась в том, чтобы создать игру в жанре "Tower defense" наоборот. Игра могла выйти неплохой, но нам пришлось нелегко, когда мы попытались превратить "могла" в "должна стать". + + + Первоначальная задумка заключалась в том, чтобы создать игру в жанре "Tower defense" наоборот. Игра могла выйти неплохой, но нам пришлось нелегко, когда мы попытались превратить "могла" в "должна стать". + + + Большинство игравших в эту игру считают, что игровой процесс очевиден, однако с этим проектом было связано множество стрессов и споров. + + + Большинство игравших в эту игру считают, что игровой процесс очевиден, однако с этим проектом было связано множество стрессов и споров. + + + Прежде чем остановиться на окончательном варианте, мы 3 или 4 раза радикально меняли принцип игры. + + + Прежде чем остановиться на окончательном варианте, мы 3 или 4 раза радикально меняли принцип игры. + + + По иронии судьбы, на сегодня именно Villainous является одним из самых успешных наших творений. И одним из самых трудных. + + + По иронии судьбы, на сегодня именно Villainous является одним из самых успешных наших творений. И одним из самых трудных. + + + Разработчики + + + Разработчики + + + Bullet Audyssey\nВремя создания: 3,5 месяца.\nДата выхода: 29 ноября 2011 г. + + + Bullet Audyssey\nВремя создания: 3,5 месяца.\nДата выхода: 29 ноября 2011 г. + + + Bullet Audyssey стала нашей последней игрой перед началом работы над Rogue Legacy. + + + Bullet Audyssey стала нашей последней игрой перед началом работы над Rogue Legacy. + + + Bullet Audyssey представляла собой стрелялку жанра "bullet hell", основанную на музыкальных ритмах. С технической точки зрения это была самая сложная из наших игр (да, она даже сложнее, чем Rogue Legacy). + + + Bullet Audyssey представляла собой стрелялку жанра "bullet hell", основанную на музыкальных ритмах. С технической точки зрения это была самая сложная из наших игр (да, она даже сложнее, чем Rogue Legacy). + + + Хочешь зафиксировать замок и получать всего 60 % золота? + + + + + + Для создания всего одного уровня требовались совместные усилия трех редакторов. + + + Для создания всего одного уровня требовались совместные усилия трех редакторов. + + + Процесс разработки этой игры тоже оказался нетрадиционным, поскольку для ее отладки требовался большой объем предварительного планирования. + + + Процесс разработки этой игры тоже оказался нетрадиционным, поскольку для ее отладки требовался большой объем предварительного планирования. + + + Поскольку мы терпеть не можем составлять документацию, планирование далось нам нелегко. Мы обсуждали все аспекты игры где-то полдня. + + + Поскольку мы терпеть не можем составлять документацию, планирование далось нам нелегко. Мы обсуждали все аспекты игры где-то полдня. + + + По задумке игры игрок должен был поглощать вражеские пули, чтобы пополнить боезапас; при этом ритм поглощения соответствовал музыкальному оформлению. + + + По задумке игры игрок должен был поглощать вражеские пули, чтобы пополнить боезапас; при этом ритм поглощения соответствовал музыкальному оформлению. + + + Первые впечатления тестеров были ужасными: игра оказалась слишком сложной и у игроков с первой же минуту просто опускались руки. + + + Первые впечатления тестеров были ужасными: игра оказалась слишком сложной и у игроков с первой же минуту просто опускались руки. + + + Говоря о тестерах, мы имеем в виду одного парня, которому даже не нравятся игры такого жанра. Впрочем, обычно у нас тестеров и того меньше. + + + Говоря о тестерах, мы имеем в виду одного парня, которому даже не нравятся игры такого жанра. Впрочем, обычно у нас тестеров и того меньше. + + + После выхода игра не пользовалась особой популярностью. Это придало нам уверенности, и мы решили сделать Rogue Legacy! + + + После выхода игра не пользовалась особой популярностью. Это придало нам уверенности, и мы решили сделать Rogue Legacy! + + + Подтвердить + + + Подтвердить + + + Отмена + + + Отмена + + + Внимание! + + + Внимание! + + + + + + Хочешь зафиксировать замок и получать всего 60 % золота? + + + Вы точно хотите начать новую игру? Все сохраненные данные прошлой игры будут удалены. + + + Вы точно хотите начать новую игру? Все сохраненные данные прошлой игры будут удалены. + + + Восстановить раскладку + + + Восстановить раскладку + + + Вы точно хотите вернуться к раскладке управления по умолчанию? + + + Вы точно хотите вернуться к раскладке управления по умолчанию? + + + + + + + + + Вы точно хотите начать новое приключение с этим героем? + + + Вы точно хотите начать новое приключение с этим героем? + + + Разрешение изменилось + + + Разрешение изменилось + + + Уверены, что хотите запустить игру при данном разрешении?\n(Разрешение восстановится через 10 секунд). + + + Уверены, что хотите запустить игру при данном разрешении?\n(Разрешение восстановится через 10 секунд). + + + Удалить файл сохранения + + + Удалить файл сохранения + + + Вы точно хотите удалить файл сохранения?\n(Все навыки, черты, родословные и снаряжение будут стерты НАВСЕГДА!) + + + Вы точно хотите удалить файл сохранения?\n(Все навыки, черты, родословные и снаряжение будут стерты НАВСЕГДА!) + + + Хочешь зафиксировать замок и получать всего 60 % золота? + + + Архитектор + + + Удалить файл сохранения + + + Удалить файл сохранения + + + Вы АБСОЛЮТНО уверены? (Спрашиваем в последний раз!)\n(Все навыки, черты, родословные и снаряжение будут стерты НАВСЕГДА.) + + + Вы АБСОЛЮТНО уверены? (Спрашиваем в последний раз!)\n(Все навыки, черты, родословные и снаряжение будут стерты НАВСЕГДА.) + + + + + + + + + Вы точно хотите выйти в главное меню? (Ваш текущий прогресс будет сохранен) + + + Вы точно хотите выйти в главное меню? (Ваш текущий прогресс будет сохранен) + + + + + + + + + Вы точно хотите закончить игру? (Ваш текущий прогресс будет сохранен) + + + Вы точно хотите закончить игру? (Ваш текущий прогресс будет сохранен) + + + Сбой сохранения + + + Сбой сохранения + + + О, нет! Файл сохранения поврежден! + + + О, нет! Файл сохранения поврежден! + + + + + + Извини, но пока фиксировать просто нечего. Этот винт просто для антуража. + + + Попробуем загрузить резервную копию сохранения. Будем надеяться, что это не слишком отбросит вас назад! + + + Попробуем загрузить резервную копию сохранения. Будем надеяться, что это не слишком отбросит вас назад! + + + Сбой сохранения + + + Сбой сохранения + + + Похоже, резервная копия тоже непригодна. Свяжитесь с нами: support@cellardoorgames.com + Похоже, резервная копия тоже непригодна. Боюсь, нам придется перезапустить игру. + + + Похоже, резервная копия тоже непригодна. Свяжитесь с нами: support@cellardoorgames.com + Похоже, резервная копия тоже непригодна. Боюсь, нам придется перезапустить игру. + + + Сбой сохранения + + + Сбой сохранения + + + Игру не удалось сохранить 3 раза подряд. + + + Игру не удалось сохранить 3 раза подряд. + + + Возможно, с файлами сохранения конфликтуют антивирусные программы или программы ручного сохранения резервных копий. Перед запуском игры отключите все такие программы. + + + Возможно, с файлами сохранения конфликтуют антивирусные программы или программы ручного сохранения резервных копий. Перед запуском игры отключите все такие программы. + + + Извини, но пока фиксировать просто нечего. Этот винт просто для антуража. + + + Архитектор + + + Архитектор + + + Чувак, этот замок уже зафиксирован. + + + Чувак, этот замок уже зафиксирован. + + + Архитектор + + + Архитектор + + + Здравствуй, героиня. + + + Мне нужна твоя помощь. Когда-то я был лучшим кузнецом в стране. Но однажды монстры из замка забрались в кузницу и украли все мои чертежи. + + + Готово! Может, ты найдешь сокровища, которые пропустили твои предки? + + + Готово! Может, ты найдешь сокровища, которые пропустили твои предки? + + + Харон + + + Харон + + + ... Тебе придется заплатить за вход. + + + ... Тебе придется заплатить за вход. + + + + + + + + + (Отдать Харону все деньги и войти в замок?) + + + (Отдать Харону все деньги и войти в замок?) + + + + + + + + + (Отдать Харону все деньги и войти в замок?) + + + (Отдать Харону все деньги и войти в замок?) + + + + + + + + + (Отдать Харону 90 % денег и войти в замок?) + + + (Отдать Харону 90 % денег и войти в замок?) + + + + + + + + + Мне нужна твоя помощь. Когда-то я был лучшим кузнецом в стране. Но однажды монстры из замка забрались в кузницу и украли все мои чертежи. + + + Без чертежей я способен делать только вилки и ведра. + + + (Отдать Харону 80 % денег и войти в замок?) + + + (Отдать Харону 80 % денег и войти в замок?) + + + + + + + + + (Отдать Харону 70 % денег и войти в замок?) + + + (Отдать Харону 70 % денег и войти в замок?) + + + + + + + + + (Отдать Харону 60 % денег и войти в замок?) + + + (Отдать Харону 60 % денег и войти в замок?) + + + + + + + + + (Отдать Харону 50 % денег и войти в замок?) + + + (Отдать Харону 50 % денег и войти в замок?) + + + Харон + + + Харон + + + Ого, тебе удалось раздобыть мой обол. Я пропущу тебя бесплатно... но только один раз. + + + Ого, тебе удалось раздобыть мой обол. Я пропущу тебя бесплатно... но только один раз. + + + Харон + + + Харон + + + Без чертежей я способен делать только вилки и ведра. + + + Пожалуйста, приноси мне найденные чертежи, а я изготовлю для тебя крутое снаряжение. По-настоящему КРУТОЕ. + + + Ого! Это очень редкий обол. + + + Ого! Это очень редкий обол. + + + Отдай его мне, и я пропущу твою душу через другие врата. + + + Отдай его мне, и я пропущу твою душу через другие врата. + + + (Отдать Харону обол и заплатить за вход?) + + + (Отдать Харону обол и заплатить за вход?) + + + Харон + + + Харон + + + Ого! Это очень редкий обол. + + + Ого! Это очень редкий обол. + + + Отдай его мне, и я пропущу твою душу через другие врата. + + + Отдай его мне, и я пропущу твою душу через другие врата. + + + (Отдать Харону обол и заплатить за вход?) + + + (Отдать Харону обол и заплатить за вход?) + + + Харон + + + Харон + + + Ого! Это очень редкий обол. + + + Ого! Это очень редкий обол. + + + Отдай его мне, и я пропущу твою душу через другие врата. + + + Отдай его мне, и я пропущу твою душу через другие врата. + + + Пожалуйста, приноси мне найденные чертежи, а я изготовлю для тебя крутое снаряжение. По-настоящему КРУТОЕ. + + + ... Разумеется, не бесплатно. + + + (Отдать Харону обол и заплатить за вход?) + + + (Отдать Харону обол и заплатить за вход?) + + + Харон + + + Харон + + + Ого! Это очень редкий обол. + + + Ого! Это очень редкий обол. + + + Отдай его мне, и я пропущу твою душу через другие врата. + + + Отдай его мне, и я пропущу твою душу через другие врата. + + + (Отдать Харону обол и заплатить за вход?) + + + (Отдать Харону обол и заплатить за вход?) + + + Харон + + + Харон + + + Ой... Тебе не следовало брать этот обол. + + + Ой... Тебе не следовало брать этот обол. + + + Готовься! + + + Готовься! + + + (Отдать Харону обол и заплатить за вход?) + + + (Отдать Харону обол и заплатить за вход?) + + + Священный алтарь + + + Священный алтарь + + + ... Разумеется, не бесплатно. + + + Колдунья + + + Хотите помолиться о помощи? + + + Хотите помолиться о помощи? + + + Последний босс + + + Последний босс + + + Здорово, герой! Твое упорство впечатляет. К сожалению, дальше тебе не пройти! + + + Здорово, герой! Твое упорство впечатляет. К сожалению, дальше тебе не пройти! + + + Сундук фей - пусто! + + + Сундук фей - пусто! + + + НИКАКОГО ТЕКСТА + + + НИКАКОГО ТЕКСТА + + + Убей всех врагов + + + Убей всех врагов + + + + + + + + + Слабое здоровье + + + Слабое здоровье + + + + + + + + + Не смотреть! + + + Не смотреть! + + + Колдунья + + + Привет! + + + + + + + + + Никаких прыжков! + + + Никаких прыжков! + + + + + + + + + Никакого шума! + + + Никакого шума! + + + + + + + + + Не касайтесь пола + + + Не касайтесь пола + + + + + + + + + Никаких боев! + + + Никаких боев! + + + + + + + + + Открой меня вовремя + + + Открой меня вовремя + + + Привет! + + + Можно тебя на минутку? Мне нужна твоя помощь. + + + + + + + + + Без единого ранения! + + + Без единого ранения! + + + + + + + + + Найди меня + + + Найди меня + + + + + + + + + Сундук фей + + + Сундук фей + + + Не смотри на меня! + + + Не смотри на меня! + + + Сундук фей + + + Сундук фей + + + Никаких прыжков! + + + Никаких прыжков! + + + Сундук фей + + + Сундук фей + + + Можно тебя на минутку? Мне нужна твоя помощь. + + + Нажмите [Input:12] для атаки. + + + Нажмите [Input:12] для атаки. + + + Продолжение приключений + + + Продолжение приключений + + + Выберите наследника + + + Выберите наследника + + + Начните родословную + + + Начните родословную + + + Учись + + + БОЛЬНО + + + БОЛЬНО + + + Ох + + + Ох + + + Ой + + + Ой + + + ХРУСТЬ + + + ХРУСТЬ + + + Сдаюсь! + + + Сдаюсь! + + + Да, детка! + + + Да, детка! + + + Попал + + + Попал + + + Щекотно! + + + Щекотно! + + + И это все? + + + И это все? + + + Уже? + + + Уже? + + + Учись + + + Мамочка! + + + Так себе + + + Так себе + + + Слабо + + + Слабо + + + Еще! + + + Еще! + + + Мамочка! + + + Больно! + + + Больно! + + + Ай, болит! + + + Ай, болит! + + + ПРЕКРАТИ! + + + ПРЕКРАТИ! + + + Зря ты! + + + Зря ты! + + + ЗА ЧТО?! + + + ЗА ЧТО?! + + + Не надо! + + + Не надо! + + + Почему? + + + Почему? + + + Вы не различаете цветов. + + + Вас не то, что ударом, ветром сдувает! + + + Вас не то, что ударом, ветром сдувает! + + + Вам трудно запомнить, где вы находитесь. + + + Вам трудно запомнить, где вы находитесь. + + + Запасы MP и HP поменялись местами. Сюрприз! + + + Запасы MP и HP поменялись местами. Сюрприз! + + + %#&@! + + + %#&@! + + + Вы энергичны! Вы быстро двигаетесь. + + + Вы энергичны! Вы быстро двигаетесь. + + + Надо. Убрать. В доме. MP за разбитые предметы. + + + Надо. Убрать. В доме. MP за разбитые предметы. + + + Вы на стероидах! Удары отбрасывают врага еще дальше. + + + Вы на стероидах! Удары отбрасывают врага еще дальше. + + + У вас хилые лапки. Удары не отбрасывают врагов. + + + У вас хилые лапки. Удары не отбрасывают врагов. + + + Вы лишены объемного зрения. + + + Вы лишены объемного зрения. + + + Даже самые доблестные герои страдают от газов. + + + Даже самые доблестные героини страдают от газов. + + + Вы не различаете цветов. + + + Вас влечет к девушкам. + + + Добро пожаловать в деревню Тошниловку! + + + Добро пожаловать в деревню Тошниловку! + + + У вас отсутствует боковое зрение. + + + У вас отсутствует боковое зрение. + + + Вы страдаете криворукостью и путаетесь в заклинаниях. + + + Вы страдаете криворукостью и путаетесь в заклинаниях. + + + У вас проблемы с сосудами. Пульс на ногах не прощупывается. + + + У вас проблемы с сосудами. Пульс на ногах не прощупывается. + + + Вас пугают цыплята! + + + Вас пугают цыплята! + + + Вы склонны ПРЕУВЕЛИЧИВАТЬ. + + + Вы склонны ПРЕУВЕЛИЧИВАТЬ. + + + Вы сошли с ума. + + + Вы сошли с ума. + + + Вы обладаете завидной гибкостью. + + + Вы обладаете завидной гибкостью. + + + Вы помните все в мельчайших деталях. + + + Вы помните все в мельчайших деталях. + + + Вы тоскуете по старым добрым временам. + + + Вы тоскуете по старым добрым временам. + + + Вас тянет к парням. + + + Вас тянет к парням. + + + Вас влечет к девушкам. + + + Чем дальше, тем более расплывчато. + + + Нечувствительность к боли. Боли нет! + + + Нечувствительность к боли. Боли нет! + + + Вы очень талантливы и немного рассеянны. + + + Вы очень талантливы и немного рассеянны. + + + Нет никакой вилки! + + + Нет никакой вилки! + + + Вы часто ломаете вещи. + + + Вы часто ломаете вещи. + + + Вы хорошо проводите электричество. + + + Вы хорошо проводите электричество. + + + Здесь очень темно... + + + Здесь очень темно... + + + Чем дальше, тем более расплывчато. + + + Чем ближе, тем более расплывчато. + + + Чем ближе, тем более расплывчато. + + + Вам трдуно чтиать напдсии. + + + Вам трдуно чтиать напдсии. + + + Вы просто созданы для баскетбола. + + + Вы просто созданы для баскетбола. + + + Вас никогда не пустят на американские горки! + + + Вас никогда не пустят на американские горки! + + + Лысые просто очаровательны! + + + Лысые просто очаровательны! + + + Вы настолько массивны, что вас нельзя отбросить. + + + Вы настолько массивны, что вас нельзя отбросить. + + + Вы не различаете цветов. + + + Удары отбрасывают вас. + + + Удары отбрасывают вас. + + + Где это вы? + + + Где это вы? + + + MP и HP поменялись местами. + + + MP и HP поменялись местами. + + + %#&@! + + + %#&@! + + + Вы быстро бегаете. + + + Вы быстро бегаете. + + + MP за разбитые предметы. + + + MP за разбитые предметы. + + + Враги разлетаются в стороны. + + + Враги разлетаются в стороны. + + + Вы не в силах отбросить врага. + + + Вы не в силах отбросить врага. + + + Вы лишены объемного зрения. + + + Вы лишены объемного зрения. + + + Вы часто портите воздух. + + + Вы часто портите воздух. + + + Вы не различаете цветов. + + + Вас влечет к девушкам. + + + Все вверх ногами! + + + Все вверх ногами! + + + Без предупреждений. + + + Без предупреждений. + + + Заклинания направлены назад. + + + Заклинания направлены назад. + + + Пульс на ногах не прощупывается. + + + Пульс на ногах не прощупывается. + + + Вы боитесь цыплят. + + + Вы боитесь цыплят. + + + Вы преувеличиваете свой урон. + + + Вы преувеличиваете свой урон. + + + Вы видите то, чего нет. + + + Вы видите то, чего нет. + + + Вы можете развернуться в ходе боя. + + + Вы можете развернуться в ходе боя. + + + Вы помните расположение врагов. + + + Вы помните расположение врагов. + + + Все по старинке. + + + Все по старинке. + + + Вас тянет к парням. + + + Вас тянет к парням. + + + Вас влечет к девушкам. + + + Чем дальше, тем более расплывчато. + + + Не видна полоска здоровья. + + + Не видна полоска здоровья. + + + Случайные заклинания. + + + Случайные заклинания. + + + Нет никакой вилки! + + + Нет никакой вилки! + + + Вы ломаете предметы и падаете. + + + Вы ломаете предметы и падаете. + + + Платформы не исчезают. + + + Платформы не исчезают. + + + Здесь очень темно... + + + Здесь очень темно... + + + Чем дальше, тем более расплывчато. + + + Чем ближе, тем более расплывчато. + + + Чем ближе, тем более расплывчато. + + + Вам трдуно чтиать напдсии. + + + Вам трдуно чтиать напдсии. + + + Вы огромны. + + + Вы огромны. + + + Вы просто крошка. + + + Вы просто крошка. + + + Вы плешивы. + + + Вы плешивы. + + + Вас нельзя отбросить. + + + Вас нельзя отбросить. + + + Дальтонизм + + + Эктоморф + + + Эктоморф + + + Б. Альцгеймера + + + Б. Альцгеймера + + + Декстрокардия + + + Декстрокардия + + + Копролалия + + + Копролалия + + + СДВГ + + + СДВГ + + + Навязчивые идеи + + + Навязчивые идеи + + + Гипергонадизм + + + Гипергонадизм + + + Слабость мышц + + + Слабость мышц + + + Плоское зрение + + + Плоское зрение + + + Метеоризм + + + Метеоризм + + + Дальтонизм + + + Гей + + + Головокружение + + + Головокружение + + + Туннельное зрение + + + Туннельное зрение + + + Криворукость + + + Криворукость + + + Болезнь сосудов + + + Болезнь сосудов + + + Боязнь кур + + + Боязнь кур + + + Ипохондрия + + + Ипохондрия + + + Безумие + + + Безумие + + + Гибкость + + + Гибкость + + + Зрительная память + + + Зрительная память + + + Ностальгия + + + Ностальгия + + + Гей + + + Близорукость + + + Терпимость + + + Терпимость + + + Гений + + + Гений + + + Избранный + + + Избранная + + + Неуклюжесть + + + Неуклюжесть + + + Проводимость + + + Проводимость + + + Глаукома + + + Глаукома + + + Близорукость + + + Дальнозоркость + + + Дальнозоркость + + + Дислексия + + + Дислексия + + + Гигантизм + + + Гигантизм + + + Карликовость + + + Карликовость + + + Плешивость + + + Плешивость + + + Эндоморф + + + Эндоморф + + + Разработка + + + Разработка + + + Дизайн + + + Дизайн + + + Программирование + + + Программирование + + + Производство + + + Производство + + + Графика + + + Графика + + + Музыкальный и звуковой дизайн + + + Музыкальный и звуковой дизайн + + + Музыка + + + Музыка + + + + + + + + + Нанесите удар вниз здесь + + + Нанесите удар вниз здесь + + + Коснитесь [Input:11] для прыжка. + + + Коснитесь [Input:11] для прыжка. + + + Удерживайте [Input:11] для высокого прыжка. + + + Удерживайте [Input:11] для высокого прыжка. + + + Коснитесь [Input:12] для атаки. + + + Коснитесь [Input:12] для атаки. + + + Удерживайте [Input:19] и коснитесь [Input:11], чтобы\nспрыгнуть. + + + Удерживайте [Input:19] и коснитесь [Input:11], чтобы\nспрыгнуть. + + + Удерживайте [Input:19] (в прыжке) и коснитесь [Input:12] для\nудара вниз. + + + Удерживайте [Input:19] (в прыжке) и коснитесь [Input:12] для\nудара вниз. + + + Коснитесь [Input:10] для прыжка. + + + Коснитесь [Input:10] для прыжка. + + + Удерживайте [Input:10] для высокого прыжка. + + + Удерживайте [Input:10] для высокого прыжка. + + + Коснитесь [Input:12] для атаки. + + + Коснитесь [Input:12] для атаки. + + + Удерживайте [Input:18] и коснитесь [Input:10], чтобы\nспрыгнуть. + + + Удерживайте [Input:18] и коснитесь [Input:10], чтобы\nспрыгнуть. + + + Удерживайте [Input:18] (в прыжке) и коснитесь [Input:12] для\nудара вниз. + + + Удерживайте [Input:18] (в прыжке) и коснитесь [Input:12] для\nудара вниз. + + + Дополнительное программирование + + + Адаптация + + + Пожертвовать {0} золота и навсегда усилить вашу тень для данного босса?\nКоличество усилений: {1} + + + Ящик для пожертвований набит битком.  Вашу тень нельзя больше усилить.  Спасибо за деньги, приятель. + + + Вы не можете себе позволить пожертвования. Возвращайтесь, когда заработаете больше золота. + + + Ваша тень становится сильнее! + + + Ящик для пожертвований + + + {0} {1} + + + Разблокировать изменника + + + Прыжок + + + Проклятие + + + Благодать + + + Сбор архитектора + + + Бонус НИ+ + + + Спринт + + + Вампир + + + Небо + + + Мана + + + Баланс + + + Возмездие + + + Награда + + + Спешка + + + {1} {0} + + + Японская локализация и выпуск + + + Обеспечение качества + + + У вас спонтанные спазмы мышц. + + + Вы не способны узнавать лица людей. + + + Клонус + + + Прозопагнозия + + + Проклятие + + + Благодать + + + Сбор архитектора + + + Бонус НИ+ + + + Прыжок + + + Спринт + + + Вампир + + + Небо + + + Мана + + + Баланс + + + Возмездие + + + Награда + + + Спешка + + + У вас спонтанные спазмы мышц. + + + Вы не способны узнавать лица людей. + + + Клонус + + + Прозопагнозия + + + Герой получает 60% золота, найденного в замке. + + + Герой получает 60% золота, найденного в замке. + + + Разблокировать изменника + + + Full Metal Furies\nВ разработке: 4 года.\nДата выпуска: 17 января 2018 г. + + + Full Metal Furies — игра из будущего! Это продолжение игры Rogue Legacy, являющееся десятой игрой, разработанной нами. + + + После Rogue Legacy мы пообещали себе, что никогда больше не возьмемся за разработку игры без предварительного планирования. Мы соврали. Черт подери вас, наши прошлые личности! + + + В итоге, мы создали одну из самых амбициозных игр на нашей истории, совместив жанр «драчуны», многопользовательский режим, метаголоволомки и темы диско и взросления в одно целое и изменив до неузнаваемости жанр «побей их всех». + + + Игру Full Metal Furies мы разрабатывали дольше всех других игр — аж четыре года, но, к сожалению, она оказалась гораздо менее рентабельной, чем другие наши игры. (Кроме тех игр для iOS, от которых вообще уходишь в минус, черт подери вас, наши прошлые личности!) + + + Но мы все равно невероятно гордимся своим созданием и еще больше — СВОИМИ НОВЫМИ ДРУЗЬЯМИ! А-А-А-А-АХ!!! + + + Copyright © 2013-2018, Cellar Door Games Inc. + + + {0} является торговой маркой Cellar Door Games Inc. Все права защищены. + + \ No newline at end of file diff --git a/RogueCastle/Resources/LocStrings.zh.resx b/RogueCastle/Resources/LocStrings.zh.resx new file mode 100644 index 0000000..d724747 --- /dev/null +++ b/RogueCastle/Resources/LocStrings.zh.resx @@ -0,0 +1,4453 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 退出到标题屏幕 + + + 退出到标题屏幕(跳过教程) + + + [Input:25]以更改人物资料({0}) + + + 生命 + + + 使用方向键选择 + + + [Button:LeftStick]导航 + + + 选择一个种类 + + + 所需图纸 + + + 此处为购买信息 + + + + + + {0}以解锁 + + + 法力 + + + 伤害 + + + 魔法 + + + 护甲 + + + 重量 + + + 附加属性: + + + [Input:0]选择/装备 + + + [Input:2]取消/关闭菜单 + + + 已摧毁目标: + + + 剩余目标: + + + 奖励: + + + 黄金 + + + 随时查看地图 + + + 更改控制 + + + 向右猛冲 + + + 施法 + + + 重设控制 + + + 按下任意键 + + + + + + + + + + + + + + + 攻击 + + + 跳跃 + + + 特殊技能 + + + 向左猛冲 + + + 水一方 + + + 唐秋香 + + + 方美人 + + + 金喜儿 + + + 达莉萍 + + + 蔡靜语 + + + 郭玲玲 + + + 黃晓莺 + + + 杜秋娘 + + + 高媛媛 + + + 林靜妤 + + + 刘妙音 + + + 凤雨婷 + + + 徐瑶瑶 + + + 祝台英 + + + 郭燕秋 + + + 江小满 + + + 项月芳 + + + 郑云云 + + + 王琼琼 + + + 李瓶儿 + + + 周楚红 + + + 郭釆薇 + + + 叶秋菊 + + + 颜如玉 + + + 陈巧雅 + + + 萧玉旋 + + + 花可秀 + + + 董小婉 + + + 李诗诗 + + + 马如龙 + + + 应楚山 + + + 江山月 + + + 赵慕寒 + + + 万重山 + + + 郭百鸣 + + + 谢武夫 + + + 关中林 + + + 吴深山 + + + 向春风 + + + 牛始旦 + + + 常遇春 + + + 卫东方 + + + 萧北辰 + + + 黃鹤年 + + + 王石柱 + + + 胡江林 + + + 周宇浩 + + + 程向阳 + + + 魏海风 + + + 龚剑辉 + + + 周宇浩 + + + 胡不归 + + + 何汝平 + + + 何千山 + + + 方日中 + + + 谢南山 + + + 慕江南 + + + 赵寒江 + + + 宋乔木 + + + 标准的英雄。各项数据平均。 + + + 行走的坦克。这个英雄可以承受巨额伤害。\n特殊技能:野蛮人之吼。 + + + 迅捷的英雄。能造成巨额伤害,但无法暴击。 + + + 迅捷的英雄。能造成巨额伤害,但无法暴击。\n特殊技能:替身瞬移。 + + + 高手用的英雄。命中敌人以获得法力。 + + + 高手用的英雄。命中敌人以获得法力。\n特殊技能:强化法术。 + + + 食尸为生。每次击杀可增加最大生命值,但有上限。“冰雪”聪明。 + + + 食尸为生。每次击杀可增加最大生命值,但有上限。“冰雪”聪明。\n特殊技能:生命转换。 + + + 你是一名龙人 + + + ????? + + + 标准的英雄。各项数据平均。\n特殊技能:守护者之盾。 + + + 冒险的英雄。属性较低,但可造成破坏性的暴击伤害。 + + + 冒险的英雄。属性较低,但可造成破坏性的暴击伤害。\n特殊技能:迷雾形态。 + + + 囤金的英雄。属性很弱,但可获得大量额外黄金。 + + + 囤金的英雄。属性很弱,但可获得大量额外黄金。\n特殊技能:普通矿灯。 + + + 强大的法师。每次击杀会恢复法力。 + + + 强大的法师。每次击杀会恢复法力。\n特殊技能:法术切换。 + + + 行走的坦克。这个英雄可以承受巨额伤害。 + + + 蛮后 + + + 蛮王 + + + 忍者 + + + 火影 + + + 魔盗 + + + 魔盗 + + + 魔剑士 + + + 魔剑士 + + + 巫妖 + + + 巫妖后 + + + 巫妖王 + + + 龙人 + + + 龙人 + + + 叛徒 + + + 叛徒 + + + 骑士 + + + 骑士 + + + 圣骑士 + + + 圣骑士 + + + 无赖 + + + 无赖 + + + 刺客 + + + 刺客 + + + 矿工 + + + 矿工 + + + 勘探者 + + + 勘探者 + + + 法师 + + + 法师 + + + 大法师 + + + 大法师 + + + 野蛮人 + + + 野蛮人 + + + 版权所有 (C) 2013-2018,Cellar Door Games公司。 + + + 日语本地化以及出品方为 + + + 质量保证 + + + 感谢游戏! + + + 美术: + + + 音乐和音频设计: + + + 音乐: + + + 营销与情节: + + + 其他音频设计: + + + 其他背景美术: + + + 商业支持: + + + 特别鸣谢:Turbo Edition + + + 特别感谢: + + + 感谢: + + + 后代总数: + + + Mac/Linux版本改编: + + + Mac/Linux测试团队: + + + 感谢所有粉丝的大力支持! + + + 原作本地化: + + + 中文版及本地化: + + + 附加程序 + + + 改编自 + + + 已游戏时间: + + + 按下[Input:0]退出 + + + 开发: + + + 设计与情节: + + + 程序编制: + + + 出品: + + + 控制杆盲区 + + + 删除存档 + + + 王子的日记 + + + 尽管我是国王的长子,却不是他最喜欢的孩子。我一直知道,他不打算为我留下任何东西。 + + + ……如果,我错把他们当成怪兽杀了,该怎么办? + + + 王子的日记 + + + 日记#17 + + + 我肯定已经疯了。我居然在这城堡里偶然闯入了一场狂欢活动。有一个悲伤的小丑,还有其他东西。 + + + 他是个蠢货。但在这种地方,也不能对你的朋友太挑剔了吧。 + + + 我又饿了。幸好我还有鸡腿充饥。我在吊灯上找到了这些。 + + + 这座堡垒……有时我怀疑这一切不过是个大玩笑。 + + + 王子的日记 + + + 日记#18 + + + 我打败了塔楼中的怪兽,又一次感到正殿大门被削弱了。 + + + 但只要我找到了灵药,一切都会改变。 + + + 从胜利中获得的快感无可匹敌!我从未感到过如此自信、如此强大、如此……酣畅。最后一步,我就能获得我的奖励! + + + 距离成功一步之遥!我会让父亲为我骄傲! + + + 王子的日记 + + + 日记#19 + + + 我已站在地牢的大门外太久太久,久到我羞于承认。 + + + 我的勇气终于消退了,我窥视到地底的怪兽,它们让我之前的所有努力看起来异常可怜可笑。 + + + 我必须坚定信念。我必须专注。地底下太黑了,我怕我会迷失本心。 + + + 王子的日记 + + + 日记#20 + + + 我以为我知道何为黑暗,但在地底,黑暗却是有声音的。 + + + 获胜者毫无疑问将在父亲过世后继承那顶王冠。 + + + 它在栅栏的另一头,在转角的另一边发出呼唤。它嘲弄我。 + + + 这里的黑暗如此厚重,几乎触手可及,怪兽们在此筑巢安家。它们从走廊中飞奔而过,比我之前战斗过的任何东西都要可怕。 + + + 我必须保持谨慎,恰当地规划我的战斗。在这里,贸然对抗可能会付出生命。 + + + 王子的日记 + + + 日记#21 + + + 我做到了!我打败了地底之王!现在只剩正殿了。 + + + 之后,国王就会以我为荣,承认我是王位的合法继承人! + + + 而不是我那群无知的弟妹! + + + 王子的日记 + + + 日记#22 + + + 继承王位后,我的妻子和儿女就可以搬回皇宫。回到皇城,获得我们应有的尊重! + + + 我坐在这里进行最后的准备。我与城堡领主之间,最后的屏障就是这道金色的大门。 + + + 我的心中涌起一股无法平复的紧张。是恐惧,还是恐惧之下的兴奋?我只知道,我终于来到了旅途的终点。 + + + 我曾经几乎忘却来到这座城堡的初衷,但现在,我想起来了。 + + + 我已证明了自己比弟妹们更加优秀,我将拯救国王——离开城堡的我,将比当初步入城堡的我更加强大。我的家族也将为此享受应得的荣光。 + + + 现在,我要进入正殿了。 + + + 王子的日记 + + + 日记#23 + + + 我从不知道这城堡中有何宝藏。我只知道这里有治好国王的灵药。 + + + 谁会想到,那竟然是青春之泉呢? + + + 我本以为等待我的会是王座上的怪兽,一名无比强大的敌人。我需要用尽全身力气才能打败的敌人。 + + + 不必再忍受堂兄弟们的窃窃私语和飞短流长。我们经过时,其他贵胄都要鞠躬让路!但我首先要超越自己。 + + + 但是当我进入城堡,看到的却是我的父亲——国王本人——端坐王座,手托酒杯,我知道,一切都完了。 + + + 他,不老不死…… + + + ……而我,永远继承不了王位。 + + + 我无法用语言形容我的感受。 + + + 王子的日记 + + + 日记#24 + + + ………………………………………… + + + …… + + + 王子的日记 + + + 日记#25 + + + 我必须记住三个最重要的目标:征服城堡、找到灵药、获得奖励。 + + + 今天,即是永恒。 + + + 我从不知道这城堡中有何宝藏。只知道那灵药可治愈国王的伤病。 + + + ……谁会知道,那竟然是青春之泉呢?传说中的泉水,给予人不老不死的生命。 + + + 当我凝视国王的身躯时,我忽然意识到,子孙后代为先辈的罪行负责,这是不可避免的。 + + + 进入这座城堡时,我是一名剑士,一个救世主…… + + + 而现在,我只留下了盗贼的遗产。 + + + 我能感到你的愤怒,但要知道,毁灭你的家族的并不是我。 + + + 自国王踏进城堡的那一刻起,国库中的所有财富都已被卡戎拿走。我的家族——所有的家族——都不可能再获得更好的生活。 + + + 在我的脑海中,我已经可以预见绝望与贫困如何蹂躏这个可悲的国度。已经没有什么让我回去的理由。 + + + 我的孩子们,我的孩子的孩子们,我就坐在这里,无悲无喜,不腐不朽,等待你们的到来。 + + + 王子的日记 + + + 约翰内斯 + + + 这算什么?你竟敢……嘲弄我!? + + + 你无数的先辈牺牲生命才来到这里,来践行他们空洞的正义。你却来嘲弄我? + + + 很好,我宽恕你的无知。动手吧! + + + 约翰内斯 + + + 你为什么要和我战斗?在你可悲的报复行动中,死去了多少儿女? + + + 是国王毁灭了你的国家,而不是我! + + + 他骗了我们。他说他身负重伤,但他只是害怕衰老的到来! + + + 他让孩子们互相残杀,牺牲一切只为了满足他自己的私欲,最后留下我们,身无分文,众叛亲离。 + + + 我只好作出了唯一的选择。我要背弃国王和这个国家…… + + + 日记#3 + + + 选择一个新的家族! + + + 约翰内斯 + + + 你以为你已经杀死我了吗? + + + 我已经活了一千多年,我还要再活一万年! + + + 亚历山大……德尔……庞塞·德莱昂…… + + + 我不是第一个到达泉水的英雄…… + + + 但我将是最后一个! + + + 青春之泉 + + + …… + + + 你打败了我……但是你又付出了怎样的代价? + + + 我付出了大笔钱财,终于进入了城堡。可恶的卡戎拿走了我所有的钱。 + + + 我杀死了国王,但那是因为他先背叛了他的子民。 + + + 而你,又行的是什么样的正义呢? + + + 殊途同归,我们犯下的是同样的罪行。看看你的先辈们吧——这就是愚忠的代价。 + + + …… + + + …… + + + 阳光…… + + + 我已经忘记了那是什么滋味…… + + + 甚至连我的小金库都拿走了!我什么也没有给妻子和孩子们留下。 + + + 日记#1 + + + 他说,这是所有要进入城堡的人都必须付出的代价。他说这很公平。 + + + 之所以公平,是因为进去的人从来都没有回来过。但我会打破这个“公平”。 + + + 我会获得胜利!即使算上我的兄弟姐妹,也没有比我更伟大的剑士了。 + + + 王子的日记 + + + 日记#4 + + + 城堡里的一切都是封闭的。我在这里晕头转向,也没有太阳或群星可以提供指示。 + + + 我发现我经常走回头路,必须煞费苦心地记录前进的路线,否则就可能原地绕圈子。 + + + 我从其他冒险者身上搜刮出的地图简直乱七八糟。仿佛我们走的不是同一个城堡! + + + 也许这个地方对人的神智有些影响…… + + + 还是说,我脚下的石头真的在移动? + + + 叛臣贼子!一名刺客刺伤了我的父亲,国王陛下! + + + 王子的日记 + + + 日记#5 + + + 我无法从正门出去,但没有关系。我将坚守信念,绝不退缩! + + + 到目前为止,我还没有发现与我自己的地图相符的地图。 + + + 但是在经过整体比较之后,我想我发现了一点小小的规律。森林似乎总在城堡的右边,而塔楼在上面…… + + + 至于下面?但愿我没机会知道。 + + + 王子的日记 + + + 日记#6 + + + 我从来不喜欢黑暗。我更喜欢在视野开阔的地带面对我的敌人。 + + + 但是现在,我不得不手握剑柄探出胳膊,在这些黑暗的绞架中穿行。我永远不知道在下一个转角会迎来怎样的恐怖。 + + + 为了重新恢复王国的秩序,国王派我和其他兄弟姐妹出来寻找治愈他的良方。我们将一同前往诅咒森林边上的哈莫森城堡。 + + + 我是大陆上最伟大的剑士,但即便是我,也无法限制住这些怪物。 + + + 我的弟妹们应该感谢我身先士卒。这对他们来说,也算因祸得福吧。他们可没有办法在这里活下来。 + + + 王子的日记 + + + 日记#7 + + + 仍然是漫漫长夜。每次路过窗口,我抬头看到的都是同一轮郁卒的月亮,但我发誓我已经在城堡里待了至少一整个白天了。 + + + 一定是肾上腺素的作用。我从未感到如此强大,同时又如此警惕。在这些房间里冲锋陷阵,杀死一个又一个的敌人,令我极度兴奋。 + + + 我总感觉这座堡垒里的敌人仿佛是为我量身定做的。训练我,引导我,观察我。 + + + 听起来可能有点疯狂,但如果城堡也有知觉,可以感受到它体内发生的事,恐怕它也是不安好心。 如果我的推理正确,所有这些房间的设计都是为了要将我引向一个早已布好的陷阱。 + + + 我必须时刻保持警惕。 + + + 王子的日记 + + + 这座被诅咒的城堡自远古时代起就伫立在森林的边缘,但人们传说其中藏有可治愈一切病痛的灵药。 + + + 日记#8 + + + 根据我在穿越这些房间时遇到的冒险者尸体的情况判断,我得出了以下几个结论: + + + 1:许多人死于供给不足。我猜不少人是活活饿死的。我自己的补给也不多了,我必须尽快找到更多补给品。 + + + 2:许多尸体没穿衣服,这就能够解释为什么有些丧尸穿着内裤了。 + + + 3:我已到达了无人曾到达的房间,因为在过去的一小时里我没有遇到任何尸体。 + + + 王子的日记 + + + 日记#9 + + + 通往正殿的大门快要把我逼疯了!大门后面就藏着国王的灵药,我的奖励,但它只是静静地伫立在城堡的大厅中,无言地嘲笑着我。 + + + 我用力推它、踢它、甚至大喊“芝麻开门”,但这一切完全不起作用。 + + + 门上装饰着各种纹章,其中一个看起来很像我曾在堡垒深处偶然遭遇,吓得我赶紧离开的怪兽。也许这其中有什么关联? + + + 今晚我要趁弟妹们还在睡觉时先拔头筹。 + + + 王子的日记 + + + 日记#10 + + + 门上的纹章是新的线索!我杀死了一头纹章上的怪兽,我感到正殿门后面有什么东西开始转动。 + + + 仿佛在梦里,我能看见门上的纹章从我的脑海中闪过。 + + + 真正的灵魂出窍。 + + + 至少我知道我走对了。但我必须加快步伐,因为国王随时可能死于伤痛…… + + + 但首先我需要休息一下。明天,我将开始探索森林。 + + + 王子的日记 + + + 日记#11 + + + 这座森林和我过去见过的一切都不相同。平静而又可怕。我站在丰茂的草地上,在我身边却有一道仿佛要吞噬一切的深沟。 + + + 任务失败将使我的声名蒙尘。 + + + 我仍然没有听见我之前扔下去的小石子的回音。走错一步,我将永远坠落。真是个可怕的念头。 + + + 永恒的黑暗比曾与我战斗过的一切怪兽都要可怕。如果我不慎摔落,最终会因何而死?饥饿,还是自杀? + + + 顺带一说,这道深沟现在也是我的个人卫生间。有点好奇我的便便是不是掉到异世界去了…… + + + 王子的日记 + + + 日记#12 + + + 我找到了解决饥饿的方法。森林里有各种各样美味的蘑菇。 + + + 蘑菇里面还藏着鸡腿!还有金币,甚至还有几瓶气泡水……早些时候我劈开一棵树干,里面掉出了一袋钱。 + + + 有时我觉得我可能已经疯了。 + + + ……还有,月亮是怎么回事?怎么那么大! + + + 王子的日记 + + + 王子的日记 + + + 日记#13 + + + 我杀死了森林中的一只怪兽,又一次感到正殿的大门变弱了一分。 + + + 至今为止,我的推论都是正确的。堡垒的每一侧都有怪兽守护。这是一场意志力的测试吗?那我绝不可能失败,我只会越战越勇! + + + 明天,我将开始探索塔楼。我手气正旺呢。 + + + 王子的日记 + + + 日记#14 + + + 我一直在不停斩杀房间里的恶魔以寻找下一头守护怪兽,但我已逐渐失去了时间的概念……还有其他东西…… + + + 好像自从我进入塔楼开始,时间就停止了。或者只是我晕头转向的幻觉?我不喜欢高处……我喜欢吗? + + + 我发现我已经越来越难以回忆起自己的过去…… + + + 王子的日记 + + + 日记#2 + + + 日记#15 + + + 我记得我曾经是赫赫有名的冒险家。 我从军的资历超过了我所有的兄弟。我很确定这一点。在他们埋头故纸堆的时候,我四方征战,杀死了不少强盗和怪兽。 + + + 我总是很好奇,为什么父亲喜爱弟弟们更甚于我?童话故事里不是这么说的吧? + + + 天佑勇者。而不是那些书呆子……之类的。 + + + 老天,我真想看看把剑横在弟弟们脸上时他们苦苦思索的表情啊。 + + + 王子的日记 + + + 日记#16 + + + 我进入这座城堡以来,是不是已经过去了很多年?确实,不断的杀戮磨练了我清理怪物的剑术,但我感觉已经过去好多年了。 + + + 我甚至已经忘了我的亲人长什么样。 + + + 如果他们认为我失败了该怎么办?如果我的一个弟弟先于我找到了灵药该怎么办? + + + 入口# + + + 捐赠 {0} 黄金,并永久为这个BOSS强化你的魔影?\n 强化次数:{1} + + + 捐赠箱已满。你的魔影无法再强化了。谢谢你的捐赠。 + + + 你无法捐赠。等赚了足够的钱再回来。 + + + 你的魔影变得更强了! + + + 捐赠箱 + + + 哈莫森城堡 + + + 深渊之地 + + + 阿布哈兹森林 + + + 玛雅 + + + 选择一个种类 + + + 所需符文 + + + 此处为购买信息 + + + {0}以解锁 + + + 符文 + + + 简介 + + + [Input:0]选择/装备 + + + [Input:2]取消/关闭菜单 + + + 使用方向键选择 + + + [Button:LeftStick]导航 + + + 已击杀敌人: + + + 按下[Input:0]退出 + + + 骷髅 + + + 软泥大王 + + + 火花爷爷 + + + 火花领主,火花塔尼亚之王 + + + 小丑 + + + 小丑王 + + + 小丑皇 + + + 小丑大王 + + + 巴巴妥司 + + + 斯托拉斯 + + + 贝列斯 + + + 阿蒙 + + + 希罗多德 + + + 弗加洛 + + + 哈法斯 + + + 尼奥德尔 + + + 亚历山大四世 + + + 阿斯德朗 + + + 庞塞·德弗莱昂 + + + 布拉内斯 + + + 筒壁炮 + + + 守门人 + + + 无限之主 + + + 链甲骑士 + + + 被遗忘者 + + + 被遗弃者 + + + 守卫者 + + + 叛徒 + + + 泉水 + + + 贝列斯与哈法斯 + + + 巴巴妥司与阿蒙 + + + 斯托拉斯与弗加洛 + + + 锁链甲骑士 + + + 锁链铠甲骑士 + + + 万神殿 + + + 土巫师 + + + 土地巫师 + + + 大地巫师 + + + 火巫师 + + + 枯骨 + + + 火焰巫师 + + + 烈焰巫师 + + + 日之大法师 + + + 冰巫师 + + + 寒冰巫师 + + + 极寒巫师 + + + 月之大法师 + + + 侦查之眼 + + + 注目之眼 + + + 幻梦之眼 + + + 骨肋 + + + 德尔 + + + 愤怒 + + + 狂怒 + + + 暴怒 + + + 亚历山大 + + + 高大守卫 + + + 巨大守卫 + + + 巨塔守卫 + + + 守卫者 + + + 小尖刺球 + + + 堕落骑士 + + + 中尖刺球 + + + 大尖刺球 + + + 尖刺者 + + + 灰暗骑士 + + + 灰暗男爵 + + + 灰暗角斗士 + + + 灰暗之王 + + + 座狼 + + + 凶恶座狼 + + + 巨型座狼 + + + 堕落先锋 + + + 座狼之王 + + + 丧尸 + + + 邪恶丧尸 + + + 巨型丧尸 + + + 丧尸之王 + + + 小型晶体 + + + 中型晶体 + + + 大型晶体 + + + 无瑕晶体 + + + 忍者 + + + 堕落领主 + + + 忍法 + + + 忍术家 + + + 忍者大师 + + + 食人花蕾 + + + 食人花苞 + + + 食人花 + + + 小火球 + + + 中火球 + + + 大火球 + + + 庞塞·德莱昂 + + + 波提斯 + + + 尖刺陷阱 + + + 弓手 + + + 弓箭手 + + + 狙击手 + + + 神枪手 + + + 约翰内斯 + + + 泉水 + + + 青春之泉 + + + 邪恶帆画 + + + 邪恶油画 + + + 软泥 + + + 邪恶壁画 + + + 塞罗司 + + + 小星镖 + + + 中星镖 + + + 大星镖 + + + 巨型星镖 + + + 肯德基 + + + 鸡块 + + + 炸鸡块 + + + 美味炸鸡块 + + + 软泥怪 + + + 防卫炮塔 + + + 大号防卫炮塔 + + + 防卫炮塔2000 + + + 巨型防卫炮塔 + + + 无头神骏 + + + 暗夜神骏 + + + 噩梦神骏 + + + 彩虹小马 + + + 火花 + + + 火花先生 + + + 跳跃 + + + 诅咒 + + + 恩典 + + + 建筑师费用 + + + NG奖励 + + + 冲刺 + + + 吸血 + + + 浮空 + + + 虹吸 + + + 平衡 + + + 惩戒 + + + 赏金 + + + 急速 + + + 跳跃 + + + 诅咒 + + + 恩典 + + + 建筑师费用 + + + NG奖励 + + + 冲刺 + + + 吸血 + + + 浮空 + + + 虹吸 + + + 平衡 + + + 惩戒 + + + 赏金 + + + 急速 + + + 侍卫 + + + 杀手 + + + 圣徒 + + + 血红 + + + 惩戒 + + + 神圣 + + + 黑暗 + + + 白银 + + + 守护者 + + + 帝国 + + + 皇室 + + + 骑士 + + + 弓箭手 + + + 浮空 + + + 巨龙 + + + {0}({1}) + + + 手持 + + + 肩部 + + + 腕部 + + + 头部 + + + 胸部 + + + + + + 手持 + + + 肩部 + + + 四肢 + + + 头部 + + + 胸部 + + + + + + 赋予你在空中跳跃的能力。可叠加多个符文,获得多次跳跃。 + + + 更难对付的敌人,获取奖励更丰厚。可叠加多个符文,提升敌人难度。 + + + 敌人速度更慢,更容易对付,但奖励较少。可叠加多个符文,降低敌人难度。 + + + 获得短距离猛冲的能力。可叠加多个符文,获得多次猛冲。 + + + 杀死敌人将消耗他们的生命。可叠加多个符文,提升生命消耗能力。 + + + 获得飞行的能力。可叠加多个符文,延长飞行时间。 + + + 从死去的敌人身上抽取法力。可叠加多个符文,提升法力消耗能力。 + + + 杀死敌人可获得生命值和法力值。可叠加多个符文,提升生命/法力消耗能力。 + + + 反弹来自敌人的伤害。可叠加多个符文,提升反弹能力。 + + + 提升从硬币中获得黄金的能力。可叠加多个符文,提升黄金获取能力。 + + + 提升你的基础移动速度。可叠加多个符文,提升更多速度。 + + + 提升敌人难度。 + + + 降低敌人难度。 + + + 在空中按下[Input:10] + + + [Input:14]或[Input:15]以猛冲。 + + + 击杀敌人以恢复生命。 + + + 在空中按下[Input:10] + + + 击杀敌人以恢复法力。 + + + 击杀敌人以恢复生命和法力。 + + + 反弹来自敌人的伤害。 + + + 硬币可提供更多黄金。 + + + 提升移动速度。 + + + 暴击率 + + + 空中猛冲 + + + 格挡 + + + 浮空 + + + 可攻击炮弹 + + + 飞行 + + + 移动速度 + + + + + + 暴击伤害 + + + 吸血 + + + 黄金奖励 + + + 虹吸 + + + 经验值奖励 + + + 空中攻击 + + + 空中跳跃 + + + 伤害反弹 + + + 在城堡内获得60%的黄金总量。 + + + 赏金提升{0}% + + + 开始时敌人等级提高{0} + + + 降低{0}敌人侦测单位速率 + + + 降低{0}敌人侦测单位速率 + + + 空中跳跃{0}次 + + + 空中跳跃{0}次 + + + 向上猛冲{0}次 + + + 向上猛冲{0}次 + + + 每次击杀获得{0}生命 + + + 飞行{0}秒 + + + 飞行{0}秒 + + + 每次击杀获得{0}法力 + + + 魔法生命值 + + + 被击中后反弹{0}%的伤害 + + + 增加{0}%的黄金掉落价值 + + + 移动速度提升{0}% + + + 退出《盗贼遗产》 + + + 按下[Input:0]继续前进 + + + 阳光……我已经忘记了那是什么滋味…… + + + {0}已经被{1}杀死 + + + 按下[Input:0]继续前进 + + + {0}已经被{1}杀死 + + + {0}已经被{1}杀死 + + + {0}被流弹击中而死 + + + {0}摔倒后被刺穿而死 + + + {0}被杀死了 + + + -{0}的遗言 + + + [Input:0]继续 + + + 已提升生命 + + + 已提升法力 + + + 已提升力量 + + + 已提升魔法伤害 + + + 已提升护甲 + + + 已提升至最大负重 + + + 奖章达成! + + + 你获得了一枚奖章! + + + 森林总在城堡的右边。 + + + 浮空符文可帮助你在空中按下[Input:10]飞行。 + + + 吸血符文和虹吸符文叠加后效果拔群。 + + + 掌握机动性符文让你所向披靡。 + + + 别忘了一定要扩建你的庄园。也许会获得意想不到的新技能。 + + + 所有职业都有可以升级的独特职业技能。 + + + 已解锁的职业天赋可通过[Input:13]激活 + + + 尽早升级你的职业以获得强力职业技能。 + + + 如果一个房间总过不去,不妨试试有没有别的路可以绕。 + + + 提升属性最快的方式是购买装备。 + + + 相比提升基础属性,购买装备获得的属性更便宜也更灵活。 + + + 玛雅总在城堡之上。 + + + 你该选另一个孩子的。 + + + 符文拥有强大的力量。你可以在女巫商店装备符文,别忘了使用它们! + + + 了解不同法术之间的细微差别,将法术的潜力发挥到极致。 + + + 试着用斧头抛物线的顶点命中敌人,以作出多次攻击。 + + + 在施放聚流法球以获得最大伤害后,不要再把它收回。 + + + 避开飞轮返回的路线以造成最大伤害。 + + + 相比承受不必要的伤害,消耗法力杀死敌人会更好。 + + + 要想在城堡中活下来,了解不同敌人的弱点至关重要。 + + + 尖刺陷阱通过脉搏来辨认活人与亡者。 + + + 按下[Input:9]打开地图。 + + + 深渊总在城堡之下。 + + + 精灵宝箱中装着游戏中的所有符文。符文可为你提供强大辅助。 + + + 如果你未能通过一个精灵宝箱房间,建筑师可为你提供第二次机会。 + + + 但是建筑师会收取高额的费用。 + + + Boss死后会掉落大量黄金。 + + + 用黄金把我埋了吧。 + + + 如果遇到了困难,试试装备恩典符文。 + + + 在选项中,你可启用快速下降进行向下攻击并带着[Input:18]下降 + + + 练习对阵Boss时,建筑师非常有用。 + + + 第三行装备通常需要牺牲大量属性。请注意。 + + + 某些符文针对某些Boss特别有效。 + + + 如果总打不过Boss,换一个符文试试。 + + + 你应该多试试通过建筑师练习对阵Boss。 + + + 提升生命属性很重要。 + + + 惩戒符文可摧毁无敌的对象。 + + + 正确使用职业技能可发挥巨大的威力。 + + + 某些职业针对特定Boss特别有效。 + + + 跳跃符文赋予你在空中带着[Input:10]跳跃的能力。 + + + 冲刺符文能让你带着[Input:PLAYER_DASHLEFT]或[Input:PLAYER_DASHRIGHT]冲刺 + + + 不同职业各有其优劣,记住根据职业改变打法。 + + + 探索和发现宝箱是获取金币的最佳方式。 + + + 越困难的区域,奖励越丰厚。 + + + 我的职责是照顾我的家人…… + + + 但我只忠诚于自己。 + + + 黄金 + + + 生命值已恢复 + + + 法力值已恢复 + + + 护甲提升 + + + 最大生命值提升 + + + 最大法力值提升 + + + 攻击提升 + + + 魔法提升 + + + 最大负重提升 + + + 正在游戏 + + + 正在进入 + + + 精灵宝箱目标: + + + 在15秒内到达宝箱: + + + 剩余时间: + + + 目标达成! + + + 目标失败 + + + 无特性 + + + 英雄的{0} + + + 神圣的{0} + + + {0}先生{1}世 + + + {0}先生 + + + 先生 + + + {0}女士{1}世 + + + {0}女士 + + + 女士 + + + + + + 传奇的{0} + + + 无用的{0} + + + 虚弱的{0} + + + 果决的{0} + + + 壮实的{0} + + + 英勇的{0} + + + 勇猛的{0} + + + [Input:0]选择后代 + + + [Button:LeftStick]查看家谱 + + + 使用方向键查看家谱 + + + [Input:9]更换一次后代 + + + 职业 + + + 特性 + + + 特性 - 无 + + + 法术 + + + 建筑 + + + 谢顶 + + + 追忆 + + + 放弃 + + + 已开启宝箱 + + + 传送标记 + + + 奖励房间 + + + [Input:9]关闭地图 + + + [Input:0]玩家焦点 + + + 使用方向键移动地图 + + + [Button:LeftStick]移动地图 + + + 传说 + + + 你的位置 + + + Boss位置 + + + 未开启宝箱 + + + 精灵宝箱 + + + 音乐音量 + + + 中文 + + + 英语 + + + 法语 + + + 德语 + + + 波兰语 + + + 葡萄牙语(巴西) + + + 俄语 + + + 西班牙语(西班牙) + + + 语言 + + + *快速下降可让你跳下平台,并通过向下键在空中\n进行向下攻击 + + + 分辨率 + + + 全屏 + + + 降低阴影品质 + + + 使用Dinput手柄 + + + 启用Steam云 + + + [Button:LeftStick]导航选项 + + + 使用方向键选择选项 + + + [Input:0]选择选项 + + + [Input:2]退出选项 + + + *游戏必须重启后才能应用此更改。 + + + *必须同时在Steam平台上启用云支持才可\n使该特性发挥作用。 + + + 职业: + + + 力量: + + + 法力: + + + 护甲: + + + 等级: + + + 生命: + + + Xbox One无线手柄已断开连接。请重新连接。 + + + ????? + + + 黄金 + + + 最大法力值 + + + 最大生命值 + + + 已转换最大法力值。需要更高等级。 + + + 全金属狂怒\n开发耗时:4年。\n发布日期:2018年1月17日 + + + 来自未来世界的全金属狂怒! 继Rogue Legacy(《盗贼遗产》)后的又一佳作,也是我们开发的第十款游戏。 + + + 在 RL 之后,我们暗自发誓,绝不在没有计划的情况下再做一个游戏。 可是事与愿违。 真是人算不如天算! + + + 此游戏是我们有史以来耗费时间和精力最多的项目,是集争霸战/多人玩家/超级谜题/富有年代的迪斯科风格为一体的‘大乱炖’,玩的时间越长,你就会发现这完全颠覆了传统意义上的争霸战游戏。 + + + 全金属狂怒的开发花了我们4年的时间,是我们耗费开发时间最长的游戏,可笑的是,此游戏却是所有开发项目中回报最低的。 (除了那些收益不佳的 IOS 游戏,只能说啪啪打脸了!) + + + 但是,我们仍然为我们所创造的结晶感到自豪,也为一路上陪伴我们的朋友感到骄傲。 啊啊啊啊啊啊!!! + + + 生命 + + + 附魔 + + + [Input:2]退出 + + + 等级 + + + 法力 + + + 护甲 + + + 重量 + + + 力量 + + + 智力 + + + 暴击率 + + + 暴击伤害 + + + 装备 + + + 100%基础属性。 + + + 特殊技能:野蛮人之吼。\n大量生命值。 力量值和法力值较低。 + + + 力量值较高,但不可暴击。\n+{0}%移动速度。 生命值和法力值较低。 + + + 特殊技能:替身瞬移。\n力量值较高,但不可暴击。\n+{0}%移动速度。 生命值和法力值较低。 + + + {0}%的伤害转化为法力。\n生命值、法力值和力量值较低。 + + + 特殊技能:强化法术。\n{0}%的伤害转化为法力。\n生命值、法力值和力量值较低。 + + + 击杀转化为最大生命值。\n生命值、法力值和力量值极低。 智力值极高。 + + + 特殊技能:生命转换。\n击杀转化为最大生命值。\n生命值、法力值和力量值极低。 智力值极高。 + + + 你是一名龙人 + + + ????? + + + 特殊技能:守护者之盾\n100%基础属性。 + + + +{0}%暴击率,+{1}%暴击伤害。\n生命值、法力值和力量值较低。 + + + 特殊技能:迷雾形态\n+{0}%暴击率,+{1}%暴击伤害。\n生命值、法力值和力量值较低。 + + + +{0}%黄金获取。\n其他属性极弱。 + + + 特殊技能:普通矿灯。\n+{0}%黄金获取。\n其他属性极弱。 + + + 每次击杀会{0}恢复法力。\n力量值和生命值较低。 智力值和法力值较高。 + + + 特殊技能:法术切换。\n每次击杀会{0}恢复法力。\n力量值和生命值较低。 智力值和法力值较高。 + + + 大量生命值。 力量值和法力值较低。 + + + -开启新的遗产- + + + NG+ + + + [Button:LeftStick]导航 + + + 使用方向键选择人物 + + + [Input:0]选择 + + + [Input:2]退出 + + + [Input:26]删除 + + + {1}{0} + + + {1} {0} + + + 已故{0} + + + 已故{0} + + + 等级 + + + 启用快速下降 + + + + + + + + + {0}({1}) + + + 音效音量 + + + 改进你的有氧锻炼。心脏好,生命值就高。 + + + 解锁铁匠,获得炫酷的战利品。 + + + 解锁女巫,掌控魔法符文之力。 + + + 解锁建筑师,获得锁定城堡的力量。 + + + 升级你的负重能力可让你穿上更好、更重的护甲。 + + + 通过自然的方式锻炼你的内在,减少受到的伤害。 + + + 提升拾取技能,为你的钱袋再添一笔。 + + + 学会与死神打交道,少付一些卡戎的船费。 + + + 肠道清洁可带来药水和肉类方面的显著提升。 + + + 利用科技的力量,制造一批全新的后代。嗯……还是别问了。 + + + 解放巫妖的力量!拥有恐怖潜力的存在。 + + + 强化你的肾上腺,像毒药一样无懈可击。放马过来! + + + 解锁矿工的技能,继续积攒你的家族财富。 + + + 解锁魔盗,成为一名近战法师。 + + + 解锁忍者,最迅捷的斗士。 + + + 学习基础知识,减少施放法术时的魔耗。 + + + 将你的骑士转化为圣骑士。冲锋陷阵的勇猛战士。 + + + 解锁法师的潜在力量,成为全知全能的大法师。 + + + 学习黑暗的技艺,将无赖变为刺客。 + + + 攻读地质学学位,由矿工转为勘探者。挺不错嘛。 + + + 成为蛮王。 自由民的国王。这话讲不通啊。 + + + 提升你强大的巫妖,让他们变为巫妖王。 + + + 释放你的猫之灵魂,躲开死亡的追捕。有时候吧。 + + + 成为村中的领袖,将忍者变为火影。信不信由你! + + + 驾驭魔法的漩涡,将魔盗变为魔剑士。 + + + 半人,半******,两者合一,完美。 + + + 快速呼吸\n你的呼吸很重。 不利于跟踪,却利于赶路!\n\n提升你的天然耐力恢复。 + + + 你在年轻时就被注入了猛虎的血液。 在被刺伤时,你将发挥出猛虎之血的力量。\n奔跑消耗的耐力较少。 + + + 你拥有维京血统。 \n\n提升你的初始耐力。 + + + 你起床很早。升级就像早起。\n你每次升级都可获得额外的生命值和法力值。 + + + 你的指尖天生凝聚魔力。\n所有法术造成更大伤害。 + + + 你的血脉天生法力沸腾。 哎呀。\n施放法术的消耗较低。 + + + 强迫症总算是有点儿用处。\n获得更多黄金。 + + + 恰当的锻炼能强化你的手臂和臀部肌肉。 + + + 根据法律,你拥有最好的基因。\n可生下更多后代。 + + + 你的父母曾说农民学习淘金没有任何用处。 现在呢?\n在游戏开始时显示藏宝房间的位置。 + + + 战争即是地狱。 幸运的是你却不在其中。\n射出更多炮弹。 + + + 你从小就表现出对爆破的兴趣。\n炸弹的爆破范围更大。 + + + 你的曾祖父是个雪人。 屁用没有。\n冰锥可刺穿更多敌人。 + + + 你充满禅意。\n静止时可更快回复耐力。 + + + 通用技能。 提升耐力最大值。 + + + 你剑术绝伦\n攻击时耐力消耗减少X%。 + + + 通用技能。 提升生命值。 + + + 你吸……血。\n每次攻击可恢复少量生命。 + + + 弹簧高跷锻炼室自有其用处。连续向下攻击可造成更多伤害。 + + + 像基督耶稣一样复活。就算会复活,你也不是耶稣。\n死后可复活一次。 + + + 清空房间就像清空大脑。 我完全不知道该怎么做。\n彻底扫荡一个房间后可恢复生命。 + + + 绘图/n每次打开1%的地图可增加0.1伤害。 + + + 通用技能。 提升攻击伤害。 + + + 你是个超级超级输不起的人。\n死亡时对全屏所有敌人造成巨额伤害。 + + + 你明白了击球会造成巨额伤害。\n暴击可造成更大伤害。 + + + 通用技能。 + + + 噢。它们在我的后边口袋里。\n获得2把额外的钥匙。 + + + 你像凤凰一样从灰烬中重生。\n恢复所有生命值和法力值。 + + + 退休后,好好规划你的投资。 尽早结束游戏,退步抽身。 + + + 了解敌人的弱点可帮助你更有效率地作出致命一击。 + + + 吨吨吨吨!\n可瞬间喝下药水。 + + + 不断练习,造成更多致命伤害。敌人无处可逃。 + + + 学习宇宙的奥秘,使用自然的法力杀死敌人。 + + + 锻炼坚毅的内心,提升最大法力值。 + + + 按下[Input:9]随机选择后代 + + + 按下[Input:13]格挡所有后续伤害。 + + + 按下[Input:13]切换法术 + + + 按下[Input:13]切换为迷雾形态 + + + 按下[Input:13]开启矿灯 + + + 按下[Input:13]释放远古吼叫,震飞全屏。 + + + 按下[Input:13]将最大生命值转化为最大法力值 + + + 按下[Input:13]闪现 + + + 按下[Input:13]施放强化法术 + + + 按下[Input:10]释放技能。 + + + + + + 生命提升 + + + 铁匠 + + + 女巫 + + + 建筑师 + + + 装备提升 + + + 护甲提升 + + + 黄金获取提升 + + + 讨价还价 + + + 药水提升 + + + 随机后代 + + + 解锁巫妖 + + + 无敌时间提升 + + + 解锁矿工 + + + 解锁魔盗 + + + 解锁忍者 + + + 降低魔耗 + + + 升级骑士 + + + 升级法师 + + + 升级无赖 + + + 升级矿工 + + + 升级野蛮人 + + + 升级巫妖 + + + 死亡蔑视 + + + 升级忍者 + + + 升级魔盗 + + + 兽行 + + + 快速呼吸 + + + 奔跑健将 + + + 勇敢的心 + + + 徘徊门外 + + + 魔剑士 + + + 术士 + + + 完美主义者 + + + 攻击提升 + + + 名门贵胄 + + + 宝藏猎人 + + + 弹药大师 + + + 爆破专家 + + + 冰锥 + + + 宗师 + + + 铁肺 + + + 剑圣 + + + 坦克 + + + 吸血鬼 + + + 向下攻击提升 + + + 第二次机会 + + + 心平气和 + + + 绘图忍者 + + + 更强的人 + + + 自杀主义者 + + + 暴击野蛮人 + + + 魔法师 + + + 开锁大师 + + + 仅此一次 + + + 急流勇退 + + + 暴击率提升 + + + 一饮而尽 + + + 暴击伤害提升 + + + 魔法伤害提升 + + + 法力提升 + + + {0}黄金以{1} + + + 解锁 + + + 升级 + + + 重量 + + + 生命 + + + 法力 + + + 力量 + + + 智力 + + + 生命/法力 + + + 最大 + + + [Input:0]购买/升级特性 + + + 护甲 + + + + + + [Input:9]切换关闭图标 + + + [Input:2]离开庄园 + + + [Button:LeftStick]导航技能 + + + 使用方向键选择技能 + + + [Input:9]切换开启图标 + + + 当前 + + + 升级 + + + 等级 + + + 铁匠可为你打造世界上最精良的武器,让你成为令敌人闻风丧胆的恶棍克星。\n收集更多图纸,他会为你的兵器库增添更多武器藏品。 + + + 将你的野蛮人转化为蛮王/蛮后!学习巨熊咆哮的秘术,粉碎阻拦你的一切。 + + + 从卑微的忍者变成火影!掌握在被击中的最后一刻替身成为木头的伟大忍术。 幸好随身带的木头还够用。 + + + 将你的无赖转化为刺客。借助暗影的力量,悄无声息地掠过敌人的队伍。 + + + 长年累月的挖掘让你的矿工成为一名勘探者!现在,你头顶那束刺眼的光芒总算发挥了点作用!(骗你的。) + + + 将你的魔盗转化为魔剑士,赋予你强化法术的力量。\n你管那叫斧头?那确实是斧头。 + + + 将你的巫妖转化为巫妖王,掌控物质与精神之力!轻轻一点,将你的最大生命值转化为最大法力值。 + + + 你找到了失传已久的龙之技艺。尽管你无法跳跃,但你可以自由飞行,还可以向敌人喷射强力火球。 + + + 你找到了只有“叛徒约翰内斯”才知道的失传技艺。让万物臣服于你! + + + 女巫可使用魔法符文为你强化身体,让你更好、更快、更强、跳得更远。\n寻找更多符文释放她的身体改造实力。\n\n她的水晶球只是为了好看罢了。 + + + 建筑师可为你锁定城堡地形,阻止变化。\n\n喜欢城堡的地形?\n锁定它!\n只要你付得起建筑师的出场费。 + + + 忍者。头系额带,迅捷无比的死亡杀手。他们不能承受太多打击,但可以将痛苦带给敌人。信不信由你! + + + 学习赚钱的艺术,然后才是杀死敌人。矿工最适合扫荡城堡里的宝箱,避免正面交锋。 + + + 魔盗通过攻击敌人消耗他们的法力。这一能力使得他们能够在战斗中拥有无限的法力补给。嗨起来! + + + 生与死的主宰。巫妖拥有巨大的潜力。每次击杀可提升巫妖的最大生命值(有上限),令人恐惧的存在。 + + + 将你的骑士转化为圣骑士。在经历艰苦的锻炼后,圣骑士学会了如何格挡来自各个方向的攻击。 + + + 将你卑微的法师转化为大法师。一切奥术魔法的集大成者,可改变任何正在施放的法术。 + + + 海伯利安的指环 + + + 庞塞·德莱昂的银币 + + + 希罗多德的银币 + + + 叛徒的银币 + + + 赫耳墨斯的靴子 + + + 刺猬的诅咒 + + + 卡戎的银币 + + + 海中女神的罗盘 + + + 赫利俄斯的赐福 + + + 书呆子的眼镜 + + + 德尔的银币 + + + 亚历山大的银币 + + + 向你面前投出一把匕首。 + + + 召唤一把剑刃保护你。 + + + 召唤一道火焰保护你。 + + + 投掷到处弹跳的法球。 + + + 发出一道射线,所到之处无人幸免。 + + + 向敌人喷出火球。 + + + 投出一连串的匕首 + + + 向前弧线掷出一把巨斧。 + + + 召唤一颗片刻后爆炸的炸弹。 + + + 冻结全屏的敌人。 + + + 攻击全屏的敌人。花费甚巨。 + + + 召唤并传送到你的影子。 + + + 释放一个传送标记。 + + + 投出一把会飞回来的飞轮。 + + + 召唤一把从头上斩下的镰刀。 + + + 投匕 + + + 剑刃之墙 + + + 怒火屏障 + + + 聚流 + + + 激.光.射.线 + + + 龙之吐息 + + + 快速投匕 + + + 掷斧 + + + 爆炸 + + + 时间停止 + + + 乌鸦风暴 + + + 量子传送 + + + 置换器 + + + 飞轮 + + + 镰刀 + + + ……正在载入中 + + + 铁匠 + + + 我曾经是一名呼风唤雨的女巫。直到有一天,这座城堡里的怪兽闯入了我的梦境,偷走了我全部的学识。 + + + 无声音 + + + 精灵宝箱 + + + 熔岩地面 + + + 布伊安 + + + 你好啊!想试试你的身手吗?\n你只有一次机会,但这是免费的!如果成功,我会给你一个奖励! + + + 10把匕首摧毁8个目标。试试看吗? + + + 布伊安 + + + 好了,玩够了。击中它! + + + 布伊安 + + + 他们将学识藏进符文里,没有那些符文,我就无法工作。 + + + 自从上次去酒馆(也就是昨天)以来,我还没见过那么多“小钢炮”呢。恭喜你击中所有目标,这里是一份薄礼! + + + 布伊安 + + + 连8个都打不中啊?\n噗嗤。 祝你接下来旅途顺利吧。 + + + 布伊安 + + + 你好啊!来试一试你的技能吧。\n你只有一次机会,但这是免费的!如果成功,我会给你一个奖励! + + + 你有5把斧头,摧毁尽可能多的目标。 剩下少于10个目标,我就给你一个奖励。试试看吗? + + + 布伊安 + + + 好极了!只剩下不到10个目标!反正我也攒不齐啦,这些东西不如都给你吧。 + + + 所以,拜托了,英雄,如果你找到任何符文,务必带回来给我,我会为你进行改造! + + + 布伊安 + + + 你还剩下超过10个目标。\n我看你是不想要这些奖励吧。 咕咚咕咚! + + + ??? + + + 你好,冒险者。 这里有一次千载难逢的好机会! + + + 神秘的妖精 + + + 付出你当前少得可怜黄金的25%,我会给你一个机会打开这3个箱子之一。 + + + 其中一个箱子中装着你所付出的三倍的黄金,另外两个箱子什么也没有。 + + + 小气鬼妖精 + + + 你想试试看吗? + + + 建筑师 + + + ??? + + + 你好,冒险者。 这里有一次千载难逢的好机会! + + + 神秘的妖精 + + + 付出你当前少得可怜黄金的50%,我会给你一个机会打开这3个箱子之一。 + + + 其中一个箱子中装着你所付出的三倍的黄金,另外两个箱子什么也没有。 + + + 小气鬼妖精 + + + 你想试试看吗? + + + ??? + + + 你好,冒险者。 这里有一次千载难逢的好机会! + + + 神秘的妖精 + + + 早~~哟~~小朋友! + + + 付出你当前少得可怜黄金的75%,我会给你一个机会打开这3个箱子之一。 + + + 其中一个箱子中装着你所付出的三倍的黄金,另外两个箱子什么也没有。 + + + 小气鬼妖精 + + + 你想试试看吗? + + + 小气鬼妖精 + + + 你钱不够了?辣鸡。 + + + 赌赢的妖精 + + + 箱子里有什么? + + + 什么也没有! + + + 你这个傻瓜!大傻瓜! + + + 告诉你一个小秘密!我~最~牛~~! + + + 赌输的妖精 + + + 切! 算你这回走运。 + + + 不耐烦的妖精 + + + 快开箱啊! + + + 小气鬼妖精 + + + 抱歉啊兄弟,一人一个箱子。 + + + 开发者: + + + Don't **** Your Pants\n开发时间:2天。\n发行日期:2009年2月16日 + + + 就个控制杆?只要轻轻一拉,我就能阻止城堡的改变。 + + + 这是我们制作的第一个游戏,那时我们的名字还叫作“Decade Studios”。在游戏中,你必须阻止一个不停想要输入文字的人。 + + + 游戏最初的设想是在一辆巴士上提出来的,我们决定在周末作出这个游戏。最后做得很不赖。 + + + 游戏的标题里有一句脏话,我们曾考虑过更改标题让它看起来更友好一点。不过最后我们还是壮了壮胆决定不改了。 + + + 游戏的很大一部分围绕文字冒险进行,允许人们输入他们想要输入的内容。为了实现这一点,我们必须事先考虑人们可能输入的内容。 + + + 我们通过2种方式实现了这一点。首先,我们减少了玩家可进行的选择(一个人和一扇门),其次,我们构建了一个成就系统,可用于指引玩家。 + + + 成就系统在游戏中所占的比重巨大,因此我们将它加入了游戏,而不仅仅是一行进度显示。这是一项虽然很小但很重大的变化。 + + + 开发者: + + + Band of Bears\n开发时间:4个月。\n发行日期:2009年8月6日 + + + 通过这种方式,你就能完全复原你的父辈曾穿过的路径。是不是很~~~~了不起?服气就对了。 + + + 这是我们尝试制作的第二个游戏,后来参加了2009年的DreamBuildPlay大赛。我们很晚才得知这个比赛的消息,因此整个游戏都在努力赶上别人的进度。 + + + 在DSYP大获成功后,我们决定扩大开发……盲目扩大。 就这样,我们成立了Cellar Door Games。 + + + 为了进行这样一个其实远远超出我们的资源和专业能力的项目,我们甚至需要糊弄我们的本职工作来保证游戏的运行。这简直糟透了。 + + + 游戏采用了B.E.A.R.S(Bare Effort Adaptable Room System)系统,它将根据游戏玩家的数量而改变房间。 + + + BEARS系统不仅改变数量,还会改变谜题。我们最终拿到了Top 20的成绩,这很不错,但还不足以拿到任何奖励。 + + + 最终我们又找回了理智,回到了现实,我们意识到我们必须放弃这个项目,或至少无限期地中断它的开发。 + + + 试玩版里的Boss还是挺酷的。 + + + 开发者: + + + Tribal Tallies\n开发时间:3个月。\n发行日期:2009年11月23日 + + + 我是怎么发明这个神~~奇~~~的装置的呀?当然是科~~~~学的力量!还有魔法。 + + + 在经历了Band of Bears的不快后,Tribal Tallies是我们首个开发时间超过一个月的项目。 + + + 这算是一个测试项目,是我们团队在iOS游戏领域的试水——我们过去从未试过在移动平台上开发游戏。 + + + 游戏的概念十分简单,就是按顺序点击数字,越快越好。 + + + 为了增添趣味性,我们增加了好几个模式,例如逆序点击、隐藏数字、点击匹配等等。 + + + 我们认为游戏流程挺合理的,但没想到开发时间远远超出了我们的预计。 即使它是完全通过一款骇客工具开发的也毫无用处。 + + + 这是一款相当平庸的游戏。我们本可以做得更好,但在Band of Bears之后,我们都变得有些过于保守了。 + + + 开发者: + + + Q\n开发时间:1个月。\n发行日期:2010年3月18日 + + + ……主要还是魔法。 + + + 我们的第四个项目。在Tribal Tallies开发完毕后,我们休息了几个月,不再开发游戏,而是专注于本职工作。 恢复一段时间后,我们又闲不住了,决定开发一款解谜游戏。 + + + 那时,Cellar Door Games初期的许多创始人已经离开了我们去寻找更好的机会,而剩下来的散兵游勇共同组成了今天的公司。 + + + 游戏采用了一个队列组合机制,要求玩家思考下一块砖的落点以形成更好的组合。 + + + 这是一款免费游戏,但仍然没人买账。在经历Band of Bears、Tribal Tallies和Q的失败后,我们已经准备好收拾包袱关门大吉了。 + + + 开发者: + + + My First Quantum Translocator\n开发时间:1个月。\n发行日期:2010年10月13日 + + + My First Quantum Translocator是在公司最苦难的时候出生的。 在经历3次重大失败后,我们已经完全卸下了精神包袱,决定随便做个flash小游戏玩玩。 + + + 欢迎,英雄。 + + + 但我这项技能可不是免~~费的哟。要我锁住这座城堡,你需要付出你获得全部40%的黄~~~金! + + + 毫无疑问,在开发过程中,谁也没有去考虑游戏的反响,大家只是乐在其中。 + + + 后来的事大家都知道了,游戏大获成功,这也是Cellar Door Games至今仍然存在的唯一原因。 在发行MFQT时,我们就知道,开弓没有回头箭了。 + + + 有趣的是,大多数人都认为这款游戏的灵感来自Portal,但实际上这些相似之处纯属巧合。 + + + 实际上,这款游戏的灵感来源于我们为《英雄联盟》设想的一个英雄。 + + + 事实上,在我们最终将美术和情节套用到MFQT上时,它才显示出与Portal的共性来。 + + + 不管怎么说,我们都为这款游戏感到自豪。它的成绩不错,结局也很好。 + + + 开发者: + + + I Have 1 Day\n开发时间:1.5个月。\n发行日期:2011年4月15日 + + + + + + 如果你要问我们,在我们开发的所有游戏中最喜欢的是哪一个,那么大家一定会异口同声地回答:I Have 1 Day。 + + + 我们的童年是在《国王密使》、《猴岛小英雄》这些经典的冒险游戏中度过的,而这款游戏正是向我们最美好的游戏回忆的一次致敬。 + + + 这是一款目标时间解谜游戏,玩家只有24小时的时间可以通关。 + + + 每一个谜题都有多种可影响时间的解答,要求玩家找出解谜的最优方式。 + + + 有趣的是,第二个结局几乎是在最后一刻才加进去的,但是如果没有这个结局,整个游戏就毁了。 + + + 开发者: + + + Villainous\n开发时间:3个月。\n发行日期:2011年4月15日 + + + 开发Villainous是我们最大的一次冒险。 + + + 你想要锁住城堡并只获得60%的黄金吗? + + + 游戏最初的概念是反塔防游戏,听起来似乎不错,但我们确实经过了艰巨的努力才将“听起来不错”变成了“确实不错”。 + + + 大多数玩过这款游戏的玩家都认为这个理念很清晰,但实际在开发过程中我们承受着相当大的压力和争议。 + + + 在确定最终版本之前,我们至少废掉了三四个草案。 + + + 讽刺的是,直到今天,Villainous也是我们最重要最成功的游戏之一。但这也是开发过程最痛苦的游戏。 + + + 开发者: + + + Bullet Audyssey\n开发时间:3.5个月。\n发行日期:2011年11月29日 + + + Bullet Audyssey是我们着手开发《盗贼遗产》前的最后一款游戏。 + + + 作为一款以节奏和节拍为基础的弹幕射击游戏,Bullet Audyssey是我们开发过的游戏中技术难度最大的(是的,甚至超过《盗贼遗产》)。 + + + + + + 开发一个关卡就需要同时运行3个编辑器。 + + + 开发这款游戏还有一点不同于传统方式的就是需要进行大量的预规划,以确定启动所有功能。 + + + 由于不适合文本介绍,这着实为难了我们,我们不得不花上大半天来讲清楚这个游戏。 + + + 玩家在游戏中根据当时播放的歌曲的节拍吸收敌人的子弹,然后再发射回去。 + + + 最初的游戏测试简直是灾难性的,因为游戏太难了,人们玩了一分钟就玩不下去了。 + + + 在测试中,我们甚至找到了一个根本不玩弹幕射击游戏的家伙。 但测试范围实际比我们通常的测试范围要广。 + + + 这款游戏在发布时表现一般。却给了我们开发《盗贼遗产》的信心! + + + 确认 + + + 取消 + + + 警告! + + + 你想要锁住城堡并只获得60%的黄金吗? + + + 你确定要开始新的游戏吗?将消除所有已保存的游戏数据。 + + + 还原控制 + + + 你确定要还原初始控制设置吗? + + + + + + 你确定要使用这名英雄开始新的冒险吗? + + + 分辨率已改变 + + + 你确定要以此分辨率运行游戏吗?\n(分辨率将在10秒后还原) + + + 删除存档文件 + + + 你确定要删除存档文件吗?\n(所有技能、特性、血统和装备将永久消除) + + + 建筑师 + + + 删除存档文件 + + + 你真的真的确定吗?(不可逆操作)\n(所有技能、特性、血统和装备将永久消除) + + + + + + 你确定要退出到主菜单吗?(将保存你当前的状态) + + + + + + 你确定要退出《盗贼遗产》吗?(将保存你当前的状态) + + + 存档错误 + + + 哦不!你的存档文件损坏了! + + + 对不起,小朋友,现在没有城堡可建。这个螺丝是摆来看的。 + + + 正在尝试载入游戏备份。希望不会让你有太大损失! + + + 存档错误 + + + 备份看起来也出了点毛病。请联系:support@cellardoorgames.com + 备份看起来也出了点毛病。恐怕我们不得不重新开始游戏了。 + + + 存档错误 + + + 连续3次游戏存档失败。 + + + 杀毒软件和手动备份保存程序可能与存档发生冲突。请在运行前关闭这些软件。 + + + 建筑师 + + + 小家伙,城堡已经锁住了。 + + + 建筑师 + + + 也许你能给我帮个忙。我曾经是这片大陆上最好的铁匠。 直到有一天,这座城堡里的怪兽袭击了我的铁匠铺,偷走了我所有的图纸。 + + + 玩儿去吧!也许你能找到一些你的父辈没找到的宝藏。 + + + 卡戎 + + + ……要想从此过,留下买路财。 + + + + + + (将所有钱交给卡戎并进入城堡?) + + + + + + (将所有钱交给卡戎并进入城堡?) + + + + + + (将90%的钱交给卡戎并进入城堡?) + + + + + + 没有这些图纸,我就只能打一些餐具了。 + + + (将80%的钱交给卡戎并进入城堡?) + + + + + + (将70%的钱交给卡戎并进入城堡?) + + + + + + (将60%的钱交给卡戎并进入城堡?) + + + + + + (将50%的钱交给卡戎并进入城堡?) + + + 卡戎 + + + 哦呵呵!你拿着我的银币。那这一次,我就让你免费进去吧。 + + + 卡戎 + + + 请为我带回你找到的任何图纸,我将为你打造世界上最强的装备。绝对。 + + + 哦哟!这可是一枚很少见的银币。 + + + 把它给我,我让你的灵魂从另一扇门进去。 + + + (将银币作为入场费交给卡戎?) + + + 卡戎 + + + 哦哟!这可是一枚很少见的银币。 + + + 把它给我,我让你的灵魂从另一扇门进去。 + + + (将银币作为入场费交给卡戎?) + + + 卡戎 + + + 哦哟!这可是一枚很少见的银币。 + + + 把它给我,我让你的灵魂从另一扇门进去。 + + + ……当然了,钱还是要付的。 + + + (将银币作为入场费交给卡戎?) + + + 卡戎 + + + 哦哟!这可是一枚很少见的银币。 + + + 把它给我,我让你的灵魂从另一扇门进去。 + + + (将银币作为入场费交给卡戎?) + + + 卡戎 + + + 噢……你不应该拿走这枚银币。 + + + 做好准备。 + + + (将银币作为入场费交给卡戎?) + + + 心灵圣殿 + + + 女巫 + + + 你会祈求帮助吗? + + + 最终Boss + + + 欢迎,英雄。 你能走这么远,真令我惊讶。不幸的是,你也只能止步于此了。 + + + 精灵宝箱 - 空 + + + 无文本 + + + 打败所有敌人 + + + + + + 低生命值 + + + + + + 不可查看 + + + 你好,英雄。 + + + + + + 不可跳跃 + + + + + + 不可发出噪音 + + + + + + 不可触碰地面 + + + + + + 不可战斗 + + + + + + 在规定时间内抵达 + + + 请驻足片刻,聆听我的求助。 + + + + + + 不受伤害 + + + + + + 找到我 + + + + + + 精灵宝箱 + + + 别看我! + + + 精灵宝箱 + + + 不可跳跃 + + + 精灵宝箱 + + + 按下[Input:12]攻击 + + + 继续你的追寻 + + + 选择你的后代 + + + 开启你的遗产 + + + {0} 是Cellar Door Games公司的商标。保留所有权利。 + + + 训练假人 + + + 很痛啊啊啊 + + + 啊呀 + + + + + + 呜哇 + + + 我投降! + + + 你就这点力气? + + + 好吧,刚才那一下很痛 + + + 挠痒痒 + + + 不过如此? + + + 不过就这点力气? + + + 哦老天! + + + 还不错 + + + 弱鸡 + + + 再试试 + + + 疼! + + + 好疼啊 + + + 别打了! + + + 我怎么你了? + + + 为什么打我??? + + + 别打我了 + + + 你干什么? + + + 你是全色盲,无法分辨颜色。 + + + 你太轻了,随便打一下就飞了出去。 + + + 你总记不住自己在哪儿。 + + + 你的生命槽和法力槽是反的。 谁知道呢? + + + [哔]! + + + 你充满力量!跑得更快了。 + + + 必须。打扫。干净。打破物品以恢复法力值。 + + + 你永远精力无穷。一拳能把敌人打得老远。 + + + 你四肢无力。 无法击倒敌人。 + + + 你无法立体视物。 + + + 最勇猛的英雄也可能拉肚子。 + + + 你身为女人喜欢女人。 + + + 欢迎来到晕车世界。 + + + 你没有周边视野。 + + + 你两只手顺拐儿,没办法正常施法。 + + + 外周动脉疾病。你的脚上没有脉搏。 + + + 你被鸡吓得半死。 + + + 你总是反应过度。 + + + 你疯疯癫癫的。 + + + 你的身体很柔韧。 + + + 你有过目不忘的本领。 + + + 你怀念过去的旧时光。 + + + 你身为男人喜欢男人。 + + + 你看不清远处的东西。 + + + 对疼痛先天不敏感。不知道啥叫痛。 + + + 你很聪明。就是脑子有点毛病。 + + + 你的眼里没有岔路。 + + + 你会摔坏很多东西。 + + + 你导电性极好。 + + + 太黑了。 + + + 你会时不时的肌肉痉挛。 + + + 你无法面部识别。 + + + 你看不清近处的东西。 + + + 你有读阅碍障。 + + + 你是个天生的篮球运动员。 + + + 你从没坐过过山车。 + + + 秃是一种美。 + + + 你太重了,敌人都打不翻你。 + + + 你看不见颜色。 + + + 容易被打飞。 + + + 你在哪儿? + + + 生命槽和法力槽相反。 + + + [哔]! + + + 你跑得更快。 + + + 打破物品以恢复法力值。 + + + 你一拳能把敌人揍飞。 + + + 你无法把敌人击倒。 + + + 你无法立体视物。 + + + 你天天放屁。 + + + 你身为女人喜欢女人。 + + + 所有东西上下颠倒。 + + + 没有预警。 + + + 法术从你身后发出。 + + + 你的脚上没有脉搏。 + + + 你害怕鸡。 + + + 夸大你受到的伤害。 + + + 你会产生幻觉。 + + + 你一边战斗一边转圈。 + + + 你记得住每个敌人的位置。 + + + 每一样东西都充满了怀旧气息。 + + + 你身为男人喜欢男人。 + + + 你看不清远处的东西。 + + + 看不见生命槽。 + + + 随机施放法术。 + + + 你的眼里没有岔路。 + + + 你总是打碎东西,平衡性极差。 + + + 平台永远开放。 + + + 太黑了。 + + + 你看不清近处的东西。 + + + 你有读阅碍障。 + + + 你很大。 + + + 你很小。 + + + 你秃了。 + + + 无法被打倒。 + + + 色盲 + + + 瘦型体质 + + + 老年痴呆 + + + 右位心 + + + 秽语症 + + + 多动症 + + + 强迫症 + + + 性腺机能亢进症 + + + 肌肉萎缩 + + + 立体盲 + + + 肠易激综合征 + + + 同性恋 + + + 眩晕症 + + + 视野狭窄 + + + 双手障碍 + + + 下肢动脉硬化闭塞症 + + + 恐鸡症 + + + 忧郁症 + + + 痴呆 + + + 柔韧 + + + 过目不忘 + + + 思乡症 + + + 近视 + + + 无痛症 + + + 学者症 + + + 单一症 + + + 笨拙 + + + 电磁波过敏症 + + + 青光眼 + + + 阵挛 + + + 人面失认症 + + + 远视 + + + 阅读障碍 + + + 巨人症 + + + 侏儒症 + + + 脱发症 + + + 胖型体质 + + + 开发: + + + 设计: + + + 程序编制: + + + 出品: + + + 美术: + + + 音效设计和音乐: + + + 音乐: + + + + + + 使用向下攻击 + + + 按下[Input:11]以跳跃 + + + 长按[Input:11]以跳得更高 + + + 按下[Input:12]以攻击 + + + 长按[Input:19]并按下[Input:11]以跳下平台 + + + (空中)长按[Input:19]并按下[Input:12]以向下攻击 + + + 按下[Input:10]以跳跃 + + + 长按[Input:10]以跳得更高 + + + 按下[Input:12]以攻击 + + + 长按[Input:18]并按下[Input:10]以跳下平台 + + + (空中)长按[Input:18]并按下[Input:12]以向下攻击 + + + 解锁叛徒 + + \ No newline at end of file diff --git a/RogueCastle/RogueCastle.csproj b/RogueCastle/RogueCastle.csproj new file mode 100644 index 0000000..0c7894f --- /dev/null +++ b/RogueCastle/RogueCastle.csproj @@ -0,0 +1,35 @@ + + + + WinExe + net40 + + + + RogueLegacy + false + + + + + {050AF89B-5F49-455E-93C1-BFE7FF9506D2} + DS2DEngine + + + {4EFA1C2F-A065-4520-A8AC-A71EA1751C54} + InputSystem + + + {92C40872-2B5C-4894-AABB-602547E1DFC3} + SpriteSystem + + + {D9583122-AC6D-41EB-8292-04BDD0519D7C} + Tweener + + + {35253CE1-C864-4CD3-8249-4D1319748E8F} + FNA + + + diff --git a/RogueCastle/src/ChestConditionChecker.cs b/RogueCastle/src/ChestConditionChecker.cs new file mode 100644 index 0000000..1ad0fef --- /dev/null +++ b/RogueCastle/src/ChestConditionChecker.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class ChestConditionChecker + { + public const byte STATE_LOCKED = 0; + public const byte STATE_FREE = 1; + public const byte STATE_FAILED = 2; + + public static float HelperFloat = 0; + + public static void SetConditionState(FairyChestObj chest, PlayerObj player) + { + int distanceCheck = 100; + switch (chest.ConditionType) + { + case (ChestConditionType.InvisibleChest): + case (ChestConditionType.None): + if (Vector2.Distance(chest.AbsPosition, player.AbsPosition) < distanceCheck) + chest.SetChestUnlocked(); + break; + case (ChestConditionType.KillAllEnemies): + if (player.AttachedLevel.CurrentRoom.ActiveEnemies <= 0) + chest.SetChestUnlocked(); + break; + case (ChestConditionType.DontLook): + SpriteEffects flipCheck = SpriteEffects.None; + if (chest.AbsPosition.X < player.AbsPosition.X) // Chest is to the left of the player. + flipCheck = SpriteEffects.FlipHorizontally; + if (Vector2.Distance(chest.AbsPosition, player.AbsPosition) < 375 && Vector2.Distance(chest.AbsPosition, player.AbsPosition) > distanceCheck && player.Flip == flipCheck) + chest.SetChestFailed(); + else if (Vector2.Distance(chest.AbsPosition, player.AbsPosition) < distanceCheck) + chest.SetChestUnlocked(); + break; + case (ChestConditionType.NoJumping): + if (Vector2.Distance(chest.AbsPosition, player.AbsPosition) < 10000 && player.IsJumping == true && player.AccelerationY < 0 && Vector2.Distance(chest.AbsPosition, player.AbsPosition) > distanceCheck) + chest.SetChestFailed(); + else if (Vector2.Distance(chest.AbsPosition, player.AbsPosition) < distanceCheck) + chest.SetChestUnlocked(); + break; + case (ChestConditionType.NoFloor): // This one isn't being used. + if (player.IsTouchingGround == true && Vector2.Distance(chest.AbsPosition, player.AbsPosition) > distanceCheck && Vector2.Distance(chest.AbsPosition, player.AbsPosition) < 1000) + chest.SetChestFailed(); + else if (Vector2.Distance(chest.AbsPosition, player.AbsPosition) < distanceCheck) + chest.SetChestUnlocked(); + break; + case (ChestConditionType.NoAttackingEnemies): + foreach (EnemyObj enemy in player.AttachedLevel.CurrentRoom.EnemyList) + { + if (enemy.CurrentHealth < enemy.MaxHealth) + { + chest.SetChestFailed(); + break; + } + } + if (Vector2.Distance(chest.AbsPosition, player.AbsPosition) < distanceCheck && chest.State == ChestConditionChecker.STATE_LOCKED) + chest.SetChestUnlocked(); + break; + case (ChestConditionType.ReachIn5Seconds): + if (Vector2.Distance(chest.AbsPosition, player.AbsPosition) > distanceCheck && chest.Timer <= 0) + chest.SetChestFailed(); + else if (Vector2.Distance(chest.AbsPosition, player.AbsPosition) < distanceCheck && chest.Timer > 0) + chest.SetChestUnlocked(); + break; + case(ChestConditionType.TakeNoDamage): + if (player.State == PlayerObj.STATE_HURT) + chest.SetChestFailed(); + else if (Vector2.Distance(chest.AbsPosition, player.AbsPosition) < distanceCheck) + chest.SetChestUnlocked(); + break; + } + } + } +} diff --git a/RogueCastle/src/Crepuscular Rays/BasePostProcess.cs b/RogueCastle/src/Crepuscular Rays/BasePostProcess.cs new file mode 100644 index 0000000..f3cd09a --- /dev/null +++ b/RogueCastle/src/Crepuscular Rays/BasePostProcess.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Randomchaos2DGodRays +{ + public class BasePostProcess + { + public Vector2 HalfPixel; + + public Texture2D BackBuffer; + public Texture2D orgBuffer; + + public bool Enabled = true; + protected Effect effect; + + protected Game Game; + public RenderTarget2D newScene; + + ScreenQuad sq; + + public bool UsesVertexShader = false; + + protected SpriteBatch spriteBatch + { + get { return (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch)); } + } + + public BasePostProcess(Game game) + { + Game = game; + + } + + public virtual void Draw(GameTime gameTime) + { + if (Enabled) + { + if (sq == null) + { + sq = new ScreenQuad(Game); + sq.Initialize(); + } + + effect.CurrentTechnique.Passes[0].Apply(); + sq.Draw(); + } + } + } +} diff --git a/RogueCastle/src/Crepuscular Rays/BasePostProcessingEffect.cs b/RogueCastle/src/Crepuscular Rays/BasePostProcessingEffect.cs new file mode 100644 index 0000000..b276f65 --- /dev/null +++ b/RogueCastle/src/Crepuscular Rays/BasePostProcessingEffect.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Randomchaos2DGodRays +{ + public class BasePostProcessingEffect + { + public Vector2 HalfPixel; + public Texture2D lastScene; + public Texture2D orgScene; + protected List postProcesses = new List(); + + protected Game Game; + + public BasePostProcessingEffect(Game game) + { + Game = game; + } + + public bool Enabled = true; + + public void AddPostProcess(BasePostProcess postProcess) + { + postProcesses.Add(postProcess); + } + + public virtual void Draw(GameTime gameTime, Texture2D scene) + { + if (!Enabled) + return; + + orgScene = scene; + + int maxProcess = postProcesses.Count; + lastScene = null; + + for (int p = 0; p < maxProcess; p++) + { + if (postProcesses[p].Enabled) + { + // Set Half Pixel value. + postProcesses[p].HalfPixel = HalfPixel; + + // Set original scene + postProcesses[p].orgBuffer = orgScene; + + // Ready render target if needed. + if (postProcesses[p].newScene == null) + postProcesses[p].newScene = new RenderTarget2D(Game.GraphicsDevice, Game.GraphicsDevice.Viewport.Width/2, Game.GraphicsDevice.Viewport.Height/2, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + + Game.GraphicsDevice.SetRenderTarget(postProcesses[p].newScene); + + // Has the scene been rendered yet (first effect may be disabled) + if (lastScene == null) + lastScene = orgScene; + + postProcesses[p].BackBuffer = lastScene; + + Game.GraphicsDevice.Textures[0] = postProcesses[p].BackBuffer; + //Game.GraphicsDevice.Clear(Color.White); // Added this to make the ray white. + postProcesses[p].Draw(gameTime); + + Game.GraphicsDevice.SetRenderTarget(null); + + lastScene = postProcesses[p].newScene; + } + } + + if (lastScene == null) + lastScene = scene; + } + } +} diff --git a/RogueCastle/src/Crepuscular Rays/CrepuscularRays.cs b/RogueCastle/src/Crepuscular Rays/CrepuscularRays.cs new file mode 100644 index 0000000..25bdc7c --- /dev/null +++ b/RogueCastle/src/Crepuscular Rays/CrepuscularRays.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Randomchaos2DGodRays +{ + public class CrepuscularRays : BasePostProcessingEffect + { + public LightSourceMask lsMask; + public LightRay rays; + + public Vector2 lightSource + { + set + { + lsMask.lighScreenSourcePos = value; + rays.lighScreenSourcePos = value; + } + get + { + return rays.lighScreenSourcePos; + } + } + + public float X + { + set + { + lsMask.lighScreenSourcePos.X = value; + rays.lighScreenSourcePos.X = value; + } + get + { return rays.lighScreenSourcePos.X; } + } + + public float Y + { + set + { + lsMask.lighScreenSourcePos.Y = value; + rays.lighScreenSourcePos.Y = value; + } + get + { return rays.lighScreenSourcePos.Y; } + } + + public Texture lightTexture + { + get { return lsMask.lishsourceTexture; } + set { lsMask.lishsourceTexture = value; } + } + + public float LightSourceSize + { + set { lsMask.lightSize = value; } + get { return lsMask.lightSize; } + } + + public float Density + { + get { return rays.Density; } + set { rays.Density = value; } + } + + public float Decay + { + get { return rays.Decay; } + set { rays.Decay = value; } + } + + public float Weight + { + get { return rays.Weight; } + set { rays.Weight = value; } + } + + public float Exposure + { + get { return rays.Exposure; } + set { rays.Exposure = value; } + } + + + public CrepuscularRays(Game game, Vector2 lightScreenSourcePos, string lightSourceImage, float lightSourceSize, float density, float decay, float weight, float exposure) + : base(game) + { + lsMask = new LightSourceMask(game, lightScreenSourcePos, lightSourceImage, lightSourceSize); + rays = new LightRay(game, lightScreenSourcePos, density, decay, weight, exposure); + AddPostProcess(lsMask); + AddPostProcess(rays); + + } + + } +} diff --git a/RogueCastle/src/Crepuscular Rays/LightRay.cs b/RogueCastle/src/Crepuscular Rays/LightRay.cs new file mode 100644 index 0000000..125d55f --- /dev/null +++ b/RogueCastle/src/Crepuscular Rays/LightRay.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Randomchaos2DGodRays +{ + public class LightRay : BasePostProcess + { + public Vector2 lighScreenSourcePos; + public float Density = .5f; + public float Decay = .95f; + public float Weight = 1.0f; + public float Exposure = .15f; + + public LightRay(Game game, Vector2 sourcePos, float density, float decay, float weight, float exposure) + : base(game) + { + lighScreenSourcePos = sourcePos; + + Density = density; + Decay = decay; + Weight = weight; + Exposure = exposure; + UsesVertexShader = true; + } + + + public override void Draw(GameTime gameTime) + { + if (effect == null) + effect = Game.Content.Load("Shaders/LightRays"); + + effect.CurrentTechnique = effect.Techniques["LightRayFX"]; + + effect.Parameters["halfPixel"].SetValue(HalfPixel); + + effect.Parameters["Density"].SetValue(Density); + effect.Parameters["Decay"].SetValue(Decay); + effect.Parameters["Weight"].SetValue(Weight); + effect.Parameters["Exposure"].SetValue(Exposure); + + effect.Parameters["lightScreenPosition"].SetValue(lighScreenSourcePos); + + // Set Params. + base.Draw(gameTime); + + } + } +} diff --git a/RogueCastle/src/Crepuscular Rays/LightSourceMask.cs b/RogueCastle/src/Crepuscular Rays/LightSourceMask.cs new file mode 100644 index 0000000..a4181d7 --- /dev/null +++ b/RogueCastle/src/Crepuscular Rays/LightSourceMask.cs @@ -0,0 +1,51 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Randomchaos2DGodRays +{ + public class LightSourceMask : BasePostProcess + { + public Texture lishsourceTexture; + public Vector2 lighScreenSourcePos; + public string lightSourceasset; + public float lightSize = 1500; + + public LightSourceMask(Game game, Vector2 sourcePos, string lightSourceasset, float lightSize) + : base(game) + { + UsesVertexShader = true; + lighScreenSourcePos = sourcePos; + this.lightSourceasset = lightSourceasset; + this.lightSize = lightSize; + } + + public override void Draw(GameTime gameTime) + { + + if (effect == null) + { + effect = Game.Content.Load("Shaders/LightSourceMask"); + lishsourceTexture = Game.Content.Load(lightSourceasset); + } + + effect.Parameters["screenRes"].SetValue(new Vector2(16, 9)); + effect.Parameters["halfPixel"].SetValue(HalfPixel); + effect.CurrentTechnique = effect.Techniques["LightSourceMask"]; + + effect.Parameters["flare"].SetValue(lishsourceTexture); + + effect.Parameters["SunSize"].SetValue(lightSize); + effect.Parameters["lightScreenPosition"].SetValue(lighScreenSourcePos); + + // Set Params. + base.Draw(gameTime); + + } + } +} diff --git a/RogueCastle/src/Crepuscular Rays/PostProcessingManager.cs b/RogueCastle/src/Crepuscular Rays/PostProcessingManager.cs new file mode 100644 index 0000000..23e07c2 --- /dev/null +++ b/RogueCastle/src/Crepuscular Rays/PostProcessingManager.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; + +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Randomchaos2DGodRays +{ + public class PostProcessingManager + { + protected Game Game; + public Texture2D Scene; + + public RenderTarget2D newScene; + + protected List postProcessingEffects = new List(); + + public Vector2 HalfPixel; + + private SpriteBatch m_spriteBatch; + public SpriteBatch spriteBatch + { + get { return m_spriteBatch; } + } + + public PostProcessingManager(Game game, SpriteBatch spriteBatch) + { + Game = game; + m_spriteBatch = spriteBatch; + } + + public void AddEffect(BasePostProcessingEffect ppEfect) + { + postProcessingEffects.Add(ppEfect); + } + + public virtual void Draw(GameTime gameTime, Texture2D scene) + { + HalfPixel = -new Vector2(.5f / (float)Game.GraphicsDevice.Viewport.Width, + .5f / (float)Game.GraphicsDevice.Viewport.Height); + + int maxEffect = postProcessingEffects.Count; + + Scene = scene; + + for (int e = 0; e < maxEffect; e++) + { + if (postProcessingEffects[e].Enabled) + { + postProcessingEffects[e].HalfPixel = HalfPixel; + + postProcessingEffects[e].orgScene = scene; + postProcessingEffects[e].Draw(gameTime, Scene); + Scene = postProcessingEffects[e].lastScene; + } + } + + spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque); + spriteBatch.Draw(Scene, new Rectangle(0, 0, Game.GraphicsDevice.Viewport.Width, Game.GraphicsDevice.Viewport.Height), Color.White); + spriteBatch.End(); + } + + protected void SaveTexture(Texture2D texture, string name) + { + FileStream stream = new FileStream(name, FileMode.Create); + texture.SaveAsJpeg(stream, texture.Width, texture.Height); + stream.Close(); + } + } +} diff --git a/RogueCastle/src/Crepuscular Rays/ScreenQuad.cs b/RogueCastle/src/Crepuscular Rays/ScreenQuad.cs new file mode 100644 index 0000000..6f5f783 --- /dev/null +++ b/RogueCastle/src/Crepuscular Rays/ScreenQuad.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Randomchaos2DGodRays +{ + public class ScreenQuad + { + VertexPositionTexture[] corners; + VertexBuffer vb; + short[] ib; + VertexDeclaration vertDec; + + Game Game; + + public ScreenQuad(Game game) + { + Game = game; + corners = new VertexPositionTexture[4]; + corners[0].Position = new Vector3(0, 0, 0); + corners[0].TextureCoordinate = Vector2.Zero; + } + + /// + /// Allows the game component to perform any initialization it needs to before starting + /// to run. This is where it can query for any required services and load content. + /// + public virtual void Initialize() + { + vertDec = VertexPositionTexture.VertexDeclaration; + + corners = new VertexPositionTexture[] + { + new VertexPositionTexture( + new Vector3(1,-1,0), + new Vector2(1,1)), + new VertexPositionTexture( + new Vector3(-1,-1,0), + new Vector2(0,1)), + new VertexPositionTexture( + new Vector3(-1,1,0), + new Vector2(0,0)), + new VertexPositionTexture( + new Vector3(1,1,0), + new Vector2(1,0)) + }; + + ib = new short[] { 0, 1, 2, 2, 3, 0 }; + vb = new VertexBuffer(Game.GraphicsDevice, typeof(VertexPositionTexture), corners.Length, BufferUsage.None); + vb.SetData(corners); + } + + public virtual void Draw() + { + Game.GraphicsDevice.SetVertexBuffer(vb); + Game.GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, corners, 0, 4, ib, 0, 2); + } + } +} diff --git a/RogueCastle/src/EVs/EnemyEV.cs b/RogueCastle/src/EVs/EnemyEV.cs new file mode 100644 index 0000000..f1a89ff --- /dev/null +++ b/RogueCastle/src/EVs/EnemyEV.cs @@ -0,0 +1,238 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + class EnemyEV + { + public const string Skeleton_Basic_Name = "Skeleton"; public const int Skeleton_Basic_MaxHealth = 27; public const int Skeleton_Basic_Damage = 20; public const int Skeleton_Basic_XPValue = 100; public const int Skeleton_Basic_Speed = 80; public const int Skeleton_Basic_Jump = 925; public const float Skeleton_Basic_Cooldown = 0.75f; public const int Skeleton_Basic_MinDropAmount = 1; public const int Skeleton_Basic_MaxDropAmount = 2; public const float Skeleton_Basic_DropChance = 0.4f; public const float Skeleton_Basic_TurnSpeed = 10f; public const float Skeleton_Basic_ProjectileSpeed = 1040f; public const float Skeleton_Basic_AnimationDelay = 10f; public const bool Skeleton_Basic_AlwaysFaceTarget = true; public const bool Skeleton_Basic_CanFallOffLedges = false; public const bool Skeleton_Basic_CanBeKnockedBack = true; public const bool Skeleton_Basic_IsWeighted = true; public static Vector2 Skeleton_Basic_KnockBack = new Vector2(0, 0); public static Vector2 Skeleton_Basic_Scale = new Vector2(2.5f, 2.5f); public static Vector2 Skeleton_Basic_ProjectileScale = new Vector2(1.25f, 1.25f); public static Color Skeleton_Basic_Tint = new Color(255, 255, 255); public const int Skeleton_Basic_MeleeRadius = 225; public const int Skeleton_Basic_ProjectileRadius = 500; public const int Skeleton_Basic_EngageRadius = 700; + public const string Skeleton_Advanced_Name = "Mr Bones"; public const int Skeleton_Advanced_MaxHealth = 36; public const int Skeleton_Advanced_Damage = 26; public const int Skeleton_Advanced_XPValue = 150; public const int Skeleton_Advanced_Speed = 80; public const int Skeleton_Advanced_Jump = 925; public const float Skeleton_Advanced_Cooldown = 0.45f; public const int Skeleton_Advanced_MinDropAmount = 1; public const int Skeleton_Advanced_MaxDropAmount = 2; public const float Skeleton_Advanced_DropChance = 0.5f; public const float Skeleton_Advanced_TurnSpeed = 10f; public const float Skeleton_Advanced_ProjectileSpeed = 1040f; public const float Skeleton_Advanced_AnimationDelay = 10f; public const bool Skeleton_Advanced_AlwaysFaceTarget = true; public const bool Skeleton_Advanced_CanFallOffLedges = false; public const bool Skeleton_Advanced_CanBeKnockedBack = true; public const bool Skeleton_Advanced_IsWeighted = true; public static Vector2 Skeleton_Advanced_KnockBack = new Vector2(0, 0); public static Vector2 Skeleton_Advanced_Scale = new Vector2(3.0f, 3.0f); public static Vector2 Skeleton_Advanced_ProjectileScale = new Vector2(1.5f, 1.5f); public static Color Skeleton_Advanced_Tint = new Color(215, 125, 135); public const int Skeleton_Advanced_MeleeRadius = 225; public const int Skeleton_Advanced_ProjectileRadius = 500; public const int Skeleton_Advanced_EngageRadius = 700; + public const string Skeleton_Expert_Name = "McRib"; public const int Skeleton_Expert_MaxHealth = 68; public const int Skeleton_Expert_Damage = 28; public const int Skeleton_Expert_XPValue = 200; public const int Skeleton_Expert_Speed = 140; public const int Skeleton_Expert_Jump = 925; public const float Skeleton_Expert_Cooldown = 0.4f; public const int Skeleton_Expert_MinDropAmount = 2; public const int Skeleton_Expert_MaxDropAmount = 3; public const float Skeleton_Expert_DropChance = 1f; public const float Skeleton_Expert_TurnSpeed = 10f; public const float Skeleton_Expert_ProjectileSpeed = 1040f; public const float Skeleton_Expert_AnimationDelay = 10f; public const bool Skeleton_Expert_AlwaysFaceTarget = true; public const bool Skeleton_Expert_CanFallOffLedges = false; public const bool Skeleton_Expert_CanBeKnockedBack = true; public const bool Skeleton_Expert_IsWeighted = true; public static Vector2 Skeleton_Expert_KnockBack = new Vector2(0, 0); public static Vector2 Skeleton_Expert_Scale = new Vector2(3.5f, 3.5f); public static Vector2 Skeleton_Expert_ProjectileScale = new Vector2(1.75f, 1.75f); public static Color Skeleton_Expert_Tint = new Color(125, 125, 125); public const int Skeleton_Expert_MeleeRadius = 225; public const int Skeleton_Expert_ProjectileRadius = 500; public const int Skeleton_Expert_EngageRadius = 700; + public const string Skeleton_Miniboss_Name = "Berith & Halphas"; public const int Skeleton_Miniboss_MaxHealth = 255; public const int Skeleton_Miniboss_Damage = 32; public const int Skeleton_Miniboss_XPValue = 1000; public const int Skeleton_Miniboss_Speed = 60; public const int Skeleton_Miniboss_Jump = 925; public const float Skeleton_Miniboss_Cooldown = 0.15f; public const int Skeleton_Miniboss_MinDropAmount = 11; public const int Skeleton_Miniboss_MaxDropAmount = 18; public const float Skeleton_Miniboss_DropChance = 1f; public const float Skeleton_Miniboss_TurnSpeed = 10f; public const float Skeleton_Miniboss_ProjectileSpeed = 1040f; public const float Skeleton_Miniboss_AnimationDelay = 10f; public const bool Skeleton_Miniboss_AlwaysFaceTarget = true; public const bool Skeleton_Miniboss_CanFallOffLedges = false; public const bool Skeleton_Miniboss_CanBeKnockedBack = false; public const bool Skeleton_Miniboss_IsWeighted = true; public static Vector2 Skeleton_Miniboss_KnockBack = new Vector2(0, 0); public static Vector2 Skeleton_Miniboss_Scale = new Vector2(7.0f, 7.0f); public static Vector2 Skeleton_Miniboss_ProjectileScale = new Vector2(1.75f, 1.75f); public static Color Skeleton_Miniboss_Tint = new Color(125, 115, 5); public const int Skeleton_Miniboss_MeleeRadius = 225; public const int Skeleton_Miniboss_ProjectileRadius = 500; public const int Skeleton_Miniboss_EngageRadius = 700; + public const string Knight_Basic_Name = "Corrupt Knight"; public const int Knight_Basic_MaxHealth = 40; public const int Knight_Basic_Damage = 27; public const int Knight_Basic_XPValue = 125; public const int Knight_Basic_Speed = 75; public const int Knight_Basic_Jump = 950; public const float Knight_Basic_Cooldown = 0.75f; public const int Knight_Basic_MinDropAmount = 1; public const int Knight_Basic_MaxDropAmount = 2; public const float Knight_Basic_DropChance = 0.4f; public const float Knight_Basic_TurnSpeed = 10f; public const float Knight_Basic_ProjectileSpeed = 860f; public const float Knight_Basic_AnimationDelay = 10f; public const bool Knight_Basic_AlwaysFaceTarget = true; public const bool Knight_Basic_CanFallOffLedges = false; public const bool Knight_Basic_CanBeKnockedBack = true; public const bool Knight_Basic_IsWeighted = true; public static Vector2 Knight_Basic_KnockBack = new Vector2(0, 0); public static Vector2 Knight_Basic_Scale = new Vector2(1.8f, 1.8f); public static Vector2 Knight_Basic_ProjectileScale = new Vector2(1.0f, 1.0f); public static Color Knight_Basic_Tint = new Color(200, 170, 50); public const int Knight_Basic_MeleeRadius = 325; public const int Knight_Basic_ProjectileRadius = 690; public const int Knight_Basic_EngageRadius = 850; + public const string Knight_Advanced_Name = "Corrupt Vanguard"; public const int Knight_Advanced_MaxHealth = 58; public const int Knight_Advanced_Damage = 32; public const int Knight_Advanced_XPValue = 185; public const int Knight_Advanced_Speed = 75; public const int Knight_Advanced_Jump = 950; public const float Knight_Advanced_Cooldown = 0.5f; public const int Knight_Advanced_MinDropAmount = 1; public const int Knight_Advanced_MaxDropAmount = 2; public const float Knight_Advanced_DropChance = 0.5f; public const float Knight_Advanced_TurnSpeed = 10f; public const float Knight_Advanced_ProjectileSpeed = 860f; public const float Knight_Advanced_AnimationDelay = 10f; public const bool Knight_Advanced_AlwaysFaceTarget = true; public const bool Knight_Advanced_CanFallOffLedges = false; public const bool Knight_Advanced_CanBeKnockedBack = true; public const bool Knight_Advanced_IsWeighted = true; public static Vector2 Knight_Advanced_KnockBack = new Vector2(0, 0); public static Vector2 Knight_Advanced_Scale = new Vector2(2.2f, 2.2f); public static Vector2 Knight_Advanced_ProjectileScale = new Vector2(1.2f, 1.2f); public static Color Knight_Advanced_Tint = new Color(215, 20, 20); public const int Knight_Advanced_MeleeRadius = 325; public const int Knight_Advanced_ProjectileRadius = 690; public const int Knight_Advanced_EngageRadius = 850; + public const string Knight_Expert_Name = "Corrupt Lord"; public const int Knight_Expert_MaxHealth = 79; public const int Knight_Expert_Damage = 36; public const int Knight_Expert_XPValue = 250; public const int Knight_Expert_Speed = 125; public const int Knight_Expert_Jump = 950; public const float Knight_Expert_Cooldown = 0.5f; public const int Knight_Expert_MinDropAmount = 2; public const int Knight_Expert_MaxDropAmount = 4; public const float Knight_Expert_DropChance = 1f; public const float Knight_Expert_TurnSpeed = 10f; public const float Knight_Expert_ProjectileSpeed = 780f; public const float Knight_Expert_AnimationDelay = 10f; public const bool Knight_Expert_AlwaysFaceTarget = true; public const bool Knight_Expert_CanFallOffLedges = false; public const bool Knight_Expert_CanBeKnockedBack = true; public const bool Knight_Expert_IsWeighted = true; public static Vector2 Knight_Expert_KnockBack = new Vector2(0, 0); public static Vector2 Knight_Expert_Scale = new Vector2(2.6f, 2.6f); public static Vector2 Knight_Expert_ProjectileScale = new Vector2(1.4f, 1.4f); public static Color Knight_Expert_Tint = new Color(255, 255, 255); public const int Knight_Expert_MeleeRadius = 325; public const int Knight_Expert_ProjectileRadius = 690; public const int Knight_Expert_EngageRadius = 850; + public const string Knight_Miniboss_Name = "Botis"; public const int Knight_Miniboss_MaxHealth = 265; public const int Knight_Miniboss_Damage = 40; public const int Knight_Miniboss_XPValue = 1250; public const int Knight_Miniboss_Speed = 200; public const int Knight_Miniboss_Jump = 1350; public const float Knight_Miniboss_Cooldown = 0.65f; public const int Knight_Miniboss_MinDropAmount = 11; public const int Knight_Miniboss_MaxDropAmount = 18; public const float Knight_Miniboss_DropChance = 1f; public const float Knight_Miniboss_TurnSpeed = 10f; public const float Knight_Miniboss_ProjectileSpeed = 780f; public const float Knight_Miniboss_AnimationDelay = 10f; public const bool Knight_Miniboss_AlwaysFaceTarget = true; public const bool Knight_Miniboss_CanFallOffLedges = false; public const bool Knight_Miniboss_CanBeKnockedBack = true; public const bool Knight_Miniboss_IsWeighted = true; public static Vector2 Knight_Miniboss_KnockBack = new Vector2(0, 0); public static Vector2 Knight_Miniboss_Scale = new Vector2(3.0f, 3.0f); public static Vector2 Knight_Miniboss_ProjectileScale = new Vector2(1.4f, 1.4f); public static Color Knight_Miniboss_Tint = new Color(0, 0, 0); public const int Knight_Miniboss_MeleeRadius = 325; public const int Knight_Miniboss_ProjectileRadius = 690; public const int Knight_Miniboss_EngageRadius = 850; + public const string Blob_Basic_Name = "Bloob"; public const int Blob_Basic_MaxHealth = 14; public const int Blob_Basic_Damage = 13; public const int Blob_Basic_XPValue = 25; public const int Blob_Basic_Speed = 50; public const int Blob_Basic_Jump = 975; public const float Blob_Basic_Cooldown = 2f; public const int Blob_Basic_MinDropAmount = 1; public const int Blob_Basic_MaxDropAmount = 1; public const float Blob_Basic_DropChance = 0.225f; public const float Blob_Basic_TurnSpeed = 10f; public const float Blob_Basic_ProjectileSpeed = 0f; public const float Blob_Basic_AnimationDelay = 20f; public const bool Blob_Basic_AlwaysFaceTarget = true; public const bool Blob_Basic_CanFallOffLedges = true; public const bool Blob_Basic_CanBeKnockedBack = true; public const bool Blob_Basic_IsWeighted = true; public static Vector2 Blob_Basic_KnockBack = new Vector2(0, 0); public static Vector2 Blob_Basic_Scale = new Vector2(2.5f, 2.5f); public static Vector2 Blob_Basic_ProjectileScale = new Vector2(2, 2); public static Color Blob_Basic_Tint = new Color(255, 255, 255); public const int Blob_Basic_MeleeRadius = 225; public const int Blob_Basic_ProjectileRadius = 500; public const int Blob_Basic_EngageRadius = 750; + public const string Blob_Advanced_Name = "Bloobite"; public const int Blob_Advanced_MaxHealth = 18; public const int Blob_Advanced_Damage = 14; public const int Blob_Advanced_XPValue = 29; public const int Blob_Advanced_Speed = 80; public const int Blob_Advanced_Jump = 975; public const float Blob_Advanced_Cooldown = 2f; public const int Blob_Advanced_MinDropAmount = 1; public const int Blob_Advanced_MaxDropAmount = 1; public const float Blob_Advanced_DropChance = 0.2f; public const float Blob_Advanced_TurnSpeed = 10f; public const float Blob_Advanced_ProjectileSpeed = 0f; public const float Blob_Advanced_AnimationDelay = 20f; public const bool Blob_Advanced_AlwaysFaceTarget = true; public const bool Blob_Advanced_CanFallOffLedges = true; public const bool Blob_Advanced_CanBeKnockedBack = true; public const bool Blob_Advanced_IsWeighted = true; public static Vector2 Blob_Advanced_KnockBack = new Vector2(0, 0); public static Vector2 Blob_Advanced_Scale = new Vector2(4.0f, 4.0f); public static Vector2 Blob_Advanced_ProjectileScale = new Vector2(3.0f, 3.0f); public static Color Blob_Advanced_Tint = new Color(35, 115, 220); public const int Blob_Advanced_MeleeRadius = 225; public const int Blob_Advanced_ProjectileRadius = 500; public const int Blob_Advanced_EngageRadius = 750; + public const string Blob_Expert_Name = "Bloobasaurus Rex"; public const int Blob_Expert_MaxHealth = 22; public const int Blob_Expert_Damage = 16; public const int Blob_Expert_XPValue = 35; public const int Blob_Expert_Speed = 90; public const int Blob_Expert_Jump = 975; public const float Blob_Expert_Cooldown = 2f; public const int Blob_Expert_MinDropAmount = 1; public const int Blob_Expert_MaxDropAmount = 1; public const float Blob_Expert_DropChance = 0.1f; public const float Blob_Expert_TurnSpeed = 10f; public const float Blob_Expert_ProjectileSpeed = 0f; public const float Blob_Expert_AnimationDelay = 20f; public const bool Blob_Expert_AlwaysFaceTarget = true; public const bool Blob_Expert_CanFallOffLedges = true; public const bool Blob_Expert_CanBeKnockedBack = true; public const bool Blob_Expert_IsWeighted = true; public static Vector2 Blob_Expert_KnockBack = new Vector2(0, 0); public static Vector2 Blob_Expert_Scale = new Vector2(5.5f, 5.5f); public static Vector2 Blob_Expert_ProjectileScale = new Vector2(4.0f, 4.0f); public static Color Blob_Expert_Tint = new Color(215, 20, 20); public const int Blob_Expert_MeleeRadius = 225; public const int Blob_Expert_ProjectileRadius = 500; public const int Blob_Expert_EngageRadius = 750; + public const string Blob_Miniboss_Name = "Herodotus"; public const int Blob_Miniboss_MaxHealth = 32; public const int Blob_Miniboss_Damage = 16; public const int Blob_Miniboss_XPValue = 70; public const int Blob_Miniboss_Speed = 110; public const int Blob_Miniboss_Jump = 975; public const float Blob_Miniboss_Cooldown = 2f; public const int Blob_Miniboss_MinDropAmount = 2; public const int Blob_Miniboss_MaxDropAmount = 4; public const float Blob_Miniboss_DropChance = 0.1f; public const float Blob_Miniboss_TurnSpeed = 10f; public const float Blob_Miniboss_ProjectileSpeed = 0f; public const float Blob_Miniboss_AnimationDelay = 20f; public const bool Blob_Miniboss_AlwaysFaceTarget = true; public const bool Blob_Miniboss_CanFallOffLedges = true; public const bool Blob_Miniboss_CanBeKnockedBack = true; public const bool Blob_Miniboss_IsWeighted = true; public static Vector2 Blob_Miniboss_KnockBack = new Vector2(0, 0); public static Vector2 Blob_Miniboss_Scale = new Vector2(3.25f, 3.25f); public static Vector2 Blob_Miniboss_ProjectileScale = new Vector2(2, 2); public static Color Blob_Miniboss_Tint = new Color(130, 130, 130); public const int Blob_Miniboss_MeleeRadius = 225; public const int Blob_Miniboss_ProjectileRadius = 500; public const int Blob_Miniboss_EngageRadius = 750; + public const string BallAndChain_Basic_Name = "Chaintor"; public const int BallAndChain_Basic_MaxHealth = 40; public const int BallAndChain_Basic_Damage = 27; public const int BallAndChain_Basic_XPValue = 125; public const int BallAndChain_Basic_Speed = 100; public const int BallAndChain_Basic_Jump = 600; public const float BallAndChain_Basic_Cooldown = 2f; public const int BallAndChain_Basic_MinDropAmount = 1; public const int BallAndChain_Basic_MaxDropAmount = 2; public const float BallAndChain_Basic_DropChance = 0.4f; public const float BallAndChain_Basic_TurnSpeed = 10f; public const float BallAndChain_Basic_ProjectileSpeed = 1020f; public const float BallAndChain_Basic_AnimationDelay = 10f; public const bool BallAndChain_Basic_AlwaysFaceTarget = true; public const bool BallAndChain_Basic_CanFallOffLedges = false; public const bool BallAndChain_Basic_CanBeKnockedBack = true; public const bool BallAndChain_Basic_IsWeighted = true; public static Vector2 BallAndChain_Basic_KnockBack = new Vector2(175, 175); public static Vector2 BallAndChain_Basic_Scale = new Vector2(1.8f, 1.8f); public static Vector2 BallAndChain_Basic_ProjectileScale = new Vector2(2.0f, 2.0f); public static Color BallAndChain_Basic_Tint = new Color(255, 255, 255); public const int BallAndChain_Basic_MeleeRadius = 225; public const int BallAndChain_Basic_ProjectileRadius = 500; public const int BallAndChain_Basic_EngageRadius = 800; + public const string BallAndChain_Advanced_Name = "Chaintex"; public const int BallAndChain_Advanced_MaxHealth = 58; public const int BallAndChain_Advanced_Damage = 32; public const int BallAndChain_Advanced_XPValue = 150; public const int BallAndChain_Advanced_Speed = 150; public const int BallAndChain_Advanced_Jump = 600; public const float BallAndChain_Advanced_Cooldown = 2f; public const int BallAndChain_Advanced_MinDropAmount = 1; public const int BallAndChain_Advanced_MaxDropAmount = 2; public const float BallAndChain_Advanced_DropChance = 0.5f; public const float BallAndChain_Advanced_TurnSpeed = 10f; public const float BallAndChain_Advanced_ProjectileSpeed = 1020f; public const float BallAndChain_Advanced_AnimationDelay = 10f; public const bool BallAndChain_Advanced_AlwaysFaceTarget = true; public const bool BallAndChain_Advanced_CanFallOffLedges = false; public const bool BallAndChain_Advanced_CanBeKnockedBack = true; public const bool BallAndChain_Advanced_IsWeighted = true; public static Vector2 BallAndChain_Advanced_KnockBack = new Vector2(175, 175); public static Vector2 BallAndChain_Advanced_Scale = new Vector2(2.0f, 2.0f); public static Vector2 BallAndChain_Advanced_ProjectileScale = new Vector2(2.3f, 2.3f); public static Color BallAndChain_Advanced_Tint = new Color(255, 195, 50); public const int BallAndChain_Advanced_MeleeRadius = 225; public const int BallAndChain_Advanced_ProjectileRadius = 500; public const int BallAndChain_Advanced_EngageRadius = 800; + public const string BallAndChain_Expert_Name = "Chaintus"; public const int BallAndChain_Expert_MaxHealth = 79; public const int BallAndChain_Expert_Damage = 36; public const int BallAndChain_Expert_XPValue = 200; public const int BallAndChain_Expert_Speed = 175; public const int BallAndChain_Expert_Jump = 600; public const float BallAndChain_Expert_Cooldown = 2f; public const int BallAndChain_Expert_MinDropAmount = 2; public const int BallAndChain_Expert_MaxDropAmount = 4; public const float BallAndChain_Expert_DropChance = 1f; public const float BallAndChain_Expert_TurnSpeed = 10f; public const float BallAndChain_Expert_ProjectileSpeed = 1020f; public const float BallAndChain_Expert_AnimationDelay = 10f; public const bool BallAndChain_Expert_AlwaysFaceTarget = true; public const bool BallAndChain_Expert_CanFallOffLedges = false; public const bool BallAndChain_Expert_CanBeKnockedBack = true; public const bool BallAndChain_Expert_IsWeighted = true; public static Vector2 BallAndChain_Expert_KnockBack = new Vector2(175, 175); public static Vector2 BallAndChain_Expert_Scale = new Vector2(2.2f, 2.2f); public static Vector2 BallAndChain_Expert_ProjectileScale = new Vector2(2.6f, 2.6f); public static Color BallAndChain_Expert_Tint = new Color(0, 255, 0); public const int BallAndChain_Expert_MeleeRadius = 225; public const int BallAndChain_Expert_ProjectileRadius = 500; public const int BallAndChain_Expert_EngageRadius = 800; + public const string BallAndChain_Miniboss_Name = "Pantheon"; public const int BallAndChain_Miniboss_MaxHealth = 300; public const int BallAndChain_Miniboss_Damage = 60; public const int BallAndChain_Miniboss_XPValue = 1250; public const int BallAndChain_Miniboss_Speed = 100; public const int BallAndChain_Miniboss_Jump = 600; public const float BallAndChain_Miniboss_Cooldown = 2f; public const int BallAndChain_Miniboss_MinDropAmount = 1; public const int BallAndChain_Miniboss_MaxDropAmount = 4; public const float BallAndChain_Miniboss_DropChance = 1f; public const float BallAndChain_Miniboss_TurnSpeed = 10f; public const float BallAndChain_Miniboss_ProjectileSpeed = 1020f; public const float BallAndChain_Miniboss_AnimationDelay = 10f; public const bool BallAndChain_Miniboss_AlwaysFaceTarget = false; public const bool BallAndChain_Miniboss_CanFallOffLedges = false; public const bool BallAndChain_Miniboss_CanBeKnockedBack = true; public const bool BallAndChain_Miniboss_IsWeighted = true; public static Vector2 BallAndChain_Miniboss_KnockBack = new Vector2(175, 175); public static Vector2 BallAndChain_Miniboss_Scale = new Vector2(2.0f, 2.0f); public static Vector2 BallAndChain_Miniboss_ProjectileScale = new Vector2(3.0f, 3.0f); public static Color BallAndChain_Miniboss_Tint = new Color(255, 0, 0); public const int BallAndChain_Miniboss_MeleeRadius = 225; public const int BallAndChain_Miniboss_ProjectileRadius = 500; public const int BallAndChain_Miniboss_EngageRadius = 800; + public const string EarthWizard_Basic_Name = "Earthsor"; public const int EarthWizard_Basic_MaxHealth = 32; public const int EarthWizard_Basic_Damage = 20; public const int EarthWizard_Basic_XPValue = 175; public const int EarthWizard_Basic_Speed = 270; public const int EarthWizard_Basic_Jump = 300; public const float EarthWizard_Basic_Cooldown = 1.25f; public const int EarthWizard_Basic_MinDropAmount = 1; public const int EarthWizard_Basic_MaxDropAmount = 2; public const float EarthWizard_Basic_DropChance = 0.4f; public const float EarthWizard_Basic_TurnSpeed = 0.04f; public const float EarthWizard_Basic_ProjectileSpeed = 650f; public const float EarthWizard_Basic_AnimationDelay = 10f; public const bool EarthWizard_Basic_AlwaysFaceTarget = true; public const bool EarthWizard_Basic_CanFallOffLedges = true; public const bool EarthWizard_Basic_CanBeKnockedBack = true; public const bool EarthWizard_Basic_IsWeighted = false; public static Vector2 EarthWizard_Basic_KnockBack = new Vector2(250, 200); public static Vector2 EarthWizard_Basic_Scale = new Vector2(1.8f, 1.8f); public static Vector2 EarthWizard_Basic_ProjectileScale = new Vector2(1.25f, 1.25f); public static Color EarthWizard_Basic_Tint = new Color(95, 255, 175); public const int EarthWizard_Basic_MeleeRadius = 225; public const int EarthWizard_Basic_ProjectileRadius = 700; public const int EarthWizard_Basic_EngageRadius = 900; + public const string EarthWizard_Advanced_Name = "Gravisor"; public const int EarthWizard_Advanced_MaxHealth = 45; public const int EarthWizard_Advanced_Damage = 24; public const int EarthWizard_Advanced_XPValue = 200; public const int EarthWizard_Advanced_Speed = 270; public const int EarthWizard_Advanced_Jump = 300; public const float EarthWizard_Advanced_Cooldown = 1.25f; public const int EarthWizard_Advanced_MinDropAmount = 1; public const int EarthWizard_Advanced_MaxDropAmount = 2; public const float EarthWizard_Advanced_DropChance = 0.5f; public const float EarthWizard_Advanced_TurnSpeed = 0.04f; public const float EarthWizard_Advanced_ProjectileSpeed = 650f; public const float EarthWizard_Advanced_AnimationDelay = 10f; public const bool EarthWizard_Advanced_AlwaysFaceTarget = true; public const bool EarthWizard_Advanced_CanFallOffLedges = true; public const bool EarthWizard_Advanced_CanBeKnockedBack = true; public const bool EarthWizard_Advanced_IsWeighted = false; public static Vector2 EarthWizard_Advanced_KnockBack = new Vector2(250, 200); public static Vector2 EarthWizard_Advanced_Scale = new Vector2(2.2f, 2.2f); public static Vector2 EarthWizard_Advanced_ProjectileScale = new Vector2(1.75f, 1.75f); public static Color EarthWizard_Advanced_Tint = new Color(15, 155, 35); public const int EarthWizard_Advanced_MeleeRadius = 225; public const int EarthWizard_Advanced_ProjectileRadius = 700; public const int EarthWizard_Advanced_EngageRadius = 900; + public const string EarthWizard_Expert_Name = "Terrasor"; public const int EarthWizard_Expert_MaxHealth = 72; public const int EarthWizard_Expert_Damage = 27; public const int EarthWizard_Expert_XPValue = 400; public const int EarthWizard_Expert_Speed = 300; public const int EarthWizard_Expert_Jump = 300; public const float EarthWizard_Expert_Cooldown = 2f; public const int EarthWizard_Expert_MinDropAmount = 2; public const int EarthWizard_Expert_MaxDropAmount = 3; public const float EarthWizard_Expert_DropChance = 1f; public const float EarthWizard_Expert_TurnSpeed = 0.04f; public const float EarthWizard_Expert_ProjectileSpeed = 650f; public const float EarthWizard_Expert_AnimationDelay = 10f; public const bool EarthWizard_Expert_AlwaysFaceTarget = true; public const bool EarthWizard_Expert_CanFallOffLedges = true; public const bool EarthWizard_Expert_CanBeKnockedBack = true; public const bool EarthWizard_Expert_IsWeighted = false; public static Vector2 EarthWizard_Expert_KnockBack = new Vector2(250, 200); public static Vector2 EarthWizard_Expert_Scale = new Vector2(2.6f, 2.6f); public static Vector2 EarthWizard_Expert_ProjectileScale = new Vector2(2.25f, 2.25f); public static Color EarthWizard_Expert_Tint = new Color(130, 150, 130); public const int EarthWizard_Expert_MeleeRadius = 225; public const int EarthWizard_Expert_ProjectileRadius = 700; public const int EarthWizard_Expert_EngageRadius = 900; + public const string EarthWizard_Miniboss_Name = "Barbatos & Amon"; public const int EarthWizard_Miniboss_MaxHealth = 225; public const int EarthWizard_Miniboss_Damage = 30; public const int EarthWizard_Miniboss_XPValue = 1000; public const int EarthWizard_Miniboss_Speed = 225; public const int EarthWizard_Miniboss_Jump = 300; public const float EarthWizard_Miniboss_Cooldown = 0.75f; public const int EarthWizard_Miniboss_MinDropAmount = 18; public const int EarthWizard_Miniboss_MaxDropAmount = 25; public const float EarthWizard_Miniboss_DropChance = 1f; public const float EarthWizard_Miniboss_TurnSpeed = 0.04f; public const float EarthWizard_Miniboss_ProjectileSpeed = 650f; public const float EarthWizard_Miniboss_AnimationDelay = 10f; public const bool EarthWizard_Miniboss_AlwaysFaceTarget = true; public const bool EarthWizard_Miniboss_CanFallOffLedges = true; public const bool EarthWizard_Miniboss_CanBeKnockedBack = true; public const bool EarthWizard_Miniboss_IsWeighted = false; public static Vector2 EarthWizard_Miniboss_KnockBack = new Vector2(75, 25); public static Vector2 EarthWizard_Miniboss_Scale = new Vector2(3.5f, 3.5f); public static Vector2 EarthWizard_Miniboss_ProjectileScale = new Vector2(4.0f, 4.0f); public static Color EarthWizard_Miniboss_Tint = new Color(100, 100, 100); public const int EarthWizard_Miniboss_MeleeRadius = 225; public const int EarthWizard_Miniboss_ProjectileRadius = 700; public const int EarthWizard_Miniboss_EngageRadius = 900; + public const string FireWizard_Basic_Name = "Flamelock"; public const int FireWizard_Basic_MaxHealth = 32; public const int FireWizard_Basic_Damage = 20; public const int FireWizard_Basic_XPValue = 175; public const int FireWizard_Basic_Speed = 270; public const int FireWizard_Basic_Jump = 300; public const float FireWizard_Basic_Cooldown = 1.25f; public const int FireWizard_Basic_MinDropAmount = 1; public const int FireWizard_Basic_MaxDropAmount = 2; public const float FireWizard_Basic_DropChance = 0.4f; public const float FireWizard_Basic_TurnSpeed = 0.04f; public const float FireWizard_Basic_ProjectileSpeed = 650f; public const float FireWizard_Basic_AnimationDelay = 10f; public const bool FireWizard_Basic_AlwaysFaceTarget = true; public const bool FireWizard_Basic_CanFallOffLedges = true; public const bool FireWizard_Basic_CanBeKnockedBack = true; public const bool FireWizard_Basic_IsWeighted = false; public static Vector2 FireWizard_Basic_KnockBack = new Vector2(250, 200); public static Vector2 FireWizard_Basic_Scale = new Vector2(1.8f, 1.8f); public static Vector2 FireWizard_Basic_ProjectileScale = new Vector2(1f, 1f); public static Color FireWizard_Basic_Tint = new Color(215, 110, 105); public const int FireWizard_Basic_MeleeRadius = 225; public const int FireWizard_Basic_ProjectileRadius = 700; public const int FireWizard_Basic_EngageRadius = 900; + public const string FireWizard_Advanced_Name = "Blazelock"; public const int FireWizard_Advanced_MaxHealth = 45; public const int FireWizard_Advanced_Damage = 28; public const int FireWizard_Advanced_XPValue = 200; public const int FireWizard_Advanced_Speed = 270; public const int FireWizard_Advanced_Jump = 300; public const float FireWizard_Advanced_Cooldown = 1.25f; public const int FireWizard_Advanced_MinDropAmount = 1; public const int FireWizard_Advanced_MaxDropAmount = 2; public const float FireWizard_Advanced_DropChance = 0.5f; public const float FireWizard_Advanced_TurnSpeed = 0.04f; public const float FireWizard_Advanced_ProjectileSpeed = 650f; public const float FireWizard_Advanced_AnimationDelay = 10f; public const bool FireWizard_Advanced_AlwaysFaceTarget = true; public const bool FireWizard_Advanced_CanFallOffLedges = true; public const bool FireWizard_Advanced_CanBeKnockedBack = true; public const bool FireWizard_Advanced_IsWeighted = false; public static Vector2 FireWizard_Advanced_KnockBack = new Vector2(250, 200); public static Vector2 FireWizard_Advanced_Scale = new Vector2(2.2f, 2.2f); public static Vector2 FireWizard_Advanced_ProjectileScale = new Vector2(1.1f, 1.1f); public static Color FireWizard_Advanced_Tint = new Color(255, 140, 20); public const int FireWizard_Advanced_MeleeRadius = 225; public const int FireWizard_Advanced_ProjectileRadius = 700; public const int FireWizard_Advanced_EngageRadius = 900; + public const string FireWizard_Expert_Name = "Sollock"; public const int FireWizard_Expert_MaxHealth = 72; public const int FireWizard_Expert_Damage = 35; public const int FireWizard_Expert_XPValue = 400; public const int FireWizard_Expert_Speed = 270; public const int FireWizard_Expert_Jump = 300; public const float FireWizard_Expert_Cooldown = 2f; public const int FireWizard_Expert_MinDropAmount = 2; public const int FireWizard_Expert_MaxDropAmount = 3; public const float FireWizard_Expert_DropChance = 1f; public const float FireWizard_Expert_TurnSpeed = 0.04f; public const float FireWizard_Expert_ProjectileSpeed = 300f; public const float FireWizard_Expert_AnimationDelay = 10f; public const bool FireWizard_Expert_AlwaysFaceTarget = true; public const bool FireWizard_Expert_CanFallOffLedges = true; public const bool FireWizard_Expert_CanBeKnockedBack = true; public const bool FireWizard_Expert_IsWeighted = false; public static Vector2 FireWizard_Expert_KnockBack = new Vector2(250, 200); public static Vector2 FireWizard_Expert_Scale = new Vector2(2.6f, 2.6f); public static Vector2 FireWizard_Expert_ProjectileScale = new Vector2(4.75f, 4.75f); public static Color FireWizard_Expert_Tint = new Color(255, 245, 20); public const int FireWizard_Expert_MeleeRadius = 225; public const int FireWizard_Expert_ProjectileRadius = 700; public const int FireWizard_Expert_EngageRadius = 900; + public const string FireWizard_Miniboss_Name = "Sol Mage"; public const int FireWizard_Miniboss_MaxHealth = 240; public const int FireWizard_Miniboss_Damage = 40; public const int FireWizard_Miniboss_XPValue = 1000; public const int FireWizard_Miniboss_Speed = 270; public const int FireWizard_Miniboss_Jump = 300; public const float FireWizard_Miniboss_Cooldown = 1.25f; public const int FireWizard_Miniboss_MinDropAmount = 18; public const int FireWizard_Miniboss_MaxDropAmount = 25; public const float FireWizard_Miniboss_DropChance = 1f; public const float FireWizard_Miniboss_TurnSpeed = 0.04f; public const float FireWizard_Miniboss_ProjectileSpeed = 650f; public const float FireWizard_Miniboss_AnimationDelay = 10f; public const bool FireWizard_Miniboss_AlwaysFaceTarget = true; public const bool FireWizard_Miniboss_CanFallOffLedges = true; public const bool FireWizard_Miniboss_CanBeKnockedBack = true; public const bool FireWizard_Miniboss_IsWeighted = false; public static Vector2 FireWizard_Miniboss_KnockBack = new Vector2(300, 250); public static Vector2 FireWizard_Miniboss_Scale = new Vector2(3.0f, 3.0f); public static Vector2 FireWizard_Miniboss_ProjectileScale = new Vector2(1f, 1f); public static Color FireWizard_Miniboss_Tint = new Color(150, 10, 0); public const int FireWizard_Miniboss_MeleeRadius = 225; public const int FireWizard_Miniboss_ProjectileRadius = 700; public const int FireWizard_Miniboss_EngageRadius = 900; + public const string IceWizard_Basic_Name = "Frosten"; public const int IceWizard_Basic_MaxHealth = 32; public const int IceWizard_Basic_Damage = 20; public const int IceWizard_Basic_XPValue = 175; public const int IceWizard_Basic_Speed = 270; public const int IceWizard_Basic_Jump = 300; public const float IceWizard_Basic_Cooldown = 1.25f; public const int IceWizard_Basic_MinDropAmount = 1; public const int IceWizard_Basic_MaxDropAmount = 2; public const float IceWizard_Basic_DropChance = 0.4f; public const float IceWizard_Basic_TurnSpeed = 0.04f; public const float IceWizard_Basic_ProjectileSpeed = 500f; public const float IceWizard_Basic_AnimationDelay = 10f; public const bool IceWizard_Basic_AlwaysFaceTarget = true; public const bool IceWizard_Basic_CanFallOffLedges = true; public const bool IceWizard_Basic_CanBeKnockedBack = true; public const bool IceWizard_Basic_IsWeighted = false; public static Vector2 IceWizard_Basic_KnockBack = new Vector2(250, 200); public static Vector2 IceWizard_Basic_Scale = new Vector2(1.8f, 1.8f); public static Vector2 IceWizard_Basic_ProjectileScale = new Vector2(1.0f, 1.0f); public static Color IceWizard_Basic_Tint = new Color(110, 215, 255); public const int IceWizard_Basic_MeleeRadius = 225; public const int IceWizard_Basic_ProjectileRadius = 700; public const int IceWizard_Basic_EngageRadius = 900; + public const string IceWizard_Advanced_Name = "Icen"; public const int IceWizard_Advanced_MaxHealth = 45; public const int IceWizard_Advanced_Damage = 28; public const int IceWizard_Advanced_XPValue = 200; public const int IceWizard_Advanced_Speed = 270; public const int IceWizard_Advanced_Jump = 300; public const float IceWizard_Advanced_Cooldown = 1.25f; public const int IceWizard_Advanced_MinDropAmount = 1; public const int IceWizard_Advanced_MaxDropAmount = 2; public const float IceWizard_Advanced_DropChance = 0.5f; public const float IceWizard_Advanced_TurnSpeed = 0.04f; public const float IceWizard_Advanced_ProjectileSpeed = 500f; public const float IceWizard_Advanced_AnimationDelay = 10f; public const bool IceWizard_Advanced_AlwaysFaceTarget = true; public const bool IceWizard_Advanced_CanFallOffLedges = true; public const bool IceWizard_Advanced_CanBeKnockedBack = true; public const bool IceWizard_Advanced_IsWeighted = false; public static Vector2 IceWizard_Advanced_KnockBack = new Vector2(250, 200); public static Vector2 IceWizard_Advanced_Scale = new Vector2(2.2f, 2.2f); public static Vector2 IceWizard_Advanced_ProjectileScale = new Vector2(1.1f, 1.1f); public static Color IceWizard_Advanced_Tint = new Color(60, 90, 150); public const int IceWizard_Advanced_MeleeRadius = 225; public const int IceWizard_Advanced_ProjectileRadius = 700; public const int IceWizard_Advanced_EngageRadius = 900; + public const string IceWizard_Expert_Name = "Glacien"; public const int IceWizard_Expert_MaxHealth = 72; public const int IceWizard_Expert_Damage = 32; public const int IceWizard_Expert_XPValue = 400; public const int IceWizard_Expert_Speed = 300; public const int IceWizard_Expert_Jump = 300; public const float IceWizard_Expert_Cooldown = 2f; public const int IceWizard_Expert_MinDropAmount = 2; public const int IceWizard_Expert_MaxDropAmount = 3; public const float IceWizard_Expert_DropChance = 1f; public const float IceWizard_Expert_TurnSpeed = 0.04f; public const float IceWizard_Expert_ProjectileSpeed = 600f; public const float IceWizard_Expert_AnimationDelay = 10f; public const bool IceWizard_Expert_AlwaysFaceTarget = true; public const bool IceWizard_Expert_CanFallOffLedges = true; public const bool IceWizard_Expert_CanBeKnockedBack = true; public const bool IceWizard_Expert_IsWeighted = false; public static Vector2 IceWizard_Expert_KnockBack = new Vector2(250, 200); public static Vector2 IceWizard_Expert_Scale = new Vector2(2.6f, 2.6f); public static Vector2 IceWizard_Expert_ProjectileScale = new Vector2(1.1f, 1.1f); public static Color IceWizard_Expert_Tint = new Color(190, 50, 205); public const int IceWizard_Expert_MeleeRadius = 225; public const int IceWizard_Expert_ProjectileRadius = 700; public const int IceWizard_Expert_EngageRadius = 900; + public const string IceWizard_Miniboss_Name = "Luna Mage"; public const int IceWizard_Miniboss_MaxHealth = 240; public const int IceWizard_Miniboss_Damage = 40; public const int IceWizard_Miniboss_XPValue = 1000; public const int IceWizard_Miniboss_Speed = 375; public const int IceWizard_Miniboss_Jump = 300; public const float IceWizard_Miniboss_Cooldown = 1.25f; public const int IceWizard_Miniboss_MinDropAmount = 18; public const int IceWizard_Miniboss_MaxDropAmount = 25; public const float IceWizard_Miniboss_DropChance = 1f; public const float IceWizard_Miniboss_TurnSpeed = 0.04f; public const float IceWizard_Miniboss_ProjectileSpeed = 500f; public const float IceWizard_Miniboss_AnimationDelay = 10f; public const bool IceWizard_Miniboss_AlwaysFaceTarget = true; public const bool IceWizard_Miniboss_CanFallOffLedges = true; public const bool IceWizard_Miniboss_CanBeKnockedBack = true; public const bool IceWizard_Miniboss_IsWeighted = false; public static Vector2 IceWizard_Miniboss_KnockBack = new Vector2(300, 250); public static Vector2 IceWizard_Miniboss_Scale = new Vector2(3.0f, 3.0f); public static Vector2 IceWizard_Miniboss_ProjectileScale = new Vector2(1.2f, 1.2f); public static Color IceWizard_Miniboss_Tint = new Color(40, 30, 255); public const int IceWizard_Miniboss_MeleeRadius = 225; public const int IceWizard_Miniboss_ProjectileRadius = 700; public const int IceWizard_Miniboss_EngageRadius = 900; + public const string Eyeball_Basic_Name = "Scout"; public const int Eyeball_Basic_MaxHealth = 12; public const int Eyeball_Basic_Damage = 15; public const int Eyeball_Basic_XPValue = 50; public const int Eyeball_Basic_Speed = 435; public const int Eyeball_Basic_Jump = 950; public const float Eyeball_Basic_Cooldown = 0f; public const int Eyeball_Basic_MinDropAmount = 1; public const int Eyeball_Basic_MaxDropAmount = 1; public const float Eyeball_Basic_DropChance = 0.4f; public const float Eyeball_Basic_TurnSpeed = 10f; public const float Eyeball_Basic_ProjectileSpeed = 435f; public const float Eyeball_Basic_AnimationDelay = 20f; public const bool Eyeball_Basic_AlwaysFaceTarget = false; public const bool Eyeball_Basic_CanFallOffLedges = false; public const bool Eyeball_Basic_CanBeKnockedBack = false; public const bool Eyeball_Basic_IsWeighted = false; public static Vector2 Eyeball_Basic_KnockBack = new Vector2(0, 0); public static Vector2 Eyeball_Basic_Scale = new Vector2(2.4f, 2.4f); public static Vector2 Eyeball_Basic_ProjectileScale = new Vector2(1f, 1f); public static Color Eyeball_Basic_Tint = new Color(255, 255, 255); public const int Eyeball_Basic_MeleeRadius = 325; public const int Eyeball_Basic_ProjectileRadius = 690; public const int Eyeball_Basic_EngageRadius = 850; + public const string Eyeball_Advanced_Name = "Pupil"; public const int Eyeball_Advanced_MaxHealth = 25; public const int Eyeball_Advanced_Damage = 18; public const int Eyeball_Advanced_XPValue = 75; public const int Eyeball_Advanced_Speed = 435; public const int Eyeball_Advanced_Jump = 950; public const float Eyeball_Advanced_Cooldown = 0f; public const int Eyeball_Advanced_MinDropAmount = 1; public const int Eyeball_Advanced_MaxDropAmount = 2; public const float Eyeball_Advanced_DropChance = 0.5f; public const float Eyeball_Advanced_TurnSpeed = 10f; public const float Eyeball_Advanced_ProjectileSpeed = 435f; public const float Eyeball_Advanced_AnimationDelay = 20f; public const bool Eyeball_Advanced_AlwaysFaceTarget = false; public const bool Eyeball_Advanced_CanFallOffLedges = false; public const bool Eyeball_Advanced_CanBeKnockedBack = false; public const bool Eyeball_Advanced_IsWeighted = false; public static Vector2 Eyeball_Advanced_KnockBack = new Vector2(0, 0); public static Vector2 Eyeball_Advanced_Scale = new Vector2(2.7f, 2.7f); public static Vector2 Eyeball_Advanced_ProjectileScale = new Vector2(1.2f, 1.2f); public static Color Eyeball_Advanced_Tint = new Color(190, 95, 95); public const int Eyeball_Advanced_MeleeRadius = 325; public const int Eyeball_Advanced_ProjectileRadius = 690; public const int Eyeball_Advanced_EngageRadius = 850; + public const string Eyeball_Expert_Name = "Visionary"; public const int Eyeball_Expert_MaxHealth = 57; public const int Eyeball_Expert_Damage = 21; public const int Eyeball_Expert_XPValue = 125; public const int Eyeball_Expert_Speed = 435; public const int Eyeball_Expert_Jump = 950; public const float Eyeball_Expert_Cooldown = 0f; public const int Eyeball_Expert_MinDropAmount = 1; public const int Eyeball_Expert_MaxDropAmount = 3; public const float Eyeball_Expert_DropChance = 1f; public const float Eyeball_Expert_TurnSpeed = 10f; public const float Eyeball_Expert_ProjectileSpeed = 435f; public const float Eyeball_Expert_AnimationDelay = 20f; public const bool Eyeball_Expert_AlwaysFaceTarget = false; public const bool Eyeball_Expert_CanFallOffLedges = false; public const bool Eyeball_Expert_CanBeKnockedBack = false; public const bool Eyeball_Expert_IsWeighted = false; public static Vector2 Eyeball_Expert_KnockBack = new Vector2(0, 0); public static Vector2 Eyeball_Expert_Scale = new Vector2(3.5f, 3.5f); public static Vector2 Eyeball_Expert_ProjectileScale = new Vector2(1.3f, 1.3f); public static Color Eyeball_Expert_Tint = new Color(80, 200, 205); public const int Eyeball_Expert_MeleeRadius = 325; public const int Eyeball_Expert_ProjectileRadius = 690; public const int Eyeball_Expert_EngageRadius = 850; + public const string Eyeball_Miniboss_Name = "Khidr"; public const int Eyeball_Miniboss_MaxHealth = 580; public const int Eyeball_Miniboss_Damage = 23; public const int Eyeball_Miniboss_XPValue = 1100; public const int Eyeball_Miniboss_Speed = 435; public const int Eyeball_Miniboss_Jump = 1350; public const float Eyeball_Miniboss_Cooldown = 1.9f; public const int Eyeball_Miniboss_MinDropAmount = 15; public const int Eyeball_Miniboss_MaxDropAmount = 20; public const float Eyeball_Miniboss_DropChance = 1f; public const float Eyeball_Miniboss_TurnSpeed = 10f; public const float Eyeball_Miniboss_ProjectileSpeed = 370f; public const float Eyeball_Miniboss_AnimationDelay = 20f; public const bool Eyeball_Miniboss_AlwaysFaceTarget = false; public const bool Eyeball_Miniboss_CanFallOffLedges = false; public const bool Eyeball_Miniboss_CanBeKnockedBack = false; public const bool Eyeball_Miniboss_IsWeighted = false; public static Vector2 Eyeball_Miniboss_KnockBack = new Vector2(0, 0); public static Vector2 Eyeball_Miniboss_Scale = new Vector2(3.3f, 3.3f); public static Vector2 Eyeball_Miniboss_ProjectileScale = new Vector2(2.4f, 2.4f); public static Color Eyeball_Miniboss_Tint = new Color(255, 255, 255); public const int Eyeball_Miniboss_MeleeRadius = 325; public const int Eyeball_Miniboss_ProjectileRadius = 690; public const int Eyeball_Miniboss_EngageRadius = 850; + public const string Fairy_Basic_Name = "Fury"; public const int Fairy_Basic_MaxHealth = 27; public const int Fairy_Basic_Damage = 18; public const int Fairy_Basic_XPValue = 125; public const int Fairy_Basic_Speed = 250; public const int Fairy_Basic_Jump = 300; public const float Fairy_Basic_Cooldown = 1.75f; public const int Fairy_Basic_MinDropAmount = 1; public const int Fairy_Basic_MaxDropAmount = 2; public const float Fairy_Basic_DropChance = 0.4f; public const float Fairy_Basic_TurnSpeed = 0.0325f; public const float Fairy_Basic_ProjectileSpeed = 475f; public const float Fairy_Basic_AnimationDelay = 10f; public const bool Fairy_Basic_AlwaysFaceTarget = true; public const bool Fairy_Basic_CanFallOffLedges = true; public const bool Fairy_Basic_CanBeKnockedBack = true; public const bool Fairy_Basic_IsWeighted = false; public static Vector2 Fairy_Basic_KnockBack = new Vector2(300, 250); public static Vector2 Fairy_Basic_Scale = new Vector2(2.8f, 2.8f); public static Vector2 Fairy_Basic_ProjectileScale = new Vector2(1.5f, 1.5f); public static Color Fairy_Basic_Tint = new Color(255, 255, 255); public const int Fairy_Basic_MeleeRadius = 225; public const int Fairy_Basic_ProjectileRadius = 700; public const int Fairy_Basic_EngageRadius = 925; + public const string Fairy_Advanced_Name = "Rage"; public const int Fairy_Advanced_MaxHealth = 37; public const int Fairy_Advanced_Damage = 22; public const int Fairy_Advanced_XPValue = 200; public const int Fairy_Advanced_Speed = 265; public const int Fairy_Advanced_Jump = 300; public const float Fairy_Advanced_Cooldown = 1.75f; public const int Fairy_Advanced_MinDropAmount = 1; public const int Fairy_Advanced_MaxDropAmount = 2; public const float Fairy_Advanced_DropChance = 0.5f; public const float Fairy_Advanced_TurnSpeed = 0.0325f; public const float Fairy_Advanced_ProjectileSpeed = 475f; public const float Fairy_Advanced_AnimationDelay = 10f; public const bool Fairy_Advanced_AlwaysFaceTarget = true; public const bool Fairy_Advanced_CanFallOffLedges = true; public const bool Fairy_Advanced_CanBeKnockedBack = true; public const bool Fairy_Advanced_IsWeighted = false; public static Vector2 Fairy_Advanced_KnockBack = new Vector2(300, 250); public static Vector2 Fairy_Advanced_Scale = new Vector2(3.7f, 3.7f); public static Vector2 Fairy_Advanced_ProjectileScale = new Vector2(2.0f, 2.0f); public static Color Fairy_Advanced_Tint = new Color(240, 240, 50); public const int Fairy_Advanced_MeleeRadius = 225; public const int Fairy_Advanced_ProjectileRadius = 700; public const int Fairy_Advanced_EngageRadius = 925; + public const string Fairy_Expert_Name = "Wrath"; public const int Fairy_Expert_MaxHealth = 72; public const int Fairy_Expert_Damage = 24; public const int Fairy_Expert_XPValue = 350; public const int Fairy_Expert_Speed = 280; public const int Fairy_Expert_Jump = 300; public const float Fairy_Expert_Cooldown = 2.5f; public const int Fairy_Expert_MinDropAmount = 2; public const int Fairy_Expert_MaxDropAmount = 4; public const float Fairy_Expert_DropChance = 1f; public const float Fairy_Expert_TurnSpeed = 0.0325f; public const float Fairy_Expert_ProjectileSpeed = 475f; public const float Fairy_Expert_AnimationDelay = 10f; public const bool Fairy_Expert_AlwaysFaceTarget = true; public const bool Fairy_Expert_CanFallOffLedges = true; public const bool Fairy_Expert_CanBeKnockedBack = true; public const bool Fairy_Expert_IsWeighted = false; public static Vector2 Fairy_Expert_KnockBack = new Vector2(175, 175); public static Vector2 Fairy_Expert_Scale = new Vector2(4.5f, 4.5f); public static Vector2 Fairy_Expert_ProjectileScale = new Vector2(2.5f, 2.5f); public static Color Fairy_Expert_Tint = new Color(25, 25, 25); public const int Fairy_Expert_MeleeRadius = 225; public const int Fairy_Expert_ProjectileRadius = 700; public const int Fairy_Expert_EngageRadius = 925; + public const string Fairy_Miniboss_Name = "Alexander"; public const int Fairy_Miniboss_MaxHealth = 635; public const int Fairy_Miniboss_Damage = 30; public const int Fairy_Miniboss_XPValue = 1000; public const int Fairy_Miniboss_Speed = 220; public const int Fairy_Miniboss_Jump = 300; public const float Fairy_Miniboss_Cooldown = 3f; public const int Fairy_Miniboss_MinDropAmount = 15; public const int Fairy_Miniboss_MaxDropAmount = 20; public const float Fairy_Miniboss_DropChance = 1f; public const float Fairy_Miniboss_TurnSpeed = 0.0325f; public const float Fairy_Miniboss_ProjectileSpeed = 545f; public const float Fairy_Miniboss_AnimationDelay = 10f; public const bool Fairy_Miniboss_AlwaysFaceTarget = true; public const bool Fairy_Miniboss_CanFallOffLedges = true; public const bool Fairy_Miniboss_CanBeKnockedBack = false; public const bool Fairy_Miniboss_IsWeighted = false; public static Vector2 Fairy_Miniboss_KnockBack = new Vector2(125, 125); public static Vector2 Fairy_Miniboss_Scale = new Vector2(7.0f, 7.0f); public static Vector2 Fairy_Miniboss_ProjectileScale = new Vector2(6.75f, 6.75f); public static Color Fairy_Miniboss_Tint = new Color(245, 155, 30); public const int Fairy_Miniboss_MeleeRadius = 225; public const int Fairy_Miniboss_ProjectileRadius = 775; public const int Fairy_Miniboss_EngageRadius = 925; + public const string ShieldKnight_Basic_Name = "Tall Guard"; public const int ShieldKnight_Basic_MaxHealth = 40; public const int ShieldKnight_Basic_Damage = 31; public const int ShieldKnight_Basic_XPValue = 150; public const int ShieldKnight_Basic_Speed = 100; public const int ShieldKnight_Basic_Jump = 950; public const float ShieldKnight_Basic_Cooldown = 2.25f; public const int ShieldKnight_Basic_MinDropAmount = 1; public const int ShieldKnight_Basic_MaxDropAmount = 2; public const float ShieldKnight_Basic_DropChance = 0.4f; public const float ShieldKnight_Basic_TurnSpeed = 0.0175f; public const float ShieldKnight_Basic_ProjectileSpeed = 650f; public const float ShieldKnight_Basic_AnimationDelay = 7f; public const bool ShieldKnight_Basic_AlwaysFaceTarget = true; public const bool ShieldKnight_Basic_CanFallOffLedges = false; public const bool ShieldKnight_Basic_CanBeKnockedBack = true; public const bool ShieldKnight_Basic_IsWeighted = true; public static Vector2 ShieldKnight_Basic_KnockBack = new Vector2(125, 125); public static Vector2 ShieldKnight_Basic_Scale = new Vector2(1.6f, 1.6f); public static Vector2 ShieldKnight_Basic_ProjectileScale = new Vector2(0.8f, 0.8f); public static Color ShieldKnight_Basic_Tint = new Color(180, 165, 115); public const int ShieldKnight_Basic_MeleeRadius = 50; public const int ShieldKnight_Basic_ProjectileRadius = 550; public const int ShieldKnight_Basic_EngageRadius = 700; + public const string ShieldKnight_Advanced_Name = "Hulk Guard"; public const int ShieldKnight_Advanced_MaxHealth = 58; public const int ShieldKnight_Advanced_Damage = 38; public const int ShieldKnight_Advanced_XPValue = 250; public const int ShieldKnight_Advanced_Speed = 175; public const int ShieldKnight_Advanced_Jump = 950; public const float ShieldKnight_Advanced_Cooldown = 2.25f; public const int ShieldKnight_Advanced_MinDropAmount = 1; public const int ShieldKnight_Advanced_MaxDropAmount = 2; public const float ShieldKnight_Advanced_DropChance = 0.5f; public const float ShieldKnight_Advanced_TurnSpeed = 0.0175f; public const float ShieldKnight_Advanced_ProjectileSpeed = 650f; public const float ShieldKnight_Advanced_AnimationDelay = 7f; public const bool ShieldKnight_Advanced_AlwaysFaceTarget = true; public const bool ShieldKnight_Advanced_CanFallOffLedges = false; public const bool ShieldKnight_Advanced_CanBeKnockedBack = true; public const bool ShieldKnight_Advanced_IsWeighted = true; public static Vector2 ShieldKnight_Advanced_KnockBack = new Vector2(125, 125); public static Vector2 ShieldKnight_Advanced_Scale = new Vector2(2.0f, 2.0f); public static Vector2 ShieldKnight_Advanced_ProjectileScale = new Vector2(0.8f, 0.8f); public static Color ShieldKnight_Advanced_Tint = new Color(35, 140, 75); public const int ShieldKnight_Advanced_MeleeRadius = 50; public const int ShieldKnight_Advanced_ProjectileRadius = 550; public const int ShieldKnight_Advanced_EngageRadius = 700; + public const string ShieldKnight_Expert_Name = "Tower Guard"; public const int ShieldKnight_Expert_MaxHealth = 79; public const int ShieldKnight_Expert_Damage = 43; public const int ShieldKnight_Expert_XPValue = 450; public const int ShieldKnight_Expert_Speed = 250; public const int ShieldKnight_Expert_Jump = 950; public const float ShieldKnight_Expert_Cooldown = 2.25f; public const int ShieldKnight_Expert_MinDropAmount = 2; public const int ShieldKnight_Expert_MaxDropAmount = 4; public const float ShieldKnight_Expert_DropChance = 1f; public const float ShieldKnight_Expert_TurnSpeed = 0.0175f; public const float ShieldKnight_Expert_ProjectileSpeed = 650f; public const float ShieldKnight_Expert_AnimationDelay = 11f; public const bool ShieldKnight_Expert_AlwaysFaceTarget = true; public const bool ShieldKnight_Expert_CanFallOffLedges = false; public const bool ShieldKnight_Expert_CanBeKnockedBack = true; public const bool ShieldKnight_Expert_IsWeighted = true; public static Vector2 ShieldKnight_Expert_KnockBack = new Vector2(125, 125); public static Vector2 ShieldKnight_Expert_Scale = new Vector2(2.4f, 2.4f); public static Vector2 ShieldKnight_Expert_ProjectileScale = new Vector2(0.8f, 0.8f); public static Color ShieldKnight_Expert_Tint = new Color(125, 125, 125); public const int ShieldKnight_Expert_MeleeRadius = 50; public const int ShieldKnight_Expert_ProjectileRadius = 550; public const int ShieldKnight_Expert_EngageRadius = 700; + public const string ShieldKnight_Miniboss_Name = "Sentinel"; public const int ShieldKnight_Miniboss_MaxHealth = 1; public const int ShieldKnight_Miniboss_Damage = 1; public const int ShieldKnight_Miniboss_XPValue = 1250; public const int ShieldKnight_Miniboss_Speed = 250; public const int ShieldKnight_Miniboss_Jump = 950; public const float ShieldKnight_Miniboss_Cooldown = 0f; public const int ShieldKnight_Miniboss_MinDropAmount = 1; public const int ShieldKnight_Miniboss_MaxDropAmount = 4; public const float ShieldKnight_Miniboss_DropChance = 1f; public const float ShieldKnight_Miniboss_TurnSpeed = 0.0175f; public const float ShieldKnight_Miniboss_ProjectileSpeed = 650f; public const float ShieldKnight_Miniboss_AnimationDelay = 7f; public const bool ShieldKnight_Miniboss_AlwaysFaceTarget = true; public const bool ShieldKnight_Miniboss_CanFallOffLedges = false; public const bool ShieldKnight_Miniboss_CanBeKnockedBack = true; public const bool ShieldKnight_Miniboss_IsWeighted = true; public static Vector2 ShieldKnight_Miniboss_KnockBack = new Vector2(125, 125); public static Vector2 ShieldKnight_Miniboss_Scale = new Vector2(1.6f, 1.6f); public static Vector2 ShieldKnight_Miniboss_ProjectileScale = new Vector2(0.8f, 0.8f); public static Color ShieldKnight_Miniboss_Tint = new Color(100, 100, 100); public const int ShieldKnight_Miniboss_MeleeRadius = 50; public const int ShieldKnight_Miniboss_ProjectileRadius = 550; public const int ShieldKnight_Miniboss_EngageRadius = 700; + public const string BouncySpike_Basic_Name = "Spiketor"; public const int BouncySpike_Basic_MaxHealth = 5; public const int BouncySpike_Basic_Damage = 27; public const int BouncySpike_Basic_XPValue = 25; public const int BouncySpike_Basic_Speed = 300; public const int BouncySpike_Basic_Jump = 300; public const float BouncySpike_Basic_Cooldown = 2f; public const int BouncySpike_Basic_MinDropAmount = 1; public const int BouncySpike_Basic_MaxDropAmount = 1; public const float BouncySpike_Basic_DropChance = 0.4f; public const float BouncySpike_Basic_TurnSpeed = 10f; public const float BouncySpike_Basic_ProjectileSpeed = 650f; public const float BouncySpike_Basic_AnimationDelay = 10f; public const bool BouncySpike_Basic_AlwaysFaceTarget = true; public const bool BouncySpike_Basic_CanFallOffLedges = false; public const bool BouncySpike_Basic_CanBeKnockedBack = false; public const bool BouncySpike_Basic_IsWeighted = false; public static Vector2 BouncySpike_Basic_KnockBack = new Vector2(0, 0); public static Vector2 BouncySpike_Basic_Scale = new Vector2(2.0f, 2.0f); public static Vector2 BouncySpike_Basic_ProjectileScale = new Vector2(1.0f, 1.0f); public static Color BouncySpike_Basic_Tint = new Color(255, 255, 255); public const int BouncySpike_Basic_MeleeRadius = 50; public const int BouncySpike_Basic_ProjectileRadius = 100; public const int BouncySpike_Basic_EngageRadius = 150; + public const string BouncySpike_Advanced_Name = "Spiketex"; public const int BouncySpike_Advanced_MaxHealth = 5; public const int BouncySpike_Advanced_Damage = 32; public const int BouncySpike_Advanced_XPValue = 25; public const int BouncySpike_Advanced_Speed = 300; public const int BouncySpike_Advanced_Jump = 300; public const float BouncySpike_Advanced_Cooldown = 2f; public const int BouncySpike_Advanced_MinDropAmount = 1; public const int BouncySpike_Advanced_MaxDropAmount = 1; public const float BouncySpike_Advanced_DropChance = 0.5f; public const float BouncySpike_Advanced_TurnSpeed = 10f; public const float BouncySpike_Advanced_ProjectileSpeed = 650f; public const float BouncySpike_Advanced_AnimationDelay = 10f; public const bool BouncySpike_Advanced_AlwaysFaceTarget = true; public const bool BouncySpike_Advanced_CanFallOffLedges = false; public const bool BouncySpike_Advanced_CanBeKnockedBack = false; public const bool BouncySpike_Advanced_IsWeighted = false; public static Vector2 BouncySpike_Advanced_KnockBack = new Vector2(0, 0); public static Vector2 BouncySpike_Advanced_Scale = new Vector2(2.3f, 2.3f); public static Vector2 BouncySpike_Advanced_ProjectileScale = new Vector2(1.0f, 1.0f); public static Color BouncySpike_Advanced_Tint = new Color(255, 255, 255); public const int BouncySpike_Advanced_MeleeRadius = 50; public const int BouncySpike_Advanced_ProjectileRadius = 100; public const int BouncySpike_Advanced_EngageRadius = 150; + public const string BouncySpike_Expert_Name = "Spiketus"; public const int BouncySpike_Expert_MaxHealth = 5; public const int BouncySpike_Expert_Damage = 38; public const int BouncySpike_Expert_XPValue = 25; public const int BouncySpike_Expert_Speed = 300; public const int BouncySpike_Expert_Jump = 300; public const float BouncySpike_Expert_Cooldown = 2f; public const int BouncySpike_Expert_MinDropAmount = 1; public const int BouncySpike_Expert_MaxDropAmount = 1; public const float BouncySpike_Expert_DropChance = 1f; public const float BouncySpike_Expert_TurnSpeed = 10f; public const float BouncySpike_Expert_ProjectileSpeed = 650f; public const float BouncySpike_Expert_AnimationDelay = 10f; public const bool BouncySpike_Expert_AlwaysFaceTarget = true; public const bool BouncySpike_Expert_CanFallOffLedges = false; public const bool BouncySpike_Expert_CanBeKnockedBack = false; public const bool BouncySpike_Expert_IsWeighted = false; public static Vector2 BouncySpike_Expert_KnockBack = new Vector2(0, 0); public static Vector2 BouncySpike_Expert_Scale = new Vector2(2.6f, 2.6f); public static Vector2 BouncySpike_Expert_ProjectileScale = new Vector2(1.0f, 1.0f); public static Color BouncySpike_Expert_Tint = new Color(255, 255, 255); public const int BouncySpike_Expert_MeleeRadius = 50; public const int BouncySpike_Expert_ProjectileRadius = 100; public const int BouncySpike_Expert_EngageRadius = 150; + public const string BouncySpike_Miniboss_Name = "Spiker"; public const int BouncySpike_Miniboss_MaxHealth = 5; public const int BouncySpike_Miniboss_Damage = 40; public const int BouncySpike_Miniboss_XPValue = 25; public const int BouncySpike_Miniboss_Speed = 300; public const int BouncySpike_Miniboss_Jump = 300; public const float BouncySpike_Miniboss_Cooldown = 2f; public const int BouncySpike_Miniboss_MinDropAmount = 1; public const int BouncySpike_Miniboss_MaxDropAmount = 1; public const float BouncySpike_Miniboss_DropChance = 1f; public const float BouncySpike_Miniboss_TurnSpeed = 10f; public const float BouncySpike_Miniboss_ProjectileSpeed = 650f; public const float BouncySpike_Miniboss_AnimationDelay = 10f; public const bool BouncySpike_Miniboss_AlwaysFaceTarget = true; public const bool BouncySpike_Miniboss_CanFallOffLedges = false; public const bool BouncySpike_Miniboss_CanBeKnockedBack = false; public const bool BouncySpike_Miniboss_IsWeighted = false; public static Vector2 BouncySpike_Miniboss_KnockBack = new Vector2(0, 0); public static Vector2 BouncySpike_Miniboss_Scale = new Vector2(3.0f, 3.0f); public static Vector2 BouncySpike_Miniboss_ProjectileScale = new Vector2(1.0f, 1.0f); public static Color BouncySpike_Miniboss_Tint = new Color(255, 255, 255); public const int BouncySpike_Miniboss_MeleeRadius = 50; public const int BouncySpike_Miniboss_ProjectileRadius = 100; public const int BouncySpike_Miniboss_EngageRadius = 150; + public const string SwordKnight_Basic_Name = "Gray Knight"; public const int SwordKnight_Basic_MaxHealth = 40; public const int SwordKnight_Basic_Damage = 36; public const int SwordKnight_Basic_XPValue = 100; public const int SwordKnight_Basic_Speed = 75; public const int SwordKnight_Basic_Jump = 950; public const float SwordKnight_Basic_Cooldown = 0.5f; public const int SwordKnight_Basic_MinDropAmount = 1; public const int SwordKnight_Basic_MaxDropAmount = 2; public const float SwordKnight_Basic_DropChance = 0.4f; public const float SwordKnight_Basic_TurnSpeed = 10f; public const float SwordKnight_Basic_ProjectileSpeed = 850f; public const float SwordKnight_Basic_AnimationDelay = 12f; public const bool SwordKnight_Basic_AlwaysFaceTarget = true; public const bool SwordKnight_Basic_CanFallOffLedges = false; public const bool SwordKnight_Basic_CanBeKnockedBack = true; public const bool SwordKnight_Basic_IsWeighted = true; public static Vector2 SwordKnight_Basic_KnockBack = new Vector2(125, 125); public static Vector2 SwordKnight_Basic_Scale = new Vector2(2.0f, 2.0f); public static Vector2 SwordKnight_Basic_ProjectileScale = new Vector2(1.25f, 1.25f); public static Color SwordKnight_Basic_Tint = new Color(255, 255, 255); public const int SwordKnight_Basic_MeleeRadius = 210; public const int SwordKnight_Basic_ProjectileRadius = 500; public const int SwordKnight_Basic_EngageRadius = 800; + public const string SwordKnight_Advanced_Name = "Gray Baron"; public const int SwordKnight_Advanced_MaxHealth = 58; public const int SwordKnight_Advanced_Damage = 51; public const int SwordKnight_Advanced_XPValue = 175; public const int SwordKnight_Advanced_Speed = 75; public const int SwordKnight_Advanced_Jump = 950; public const float SwordKnight_Advanced_Cooldown = 1.25f; public const int SwordKnight_Advanced_MinDropAmount = 1; public const int SwordKnight_Advanced_MaxDropAmount = 2; public const float SwordKnight_Advanced_DropChance = 0.5f; public const float SwordKnight_Advanced_TurnSpeed = 10f; public const float SwordKnight_Advanced_ProjectileSpeed = 850f; public const float SwordKnight_Advanced_AnimationDelay = 12f; public const bool SwordKnight_Advanced_AlwaysFaceTarget = true; public const bool SwordKnight_Advanced_CanFallOffLedges = false; public const bool SwordKnight_Advanced_CanBeKnockedBack = true; public const bool SwordKnight_Advanced_IsWeighted = true; public static Vector2 SwordKnight_Advanced_KnockBack = new Vector2(125, 125); public static Vector2 SwordKnight_Advanced_Scale = new Vector2(2.4f, 2.4f); public static Vector2 SwordKnight_Advanced_ProjectileScale = new Vector2(1.35f, 1.35f); public static Color SwordKnight_Advanced_Tint = new Color(125, 150, 175); public const int SwordKnight_Advanced_MeleeRadius = 300; public const int SwordKnight_Advanced_ProjectileRadius = 500; public const int SwordKnight_Advanced_EngageRadius = 800; + public const string SwordKnight_Expert_Name = "Graydiator"; public const int SwordKnight_Expert_MaxHealth = 72; public const int SwordKnight_Expert_Damage = 57; public const int SwordKnight_Expert_XPValue = 350; public const int SwordKnight_Expert_Speed = 85; public const int SwordKnight_Expert_Jump = 950; public const float SwordKnight_Expert_Cooldown = 1.25f; public const int SwordKnight_Expert_MinDropAmount = 2; public const int SwordKnight_Expert_MaxDropAmount = 4; public const float SwordKnight_Expert_DropChance = 1f; public const float SwordKnight_Expert_TurnSpeed = 10f; public const float SwordKnight_Expert_ProjectileSpeed = 1350f; public const float SwordKnight_Expert_AnimationDelay = 12f; public const bool SwordKnight_Expert_AlwaysFaceTarget = true; public const bool SwordKnight_Expert_CanFallOffLedges = false; public const bool SwordKnight_Expert_CanBeKnockedBack = true; public const bool SwordKnight_Expert_IsWeighted = true; public static Vector2 SwordKnight_Expert_KnockBack = new Vector2(125, 125); public static Vector2 SwordKnight_Expert_Scale = new Vector2(3.0f, 3.0f); public static Vector2 SwordKnight_Expert_ProjectileScale = new Vector2(1.5f, 1.5f); public static Color SwordKnight_Expert_Tint = new Color(75, 75, 75); public const int SwordKnight_Expert_MeleeRadius = 375; public const int SwordKnight_Expert_ProjectileRadius = 500; public const int SwordKnight_Expert_EngageRadius = 800; + public const string SwordKnight_Miniboss_Name = "Graypion"; public const int SwordKnight_Miniboss_MaxHealth = 750; public const int SwordKnight_Miniboss_Damage = 80; public const int SwordKnight_Miniboss_XPValue = 800; public const int SwordKnight_Miniboss_Speed = 85; public const int SwordKnight_Miniboss_Jump = 950; public const float SwordKnight_Miniboss_Cooldown = 8f; public const int SwordKnight_Miniboss_MinDropAmount = 10; public const int SwordKnight_Miniboss_MaxDropAmount = 15; public const float SwordKnight_Miniboss_DropChance = 1f; public const float SwordKnight_Miniboss_TurnSpeed = 10f; public const float SwordKnight_Miniboss_ProjectileSpeed = 850f; public const float SwordKnight_Miniboss_AnimationDelay = 8f; public const bool SwordKnight_Miniboss_AlwaysFaceTarget = true; public const bool SwordKnight_Miniboss_CanFallOffLedges = false; public const bool SwordKnight_Miniboss_CanBeKnockedBack = true; public const bool SwordKnight_Miniboss_IsWeighted = true; public static Vector2 SwordKnight_Miniboss_KnockBack = new Vector2(125, 125); public static Vector2 SwordKnight_Miniboss_Scale = new Vector2(6.5f, 6.5f); public static Vector2 SwordKnight_Miniboss_ProjectileScale = new Vector2(1.25f, 1.25f); public static Color SwordKnight_Miniboss_Tint = new Color(20, 105, 25); public const int SwordKnight_Miniboss_MeleeRadius = 300; public const int SwordKnight_Miniboss_ProjectileRadius = 500; public const int SwordKnight_Miniboss_EngageRadius = 800; + public const string Wolf_Basic_Name = "Warg"; public const int Wolf_Basic_MaxHealth = 18; public const int Wolf_Basic_Damage = 25; public const int Wolf_Basic_XPValue = 75; public const int Wolf_Basic_Speed = 600; public const int Wolf_Basic_Jump = 1035; public const float Wolf_Basic_Cooldown = 2f; public const int Wolf_Basic_MinDropAmount = 1; public const int Wolf_Basic_MaxDropAmount = 2; public const float Wolf_Basic_DropChance = 0.4f; public const float Wolf_Basic_TurnSpeed = 10f; public const float Wolf_Basic_ProjectileSpeed = 650f; public const float Wolf_Basic_AnimationDelay = 30f; public const bool Wolf_Basic_AlwaysFaceTarget = true; public const bool Wolf_Basic_CanFallOffLedges = true; public const bool Wolf_Basic_CanBeKnockedBack = true; public const bool Wolf_Basic_IsWeighted = true; public static Vector2 Wolf_Basic_KnockBack = new Vector2(0, 0); public static Vector2 Wolf_Basic_Scale = new Vector2(2.5f, 2.5f); public static Vector2 Wolf_Basic_ProjectileScale = new Vector2(2f, 2f); public static Color Wolf_Basic_Tint = new Color(125, 125, 125); public const int Wolf_Basic_MeleeRadius = 50; public const int Wolf_Basic_ProjectileRadius = 400; public const int Wolf_Basic_EngageRadius = 550; + public const string Wolf_Advanced_Name = "Wargen"; public const int Wolf_Advanced_MaxHealth = 25; public const int Wolf_Advanced_Damage = 28; public const int Wolf_Advanced_XPValue = 125; public const int Wolf_Advanced_Speed = 700; public const int Wolf_Advanced_Jump = 1035; public const float Wolf_Advanced_Cooldown = 2f; public const int Wolf_Advanced_MinDropAmount = 1; public const int Wolf_Advanced_MaxDropAmount = 2; public const float Wolf_Advanced_DropChance = 0.5f; public const float Wolf_Advanced_TurnSpeed = 10f; public const float Wolf_Advanced_ProjectileSpeed = 650f; public const float Wolf_Advanced_AnimationDelay = 30f; public const bool Wolf_Advanced_AlwaysFaceTarget = true; public const bool Wolf_Advanced_CanFallOffLedges = true; public const bool Wolf_Advanced_CanBeKnockedBack = true; public const bool Wolf_Advanced_IsWeighted = true; public static Vector2 Wolf_Advanced_KnockBack = new Vector2(0, 0); public static Vector2 Wolf_Advanced_Scale = new Vector2(3.0f, 3.0f); public static Vector2 Wolf_Advanced_ProjectileScale = new Vector2(2f, 2f); public static Color Wolf_Advanced_Tint = new Color(155, 30, 30); public const int Wolf_Advanced_MeleeRadius = 50; public const int Wolf_Advanced_ProjectileRadius = 400; public const int Wolf_Advanced_EngageRadius = 575; + public const string Wolf_Expert_Name = "Wargenflorgen"; public const int Wolf_Expert_MaxHealth = 52; public const int Wolf_Expert_Damage = 32; public const int Wolf_Expert_XPValue = 225; public const int Wolf_Expert_Speed = 850; public const int Wolf_Expert_Jump = 1035; public const float Wolf_Expert_Cooldown = 2f; public const int Wolf_Expert_MinDropAmount = 2; public const int Wolf_Expert_MaxDropAmount = 3; public const float Wolf_Expert_DropChance = 1f; public const float Wolf_Expert_TurnSpeed = 10f; public const float Wolf_Expert_ProjectileSpeed = 650f; public const float Wolf_Expert_AnimationDelay = 30f; public const bool Wolf_Expert_AlwaysFaceTarget = true; public const bool Wolf_Expert_CanFallOffLedges = true; public const bool Wolf_Expert_CanBeKnockedBack = true; public const bool Wolf_Expert_IsWeighted = true; public static Vector2 Wolf_Expert_KnockBack = new Vector2(0, 0); public static Vector2 Wolf_Expert_Scale = new Vector2(4.0f, 4.0f); public static Vector2 Wolf_Expert_ProjectileScale = new Vector2(2f, 2f); public static Color Wolf_Expert_Tint = new Color(255, 255, 255); public const int Wolf_Expert_MeleeRadius = 50; public const int Wolf_Expert_ProjectileRadius = 400; public const int Wolf_Expert_EngageRadius = 625; + public const string Wolf_Miniboss_Name = "Zorg Warg"; public const int Wolf_Miniboss_MaxHealth = 500; public const int Wolf_Miniboss_Damage = 35; public const int Wolf_Miniboss_XPValue = 750; public const int Wolf_Miniboss_Speed = 925; public const int Wolf_Miniboss_Jump = 1035; public const float Wolf_Miniboss_Cooldown = 2f; public const int Wolf_Miniboss_MinDropAmount = 1; public const int Wolf_Miniboss_MaxDropAmount = 2; public const float Wolf_Miniboss_DropChance = 1f; public const float Wolf_Miniboss_TurnSpeed = 10f; public const float Wolf_Miniboss_ProjectileSpeed = 650f; public const float Wolf_Miniboss_AnimationDelay = 30f; public const bool Wolf_Miniboss_AlwaysFaceTarget = true; public const bool Wolf_Miniboss_CanFallOffLedges = true; public const bool Wolf_Miniboss_CanBeKnockedBack = true; public const bool Wolf_Miniboss_IsWeighted = true; public static Vector2 Wolf_Miniboss_KnockBack = new Vector2(0, 0); public static Vector2 Wolf_Miniboss_Scale = new Vector2(5.0f, 5.0f); public static Vector2 Wolf_Miniboss_ProjectileScale = new Vector2(2f, 2f); public static Color Wolf_Miniboss_Tint = new Color(125, 125, 125); public const int Wolf_Miniboss_MeleeRadius = 50; public const int Wolf_Miniboss_ProjectileRadius = 400; public const int Wolf_Miniboss_EngageRadius = 700; + public const string Zombie_Basic_Name = "Zombie"; public const int Zombie_Basic_MaxHealth = 24; public const int Zombie_Basic_Damage = 25; public const int Zombie_Basic_XPValue = 25; public const int Zombie_Basic_Speed = 160; public const int Zombie_Basic_Jump = 900; public const float Zombie_Basic_Cooldown = 2f; public const int Zombie_Basic_MinDropAmount = 1; public const int Zombie_Basic_MaxDropAmount = 1; public const float Zombie_Basic_DropChance = 0.4f; public const float Zombie_Basic_TurnSpeed = 10f; public const float Zombie_Basic_ProjectileSpeed = 650f; public const float Zombie_Basic_AnimationDelay = 12f; public const bool Zombie_Basic_AlwaysFaceTarget = true; public const bool Zombie_Basic_CanFallOffLedges = false; public const bool Zombie_Basic_CanBeKnockedBack = true; public const bool Zombie_Basic_IsWeighted = true; public static Vector2 Zombie_Basic_KnockBack = new Vector2(0, 0); public static Vector2 Zombie_Basic_Scale = new Vector2(2.5f, 2.5f); public static Vector2 Zombie_Basic_ProjectileScale = new Vector2(2f, 2f); public static Color Zombie_Basic_Tint = new Color(255, 255, 255); public const int Zombie_Basic_MeleeRadius = 100; public const int Zombie_Basic_ProjectileRadius = 150; public const int Zombie_Basic_EngageRadius = 435; + public const string Zombie_Advanced_Name = "Zomboner"; public const int Zombie_Advanced_MaxHealth = 39; public const int Zombie_Advanced_Damage = 29; public const int Zombie_Advanced_XPValue = 75; public const int Zombie_Advanced_Speed = 260; public const int Zombie_Advanced_Jump = 900; public const float Zombie_Advanced_Cooldown = 2f; public const int Zombie_Advanced_MinDropAmount = 1; public const int Zombie_Advanced_MaxDropAmount = 2; public const float Zombie_Advanced_DropChance = 0.5f; public const float Zombie_Advanced_TurnSpeed = 10f; public const float Zombie_Advanced_ProjectileSpeed = 650f; public const float Zombie_Advanced_AnimationDelay = 14f; public const bool Zombie_Advanced_AlwaysFaceTarget = true; public const bool Zombie_Advanced_CanFallOffLedges = false; public const bool Zombie_Advanced_CanBeKnockedBack = true; public const bool Zombie_Advanced_IsWeighted = true; public static Vector2 Zombie_Advanced_KnockBack = new Vector2(300, 250); public static Vector2 Zombie_Advanced_Scale = new Vector2(3.0f, 3.0f); public static Vector2 Zombie_Advanced_ProjectileScale = new Vector2(2f, 2f); public static Color Zombie_Advanced_Tint = new Color(185, 50, 20); public const int Zombie_Advanced_MeleeRadius = 100; public const int Zombie_Advanced_ProjectileRadius = 150; public const int Zombie_Advanced_EngageRadius = 435; + public const string Zombie_Expert_Name = "Zombishnu"; public const int Zombie_Expert_MaxHealth = 70; public const int Zombie_Expert_Damage = 33; public const int Zombie_Expert_XPValue = 200; public const int Zombie_Expert_Speed = 350; public const int Zombie_Expert_Jump = 900; public const float Zombie_Expert_Cooldown = 2f; public const int Zombie_Expert_MinDropAmount = 1; public const int Zombie_Expert_MaxDropAmount = 3; public const float Zombie_Expert_DropChance = 1f; public const float Zombie_Expert_TurnSpeed = 10f; public const float Zombie_Expert_ProjectileSpeed = 650f; public const float Zombie_Expert_AnimationDelay = 16f; public const bool Zombie_Expert_AlwaysFaceTarget = true; public const bool Zombie_Expert_CanFallOffLedges = false; public const bool Zombie_Expert_CanBeKnockedBack = false; public const bool Zombie_Expert_IsWeighted = true; public static Vector2 Zombie_Expert_KnockBack = new Vector2(75, 25); public static Vector2 Zombie_Expert_Scale = new Vector2(3.5f, 3.5f); public static Vector2 Zombie_Expert_ProjectileScale = new Vector2(2f, 2f); public static Color Zombie_Expert_Tint = new Color(145, 130, 35); public const int Zombie_Expert_MeleeRadius = 100; public const int Zombie_Expert_ProjectileRadius = 150; public const int Zombie_Expert_EngageRadius = 435; + public const string Zombie_Miniboss_Name = "Zomg"; public const int Zombie_Miniboss_MaxHealth = 800; public const int Zombie_Miniboss_Damage = 40; public const int Zombie_Miniboss_XPValue = 600; public const int Zombie_Miniboss_Speed = 600; public const int Zombie_Miniboss_Jump = 900; public const float Zombie_Miniboss_Cooldown = 2f; public const int Zombie_Miniboss_MinDropAmount = 1; public const int Zombie_Miniboss_MaxDropAmount = 2; public const float Zombie_Miniboss_DropChance = 1f; public const float Zombie_Miniboss_TurnSpeed = 10f; public const float Zombie_Miniboss_ProjectileSpeed = 650f; public const float Zombie_Miniboss_AnimationDelay = 14f; public const bool Zombie_Miniboss_AlwaysFaceTarget = true; public const bool Zombie_Miniboss_CanFallOffLedges = false; public const bool Zombie_Miniboss_CanBeKnockedBack = false; public const bool Zombie_Miniboss_IsWeighted = true; public static Vector2 Zombie_Miniboss_KnockBack = new Vector2(75, 25); public static Vector2 Zombie_Miniboss_Scale = new Vector2(4.5f, 4.5f); public static Vector2 Zombie_Miniboss_ProjectileScale = new Vector2(2f, 2f); public static Color Zombie_Miniboss_Tint = new Color(45, 45, 45); public const int Zombie_Miniboss_MeleeRadius = 100; public const int Zombie_Miniboss_ProjectileRadius = 150; public const int Zombie_Miniboss_EngageRadius = 435; + public const string Energon_Basic_Name = "Energon"; public const int Energon_Basic_MaxHealth = 25; public const int Energon_Basic_Damage = 25; public const int Energon_Basic_XPValue = 150; public const int Energon_Basic_Speed = 75; public const int Energon_Basic_Jump = 950; public const float Energon_Basic_Cooldown = 2f; public const int Energon_Basic_MinDropAmount = 1; public const int Energon_Basic_MaxDropAmount = 2; public const float Energon_Basic_DropChance = 0.4f; public const float Energon_Basic_TurnSpeed = 10f; public const float Energon_Basic_ProjectileSpeed = 300f; public const float Energon_Basic_AnimationDelay = 10f; public const bool Energon_Basic_AlwaysFaceTarget = true; public const bool Energon_Basic_CanFallOffLedges = false; public const bool Energon_Basic_CanBeKnockedBack = true; public const bool Energon_Basic_IsWeighted = true; public static Vector2 Energon_Basic_KnockBack = new Vector2(0, 0); public static Vector2 Energon_Basic_Scale = new Vector2(2.5f, 2.5f); public static Vector2 Energon_Basic_ProjectileScale = new Vector2(1.75f, 1.75f); public static Color Energon_Basic_Tint = new Color(255, 255, 255); public const int Energon_Basic_MeleeRadius = 150; public const int Energon_Basic_ProjectileRadius = 750; public const int Energon_Basic_EngageRadius = 850; + public const string Energon_Advanced_Name = "Mastertron"; public const int Energon_Advanced_MaxHealth = 38; public const int Energon_Advanced_Damage = 29; public const int Energon_Advanced_XPValue = 250; public const int Energon_Advanced_Speed = 100; public const int Energon_Advanced_Jump = 950; public const float Energon_Advanced_Cooldown = 2f; public const int Energon_Advanced_MinDropAmount = 1; public const int Energon_Advanced_MaxDropAmount = 2; public const float Energon_Advanced_DropChance = 0.5f; public const float Energon_Advanced_TurnSpeed = 10f; public const float Energon_Advanced_ProjectileSpeed = 300f; public const float Energon_Advanced_AnimationDelay = 10f; public const bool Energon_Advanced_AlwaysFaceTarget = true; public const bool Energon_Advanced_CanFallOffLedges = false; public const bool Energon_Advanced_CanBeKnockedBack = true; public const bool Energon_Advanced_IsWeighted = true; public static Vector2 Energon_Advanced_KnockBack = new Vector2(0, 0); public static Vector2 Energon_Advanced_Scale = new Vector2(2.5f, 2.5f); public static Vector2 Energon_Advanced_ProjectileScale = new Vector2(1.75f, 1.75f); public static Color Energon_Advanced_Tint = new Color(125, 150, 175); public const int Energon_Advanced_MeleeRadius = 150; public const int Energon_Advanced_ProjectileRadius = 750; public const int Energon_Advanced_EngageRadius = 850; + public const string Energon_Expert_Name = "Voltron"; public const int Energon_Expert_MaxHealth = 61; public const int Energon_Expert_Damage = 33; public const int Energon_Expert_XPValue = 375; public const int Energon_Expert_Speed = 125; public const int Energon_Expert_Jump = 950; public const float Energon_Expert_Cooldown = 2f; public const int Energon_Expert_MinDropAmount = 2; public const int Energon_Expert_MaxDropAmount = 4; public const float Energon_Expert_DropChance = 1f; public const float Energon_Expert_TurnSpeed = 10f; public const float Energon_Expert_ProjectileSpeed = 300f; public const float Energon_Expert_AnimationDelay = 10f; public const bool Energon_Expert_AlwaysFaceTarget = true; public const bool Energon_Expert_CanFallOffLedges = false; public const bool Energon_Expert_CanBeKnockedBack = true; public const bool Energon_Expert_IsWeighted = true; public static Vector2 Energon_Expert_KnockBack = new Vector2(0, 0); public static Vector2 Energon_Expert_Scale = new Vector2(2.5f, 2.5f); public static Vector2 Energon_Expert_ProjectileScale = new Vector2(1.75f, 1.75f); public static Color Energon_Expert_Tint = new Color(200, 200, 255); public const int Energon_Expert_MeleeRadius = 150; public const int Energon_Expert_ProjectileRadius = 750; public const int Energon_Expert_EngageRadius = 850; + public const string Energon_Miniboss_Name = "Prime"; public const int Energon_Miniboss_MaxHealth = 300; public const int Energon_Miniboss_Damage = 39; public const int Energon_Miniboss_XPValue = 1500; public const int Energon_Miniboss_Speed = 200; public const int Energon_Miniboss_Jump = 950; public const float Energon_Miniboss_Cooldown = 2f; public const int Energon_Miniboss_MinDropAmount = 8; public const int Energon_Miniboss_MaxDropAmount = 16; public const float Energon_Miniboss_DropChance = 1f; public const float Energon_Miniboss_TurnSpeed = 10f; public const float Energon_Miniboss_ProjectileSpeed = 300f; public const float Energon_Miniboss_AnimationDelay = 10f; public const bool Energon_Miniboss_AlwaysFaceTarget = true; public const bool Energon_Miniboss_CanFallOffLedges = false; public const bool Energon_Miniboss_CanBeKnockedBack = true; public const bool Energon_Miniboss_IsWeighted = true; public static Vector2 Energon_Miniboss_KnockBack = new Vector2(0, 0); public static Vector2 Energon_Miniboss_Scale = new Vector2(2.5f, 2.5f); public static Vector2 Energon_Miniboss_ProjectileScale = new Vector2(1.75f, 1.75f); public static Color Energon_Miniboss_Tint = new Color(255, 0, 255); public const int Energon_Miniboss_MeleeRadius = 150; public const int Energon_Miniboss_ProjectileRadius = 750; public const int Energon_Miniboss_EngageRadius = 850; + public const string Ninja_Basic_Name = "Ninjo"; public const int Ninja_Basic_MaxHealth = 30; public const int Ninja_Basic_Damage = 20; public const int Ninja_Basic_XPValue = 150; public const int Ninja_Basic_Speed = 250; public const int Ninja_Basic_Jump = 600; public const float Ninja_Basic_Cooldown = 1.5f; public const int Ninja_Basic_MinDropAmount = 1; public const int Ninja_Basic_MaxDropAmount = 2; public const float Ninja_Basic_DropChance = 0.4f; public const float Ninja_Basic_TurnSpeed = 10f; public const float Ninja_Basic_ProjectileSpeed = 550f; public const float Ninja_Basic_AnimationDelay = 10f; public const bool Ninja_Basic_AlwaysFaceTarget = true; public const bool Ninja_Basic_CanFallOffLedges = false; public const bool Ninja_Basic_CanBeKnockedBack = true; public const bool Ninja_Basic_IsWeighted = true; public static Vector2 Ninja_Basic_KnockBack = new Vector2(0, 0); public static Vector2 Ninja_Basic_Scale = new Vector2(2.4f, 2.4f); public static Vector2 Ninja_Basic_ProjectileScale = new Vector2(1.75f, 1.75f); public static Color Ninja_Basic_Tint = new Color(255, 255, 255); public const int Ninja_Basic_MeleeRadius = 225; public const int Ninja_Basic_ProjectileRadius = 700; public const int Ninja_Basic_EngageRadius = 1000; + public const string Ninja_Advanced_Name = "Ninpo"; public const int Ninja_Advanced_MaxHealth = 44; public const int Ninja_Advanced_Damage = 25; public const int Ninja_Advanced_XPValue = 250; public const int Ninja_Advanced_Speed = 325; public const int Ninja_Advanced_Jump = 600; public const float Ninja_Advanced_Cooldown = 1.5f; public const int Ninja_Advanced_MinDropAmount = 1; public const int Ninja_Advanced_MaxDropAmount = 2; public const float Ninja_Advanced_DropChance = 0.5f; public const float Ninja_Advanced_TurnSpeed = 10f; public const float Ninja_Advanced_ProjectileSpeed = 625f; public const float Ninja_Advanced_AnimationDelay = 10f; public const bool Ninja_Advanced_AlwaysFaceTarget = true; public const bool Ninja_Advanced_CanFallOffLedges = false; public const bool Ninja_Advanced_CanBeKnockedBack = true; public const bool Ninja_Advanced_IsWeighted = true; public static Vector2 Ninja_Advanced_KnockBack = new Vector2(0, 0); public static Vector2 Ninja_Advanced_Scale = new Vector2(2.7f, 2.7f); public static Vector2 Ninja_Advanced_ProjectileScale = new Vector2(1.85f, 1.85f); public static Color Ninja_Advanced_Tint = new Color(215, 125, 135); public const int Ninja_Advanced_MeleeRadius = 225; public const int Ninja_Advanced_ProjectileRadius = 700; public const int Ninja_Advanced_EngageRadius = 1000; + public const string Ninja_Expert_Name = "Ninopojo"; public const int Ninja_Expert_MaxHealth = 62; public const int Ninja_Expert_Damage = 29; public const int Ninja_Expert_XPValue = 450; public const int Ninja_Expert_Speed = 400; public const int Ninja_Expert_Jump = 600; public const float Ninja_Expert_Cooldown = 1.5f; public const int Ninja_Expert_MinDropAmount = 2; public const int Ninja_Expert_MaxDropAmount = 4; public const float Ninja_Expert_DropChance = 1f; public const float Ninja_Expert_TurnSpeed = 10f; public const float Ninja_Expert_ProjectileSpeed = 700f; public const float Ninja_Expert_AnimationDelay = 10f; public const bool Ninja_Expert_AlwaysFaceTarget = true; public const bool Ninja_Expert_CanFallOffLedges = false; public const bool Ninja_Expert_CanBeKnockedBack = true; public const bool Ninja_Expert_IsWeighted = true; public static Vector2 Ninja_Expert_KnockBack = new Vector2(0, 0); public static Vector2 Ninja_Expert_Scale = new Vector2(3.3f, 3.3f); public static Vector2 Ninja_Expert_ProjectileScale = new Vector2(2.0f, 2.0f); public static Color Ninja_Expert_Tint = new Color(250, 180, 20); public const int Ninja_Expert_MeleeRadius = 225; public const int Ninja_Expert_ProjectileRadius = 700; public const int Ninja_Expert_EngageRadius = 1000; + public const string Ninja_Miniboss_Name = "Master Ninja"; public const int Ninja_Miniboss_MaxHealth = 900; public const int Ninja_Miniboss_Damage = 38; public const int Ninja_Miniboss_XPValue = 1250; public const int Ninja_Miniboss_Speed = 150; public const int Ninja_Miniboss_Jump = 600; public const float Ninja_Miniboss_Cooldown = 1.5f; public const int Ninja_Miniboss_MinDropAmount = 10; public const int Ninja_Miniboss_MaxDropAmount = 15; public const float Ninja_Miniboss_DropChance = 1f; public const float Ninja_Miniboss_TurnSpeed = 10f; public const float Ninja_Miniboss_ProjectileSpeed = 600f; public const float Ninja_Miniboss_AnimationDelay = 10f; public const bool Ninja_Miniboss_AlwaysFaceTarget = true; public const bool Ninja_Miniboss_CanFallOffLedges = false; public const bool Ninja_Miniboss_CanBeKnockedBack = true; public const bool Ninja_Miniboss_IsWeighted = true; public static Vector2 Ninja_Miniboss_KnockBack = new Vector2(0, 0); public static Vector2 Ninja_Miniboss_Scale = new Vector2(2.7f, 2.7f); public static Vector2 Ninja_Miniboss_ProjectileScale = new Vector2(1.75f, 1.75f); public static Color Ninja_Miniboss_Tint = new Color(100, 100, 100); public const int Ninja_Miniboss_MeleeRadius = 225; public const int Ninja_Miniboss_ProjectileRadius = 700; public const int Ninja_Miniboss_EngageRadius = 1000; + public const string Plant_Basic_Name = "Bud"; public const int Plant_Basic_MaxHealth = 20; public const int Plant_Basic_Damage = 20; public const int Plant_Basic_XPValue = 25; public const int Plant_Basic_Speed = 125; public const int Plant_Basic_Jump = 900; public const float Plant_Basic_Cooldown = 2f; public const int Plant_Basic_MinDropAmount = 1; public const int Plant_Basic_MaxDropAmount = 2; public const float Plant_Basic_DropChance = 0.4f; public const float Plant_Basic_TurnSpeed = 10f; public const float Plant_Basic_ProjectileSpeed = 900f; public const float Plant_Basic_AnimationDelay = 10f; public const bool Plant_Basic_AlwaysFaceTarget = true; public const bool Plant_Basic_CanFallOffLedges = false; public const bool Plant_Basic_CanBeKnockedBack = true; public const bool Plant_Basic_IsWeighted = true; public static Vector2 Plant_Basic_KnockBack = new Vector2(100, 100); public static Vector2 Plant_Basic_Scale = new Vector2(2.0f, 2.0f); public static Vector2 Plant_Basic_ProjectileScale = new Vector2(2.0f, 2.0f); public static Color Plant_Basic_Tint = new Color(10, 160, 165); public const int Plant_Basic_MeleeRadius = 325; public const int Plant_Basic_ProjectileRadius = 690; public const int Plant_Basic_EngageRadius = 850; + public const string Plant_Advanced_Name = "Plantite"; public const int Plant_Advanced_MaxHealth = 28; public const int Plant_Advanced_Damage = 23; public const int Plant_Advanced_XPValue = 50; public const int Plant_Advanced_Speed = 150; public const int Plant_Advanced_Jump = 900; public const float Plant_Advanced_Cooldown = 1.75f; public const int Plant_Advanced_MinDropAmount = 1; public const int Plant_Advanced_MaxDropAmount = 2; public const float Plant_Advanced_DropChance = 0.5f; public const float Plant_Advanced_TurnSpeed = 10f; public const float Plant_Advanced_ProjectileSpeed = 1000f; public const float Plant_Advanced_AnimationDelay = 10f; public const bool Plant_Advanced_AlwaysFaceTarget = true; public const bool Plant_Advanced_CanFallOffLedges = false; public const bool Plant_Advanced_CanBeKnockedBack = true; public const bool Plant_Advanced_IsWeighted = true; public static Vector2 Plant_Advanced_KnockBack = new Vector2(100, 100); public static Vector2 Plant_Advanced_Scale = new Vector2(2.5f, 2.5f); public static Vector2 Plant_Advanced_ProjectileScale = new Vector2(2.0f, 2.0f); public static Color Plant_Advanced_Tint = new Color(210, 20, 0); public const int Plant_Advanced_MeleeRadius = 325; public const int Plant_Advanced_ProjectileRadius = 690; public const int Plant_Advanced_EngageRadius = 850; + public const string Plant_Expert_Name = "Flowermon"; public const int Plant_Expert_MaxHealth = 53; public const int Plant_Expert_Damage = 26; public const int Plant_Expert_XPValue = 175; public const int Plant_Expert_Speed = 200; public const int Plant_Expert_Jump = 900; public const float Plant_Expert_Cooldown = 1.25f; public const int Plant_Expert_MinDropAmount = 2; public const int Plant_Expert_MaxDropAmount = 4; public const float Plant_Expert_DropChance = 1f; public const float Plant_Expert_TurnSpeed = 10f; public const float Plant_Expert_ProjectileSpeed = 1000f; public const float Plant_Expert_AnimationDelay = 10f; public const bool Plant_Expert_AlwaysFaceTarget = true; public const bool Plant_Expert_CanFallOffLedges = false; public const bool Plant_Expert_CanBeKnockedBack = true; public const bool Plant_Expert_IsWeighted = true; public static Vector2 Plant_Expert_KnockBack = new Vector2(100, 100); public static Vector2 Plant_Expert_Scale = new Vector2(3.0f, 3.0f); public static Vector2 Plant_Expert_ProjectileScale = new Vector2(2.0f, 2.0f); public static Color Plant_Expert_Tint = new Color(240, 225, 10); public const int Plant_Expert_MeleeRadius = 325; public const int Plant_Expert_ProjectileRadius = 690; public const int Plant_Expert_EngageRadius = 850; + public const string Plant_Miniboss_Name = "Stolas & Focalor"; public const int Plant_Miniboss_MaxHealth = 165; public const int Plant_Miniboss_Damage = 28; public const int Plant_Miniboss_XPValue = 500; public const int Plant_Miniboss_Speed = 450; public const int Plant_Miniboss_Jump = 900; public const float Plant_Miniboss_Cooldown = 0.5f; public const int Plant_Miniboss_MinDropAmount = 11; public const int Plant_Miniboss_MaxDropAmount = 18; public const float Plant_Miniboss_DropChance = 1f; public const float Plant_Miniboss_TurnSpeed = 10f; public const float Plant_Miniboss_ProjectileSpeed = 700f; public const float Plant_Miniboss_AnimationDelay = 10f; public const bool Plant_Miniboss_AlwaysFaceTarget = true; public const bool Plant_Miniboss_CanFallOffLedges = false; public const bool Plant_Miniboss_CanBeKnockedBack = true; public const bool Plant_Miniboss_IsWeighted = true; public static Vector2 Plant_Miniboss_KnockBack = new Vector2(100, 100); public static Vector2 Plant_Miniboss_Scale = new Vector2(3.5f, 3.5f); public static Vector2 Plant_Miniboss_ProjectileScale = new Vector2(2.0f, 2.0f); public static Color Plant_Miniboss_Tint = new Color(35, 35, 35); public const int Plant_Miniboss_MeleeRadius = 325; public const int Plant_Miniboss_ProjectileRadius = 690; public const int Plant_Miniboss_EngageRadius = 850; + public const string Fireball_Basic_Name = "Charite"; public const int Fireball_Basic_MaxHealth = 35; public const int Fireball_Basic_Damage = 23; public const int Fireball_Basic_XPValue = 100; public const int Fireball_Basic_Speed = 400; public const int Fireball_Basic_Jump = 950; public const float Fireball_Basic_Cooldown = 4f; public const int Fireball_Basic_MinDropAmount = 1; public const int Fireball_Basic_MaxDropAmount = 2; public const float Fireball_Basic_DropChance = 0.4f; public const float Fireball_Basic_TurnSpeed = 0.0275f; public const float Fireball_Basic_ProjectileSpeed = 525f; public const float Fireball_Basic_AnimationDelay = 20f; public const bool Fireball_Basic_AlwaysFaceTarget = true; public const bool Fireball_Basic_CanFallOffLedges = false; public const bool Fireball_Basic_CanBeKnockedBack = true; public const bool Fireball_Basic_IsWeighted = false; public static Vector2 Fireball_Basic_KnockBack = new Vector2(250, 200); public static Vector2 Fireball_Basic_Scale = new Vector2(2.5f, 2.5f); public static Vector2 Fireball_Basic_ProjectileScale = new Vector2(1.75f, 1.75f); public static Color Fireball_Basic_Tint = new Color(255, 255, 255); public const int Fireball_Basic_MeleeRadius = 500; public const int Fireball_Basic_ProjectileRadius = 700; public const int Fireball_Basic_EngageRadius = 1350; + public const string Fireball_Advanced_Name = "Pyrite"; public const int Fireball_Advanced_MaxHealth = 45; public const int Fireball_Advanced_Damage = 25; public const int Fireball_Advanced_XPValue = 175; public const int Fireball_Advanced_Speed = 420; public const int Fireball_Advanced_Jump = 950; public const float Fireball_Advanced_Cooldown = 4f; public const int Fireball_Advanced_MinDropAmount = 1; public const int Fireball_Advanced_MaxDropAmount = 2; public const float Fireball_Advanced_DropChance = 0.5f; public const float Fireball_Advanced_TurnSpeed = 0.03f; public const float Fireball_Advanced_ProjectileSpeed = 525f; public const float Fireball_Advanced_AnimationDelay = 20f; public const bool Fireball_Advanced_AlwaysFaceTarget = true; public const bool Fireball_Advanced_CanFallOffLedges = false; public const bool Fireball_Advanced_CanBeKnockedBack = true; public const bool Fireball_Advanced_IsWeighted = false; public static Vector2 Fireball_Advanced_KnockBack = new Vector2(250, 200); public static Vector2 Fireball_Advanced_Scale = new Vector2(3.0f, 3.0f); public static Vector2 Fireball_Advanced_ProjectileScale = new Vector2(1.75f, 1.75f); public static Color Fireball_Advanced_Tint = new Color(255, 180, 0); public const int Fireball_Advanced_MeleeRadius = 500; public const int Fireball_Advanced_ProjectileRadius = 700; public const int Fireball_Advanced_EngageRadius = 1350; + public const string Fireball_Expert_Name = "Infernite"; public const int Fireball_Expert_MaxHealth = 63; public const int Fireball_Expert_Damage = 27; public const int Fireball_Expert_XPValue = 350; public const int Fireball_Expert_Speed = 440; public const int Fireball_Expert_Jump = 950; public const float Fireball_Expert_Cooldown = 4f; public const int Fireball_Expert_MinDropAmount = 2; public const int Fireball_Expert_MaxDropAmount = 3; public const float Fireball_Expert_DropChance = 1f; public const float Fireball_Expert_TurnSpeed = 0.03f; public const float Fireball_Expert_ProjectileSpeed = 525f; public const float Fireball_Expert_AnimationDelay = 20f; public const bool Fireball_Expert_AlwaysFaceTarget = true; public const bool Fireball_Expert_CanFallOffLedges = false; public const bool Fireball_Expert_CanBeKnockedBack = true; public const bool Fireball_Expert_IsWeighted = false; public static Vector2 Fireball_Expert_KnockBack = new Vector2(250, 200); public static Vector2 Fireball_Expert_Scale = new Vector2(3.5f, 3.5f); public static Vector2 Fireball_Expert_ProjectileScale = new Vector2(1.75f, 1.75f); public static Color Fireball_Expert_Tint = new Color(255, 0, 0); public const int Fireball_Expert_MeleeRadius = 500; public const int Fireball_Expert_ProjectileRadius = 700; public const int Fireball_Expert_EngageRadius = 1350; + public const string Fireball_Miniboss_Name = "Ponce de Leon"; public const int Fireball_Miniboss_MaxHealth = 505; public const int Fireball_Miniboss_Damage = 29; public const int Fireball_Miniboss_XPValue = 800; public const int Fireball_Miniboss_Speed = 380; public const int Fireball_Miniboss_Jump = 950; public const float Fireball_Miniboss_Cooldown = 4f; public const int Fireball_Miniboss_MinDropAmount = 15; public const int Fireball_Miniboss_MaxDropAmount = 20; public const float Fireball_Miniboss_DropChance = 1f; public const float Fireball_Miniboss_TurnSpeed = 0.03f; public const float Fireball_Miniboss_ProjectileSpeed = 0f; public const float Fireball_Miniboss_AnimationDelay = 20f; public const bool Fireball_Miniboss_AlwaysFaceTarget = true; public const bool Fireball_Miniboss_CanFallOffLedges = false; public const bool Fireball_Miniboss_CanBeKnockedBack = false; public const bool Fireball_Miniboss_IsWeighted = false; public static Vector2 Fireball_Miniboss_KnockBack = new Vector2(250, 200); public static Vector2 Fireball_Miniboss_Scale = new Vector2(3.25f, 3.25f); public static Vector2 Fireball_Miniboss_ProjectileScale = new Vector2(2.25f, 2.25f); public static Color Fireball_Miniboss_Tint = new Color(0, 0, 0); public const int Fireball_Miniboss_MeleeRadius = 500; public const int Fireball_Miniboss_ProjectileRadius = 775; public const int Fireball_Miniboss_EngageRadius = 1350; + public const string SpikeTrap_Basic_Name = "Spike Trap"; public const int SpikeTrap_Basic_MaxHealth = 1; public const int SpikeTrap_Basic_Damage = 25; public const int SpikeTrap_Basic_XPValue = 150; public const int SpikeTrap_Basic_Speed = 100; public const int SpikeTrap_Basic_Jump = 600; public const float SpikeTrap_Basic_Cooldown = 2f; public const int SpikeTrap_Basic_MinDropAmount = 1; public const int SpikeTrap_Basic_MaxDropAmount = 1; public const float SpikeTrap_Basic_DropChance = 0.4f; public const float SpikeTrap_Basic_TurnSpeed = 10f; public const float SpikeTrap_Basic_ProjectileSpeed = 1020f; public const float SpikeTrap_Basic_AnimationDelay = 10f; public const bool SpikeTrap_Basic_AlwaysFaceTarget = false; public const bool SpikeTrap_Basic_CanFallOffLedges = false; public const bool SpikeTrap_Basic_CanBeKnockedBack = false; public const bool SpikeTrap_Basic_IsWeighted = false; public static Vector2 SpikeTrap_Basic_KnockBack = new Vector2(0, 0); public static Vector2 SpikeTrap_Basic_Scale = new Vector2(2.0f, 2.0f); public static Vector2 SpikeTrap_Basic_ProjectileScale = new Vector2(1.5f, 1.5f); public static Color SpikeTrap_Basic_Tint = new Color(255, 255, 255); public const int SpikeTrap_Basic_MeleeRadius = 225; public const int SpikeTrap_Basic_ProjectileRadius = 500; public const int SpikeTrap_Basic_EngageRadius = 700; + public const string SpikeTrap_Advanced_Name = "Spike Trap"; public const int SpikeTrap_Advanced_MaxHealth = 1; public const int SpikeTrap_Advanced_Damage = 30; public const int SpikeTrap_Advanced_XPValue = 250; public const int SpikeTrap_Advanced_Speed = 100; public const int SpikeTrap_Advanced_Jump = 600; public const float SpikeTrap_Advanced_Cooldown = 2f; public const int SpikeTrap_Advanced_MinDropAmount = 1; public const int SpikeTrap_Advanced_MaxDropAmount = 1; public const float SpikeTrap_Advanced_DropChance = 0.5f; public const float SpikeTrap_Advanced_TurnSpeed = 10f; public const float SpikeTrap_Advanced_ProjectileSpeed = 1020f; public const float SpikeTrap_Advanced_AnimationDelay = 10f; public const bool SpikeTrap_Advanced_AlwaysFaceTarget = false; public const bool SpikeTrap_Advanced_CanFallOffLedges = false; public const bool SpikeTrap_Advanced_CanBeKnockedBack = false; public const bool SpikeTrap_Advanced_IsWeighted = false; public static Vector2 SpikeTrap_Advanced_KnockBack = new Vector2(0, 0); public static Vector2 SpikeTrap_Advanced_Scale = new Vector2(2.0f, 2.0f); public static Vector2 SpikeTrap_Advanced_ProjectileScale = new Vector2(1.5f, 1.5f); public static Color SpikeTrap_Advanced_Tint = new Color(255, 255, 255); public const int SpikeTrap_Advanced_MeleeRadius = 225; public const int SpikeTrap_Advanced_ProjectileRadius = 500; public const int SpikeTrap_Advanced_EngageRadius = 700; + public const string SpikeTrap_Expert_Name = "Spike Trap"; public const int SpikeTrap_Expert_MaxHealth = 1; public const int SpikeTrap_Expert_Damage = 35; public const int SpikeTrap_Expert_XPValue = 500; public const int SpikeTrap_Expert_Speed = 100; public const int SpikeTrap_Expert_Jump = 600; public const float SpikeTrap_Expert_Cooldown = 2f; public const int SpikeTrap_Expert_MinDropAmount = 1; public const int SpikeTrap_Expert_MaxDropAmount = 1; public const float SpikeTrap_Expert_DropChance = 1f; public const float SpikeTrap_Expert_TurnSpeed = 10f; public const float SpikeTrap_Expert_ProjectileSpeed = 1020f; public const float SpikeTrap_Expert_AnimationDelay = 10f; public const bool SpikeTrap_Expert_AlwaysFaceTarget = false; public const bool SpikeTrap_Expert_CanFallOffLedges = false; public const bool SpikeTrap_Expert_CanBeKnockedBack = false; public const bool SpikeTrap_Expert_IsWeighted = false; public static Vector2 SpikeTrap_Expert_KnockBack = new Vector2(0, 0); public static Vector2 SpikeTrap_Expert_Scale = new Vector2(2.0f, 2.0f); public static Vector2 SpikeTrap_Expert_ProjectileScale = new Vector2(1.5f, 1.5f); public static Color SpikeTrap_Expert_Tint = new Color(255, 255, 255); public const int SpikeTrap_Expert_MeleeRadius = 225; public const int SpikeTrap_Expert_ProjectileRadius = 500; public const int SpikeTrap_Expert_EngageRadius = 700; + public const string SpikeTrap_Miniboss_Name = "Spike Trap"; public const int SpikeTrap_Miniboss_MaxHealth = 1; public const int SpikeTrap_Miniboss_Damage = 40; public const int SpikeTrap_Miniboss_XPValue = 1250; public const int SpikeTrap_Miniboss_Speed = 100; public const int SpikeTrap_Miniboss_Jump = 600; public const float SpikeTrap_Miniboss_Cooldown = 2f; public const int SpikeTrap_Miniboss_MinDropAmount = 1; public const int SpikeTrap_Miniboss_MaxDropAmount = 1; public const float SpikeTrap_Miniboss_DropChance = 1f; public const float SpikeTrap_Miniboss_TurnSpeed = 10f; public const float SpikeTrap_Miniboss_ProjectileSpeed = 1020f; public const float SpikeTrap_Miniboss_AnimationDelay = 10f; public const bool SpikeTrap_Miniboss_AlwaysFaceTarget = false; public const bool SpikeTrap_Miniboss_CanFallOffLedges = false; public const bool SpikeTrap_Miniboss_CanBeKnockedBack = false; public const bool SpikeTrap_Miniboss_IsWeighted = false; public static Vector2 SpikeTrap_Miniboss_KnockBack = new Vector2(0, 0); public static Vector2 SpikeTrap_Miniboss_Scale = new Vector2(2.0f, 2.0f); public static Vector2 SpikeTrap_Miniboss_ProjectileScale = new Vector2(1.5f, 1.5f); public static Color SpikeTrap_Miniboss_Tint = new Color(255, 255, 255); public const int SpikeTrap_Miniboss_MeleeRadius = 225; public const int SpikeTrap_Miniboss_ProjectileRadius = 500; public const int SpikeTrap_Miniboss_EngageRadius = 700; + public const string SkeletonArcher_Basic_Name = "Archer"; public const int SkeletonArcher_Basic_MaxHealth = 20; public const int SkeletonArcher_Basic_Damage = 22; public const int SkeletonArcher_Basic_XPValue = 75; public const int SkeletonArcher_Basic_Speed = 125; public const int SkeletonArcher_Basic_Jump = 0; public const float SkeletonArcher_Basic_Cooldown = 2f; public const int SkeletonArcher_Basic_MinDropAmount = 1; public const int SkeletonArcher_Basic_MaxDropAmount = 1; public const float SkeletonArcher_Basic_DropChance = 0.4f; public const float SkeletonArcher_Basic_TurnSpeed = 10f; public const float SkeletonArcher_Basic_ProjectileSpeed = 1000f; public const float SkeletonArcher_Basic_AnimationDelay = 10f; public const bool SkeletonArcher_Basic_AlwaysFaceTarget = true; public const bool SkeletonArcher_Basic_CanFallOffLedges = false; public const bool SkeletonArcher_Basic_CanBeKnockedBack = true; public const bool SkeletonArcher_Basic_IsWeighted = true; public static Vector2 SkeletonArcher_Basic_KnockBack = new Vector2(0, 0); public static Vector2 SkeletonArcher_Basic_Scale = new Vector2(2.4f, 2.4f); public static Vector2 SkeletonArcher_Basic_ProjectileScale = new Vector2(1.2f, 1.2f); public static Color SkeletonArcher_Basic_Tint = new Color(255, 255, 255); public const int SkeletonArcher_Basic_MeleeRadius = 325; public const int SkeletonArcher_Basic_ProjectileRadius = 625; public const int SkeletonArcher_Basic_EngageRadius = 850; + public const string SkeletonArcher_Advanced_Name = "Ranger"; public const int SkeletonArcher_Advanced_MaxHealth = 35; public const int SkeletonArcher_Advanced_Damage = 27; public const int SkeletonArcher_Advanced_XPValue = 125; public const int SkeletonArcher_Advanced_Speed = 150; public const int SkeletonArcher_Advanced_Jump = 0; public const float SkeletonArcher_Advanced_Cooldown = 2f; public const int SkeletonArcher_Advanced_MinDropAmount = 1; public const int SkeletonArcher_Advanced_MaxDropAmount = 2; public const float SkeletonArcher_Advanced_DropChance = 0.5f; public const float SkeletonArcher_Advanced_TurnSpeed = 10f; public const float SkeletonArcher_Advanced_ProjectileSpeed = 1100f; public const float SkeletonArcher_Advanced_AnimationDelay = 10f; public const bool SkeletonArcher_Advanced_AlwaysFaceTarget = true; public const bool SkeletonArcher_Advanced_CanFallOffLedges = false; public const bool SkeletonArcher_Advanced_CanBeKnockedBack = true; public const bool SkeletonArcher_Advanced_IsWeighted = true; public static Vector2 SkeletonArcher_Advanced_KnockBack = new Vector2(0, 0); public static Vector2 SkeletonArcher_Advanced_Scale = new Vector2(2.8f, 2.8f); public static Vector2 SkeletonArcher_Advanced_ProjectileScale = new Vector2(1.3f, 1.3f); public static Color SkeletonArcher_Advanced_Tint = new Color(200, 200, 200); public const int SkeletonArcher_Advanced_MeleeRadius = 325; public const int SkeletonArcher_Advanced_ProjectileRadius = 625; public const int SkeletonArcher_Advanced_EngageRadius = 850; + public const string SkeletonArcher_Expert_Name = "Sniper"; public const int SkeletonArcher_Expert_MaxHealth = 61; public const int SkeletonArcher_Expert_Damage = 31; public const int SkeletonArcher_Expert_XPValue = 275; public const int SkeletonArcher_Expert_Speed = 200; public const int SkeletonArcher_Expert_Jump = 0; public const float SkeletonArcher_Expert_Cooldown = 2f; public const int SkeletonArcher_Expert_MinDropAmount = 1; public const int SkeletonArcher_Expert_MaxDropAmount = 3; public const float SkeletonArcher_Expert_DropChance = 1f; public const float SkeletonArcher_Expert_TurnSpeed = 10f; public const float SkeletonArcher_Expert_ProjectileSpeed = 1100f; public const float SkeletonArcher_Expert_AnimationDelay = 10f; public const bool SkeletonArcher_Expert_AlwaysFaceTarget = true; public const bool SkeletonArcher_Expert_CanFallOffLedges = false; public const bool SkeletonArcher_Expert_CanBeKnockedBack = true; public const bool SkeletonArcher_Expert_IsWeighted = true; public static Vector2 SkeletonArcher_Expert_KnockBack = new Vector2(0, 0); public static Vector2 SkeletonArcher_Expert_Scale = new Vector2(3.2f, 3.2f); public static Vector2 SkeletonArcher_Expert_ProjectileScale = new Vector2(1.4f, 1.4f); public static Color SkeletonArcher_Expert_Tint = new Color(150, 150, 150); public const int SkeletonArcher_Expert_MeleeRadius = 325; public const int SkeletonArcher_Expert_ProjectileRadius = 625; public const int SkeletonArcher_Expert_EngageRadius = 850; + public const string SkeletonArcher_Miniboss_Name = "Sharpshooter"; public const int SkeletonArcher_Miniboss_MaxHealth = 600; public const int SkeletonArcher_Miniboss_Damage = 40; public const int SkeletonArcher_Miniboss_XPValue = 600; public const int SkeletonArcher_Miniboss_Speed = 250; public const int SkeletonArcher_Miniboss_Jump = 0; public const float SkeletonArcher_Miniboss_Cooldown = 2f; public const int SkeletonArcher_Miniboss_MinDropAmount = 1; public const int SkeletonArcher_Miniboss_MaxDropAmount = 2; public const float SkeletonArcher_Miniboss_DropChance = 1f; public const float SkeletonArcher_Miniboss_TurnSpeed = 10f; public const float SkeletonArcher_Miniboss_ProjectileSpeed = 1000f; public const float SkeletonArcher_Miniboss_AnimationDelay = 10f; public const bool SkeletonArcher_Miniboss_AlwaysFaceTarget = true; public const bool SkeletonArcher_Miniboss_CanFallOffLedges = false; public const bool SkeletonArcher_Miniboss_CanBeKnockedBack = true; public const bool SkeletonArcher_Miniboss_IsWeighted = true; public static Vector2 SkeletonArcher_Miniboss_KnockBack = new Vector2(0, 0); public static Vector2 SkeletonArcher_Miniboss_Scale = new Vector2(2.5f, 2.5f); public static Vector2 SkeletonArcher_Miniboss_ProjectileScale = new Vector2(1.25f, 1.25f); public static Color SkeletonArcher_Miniboss_Tint = new Color(0, 0, 0); public const int SkeletonArcher_Miniboss_MeleeRadius = 325; public const int SkeletonArcher_Miniboss_ProjectileRadius = 625; public const int SkeletonArcher_Miniboss_EngageRadius = 850; + public const string LastBoss_Basic_Name = "Johannes"; public const int LastBoss_Basic_MaxHealth = 300; public const int LastBoss_Basic_Damage = 22; public const int LastBoss_Basic_XPValue = 1000; public const int LastBoss_Basic_Speed = 500; public const int LastBoss_Basic_Jump = 1050; public const float LastBoss_Basic_Cooldown = 1f; public const int LastBoss_Basic_MinDropAmount = 20; public const int LastBoss_Basic_MaxDropAmount = 30; public const float LastBoss_Basic_DropChance = 1f; public const float LastBoss_Basic_TurnSpeed = 2f; public const float LastBoss_Basic_ProjectileSpeed = 1100f; public const float LastBoss_Basic_AnimationDelay = 10f; public const bool LastBoss_Basic_AlwaysFaceTarget = false; public const bool LastBoss_Basic_CanFallOffLedges = false; public const bool LastBoss_Basic_CanBeKnockedBack = true; public const bool LastBoss_Basic_IsWeighted = true; public static Vector2 LastBoss_Basic_KnockBack = new Vector2(400, 250); public static Vector2 LastBoss_Basic_Scale = new Vector2(2.5f, 2.5f); public static Vector2 LastBoss_Basic_ProjectileScale = new Vector2(1.5f, 1.5f); public static Color LastBoss_Basic_Tint = new Color(255, 255, 255); public const int LastBoss_Basic_MeleeRadius = 300; public const int LastBoss_Basic_ProjectileRadius = 650; public const int LastBoss_Basic_EngageRadius = 900; + public const string LastBoss_Advanced_Name = "The Fountain"; public const int LastBoss_Advanced_MaxHealth = 530; public const int LastBoss_Advanced_Damage = 22; public const int LastBoss_Advanced_XPValue = 5000; public const int LastBoss_Advanced_Speed = 325; public const int LastBoss_Advanced_Jump = 1050; public const float LastBoss_Advanced_Cooldown = 1f; public const int LastBoss_Advanced_MinDropAmount = 20; public const int LastBoss_Advanced_MaxDropAmount = 30; public const float LastBoss_Advanced_DropChance = 1f; public const float LastBoss_Advanced_TurnSpeed = 2f; public const float LastBoss_Advanced_ProjectileSpeed = 1000f; public const float LastBoss_Advanced_AnimationDelay = 10f; public const bool LastBoss_Advanced_AlwaysFaceTarget = true; public const bool LastBoss_Advanced_CanFallOffLedges = false; public const bool LastBoss_Advanced_CanBeKnockedBack = false; public const bool LastBoss_Advanced_IsWeighted = true; public static Vector2 LastBoss_Advanced_KnockBack = new Vector2(150, 100); public static Vector2 LastBoss_Advanced_Scale = new Vector2(2.0f, 2.0f); public static Vector2 LastBoss_Advanced_ProjectileScale = new Vector2(2.0f, 2.0f); public static Color LastBoss_Advanced_Tint = new Color(255, 255, 255); public const int LastBoss_Advanced_MeleeRadius = 300; public const int LastBoss_Advanced_ProjectileRadius = 675; public const int LastBoss_Advanced_EngageRadius = 925; + public const string LastBoss_Expert_Name = "Johannes"; public const int LastBoss_Expert_MaxHealth = 100; public const int LastBoss_Expert_Damage = 30; public const int LastBoss_Expert_XPValue = 1000; public const int LastBoss_Expert_Speed = 550; public const int LastBoss_Expert_Jump = 1050; public const float LastBoss_Expert_Cooldown = 1f; public const int LastBoss_Expert_MinDropAmount = 20; public const int LastBoss_Expert_MaxDropAmount = 30; public const float LastBoss_Expert_DropChance = 1f; public const float LastBoss_Expert_TurnSpeed = 2f; public const float LastBoss_Expert_ProjectileSpeed = 1100f; public const float LastBoss_Expert_AnimationDelay = 10f; public const bool LastBoss_Expert_AlwaysFaceTarget = false; public const bool LastBoss_Expert_CanFallOffLedges = false; public const bool LastBoss_Expert_CanBeKnockedBack = true; public const bool LastBoss_Expert_IsWeighted = true; public static Vector2 LastBoss_Expert_KnockBack = new Vector2(350, 300); public static Vector2 LastBoss_Expert_Scale = new Vector2(2.5f, 2.5f); public static Vector2 LastBoss_Expert_ProjectileScale = new Vector2(1.5f, 1.5f); public static Color LastBoss_Expert_Tint = new Color(255, 255, 255); public const int LastBoss_Expert_MeleeRadius = 300; public const int LastBoss_Expert_ProjectileRadius = 650; public const int LastBoss_Expert_EngageRadius = 900; + public const string LastBoss_Miniboss_Name = "Fountain of Youth"; public const int LastBoss_Miniboss_MaxHealth = 100; public const int LastBoss_Miniboss_Damage = 38; public const int LastBoss_Miniboss_XPValue = 5000; public const int LastBoss_Miniboss_Speed = 125; public const int LastBoss_Miniboss_Jump = 1050; public const float LastBoss_Miniboss_Cooldown = 1f; public const int LastBoss_Miniboss_MinDropAmount = 20; public const int LastBoss_Miniboss_MaxDropAmount = 30; public const float LastBoss_Miniboss_DropChance = 1f; public const float LastBoss_Miniboss_TurnSpeed = 2f; public const float LastBoss_Miniboss_ProjectileSpeed = 1000f; public const float LastBoss_Miniboss_AnimationDelay = 10f; public const bool LastBoss_Miniboss_AlwaysFaceTarget = true; public const bool LastBoss_Miniboss_CanFallOffLedges = false; public const bool LastBoss_Miniboss_CanBeKnockedBack = false; public const bool LastBoss_Miniboss_IsWeighted = true; public static Vector2 LastBoss_Miniboss_KnockBack = new Vector2(300, 250); public static Vector2 LastBoss_Miniboss_Scale = new Vector2(2.0f, 2.0f); public static Vector2 LastBoss_Miniboss_ProjectileScale = new Vector2(2.0f, 2.0f); public static Color LastBoss_Miniboss_Tint = new Color(255, 255, 255); public const int LastBoss_Miniboss_MeleeRadius = 325; public const int LastBoss_Miniboss_ProjectileRadius = 675; public const int LastBoss_Miniboss_EngageRadius = 925; + public const string Portrait_Basic_Name = "Doomvas"; public const int Portrait_Basic_MaxHealth = 35; public const int Portrait_Basic_Damage = 21; public const int Portrait_Basic_XPValue = 50; public const int Portrait_Basic_Speed = 500; public const int Portrait_Basic_Jump = 600; public const float Portrait_Basic_Cooldown = 2f; public const int Portrait_Basic_MinDropAmount = 1; public const int Portrait_Basic_MaxDropAmount = 2; public const float Portrait_Basic_DropChance = 0.4f; public const float Portrait_Basic_TurnSpeed = 0.03f; public const float Portrait_Basic_ProjectileSpeed = 1020f; public const float Portrait_Basic_AnimationDelay = 60f; public const bool Portrait_Basic_AlwaysFaceTarget = false; public const bool Portrait_Basic_CanFallOffLedges = false; public const bool Portrait_Basic_CanBeKnockedBack = false; public const bool Portrait_Basic_IsWeighted = false; public static Vector2 Portrait_Basic_KnockBack = new Vector2(10, 10); public static Vector2 Portrait_Basic_Scale = new Vector2(2.0f, 2.0f); public static Vector2 Portrait_Basic_ProjectileScale = new Vector2(1.5f, 1.5f); public static Color Portrait_Basic_Tint = new Color(255, 255, 255); public const int Portrait_Basic_MeleeRadius = 25; public const int Portrait_Basic_ProjectileRadius = 100; public const int Portrait_Basic_EngageRadius = 300; + public const string Portrait_Advanced_Name = "Doomtrait"; public const int Portrait_Advanced_MaxHealth = 43; public const int Portrait_Advanced_Damage = 25; public const int Portrait_Advanced_XPValue = 75; public const int Portrait_Advanced_Speed = 550; public const int Portrait_Advanced_Jump = 600; public const float Portrait_Advanced_Cooldown = 2f; public const int Portrait_Advanced_MinDropAmount = 1; public const int Portrait_Advanced_MaxDropAmount = 2; public const float Portrait_Advanced_DropChance = 0.5f; public const float Portrait_Advanced_TurnSpeed = 0.0425f; public const float Portrait_Advanced_ProjectileSpeed = 400f; public const float Portrait_Advanced_AnimationDelay = 60f; public const bool Portrait_Advanced_AlwaysFaceTarget = false; public const bool Portrait_Advanced_CanFallOffLedges = false; public const bool Portrait_Advanced_CanBeKnockedBack = false; public const bool Portrait_Advanced_IsWeighted = false; public static Vector2 Portrait_Advanced_KnockBack = new Vector2(10, 10); public static Vector2 Portrait_Advanced_Scale = new Vector2(2.0f, 2.0f); public static Vector2 Portrait_Advanced_ProjectileScale = new Vector2(2.2f, 2.2f); public static Color Portrait_Advanced_Tint = new Color(255, 255, 255); public const int Portrait_Advanced_MeleeRadius = 25; public const int Portrait_Advanced_ProjectileRadius = 100; public const int Portrait_Advanced_EngageRadius = 300; + public const string Portrait_Expert_Name = "Doomscape"; public const int Portrait_Expert_MaxHealth = 61; public const int Portrait_Expert_Damage = 27; public const int Portrait_Expert_XPValue = 100; public const int Portrait_Expert_Speed = 600; public const int Portrait_Expert_Jump = 600; public const float Portrait_Expert_Cooldown = 2f; public const int Portrait_Expert_MinDropAmount = 1; public const int Portrait_Expert_MaxDropAmount = 2; public const float Portrait_Expert_DropChance = 1f; public const float Portrait_Expert_TurnSpeed = 0.03f; public const float Portrait_Expert_ProjectileSpeed = 400f; public const float Portrait_Expert_AnimationDelay = 60f; public const bool Portrait_Expert_AlwaysFaceTarget = false; public const bool Portrait_Expert_CanFallOffLedges = false; public const bool Portrait_Expert_CanBeKnockedBack = false; public const bool Portrait_Expert_IsWeighted = false; public static Vector2 Portrait_Expert_KnockBack = new Vector2(10, 10); public static Vector2 Portrait_Expert_Scale = new Vector2(2.0f, 2.0f); public static Vector2 Portrait_Expert_ProjectileScale = new Vector2(2.2f, 2.2f); public static Color Portrait_Expert_Tint = new Color(255, 255, 255); public const int Portrait_Expert_MeleeRadius = 25; public const int Portrait_Expert_ProjectileRadius = 100; public const int Portrait_Expert_EngageRadius = 300; + public const string Portrait_Miniboss_Name = "Sallos"; public const int Portrait_Miniboss_MaxHealth = 215; public const int Portrait_Miniboss_Damage = 28; public const int Portrait_Miniboss_XPValue = 1000; public const int Portrait_Miniboss_Speed = 515; public const int Portrait_Miniboss_Jump = 600; public const float Portrait_Miniboss_Cooldown = 2f; public const int Portrait_Miniboss_MinDropAmount = 11; public const int Portrait_Miniboss_MaxDropAmount = 15; public const float Portrait_Miniboss_DropChance = 1f; public const float Portrait_Miniboss_TurnSpeed = 0.03f; public const float Portrait_Miniboss_ProjectileSpeed = 250f; public const float Portrait_Miniboss_AnimationDelay = 60f; public const bool Portrait_Miniboss_AlwaysFaceTarget = false; public const bool Portrait_Miniboss_CanFallOffLedges = false; public const bool Portrait_Miniboss_CanBeKnockedBack = false; public const bool Portrait_Miniboss_IsWeighted = false; public static Vector2 Portrait_Miniboss_KnockBack = new Vector2(10, 10); public static Vector2 Portrait_Miniboss_Scale = new Vector2(5.0f, 5.0f); public static Vector2 Portrait_Miniboss_ProjectileScale = new Vector2(2.75f, 2.75f); public static Color Portrait_Miniboss_Tint = new Color(255, 255, 255); public const int Portrait_Miniboss_MeleeRadius = 25; public const int Portrait_Miniboss_ProjectileRadius = 100; public const int Portrait_Miniboss_EngageRadius = 300; + public const string Starburst_Basic_Name = "Plinky"; public const int Starburst_Basic_MaxHealth = 18; public const int Starburst_Basic_Damage = 15; public const int Starburst_Basic_XPValue = 50; public const int Starburst_Basic_Speed = 435; public const int Starburst_Basic_Jump = 950; public const float Starburst_Basic_Cooldown = 0f; public const int Starburst_Basic_MinDropAmount = 1; public const int Starburst_Basic_MaxDropAmount = 1; public const float Starburst_Basic_DropChance = 0.4f; public const float Starburst_Basic_TurnSpeed = 10f; public const float Starburst_Basic_ProjectileSpeed = 435f; public const float Starburst_Basic_AnimationDelay = 20f; public const bool Starburst_Basic_AlwaysFaceTarget = false; public const bool Starburst_Basic_CanFallOffLedges = false; public const bool Starburst_Basic_CanBeKnockedBack = false; public const bool Starburst_Basic_IsWeighted = false; public static Vector2 Starburst_Basic_KnockBack = new Vector2(0, 0); public static Vector2 Starburst_Basic_Scale = new Vector2(2.25f, 2.25f); public static Vector2 Starburst_Basic_ProjectileScale = new Vector2(1.1f, 1.1f); public static Color Starburst_Basic_Tint = new Color(255, 255, 255); public const int Starburst_Basic_MeleeRadius = 325; public const int Starburst_Basic_ProjectileRadius = 690; public const int Starburst_Basic_EngageRadius = 850; + public const string Starburst_Advanced_Name = "Planky"; public const int Starburst_Advanced_MaxHealth = 25; public const int Starburst_Advanced_Damage = 18; public const int Starburst_Advanced_XPValue = 75; public const int Starburst_Advanced_Speed = 435; public const int Starburst_Advanced_Jump = 950; public const float Starburst_Advanced_Cooldown = 0f; public const int Starburst_Advanced_MinDropAmount = 1; public const int Starburst_Advanced_MaxDropAmount = 2; public const float Starburst_Advanced_DropChance = 0.5f; public const float Starburst_Advanced_TurnSpeed = 10f; public const float Starburst_Advanced_ProjectileSpeed = 435f; public const float Starburst_Advanced_AnimationDelay = 20f; public const bool Starburst_Advanced_AlwaysFaceTarget = false; public const bool Starburst_Advanced_CanFallOffLedges = false; public const bool Starburst_Advanced_CanBeKnockedBack = false; public const bool Starburst_Advanced_IsWeighted = false; public static Vector2 Starburst_Advanced_KnockBack = new Vector2(0, 0); public static Vector2 Starburst_Advanced_Scale = new Vector2(2.75f, 2.75f); public static Vector2 Starburst_Advanced_ProjectileScale = new Vector2(1.3f, 1.3f); public static Color Starburst_Advanced_Tint = new Color(190, 95, 95); public const int Starburst_Advanced_MeleeRadius = 325; public const int Starburst_Advanced_ProjectileRadius = 690; public const int Starburst_Advanced_EngageRadius = 850; + public const string Starburst_Expert_Name = "Plonky"; public const int Starburst_Expert_MaxHealth = 42; public const int Starburst_Expert_Damage = 21; public const int Starburst_Expert_XPValue = 125; public const int Starburst_Expert_Speed = 435; public const int Starburst_Expert_Jump = 950; public const float Starburst_Expert_Cooldown = 0f; public const int Starburst_Expert_MinDropAmount = 1; public const int Starburst_Expert_MaxDropAmount = 3; public const float Starburst_Expert_DropChance = 1f; public const float Starburst_Expert_TurnSpeed = 10f; public const float Starburst_Expert_ProjectileSpeed = 435f; public const float Starburst_Expert_AnimationDelay = 20f; public const bool Starburst_Expert_AlwaysFaceTarget = false; public const bool Starburst_Expert_CanFallOffLedges = false; public const bool Starburst_Expert_CanBeKnockedBack = false; public const bool Starburst_Expert_IsWeighted = false; public static Vector2 Starburst_Expert_KnockBack = new Vector2(0, 0); public static Vector2 Starburst_Expert_Scale = new Vector2(3.25f, 3.25f); public static Vector2 Starburst_Expert_ProjectileScale = new Vector2(1.6f, 1.6f); public static Color Starburst_Expert_Tint = new Color(0, 255, 0); public const int Starburst_Expert_MeleeRadius = 325; public const int Starburst_Expert_ProjectileRadius = 690; public const int Starburst_Expert_EngageRadius = 850; + public const string Starburst_Miniboss_Name = "Ploo"; public const int Starburst_Miniboss_MaxHealth = 750; public const int Starburst_Miniboss_Damage = 30; public const int Starburst_Miniboss_XPValue = 1100; public const int Starburst_Miniboss_Speed = 435; public const int Starburst_Miniboss_Jump = 1350; public const float Starburst_Miniboss_Cooldown = 0f; public const int Starburst_Miniboss_MinDropAmount = 8; public const int Starburst_Miniboss_MaxDropAmount = 16; public const float Starburst_Miniboss_DropChance = 1f; public const float Starburst_Miniboss_TurnSpeed = 10f; public const float Starburst_Miniboss_ProjectileSpeed = 370f; public const float Starburst_Miniboss_AnimationDelay = 20f; public const bool Starburst_Miniboss_AlwaysFaceTarget = false; public const bool Starburst_Miniboss_CanFallOffLedges = false; public const bool Starburst_Miniboss_CanBeKnockedBack = false; public const bool Starburst_Miniboss_IsWeighted = false; public static Vector2 Starburst_Miniboss_KnockBack = new Vector2(0, 0); public static Vector2 Starburst_Miniboss_Scale = new Vector2(4.0f, 4.0f); public static Vector2 Starburst_Miniboss_ProjectileScale = new Vector2(2.5f, 2.5f); public static Color Starburst_Miniboss_Tint = new Color(255, 255, 255); public const int Starburst_Miniboss_MeleeRadius = 325; public const int Starburst_Miniboss_ProjectileRadius = 690; public const int Starburst_Miniboss_EngageRadius = 850; + public const string Chicken_Basic_Name = "Kentucky"; public const int Chicken_Basic_MaxHealth = 1; public const int Chicken_Basic_Damage = 8; public const int Chicken_Basic_XPValue = 100; public const int Chicken_Basic_Speed = 350; public const int Chicken_Basic_Jump = 950; public const float Chicken_Basic_Cooldown = 2f; public const int Chicken_Basic_MinDropAmount = 1; public const int Chicken_Basic_MaxDropAmount = 1; public const float Chicken_Basic_DropChance = 0f; public const float Chicken_Basic_TurnSpeed = 10f; public const float Chicken_Basic_ProjectileSpeed = 850f; public const float Chicken_Basic_AnimationDelay = 30f; public const bool Chicken_Basic_AlwaysFaceTarget = false; public const bool Chicken_Basic_CanFallOffLedges = true; public const bool Chicken_Basic_CanBeKnockedBack = true; public const bool Chicken_Basic_IsWeighted = false; public static Vector2 Chicken_Basic_KnockBack = new Vector2(500, 350); public static Vector2 Chicken_Basic_Scale = new Vector2(2.0f, 2.0f); public static Vector2 Chicken_Basic_ProjectileScale = new Vector2(1.25f, 1.25f); public static Color Chicken_Basic_Tint = new Color(255, 255, 255); public const int Chicken_Basic_MeleeRadius = 10; public const int Chicken_Basic_ProjectileRadius = 20; public const int Chicken_Basic_EngageRadius = 30; + public const string Chicken_Advanced_Name = "Fried"; public const int Chicken_Advanced_MaxHealth = 1; public const int Chicken_Advanced_Damage = 11; public const int Chicken_Advanced_XPValue = 175; public const int Chicken_Advanced_Speed = 375; public const int Chicken_Advanced_Jump = 950; public const float Chicken_Advanced_Cooldown = 2f; public const int Chicken_Advanced_MinDropAmount = 1; public const int Chicken_Advanced_MaxDropAmount = 1; public const float Chicken_Advanced_DropChance = 0f; public const float Chicken_Advanced_TurnSpeed = 10f; public const float Chicken_Advanced_ProjectileSpeed = 850f; public const float Chicken_Advanced_AnimationDelay = 30f; public const bool Chicken_Advanced_AlwaysFaceTarget = false; public const bool Chicken_Advanced_CanFallOffLedges = true; public const bool Chicken_Advanced_CanBeKnockedBack = true; public const bool Chicken_Advanced_IsWeighted = false; public static Vector2 Chicken_Advanced_KnockBack = new Vector2(500, 350); public static Vector2 Chicken_Advanced_Scale = new Vector2(2.0f, 2.0f); public static Vector2 Chicken_Advanced_ProjectileScale = new Vector2(1.35f, 1.35f); public static Color Chicken_Advanced_Tint = new Color(255, 255, 255); public const int Chicken_Advanced_MeleeRadius = 10; public const int Chicken_Advanced_ProjectileRadius = 20; public const int Chicken_Advanced_EngageRadius = 30; + public const string Chicken_Expert_Name = "Chicken"; public const int Chicken_Expert_MaxHealth = 1; public const int Chicken_Expert_Damage = 14; public const int Chicken_Expert_XPValue = 350; public const int Chicken_Expert_Speed = 400; public const int Chicken_Expert_Jump = 950; public const float Chicken_Expert_Cooldown = 2f; public const int Chicken_Expert_MinDropAmount = 1; public const int Chicken_Expert_MaxDropAmount = 2; public const float Chicken_Expert_DropChance = 0f; public const float Chicken_Expert_TurnSpeed = 10f; public const float Chicken_Expert_ProjectileSpeed = 850f; public const float Chicken_Expert_AnimationDelay = 30f; public const bool Chicken_Expert_AlwaysFaceTarget = false; public const bool Chicken_Expert_CanFallOffLedges = true; public const bool Chicken_Expert_CanBeKnockedBack = true; public const bool Chicken_Expert_IsWeighted = false; public static Vector2 Chicken_Expert_KnockBack = new Vector2(500, 350); public static Vector2 Chicken_Expert_Scale = new Vector2(2.0f, 2.0f); public static Vector2 Chicken_Expert_ProjectileScale = new Vector2(1.5f, 1.5f); public static Color Chicken_Expert_Tint = new Color(255, 255, 255); public const int Chicken_Expert_MeleeRadius = 10; public const int Chicken_Expert_ProjectileRadius = 20; public const int Chicken_Expert_EngageRadius = 30; + public const string Chicken_Miniboss_Name = "Delicious"; public const int Chicken_Miniboss_MaxHealth = 1; public const int Chicken_Miniboss_Damage = 35; public const int Chicken_Miniboss_XPValue = 800; public const int Chicken_Miniboss_Speed = 750; public const int Chicken_Miniboss_Jump = 950; public const float Chicken_Miniboss_Cooldown = 2f; public const int Chicken_Miniboss_MinDropAmount = 2; public const int Chicken_Miniboss_MaxDropAmount = 5; public const float Chicken_Miniboss_DropChance = 0f; public const float Chicken_Miniboss_TurnSpeed = 10f; public const float Chicken_Miniboss_ProjectileSpeed = 850f; public const float Chicken_Miniboss_AnimationDelay = 30f; public const bool Chicken_Miniboss_AlwaysFaceTarget = false; public const bool Chicken_Miniboss_CanFallOffLedges = true; public const bool Chicken_Miniboss_CanBeKnockedBack = true; public const bool Chicken_Miniboss_IsWeighted = false; public static Vector2 Chicken_Miniboss_KnockBack = new Vector2(500, 350); public static Vector2 Chicken_Miniboss_Scale = new Vector2(8.0f, 8.0f); public static Vector2 Chicken_Miniboss_ProjectileScale = new Vector2(1.25f, 1.25f); public static Color Chicken_Miniboss_Tint = new Color(255, 125, 125); public const int Chicken_Miniboss_MeleeRadius = 10; public const int Chicken_Miniboss_ProjectileRadius = 20; public const int Chicken_Miniboss_EngageRadius = 30; + public const string HomingTurret_Basic_Name = "GuardBox"; public const int HomingTurret_Basic_MaxHealth = 18; public const int HomingTurret_Basic_Damage = 20; public const int HomingTurret_Basic_XPValue = 75; public const int HomingTurret_Basic_Speed = 0; public const int HomingTurret_Basic_Jump = 1035; public const float HomingTurret_Basic_Cooldown = 2f; public const int HomingTurret_Basic_MinDropAmount = 1; public const int HomingTurret_Basic_MaxDropAmount = 1; public const float HomingTurret_Basic_DropChance = 0.4f; public const float HomingTurret_Basic_TurnSpeed = 10f; public const float HomingTurret_Basic_ProjectileSpeed = 775f; public const float HomingTurret_Basic_AnimationDelay = 10f; public const bool HomingTurret_Basic_AlwaysFaceTarget = true; public const bool HomingTurret_Basic_CanFallOffLedges = false; public const bool HomingTurret_Basic_CanBeKnockedBack = true; public const bool HomingTurret_Basic_IsWeighted = true; public static Vector2 HomingTurret_Basic_KnockBack = new Vector2(125, 125); public static Vector2 HomingTurret_Basic_Scale = new Vector2(2.0f, 2.0f); public static Vector2 HomingTurret_Basic_ProjectileScale = new Vector2(1.0f, 1.0f); public static Color HomingTurret_Basic_Tint = new Color(255, 255, 255); public const int HomingTurret_Basic_MeleeRadius = 10; public const int HomingTurret_Basic_ProjectileRadius = 20; public const int HomingTurret_Basic_EngageRadius = 975; + public const string HomingTurret_Advanced_Name = "GuardBox XL"; public const int HomingTurret_Advanced_MaxHealth = 25; public const int HomingTurret_Advanced_Damage = 26; public const int HomingTurret_Advanced_XPValue = 125; public const int HomingTurret_Advanced_Speed = 0; public const int HomingTurret_Advanced_Jump = 1035; public const float HomingTurret_Advanced_Cooldown = 2f; public const int HomingTurret_Advanced_MinDropAmount = 1; public const int HomingTurret_Advanced_MaxDropAmount = 2; public const float HomingTurret_Advanced_DropChance = 0.5f; public const float HomingTurret_Advanced_TurnSpeed = 10f; public const float HomingTurret_Advanced_ProjectileSpeed = 1100f; public const float HomingTurret_Advanced_AnimationDelay = 10f; public const bool HomingTurret_Advanced_AlwaysFaceTarget = true; public const bool HomingTurret_Advanced_CanFallOffLedges = false; public const bool HomingTurret_Advanced_CanBeKnockedBack = true; public const bool HomingTurret_Advanced_IsWeighted = true; public static Vector2 HomingTurret_Advanced_KnockBack = new Vector2(125, 125); public static Vector2 HomingTurret_Advanced_Scale = new Vector2(2.5f, 2.5f); public static Vector2 HomingTurret_Advanced_ProjectileScale = new Vector2(1.25f, 1.25f); public static Color HomingTurret_Advanced_Tint = new Color(200, 200, 200); public const int HomingTurret_Advanced_MeleeRadius = 10; public const int HomingTurret_Advanced_ProjectileRadius = 20; public const int HomingTurret_Advanced_EngageRadius = 975; + public const string HomingTurret_Expert_Name = "GuardBox 2000"; public const int HomingTurret_Expert_MaxHealth = 42; public const int HomingTurret_Expert_Damage = 30; public const int HomingTurret_Expert_XPValue = 225; public const int HomingTurret_Expert_Speed = 0; public const int HomingTurret_Expert_Jump = 1035; public const float HomingTurret_Expert_Cooldown = 2f; public const int HomingTurret_Expert_MinDropAmount = 1; public const int HomingTurret_Expert_MaxDropAmount = 3; public const float HomingTurret_Expert_DropChance = 1f; public const float HomingTurret_Expert_TurnSpeed = 10f; public const float HomingTurret_Expert_ProjectileSpeed = 925f; public const float HomingTurret_Expert_AnimationDelay = 10f; public const bool HomingTurret_Expert_AlwaysFaceTarget = true; public const bool HomingTurret_Expert_CanFallOffLedges = false; public const bool HomingTurret_Expert_CanBeKnockedBack = true; public const bool HomingTurret_Expert_IsWeighted = true; public static Vector2 HomingTurret_Expert_KnockBack = new Vector2(125, 125); public static Vector2 HomingTurret_Expert_Scale = new Vector2(2.75f, 2.75f); public static Vector2 HomingTurret_Expert_ProjectileScale = new Vector2(1.5f, 1.5f); public static Color HomingTurret_Expert_Tint = new Color(150, 150, 150); public const int HomingTurret_Expert_MeleeRadius = 10; public const int HomingTurret_Expert_ProjectileRadius = 20; public const int HomingTurret_Expert_EngageRadius = 975; + public const string HomingTurret_Miniboss_Name = "GuardBox Gigasaur"; public const int HomingTurret_Miniboss_MaxHealth = 500; public const int HomingTurret_Miniboss_Damage = 40; public const int HomingTurret_Miniboss_XPValue = 750; public const int HomingTurret_Miniboss_Speed = 0; public const int HomingTurret_Miniboss_Jump = 1035; public const float HomingTurret_Miniboss_Cooldown = 2f; public const int HomingTurret_Miniboss_MinDropAmount = 1; public const int HomingTurret_Miniboss_MaxDropAmount = 4; public const float HomingTurret_Miniboss_DropChance = 1f; public const float HomingTurret_Miniboss_TurnSpeed = 10f; public const float HomingTurret_Miniboss_ProjectileSpeed = 900f; public const float HomingTurret_Miniboss_AnimationDelay = 10f; public const bool HomingTurret_Miniboss_AlwaysFaceTarget = true; public const bool HomingTurret_Miniboss_CanFallOffLedges = false; public const bool HomingTurret_Miniboss_CanBeKnockedBack = true; public const bool HomingTurret_Miniboss_IsWeighted = true; public static Vector2 HomingTurret_Miniboss_KnockBack = new Vector2(125, 125); public static Vector2 HomingTurret_Miniboss_Scale = new Vector2(3.0f, 3.0f); public static Vector2 HomingTurret_Miniboss_ProjectileScale = new Vector2(2f, 2f); public static Color HomingTurret_Miniboss_Tint = new Color(155, 30, 0); public const int HomingTurret_Miniboss_MeleeRadius = 10; public const int HomingTurret_Miniboss_ProjectileRadius = 20; public const int HomingTurret_Miniboss_EngageRadius = 975; + public const string Horse_Basic_Name = "Headless Horse"; public const int Horse_Basic_MaxHealth = 30; public const int Horse_Basic_Damage = 23; public const int Horse_Basic_XPValue = 25; public const int Horse_Basic_Speed = 425; public const int Horse_Basic_Jump = 900; public const float Horse_Basic_Cooldown = 2f; public const int Horse_Basic_MinDropAmount = 1; public const int Horse_Basic_MaxDropAmount = 2; public const float Horse_Basic_DropChance = 0.4f; public const float Horse_Basic_TurnSpeed = 10f; public const float Horse_Basic_ProjectileSpeed = 0f; public const float Horse_Basic_AnimationDelay = 15f; public const bool Horse_Basic_AlwaysFaceTarget = false; public const bool Horse_Basic_CanFallOffLedges = false; public const bool Horse_Basic_CanBeKnockedBack = false; public const bool Horse_Basic_IsWeighted = true; public static Vector2 Horse_Basic_KnockBack = new Vector2(100, 100); public static Vector2 Horse_Basic_Scale = new Vector2(1.6f, 1.6f); public static Vector2 Horse_Basic_ProjectileScale = new Vector2(1.0f, 1.0f); public static Color Horse_Basic_Tint = new Color(255, 255, 255); public const int Horse_Basic_MeleeRadius = 700; public const int Horse_Basic_ProjectileRadius = 1800; public const int Horse_Basic_EngageRadius = 2100; + public const string Horse_Advanced_Name = "Dark Stallion"; public const int Horse_Advanced_MaxHealth = 37; public const int Horse_Advanced_Damage = 27; public const int Horse_Advanced_XPValue = 75; public const int Horse_Advanced_Speed = 500; public const int Horse_Advanced_Jump = 900; public const float Horse_Advanced_Cooldown = 2f; public const int Horse_Advanced_MinDropAmount = 1; public const int Horse_Advanced_MaxDropAmount = 2; public const float Horse_Advanced_DropChance = 0.5f; public const float Horse_Advanced_TurnSpeed = 10f; public const float Horse_Advanced_ProjectileSpeed = 0f; public const float Horse_Advanced_AnimationDelay = 15f; public const bool Horse_Advanced_AlwaysFaceTarget = false; public const bool Horse_Advanced_CanFallOffLedges = false; public const bool Horse_Advanced_CanBeKnockedBack = false; public const bool Horse_Advanced_IsWeighted = true; public static Vector2 Horse_Advanced_KnockBack = new Vector2(100, 100); public static Vector2 Horse_Advanced_Scale = new Vector2(2.2f, 2.2f); public static Vector2 Horse_Advanced_ProjectileScale = new Vector2(2.0f, 2.0f); public static Color Horse_Advanced_Tint = new Color(250, 180, 20); public const int Horse_Advanced_MeleeRadius = 700; public const int Horse_Advanced_ProjectileRadius = 1800; public const int Horse_Advanced_EngageRadius = 2100; + public const string Horse_Expert_Name = "Night Mare"; public const int Horse_Expert_MaxHealth = 60; public const int Horse_Expert_Damage = 30; public const int Horse_Expert_XPValue = 200; public const int Horse_Expert_Speed = 550; public const int Horse_Expert_Jump = 900; public const float Horse_Expert_Cooldown = 2f; public const int Horse_Expert_MinDropAmount = 2; public const int Horse_Expert_MaxDropAmount = 3; public const float Horse_Expert_DropChance = 1f; public const float Horse_Expert_TurnSpeed = 10f; public const float Horse_Expert_ProjectileSpeed = 0f; public const float Horse_Expert_AnimationDelay = 15f; public const bool Horse_Expert_AlwaysFaceTarget = false; public const bool Horse_Expert_CanFallOffLedges = false; public const bool Horse_Expert_CanBeKnockedBack = false; public const bool Horse_Expert_IsWeighted = true; public static Vector2 Horse_Expert_KnockBack = new Vector2(100, 100); public static Vector2 Horse_Expert_Scale = new Vector2(2.6f, 2.6f); public static Vector2 Horse_Expert_ProjectileScale = new Vector2(2.25f, 2.25f); public static Color Horse_Expert_Tint = new Color(215, 20, 20); public const int Horse_Expert_MeleeRadius = 700; public const int Horse_Expert_ProjectileRadius = 1800; public const int Horse_Expert_EngageRadius = 2100; + public const string Horse_Miniboss_Name = "My Little Pony"; public const int Horse_Miniboss_MaxHealth = 800; public const int Horse_Miniboss_Damage = 40; public const int Horse_Miniboss_XPValue = 600; public const int Horse_Miniboss_Speed = 900; public const int Horse_Miniboss_Jump = 900; public const float Horse_Miniboss_Cooldown = 2f; public const int Horse_Miniboss_MinDropAmount = 10; public const int Horse_Miniboss_MaxDropAmount = 15; public const float Horse_Miniboss_DropChance = 1f; public const float Horse_Miniboss_TurnSpeed = 10f; public const float Horse_Miniboss_ProjectileSpeed = 0f; public const float Horse_Miniboss_AnimationDelay = 15f; public const bool Horse_Miniboss_AlwaysFaceTarget = false; public const bool Horse_Miniboss_CanFallOffLedges = false; public const bool Horse_Miniboss_CanBeKnockedBack = false; public const bool Horse_Miniboss_IsWeighted = true; public static Vector2 Horse_Miniboss_KnockBack = new Vector2(100, 100); public static Vector2 Horse_Miniboss_Scale = new Vector2(3.4f, 3.4f); public static Vector2 Horse_Miniboss_ProjectileScale = new Vector2(1.0f, 1.0f); public static Color Horse_Miniboss_Tint = new Color(0, 0, 0); public const int Horse_Miniboss_MeleeRadius = 700; public const int Horse_Miniboss_ProjectileRadius = 1800; public const int Horse_Miniboss_EngageRadius = 2100; + public const string Spark_Basic_Name = "Sparky"; public const int Spark_Basic_MaxHealth = 20; public const int Spark_Basic_Damage = 20; public const int Spark_Basic_XPValue = 100; public const int Spark_Basic_Speed = 200; public const int Spark_Basic_Jump = 500; public const float Spark_Basic_Cooldown = 2f; public const int Spark_Basic_MinDropAmount = 1; public const int Spark_Basic_MaxDropAmount = 2; public const float Spark_Basic_DropChance = 0.4f; public const float Spark_Basic_TurnSpeed = 0.0275f; public const float Spark_Basic_ProjectileSpeed = 525f; public const float Spark_Basic_AnimationDelay = 10f; public const bool Spark_Basic_AlwaysFaceTarget = false; public const bool Spark_Basic_CanFallOffLedges = false; public const bool Spark_Basic_CanBeKnockedBack = false; public const bool Spark_Basic_IsWeighted = false; public static Vector2 Spark_Basic_KnockBack = new Vector2(300, 250); public static Vector2 Spark_Basic_Scale = new Vector2(2.0f, 2.0f); public static Vector2 Spark_Basic_ProjectileScale = new Vector2(1.0f, 1.0f); public static Color Spark_Basic_Tint = new Color(255, 255, 255); public const int Spark_Basic_MeleeRadius = 10; public const int Spark_Basic_ProjectileRadius = 20; public const int Spark_Basic_EngageRadius = 30; + public const string Spark_Advanced_Name = "Mr. Spark"; public const int Spark_Advanced_MaxHealth = 20; public const int Spark_Advanced_Damage = 28; public const int Spark_Advanced_XPValue = 175; public const int Spark_Advanced_Speed = 300; public const int Spark_Advanced_Jump = 500; public const float Spark_Advanced_Cooldown = 2f; public const int Spark_Advanced_MinDropAmount = 1; public const int Spark_Advanced_MaxDropAmount = 2; public const float Spark_Advanced_DropChance = 0.5f; public const float Spark_Advanced_TurnSpeed = 0.03f; public const float Spark_Advanced_ProjectileSpeed = 525f; public const float Spark_Advanced_AnimationDelay = 10f; public const bool Spark_Advanced_AlwaysFaceTarget = false; public const bool Spark_Advanced_CanFallOffLedges = false; public const bool Spark_Advanced_CanBeKnockedBack = false; public const bool Spark_Advanced_IsWeighted = false; public static Vector2 Spark_Advanced_KnockBack = new Vector2(300, 250); public static Vector2 Spark_Advanced_Scale = new Vector2(2.5f, 2.5f); public static Vector2 Spark_Advanced_ProjectileScale = new Vector2(1.25f, 1.25f); public static Color Spark_Advanced_Tint = new Color(125, 150, 175); public const int Spark_Advanced_MeleeRadius = 10; public const int Spark_Advanced_ProjectileRadius = 20; public const int Spark_Advanced_EngageRadius = 30; + public const string Spark_Expert_Name = "Grandpa Spark"; public const int Spark_Expert_MaxHealth = 20; public const int Spark_Expert_Damage = 32; public const int Spark_Expert_XPValue = 350; public const int Spark_Expert_Speed = 375; public const int Spark_Expert_Jump = 500; public const float Spark_Expert_Cooldown = 2f; public const int Spark_Expert_MinDropAmount = 2; public const int Spark_Expert_MaxDropAmount = 3; public const float Spark_Expert_DropChance = 1f; public const float Spark_Expert_TurnSpeed = 0.03f; public const float Spark_Expert_ProjectileSpeed = 525f; public const float Spark_Expert_AnimationDelay = 10f; public const bool Spark_Expert_AlwaysFaceTarget = false; public const bool Spark_Expert_CanFallOffLedges = false; public const bool Spark_Expert_CanBeKnockedBack = false; public const bool Spark_Expert_IsWeighted = false; public static Vector2 Spark_Expert_KnockBack = new Vector2(300, 250); public static Vector2 Spark_Expert_Scale = new Vector2(3.0f, 3.0f); public static Vector2 Spark_Expert_ProjectileScale = new Vector2(1.5f, 1.5f); public static Color Spark_Expert_Tint = new Color(255, 0, 0); public const int Spark_Expert_MeleeRadius = 10; public const int Spark_Expert_ProjectileRadius = 20; public const int Spark_Expert_EngageRadius = 30; + public const string Spark_Miniboss_Name = "Lord Spark, King of Sparkatonia"; public const int Spark_Miniboss_MaxHealth = 500; public const int Spark_Miniboss_Damage = 45; public const int Spark_Miniboss_XPValue = 800; public const int Spark_Miniboss_Speed = 380; public const int Spark_Miniboss_Jump = 500; public const float Spark_Miniboss_Cooldown = 2f; public const int Spark_Miniboss_MinDropAmount = 6; public const int Spark_Miniboss_MaxDropAmount = 10; public const float Spark_Miniboss_DropChance = 1f; public const float Spark_Miniboss_TurnSpeed = 0.03f; public const float Spark_Miniboss_ProjectileSpeed = 0f; public const float Spark_Miniboss_AnimationDelay = 10f; public const bool Spark_Miniboss_AlwaysFaceTarget = false; public const bool Spark_Miniboss_CanFallOffLedges = false; public const bool Spark_Miniboss_CanBeKnockedBack = false; public const bool Spark_Miniboss_IsWeighted = false; public static Vector2 Spark_Miniboss_KnockBack = new Vector2(300, 250); public static Vector2 Spark_Miniboss_Scale = new Vector2(3.5f, 3.5f); public static Vector2 Spark_Miniboss_ProjectileScale = new Vector2(2.5f, 2.5f); public static Color Spark_Miniboss_Tint = new Color(0, 0, 0); public const int Spark_Miniboss_MeleeRadius = 10; public const int Spark_Miniboss_ProjectileRadius = 20; public const int Spark_Miniboss_EngageRadius = 30; + public const string Mimic_Basic_Name = "Mimic"; public const int Mimic_Basic_MaxHealth = 35; public const int Mimic_Basic_Damage = 20; public const int Mimic_Basic_XPValue = 75; public const int Mimic_Basic_Speed = 400; public const int Mimic_Basic_Jump = 550; public const float Mimic_Basic_Cooldown = 2f; public const int Mimic_Basic_MinDropAmount = 1; public const int Mimic_Basic_MaxDropAmount = 1; public const float Mimic_Basic_DropChance = 0.4f; public const float Mimic_Basic_TurnSpeed = 10f; public const float Mimic_Basic_ProjectileSpeed = 775f; public const float Mimic_Basic_AnimationDelay = 20f; public const bool Mimic_Basic_AlwaysFaceTarget = true; public const bool Mimic_Basic_CanFallOffLedges = true; public const bool Mimic_Basic_CanBeKnockedBack = true; public const bool Mimic_Basic_IsWeighted = true; public static Vector2 Mimic_Basic_KnockBack = new Vector2(250, 200); public static Vector2 Mimic_Basic_Scale = new Vector2(2.0f, 2.0f); public static Vector2 Mimic_Basic_ProjectileScale = new Vector2(1.0f, 1.0f); public static Color Mimic_Basic_Tint = new Color(255, 255, 255); public const int Mimic_Basic_MeleeRadius = 10; public const int Mimic_Basic_ProjectileRadius = 20; public const int Mimic_Basic_EngageRadius = 975; + public const string Mimic_Advanced_Name = "Mimicant"; public const int Mimic_Advanced_MaxHealth = 40; public const int Mimic_Advanced_Damage = 23; public const int Mimic_Advanced_XPValue = 125; public const int Mimic_Advanced_Speed = 600; public const int Mimic_Advanced_Jump = 650; public const float Mimic_Advanced_Cooldown = 2f; public const int Mimic_Advanced_MinDropAmount = 1; public const int Mimic_Advanced_MaxDropAmount = 2; public const float Mimic_Advanced_DropChance = 0.5f; public const float Mimic_Advanced_TurnSpeed = 10f; public const float Mimic_Advanced_ProjectileSpeed = 1100f; public const float Mimic_Advanced_AnimationDelay = 20f; public const bool Mimic_Advanced_AlwaysFaceTarget = true; public const bool Mimic_Advanced_CanFallOffLedges = true; public const bool Mimic_Advanced_CanBeKnockedBack = true; public const bool Mimic_Advanced_IsWeighted = true; public static Vector2 Mimic_Advanced_KnockBack = new Vector2(250, 200); public static Vector2 Mimic_Advanced_Scale = new Vector2(2.0f, 2.0f); public static Vector2 Mimic_Advanced_ProjectileScale = new Vector2(1.25f, 1.25f); public static Color Mimic_Advanced_Tint = new Color(255, 255, 255); public const int Mimic_Advanced_MeleeRadius = 10; public const int Mimic_Advanced_ProjectileRadius = 20; public const int Mimic_Advanced_EngageRadius = 975; + public const string Mimic_Expert_Name = "Mimicrunch"; public const int Mimic_Expert_MaxHealth = 70; public const int Mimic_Expert_Damage = 25; public const int Mimic_Expert_XPValue = 225; public const int Mimic_Expert_Speed = 750; public const int Mimic_Expert_Jump = 550; public const float Mimic_Expert_Cooldown = 2f; public const int Mimic_Expert_MinDropAmount = 2; public const int Mimic_Expert_MaxDropAmount = 3; public const float Mimic_Expert_DropChance = 1f; public const float Mimic_Expert_TurnSpeed = 10f; public const float Mimic_Expert_ProjectileSpeed = 925f; public const float Mimic_Expert_AnimationDelay = 20f; public const bool Mimic_Expert_AlwaysFaceTarget = true; public const bool Mimic_Expert_CanFallOffLedges = true; public const bool Mimic_Expert_CanBeKnockedBack = true; public const bool Mimic_Expert_IsWeighted = true; public static Vector2 Mimic_Expert_KnockBack = new Vector2(250, 200); public static Vector2 Mimic_Expert_Scale = new Vector2(2.0f, 2.0f); public static Vector2 Mimic_Expert_ProjectileScale = new Vector2(1.5f, 1.5f); public static Color Mimic_Expert_Tint = new Color(255, 255, 255); public const int Mimic_Expert_MeleeRadius = 10; public const int Mimic_Expert_ProjectileRadius = 20; public const int Mimic_Expert_EngageRadius = 975; + public const string Mimic_Miniboss_Name = "Chesticles"; public const int Mimic_Miniboss_MaxHealth = 100; public const int Mimic_Miniboss_Damage = 32; public const int Mimic_Miniboss_XPValue = 750; public const int Mimic_Miniboss_Speed = 0; public const int Mimic_Miniboss_Jump = 750; public const float Mimic_Miniboss_Cooldown = 2f; public const int Mimic_Miniboss_MinDropAmount = 1; public const int Mimic_Miniboss_MaxDropAmount = 4; public const float Mimic_Miniboss_DropChance = 1f; public const float Mimic_Miniboss_TurnSpeed = 10f; public const float Mimic_Miniboss_ProjectileSpeed = 900f; public const float Mimic_Miniboss_AnimationDelay = 20f; public const bool Mimic_Miniboss_AlwaysFaceTarget = true; public const bool Mimic_Miniboss_CanFallOffLedges = true; public const bool Mimic_Miniboss_CanBeKnockedBack = true; public const bool Mimic_Miniboss_IsWeighted = true; public static Vector2 Mimic_Miniboss_KnockBack = new Vector2(250, 200); public static Vector2 Mimic_Miniboss_Scale = new Vector2(2.0f, 2.0f); public static Vector2 Mimic_Miniboss_ProjectileScale = new Vector2(2f, 2f); public static Color Mimic_Miniboss_Tint = new Color(255, 255, 255); public const int Mimic_Miniboss_MeleeRadius = 10; public const int Mimic_Miniboss_ProjectileRadius = 20; public const int Mimic_Miniboss_EngageRadius = 975; + + // Loc string IDs + public const string Skeleton_Basic_Name_locID = "LOC_ID_ENEMY_NAME_1"; + public const string Skeleton_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_2"; + public const string Skeleton_Expert_Name_locID = "LOC_ID_ENEMY_NAME_3"; + public const string Skeleton_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_125"; + public const string Knight_Basic_Name_locID = "LOC_ID_ENEMY_NAME_4"; + public const string Knight_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_5"; + public const string Knight_Expert_Name_locID = "LOC_ID_ENEMY_NAME_6"; + public const string Knight_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_7"; + public const string Blob_Basic_Name_locID = "LOC_ID_ENEMY_NAME_8"; + public const string Blob_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_9"; + public const string Blob_Expert_Name_locID = "LOC_ID_ENEMY_NAME_10"; + public const string Blob_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_11"; + public const string BallAndChain_Basic_Name_locID = "LOC_ID_ENEMY_NAME_12"; + public const string BallAndChain_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_13"; + public const string BallAndChain_Expert_Name_locID = "LOC_ID_ENEMY_NAME_14"; + public const string BallAndChain_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_15"; + public const string EarthWizard_Basic_Name_locID = "LOC_ID_ENEMY_NAME_16"; + public const string EarthWizard_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_17"; + public const string EarthWizard_Expert_Name_locID = "LOC_ID_ENEMY_NAME_18"; + public const string EarthWizard_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_126"; + public const string FireWizard_Basic_Name_locID = "LOC_ID_ENEMY_NAME_19"; + public const string FireWizard_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_20"; + public const string FireWizard_Expert_Name_locID = "LOC_ID_ENEMY_NAME_21"; + public const string FireWizard_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_22"; + public const string IceWizard_Basic_Name_locID = "LOC_ID_ENEMY_NAME_23"; + public const string IceWizard_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_24"; + public const string IceWizard_Expert_Name_locID = "LOC_ID_ENEMY_NAME_25"; + public const string IceWizard_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_26"; + public const string Eyeball_Basic_Name_locID = "LOC_ID_ENEMY_NAME_27"; + public const string Eyeball_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_28"; + public const string Eyeball_Expert_Name_locID = "LOC_ID_ENEMY_NAME_29"; + public const string Eyeball_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_30"; + public const string Fairy_Basic_Name_locID = "LOC_ID_ENEMY_NAME_31"; + public const string Fairy_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_32"; + public const string Fairy_Expert_Name_locID = "LOC_ID_ENEMY_NAME_33"; + public const string Fairy_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_34"; + public const string ShieldKnight_Basic_Name_locID = "LOC_ID_ENEMY_NAME_35"; + public const string ShieldKnight_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_36"; + public const string ShieldKnight_Expert_Name_locID = "LOC_ID_ENEMY_NAME_37"; + public const string ShieldKnight_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_38"; + public const string BouncySpike_Basic_Name_locID = "LOC_ID_ENEMY_NAME_39"; + public const string BouncySpike_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_40"; + public const string BouncySpike_Expert_Name_locID = "LOC_ID_ENEMY_NAME_41"; + public const string BouncySpike_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_42"; + public const string SwordKnight_Basic_Name_locID = "LOC_ID_ENEMY_NAME_43"; + public const string SwordKnight_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_44"; + public const string SwordKnight_Expert_Name_locID = "LOC_ID_ENEMY_NAME_45"; + public const string SwordKnight_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_46"; + public const string Wolf_Basic_Name_locID = "LOC_ID_ENEMY_NAME_47"; + public const string Wolf_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_48"; + public const string Wolf_Expert_Name_locID = "LOC_ID_ENEMY_NAME_49"; + public const string Wolf_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_50"; + public const string Zombie_Basic_Name_locID = "LOC_ID_ENEMY_NAME_51"; + public const string Zombie_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_52"; + public const string Zombie_Expert_Name_locID = "LOC_ID_ENEMY_NAME_53"; + public const string Zombie_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_54"; + public const string Energon_Basic_Name_locID = "LOC_ID_ENEMY_NAME_55"; + public const string Energon_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_56"; + public const string Energon_Expert_Name_locID = "LOC_ID_ENEMY_NAME_57"; + public const string Energon_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_58"; + public const string Ninja_Basic_Name_locID = "LOC_ID_ENEMY_NAME_59"; + public const string Ninja_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_60"; + public const string Ninja_Expert_Name_locID = "LOC_ID_ENEMY_NAME_61"; + public const string Ninja_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_62"; + public const string Plant_Basic_Name_locID = "LOC_ID_ENEMY_NAME_63"; + public const string Plant_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_64"; + public const string Plant_Expert_Name_locID = "LOC_ID_ENEMY_NAME_65"; + public const string Plant_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_127"; + public const string Fireball_Basic_Name_locID = "LOC_ID_ENEMY_NAME_66"; + public const string Fireball_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_67"; + public const string Fireball_Expert_Name_locID = "LOC_ID_ENEMY_NAME_68"; + public const string Fireball_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_69"; + public const string SpikeTrap_Basic_Name_locID = "LOC_ID_ENEMY_NAME_70"; + public const string SpikeTrap_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_70"; + public const string SpikeTrap_Expert_Name_locID = "LOC_ID_ENEMY_NAME_70"; + public const string SpikeTrap_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_70"; + public const string SkeletonArcher_Basic_Name_locID = "LOC_ID_ENEMY_NAME_71"; + public const string SkeletonArcher_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_72"; + public const string SkeletonArcher_Expert_Name_locID = "LOC_ID_ENEMY_NAME_73"; + public const string SkeletonArcher_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_74"; + public const string LastBoss_Basic_Name_locID = "LOC_ID_ENEMY_NAME_75"; + public const string LastBoss_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_76"; + public const string LastBoss_Expert_Name_locID = "LOC_ID_ENEMY_NAME_75"; + public const string LastBoss_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_77"; + public const string Portrait_Basic_Name_locID = "LOC_ID_ENEMY_NAME_78"; + public const string Portrait_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_79"; + public const string Portrait_Expert_Name_locID = "LOC_ID_ENEMY_NAME_80"; + public const string Portrait_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_81"; + public const string Starburst_Basic_Name_locID = "LOC_ID_ENEMY_NAME_82"; + public const string Starburst_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_83"; + public const string Starburst_Expert_Name_locID = "LOC_ID_ENEMY_NAME_84"; + public const string Starburst_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_85"; + public const string Chicken_Basic_Name_locID = "LOC_ID_ENEMY_NAME_86"; + public const string Chicken_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_87"; + public const string Chicken_Expert_Name_locID = "LOC_ID_ENEMY_NAME_88"; + public const string Chicken_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_89"; + public const string HomingTurret_Basic_Name_locID = "LOC_ID_ENEMY_NAME_90"; + public const string HomingTurret_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_91"; + public const string HomingTurret_Expert_Name_locID = "LOC_ID_ENEMY_NAME_92"; + public const string HomingTurret_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_93"; + public const string Horse_Basic_Name_locID = "LOC_ID_ENEMY_NAME_94"; + public const string Horse_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_95"; + public const string Horse_Expert_Name_locID = "LOC_ID_ENEMY_NAME_96"; + public const string Horse_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_97"; + public const string Spark_Basic_Name_locID = "LOC_ID_ENEMY_NAME_98"; + public const string Spark_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_99"; + public const string Spark_Expert_Name_locID = "LOC_ID_ENEMY_NAME_100"; + public const string Spark_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_101"; + public const string Mimic_Basic_Name_locID = "LOC_ID_ENEMY_NAME_102"; + public const string Mimic_Advanced_Name_locID = "LOC_ID_ENEMY_NAME_103"; + public const string Mimic_Expert_Name_locID = "LOC_ID_ENEMY_NAME_104"; + public const string Mimic_Miniboss_Name_locID = "LOC_ID_ENEMY_NAME_105"; + } +} diff --git a/RogueCastle/src/EVs/GameEV.cs b/RogueCastle/src/EVs/GameEV.cs new file mode 100644 index 0000000..b968527 --- /dev/null +++ b/RogueCastle/src/EVs/GameEV.cs @@ -0,0 +1,205 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + class GameEV + { + //MISC + public const int SKILL_LEVEL_COST_INCREASE = 10; //5;//10; //20;//50;//25; //The cost increase of ALL traits. This value is multiplied off of the player's level. + public const float GATEKEEPER_TOLL_COST = 1;// The PERCENT of your money that the gate keeper takes when you restart a castle. + public const float MANA_OVER_TIME_TIC_RATE = 0.33f; //The rate that mana drain tics on a per second basis. + public const float FLIGHT_SPEED_MOD = 0.15f;//0.25f;//0.35f; //Speed increase the player gets when they fly. + public const int ARMOR_DIVIDER = 200; //LoL Equation. Player_Armor/ (ARMOR_DIVIDER + Player_Armor) + public const float NEWGAMEPLUS_GOLDBOUNTY = 0.5f;//0.1f; // Player gets 10% gold increase per times castle beaten. + public const float HAZARD_DAMAGE_PERCENT = 0.2f; // The percentage of health that hazards deal to player. + public const int FART_CHANCE = 91;//88; //82 //70 //The higher the number, the lower the chance of farting. + public const float ARCHITECT_FEE = 0.6f;//0.7f; // Total percentage of gold gained (not lost). + + //TRAITS AND RUNES + public const int RUNE_VAMPIRISM_HEALTH_GAIN = 2;//3;//2; //The amount of lifedrain you get per enemy kill per vampirism rune. + public const int RUNE_MANA_GAIN = 2; //3; //2; //The amount of managain you get per enemy kill per mana rune. + public const float RUNE_FLIGHT = 0.6f;//0.5f;//1.0f;//1.5f; //2.0f; //1.5f; //The number of seconds of flight you get per rune. + public const float RUNE_MOVEMENTSPEED_MOD = 0.2f;//0.1f; + public const float RUNE_DAMAGERETURN_MOD = 0.5f;//0.3f;//0.50f; + public const float RUNE_GOLDGAIN_MOD = 0.1f; + public const int RUNE_MANAHPGAIN = 1; + public const float ROOM_VITA_CHAMBER_REGEN_AMOUNT = 0.3f;//0.35f; //The amount of mana and health you get back from the vita chambers. + public const int RUNE_CURSE_ROOM_LEVEL_GAIN = 8;//5; // The amount of levels that is added to each room. + public const float RUNE_GRACE_ROOM_LEVEL_LOSS = 0.75f;//1; // The amount of levels that is added to the required room level to level up an enemy. + + + public const int BASE_ERA = 700; + + // CLASS EV + public const float SPELLSWORD_SPELLDAMAGE_MOD = 2.0f;//1.5f; + public const float SPELLSWORD_MANACOST_MOD = 2.0f; + public const float SPELLSWORD_SPELL_SCALE = 1.75f; + public const float SPELLSWORD_ATTACK_MANA_CONVERSION = 0.3f; + + public const int LICH_HEALTH_GAIN_PER_KILL = 4;//6;//3; + public const int LICH_HEALTH_GAIN_PER_KILL_LESSER = 4;//3;//3; + public const float LICH_HEALTH_CONVERSION_PERCENT = 0.5f; + public const float LICH_MAX_HP_OFF_BASE = 1.0f;//1.25f;//2.0f; + public const float LICH_MAX_MP_OFF_BASE = 2.0f;//1.75f;//1.25f; + + public const float ASSASSIN_ACTIVE_MANA_DRAIN = 7;//6;//5;//3;//5; // The amount of mana that is drained per half second while the assassin spell is active. + public const float ASSASSIN_ACTIVE_INITIAL_COST = 5;//10; // The initial cost of mana to cast the assassin's active. + + public const int KNIGHT_BLOCK_DRAIN = 25; + public const float TANOOKI_ACTIVE_MANA_DRAIN = 6;//3; + public const float TANOOKI_ACTIVE_INITIAL_COST = 25; + + public const float BARBARIAN_SHOUT_INITIAL_COST = 20;//15; + public const float BARBARIAN_SHOUT_KNOCKBACK_MOD = 3; + + public const float DRAGON_MANAGAIN = 4;// The amount of mana the dragon regains per mana over time tic rate. + public const float SPELUNKER_LIGHT_DRAIN = 0;//1; // The amount of mana the spelunker loses while the light is on PER SECOND. DOES NOT USE TIC RATE. + + public const int MAGE_MANA_GAIN = 6;//12;//10;//15; //The amount of mana the Mage gets from killing enemies. + + public const int NINJA_TELEPORT_COST = 5; + public const int NINJA_TELEPORT_DISTANCE = 350;//300; + + + // SPELL EV + public const float TIMESTOP_ACTIVE_MANA_DRAIN = 8;//7; //5; + public const float DAMAGESHIELD_ACTIVE_MANA_DRAIN = 6;//5;//7; + // ITEM DROP EV + + // ITEM DROP CHANCES + public const int ENEMY_ITEMDROP_CHANCE = 2; // 2 percent chance of enemy dropping health or mana on death. + + public static int[] BREAKABLE_ITEMDROP_CHANCE = new int[] { 3, 4, 36, 1, 56 }; // Chance of breakable dropping HP/MP/COIN/MONEYBAG/NOTHING. + + public static int[] CHEST_TYPE_CHANCE = new int[] { 87, 13, 0 };//{ 83, 14, 3 }; // Chance of chest being bronze, silver, or gold. + + public static int[] BRONZECHEST_ITEMDROP_CHANCE = new int[] { 85, 0, 15 }; // Chance of bronze chest dropping MONEY/STAT DROP/BLUEPRINT + public static int[] SILVERCHEST_ITEMDROP_CHANCE = new int[] {22, 5, 73 }; // Chance of silver chest dropping MONEY/STAT DROP/BLUEPRINT + public static int[] GOLDCHEST_ITEMDROP_CHANCE = new int[] {0, 20, 80 };//{4, 9, 87 }; // Chance of gold chest dropping MONEY/STAT DROP/BLUEPRINT + + public static int[] STATDROP_CHANCE = new int[] { 15, 15, 15, 25, 25, 5 }; // When you get a stat drop, the chance of it being STR/MAG/DEF/HP/MP/WEIGHT + + + // ITEM DROP AMOUNTS + public const float ITEM_MANADROP_AMOUNT = 0.1f; // Percent amount of mana you get from a mana item drop. + public const float ITEM_HEALTHDROP_AMOUNT = 0.1f; // Percent amount of health you get from a health item drop. + public const int ITEM_STAT_STRENGTH_AMOUNT = 1; // Amount of strength you get for picking up a strength item drop. + public const int ITEM_STAT_MAGIC_AMOUNT = 1; // Amount of magic you get for picking up a magic item drop. + public const int ITEM_STAT_ARMOR_AMOUNT = 2; // Amount of armor you get for picking up an armor item drop. + public const int ITEM_STAT_MAXHP_AMOUNT = 5;//3; // Amount of max HP you get for picking up a max HP item drop. + public const int ITEM_STAT_MAXMP_AMOUNT = 5;//3; // Amount of max MP you get for picking up a max MP item drop. + public const int ITEM_STAT_WEIGHT_AMOUNT = 5;//3; // Amount of weight you get for picking up a weight item drop. + + /* + // Hint text, format is { textID, action, textID } + public static string[,] GAME_HINTS = new string[,] { + { "LOC_ID_HINT_1", "", "" }, // The Forest is always to the right side of the Castle.", "", "" }, + { "LOC_ID_HINT_2", "", "" }, // The Maya is always at the top of the Castle.", "", "" }, + { "LOC_ID_HINT_3", "", "" }, // The Darkness is always at the bottom of the Castle.", "", "" }, + { "LOC_ID_HINT_4", "", "" }, // If you're having trouble with a boss, try using different runes.", "", "" }, + { "LOC_ID_HINT_5", " [Input:" + InputMapType.PLAYER_JUMP1 + "]", "" }, // Vault runes let you to jump in the air with + { "LOC_ID_HINT_6", "", "" }, // Sprint runes let you dash with... + { "LOC_ID_HINT_7", "", "" }, // Each class has pros and cons. Make sure to change your playstyle accordingly.", "", "" }, + { "LOC_ID_HINT_8", "", "" }, // Exploring and finding chests is the best way to earn gold.", "", "" }, + { "LOC_ID_HINT_9", "", "" }, // Harder areas offer greater rewards.", "", "" }, + { "LOC_ID_HINT_10", " [Input:" + InputMapType.PLAYER_JUMP1 + "] ", "LOC_ID_HINT_10b" }, // Sky runes let you fly by pressing", " [Input:" + InputMapType.PLAYER_JUMP1 + "] ", "while in the air." }, + { "LOC_ID_HINT_11", "", "" }, // Vampirism and Siphon runes are very powerful when stacked.", "", "" }, + { "LOC_ID_HINT_12", "", "" }, // Mastering mobility runes makes you awesome.", "", "" }, + { "LOC_ID_HINT_13", "", "" }, // Make sure to expand your manor. You never know what new skills can be revealed.", "", "" }, + { "LOC_ID_HINT_14", "", "" }, // All classes can be upgraded with unique class abilities.", "", "" }, + { "LOC_ID_HINT_15", " [Input:" + InputMapType.PLAYER_BLOCK + "]", "" }, // Unlocked class abilities can be activated with", " [Input:" + InputMapType.PLAYER_BLOCK + "]", "" }, + { "LOC_ID_HINT_16", "", "" }, // Upgrade your classes early to obtain powerful class abilities.", "", "" }, + { "LOC_ID_HINT_17", "", "" }, // If you are having trouble with a room, see if you can bypass it instead.", "", "" }, + { "LOC_ID_HINT_18", "", "" }, // Buying equipment is the fastest way to raise your stats.", "", "" }, + { "LOC_ID_HINT_19", "", "" }, // Purchasing equipment is cheaper and more flexible than raising your base stats.", "", "" }, + { "LOC_ID_HINT_20", "", "" }, // You should have picked the other child.", "", "" }, + { "LOC_ID_HINT_21", "", "" }, // Runes are very powerful. Equip runes at the Enchantress, and don't forget to use them!", "", "" }, + { "LOC_ID_HINT_22", "", "" }, // Learn the nuances of your spell to maximize their potential.", "", "" }, + { "LOC_ID_HINT_23", "", "" }, // Try to hit enemies near the apex of the axe's arc in order to hit them multiple times.", "", "" }, + { "LOC_ID_HINT_24", "", "" }, // Avoid picking up the conflux orbs after casting it to maximize damage.", "", "" }, + { "LOC_ID_HINT_25", "", "" }, // Dodge the chakrams return trip in order to maximize its damage.", "", "" }, + { "LOC_ID_HINT_26", "", "" }, // Better to use mana to kill enemies than to take unnecessary damage.", "", "" }, + { "LOC_ID_HINT_27", "", "" }, // Learning enemy 'tells' is integral to surviving the castle.", "", "" }, + { "LOC_ID_HINT_28", "", "" }, // Spike traps check for a pulse to tell the dead from the living.", "", "" }, + { "LOC_ID_HINT_29", " [Input:" + InputMapType.MENU_MAP + "] ", "LOC_ID_HINT_29b" }, // Press", " [Input:" + InputMapType.MENU_MAP + "] ", "to open the map." }, + { "LOC_ID_HINT_30", "", "" }, // Fairy chests hold all the runes in the game. Runes will help you immensely.", "", "" }, + { "LOC_ID_HINT_31", "", "" }, // If you fail a Fairy chest room, the Architect can give you a second chance.", "", "" }, + { "LOC_ID_HINT_32", "", "" }, // The Architect has a hefty fee for those who use his service.", "", "" }, + { "LOC_ID_HINT_33", "", "" }, // Bosses drop large amounts of gold on their death.", "", "" }, + { "LOC_ID_HINT_34", "", "" }, // Bury me with my money.", "", "" }, + { "LOC_ID_HINT_35", "", "" }, // If you are having trouble, try equipping Grace runes.", "", "" }, + { "LOC_ID_HINT_36", " [Input:" + InputMapType.PLAYER_DOWN1 + "]", "" }, // In options you can enable Quick Drop to downstrike and drop with", " [Input:" + InputMapType.PLAYER_DOWN1 + "]", "" }, + { "LOC_ID_HINT_37", "", "" }, // The architect is very useful for practicing against bosses.", "", "" }, + { "LOC_ID_HINT_38", "", "" }, // The third row of equipment usually has major tradeoffs. Be careful.", "", "" }, + { "LOC_ID_HINT_39", "", "" }, // Certain runes work better with certain bosses.", "", "" }, + { "LOC_ID_HINT_40", "", "" }, // You should practice fighting bosses using the architect.", "", "" }, + { "LOC_ID_HINT_41", "", "" }, // Health is a very important stat to raise.", "", "" }, + { "LOC_ID_HINT_42", "", "" }, // Retribution runes can damage invulnerable objects.", "", "" }, + { "LOC_ID_HINT_43", "", "" }, // Class abilities are very powerful if used correctly.", "", "" }, + { "LOC_ID_HINT_44", "", "" }, // Some classes have advantages over certain bosses.", "", "" } + }; + */ + + // NEW PLACEHOLDER TEXT + public static string[] GAME_HINTS = new string[] { + "LOC_ID_HINT_1", // The Forest is always to the right side of the Castle. + "LOC_ID_HINT_2", // The Maya is always at the top of the Castle. + "LOC_ID_HINT_3", // The Darkness is always at the bottom of the Castle. + "LOC_ID_HINT_4", // If you're having trouble with a boss, try using different runes. + "LOC_ID_HINT_5_NEW", // Vault runes let you to jump in the air with [Input:PLAYER_JUMP1] + "LOC_ID_HINT_6", // Sprint runes let you dash with... + "LOC_ID_HINT_7", // Each class has pros and cons. Make sure to change your playstyle accordingly. + "LOC_ID_HINT_8", // Exploring and finding chests is the best way to earn gold. + "LOC_ID_HINT_9", // Harder areas offer greater rewards. + "LOC_ID_HINT_10_NEW", // Sky runes let you fly by pressing [Input:PLAYER_JUMP1] while in the air. + "LOC_ID_HINT_11", // Vampirism and Siphon runes are very powerful when stacked. + "LOC_ID_HINT_12", // Mastering mobility runes makes you awesome. + "LOC_ID_HINT_13", // Make sure to expand your manor. You never know what new skills can be revealed. + "LOC_ID_HINT_14", // All classes can be upgraded with unique class abilities. + "LOC_ID_HINT_15_NEW", // Unlocked class abilities can be activated with [Input:PLAYER_BLOCK] + "LOC_ID_HINT_16", // Upgrade your classes early to obtain powerful class abilities. + "LOC_ID_HINT_17", // If you are having trouble with a room, see if you can bypass it instead. + "LOC_ID_HINT_18", // Buying equipment is the fastest way to raise your stats. + "LOC_ID_HINT_19", // Purchasing equipment is cheaper and more flexible than raising your base stats. + "LOC_ID_HINT_20", // You should have picked the other child. + "LOC_ID_HINT_21", // Runes are very powerful. Equip runes at the Enchantress, and don't forget to use them! + "LOC_ID_HINT_22", // Learn the nuances of your spell to maximize their potential. + "LOC_ID_HINT_23", // Try to hit enemies near the apex of the axe's arc in order to hit them multiple times. + "LOC_ID_HINT_24", // Avoid picking up the conflux orbs after casting it to maximize damage. + "LOC_ID_HINT_25", // Dodge the chakrams return trip in order to maximize its damage. + "LOC_ID_HINT_26", // Better to use mana to kill enemies than to take unnecessary damage. + "LOC_ID_HINT_27", // Learning enemy 'tells' is integral to surviving the castle. + "LOC_ID_HINT_28", // Spike traps check for a pulse to tell the dead from the living. + "LOC_ID_HINT_29_NEW", // Press [Input:MENU_MAP] to open the map. + "LOC_ID_HINT_30", // Fairy chests hold all the runes in the game. Runes will help you immensely. + "LOC_ID_HINT_31", // If you fail a Fairy chest room, the Architect can give you a second chance. + "LOC_ID_HINT_32", // The Architect has a hefty fee for those who use his service. + "LOC_ID_HINT_33", // Bosses drop large amounts of gold on their death. + "LOC_ID_HINT_34", // Bury me with my money. + "LOC_ID_HINT_35", // If you are having trouble, try equipping Grace runes. + "LOC_ID_HINT_36_NEW", // In options you can enable Quick Drop to downstrike and drop with [Input:PLAYER_DOWN1] + "LOC_ID_HINT_37", // The architect is very useful for practicing against bosses.", "", "" }, + "LOC_ID_HINT_38", // The third row of equipment usually has major tradeoffs. Be careful.", "", "" }, + "LOC_ID_HINT_39", // Certain runes work better with certain bosses.", "", "" }, + "LOC_ID_HINT_40", // You should practice fighting bosses using the architect.", "", "" }, + "LOC_ID_HINT_41", // Health is a very important stat to raise.", "", "" }, + "LOC_ID_HINT_42", // Retribution runes can damage invulnerable objects.", "", "" }, + "LOC_ID_HINT_43", // Class abilities are very powerful if used correctly.", "", "" }, + "LOC_ID_HINT_44", // Some classes have advantages over certain bosses.", "", "" } + }; + + //TRAITS + public const float TRAIT_GIGANTISM = 3.0f;//2.5f;//3.5f; //The amount the player is scaled. + public const float TRAIT_DWARFISM = 1.35f;//1.25f; //The amount the player is scaled. + public const float TRAIT_HYPERGONADISM = 2.0f; //The amount the player will knock enemies back with Hypergonadism + public const float TRAIT_ECTOMORPH = 1.85f;//2.0f; //The amount the player gets knocked if Skinny + public const float TRAIT_ENDOMORPH = 0.5f; //The amount the player gets knocked if Fat. + public const float TRAIT_MOVESPEED_AMOUNT = 0.3f; //0.5f; //0.25f; // The amount of movespeed you get for the hyperactive trait. + public const float TRAIT_DEMENTIA_SPAWN_CHANCE = 0.2f; // The chance of dementia spawning a fake enemy. + public const float TRAIT_CLONUS_MIN = 12; // The min time it takes for clonus to trigger again in seconds. + public const float TRAIT_CLONUS_MAX = 35; // The max time it takes for clonus to trigger again in seconds. + } +} diff --git a/RogueCastle/src/EVs/GlobalEV.cs b/RogueCastle/src/EVs/GlobalEV.cs new file mode 100644 index 0000000..18b0624 --- /dev/null +++ b/RogueCastle/src/EVs/GlobalEV.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class GlobalEV + { + //Base screen resolution size for the game. 1320x720 == 60x60 tiles + public const int ScreenWidth = 1320; //1366; + public const int ScreenHeight = 720; //768; + + public const float GRAVITY = -1830;//-30.5f;//-28.5f;//-27f; //-15f; + public static float Camera_XOffset = 0; + public static float Camera_YOffset = -22;//2; //-23;//50; // The amount the camera is offset by when following the player. + } +} diff --git a/RogueCastle/src/EVs/LevelEV.cs b/RogueCastle/src/EVs/LevelEV.cs new file mode 100644 index 0000000..5f103e4 --- /dev/null +++ b/RogueCastle/src/EVs/LevelEV.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + public class LevelEV + { + public const int ENEMY_LEVEL_DIFFICULTY_MOD = 32;//30; //40;//30;//15;//6;//12; // The number of levels an enemy needs to be before he goes to the next difficulty. + public const float ENEMY_LEVEL_FAKE_MULTIPLIER = 2.75f;//3.0f;//2.75f;//2.5f;//2.25f;//This multiplies the enemy level by a fake amount in order to keep it more in par with how close we want the player to be when engaging. + public const int ROOM_LEVEL_MOD = 4;//6; //The number of rooms that have to be generated before the room raises a difficulty level (raising enemy lvl). + public const byte TOTAL_JOURNAL_ENTRIES = 25;//5;//19;//15; // This needs to be kept up-to-date. + + public const int ENEMY_EXPERT_LEVEL_MOD = 4; //3; //The number of bonus levels an expert enemy gains over the current room level mod. + public const int ENEMY_MINIBOSS_LEVEL_MOD = 7;//8;//5; //The number of bonus levels the BOSSES GAIN over the current room level mod. + + public const int LAST_BOSS_MODE1_LEVEL_MOD = 8; //ADDS DIRECTLY TO THE LEVEL, IGNORING ROOM_LEVEL_MOD. + public const int LAST_BOSS_MODE2_LEVEL_MOD = 10; //ADDS DIRECTLY TO THE LEVEL, IGNORING ROOM_LEVEL_MOD. + + ////////////////////////////////////////////////////////////// + + // EVs related to new game + + + // These are room levels prior to dividing by ROOM_LEVEL_MOD. + public const int CASTLE_ROOM_LEVEL_BOOST = 0; + public const int GARDEN_ROOM_LEVEL_BOOST = 2;//3;//5;//10; + public const int TOWER_ROOM_LEVEL_BOOST = 4;//6;//10;//20; + public const int DUNGEON_ROOM_LEVEL_BOOST = 6;//9;//15;//30; + + public const int NEWGAMEPLUS_LEVEL_BASE = 128;//120;//120;//10; + public const int NEWGAMEPLUS_LEVEL_APPRECIATION = 128;//80; //60; + public const int NEWGAMEPLUS_MINIBOSS_LEVEL_BASE = 0; + public const int NEWGAMEPLUS_MINIBOSS_LEVEL_APPRECIATION = 0; + + ////////////////////////////////////////////////////////////// + + public const bool LINK_TO_CASTLE_ONLY = true; + public const byte CASTLE_BOSS_ROOM = BossRoomType.EyeballBossRoom; + public const byte TOWER_BOSS_ROOM = BossRoomType.FireballBossRoom; + public const byte DUNGEON_BOSS_ROOM = BossRoomType.BlobBossRoom; + public const byte GARDEN_BOSS_ROOM = BossRoomType.FairyBossRoom; + public const byte LAST_BOSS_ROOM = BossRoomType.LastBossRoom; + + /////////////////////////////////////////////////////////////// + //The list of enemies that each area will randomly add enemies to. + + + public static byte[] DEMENTIA_FLIGHT_LIST = new byte[] { EnemyType.FireWizard, EnemyType.IceWizard, EnemyType.Eyeball, EnemyType.Fairy, EnemyType.BouncySpike, EnemyType.Fireball, EnemyType.Starburst }; + public static byte[] DEMENTIA_GROUND_LIST = new byte[] { EnemyType.Skeleton, EnemyType.Knight, EnemyType.Blob, EnemyType.BallAndChain, EnemyType.SwordKnight, EnemyType.Zombie, EnemyType.Ninja, EnemyType.Plant, EnemyType.HomingTurret, EnemyType.Horse, }; + + public static byte[] CASTLE_ENEMY_LIST = new byte[] { EnemyType.Skeleton, EnemyType.Knight, EnemyType.FireWizard, EnemyType.IceWizard, EnemyType.Eyeball, EnemyType.BouncySpike, EnemyType.SwordKnight, EnemyType.Zombie, EnemyType.Fireball, EnemyType.Portrait, EnemyType.Starburst, EnemyType.HomingTurret, }; + public static byte[] GARDEN_ENEMY_LIST = new byte[] { EnemyType.Skeleton, EnemyType.Blob, EnemyType.BallAndChain, EnemyType.EarthWizard, EnemyType.FireWizard, EnemyType.Eyeball, EnemyType.Fairy, EnemyType.ShieldKnight, EnemyType.BouncySpike, EnemyType.Wolf, EnemyType.Plant, EnemyType.SkeletonArcher, EnemyType.Starburst, EnemyType.Horse, }; + public static byte[] TOWER_ENEMY_LIST = new byte[] { EnemyType.Knight, EnemyType.BallAndChain, EnemyType.IceWizard, EnemyType.Eyeball, EnemyType.Fairy, EnemyType.ShieldKnight, EnemyType.BouncySpike, EnemyType.Wolf, EnemyType.Ninja, EnemyType.Plant, EnemyType.Fireball, EnemyType.SkeletonArcher, EnemyType.Portrait, EnemyType.Starburst, EnemyType.HomingTurret, EnemyType.Mimic, }; + public static byte[] DUNGEON_ENEMY_LIST = new byte[] { EnemyType.Skeleton, EnemyType.Knight, EnemyType.Blob, EnemyType.BallAndChain, EnemyType.EarthWizard, EnemyType.FireWizard, EnemyType.IceWizard, EnemyType.Eyeball, EnemyType.Fairy, EnemyType.BouncySpike, EnemyType.SwordKnight, EnemyType.Zombie, EnemyType.Ninja, EnemyType.Plant, EnemyType.Fireball, EnemyType.Starburst, EnemyType.HomingTurret, EnemyType.Horse, }; + + public static byte[] CASTLE_ENEMY_DIFFICULTY_LIST = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; + public static byte[] GARDEN_ENEMY_DIFFICULTY_LIST = new byte[] { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; + public static byte[] TOWER_ENEMY_DIFFICULTY_LIST = new byte[] { 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, }; + public static byte[] DUNGEON_ENEMY_DIFFICULTY_LIST = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; + + + //EVERY CURRENT ENEMY + //{ EnemyType.BallAndChain, EnemyType.Blob, EnemyType.BouncySpike, EnemyType.Eagle, EnemyType.EarthWizard, EnemyType.Energon, EnemyType.Eyeball, EnemyType.Fairy, EnemyType.Fireball, EnemyType.FireWizard, EnemyType.HomingTurret, EnemyType.Horse, EnemyType.IceWizard, EnemyType.Knight, EnemyType.Ninja, EnemyType.Plant, EnemyType.ShieldKnight, EnemyType.Skeleton, EnemyType.SkeletonArcher, EnemyType.Spark, EnemyType.SpikeTrap, EnemyType.SwordKnight, EnemyType.Wolf, EnemyType.Zombie }; + + public static string[] CASTLE_ASSETSWAP_LIST = new string[] { "BreakableBarrel1_Character", "BreakableBarrel2_Character", "CastleAssetKnightStatue_Character", "CastleAssetWindow1_Sprite", "CastleAssetWindow2_Sprite", "CastleBGPillar_Character", "CastleAssetWeb1_Sprite", "CastleAssetWeb2_Sprite", "CastleAssetBackTorch_Character", "CastleAssetSideTorch_Character", "CastleAssetChandelier1_Character", "CastleAssetChandelier2_Character", "CastleAssetCandle1_Character", "CastleAssetCandle2_Character", "CastleAssetFireplace_Character", "CastleAssetBookcase_Sprite", "CastleAssetBookCase2_Sprite", "CastleAssetBookCase3_Sprite", "CastleAssetUrn1_Character", "CastleAssetUrn2_Character", "BreakableChair1_Character", "BreakableChair2_Character", "CastleAssetTable1_Character", "CastleAssetTable2_Character", "CastleDoorOpen_Sprite", "CastleAssetFrame_Sprite" }; + public static string[] DUNGEON_ASSETSWAP_LIST = new string[] { "BreakableCrate1_Character", "BreakableBarrel1_Character", "CastleAssetDemonStatue_Character", "DungeonSewerGrate1_Sprite", "DungeonSewerGrate2_Sprite", "", "CastleAssetWeb1_Sprite", "CastleAssetWeb2_Sprite", "DungeonChainRANDOM2_Character", "", "DungeonHangingCell1_Character", "DungeonHangingCell2_Character", "DungeonTorch1_Character", "DungeonTorch2_Character", "DungeonMaidenRANDOM3_Character", "DungeonPrison1_Sprite", "DungeonPrison2_Sprite", "DungeonPrison3_Sprite", "", "", "DungeonBucket1_Character", "DungeonBucket2_Character", "DungeonTable1_Character", "DungeonTable2_Character", "DungeonDoorOpen_Sprite",""}; + public static string[] TOWER_ASSETSWAP_LIST = new string[] { "BreakableCrate1_Character", "BreakableCrate2_Character", "CastleAssetAngelStatue_Character", "TowerHoleRANDOM9_Sprite", "TowerHoleRANDOM9_Sprite", "", "TowerLever1_Sprite", "TowerLever2_Sprite", "CastleAssetBackTorchUnlit_Character", "CastleAssetSideTorchUnlit_Character", "DungeonChain1_Character", "DungeonChain2_Character", "TowerTorch_Character", "TowerPedestal2_Character", "CastleAssetFireplaceNoFire_Character", "BrokenBookcase1_Sprite", "BrokenBookcase2_Sprite", "", "TowerBust1_Character", "TowerBust2_Character", "TowerChair1_Character", "TowerChair2_Character", "TowerTable1_Character", "TowerTable2_Character", "TowerDoorOpen_Sprite", "CastleAssetFrame_Sprite" }; + public static string[] GARDEN_ASSETSWAP_LIST = new string[] { "GardenUrn1_Character", "GardenUrn2_Character", "CherubStatue_Character", "GardenFloatingRockRANDOM5_Sprite", "GardenFloatingRockRANDOM5_Sprite", "GardenPillar_Character", "", "", "GardenFairy_Character", "", "GardenVine1_Character", "GardenVine2_Character", "GardenLampPost1_Character", "GardenLampPost2_Character", "GardenFountain_Character", "GardenBush1_Sprite", "GardenBush2_Sprite", "", "", "", "GardenMushroom1_Character", "GardenMushroom2_Character", "GardenTrunk1_Character", "GardenTrunk2_Character", "GardenDoorOpen_Sprite", "" }; + + /////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////// + //Percent chance the door direction will be open or closed when procedurally generating a room. + public const int LEVEL_CASTLE_LEFTDOOR = 90;//70; + public const int LEVEL_CASTLE_RIGHTDOOR = 90;//70; + public const int LEVEL_CASTLE_TOPDOOR = 90;//70; + public const int LEVEL_CASTLE_BOTTOMDOOR = 90;//70; + + public const int LEVEL_GARDEN_LEFTDOOR = 70;//80; + public const int LEVEL_GARDEN_RIGHTDOOR = 100;//80; + public const int LEVEL_GARDEN_TOPDOOR = 45;//85;//40; + public const int LEVEL_GARDEN_BOTTOMDOOR = 45;//85;//40; + + public const int LEVEL_TOWER_LEFTDOOR = 45;//65; + public const int LEVEL_TOWER_RIGHTDOOR = 45;//65; + public const int LEVEL_TOWER_TOPDOOR = 100; //90; + public const int LEVEL_TOWER_BOTTOMDOOR = 60;//40; + + public const int LEVEL_DUNGEON_LEFTDOOR = 55;//50; + public const int LEVEL_DUNGEON_RIGHTDOOR = 55; //50; + public const int LEVEL_DUNGEON_TOPDOOR = 45; //40; + public const int LEVEL_DUNGEON_BOTTOMDOOR = 100;//75; //100; + //////////////////////////////////////////////////////////////// + + //DEBUG EVS + public static bool SHOW_ENEMY_RADII = false; + public static bool ENABLE_DEBUG_INPUT = true; + public static bool UNLOCK_ALL_ABILITIES = false; + public static bool UNLOCK_ALL_DIARY_ENTRIES = false; + + public static GameTypes.LevelType TESTROOM_LEVELTYPE = GameTypes.LevelType.CASTLE; + public static bool TESTROOM_REVERSE = false; + public static bool RUN_TESTROOM = false; + public static bool SHOW_DEBUG_TEXT = false; + public static bool LOAD_TITLE_SCREEN = true; + public static bool LOAD_SPLASH_SCREEN = false; + public static bool SHOW_SAVELOAD_DEBUG_TEXT = false; + public static bool DELETE_SAVEFILE = false; + //public static bool CLOSE_TESTROOM_DOORS = true; + public static bool CLOSE_TESTROOM_DOORS = false; + public static bool RUN_TUTORIAL = false; + public static bool RUN_DEMO_VERSION = false; + public static bool DISABLE_SAVING = false; + public static bool RUN_CRASH_LOGS = false; + public static bool WEAKEN_BOSSES = false; + public static bool ENABLE_OFFSCREEN_CONTROL = false; + public static bool ENABLE_BACKUP_SAVING = true; + public const string GAME_VERSION = "v1.4.1"; + public static bool ENABLE_BLITWORKS_SPLASH = false; + public static bool CREATE_RETAIL_VERSION = true; // This EV overrides all the other Level EVs to create a retail build of the game. + + public static bool SHOW_FPS = false; // Setting this true also turns vsync off (so that you can get an FPS greater than 60). + public static bool SAVE_FRAMES = false; + public static int SAVEFILE_REVISION_NUMBER = 1; + } +} diff --git a/RogueCastle/src/EVs/PlayerEV.cs b/RogueCastle/src/EVs/PlayerEV.cs new file mode 100644 index 0000000..9ae9440 --- /dev/null +++ b/RogueCastle/src/EVs/PlayerEV.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + class PlayerEV + { + public const float KNIGHT_DAMAGE_MOD = 1.0f; + + public const float ASSASSIN_CRITDAMAGE_MOD = 1.25f; + public const float ASSASSIN_CRITCHANCE_MOD = 0.15f; + public const float ASSASSIN_DAMAGE_MOD = 0.75f; + public const float ASSASSIN_HEALTH_MOD = 0.75f; + public const float ASSASSIN_MANA_MOD = 0.65f;//0.75f; + + public const float BARBARIAN_DAMAGE_MOD = 0.75f; + public const float BARBARIAN_HEALTH_MOD = 1.5f; + public const float BARBARIAN_MANA_MOD = 0.5f; + + public const float MAGE_DAMAGE_MOD = 0.5f; + public const float MAGE_MAGICDAMAGE_MOD = 1.25f;//1.3f;//1.35f;//1.5f; //1.4f; + public const float MAGE_HEALTH_MOD = 0.5f; + public const float MAGE_MANA_MOD = 1.5f; + + public const float BANKER_DAMAGE_MOD = 0.75f; + public const float BANKER_HEALTH_MOD = 0.5f; + public const float BANKER_GOLDGAIN_MOD = 0.3f; + public const float BANKER_MANA_MOD = 0.5f; + + public const float NINJA_DAMAGE_MOD = 1.75f; + public const float NINJA_MOVESPEED_MOD = 0.3f; + public const float NINJA_HEALTH_MOD = 0.6f; + public const float NINJA_MANA_MOD = 0.4f; + + public const float LICH_DAMAGE_MOD = 0.75f;//0.6f; + public const float LICH_MAGICDAMAGE_MOD = 1.5f; + public const float LICH_HEALTH_MOD = 0.35f; + public const float LICH_MANA_MOD = 0.5f;//0.7f;//0.25f; + + public const float SPELLSWORD_DAMAGE_MOD = 0.75f; + public const float SPELLSWORD_MANA_MOD = 0.4f; + public const float SPELLSWORD_HEALTH_MOD = 0.75f; + + public const float DRAGON_HEALTH_MOD = 0.40f; + public const float DRAGON_MANA_MOD = 0.25f; + public const float DRAGON_MOVESPEED_MOD = 0f; + + public const float TRAITOR_HEALTH_MOD = 0.70f; + public const float TRAITOR_MANA_MOD = 0.70f; + public const float TRAITOR_CLOSE_MANACOST = 30; + public const float TRAITOR_CLOSE_DAMAGEMOD = 1f;//0.5f; + public const float TRAITOR_AXE_MANACOST = 30; + public const float TRAITOR_AXE_DAMAGEMOD = 1f;//0.75f; + + } +} diff --git a/RogueCastle/src/EVs/SpellEV.cs b/RogueCastle/src/EVs/SpellEV.cs new file mode 100644 index 0000000..17f74d3 --- /dev/null +++ b/RogueCastle/src/EVs/SpellEV.cs @@ -0,0 +1,435 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + class SpellEV + { + public const string AXE_Name = "Axe"; public const int AXE_Cost = 15; public const float AXE_Damage = 1f; public const float AXE_XVal = 0f; public const float AXE_YVal = 0f; public const int AXE_Rarity = 1; + public const string DAGGER_Name = "Dagger"; public const int DAGGER_Cost = 10; public const float DAGGER_Damage = 1f; public const float DAGGER_XVal = 0f; public const float DAGGER_YVal = 0f; public const int DAGGER_Rarity = 1; + public const string TIMEBOMB_Name = "Runic Trigger"; public const int TIMEBOMB_Cost = 15; public const float TIMEBOMB_Damage = 1.5f; public const float TIMEBOMB_XVal = 1f; public const float TIMEBOMB_YVal = 0f; public const int TIMEBOMB_Rarity = 1; + public const string TIMESTOP_Name = "Stop Watch"; public const int TIMESTOP_Cost = 15; public const float TIMESTOP_Damage = 0f; public const float TIMESTOP_XVal = 3f; public const float TIMESTOP_YVal = 0f; public const int TIMESTOP_Rarity = 2; + public const string NUKE_Name = "Nuke"; public const int NUKE_Cost = 40; public const float NUKE_Damage = 0.75f; public const float NUKE_XVal = 0f; public const float NUKE_YVal = 0f; public const int NUKE_Rarity = 3; + public const string TRANSLOCATER_Name = "Quantum Translocater"; public const int TRANSLOCATER_Cost = 5; public const float TRANSLOCATER_Damage = 0f; public const float TRANSLOCATER_XVal = 0f; public const float TRANSLOCATER_YVal = 0f; public const int TRANSLOCATER_Rarity = 3; + public const string DISPLACER_Name = "Displacer"; public const int DISPLACER_Cost = 10; public const float DISPLACER_Damage = 0f; public const float DISPLACER_XVal = 0f; public const float DISPLACER_YVal = 0f; public const int DISPLACER_Rarity = 0; + public const string BOOMERANG_Name = "Cross"; public const int BOOMERANG_Cost = 15; public const float BOOMERANG_Damage = 1f; public const float BOOMERANG_XVal = 18f; public const float BOOMERANG_YVal = 0f; public const int BOOMERANG_Rarity = 2; + public const string DUAL_BLADES_Name = "Spark"; public const int DUAL_BLADES_Cost = 15; public const float DUAL_BLADES_Damage = 1f; public const float DUAL_BLADES_XVal = 0f; public const float DUAL_BLADES_YVal = 0f; public const int DUAL_BLADES_Rarity = 1; + public const string CLOSE_Name = "Katana"; public const int CLOSE_Cost = 15; public const float CLOSE_Damage = 0.5f; public const float CLOSE_XVal = 2.1f; public const float CLOSE_YVal = 0f; public const int CLOSE_Rarity = 2; + public const string DAMAGE_SHIELD_Name = "Leaf"; public const int DAMAGE_SHIELD_Cost = 15; public const float DAMAGE_SHIELD_Damage = 1f; public const float DAMAGE_SHIELD_XVal = 9999f; public const float DAMAGE_SHIELD_YVal = 5f; public const int DAMAGE_SHIELD_Rarity = 2; + public const string BOUNCE_Name = "Chaos"; public const int BOUNCE_Cost = 30; public const float BOUNCE_Damage = 0.4f; public const float BOUNCE_XVal = 3.5f; public const float BOUNCE_YVal = 0f; public const int BOUNCE_Rarity = 3; + public const string LASER_Name = "Laser"; public const int LASER_Cost = 15; public const float LASER_Damage = 1f; public const float LASER_XVal = 5f; public const float LASER_YVal = 0f; public const int LASER_Rarity = 3; + public const string DRAGONFIRE_Name = "Dragon Fire"; public const int DRAGONFIRE_Cost = 15; public const float DRAGONFIRE_Damage = 1f; public const float DRAGONFIRE_XVal = 0.35f; public const float DRAGONFIRE_YVal = 0f; public const int DRAGONFIRE_Rarity = 3; + public const string RAPIDDAGGER_Name = "Rapid Dagger"; public const int RAPIDDAGGER_Cost = 30; public const float RAPIDDAGGER_Damage = 0.75f; public const float RAPIDDAGGER_XVal = 0f; public const float RAPIDDAGGER_YVal = 0f; public const int RAPIDDAGGER_Rarity = 1; + public const string DRAGONFIRENEO_Name = "Dragon Fire Neo"; public const int DRAGONFIRENEO_Cost = 0; public const float DRAGONFIRENEO_Damage = 1f; public const float DRAGONFIRENEO_XVal = 0.75f; public const float DRAGONFIRENEO_YVal = 0f; public const int DRAGONFIRENEO_Rarity = 3; + + + public static ProjectileData GetProjData(byte spellType, PlayerObj player) + { + ProjectileData projData = new ProjectileData(player) + { + SpriteName = "BoneProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(0, 0), + IsWeighted = false, + RotationSpeed = 0, + Damage = 0, + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = Vector2.One, + ShowIcon = false, + }; + + switch (spellType) + { + case (SpellType.Axe): + projData.SpriteName = "SpellAxe_Sprite"; + projData.Angle = new Vector2(-74, -74); + projData.Speed = new Vector2(1050, 1050);//(1000, 1000); + projData.SourceAnchor = new Vector2(50, -50); + projData.IsWeighted = true; + projData.RotationSpeed = 10;//15; + projData.CollidesWithTerrain = false; + projData.DestroysWithTerrain = false; + projData.DestroysWithEnemy = false; + projData.Scale = new Vector2(3,3);//(2, 2); + break; + case (SpellType.Dagger): + projData.SpriteName = "SpellDagger_Sprite"; + projData.Angle = Vector2.Zero; + projData.SourceAnchor = new Vector2(50, 0); + projData.Speed = new Vector2(1750, 1750); + projData.IsWeighted = false; + projData.RotationSpeed = 0;//35; + projData.CollidesWithTerrain = true; + projData.DestroysWithTerrain = true; + projData.Scale = new Vector2(2.5f,2.5f);//(2, 2); + break; + case (SpellType.DragonFire): + projData.SpriteName = "TurretProjectile_Sprite"; + projData.Angle = Vector2.Zero; + projData.SourceAnchor = new Vector2(50, 0); + projData.Speed = new Vector2(1100,1100);//(1450, 1450); + projData.Lifespan = DRAGONFIRE_XVal; + projData.IsWeighted = false; + projData.RotationSpeed = 0;//35; + projData.CollidesWithTerrain = true; + projData.DestroysWithTerrain = true; + projData.Scale = new Vector2(2.5f,2.5f);//(2, 2); + break; + case (SpellType.DragonFireNeo): + projData.SpriteName = "TurretProjectile_Sprite"; + projData.Angle = Vector2.Zero; + projData.SourceAnchor = new Vector2(50, 0); + projData.Speed = new Vector2(1750,1750);//(1450, 1450); + projData.Lifespan = DRAGONFIRENEO_XVal; + projData.IsWeighted = false; + projData.RotationSpeed = 0;//35; + projData.CollidesWithTerrain = true; + projData.DestroysWithTerrain = true; + projData.Scale = new Vector2(2.75f,2.75f);//(2, 2); + break; + case (SpellType.TimeBomb): + projData.SpriteName = "SpellTimeBomb_Sprite"; + projData.Angle = new Vector2(-35,-35);//(-65, -65); + projData.Speed = new Vector2(500,500); //(1000, 1000); + projData.SourceAnchor = new Vector2 (50, -50);//(0, -100);//(50, -50); + projData.IsWeighted = true; + projData.RotationSpeed = 0; + projData.StartingRotation = 0; + projData.CollidesWithTerrain = true; + projData.DestroysWithTerrain = false; + projData.CollidesWith1Ways = true; + projData.Scale = new Vector2(3,3);//(2, 2); + break; + case (SpellType.TimeStop): + break; + case (SpellType.Nuke): + projData.SpriteName = "SpellNuke_Sprite"; + projData.Angle = new Vector2(-65, -65); + projData.Speed = new Vector2(500, 500); + projData.IsWeighted = false; + projData.RotationSpeed = 0; + projData.CollidesWithTerrain = false; + projData.DestroysWithTerrain = false; + projData.ChaseTarget = false; // This needs to be set to false because I'm doing something special for the nuke spell. + projData.DestroysWithEnemy = true; + projData.Scale = new Vector2(2, 2); + break; + case (SpellType.Translocator): + break; + case (SpellType.Displacer): + projData.SourceAnchor = new Vector2(0,0);//(300, 0); + projData.SpriteName = "SpellDisplacer_Sprite"; + projData.Angle = new Vector2(0,0);//(90,90);//(0,0);//(-65, -65); + projData.Speed = Vector2.Zero; //new Vector2(8000,8000);//(1000, 1000); + projData.IsWeighted = false; + projData.RotationSpeed = 0;//45;//0; + projData.CollidesWithTerrain = true; + projData.DestroysWithTerrain = false; + projData.CollidesWith1Ways = true; //SETTING TO TRUE TO FIX BUGS WITH LARGE GUYS GETTING INTO TINY HOLES + projData.Scale = new Vector2(2,2);//(2, 2); + break; + case (SpellType.Boomerang): + projData.SpriteName = "SpellBoomerang_Sprite"; + projData.Angle = new Vector2(0, 0); + projData.SourceAnchor = new Vector2(50, -10); + projData.Speed = new Vector2(790, 790);//Vector2(730, 730);//(1000, 1000); + projData.IsWeighted = false; + projData.RotationSpeed = 25; + projData.CollidesWithTerrain = false; + projData.DestroysWithTerrain = false; + projData.DestroysWithEnemy = false; + projData.Scale = new Vector2(3,3); + break; + case (SpellType.DualBlades): + projData.SpriteName = "SpellDualBlades_Sprite"; + projData.Angle = new Vector2(-55, -55); + projData.SourceAnchor = new Vector2(50, 30); + projData.Speed = new Vector2(1000, 1000); + projData.IsWeighted = false; + //projData.StartingRotation = 45; + projData.RotationSpeed = 30;//20; + projData.CollidesWithTerrain = false; + projData.DestroysWithTerrain = false; + projData.DestroysWithEnemy = false; + projData.Scale = new Vector2(2, 2); + break; + case (SpellType.Close): + projData.SpriteName = "SpellClose_Sprite"; + //projData.Angle = new Vector2(90, 90); + projData.SourceAnchor = new Vector2(120, -60);//(75,-200);//(50, 0); + projData.Speed = new Vector2(0,0);//(450,450);//(1000, 1000); + projData.IsWeighted = false; + projData.RotationSpeed = 0f; + projData.DestroysWithEnemy = false; + projData.DestroysWithTerrain = false; + projData.CollidesWithTerrain = false; + projData.Scale = new Vector2(2.5f, 2.5f); + projData.LockPosition = true; + break; + case (SpellType.DamageShield): + projData.SpriteName = "SpellDamageShield_Sprite"; + projData.Angle = new Vector2(-65, -65); + projData.Speed = new Vector2(3.25f, 3.25f);//(2.45f, 2.45f);//(2.0f, 2.0f); + projData.Target = player; + projData.IsWeighted = false; + projData.RotationSpeed = 0; + projData.CollidesWithTerrain = false; + projData.DestroysWithTerrain = false; + projData.DestroysWithEnemy = false; + projData.Scale = new Vector2(3.0f, 3.0f); + projData.DestroyOnRoomTransition = false; + break; + case (SpellType.Bounce): + projData.SpriteName = "SpellBounce_Sprite"; + projData.Angle = new Vector2(-135, -135); + projData.Speed = new Vector2(785,785);//(825, 825); + projData.IsWeighted = false; + projData.StartingRotation = -135; + projData.FollowArc = false; + projData.RotationSpeed = 20; + projData.SourceAnchor = new Vector2(-10, -10); + projData.DestroysWithTerrain = false; + projData.DestroysWithEnemy = false;//true; + projData.CollidesWithTerrain = true; + projData.Scale = new Vector2(3.25f, 3.25f);//(2.5f, 2.5f); + break; + case (SpellType.Laser): + projData.SpriteName = "LaserSpell_Sprite"; + projData.Angle = new Vector2(0, 0); + projData.Speed = new Vector2(0, 0); + projData.IsWeighted = false; + projData.IsCollidable = false; + projData.StartingRotation = 0; + projData.FollowArc = false; + projData.RotationSpeed = 0; + projData.DestroysWithTerrain = false; + projData.DestroysWithEnemy = false; + projData.CollidesWithTerrain = false; + projData.LockPosition = true; + break; + case (SpellType.RapidDagger): + projData.SpriteName = "LaserSpell_Sprite"; + projData.Angle = new Vector2(0, 0); + projData.Speed = new Vector2(0, 0); + projData.IsWeighted = false; + projData.IsCollidable = false; + projData.StartingRotation = 0; + projData.FollowArc = false; + projData.RotationSpeed = 0; + projData.DestroysWithTerrain = false; + projData.DestroysWithEnemy = false; + projData.CollidesWithTerrain = false; + projData.LockPosition = true; + break; + } + + return projData; + } + + public static int GetManaCost(byte spellType) + { + switch (spellType) + { + case (SpellType.Dagger): + return SpellEV.DAGGER_Cost; + case (SpellType.Axe): + return SpellEV.AXE_Cost; + case (SpellType.TimeBomb): + return SpellEV.TIMEBOMB_Cost; + case (SpellType.TimeStop): + return SpellEV.TIMESTOP_Cost; + case (SpellType.Nuke): + return SpellEV.NUKE_Cost; + case (SpellType.Translocator): + return SpellEV.TRANSLOCATER_Cost; + case (SpellType.Displacer): + return SpellEV.DISPLACER_Cost; + case (SpellType.Boomerang): + return SpellEV.BOOMERANG_Cost; + case (SpellType.DualBlades): + return SpellEV.DUAL_BLADES_Cost; + case (SpellType.Close): + return SpellEV.CLOSE_Cost; + case (SpellType.DamageShield): + return SpellEV.DAMAGE_SHIELD_Cost; + case (SpellType.Bounce): + return SpellEV.BOUNCE_Cost; + case (SpellType.Laser): + return SpellEV.LASER_Cost; + case (SpellType.DragonFire): + return SpellEV.DRAGONFIRE_Cost; + case (SpellType.DragonFireNeo): + return SpellEV.DRAGONFIRENEO_Cost; + case (SpellType.RapidDagger): + return SpellEV.RAPIDDAGGER_Cost; + } + + return 0; + } + + public static int GetRarity(byte spellType) + { + switch (spellType) + { + case (SpellType.Dagger): + return SpellEV.DAGGER_Rarity; + case (SpellType.Axe): + return SpellEV.AXE_Rarity; + case (SpellType.TimeBomb): + return SpellEV.TIMEBOMB_Rarity; + case (SpellType.TimeStop): + return SpellEV.TIMESTOP_Rarity; + case (SpellType.Nuke): + return SpellEV.NUKE_Rarity; + case (SpellType.Translocator): + return SpellEV.TRANSLOCATER_Rarity; + case (SpellType.Displacer): + return SpellEV.DISPLACER_Rarity; + case (SpellType.Boomerang): + return SpellEV.BOOMERANG_Rarity; + case (SpellType.DualBlades): + return SpellEV.DUAL_BLADES_Rarity; + case (SpellType.Close): + return SpellEV.CLOSE_Rarity; + case (SpellType.DamageShield): + return SpellEV.DAMAGE_SHIELD_Rarity; + case (SpellType.Bounce): + return SpellEV.BOUNCE_Rarity; + case (SpellType.Laser): + return SpellEV.LASER_Rarity; + case (SpellType.DragonFire): + return SpellEV.DRAGONFIRE_Rarity; + case (SpellType.DragonFireNeo): + return SpellEV.DRAGONFIRENEO_Rarity; + case (SpellType.RapidDagger): + return SpellEV.RAPIDDAGGER_Rarity; + } + + return 0; + } + + public static float GetDamageMultiplier(byte spellType) + { + switch (spellType) + { + case (SpellType.Dagger): + return SpellEV.DAGGER_Damage; + case (SpellType.Axe): + return SpellEV.AXE_Damage; + case (SpellType.TimeBomb): + return SpellEV.TIMEBOMB_Damage; + case (SpellType.TimeStop): + return SpellEV.TIMESTOP_Damage; + case (SpellType.Nuke): + return SpellEV.NUKE_Damage; + case (SpellType.Translocator): + return SpellEV.TRANSLOCATER_Damage; + case (SpellType.Displacer): + return SpellEV.DISPLACER_Damage; + case (SpellType.Boomerang): + return SpellEV.BOOMERANG_Damage; + case (SpellType.DualBlades): + return SpellEV.DUAL_BLADES_Damage; + case (SpellType.Close): + return SpellEV.CLOSE_Damage; + case (SpellType.DamageShield): + return SpellEV.DAMAGE_SHIELD_Damage; + case (SpellType.Bounce): + return SpellEV.BOUNCE_Damage; + case (SpellType.Laser): + return SpellEV.LASER_Damage; + case (SpellType.DragonFire): + return SpellEV.DRAGONFIRE_Damage; + case (SpellType.DragonFireNeo): + return SpellEV.DRAGONFIRENEO_Damage; + case (SpellType.RapidDagger): + return SpellEV.RAPIDDAGGER_Damage; + } + + return 0; + } + + public static float GetXValue(byte spellType) + { + switch (spellType) + { + case (SpellType.Dagger): + return SpellEV.DAGGER_XVal; + case (SpellType.Axe): + return SpellEV.AXE_XVal; + case (SpellType.TimeBomb): + return SpellEV.TIMEBOMB_XVal; + case (SpellType.TimeStop): + return SpellEV.TIMESTOP_XVal; + case (SpellType.Nuke): + return SpellEV.NUKE_XVal; + case (SpellType.Translocator): + return SpellEV.TRANSLOCATER_XVal; + case (SpellType.Displacer): + return SpellEV.DISPLACER_XVal; + case (SpellType.Boomerang): + return SpellEV.BOOMERANG_XVal; + case (SpellType.DualBlades): + return SpellEV.DUAL_BLADES_XVal; + case (SpellType.Close): + return SpellEV.CLOSE_XVal; + case (SpellType.DamageShield): + return SpellEV.DAMAGE_SHIELD_XVal; + case (SpellType.Bounce): + return SpellEV.BOUNCE_XVal; + case (SpellType.Laser): + return SpellEV.LASER_XVal; + case (SpellType.DragonFire): + return SpellEV.DRAGONFIRE_XVal; + case (SpellType.DragonFireNeo): + return SpellEV.DRAGONFIRENEO_XVal; + } + + return 0; + } + + public static float GetYValue(byte spellType) + { + switch (spellType) + { + case (SpellType.Dagger): + return SpellEV.DAGGER_YVal; + case (SpellType.Axe): + return SpellEV.AXE_YVal; + case (SpellType.TimeBomb): + return SpellEV.TIMEBOMB_YVal; + case (SpellType.TimeStop): + return SpellEV.TIMESTOP_YVal; + case (SpellType.Nuke): + return SpellEV.NUKE_YVal; + case (SpellType.Translocator): + return SpellEV.TRANSLOCATER_YVal; + case (SpellType.Displacer): + return SpellEV.DISPLACER_YVal; + case (SpellType.Boomerang): + return SpellEV.BOOMERANG_YVal; + case (SpellType.DualBlades): + return SpellEV.DUAL_BLADES_YVal; + case (SpellType.Close): + return SpellEV.CLOSE_YVal; + case (SpellType.DamageShield): + return SpellEV.DAMAGE_SHIELD_YVal; + case (SpellType.Bounce): + return SpellEV.BOUNCE_YVal; + case (SpellType.Laser): + return SpellEV.LASER_YVal; + case (SpellType.DragonFire): + return SpellEV.DRAGONFIRE_YVal; + case (SpellType.DragonFireNeo): + return SpellEV.DRAGONFIRENEO_YVal; + } + + return 0; + } + } +} diff --git a/RogueCastle/src/EnemyBuilder.cs b/RogueCastle/src/EnemyBuilder.cs new file mode 100644 index 0000000..7fec65b --- /dev/null +++ b/RogueCastle/src/EnemyBuilder.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyBuilder + { + public static EnemyObj BuildEnemy(int enemyType, PlayerObj player, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty, bool doNotInitialize = false) + { + EnemyObj objToReturn = null; + switch (enemyType) + { + case (EnemyType.Skeleton): + objToReturn = new EnemyObj_Skeleton(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Knight): + objToReturn = new EnemyObj_Knight(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Fireball): + objToReturn = new EnemyObj_Fireball(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Fairy): + objToReturn = new EnemyObj_Fairy(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Turret): + objToReturn = new EnemyObj_Turret(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Wall): + objToReturn = new EnemyObj_Wall(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Horse): + objToReturn = new EnemyObj_Horse(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Zombie): + objToReturn = new EnemyObj_Zombie(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Wolf): + objToReturn = new EnemyObj_Wolf(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.BallAndChain): + objToReturn = new EnemyObj_BallAndChain(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Eyeball): + objToReturn = new EnemyObj_Eyeball(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Ninja): + objToReturn = new EnemyObj_Ninja(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Blob): + objToReturn = new EnemyObj_Blob(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.SwordKnight): + objToReturn = new EnemyObj_SwordKnight(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Eagle): + objToReturn = new EnemyObj_Eagle(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.ShieldKnight): + objToReturn = new EnemyObj_ShieldKnight(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.FireWizard): + objToReturn = new EnemyObj_FireWizard(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.IceWizard): + objToReturn = new EnemyObj_IceWizard(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.EarthWizard): + objToReturn = new EnemyObj_EarthWizard(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.BouncySpike): + objToReturn = new EnemyObj_BouncySpike(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.SpikeTrap): + objToReturn = new EnemyObj_SpikeTrap(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Plant): + objToReturn = new EnemyObj_Plant(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Energon): + objToReturn = new EnemyObj_Energon(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Spark): + objToReturn = new EnemyObj_Spark(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.SkeletonArcher): + objToReturn = new EnemyObj_SkeletonArcher(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Chicken): + objToReturn = new EnemyObj_Chicken(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Platform): + objToReturn = new EnemyObj_Platform(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.HomingTurret): + objToReturn = new EnemyObj_HomingTurret(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.LastBoss): + objToReturn = new EnemyObj_LastBoss(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Dummy): + objToReturn = new EnemyObj_Dummy(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Starburst): + objToReturn = new EnemyObj_Starburst(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Portrait): + objToReturn = new EnemyObj_Portrait(player, physicsManager, levelToAttachTo, difficulty); + break; + case (EnemyType.Mimic): + objToReturn = new EnemyObj_Mimic(player, physicsManager, levelToAttachTo, difficulty); + break; + } + + if (player == null && doNotInitialize == false) + objToReturn.Initialize(); + return objToReturn; + } + } +} diff --git a/RogueCastle/src/EquipmentSystem.cs b/RogueCastle/src/EquipmentSystem.cs new file mode 100644 index 0000000..5c6221a --- /dev/null +++ b/RogueCastle/src/EquipmentSystem.cs @@ -0,0 +1,244 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EquipmentSystem + { + private List m_equipmentDataArray; + private List m_abilityCostArray; + private float AbilityCostMod = 175;//200;//175; //200; + private int AbilityCostBase = 175;//200;//175; //200; + + public EquipmentSystem() + { + m_equipmentDataArray = new List(); + for (int i = 0; i < EquipmentCategoryType.Total; i++) + { + EquipmentData[] dataArray = new EquipmentData[EquipmentBaseType.Total]; + for (int j = 0; j < EquipmentBaseType.Total; j++) + dataArray[j] = new EquipmentData(); + m_equipmentDataArray.Add(dataArray); + } + + m_abilityCostArray = new List(); + for (int i = 0; i < EquipmentCategoryType.Total; i++) + { + int[] dataArray = new int[EquipmentAbilityType.Total]; + for (int j = 0; j < EquipmentAbilityType.Total; j++) + dataArray[j] = 9999; + m_abilityCostArray.Add(dataArray); + } + } + + public void InitializeAbilityCosts() + { + m_abilityCostArray[EquipmentCategoryType.Sword][EquipmentAbilityType.DoubleJump] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Sword][EquipmentAbilityType.Dash] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Sword][EquipmentAbilityType.Vampirism] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Sword][EquipmentAbilityType.Flight] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Sword][EquipmentAbilityType.ManaGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Sword][EquipmentAbilityType.MovementSpeed] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Sword][EquipmentAbilityType.DamageReturn] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Sword][EquipmentAbilityType.GoldGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Sword][EquipmentAbilityType.ManaHPGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Sword][EquipmentAbilityType.RoomLevelDown] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Sword][EquipmentAbilityType.RoomLevelUp] = AbilityCostBase; + + m_abilityCostArray[EquipmentCategoryType.Cape][EquipmentAbilityType.DoubleJump] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Cape][EquipmentAbilityType.Dash] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Cape][EquipmentAbilityType.Vampirism] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Cape][EquipmentAbilityType.Flight] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Cape][EquipmentAbilityType.ManaGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Cape][EquipmentAbilityType.MovementSpeed] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Cape][EquipmentAbilityType.DamageReturn] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Cape][EquipmentAbilityType.GoldGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Cape][EquipmentAbilityType.ManaHPGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Cape][EquipmentAbilityType.RoomLevelDown] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Cape][EquipmentAbilityType.RoomLevelUp] = AbilityCostBase; + + m_abilityCostArray[EquipmentCategoryType.Chest][EquipmentAbilityType.DoubleJump] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Chest][EquipmentAbilityType.Dash] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Chest][EquipmentAbilityType.Vampirism] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Chest][EquipmentAbilityType.Flight] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Chest][EquipmentAbilityType.ManaGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Chest][EquipmentAbilityType.MovementSpeed] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Chest][EquipmentAbilityType.DamageReturn] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Chest][EquipmentAbilityType.GoldGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Chest][EquipmentAbilityType.ManaHPGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Chest][EquipmentAbilityType.RoomLevelDown] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Chest][EquipmentAbilityType.RoomLevelUp] = AbilityCostBase; + + m_abilityCostArray[EquipmentCategoryType.Limbs][EquipmentAbilityType.DoubleJump] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Limbs][EquipmentAbilityType.Dash] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Limbs][EquipmentAbilityType.Vampirism] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Limbs][EquipmentAbilityType.Flight] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Limbs][EquipmentAbilityType.ManaGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Limbs][EquipmentAbilityType.MovementSpeed] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Limbs][EquipmentAbilityType.DamageReturn] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Limbs][EquipmentAbilityType.GoldGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Limbs][EquipmentAbilityType.ManaHPGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Limbs][EquipmentAbilityType.RoomLevelDown] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Limbs][EquipmentAbilityType.RoomLevelUp] = AbilityCostBase; + + m_abilityCostArray[EquipmentCategoryType.Helm][EquipmentAbilityType.DoubleJump] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Helm][EquipmentAbilityType.Dash] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Helm][EquipmentAbilityType.Vampirism] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Helm][EquipmentAbilityType.Flight] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Helm][EquipmentAbilityType.ManaGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Helm][EquipmentAbilityType.MovementSpeed] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Helm][EquipmentAbilityType.DamageReturn] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Helm][EquipmentAbilityType.GoldGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Helm][EquipmentAbilityType.ManaHPGain] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Helm][EquipmentAbilityType.RoomLevelDown] = AbilityCostBase; + m_abilityCostArray[EquipmentCategoryType.Helm][EquipmentAbilityType.RoomLevelUp] = AbilityCostBase; + + + } + + public void InitializeEquipmentData() + { + //Equipment Type, Equipment Index, Health, Mana, Damage, Weight, Color1, Color2, Cost, Secondary Attributes. + //CreateEquipmentData(EquipmentCategoryType.Sword, 0, 10, 0.1f, 0, 10, 5, Color.Green, Color.Blue, 100, new Vector2(EquipmentSecondaryDataType.CritDamage, 1), new Vector2(EquipmentSecondaryDataType.CritDamage, 10)); + CreateEquipmentData(EquipmentCategoryType.Sword, 1, 0, 0, 250, 15, 0, 7, 0, 0, 0, new Color(255, 230, 175), new Color(70, 130, 255)); + CreateEquipmentData(EquipmentCategoryType.Helm, 1, 0, 0, 150, 10, 20, 0, 0, 5, 0, new Color(255, 221, 130), new Color(70, 130, 255)); + CreateEquipmentData(EquipmentCategoryType.Cape, 3, 2, 0, 300, 10, 0, 0, 0, 0, 0, new Color(255, 221, 130), new Color(0, 0, 0), new Vector2(EquipmentSecondaryDataType.CritChance, 0.04f)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 1, 0, 0, 200, 10, 0, 0, 0, 0, 5, new Color(210, 195, 125), new Color(210, 195, 125)); + CreateEquipmentData(EquipmentCategoryType.Chest, 1, 0, 0, 350, 20, 0, 0, 9, 0, 0, new Color(190, 165, 105), new Color(155, 190, 366)); + CreateEquipmentData(EquipmentCategoryType.Sword, 5, 0, 5, 375, 20, 0, 11, 0, 0, 0, new Color(135, 135, 135), new Color(95, 95, 95)); + CreateEquipmentData(EquipmentCategoryType.Helm, 3, 0, 5, 250, 15, 25, 0, 0, 20, 0, new Color(165, 165, 165), new Color(125, 235, 80)); + CreateEquipmentData(EquipmentCategoryType.Cape, 5, 0, 5, 425, 15, 0, 0, 0, 0, 0, new Color(125, 235, 80), new Color(0, 0, 0), new Vector2(EquipmentSecondaryDataType.CritDamage, 0.15f)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 3, 0, 5, 375, 20, 0, 0, 0, 0, 11, new Color(155, 155, 155), new Color(155, 155, 155)); + CreateEquipmentData(EquipmentCategoryType.Chest, 3, 0, 5, 525, 30, 0, 0, 16, 0, 0, new Color(120, 120, 120), new Color(95, 95, 95)); + CreateEquipmentData(EquipmentCategoryType.Sword, 1, 2, 10, 500, 35, -30, 9, 0, 0, 0, new Color(105, 0, 0), new Color(105, 0, 0), new Vector2(EquipmentSecondaryDataType.Vampirism, 1)); + CreateEquipmentData(EquipmentCategoryType.Helm, 1, 3, 10, 500, 35, -30, 0, 0, 25, 0, new Color(230, 0, 0), new Color(105, 0, 0), new Vector2(EquipmentSecondaryDataType.Vampirism, 1)); + CreateEquipmentData(EquipmentCategoryType.Cape, 1, 2, 10, 500, 35, -30, 0, 0, 0, 0, new Color(230, 0, 0), new Color(0, 0, 0), new Vector2(EquipmentSecondaryDataType.Vampirism, 1)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 1, 3, 10, 500, 35, -30, 0, 0, 0, 9, new Color(230, 0, 0), new Color(105, 0, 0), new Vector2(EquipmentSecondaryDataType.Vampirism, 1)); + CreateEquipmentData(EquipmentCategoryType.Chest, 1, 2, 10, 500, 35, -30, 0, 14, 0, 0, new Color(230, 0, 0), new Color(105, 0, 0), new Vector2(EquipmentSecondaryDataType.Vampirism, 1)); + CreateEquipmentData(EquipmentCategoryType.Sword, 10, 2, 1, 750, 35, 0, 17, 0, 0, 0, new Color(245, 255, 175), new Color(215, 215, 215)); + CreateEquipmentData(EquipmentCategoryType.Helm, 8, 0, 1, 550, 25, 35, 0, 0, 25, 0, new Color(245, 255, 175), new Color(215, 215, 215)); + CreateEquipmentData(EquipmentCategoryType.Cape, 11, 2, 1, 850, 35, 0, 0, 0, 0, 0, new Color(245, 255, 175), new Color(0, 0, 0), new Vector2(EquipmentSecondaryDataType.ManaDrain, 1)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 8, 0, 1, 750, 35, 0, 0, 0, 0, 17, new Color(245, 255, 175), new Color(245, 255, 175)); + CreateEquipmentData(EquipmentCategoryType.Chest, 8, 0, 1, 950, 45, 0, 0, 25, 0, 0, new Color(245, 255, 175), new Color(215, 215, 215)); + CreateEquipmentData(EquipmentCategoryType.Sword, 15, 2, 6, 1150, 40, 0, 22, 0, 0, 0, new Color(10, 150, 50), new Color(10, 150, 50)); + CreateEquipmentData(EquipmentCategoryType.Helm, 12, 0, 6, 950, 30, 55, 0, 0, 15, 0, new Color(180, 120, 70), new Color(78, 181, 80)); + CreateEquipmentData(EquipmentCategoryType.Cape, 13, 2, 6, 1300, 40, 0, 0, 0, 0, 0, new Color(135, 200, 130), new Color(0, 0, 0), new Vector2(EquipmentSecondaryDataType.CritChance, 0.04f), new Vector2(EquipmentSecondaryDataType.CritDamage, 0.15f)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 12, 0, 6, 1075, 40, 0, 0, 0, 0, 22, new Color(160, 125, 80), new Color(160, 125, 80)); + CreateEquipmentData(EquipmentCategoryType.Chest, 12, 0, 6, 1500, 55, 0, 0, 38, 0, 0, new Color(180, 120, 70), new Color(145, 55, 15)); + CreateEquipmentData(EquipmentCategoryType.Sword, 10, 2, 11, 1250, 45, 0, -10, 0, 0, 0, new Color(240, 235, 90), new Color(215, 135, 75), new Vector2(EquipmentSecondaryDataType.GoldBonus, 0.1f)); + CreateEquipmentData(EquipmentCategoryType.Helm, 10, 3, 11, 1250, 45, 0, -10, 0, 0, 0, new Color(240, 235, 90), new Color(215, 135, 75), new Vector2(EquipmentSecondaryDataType.GoldBonus, 0.1f)); + CreateEquipmentData(EquipmentCategoryType.Cape, 10, 3, 11, 1250, 75, 0, 0, 0, 0, 0, new Color(210, 240, 75), new Color(0, 0, 0), new Vector2(EquipmentSecondaryDataType.GoldBonus, 0.1f)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 10, 2, 11, 1250, 45, 0, -10, 0, 0, 0, new Color(235, 220, 135), new Color(235, 220, 135), new Vector2(EquipmentSecondaryDataType.GoldBonus, 0.1f)); + CreateEquipmentData(EquipmentCategoryType.Chest, 10, 3, 11, 1250, 45, 0, -10, 0, 0, 0, new Color(240, 235, 90), new Color(235, 135, 75), new Vector2(EquipmentSecondaryDataType.GoldBonus, 0.1f)); + CreateEquipmentData(EquipmentCategoryType.Sword, 18, 0, 2, 1450, 55, 0, 14, 12, 0, 0, new Color(255, 190, 45), new Color(240, 230, 0)); + CreateEquipmentData(EquipmentCategoryType.Helm, 15, 0, 2, 1200, 45, 20, 0, 18, 20, 0, new Color(255, 190, 45), new Color(240, 230, 0)); + CreateEquipmentData(EquipmentCategoryType.Cape, 19, 2, 2, 1600, 40, 0, 0, 27, 0, 0, new Color(255, 190, 45), new Color(0, 0, 0)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 15, 0, 2, 1400, 45, 0, 0, 18, 0, 10, new Color(255, 190, 45), new Color(240, 230, 0)); + CreateEquipmentData(EquipmentCategoryType.Chest, 15, 3, 2, 1875, 80, 0, 0, 70, 0, 0, new Color(255, 190, 45), new Color(240, 230, 0)); + CreateEquipmentData(EquipmentCategoryType.Sword, 21, 2, 7, 1700, 45, 0, 27, 0, 0, 0, new Color(170, 255, 250), new Color(255, 245, 255)); + CreateEquipmentData(EquipmentCategoryType.Helm, 18, 0, 7, 1500, 40, 40, 0, 0, 45, 0, new Color(115, 175, 185), new Color(255, 245, 255)); + CreateEquipmentData(EquipmentCategoryType.Cape, 23, 2, 7, 2100, 55, 0, 0, 0, 0, 0, new Color(170, 255, 250), new Color(0, 0, 0), new Vector2(EquipmentSecondaryDataType.DoubleJump, 2)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 18, 0, 7, 1800, 50, 0, 0, 0, 0, 32, new Color(255, 245, 255), new Color(255, 245, 255)); + CreateEquipmentData(EquipmentCategoryType.Chest, 18, 0, 7, 1650, 65, 0, 0, 48, 0, 0, new Color(115, 175, 185), new Color(170, 255, 250)); + CreateEquipmentData(EquipmentCategoryType.Sword, 20, 3, 12, 1600, 50, 0, 15, -15, 0, 0, new Color(60, 60, 60), new Color(30, 30, 30), new Vector2(EquipmentSecondaryDataType.DamageReturn, 0.5f)); + CreateEquipmentData(EquipmentCategoryType.Helm, 20, 3, 12, 1400, 50, 30, 0, -15, 30, 0, new Color(90, 90, 90), new Color(30, 30, 30), new Vector2(EquipmentSecondaryDataType.DamageReturn, 0.5f)); + CreateEquipmentData(EquipmentCategoryType.Cape, 20, 2, 12, 1800, 35, 0, 0, -15, 0, 0, new Color(85, 15, 5), new Color(0, 0, 0), new Vector2(EquipmentSecondaryDataType.DamageReturn, 0.5f)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 20, 3, 12, 1500, 50, 0, 0, -15, 0, 15, new Color(30, 30, 30), new Color(90, 90, 90), new Vector2(EquipmentSecondaryDataType.DamageReturn, 0.5f)); + CreateEquipmentData(EquipmentCategoryType.Chest, 20, 2, 12, 1850, 50, 30, 0, -15, 30, 0, new Color(90, 90, 90), new Color(30, 30, 30), new Vector2(EquipmentSecondaryDataType.DamageReturn, 0.5f)); + CreateEquipmentData(EquipmentCategoryType.Sword, 27, 2, 3, 2300, 55, 0, 36, 0, 0, 0, new Color(240, 230, 0), new Color(240, 230, 0)); + CreateEquipmentData(EquipmentCategoryType.Helm, 25, 0, 3, 1900, 50, 55, 0, 0, 40, 0, new Color(115, 100, 190), new Color(240, 230, 0)); + CreateEquipmentData(EquipmentCategoryType.Cape, 29, 2, 3, 2600, 55, 0, 0, 0, 0, 0, new Color(55, 0, 145), new Color(0, 0, 0), new Vector2(EquipmentSecondaryDataType.CritDamage, 0.5f)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 25, 0, 3, 2250, 55, 0, 0, 0, 0, 36, new Color(115, 100, 190), new Color(50, 55, 210)); + CreateEquipmentData(EquipmentCategoryType.Chest, 25, 2, 3, 3000, 75, 0, 0, 59, 0, 0, new Color(115, 100, 190), new Color(50, 55, 210)); + CreateEquipmentData(EquipmentCategoryType.Sword, 31, 2, 8, 2800, 75, 0, 46, 0, 0, 0, new Color(200, 0, 0), new Color(50, 50, 50)); + CreateEquipmentData(EquipmentCategoryType.Helm, 29, 0, 8, 2400, 60, 75, 0, 0, 60, 0, new Color(50, 50, 50), new Color(120, 0, 0)); + CreateEquipmentData(EquipmentCategoryType.Cape, 34, 3, 8, 3200, 75, 0, 0, 0, 0, 0, new Color(255, 0, 0), new Color(0, 0, 0), new Vector2(EquipmentSecondaryDataType.Vampirism, 2)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 29, 0, 8, 2600, 60, 0, 0, 0, 0, 42, new Color(50, 50, 50), new Color(50, 50, 50)); + CreateEquipmentData(EquipmentCategoryType.Chest, 29, 2, 8, 3750, 85, 0, 0, 78, 0, 0, new Color(160, 0, 0), new Color(80, 0, 0)); + CreateEquipmentData(EquipmentCategoryType.Sword, 30, 3, 13, 3200, 55, 0, 20, 0, 25, 0, new Color(215, 245, 70), new Color(255, 255, 255), new Vector2(EquipmentSecondaryDataType.ManaDrain, 1)); + CreateEquipmentData(EquipmentCategoryType.Helm, 30, 3, 13, 2800, 55, 25, 0, 0, 50, 0, new Color(215, 245, 70), new Color(255, 255, 255), new Vector2(EquipmentSecondaryDataType.ManaDrain, 1)); + CreateEquipmentData(EquipmentCategoryType.Cape, 30, 3, 13, 3300, 65, 0, 0, 0, 25, 0, new Color(215, 245, 70), new Color(0, 0, 0), new Vector2(EquipmentSecondaryDataType.ManaDrain, 1)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 30, 3, 13, 3000, 100, 0, 0, 0, 25, 72, new Color(215, 245, 70), new Color(255, 255, 255), new Vector2(EquipmentSecondaryDataType.ManaDrain, 1)); + CreateEquipmentData(EquipmentCategoryType.Chest, 30, 2, 13, 3800, 65, 0, 0, 40, 25, 0, new Color(215, 245, 70), new Color(255, 255, 255), new Vector2(EquipmentSecondaryDataType.ManaDrain, 1)); + CreateEquipmentData(EquipmentCategoryType.Sword, 40, 3, 4, 4250, 85, 0, 60, 0, 0, 0, new Color(20, 60, 255), new Color(255, 40, 40)); + CreateEquipmentData(EquipmentCategoryType.Helm, 38, 0, 4, 3750, 70, 90, 0, 0, 90, 0, new Color(180, 180, 180), new Color(110, 100, 240)); + CreateEquipmentData(EquipmentCategoryType.Cape, 43, 2, 4, 4100, 80, 0, 0, 0, 0, 0, new Color(255, 255, 255), new Color(0, 0, 0), new Vector2(EquipmentSecondaryDataType.Flight, 3)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 38, 0, 4, 3800, 85, 0, 0, 0, 0, 60, new Color(150, 150, 150), new Color(120, 120, 120)); + CreateEquipmentData(EquipmentCategoryType.Chest, 38, 2, 4, 4500, 125, 0, 0, 100, 0, 0, new Color(120, 120, 120), new Color(105, 80, 240)); + CreateEquipmentData(EquipmentCategoryType.Sword, 52, 2, 9, 4750, 75, 0, 40, 0, 0, 0, new Color(125, 125, 125), new Color(60, 130, 70), new Vector2(EquipmentSecondaryDataType.CritChance, 0.04f), new Vector2(EquipmentSecondaryDataType.CritDamage, 0.15f), new Vector2(EquipmentSecondaryDataType.DamageReturn, 0.5f)); + CreateEquipmentData(EquipmentCategoryType.Helm, 49, 2, 9, 3900, 65, 40, 0, 0, 40, 0, new Color(255, 255, 255), new Color(70, 70, 70), new Vector2(EquipmentSecondaryDataType.CritChance, 0.04f), new Vector2(EquipmentSecondaryDataType.CritDamage, 0.15f), new Vector2(EquipmentSecondaryDataType.DamageReturn, 0.5f)); + CreateEquipmentData(EquipmentCategoryType.Cape, 57, 2, 9, 5750, 85, 0, 0, 0, 0, 0, new Color(255, 250, 120), new Color(0, 0, 0), new Vector2(EquipmentSecondaryDataType.CritChance, 0.04f), new Vector2(EquipmentSecondaryDataType.CritDamage, 0.15f), new Vector2(EquipmentSecondaryDataType.DamageReturn, 0.5f)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 46, 2, 9, 4600, 60, 0, 0, 0, 0, 40, new Color(255, 255, 255), new Color(70, 70, 70), new Vector2(EquipmentSecondaryDataType.CritChance, 0.04f), new Vector2(EquipmentSecondaryDataType.CritDamage, 0.15f), new Vector2(EquipmentSecondaryDataType.DamageReturn, 0.5f)); + CreateEquipmentData(EquipmentCategoryType.Chest, 46, 2, 9, 6750, 140, 0, 0, 50, 0, 0, new Color(255, 255, 255), new Color(70, 70, 70), new Vector2(EquipmentSecondaryDataType.CritChance, 0.04f), new Vector2(EquipmentSecondaryDataType.CritDamage, 0.15f), new Vector2(EquipmentSecondaryDataType.DamageReturn, 0.5f)); + CreateEquipmentData(EquipmentCategoryType.Sword, 50, 3, 14, 6000, 100, 0, 50, 0, 0, 0, new Color(15, 15, 15), new Color(15, 15, 15), new Vector2(EquipmentSecondaryDataType.Vampirism, 1), new Vector2(EquipmentSecondaryDataType.ManaDrain, 1), new Vector2(EquipmentSecondaryDataType.AirDash, 1)); + CreateEquipmentData(EquipmentCategoryType.Helm, 50, 3, 14, 6000, 100, 60, 0, 0, 60, 0, new Color(45, 45, 45), new Color(15, 15, 15), new Vector2(EquipmentSecondaryDataType.Vampirism, 1), new Vector2(EquipmentSecondaryDataType.ManaDrain, 1), new Vector2(EquipmentSecondaryDataType.DoubleJump, 1)); + CreateEquipmentData(EquipmentCategoryType.Cape, 50, 3, 14, 6000, 100, 0, 0, 0, 0, 0, new Color(15, 15, 15), new Color(15, 15, 15), new Vector2(EquipmentSecondaryDataType.Vampirism, 1), new Vector2(EquipmentSecondaryDataType.ManaDrain, 1), new Vector2(EquipmentSecondaryDataType.DoubleJump, 1)); + CreateEquipmentData(EquipmentCategoryType.Limbs, 50, 3, 14, 6000, 100, 0, 0, 0, 0, 50, new Color(45, 45, 45), new Color(45, 45, 45), new Vector2(EquipmentSecondaryDataType.Vampirism, 1), new Vector2(EquipmentSecondaryDataType.ManaDrain, 1), new Vector2(EquipmentSecondaryDataType.DoubleJump, 1)); + CreateEquipmentData(EquipmentCategoryType.Chest, 50, 3, 14, 6000, 100, 50, 0, 0, 0, 0, new Color(15, 15, 15), new Color(15, 15, 15), new Vector2(EquipmentSecondaryDataType.Vampirism, 1), new Vector2(EquipmentSecondaryDataType.ManaDrain, 1), new Vector2(EquipmentSecondaryDataType.AirDash, 1)); + } + + //private void CreateEquipmentData(int equipmentType, int equipmentIndex, int bonusHealth, float dmgReduc, int bonusMana, int bonusDamage, int weight, Color firstColour, Color secondColour, int cost, params Vector2[] secondaryAttributes) + private void CreateEquipmentData(int equipmentType, byte levelRequirement, byte chestColourRequirement, int equipmentIndex, int cost, int weight, int bonusHealth, int bonusDamage, int BonusArmor, int bonusMana, int bonusMagic, Color firstColour, Color secondColour, params Vector2[] secondaryAttributes) + { + EquipmentData data = new EquipmentData(); + data.BonusDamage = bonusDamage; + data.BonusHealth = bonusHealth; + data.BonusArmor = BonusArmor; + data.BonusMana = bonusMana; + data.BonusMagic = bonusMagic; + data.Weight = weight; + data.FirstColour = firstColour; + data.SecondColour = secondColour; + data.Cost = cost; + data.LevelRequirement = levelRequirement; + data.ChestColourRequirement = chestColourRequirement; + data.SecondaryAttribute = new Vector2[secondaryAttributes.Length]; + for (int i = 0; i < secondaryAttributes.Length; i++) + { + data.SecondaryAttribute[i] = secondaryAttributes[i]; + } + + m_equipmentDataArray[equipmentType][equipmentIndex] = data; + } + + public EquipmentData GetEquipmentData(int categoryType, int equipmentIndex) + { + return m_equipmentDataArray[categoryType][equipmentIndex]; + } + + public int GetAbilityCost(int categoryType, int itemIndex) + { + return (int)(m_abilityCostArray[categoryType][itemIndex] + (Game.PlayerStats.TotalRunesPurchased * AbilityCostMod)); + } + + public int GetBaseAbilityCost(int categoryType, int itemIndex) + { + return (m_abilityCostArray[categoryType][itemIndex]); + } + + public void SetBlueprintState(byte state) + { + foreach (byte[] stateArray in Game.PlayerStats.GetBlueprintArray) + { + for (int i = 0; i < stateArray.Length; i++) + { + if (stateArray[i] < state) + stateArray[i] = state; + } + } + + foreach (byte[] stateArray in Game.PlayerStats.GetRuneArray) + { + for (int i = 0; i < stateArray.Length; i++) + { + if (stateArray[i] < state) + stateArray[i] = state; + } + } + } + } +} diff --git a/RogueCastle/src/FrameRateCounter.cs b/RogueCastle/src/FrameRateCounter.cs new file mode 100644 index 0000000..af60d18 --- /dev/null +++ b/RogueCastle/src/FrameRateCounter.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class FrameRateCounter : DrawableGameComponent + { + ContentManager content; + SpriteBatch spriteBatch; + SpriteFont spriteFont; + + int frameRate = 0; + int frameCounter = 0; + TimeSpan elapsedTime = TimeSpan.Zero; + + + public FrameRateCounter(Game game) + : base(game) + { + this.content = Game.Content; + } + + + + protected override void LoadContent() + { + spriteBatch = new SpriteBatch(GraphicsDevice); + spriteFont = content.Load("Fonts\\FpsFont"); + } + + protected override void UnloadContent() + { + content.Unload(); + } + + + public override void Update(GameTime gameTime) + { + elapsedTime += gameTime.ElapsedGameTime; + + if (elapsedTime > TimeSpan.FromSeconds(1)) + { + elapsedTime -= TimeSpan.FromSeconds(1); + frameRate = frameCounter; + frameCounter = 0; + } + } + + + public override void Draw(GameTime gameTime) + { + frameCounter++; + + string fps = string.Format("fps: {0}", frameRate); + + spriteBatch.Begin(); + + spriteBatch.DrawString(spriteFont, fps, new Vector2(GlobalEV.ScreenWidth - 150, 33), Color.Black); + spriteBatch.DrawString(spriteFont, fps, new Vector2(GlobalEV.ScreenWidth - 149, 32), Color.White); + + spriteBatch.End(); + } + } +} diff --git a/RogueCastle/src/Game Objects/BlacksmithObj.cs b/RogueCastle/src/Game Objects/BlacksmithObj.cs new file mode 100644 index 0000000..5967780 --- /dev/null +++ b/RogueCastle/src/Game Objects/BlacksmithObj.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class BlacksmithObj : ObjContainer + { + private const int PART_ASSET1 = 0; + private const int PART_ASSET2 = 1; + private const int PART_BODY = 2; + private const int PART_HEAD = 3; + private const int PART_HEADTRIM = 4; + private const int PART_ARM = 5; + + private SpriteObj m_hammerSprite; + private SpriteObj m_headSprite; + private float m_hammerAnimCounter = 0; + + public BlacksmithObj() + : base("Blacksmith_Character") + { + m_hammerSprite = _objectList[PART_ARM] as SpriteObj; + m_headSprite = _objectList[PART_HEAD] as SpriteObj; + this.AnimationDelay = 1 / 10f; + } + + public void Update(GameTime gameTime) + { + if (m_hammerAnimCounter <= 0 && m_hammerSprite.IsAnimating == false) + { + m_hammerSprite.PlayAnimation(false); + m_hammerAnimCounter = CDGMath.RandomFloat(0.5f, 3); + } + else + m_hammerAnimCounter -= (float)gameTime.ElapsedGameTime.TotalSeconds; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_hammerSprite = null; + m_headSprite = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/BorderObj.cs b/RogueCastle/src/Game Objects/BorderObj.cs new file mode 100644 index 0000000..684cf2b --- /dev/null +++ b/RogueCastle/src/Game Objects/BorderObj.cs @@ -0,0 +1,302 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; +using System.Globalization; + +namespace RogueCastle +{ + public class BorderObj : GameObj + { + public bool BorderTop = false; + public bool BorderBottom = false; + public bool BorderLeft = false; + public bool BorderRight = false; + + public GameTypes.LevelType LevelType = GameTypes.LevelType.CASTLE; + public Texture2D BorderTexture { get; internal set; } + public SpriteObj CornerTexture { get; internal set; } + public SpriteObj CornerLTexture { get; internal set; } + + public Texture2D NeoTexture { get; set; } + public Vector2 TextureScale { get; set; } + public Vector2 TextureOffset { get; set; } + + public BorderObj() + { + TextureScale = new Vector2(1, 1); + CornerTexture = new SpriteObj("Blank_Sprite"); + CornerTexture.Scale = new Vector2(2, 2); + CornerLTexture = new SpriteObj("Blank_Sprite"); + CornerLTexture.Scale = new Vector2(2, 2); + } + + public void SetBorderTextures(Texture2D borderTexture, string cornerTextureString, string cornerLTextureString) + { + BorderTexture = borderTexture; + CornerTexture.ChangeSprite(cornerTextureString); + CornerLTexture.ChangeSprite(cornerLTextureString); + } + + public void SetWidth(int width) + { + _width = width; + } + + public void SetHeight(int height) + { + _height = height; + if (height < 60) + { + BorderBottom = false; + BorderLeft = false; + BorderRight = false; + this.TextureColor = new Color(150, 150, 150); + } + } + + public override void Draw(Camera2D camera) + { + Texture2D borderTexture = BorderTexture; + if (Game.PlayerStats.Traits.X == TraitType.TheOne || Game.PlayerStats.Traits.Y == TraitType.TheOne) + { + TextureOffset = Vector2.Zero; + borderTexture = NeoTexture; + } + + // Drawing the sides. + if (BorderBottom == true) + camera.Draw(borderTexture, new Vector2(this.Bounds.Right - CornerTexture.Width + TextureOffset.X, this.Bounds.Bottom - TextureOffset.Y), new Rectangle(0, 0, (int)(Width * 1 / TextureScale.X) - CornerTexture.Width * 2, borderTexture.Height), this.TextureColor, MathHelper.ToRadians(180), Vector2.Zero, this.TextureScale, SpriteEffects.None, 0); + + if (BorderLeft == true) + camera.Draw(borderTexture, new Vector2(this.X + TextureOffset.Y, this.Bounds.Bottom - CornerTexture.Width - TextureOffset.X), new Rectangle(0, 0, (int)(Height * 1 / TextureScale.Y) - CornerTexture.Width * 2, borderTexture.Height), this.TextureColor, MathHelper.ToRadians(-90), Vector2.Zero, this.TextureScale, SpriteEffects.None, 0); + + if (BorderRight == true) + camera.Draw(borderTexture, new Vector2(this.Bounds.Right - TextureOffset.Y, this.Y + CornerTexture.Width + TextureOffset.X), new Rectangle(0, 0, (int)(Height * 1 / TextureScale.Y) - CornerTexture.Width * 2, borderTexture.Height), this.TextureColor, MathHelper.ToRadians(90), Vector2.Zero, this.TextureScale, SpriteEffects.None, 0); + + if (BorderTop == true) + { + if (this.Rotation == 0) + camera.Draw(borderTexture, new Vector2(this.X + CornerTexture.Width + TextureOffset.X, this.Y + TextureOffset.Y), new Rectangle(0, 0, (int)(Width * 1 / TextureScale.X) - CornerTexture.Width * 2, borderTexture.Height), this.TextureColor, MathHelper.ToRadians(this.Rotation), Vector2.Zero, this.TextureScale, SpriteEffects.None, 0); + else + { + // Special borders for angled terrain. + Vector2 topLeftCorner = CollisionMath.UpperLeftCorner(new Rectangle((int)this.X, (int)this.Y, _width, _height), this.Rotation, Vector2.Zero); + Vector2 topRightCorner = CollisionMath.UpperRightCorner(new Rectangle((int)this.X, (int)this.Y, _width, _height), this.Rotation, Vector2.Zero); + + //if (this.Rotation == 45) // ROTCHECK + if (this.Rotation > 0 && this.Rotation < 80) + { + CornerTexture.Flip = SpriteEffects.FlipHorizontally; + CornerTexture.Position = topLeftCorner; + CornerTexture.Rotation = 0; + CornerTexture.Draw(camera); + + CornerTexture.Flip = SpriteEffects.None; + CornerTexture.Position = new Vector2(topRightCorner.X - CornerTexture.Width /2f, topRightCorner.Y); + CornerTexture.Rotation = 0; + CornerTexture.Draw(camera); + + } + //else if (this.Rotation == -45) // ROTCHECK + if (this.Rotation < 0 && this.Rotation > -80) + { + CornerTexture.Flip = SpriteEffects.FlipHorizontally; + CornerTexture.Position = topLeftCorner; + CornerTexture.X += CornerTexture.Width / 2f; + CornerTexture.Rotation = 0; + CornerTexture.Draw(camera); + + + CornerTexture.Flip = SpriteEffects.None; + CornerTexture.Position = topRightCorner; + CornerTexture.Rotation = 0; + CornerTexture.Draw(camera); + } + + camera.Draw(borderTexture, new Vector2(this.X + TextureOffset.X - ((float)Math.Sin(MathHelper.ToRadians(this.Rotation)) * TextureOffset.Y), this.Y + ((float)Math.Cos(MathHelper.ToRadians(this.Rotation)) * TextureOffset.Y)), new Rectangle(0, 0, (int)(Width * 1 / TextureScale.X), borderTexture.Height), this.TextureColor, MathHelper.ToRadians(this.Rotation), Vector2.Zero, this.TextureScale, SpriteEffects.None, 0); + } + } + + base.Draw(camera); + } + + public void DrawCorners(Camera2D camera) + { + CornerTexture.TextureColor = this.TextureColor; + CornerLTexture.TextureColor = this.TextureColor; + CornerLTexture.Flip = SpriteEffects.None; + CornerTexture.Flip = SpriteEffects.None; + CornerLTexture.Rotation = 0; + + // Drawing the top borders. + if (BorderTop == true) + { + if (BorderRight == true) // Draw top right corner L + { + CornerLTexture.Position = new Vector2(this.Bounds.Right - CornerLTexture.Width, this.Bounds.Top); + CornerLTexture.Draw(camera); + } + else // Drop a top right corner only + { + CornerTexture.Position = new Vector2(this.Bounds.Right - CornerTexture.Width, this.Bounds.Top); + CornerTexture.Draw(camera); + } + + CornerLTexture.Flip = SpriteEffects.FlipHorizontally; + CornerTexture.Flip = SpriteEffects.FlipHorizontally; + if (BorderLeft == true) // Draw top left corner L + { + CornerLTexture.Position = new Vector2(this.Bounds.Left + CornerLTexture.Width, this.Bounds.Top); + CornerLTexture.Draw(camera); + } + else // Drop a top left corner only + { + CornerTexture.Position = new Vector2(this.Bounds.Left + CornerTexture.Width, this.Bounds.Top); + CornerTexture.Draw(camera); + } + + } + + // Drawing the bottom borders. + if (BorderBottom == true) + { + CornerTexture.Flip = SpriteEffects.FlipVertically; + CornerLTexture.Flip = SpriteEffects.FlipVertically; + + if (BorderRight == true) // Draw bottom right corner L + { + CornerLTexture.Position = new Vector2(this.Bounds.Right - CornerLTexture.Width, this.Bounds.Bottom - CornerLTexture.Height); + CornerLTexture.Draw(camera); + } + else // Draw a bottom right corner only + { + CornerTexture.Flip = SpriteEffects.FlipVertically; + CornerTexture.Position = new Vector2(this.Bounds.Right - CornerTexture.Width, this.Bounds.Bottom - CornerTexture.Height); + CornerTexture.Draw(camera); + } + + if (BorderLeft == true) // Draw bottom left corner L + { + CornerLTexture.Position = new Vector2(this.Bounds.Left + CornerLTexture.Width, this.Bounds.Bottom - CornerLTexture.Height); + CornerLTexture.Rotation = 90; + CornerLTexture.Draw(camera); + CornerLTexture.Rotation = 0; + } + else // Drop a bottom left corner only + { + CornerTexture.Flip = SpriteEffects.None; + CornerTexture.Position = new Vector2(this.Bounds.Left + CornerTexture.Width, this.Bounds.Bottom); + CornerTexture.Rotation = 180; + CornerTexture.Draw(camera); + CornerTexture.Rotation = 0; + } + } + + // Drawing left side corners. + if (BorderLeft == true) + { + CornerTexture.Flip = SpriteEffects.None; + CornerLTexture.Flip = SpriteEffects.None; + + if (BorderBottom == false) + { + CornerTexture.Position = new Vector2(this.Bounds.Left, this.Bounds.Bottom - CornerTexture.Width); + CornerTexture.Flip = SpriteEffects.FlipHorizontally; + CornerTexture.Rotation = -90; + CornerTexture.Draw(camera); + CornerTexture.Rotation = 0; + } + + if (BorderTop == false) + { + CornerTexture.Position = new Vector2(this.Bounds.Left, this.Bounds.Top + CornerTexture.Width); + CornerTexture.Flip = SpriteEffects.None; + CornerTexture.Rotation = -90; + CornerTexture.Draw(camera); + CornerTexture.Rotation = 0; + } + } + + // Drawing right side corners + if (BorderRight == true) + { + CornerTexture.Flip = SpriteEffects.None; + CornerLTexture.Flip = SpriteEffects.None; + + if (BorderBottom == false) + { + CornerTexture.Position = new Vector2(this.Bounds.Right, this.Bounds.Bottom - CornerTexture.Width); + CornerTexture.Rotation = 90; + CornerTexture.Draw(camera); + CornerTexture.Rotation = 0; + } + + if (BorderTop == false) + { + CornerTexture.Position = new Vector2(this.Bounds.Right, this.Bounds.Top + CornerTexture.Width); + CornerTexture.Flip = SpriteEffects.FlipHorizontally; + CornerTexture.Rotation = 90; + CornerTexture.Draw(camera); + CornerTexture.Rotation = 0; + } + } + } + + protected override GameObj CreateCloneInstance() + { + return new BorderObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + BorderObj clone = obj as BorderObj; + clone.LevelType = this.LevelType; + clone.BorderTop = this.BorderTop; + clone.BorderBottom = this.BorderBottom; + clone.BorderLeft = this.BorderLeft; + clone.BorderRight = this.BorderRight; + clone.SetHeight(_height); + clone.SetWidth(_width); + clone.NeoTexture = this.NeoTexture; + + clone.SetBorderTextures(this.BorderTexture, this.CornerTexture.SpriteName, this.CornerLTexture.SpriteName); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + BorderTexture = null; // Do not dispose. SetBorderTexture passes a reference to a texture. Whatever classes passing that texture should dispose of it. + CornerTexture.Dispose(); // You can dispose this one because it isn't a texture2D. It's a spriteobj. + CornerTexture = null; + CornerLTexture.Dispose(); // You can dispose this one because it isn't a texture2D. It's a spriteobj. + CornerLTexture = null; + NeoTexture = null; + base.Dispose(); + } + } + + public override void PopulateFromXMLReader(System.Xml.XmlReader reader, System.Globalization.CultureInfo ci) + { + base.PopulateFromXMLReader(reader, ci); + + SetWidth(_width); + SetHeight(_height); + if (reader.MoveToAttribute("CollidesTop")) + this.BorderTop = bool.Parse(reader.Value); + if (reader.MoveToAttribute("CollidesBottom")) + this.BorderBottom = bool.Parse(reader.Value); + if (reader.MoveToAttribute("CollidesLeft")) + this.BorderLeft = bool.Parse(reader.Value); + if (reader.MoveToAttribute("CollidesRight")) + this.BorderRight = bool.Parse(reader.Value); + } + } +} diff --git a/RogueCastle/src/Game Objects/BreakableObj.cs b/RogueCastle/src/Game Objects/BreakableObj.cs new file mode 100644 index 0000000..cf54876 --- /dev/null +++ b/RogueCastle/src/Game Objects/BreakableObj.cs @@ -0,0 +1,217 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class BreakableObj : PhysicsObjContainer + { + public bool Broken { get; internal set; } + private bool m_internalIsWeighted = false; + public bool DropItem { get; set; } + public bool HitBySpellsOnly { get; set; } + + public BreakableObj(string spriteName) + : base(spriteName) + { + this.DisableCollisionBoxRotations = true; + Broken = false; + this.OutlineWidth = 2; + this.SameTypesCollide = true; + CollisionTypeTag = GameTypes.CollisionType_WALL_FOR_PLAYER; + this.CollidesLeft = false; + this.CollidesRight = false; + this.CollidesBottom = false; + + foreach (GameObj obj in _objectList) + obj.Visible = false; + _objectList[0].Visible = true; + + DropItem = true; + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + PlayerObj player = otherBox.AbsParent as PlayerObj; + + if (player != null && otherBox.Type == Consts.WEAPON_HITBOX && HitBySpellsOnly == false) + { + if (Broken == false) + Break(); + } + + ProjectileObj projectile = otherBox.AbsParent as ProjectileObj; + if (projectile != null && (projectile.CollisionTypeTag == GameTypes.CollisionType_PLAYER || projectile.CollisionTypeTag == GameTypes.CollisionType_GLOBAL_DAMAGE_WALL) && otherBox.Type == Consts.WEAPON_HITBOX) + { + if (Broken == false) + Break(); + + if (projectile.DestroysWithTerrain == true && this.SpriteName == "Target1_Character") + projectile.RunDestroyAnimation(false); + } + + // Hack to make only terrain or other breakables collide with this. + if ((otherBox.AbsRect.Y > thisBox.AbsRect.Y || otherBox.AbsRotation != 0) && (otherBox.Parent is TerrainObj || otherBox.AbsParent is BreakableObj)) + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + public void Break() + { + PlayerObj player = Game.ScreenManager.Player; + + foreach (GameObj obj in _objectList) + obj.Visible = true; + + this.GoToFrame(2); + Broken = true; + m_internalIsWeighted = this.IsWeighted; + this.IsWeighted = false; + this.IsCollidable = false; + + // Chance of dropping item. HP/MP/COIN/MONEYBAG/NOTHING. + if (DropItem == true) + { + // Special code to force drop an item. + bool droppedItem = false; + if (this.Name == "Health") + { + player.AttachedLevel.ItemDropManager.DropItem(this.Position, ItemDropType.Health, GameEV.ITEM_HEALTHDROP_AMOUNT); + droppedItem = true; + } + else if (this.Name == "Mana") + { + player.AttachedLevel.ItemDropManager.DropItem(this.Position, ItemDropType.Mana, GameEV.ITEM_MANADROP_AMOUNT); + droppedItem = true; + } + + if (droppedItem == true) + { + for (int i = 0; i < this.NumChildren; i++) + { + Tweener.Tween.By(this.GetChildAt(i), 0.3f, Tweener.Ease.Linear.EaseNone, "X", CDGMath.RandomInt(-50, 50).ToString(), "Y", "50", "Rotation", CDGMath.RandomInt(-360, 360).ToString()); + Tweener.Tween.To(this.GetChildAt(i), 0.1f, Tweener.Ease.Linear.EaseNone, "delay", "0.2", "Opacity", "0"); + } + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "EnemyHit1", "EnemyHit2", "EnemyHit3", "EnemyHit4", "EnemyHit5", "EnemyHit6"); + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "Break1", "Break2", "Break3"); + + if (Game.PlayerStats.Traits.X == TraitType.OCD || Game.PlayerStats.Traits.Y == TraitType.OCD) + { + player.CurrentMana += 1; + player.AttachedLevel.TextManager.DisplayNumberStringText(1, "LOC_ID_SKILL_SCREEN_15" /*"mp"*/, Color.RoyalBlue, new Vector2(player.X, player.Bounds.Top - 30)); + } + return; + } + + int dropRoll = CDGMath.RandomInt(1, 100); + int dropChance = 0; + for (int i = 0; i < GameEV.BREAKABLE_ITEMDROP_CHANCE.Length; i++) + { + dropChance += GameEV.BREAKABLE_ITEMDROP_CHANCE[i]; + if (dropRoll <= dropChance) + { + if (i == 0) + { + if (Game.PlayerStats.Traits.X != TraitType.Alektorophobia && Game.PlayerStats.Traits.Y != TraitType.Alektorophobia) + player.AttachedLevel.ItemDropManager.DropItem(this.Position, ItemDropType.Health, GameEV.ITEM_HEALTHDROP_AMOUNT); + else + { + EnemyObj_Chicken chicken = new EnemyObj_Chicken(null, null, null, GameTypes.EnemyDifficulty.BASIC); + chicken.AccelerationY = -500; + chicken.Position = this.Position; + chicken.Y -= 50; + chicken.SaveToFile = false; + player.AttachedLevel.AddEnemyToCurrentRoom(chicken); + chicken.IsCollidable = false; + Tweener.Tween.RunFunction(0.2f, chicken, "MakeCollideable"); + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "Chicken_Cluck_01", "Chicken_Cluck_02", "Chicken_Cluck_03"); + } + } + else if (i == 1) + player.AttachedLevel.ItemDropManager.DropItem(this.Position, ItemDropType.Mana, GameEV.ITEM_MANADROP_AMOUNT); + else if (i == 2) + player.AttachedLevel.ItemDropManager.DropItem(this.Position, ItemDropType.Coin, ItemDropType.CoinAmount); + else if (i == 3) + player.AttachedLevel.ItemDropManager.DropItem(this.Position, ItemDropType.MoneyBag, ItemDropType.MoneyBagAmount); + break; + } + } + } + + for (int i = 0; i < this.NumChildren; i++) + { + Tweener.Tween.By(this.GetChildAt(i), 0.3f, Tweener.Ease.Linear.EaseNone, "X", CDGMath.RandomInt(-50, 50).ToString(), "Y", "50", "Rotation", CDGMath.RandomInt(-360,360).ToString()); + Tweener.Tween.To(this.GetChildAt(i), 0.1f, Tweener.Ease.Linear.EaseNone, "delay", "0.2", "Opacity", "0"); + } + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"EnemyHit1", "EnemyHit2", "EnemyHit3", "EnemyHit4", "EnemyHit5", "EnemyHit6"); + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Break1", "Break2", "Break3"); + + if (Game.PlayerStats.Traits.X == TraitType.OCD || Game.PlayerStats.Traits.Y == TraitType.OCD) + { + player.CurrentMana += 1; + player.AttachedLevel.TextManager.DisplayNumberStringText(1, "LOC_ID_SKILL_SCREEN_15" /*"mp"*/, Color.RoyalBlue, new Vector2(player.X, player.Bounds.Top - 30)); + } + } + + public void ForceBreak() + { + foreach (GameObj obj in _objectList) + { + obj.Visible = true; + obj.Opacity = 0; + } + + this.GoToFrame(2); + Broken = true; + m_internalIsWeighted = this.IsWeighted; + this.IsWeighted = false; + this.IsCollidable = false; + } + + public void Reset() + { + this.GoToFrame(1); + Broken = false; + this.IsWeighted = m_internalIsWeighted; + this.IsCollidable = true; + this.ChangeSprite(_spriteName); + for (int i = 0; i < this.NumChildren; i++) + { + this.GetChildAt(i).Opacity = 1; + this.GetChildAt(i).Rotation = 0; + } + + // Call this after ChangeSprite, since ChangeSprite() overrides object visibility. + foreach (GameObj obj in _objectList) + obj.Visible = false; + _objectList[0].Visible = true; + } + + public void UpdateTerrainBox() + { + foreach (CollisionBox box in CollisionBoxes) + { + if (box.Type == Consts.TERRAIN_HITBOX) + { + m_terrainBounds = box.AbsRect; + break; + } + } + } + + protected override GameObj CreateCloneInstance() + { + return new BreakableObj(_spriteName); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + BreakableObj clone = obj as BreakableObj; + clone.HitBySpellsOnly = this.HitBySpellsOnly; + clone.DropItem = this.DropItem; + } + } +} diff --git a/RogueCastle/src/Game Objects/CharacterObj.cs b/RogueCastle/src/Game Objects/CharacterObj.cs new file mode 100644 index 0000000..e39cc19 --- /dev/null +++ b/RogueCastle/src/Game Objects/CharacterObj.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public abstract class CharacterObj : PhysicsObjContainer, IStateObj, IKillableObj + { + //TODO: Clone(). + + public string LocStringID { get; set; } + + //EV Values + public float JumpHeight { get; set; } + public virtual int MaxHealth { get; internal set; } + public Vector2 KnockBack { get; internal set; } + protected float CurrentAirSpeed = 0; + public float DoubleJumpHeight { get; internal set; } + public bool CanBeKnockedBack { get; set; } + + public float SlopeClimbRotation = 45; + + protected int StepUp; // The number of pixels that the player can hit before he "steps up" a block. + + public int State { get; set; } + + protected bool m_isTouchingGround = false; + + protected bool m_isKilled = false; + protected ProceduralLevelScreen m_levelScreen; + + + // Internal flags used to remember the state of the enemy when ResetState() is called. + public SpriteEffects InternalFlip = SpriteEffects.None; + protected bool m_internalLockFlip = false; + protected bool m_internalIsWeighted = true; // An internal flag that tells what state to set the enemy's IsWeighted flag to. + protected float m_internalRotation = 0; + protected float m_internalAnimationDelay = 1 / 10f; + protected Vector2 m_internalScale = new Vector2(1, 1); + + private Color m_blinkColour = Color.White; + protected float m_blinkTimer = 0; + + private int m_currentHealth = 0; + public int CurrentHealth + { + get { return m_currentHealth;} + set + { + m_currentHealth = value; + if (m_currentHealth > MaxHealth) + m_currentHealth = MaxHealth; + if (m_currentHealth < 0) + m_currentHealth = 0; + } + } + + public CharacterObj(string spriteName, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo) + : base(spriteName, physicsManager) + { + m_levelScreen = levelToAttachTo; + CanBeKnockedBack = true; + } + + protected abstract void InitializeEV(); + + protected abstract void InitializeLogic(); + + public virtual void HandleInput() { } + + public virtual void Update(GameTime gameTime) + { + if (m_blinkTimer > 0) + { + m_blinkTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds; + this.TextureColor = m_blinkColour; + } + else if (this.TextureColor == m_blinkColour) + this.TextureColor = Color.White; + } + + public void Blink(Color blinkColour, float duration) + { + m_blinkColour = blinkColour; + m_blinkTimer = duration; + } + + public virtual void Kill(bool giveXP = true) + { + AccelerationX = 0; + AccelerationY = 0; + this.Opacity = 1; + this.CurrentSpeed = 0; + this.StopAnimation(); + this.Visible = false; + m_isKilled = true; + IsCollidable = false; + IsWeighted = false; + m_blinkTimer = 0; + } + + public virtual void Reset() + { + this.AccelerationX = 0; + this.AccelerationY = 0; + this.CurrentSpeed = 0; + this.CurrentHealth = this.MaxHealth; + this.Opacity = 1; + + IsCollidable = true; + IsWeighted = m_internalIsWeighted; + LockFlip = m_internalLockFlip; + this.Rotation = m_internalRotation; + this.AnimationDelay = m_internalAnimationDelay; + this.Scale = m_internalScale; + Flip = InternalFlip; + m_isKilled = false; + this.Visible = true; + IsTriggered = false; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_levelScreen = null; + base.Dispose(); + } + } + + public bool IsKilled { get { return m_isKilled; } } + public bool IsTouchingGround { get { return m_isTouchingGround; } } + public Vector2 InternalScale { get { return m_internalScale; } } + } +} diff --git a/RogueCastle/src/Game Objects/ChestObj.cs b/RogueCastle/src/Game Objects/ChestObj.cs new file mode 100644 index 0000000..53494bd --- /dev/null +++ b/RogueCastle/src/Game Objects/ChestObj.cs @@ -0,0 +1,442 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class ChestObj : PhysicsObj + { + private byte m_chestType; + + //private int BrownChestGoldChance = 90;//100;//90; //Chance to get gold over getting a blueprint + //private int SilverChestGoldChance = 40; //35;//65; + + private float GoldIncreasePerLevel = 1.425f;//1.375f;//1.35f;//1.25f;//1.15f;//1.0f;//0.90f;//0.70f; //How many coins each chest gives per room level, this takes room_level into account TESTED TRUE. + + //private int GoldBaseMod = 10;//300; //Minimum amount a chest will give the player. + private Vector2 BronzeChestGoldRange = new Vector2(9, 14);//(7, 12);//(5, 15);//(10, 30); //How much gold a Bronze Chest gives. + private Vector2 SilverChestGoldRange = new Vector2(20, 28);//(18, 25);//(15, 30);//(30, 50); //How much gold a Silver Chest gives. + private Vector2 GoldChestGoldRange = new Vector2(47, 57);//(43, 52);//(45, 60);//(35, 60);//(30, 50); //How much gold a Gold Chest gives. + + public bool IsEmpty { get; set; } + public bool IsLocked { get; set; } + + public int ForcedItemType { get; set; } + public float ForcedAmount { get; set; } + public bool IsProcedural { get; set; } + + public int Level = 0; + + private SpriteObj m_arrowIcon; + + public ChestObj(PhysicsManager physicsManager) + : base("Chest1_Sprite", physicsManager) + { + DisableHitboxUpdating = true; + this.IsWeighted = false; + this.Layer = 1; + this.OutlineWidth = 2; + IsProcedural = true; + + m_arrowIcon = new SpriteObj("UpArrowSquare_Sprite"); + m_arrowIcon.OutlineWidth = 2; + m_arrowIcon.Visible = false; + } + + public virtual void OpenChest(ItemDropManager itemDropManager, PlayerObj player) + { + if (IsOpen == false && IsLocked == false) + { + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Chest_Open_Large"); + + this.GoToFrame(2); + if (IsEmpty == true) + return; + + if (this.ChestType == RogueCastle.ChestType.Gold) + GameUtil.UnlockAchievement("LOVE_OF_GOLD"); + + if (ForcedItemType == 0) + { + // Item drop chance for MONEY/STAT DROP/BLUEPRINT + int dropRoll = CDGMath.RandomInt(1, 100); + int itemType = 0; + int[] dropChance = null; + if (this.ChestType == RogueCastle.ChestType.Brown) + dropChance = GameEV.BRONZECHEST_ITEMDROP_CHANCE; + else if (this.ChestType == RogueCastle.ChestType.Silver) + dropChance = GameEV.SILVERCHEST_ITEMDROP_CHANCE; + else + dropChance = GameEV.GOLDCHEST_ITEMDROP_CHANCE; + + int itemChance = 0; + for (int i = 0; i < dropChance.Length; i++) + { + itemChance += dropChance[i]; + if (dropRoll <= itemChance) + { + itemType = i; + break; + } + } + + if (itemType == 0) + GiveGold(itemDropManager); + else if (itemType == 1) + GiveStatDrop(itemDropManager, player, 1, 0); + else + GivePrint(itemDropManager, player); + } + else + { + switch (ForcedItemType) + { + case (ItemDropType.Coin): + case (ItemDropType.MoneyBag): + case (ItemDropType.Diamond): + case(ItemDropType.BigDiamond): + GiveGold(itemDropManager, (int)ForcedAmount); + break; + case (ItemDropType.Stat_Defense): + case (ItemDropType.Stat_Magic): + case (ItemDropType.Stat_MaxHealth): + case (ItemDropType.Stat_MaxMana): + case (ItemDropType.Stat_Weight): + case (ItemDropType.Stat_Strength): + GiveStatDrop(itemDropManager, player, 1, ForcedItemType); + break; + case (ItemDropType.Blueprint): + case (ItemDropType.Redprint): + GivePrint(itemDropManager, player); + break; + case (ItemDropType.TripStatDrop): + GiveStatDrop(itemDropManager, player, 3, 0); + break; + case (ItemDropType.FountainPiece1): + case (ItemDropType.FountainPiece2): + case (ItemDropType.FountainPiece3): + case (ItemDropType.FountainPiece4): + case (ItemDropType.FountainPiece5): + GiveStatDrop(itemDropManager, player, 1, ForcedItemType); + break; + } + } + + player.AttachedLevel.RefreshMapChestIcons(); + //SoundManager.Play3DSound(this, Game.ScreenManager.Player,"ChestOpen1"); + } + } + + public void GiveGold(ItemDropManager itemDropManager, int amount = 0) + { + int goldAmount = 0; + if (this.ChestType == RogueCastle.ChestType.Brown) + goldAmount = CDGMath.RandomInt((int)BronzeChestGoldRange.X, (int)BronzeChestGoldRange.Y) * 10; + else if (this.ChestType == RogueCastle.ChestType.Silver || this.ChestType == RogueCastle.ChestType.Fairy) + goldAmount = CDGMath.RandomInt((int)SilverChestGoldRange.X, (int)SilverChestGoldRange.Y) * 10; + else + goldAmount = CDGMath.RandomInt((int)GoldChestGoldRange.X, (int)GoldChestGoldRange.Y) * 10; //TEDDY ADDED ELSE IF SO GOLD CHESTS COULD DROP MONEY + goldAmount += (int)Math.Floor(GoldIncreasePerLevel * this.Level * 10); + + if (amount != 0) // Override the randomized gold amount if a method parameter is passed in. + goldAmount = amount; + + int numBigDiamonds = (int)(goldAmount / ItemDropType.BigDiamondAmount); + goldAmount -= numBigDiamonds * ItemDropType.BigDiamondAmount; + + int numDiamonds = (int)(goldAmount / ItemDropType.DiamondAmount); + goldAmount -= numDiamonds * ItemDropType.DiamondAmount; + + int numMoneyBags = (int)(goldAmount / ItemDropType.MoneyBagAmount); + goldAmount -= numMoneyBags * ItemDropType.MoneyBagAmount; + + int numCoins = goldAmount / ItemDropType.CoinAmount; + + float delay = 0f; + + for (int i = 0; i < numBigDiamonds; i++) + { + Tweener.Tween.To(this, delay, Tweener.Ease.Linear.EaseNone); + Tweener.Tween.AddEndHandlerToLastTween(itemDropManager, "DropItem", new Vector2(this.Position.X, this.Position.Y - this.Height / 2), ItemDropType.BigDiamond, ItemDropType.BigDiamondAmount); + delay += 0.1f; + } + delay = 0f; + + for (int i = 0; i < numDiamonds; i++) + { + Tweener.Tween.To(this, delay, Tweener.Ease.Linear.EaseNone); + Tweener.Tween.AddEndHandlerToLastTween(itemDropManager, "DropItem", new Vector2(this.Position.X, this.Position.Y - this.Height / 2), ItemDropType.Diamond, ItemDropType.DiamondAmount); + delay += 0.1f; + } + delay = 0f; + for (int i = 0; i < numMoneyBags; i++) + { + Tweener.Tween.To(this, delay, Tweener.Ease.Linear.EaseNone); + Tweener.Tween.AddEndHandlerToLastTween(itemDropManager, "DropItem", new Vector2(this.Position.X, this.Position.Y - this.Height / 2), ItemDropType.MoneyBag, ItemDropType.MoneyBagAmount); + delay += 0.1f; + } + delay = 0f; + for (int i = 0; i < numCoins; i++) + { + Tweener.Tween.To(this, delay, Tweener.Ease.Linear.EaseNone); + Tweener.Tween.AddEndHandlerToLastTween(itemDropManager, "DropItem", new Vector2(this.Position.X, this.Position.Y - this.Height / 2), ItemDropType.Coin, ItemDropType.CoinAmount); + delay += 0.1f; + } + } + + public void GiveStatDrop(ItemDropManager manager, PlayerObj player, int numDrops, int statDropType) + { + int[] dropArray = new int[numDrops]; + + for (int k = 0; k < numDrops; k++) + { + if (statDropType == 0) + { + //Dropping Stat drop of type STR/MAG/DEF/HP/MP/WEIGHT + int dropRoll = CDGMath.RandomInt(1, 100); + int dropType = 0; + + for (int i = 0; i < GameEV.STATDROP_CHANCE.Length; i++) + { + dropType += GameEV.STATDROP_CHANCE[i]; + if (dropRoll <= dropType) + { + if (i == 0) + { + dropArray[k] = ItemDropType.Stat_Strength; + Game.PlayerStats.BonusStrength += 1 + Game.PlayerStats.TimesCastleBeaten; + } + else if (i == 1) + { + dropArray[k] = ItemDropType.Stat_Magic; + Game.PlayerStats.BonusMagic += 1 + Game.PlayerStats.TimesCastleBeaten; + + } + else if (i == 2) + { + dropArray[k] = ItemDropType.Stat_Defense; + Game.PlayerStats.BonusDefense += 1 + Game.PlayerStats.TimesCastleBeaten; + } + else if (i == 3) + { + dropArray[k] = ItemDropType.Stat_MaxHealth; + Game.PlayerStats.BonusHealth += 1 + Game.PlayerStats.TimesCastleBeaten; + } + else if (i == 4) + { + dropArray[k] = ItemDropType.Stat_MaxMana; + Game.PlayerStats.BonusMana += 1 + Game.PlayerStats.TimesCastleBeaten; + } + else + { + dropArray[k] = ItemDropType.Stat_Weight; + Game.PlayerStats.BonusWeight += 1 + Game.PlayerStats.TimesCastleBeaten; + } + break; + } + } + } + else + { + switch (statDropType) + { + case (ItemDropType.Stat_MaxHealth): + Game.PlayerStats.BonusHealth += 1 + Game.PlayerStats.TimesCastleBeaten; + break; + case (ItemDropType.Stat_MaxMana): + Game.PlayerStats.BonusMana += 1 + Game.PlayerStats.TimesCastleBeaten; + break; + case (ItemDropType.Stat_Defense): + Game.PlayerStats.BonusDefense += 1 + Game.PlayerStats.TimesCastleBeaten; + break; + case (ItemDropType.Stat_Magic): + Game.PlayerStats.BonusMagic += 1 + Game.PlayerStats.TimesCastleBeaten; + break; + case (ItemDropType.Stat_Strength): + Game.PlayerStats.BonusStrength += 1 + Game.PlayerStats.TimesCastleBeaten; + break; + case (ItemDropType.Stat_Weight): + Game.PlayerStats.BonusWeight += 1 + Game.PlayerStats.TimesCastleBeaten; + break; + } + dropArray[k] = statDropType; + } + } + + List objectList = new List(); + // First data stored in the object is its position. + // Second data stored in the object is the GetItemType + // Third data stored in the object is misc data stored in a vector2 + // Fourth data stored only applies to triple stats, and is a vector2 that contains 2 of the 3 random stats for the player to collect. + + objectList.Add(new Vector2(this.X, this.Y - this.Height / 2f)); + + if (statDropType >= ItemDropType.FountainPiece1 && statDropType <= ItemDropType.FountainPiece5) + { + objectList.Add(GetItemType.FountainPiece); + } + else + { + if (numDrops <= 1) + objectList.Add(GetItemType.StatDrop); + else + objectList.Add(GetItemType.TripStatDrop); + } + + objectList.Add(new Vector2(dropArray[0], 0)); + + if (numDrops > 1) + objectList.Add(new Vector2(dropArray[1], dropArray[2])); + + player.AttachedLevel.UpdatePlayerHUD(); + (player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.GetItem, true, objectList); + player.RunGetItemAnimation(); + } + + public void GivePrint(ItemDropManager manager, PlayerObj player) + { + // Give gold if all blueprints have been found + if (Game.PlayerStats.TotalBlueprintsFound >= EquipmentCategoryType.Total * EquipmentBaseType.Total) + { + if (this.ChestType == RogueCastle.ChestType.Gold) + GiveStatDrop(manager, player, 1, 0); + else + GiveGold(manager); + } + else + { + List blueprintArray = Game.PlayerStats.GetBlueprintArray; + List possibleBlueprints = new List(); + + int categoryCounter = 0; + foreach (byte[] itemArray in blueprintArray) + { + int itemCounter = 0; + foreach (byte itemState in itemArray) + { + if (itemState == EquipmentState.NotFound) + { + EquipmentData item = Game.EquipmentSystem.GetEquipmentData(categoryCounter, itemCounter); + if (this.Level >= item.LevelRequirement && this.ChestType >= item.ChestColourRequirement) + possibleBlueprints.Add(new Vector2(categoryCounter, itemCounter)); + } + itemCounter++; + } + categoryCounter++; + } + + if (possibleBlueprints.Count > 0) + { + Vector2 chosenBlueprint = possibleBlueprints[CDGMath.RandomInt(0, possibleBlueprints.Count - 1)]; + Game.PlayerStats.GetBlueprintArray[(int)chosenBlueprint.X][(int)chosenBlueprint.Y] = EquipmentState.FoundButNotSeen; + List objectList = new List(); + objectList.Add(new Vector2(this.X, this.Y - this.Height / 2f)); + objectList.Add(GetItemType.Blueprint); + objectList.Add(new Vector2(chosenBlueprint.X, chosenBlueprint.Y)); + + (player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.GetItem, true, objectList); + player.RunGetItemAnimation(); + + Console.WriteLine("Unlocked item index " + chosenBlueprint.X + " of type " + chosenBlueprint.Y); + } + else + GiveGold(manager); + } + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + PlayerObj player = otherBox.AbsParent as PlayerObj; + if (this.IsLocked == false && this.IsOpen == false && player != null && player.IsTouchingGround == true) + m_arrowIcon.Visible = true; + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + public override void Draw(Camera2D camera) + { + if (m_arrowIcon.Visible == true) + { + m_arrowIcon.Position = new Vector2(this.Bounds.Center.X, this.Bounds.Top - 50 + (float)Math.Sin(Game.TotalGameTime * 20) * 3); + m_arrowIcon.Draw(camera); + m_arrowIcon.Visible = false; + } + + base.Draw(camera); + } + + // Opens the chest but gives none of the good stuff to the player. + public virtual void ForceOpen() + { + this.GoToFrame(2); + } + + public virtual void ResetChest() + { + this.GoToFrame(1); + } + + protected override GameObj CreateCloneInstance() + { + return new ChestObj(this.PhysicsMngr); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + ChestObj clone = obj as ChestObj; + + clone.IsProcedural = this.IsProcedural; + clone.ChestType = this.ChestType; + clone.Level = this.Level; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_arrowIcon.Dispose(); + m_arrowIcon = null; + base.Dispose(); + } + } + + public byte ChestType + { + get { return m_chestType; } + set + { + m_chestType = value; + bool openChest = this.IsOpen; + if (m_chestType == RogueCastle.ChestType.Boss) + { + ForcedItemType = ItemDropType.TripStatDrop; + this.ChangeSprite("BossChest_Sprite"); + } + else if (m_chestType == RogueCastle.ChestType.Fairy) + this.ChangeSprite("Chest4_Sprite"); + else if (m_chestType == RogueCastle.ChestType.Gold) + this.ChangeSprite("Chest3_Sprite"); + else if (m_chestType == RogueCastle.ChestType.Silver) + this.ChangeSprite("Chest2_Sprite"); + else + this.ChangeSprite("Chest1_Sprite"); + + if (openChest == true) + this.GoToFrame(2); + + //System.Diagnostics.Debug.Assert((value == RogueCastle.ChestType.Fairy && this is FairyChestObj) || value != RogueCastle.ChestType.Fairy); + } + } + + public bool IsOpen + { + get { return this.CurrentFrame == 2; } + } + } + +} diff --git a/RogueCastle/src/Game Objects/DialogueObj.cs b/RogueCastle/src/Game Objects/DialogueObj.cs new file mode 100644 index 0000000..efab61a --- /dev/null +++ b/RogueCastle/src/Game Objects/DialogueObj.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; + +namespace RogueCastle +{ + public class DialogueObj : IDisposableObj + { + public string[] Speakers { get; set; } + public string[] Dialogue { get; set; } + private bool m_isDisposed = false; + + public DialogueObj(string[] speakers, string[] dialogue) + { + if (speakers.Length != dialogue.Length) + throw new Exception("Cannot create dialogue obj with mismatching speakers and dialogue"); + Speakers = speakers; + Dialogue = dialogue; + } + + public void Dispose() + { + if (m_isDisposed == false) + { + // Done + Array.Clear(Dialogue, 0, Dialogue.Length); + Dialogue = null; + Array.Clear(Speakers, 0, Speakers.Length); + Speakers = null; + m_isDisposed = true; + } + } + + public bool IsDisposed + { + get { return m_isDisposed; } + } + } +} diff --git a/RogueCastle/src/Game Objects/DoorObj.cs b/RogueCastle/src/Game Objects/DoorObj.cs new file mode 100644 index 0000000..4e8ea4f --- /dev/null +++ b/RogueCastle/src/Game Objects/DoorObj.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class DoorObj : TerrainObj + { + private GameTypes.DoorType m_doorType = GameTypes.DoorType.OPEN; + public string DoorPosition = "NONE"; + public RoomObj Room { get; set; } // Stores a reference to the room it is in. + public bool Attached = false; // Keeps track of whether a door is attached to another door or not. + public bool IsBossDoor = false; + public bool Locked = false; + + private SpriteObj m_arrowIcon; + + public DoorObj(RoomObj roomRef, int width, int height, GameTypes.DoorType doorType) + : base(width, height) + { + m_doorType = doorType; + Room = roomRef; + CollisionTypeTag = GameTypes.CollisionType_NULL; + DisableHitboxUpdating = true; + + m_arrowIcon = new SpriteObj("UpArrowSquare_Sprite"); + m_arrowIcon.OutlineWidth = 2; + m_arrowIcon.Visible = false; + } + + public override void Draw(Camera2D camera) + { + if (m_arrowIcon.Visible == true) + { + m_arrowIcon.Position = new Vector2(this.Bounds.Center.X, this.Bounds.Top - 10 + (float)Math.Sin(Game.TotalGameTime * 20) * 3); + m_arrowIcon.Draw(camera); + m_arrowIcon.Visible = false; + } + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + PlayerObj player = otherBox.AbsParent as PlayerObj; + if (this.Locked == false && player != null && player.IsTouchingGround == true && this.DoorPosition == "None") + m_arrowIcon.Visible = true; + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + protected override GameObj CreateCloneInstance() + { + return new DoorObj(Room, _width, _height, m_doorType); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + DoorObj clone = obj as DoorObj; + clone.Attached = this.Attached; + clone.IsBossDoor = this.IsBossDoor; + clone.Locked = this.Locked; + clone.DoorPosition = this.DoorPosition; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + Room = null; // Do not dispose the room in case we are simply closing this door. + m_arrowIcon.Dispose(); + m_arrowIcon = null; + base.Dispose(); + } + } + + public override void PopulateFromXMLReader(System.Xml.XmlReader reader, System.Globalization.CultureInfo ci) + { + base.PopulateFromXMLReader(reader, ci); + + if (reader.MoveToAttribute("BossDoor")) + this.IsBossDoor = bool.Parse(reader.Value); + + if (reader.MoveToAttribute("DoorPos")) + this.DoorPosition = reader.Value; + } + + public GameTypes.DoorType DoorType + { + get { return m_doorType; } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyHUDObj.cs b/RogueCastle/src/Game Objects/EnemyHUDObj.cs new file mode 100644 index 0000000..d0fbe73 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyHUDObj.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyHUDObj : SpriteObj + { + private TextObj m_enemyNameText; + private TextObj m_enemyLevelText; + private SpriteObj m_enemyHPBar; + private float m_enemyHPPercent; + private int m_enemyHPBarLength; + + private int m_blinkNumber = 13; // Must be end for it to disappear. + private float m_blinkDuration = 0.05f; + + private int m_blinkCounter = 0; + private float m_blinkDurationCounter = 0; + private float m_opacity = 1; + + public EnemyHUDObj() + : base("EnemyHUD_Sprite") + { + this.ForceDraw = true; + + m_enemyNameText = new TextObj(); + m_enemyNameText.Font = Game.JunicodeFont; + m_enemyNameText.FontSize = 10; + m_enemyNameText.Align = Types.TextAlign.Right; + + m_enemyLevelText = new TextObj(); + m_enemyLevelText.Font = Game.EnemyLevelFont; + + m_enemyHPBar = new SpriteObj("EnemyHPBar_Sprite"); + m_enemyHPBar.ForceDraw = true; + m_enemyHPBarLength = m_enemyHPBar.SpriteRect.Width; + } + + public void UpdateEnemyInfo(string enemyNameID, int enemyLevel, float enemyHPPercent) + { + m_blinkDurationCounter = 0; + m_blinkCounter = 0; + m_enemyHPBar.Opacity = 1; + m_enemyLevelText.Opacity = 1; + m_enemyNameText.Opacity = 1; + this.Opacity = 1; + + if (enemyNameID == null) + m_enemyNameText.Text = "Default Enemy"; + else + { + m_enemyNameText.Text = LocaleBuilder.getString(enemyNameID, m_enemyNameText); + // TODO, adjust limit for different languages and fonts? + if (m_enemyNameText.Text.Length > 17) + m_enemyNameText.Text = m_enemyNameText.Text.Substring(0, 14) + "..."; + } + + m_enemyLevelText.Text = ((int)(enemyLevel * LevelEV.ENEMY_LEVEL_FAKE_MULTIPLIER)).ToString(); + m_enemyHPPercent = enemyHPPercent; + + if (enemyHPPercent <= 0) + { + m_blinkCounter = m_blinkNumber; + m_blinkDurationCounter = m_blinkDuration; + + m_opacity = 0.5f; + m_enemyHPBar.Opacity = 0.5f; + m_enemyLevelText.Opacity = 0.5f; + m_enemyNameText.Opacity = 0.5f; + this.Opacity = 0.5f; + } + } + + public void Update(GameTime gameTime) + { + if (m_blinkDurationCounter > 0) + m_blinkDurationCounter -= (float)gameTime.ElapsedGameTime.TotalSeconds; + + if (m_blinkCounter > 0 && m_blinkDurationCounter <= 0) + { + if (m_opacity > 0) + m_opacity = 0; + else + m_opacity = 0.5f; + + m_enemyHPBar.Opacity = m_opacity; + m_enemyLevelText.Opacity = m_opacity; + m_enemyNameText.Opacity = m_opacity; + this.Opacity = m_opacity; + m_blinkCounter--; + m_blinkDurationCounter = m_blinkDuration; + } + } + + public override void Draw(Camera2D camera) + { + base.Draw(camera); + + m_enemyHPBar.Position = new Vector2(this.X + 8, this.Y + 17); + m_enemyHPBar.SpriteRect = new Rectangle(m_enemyHPBar.SpriteRect.X, m_enemyHPBar.SpriteRect.Y, (int)(m_enemyHPBarLength * m_enemyHPPercent), m_enemyHPBar.SpriteRect.Height); + m_enemyHPBar.Draw(camera); + + m_enemyNameText.Position = new Vector2(this.X + this.Width - 5, this.Y - 10); + m_enemyNameText.Draw(camera); + + m_enemyLevelText.Position = new Vector2(this.X + 22, this.Y - 8); + m_enemyLevelText.Draw(camera); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_enemyNameText.Dispose(); + m_enemyNameText = null; + m_enemyLevelText.Dispose(); + m_enemyLevelText = null; + m_enemyHPBar.Dispose(); + m_enemyHPBar = null; + base.Dispose(); + } + } + + public void RefreshTextObjs() + { + // TODO, adjust limit for different languages and fonts? + if (m_enemyNameText.Text.Length > 17) + m_enemyNameText.Text = m_enemyNameText.Text.Substring(0, 14) + ".."; + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj.cs new file mode 100644 index 0000000..9da6c69 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj.cs @@ -0,0 +1,1272 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Tweener; +using System.Globalization; + +namespace RogueCastle +{ + public abstract class EnemyObj : CharacterObj, IDealsDamageObj + { + #region Variables + protected const int STATE_WANDER = 0; + protected const int STATE_ENGAGE = 1; + protected const int STATE_PROJECTILE_ENGAGE = 2; + protected const int STATE_MELEE_ENGAGE = 3; + + protected float DistanceToPlayer; + + protected GameObj TintablePart = null; + protected int ProjectileRadius = 0; + protected int MeleeRadius = 0; + protected int EngageRadius = 0; + protected float CooldownTime = 0; // The amount of time it takes before an enemy runs logic again. + protected int m_damage = 0; // Used for property. + protected bool CanFallOffLedges = true; + protected bool AlwaysFaceTarget = false; + public Vector2 ProjectileScale { get; internal set; } + protected int ProjectileDamage = 5; + protected float ProjectileSpeed = 100; + protected int m_xpValue = 0; // Used for property. + public bool Procedural { get; set; } + public bool NonKillable { get; set; } + public bool GivesLichHealth { get; set; } + public bool IsDemented { get; set; } + + private int m_level = 0; + public int Level + { + get { return m_level; } + set + { + m_level = value; + if (m_level < 0) + m_level = 0; + } + } + + protected int DamageGainPerLevel = 0; + protected int XPBonusPerLevel = 0; + protected int HealthGainPerLevel = 0; + + protected float MinMoneyGainPerLevel = 0; + protected float MaxMoneyGainPerLevel = 0; + + protected float ItemDropChance = 0; + protected int MinMoneyDropAmount = 0; + protected int MaxMoneyDropAmount = 0; + protected float MoneyDropChance = 0; + + protected float m_invincibilityTime = 0.4f; // The base delay speed for invincibility. Four frames. + protected float InvincibilityTime + { + get + { + //Console.WriteLine(m_invincibilityTime * m_target.AttackAnimationDelay); + //return m_invincibilityTime * m_target.AttackAnimationDelay; + return m_invincibilityTime; + } + } + protected float m_invincibleCounter = 0; + protected float m_invincibleCounterProjectile = 0; + + protected float StatLevelHPMod = 0; + protected float StatLevelDMGMod = 0; + protected float StatLevelXPMod = 0; + + public float InitialLogicDelay = 0; + protected float m_initialDelayCounter = 0; + + protected PlayerObj m_target; + public GameTypes.EnemyDifficulty Difficulty { get; internal set; } + protected string m_resetSpriteName; // The name of the sprite when its Reset() method is called. + + private int m_numTouchingGrounds; // An int used to allow enemies to walk off ledges if he's touching more than one ground tile. + + private LogicBlock m_walkingLB; + protected LogicBlock m_currentActiveLB; + + private LogicBlock m_cooldownLB; // The logicblock that is run while the enemy is in a cooldown state. + private bool m_runCooldown = false; + private float m_cooldownTimer = 0; + private int[] m_cooldownParams; + + private Texture2D m_engageRadiusTexture; + private Texture2D m_projectileRadiusTexture; + private Texture2D m_meleeRadiusTexture; + + public bool IsProcedural { get; set; } + public bool SaveToFile = true; + public byte Type; + + private bool m_isPaused = false; + protected bool m_bossVersionKilled = false; + + protected List logicBlocksToDispose; // A list primarily used for disposing LogicBlocks from classes that inherit from this base class. + protected TweenObject m_flipTween; + public bool PlayAnimationOnRestart { get; set; } + public bool DropsItem { get; set; } + protected bool m_saveToEnemiesKilledList = true; + #endregion + + private void InitializeBaseEV() + { + Speed = 1; + MaxHealth = 10; + EngageRadius = 400; + ProjectileRadius = 200; + MeleeRadius = 50; + KnockBack = Vector2.Zero; + Damage = 5; + ProjectileScale = new Vector2(1, 1); + XPValue = 0; + ProjectileDamage = 5; + ItemDropChance = 0.0f; //0.5f; + MinMoneyDropAmount = 1; + MaxMoneyDropAmount = 1; + //InvincibilityTime = 0.4f; + MoneyDropChance = 0.50f; + StatLevelHPMod = 0.160f;//0.165f;//0.16f;//0.175f;//0.15f; + StatLevelDMGMod = 0.0910f;//0.0925f; //0.095f;//0.09f; // 0.1f; + StatLevelXPMod = 0.025f; + MinMoneyGainPerLevel = 0.23f;//0.20f;//0.215f;//0.17f;//0.25f; //The rate that the min money will raise. This is tied into Enemy level. ADDITIVE + MaxMoneyGainPerLevel = 0.29f;//0.26f;//0.325f;//0.32f;//0.4f; //The rate that max money will raise. This is tied into Enemy level. ADDITIVE + ForceDraw = true; + } + + protected override void InitializeEV() { } + + protected override void InitializeLogic() + { + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new PlayAnimationLogicAction(true)); + walkTowardsLS.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsLS.AddAction(new DelayLogicAction(1)); + + LogicSet walkAwayLS = new LogicSet(this); + walkAwayLS.AddAction(new PlayAnimationLogicAction(true)); + walkAwayLS.AddAction(new MoveLogicAction(m_target, false)); + walkAwayLS.AddAction(new DelayLogicAction(1)); + + LogicSet stopWalkingLS = new LogicSet(this); + stopWalkingLS.AddAction(new StopAnimationLogicAction()); + stopWalkingLS.AddAction(new MoveLogicAction(m_target, true, 0)); + stopWalkingLS.AddAction(new DelayLogicAction(1)); + + m_walkingLB.AddLogicSet(walkTowardsLS, walkAwayLS, stopWalkingLS); + } + + public EnemyObj(string spriteName, PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base(spriteName, physicsManager, levelToAttachTo) + { + this.DisableCollisionBoxRotations = true; + this.Type = EnemyType.None; + CollisionTypeTag = GameTypes.CollisionType_ENEMY; + m_target = target; + m_walkingLB = new LogicBlock(); + m_currentActiveLB = new LogicBlock(); + m_cooldownLB = new LogicBlock(); + logicBlocksToDispose = new List(); + m_resetSpriteName = spriteName; + Difficulty = difficulty; + ProjectileScale = new Vector2(1, 1); + this.PlayAnimation(true); + PlayAnimationOnRestart = true; + this.OutlineWidth = 2; + this.GivesLichHealth = true; + this.DropsItem = true; + } + + public void SetDifficulty(GameTypes.EnemyDifficulty difficulty, bool reinitialize) + { + Difficulty = difficulty; + if (reinitialize == true) + Initialize(); + } + + public void Initialize() + { + if (TintablePart == null) + TintablePart = this.GetChildAt(0); + + InitializeBaseEV(); + InitializeEV(); + + + HealthGainPerLevel = (int)(base.MaxHealth * StatLevelHPMod); + DamageGainPerLevel = (int)(m_damage * StatLevelDMGMod); + XPBonusPerLevel = (int)(m_xpValue * StatLevelXPMod); + + // Saving the state of these properties so that they can be reset when ResetState() is called. + m_internalLockFlip = this.LockFlip; + m_internalIsWeighted = this.IsWeighted; + m_internalRotation = this.Rotation; + m_internalAnimationDelay = this.AnimationDelay; + m_internalScale = this.Scale; + InternalFlip = this.Flip; + + // This code is necessary in case InitializeLogic is called more than once on an enemy. + // The caveat to this is we need to make sure all logic blocks are properly added to the logicBlocksToDispose (although they should be, otherwise we will leak memory). + foreach (LogicBlock block in logicBlocksToDispose) + block.ClearAllLogicSets(); + + if (m_levelScreen != null) + InitializeLogic(); + + m_initialDelayCounter = InitialLogicDelay; + //Console.WriteLine(InitialLogicDelay); + CurrentHealth = MaxHealth; + } + + public void InitializeDebugRadii() + { + if (m_engageRadiusTexture == null) + { + // Makes sure you don't create a texture greater than 2048. Textures are Radius * 2 + 2. + int engageRadius = EngageRadius; + int projectileRadius = ProjectileRadius; + int meleeRadius = MeleeRadius; + + if (engageRadius > 1000) engageRadius = 1000; + if (projectileRadius > 1000) projectileRadius = 1000; + if (meleeRadius > 1000) meleeRadius = 1000; + + m_engageRadiusTexture = DebugHelper.CreateCircleTexture(engageRadius, m_levelScreen.Camera.GraphicsDevice); + m_projectileRadiusTexture = DebugHelper.CreateCircleTexture(projectileRadius, m_levelScreen.Camera.GraphicsDevice); + m_meleeRadiusTexture = DebugHelper.CreateCircleTexture(meleeRadius, m_levelScreen.Camera.GraphicsDevice); + } + } + + public void SetPlayerTarget(PlayerObj target) + { + m_target = target; + } + + public void SetLevelScreen(ProceduralLevelScreen levelScreen) + { + m_levelScreen = levelScreen; + } + + public override void Update(GameTime gameTime) + { + float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds; + + if (m_initialDelayCounter > 0) + m_initialDelayCounter -= elapsedSeconds; + else + { + if (m_invincibleCounter > 0) + m_invincibleCounter -= elapsedSeconds; + + if (m_invincibleCounterProjectile > 0) + m_invincibleCounterProjectile -= elapsedSeconds; + + if ((m_invincibleCounter <= 0 && m_invincibleCounterProjectile <= 0) && IsWeighted == false) + { + // Resets acceleration for enemies that have no weight (i.e. are flying). Acceleration reduction is eased in to give it a nice smooth look. + if (AccelerationY < 0) AccelerationY += 15f; + else if (AccelerationY > 0) AccelerationY -= 15f; + if (AccelerationX < 0) AccelerationX += 15f; + else if (AccelerationX > 0) AccelerationX -= 15f; + + if (AccelerationY < 3.6f && AccelerationY > -3.6f) AccelerationY = 0; + if (AccelerationX < 3.6f && AccelerationX > -3.6f) AccelerationX = 0; + } + + if (IsKilled == false && IsPaused == false) + { + DistanceToPlayer = CDGMath.DistanceBetweenPts(this.Position, m_target.Position); + if (DistanceToPlayer > EngageRadius) + State = STATE_WANDER; + else if (DistanceToPlayer < EngageRadius && DistanceToPlayer >= ProjectileRadius) + State = STATE_ENGAGE; + else if (DistanceToPlayer < ProjectileRadius && DistanceToPlayer >= MeleeRadius) + State = STATE_PROJECTILE_ENGAGE; + else + State = STATE_MELEE_ENGAGE; + + // Count down the cooldown timer. + if (m_cooldownTimer > 0 && m_currentActiveLB == m_cooldownLB) + m_cooldownTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds; + + if (m_cooldownTimer <= 0 && m_runCooldown == true) + m_runCooldown = false; + + // This needs to go before the next attack is executed, otherwise if the developer ever wants the enemy to face the player then lock direction, it will never happen since he will lock + // before turning. + if (LockFlip == false) + { + if (AlwaysFaceTarget == false) + { + if (this.Heading.X < 0) + this.Flip = SpriteEffects.FlipHorizontally; + else + this.Flip = SpriteEffects.None; + } + else + { + if (this.X > m_target.X) + this.Flip = SpriteEffects.FlipHorizontally; + else + this.Flip = SpriteEffects.None; + } + } + + //Only run an action check if another one is not currently being run. + if (m_currentActiveLB.IsActive == false && m_runCooldown == false) + { + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.BASIC): + RunBasicLogic(); + break; + case (GameTypes.EnemyDifficulty.ADVANCED): + RunAdvancedLogic(); + break; + case (GameTypes.EnemyDifficulty.EXPERT): + RunExpertLogic(); + break; + case (GameTypes.EnemyDifficulty.MINIBOSS): + RunMinibossLogic(); + break; + } + + // Starts the timer. + if (m_runCooldown == true && m_currentActiveLB.ActiveLS.Tag == GameTypes.LogicSetType_ATTACK) // The tag makes sure that the current Logic set executed was an attack. + m_cooldownTimer = CooldownTime; // Convert to milliseconds. + } + + if (m_currentActiveLB.IsActive == false && m_runCooldown == true && m_cooldownTimer > 0 && m_cooldownLB.IsActive == false) + { + m_currentActiveLB = m_cooldownLB; + m_currentActiveLB.RunLogicBlock(m_cooldownParams); + } + + // Only make the enemy move if they are not invincible. This prevents enemies from moving in the air after getting hit. + // Only for Weighted enemies. Non-weighted logic is above. + if (IsWeighted == true && (m_invincibleCounter <= 0 && m_invincibleCounterProjectile <= 0)) + { + if (HeadingX > 0) this.HeadingX = 1; // A hack to maintain a horizontal speed. + else if (HeadingX < 0) this.HeadingX = -1; + this.X += this.HeadingX * (this.CurrentSpeed * elapsedSeconds); + } + else if (m_isTouchingGround == true || IsWeighted == false) // Only move if you're touching the ground. + this.Position += this.Heading * (this.CurrentSpeed * elapsedSeconds); + + // Code to make sure enemies cannot exit the room. + //bool stopMovement = false; + //if (IsWeighted == true) + { + if (this.X < m_levelScreen.CurrentRoom.Bounds.Left) + this.X = m_levelScreen.CurrentRoom.Bounds.Left; + else if (this.X > m_levelScreen.CurrentRoom.Bounds.Right) + this.X = m_levelScreen.CurrentRoom.Bounds.Right; + + if (this.Y < m_levelScreen.CurrentRoom.Bounds.Top) + this.Y = m_levelScreen.CurrentRoom.Bounds.Top; + else if (this.Y > m_levelScreen.CurrentRoom.Bounds.Bottom) + this.Y = m_levelScreen.CurrentRoom.Bounds.Bottom; + } + + if (m_currentActiveLB == m_cooldownLB) // If Teddy made CoolDownLB == currentActiveLB (which is a no-no), only update one of them. + m_currentActiveLB.Update(gameTime); + else + { + m_currentActiveLB.Update(gameTime); + m_cooldownLB.Update(gameTime); + } + } + } + + if (IsWeighted == true) + CheckGroundCollision(); + + // Maintains the enemy's speed in the air so that he can jump onto platforms. + //if (m_isTouchingGround == false && IsWeighted == true && CurrentSpeed == 0) + // this.CurrentSpeed = this.Speed; + + + if (this.CurrentHealth <= 0 && IsKilled == false && m_bossVersionKilled == false) + Kill(); + + base.Update(gameTime); + } + + public void CheckGroundCollisionOld() + { + m_numTouchingGrounds = 0; + float closestGround = int.MaxValue; + IPhysicsObj collidedObj = null; + int collisionMarginOfError = 10; + bool goingDown = true; // A bool that keeps track of whether the player is going down a slope or not. + //Might not need GroundCollisionRect. Could just use this.Bounds.bottom + 10 or something. + // Finds the distance between the player and the closest collidable object below him. + foreach (IPhysicsObj obj in m_levelScreen.PhysicsManager.ObjectList) + { + if (obj != this && obj.CollidesTop == true && + (obj.CollisionTypeTag == GameTypes.CollisionType_WALL || obj.CollisionTypeTag == GameTypes.CollisionType_WALL_FOR_PLAYER || obj.CollisionTypeTag == GameTypes.CollisionType_ENEMYWALL + || obj.CollisionTypeTag == GameTypes.CollisionType_GLOBAL_DAMAGE_WALL)) // only check walls below the player. + { + //if ((obj.Rotation != 0) || //&& obj.Rotation >= -SlopeClimbRotation && obj.Rotation <= SlopeClimbRotation) || // Disabled because turrets go beyond slope rotation. + // (obj.Bounds.Top >= this.Bounds.Bottom - 5 && // -5 margin of error + // ((obj.Bounds.Left <= this.Bounds.Right && obj.Bounds.Right >= this.Bounds.Right && (this.Bounds.Right - obj.Bounds.Left > collisionMarginOfError)) || + // (this.Bounds.Left <= obj.Bounds.Right && this.Bounds.Right >= obj.Bounds.Right && (obj.Bounds.Right - this.Bounds.Left > collisionMarginOfError))))) + if (Math.Abs(obj.Bounds.Top - this.Bounds.Bottom) < collisionMarginOfError) + { + foreach (CollisionBox box in obj.CollisionBoxes) + { + if (box.Type == Consts.TERRAIN_HITBOX) + { + Rectangle rectToCheck = GroundCollisionRect; + if (box.AbsRotation != 0) + rectToCheck = RotatedGroundCollisionRect; + + if (CollisionMath.RotatedRectIntersects(rectToCheck, 0, Vector2.Zero, box.AbsRect, box.AbsRotation, Vector2.Zero)) + { + m_numTouchingGrounds++; + + if (box.AbsParent.Rotation == 0) + goingDown = false; + + Vector2 mtd = CollisionMath.RotatedRectIntersectsMTD(GroundCollisionRect, 0, Vector2.Zero, box.AbsRect, box.AbsRotation, Vector2.Zero); + //float distanceBetween = box.AbsRect.Top - (this.Bounds.Bottom); + if (goingDown == true) + goingDown = !CollisionMath.RotatedRectIntersects(this.Bounds, 0, Vector2.Zero, box.AbsRect, box.AbsRotation, Vector2.Zero); + float distanceBetween = mtd.Y; + if (closestGround > distanceBetween) + { + closestGround = distanceBetween; + collidedObj = obj; + } + } + } + } + } + } + } + + // Check to see if the player is touching the ground or not. Margin of error +-2. + if (closestGround <= 2 && AccelerationY >= 0) // Only check ground if the player is falling. + m_isTouchingGround = true; + } + + + private void CheckGroundCollision() + { + m_isTouchingGround = false; + m_numTouchingGrounds = 0; + + if (this.AccelerationY >= 0)// Only check ground collision if falling. Do not check if he's going up, or jumping. + { + IPhysicsObj closestTerrain = null; + float closestFloor = float.MaxValue; + + IPhysicsObj closestRotatedTerrain = null; + float closestRotatedFloor = float.MaxValue; + + Rectangle elongatedBounds = this.TerrainBounds; + elongatedBounds.Height += 10; // A rectangle slightly larger than the player's height is needed to check for collisions with. + + //foreach (IPhysicsObj collisionObj in PhysicsMngr.ObjectList) + foreach (TerrainObj collisionObj in m_levelScreen.CurrentRoom.TerrainObjList) + { + if (collisionObj.Visible == true && collisionObj.IsCollidable == true && collisionObj.CollidesTop == true && collisionObj.HasTerrainHitBox == true && + (collisionObj.CollisionTypeTag == GameTypes.CollisionType_WALL || + collisionObj.CollisionTypeTag == GameTypes.CollisionType_GLOBAL_DAMAGE_WALL || + collisionObj.CollisionTypeTag == GameTypes.CollisionType_WALL_FOR_ENEMY || + collisionObj.CollisionTypeTag == GameTypes.CollisionType_ENEMYWALL)) + { + // Do separate checks for sloped and non-sloped terrain. + if (collisionObj.Rotation == 0) + { + Rectangle elongatedNumGroundsBounds = elongatedBounds; // A special bounds purely for checking the number of ground objects you're touching. + elongatedNumGroundsBounds.X -= 30; + elongatedNumGroundsBounds.Width += 60; + Vector2 numGroundMTD = CollisionMath.CalculateMTD(elongatedNumGroundsBounds, collisionObj.Bounds); + if (numGroundMTD != Vector2.Zero) + m_numTouchingGrounds++; + + Vector2 mtd = CollisionMath.CalculateMTD(elongatedBounds, collisionObj.Bounds); + if (mtd.Y < 0) // Object is below player. + { + int distance = collisionObj.Bounds.Top - this.Bounds.Bottom; + if (distance < closestFloor) + { + closestTerrain = collisionObj; + closestFloor = distance; + } + } + } + else + { + Vector2 rotatedMTD = CollisionMath.RotatedRectIntersectsMTD(elongatedBounds, this.Rotation, Vector2.Zero, collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + if (rotatedMTD != Vector2.Zero) + m_numTouchingGrounds++; + + + if (rotatedMTD.Y < 0) + { + float distance = rotatedMTD.Y; + if (distance < closestRotatedFloor) + if (rotatedMTD.Y < 0) + { + closestRotatedTerrain = collisionObj; + closestRotatedFloor = distance; + } + } + + //if (State != STATE_DASHING) + { + // Code for hooking the player to a slope + Rectangle elongatedRect = this.TerrainBounds; + elongatedRect.Height += 50; + int checkAmount = 15; + Vector2 elongatedMTD = CollisionMath.RotatedRectIntersectsMTD(elongatedRect, this.Rotation, Vector2.Zero, collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + if (elongatedMTD.Y < 0) // Player is standing on a slope because the mtd is telling you to push him up. + { + float dist = CDGMath.DistanceBetweenPts(elongatedMTD, Vector2.Zero); + float slopeDistance = (float)(50 - (Math.Sqrt((dist * dist) * 2))); + if (slopeDistance > 0 && slopeDistance < checkAmount) // This checks to see if the player is close enough to the ground to latch to it. + this.Y += slopeDistance; + float distance = rotatedMTD.Y; + if (distance < closestRotatedFloor) + { + closestRotatedTerrain = collisionObj; + closestRotatedFloor = distance; + } + } + } + } + } + + if (closestTerrain != null) + m_isTouchingGround = true; + + if (closestRotatedTerrain != null) + { + //HookToSlope(closestRotatedTerrain); + m_isTouchingGround = true; + } + + //if (this is EnemyObj_Zombie) + //Console.WriteLine(m_numTouchingGrounds); + } + } + } + + private void HookToSlope(IPhysicsObj collisionObj) + { + this.UpdateCollisionBoxes(); + + // Code for hooking the player to a slope + Rectangle elongatedRect = this.TerrainBounds; + elongatedRect.Height += 100; + //int checkAmount = 15; + float x1 = this.X; + + Vector2 elongatedMTD = CollisionMath.RotatedRectIntersectsMTD(elongatedRect, this.Rotation, Vector2.Zero, collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + if (elongatedMTD.Y < 0) // Player is standing on a slope because the mtd is telling you to push him up. + { + bool checkCollision = false; + float y1 = float.MaxValue; + Vector2 pt1, pt2; + if (collisionObj.Width > collisionObj.Height) // If rotated objects are done correctly. + { + pt1 = CollisionMath.UpperLeftCorner(collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + pt2 = CollisionMath.UpperRightCorner(collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + + //if (collisionObj.Rotation == 45) + if (collisionObj.Rotation > 0)// ROTCHECK + x1 = this.TerrainBounds.Left; + else + x1 = this.TerrainBounds.Right; + + if (x1 > pt1.X && x1 < pt2.X) + checkCollision = true; + } + else // If rotated objects are done Teddy's incorrect way. + { + //if (collisionObj.Rotation == 45) + if (collisionObj.Rotation > 0) // ROTCHECK + { + pt1 = CollisionMath.LowerLeftCorner(collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + pt2 = CollisionMath.UpperLeftCorner(collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + x1 = this.TerrainBounds.Right; + if (x1 > pt1.X && x1 < pt2.X) + checkCollision = true; + } + else + { + pt1 = CollisionMath.UpperRightCorner(collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + pt2 = CollisionMath.LowerRightCorner(collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + x1 = this.TerrainBounds.Left; + if (x1 > pt1.X && x1 < pt2.X) + checkCollision = true; + } + } + + if (checkCollision == true) + { + float u = pt2.X - pt1.X; + float v = pt2.Y - pt1.Y; + float x = pt1.X; + float y = pt1.Y; + + y1 = y + (x1 - x) * (v / u); + y1 -= this.TerrainBounds.Bottom - this.Y - 2; // Up by 2 to ensure collision response doesn't kick in. + this.Y = (int)y1; + } + } + } + + protected void SetCooldownLogicBlock(LogicBlock cooldownLB, params int[] percentage) + { + m_cooldownLB = cooldownLB; + m_cooldownParams = percentage; + } + + protected void RunLogicBlock(bool runCDLogicAfterward, LogicBlock block, params int[] percentage) + { + m_runCooldown = runCDLogicAfterward; + m_currentActiveLB = block; + m_currentActiveLB.RunLogicBlock(percentage); + } + + protected virtual void RunBasicLogic() + { + //m_currentActiveLB = m_walkingLB; + //m_currentActiveLB.RunLogicBlock(50, 30, 20); + } + + protected virtual void RunAdvancedLogic() { RunBasicLogic(); } + + protected virtual void RunExpertLogic() { RunBasicLogic(); } + + protected virtual void RunMinibossLogic() { RunBasicLogic(); } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + IPhysicsObj otherBoxParent = otherBox.AbsParent as IPhysicsObj; + Vector2 mtd = CollisionMath.CalculateMTD(thisBox.AbsRect, otherBox.AbsRect); + + if (collisionResponseType == Consts.COLLISIONRESPONSE_FIRSTBOXHIT && (otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_PLAYER || otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_GLOBAL_DAMAGE_WALL || (otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_GLOBAL_DAMAGE_WALL && this.IsWeighted == true)) + && ((otherBox.AbsParent is ProjectileObj == false && m_invincibleCounter <= 0) || (otherBox.AbsParent is ProjectileObj && (m_invincibleCounterProjectile <= 0 || (otherBox.AbsParent as ProjectileObj).IgnoreInvincibleCounter == true)))) + { + // Don't do anything if the enemy is demented + if (IsDemented == true) + { + m_invincibleCounter = InvincibilityTime; + m_invincibleCounterProjectile = InvincibilityTime; + m_levelScreen.ImpactEffectPool.DisplayQuestionMark(new Vector2(this.X, this.Bounds.Top)); + return; + } + + // Player has hit enemy. + int damage = (otherBoxParent as IDealsDamageObj).Damage; + bool isPlayer = false; // Keeps track of whether or not it is the player hitting the enemy. + + //if (otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_PLAYER) + if (otherBoxParent == m_target) + { + if (CDGMath.RandomFloat(0, 1) <= m_target.TotalCritChance && this.NonKillable == false && otherBoxParent == m_target) + { + //m_levelScreen.TextManager.DisplayStringText("Critical!", Color.Red, new Vector2(this.X, this.Bounds.Top - 65)); + m_levelScreen.ImpactEffectPool.DisplayCriticalText(new Vector2(this.X, this.Bounds.Top)); + damage = (int)(damage * m_target.TotalCriticalDamage); // Critical hit! + } + isPlayer = true; + } + + ProjectileObj projectile = otherBox.AbsParent as ProjectileObj; + if (projectile != null) + { + // m_lastDamageSource is for projectiles only. + m_invincibleCounterProjectile = InvincibilityTime; + + if (projectile.DestroysWithEnemy == true && this.NonKillable == false) + projectile.RunDestroyAnimation(false); + } + + Point intersectPt = Rectangle.Intersect(thisBox.AbsRect, otherBox.AbsRect).Center; + if (thisBox.AbsRotation != 0 || otherBox.AbsRotation != 0) + intersectPt = Rectangle.Intersect(thisBox.AbsParent.Bounds, otherBox.AbsParent.Bounds).Center; + Vector2 impactPosition = new Vector2(intersectPt.X, intersectPt.Y); + + if (projectile == null || (projectile != null && projectile.Spell != SpellType.Shout)) + { + if (projectile != null || (otherBoxParent.CollisionTypeTag != GameTypes.CollisionType_GLOBAL_DAMAGE_WALL || + (otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_GLOBAL_DAMAGE_WALL && this.IsWeighted == true))) // Make sure flying enemies don't hit global damage walls. + HitEnemy(damage, impactPosition, isPlayer); + } + else if (projectile != null && projectile.Spell == SpellType.Shout) // Fus roh dah logic. + { + if (CanBeKnockedBack == true && IsPaused == false) + { + //Knock the enemy to the left if he's to the left of the player. + this.CurrentSpeed = 0; + + float knockbackMod = GameEV.BARBARIAN_SHOUT_KNOCKBACK_MOD; + if (this.KnockBack == Vector2.Zero) + { + if (this.X < m_target.X) + AccelerationX = -m_target.EnemyKnockBack.X * knockbackMod; + else + AccelerationX = m_target.EnemyKnockBack.X * knockbackMod; + AccelerationY = -m_target.EnemyKnockBack.Y * knockbackMod; + } + else + { + if (this.X < m_target.X) + AccelerationX = -KnockBack.X * knockbackMod; + else + AccelerationX = KnockBack.X * knockbackMod; + AccelerationY = -KnockBack.Y * knockbackMod; + } + } + } + + // The invincibility counter is for the player only. + if (otherBoxParent == m_target) + m_invincibleCounter = InvincibilityTime; // Convert to milliseconds. + + //m_levelScreen.ProjectileManager.DestroyProjectile(projectile); + } + + // Only do terrain collision with actual terrain, since the player also has a terrain collision box. + if (collisionResponseType == Consts.COLLISIONRESPONSE_TERRAIN && + (otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_WALL || + otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_WALL_FOR_ENEMY || + otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_GLOBAL_DAMAGE_WALL) + && this.CollisionTypeTag != GameTypes.CollisionType_ENEMYWALL) + { + // Enemy is colliding with a wall, so stop animating it. + if (this.CurrentSpeed != 0 && mtd.X != 0) + { + if (Math.Abs(mtd.X) > 10 && ((mtd.X > 0 && otherBoxParent.CollidesRight == true) ||( mtd.X < 0 && otherBoxParent.CollidesLeft == true))) + this.CurrentSpeed = 0; + //this.StopAnimation(); // OR don't stop it. + //this.PlayAnimation(0, 0, false); // Rather than stopping the animation, set it to the first frame. + } + + //// Enemy is near an edge and is not allowed to fall off. + if (m_numTouchingGrounds <= 1 && this.CurrentSpeed != 0 && mtd.Y < 0 && CanFallOffLedges == false) + { + if (this.Bounds.Left < otherBoxParent.Bounds.Left && this.HeadingX < 0) + { + this.X = otherBoxParent.Bounds.Left + (this.AbsX - this.Bounds.Left); + this.CurrentSpeed = 0; + //this.StopAnimation(); + } + else if (this.Bounds.Right > otherBoxParent.Bounds.Right && this.HeadingX > 0) + { + this.X = otherBoxParent.Bounds.Right - (this.Bounds.Right - this.AbsX); + this.CurrentSpeed = 0; + //this.StopAnimation(); + } + + m_isTouchingGround = true; + } + + // If enemy is knocked back and touches the ground, stop moving him backwards. + //if (this.AccelerationX != 0 && this.AccelerationY > 0 && CollisionMath.CalculateMTD(thisBox.AbsRect, otherBox.AbsRect).Y != 0) + if (this.AccelerationX != 0 && m_isTouchingGround == true) + this.AccelerationX = 0; + //else + //{ + // Console.WriteLine(AccelerationX + " " + (AccelerationY > 0) + " " + (CollisionMath.CalculateMTD(thisBox.AbsRect, otherBox.AbsRect).Y != 0)); + //} + + bool disableCollision = false; + if (Math.Abs(mtd.X) < 10 && mtd.X != 0 && Math.Abs(mtd.Y) < 10 && mtd.Y != 0) + disableCollision = true; + + // Used to make sure enemy doesn't hook to 1-way ground above him if he's already standing on flooring. + if (m_isTouchingGround == true && otherBoxParent.CollidesBottom == false && otherBoxParent.CollidesTop == true && otherBoxParent.TerrainBounds.Top < this.TerrainBounds.Bottom - 30) + disableCollision = true; + + // Special handling to prevent enemy from hooking to the top of tunnels. + if (otherBoxParent.CollidesRight == false && otherBoxParent.CollidesLeft == false && otherBoxParent.CollidesTop == true && otherBoxParent.CollidesBottom == true) + disableCollision = true; + + // Disables collision on bookcases and stuff for enemies. + //if (otherBoxParent is TerrainObj == false) + // disableCollision = true; + + Vector2 rotatedMTDPos = CollisionMath.RotatedRectIntersectsMTD(thisBox.AbsRect, thisBox.AbsRotation, Vector2.Zero, otherBox.AbsRect, otherBox.AbsRotation, Vector2.Zero); + if (disableCollision == false) + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + + if (rotatedMTDPos.Y < 0 && otherBox.AbsRotation != 0 && IsWeighted == true) // Code to prevent player from sliding down rotated objects. + this.X -= rotatedMTDPos.X; + } + } + + public virtual void HitEnemy(int damage, Vector2 collisionPt, bool isPlayer) + { + if (Game.PlayerStats.GodMode == true) + damage = 9999999; + + if (m_target != null && m_target.CurrentHealth > 0) + { + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "EnemyHit1", "EnemyHit2", "EnemyHit3", "EnemyHit4", "EnemyHit5", "EnemyHit6"); + Blink(Color.Red, 0.1f); + this.m_levelScreen.ImpactEffectPool.DisplayEnemyImpactEffect(collisionPt); + + if (isPlayer == true && (Game.PlayerStats.Class == ClassType.SpellSword || Game.PlayerStats.Class == ClassType.SpellSword2)) + { + this.CurrentHealth -= damage; + m_target.CurrentMana += (int)(damage * GameEV.SPELLSWORD_ATTACK_MANA_CONVERSION); + m_levelScreen.TextManager.DisplayNumberText(damage, Color.Red, new Vector2(this.X, this.Bounds.Top)); + m_levelScreen.TextManager.DisplayNumberStringText((int)(damage * GameEV.SPELLSWORD_ATTACK_MANA_CONVERSION), "LOC_ID_SKILL_SCREEN_15" /*"mp"*/, Color.RoyalBlue, new Vector2(m_target.X, m_target.Bounds.Top - 30)); + } + else + { + this.CurrentHealth -= damage; + m_levelScreen.TextManager.DisplayNumberText(damage, Color.Red, new Vector2(this.X, this.Bounds.Top)); + } + + if (isPlayer == true) // Only perform these checks if the object hitting the enemy is the player. + { + m_target.NumSequentialAttacks++; + + if (m_target.IsAirAttacking == true) + { + m_target.IsAirAttacking = false; // Only allow one object to perform upwards air knockback on the player. + m_target.AccelerationY = -m_target.AirAttackKnockBack; + m_target.NumAirBounces++; + } + } + + if (CanBeKnockedBack == true && IsPaused == false && (Game.PlayerStats.Traits.X != TraitType.Hypogonadism && Game.PlayerStats.Traits.Y != TraitType.Hypogonadism)) + { + //Knock the enemy to the left if he's to the left of the player. + this.CurrentSpeed = 0; + + float knockbackMod = 1; + if (Game.PlayerStats.Traits.X == TraitType.Hypergonadism || Game.PlayerStats.Traits.Y == TraitType.Hypergonadism) + knockbackMod = GameEV.TRAIT_HYPERGONADISM; + + if (this.KnockBack == Vector2.Zero) + { + if (this.X < m_target.X) + AccelerationX = -m_target.EnemyKnockBack.X * knockbackMod; + else + AccelerationX = m_target.EnemyKnockBack.X * knockbackMod; + AccelerationY = -m_target.EnemyKnockBack.Y * knockbackMod; + } + else + { + if (this.X < m_target.X) + AccelerationX = -KnockBack.X * knockbackMod; + else + AccelerationX = KnockBack.X * knockbackMod; + AccelerationY = -KnockBack.Y * knockbackMod; + } + } + + m_levelScreen.SetLastEnemyHit(this); + } + } + + // Sets the enemy to a killed state, without all the jazz of SFX, animations, and giving you XP. + public void KillSilently() + { + base.Kill(false); + } + + public override void Kill(bool giveXP = true) + { + // Get health back for killing enemy. + int vampirism = m_target.TotalVampBonus; + if (vampirism > 0) + { + m_target.CurrentHealth += vampirism; + this.m_levelScreen.TextManager.DisplayNumberStringText(vampirism, "LOC_ID_SKILL_SCREEN_14" /*"hp"*/, Color.LightGreen, new Vector2(m_target.X, m_target.Bounds.Top - 60)); + } + + // Get mana back for killing enemy. + if (m_target.ManaGain > 0) + { + m_target.CurrentMana += m_target.ManaGain; + m_levelScreen.TextManager.DisplayNumberStringText((int)m_target.ManaGain, "LOC_ID_SKILL_SCREEN_15" /*"mp"*/, Color.RoyalBlue, new Vector2(m_target.X, m_target.Bounds.Top - 90)); + } + + if (Game.PlayerStats.SpecialItem == SpecialItemType.GoldPerKill) + { + m_levelScreen.ItemDropManager.DropItem(this.Position, ItemDropType.Coin, ItemDropType.CoinAmount); + m_levelScreen.ItemDropManager.DropItem(this.Position, ItemDropType.Coin, ItemDropType.CoinAmount); + //m_levelScreen.ItemDropManager.DropItem(this.Position, ItemDropType.Coin, ItemDropType.CoinAmount); + } + + this.m_levelScreen.KillEnemy(this); + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Enemy_Death"); + //SoundManager.Play3DSound(this, Game.ScreenManager.Player, "EnemyDeath2", "EnemyDeath3", "EnemyDeath4", "EnemyDeath5", "EnemyDeath6" + // , "EnemyDeath7", "EnemyDeath8", "EnemyDeath9"); + + if (DropsItem == true) + { + // Chance of dropping health or mana. Or in the case of a chicken, health. + if (this.Type == EnemyType.Chicken) + m_levelScreen.ItemDropManager.DropItem(this.Position, ItemDropType.Health, GameEV.ITEM_HEALTHDROP_AMOUNT); + else if (CDGMath.RandomInt(1, 100) <= GameEV.ENEMY_ITEMDROP_CHANCE) + { + if (CDGMath.RandomPlusMinus() < 0) + m_levelScreen.ItemDropManager.DropItem(this.Position, ItemDropType.Health, GameEV.ITEM_HEALTHDROP_AMOUNT); + else + m_levelScreen.ItemDropManager.DropItem(this.Position, ItemDropType.Mana, GameEV.ITEM_MANADROP_AMOUNT); + } + + if (CDGMath.RandomFloat(0, 1) <= MoneyDropChance) // 100% chance of dropping money. + { + int goldAmount = CDGMath.RandomInt(MinMoneyDropAmount, MaxMoneyDropAmount) * 10 + (int)((CDGMath.RandomFloat(MinMoneyGainPerLevel, MaxMoneyGainPerLevel) * this.Level) * 10); + + int numBigDiamonds = (int)(goldAmount / ItemDropType.BigDiamondAmount); + goldAmount -= numBigDiamonds * ItemDropType.BigDiamondAmount; + + int numDiamonds = (int)(goldAmount / ItemDropType.DiamondAmount); + goldAmount -= numDiamonds * ItemDropType.DiamondAmount; + + int numMoneyBags = (int)(goldAmount / ItemDropType.MoneyBagAmount); + goldAmount -= numMoneyBags * ItemDropType.MoneyBagAmount; + + int numCoins = goldAmount / ItemDropType.CoinAmount; + + for (int i = 0; i < numBigDiamonds; i++) + m_levelScreen.ItemDropManager.DropItem(this.Position, ItemDropType.BigDiamond, ItemDropType.BigDiamondAmount); + + for (int i = 0; i < numDiamonds; i++) + m_levelScreen.ItemDropManager.DropItem(this.Position, ItemDropType.Diamond, ItemDropType.DiamondAmount); + + for (int i = 0; i < numMoneyBags; i++) + m_levelScreen.ItemDropManager.DropItem(this.Position, ItemDropType.MoneyBag, ItemDropType.MoneyBagAmount); + + for (int i = 0; i < numCoins; i++) + m_levelScreen.ItemDropManager.DropItem(this.Position, ItemDropType.Coin, ItemDropType.CoinAmount); + } + } + + if (m_currentActiveLB.IsActive) + m_currentActiveLB.StopLogicBlock(); + m_levelScreen.ImpactEffectPool.DisplayDeathEffect(this.Position); + + if ((Game.PlayerStats.Class == ClassType.Lich || Game.PlayerStats.Class == ClassType.Lich2) && this.GivesLichHealth == true) + { + int lichHealthGain = 0; + int playerLevel = Game.PlayerStats.CurrentLevel; + int enemyLevel = (int)(this.Level * LevelEV.ENEMY_LEVEL_FAKE_MULTIPLIER); + + if (playerLevel < enemyLevel) + lichHealthGain = GameEV.LICH_HEALTH_GAIN_PER_KILL; + else if (playerLevel >= enemyLevel) + lichHealthGain = GameEV.LICH_HEALTH_GAIN_PER_KILL_LESSER; + + int maxPlayerHealth = (int)Math.Round(((m_target.BaseHealth + m_target.GetEquipmentHealth() + + (Game.PlayerStats.BonusHealth * GameEV.ITEM_STAT_MAXHP_AMOUNT) + + SkillSystem.GetSkill(SkillType.Health_Up).ModifierAmount + + SkillSystem.GetSkill(SkillType.Health_Up_Final).ModifierAmount)) * GameEV.LICH_MAX_HP_OFF_BASE, MidpointRounding.AwayFromZero); + + // Only give health if the lich hasn't reach max health allowed. + if (m_target.MaxHealth + lichHealthGain < maxPlayerHealth) + { + Game.PlayerStats.LichHealth += lichHealthGain; + m_target.CurrentHealth += lichHealthGain; + m_levelScreen.TextManager.DisplayNumberStringText(lichHealthGain, "LOC_ID_PLAYER_OBJ_3" /*"max hp"*/, Color.LightGreen, new Vector2(m_target.X, m_target.Bounds.Top - 30)); + } + + //Game.PlayerStats.LichHealth += GameEV.LICH_HEALTH_GAIN_PER_KILL; + //m_target.CurrentHealth += GameEV.LICH_HEALTH_GAIN_PER_KILL; + //m_levelScreen.TextManager.DisplayNumberStringText(GameEV.LICH_HEALTH_GAIN_PER_KILL, "LOC_ID_PLAYER_OBJ_3" /*"max hp"*/, Color.LightGreen, new Vector2(m_target.X, m_target.Bounds.Top - 30)); + } + + Game.PlayerStats.NumEnemiesBeaten++; + + if (m_saveToEnemiesKilledList == true) + { + // Incrementing the number of times you've killed a specific type of enemy. + Vector4 enemyData = Game.PlayerStats.EnemiesKilledList[(int)this.Type]; + switch (this.Difficulty) + { + case (GameTypes.EnemyDifficulty.BASIC): + enemyData.X += 1; + break; + case (GameTypes.EnemyDifficulty.ADVANCED): + enemyData.Y += 1; + break; + case (GameTypes.EnemyDifficulty.EXPERT): + enemyData.Z += 1; + break; + case (GameTypes.EnemyDifficulty.MINIBOSS): + enemyData.W += 1; + break; + } + Game.PlayerStats.EnemiesKilledList[(int)this.Type] = enemyData; + } + + if (giveXP == true && this.Type == EnemyType.Chicken) + GameUtil.UnlockAchievement("FEAR_OF_CHICKENS"); + + base.Kill(); + } + + public void PauseEnemy(bool forcePause = false) + { + if ((IsPaused == false && IsKilled == false && m_bossVersionKilled == false) || forcePause == true) + { + m_isPaused = true; + this.DisableAllWeight = true; + this.PauseAnimation(); + } + } + + public void UnpauseEnemy(bool forceUnpause = false) + { + if ((IsPaused == true && IsKilled == false && m_bossVersionKilled == false) || forceUnpause == true) + { + m_isPaused = false; + this.DisableAllWeight = false; + this.ResumeAnimation(); + } + } + + public void DrawDetectionRadii(Camera2D camera) + { + camera.Draw(m_engageRadiusTexture, new Vector2(this.Position.X - EngageRadius, this.Position.Y - EngageRadius), Color.Red * 0.5f); + camera.Draw(m_projectileRadiusTexture, new Vector2(this.Position.X - ProjectileRadius, this.Position.Y - ProjectileRadius), Color.Blue * 0.5f); + camera.Draw(m_meleeRadiusTexture, new Vector2(this.Position.X - MeleeRadius, this.Position.Y - MeleeRadius), Color.Green * 0.5f); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + if (m_currentActiveLB.IsActive) + m_currentActiveLB.StopLogicBlock(); + m_currentActiveLB = null; + + // Disposing all logicblocks creating by classes that inherit from EnemyObj. + foreach (LogicBlock disposeLB in logicBlocksToDispose) + disposeLB.Dispose(); + + for (int i = 0; i < logicBlocksToDispose.Count; i++) + logicBlocksToDispose[i] = null; + logicBlocksToDispose.Clear(); + logicBlocksToDispose = null; + + m_target = null; // Do not dispose player. He will dispose himself. + m_walkingLB.Dispose(); + m_walkingLB = null; + + if (m_cooldownLB.IsActive) + m_cooldownLB.StopLogicBlock(); + m_cooldownLB.Dispose(); + m_cooldownLB = null; + + if (m_engageRadiusTexture != null) + m_engageRadiusTexture.Dispose(); + m_engageRadiusTexture = null; + + if (m_engageRadiusTexture != null) + m_projectileRadiusTexture.Dispose(); + m_projectileRadiusTexture = null; + + if (m_engageRadiusTexture != null) + m_meleeRadiusTexture.Dispose(); + m_meleeRadiusTexture = null; + + if (m_cooldownParams != null) + Array.Clear(m_cooldownParams, 0, m_cooldownParams.Length); + m_cooldownParams = null; + + TintablePart = null; + m_flipTween = null; + + base.Dispose(); + } + } + + public override void Reset() + { + if (m_currentActiveLB.IsActive == true) + m_currentActiveLB.StopLogicBlock(); + + if (m_cooldownLB.IsActive == true) + m_cooldownLB.StopLogicBlock(); + + this.m_invincibleCounter = 0; + this.m_invincibleCounterProjectile = 0; + this.State = STATE_WANDER; + this.ChangeSprite(m_resetSpriteName); + if (this.PlayAnimationOnRestart == true) + this.PlayAnimation(true); + m_initialDelayCounter = InitialLogicDelay; + UnpauseEnemy(true); + m_bossVersionKilled = false; + m_blinkTimer = 0; + base.Reset(); + } + + public virtual void ResetState() // The state to reset the enemy to when transitioning rooms. + { + if (m_currentActiveLB.IsActive == true) + m_currentActiveLB.StopLogicBlock(); + + if (m_cooldownLB.IsActive == true) + m_cooldownLB.StopLogicBlock(); + + this.m_invincibleCounter = 0; + m_invincibleCounterProjectile = 0; + this.State = STATE_WANDER; + if (this.Type != EnemyType.Portrait) // Hack to make sure portraits don't change their picture. + this.ChangeSprite(m_resetSpriteName); + if (this.PlayAnimationOnRestart == true) + this.PlayAnimation(true); + m_initialDelayCounter = InitialLogicDelay; + + LockFlip = m_internalLockFlip; + Flip = InternalFlip; + this.AnimationDelay = m_internalAnimationDelay; + UnpauseEnemy(true); + + CurrentHealth = MaxHealth; // Refresh the enemy's health if you leave the room. + + m_blinkTimer = 0; + } + + protected float ParseTagToFloat(string key) + { + if (this.Tag != "") + { + int firstIndex = Tag.IndexOf(key + ":") + key.Length + 1; // Find the end of the word. + int length = Tag.IndexOf(",", firstIndex); // Find the first comma. + if (length == -1) + length = Tag.Length; // If you still can't find anything, go to the end of the string. + try + { + // flibit didn't like this + // CultureInfo ci = (CultureInfo)CultureInfo.CurrentCulture.Clone(); + // ci.NumberFormat.CurrencyDecimalSeparator = "."; + CultureInfo ci = CultureInfo.InvariantCulture; + return float.Parse(Tag.Substring(firstIndex, length - firstIndex), NumberStyles.Any, ci); + } + catch (Exception ex) + { + Console.WriteLine("Could not parse key:" + key + " with string:" + Tag + ". Original Error: " + ex.Message); + return 0; + } + } + return 0; + } + + protected string ParseTagToString(string key) + { + int firstIndex = Tag.IndexOf(key + ":") + key.Length + 1; // Find the end of the word. + int length = Tag.IndexOf(",", firstIndex); // Find the first comma. + if (length == -1) + length = Tag.Length; // If you still can't find anything, go to the end of the string. + return Tag.Substring(firstIndex, length - firstIndex); + } + + //public override void Draw(Camera2D camera) + //{ + // camera.Draw(Game.GenericTexture, GroundCollisionRect, Color.White); + // base.Draw(camera); + //} + + protected override GameObj CreateCloneInstance() + { + return EnemyBuilder.BuildEnemy(this.Type, m_target, null, m_levelScreen, this.Difficulty); + //return EnemyBuilder.BuildEnemy(this.Type, m_target, PhysicsMngr, m_levelScreen, this.Difficulty); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + EnemyObj clone = obj as EnemyObj; + clone.IsProcedural = this.IsProcedural; + clone.InitialLogicDelay = this.InitialLogicDelay; + clone.NonKillable = this.NonKillable; + clone.GivesLichHealth = this.GivesLichHealth; + clone.DropsItem = this.DropsItem; + clone.IsDemented = this.IsDemented; + + //clone.InternalFlip = this.InternalFlip; Defined in CharacterObj + } + + private Rectangle GroundCollisionRect + { + get { return new Rectangle((int)this.Bounds.X - 10, (int)this.Bounds.Y, this.Width + 20, this.Height + 10); } + } + + private Rectangle RotatedGroundCollisionRect + { + get { return new Rectangle((int)this.Bounds.X, (int)this.Bounds.Y, this.Bounds.Width, this.Bounds.Height + 40); } + } + + public override Rectangle Bounds + { + get + { + if (this.IsWeighted == true) + return this.TerrainBounds; + else + return base.Bounds; + } + } + + public override int MaxHealth + { + get { return base.MaxHealth + (HealthGainPerLevel * (Level - 1)); } + internal set { base.MaxHealth = value; } + } + + public int Damage + { + get { return m_damage + (DamageGainPerLevel * (Level - 1)); } + internal set { m_damage = value; } + } + + public int XPValue + { + get { return m_xpValue + (XPBonusPerLevel * (Level - 1)); } + internal set { m_xpValue = value; } + } + + public string ResetSpriteName + { + get { return m_resetSpriteName; } + } + + public new bool IsPaused + { + get { return m_isPaused; } + } + + public override SpriteEffects Flip + { + get { return base.Flip; } + set + { + if (Game.PlayerStats.Traits.X == TraitType.StereoBlind || Game.PlayerStats.Traits.Y == TraitType.StereoBlind) + { + if (Flip != value && m_levelScreen != null) + { + if (m_flipTween != null && m_flipTween.TweenedObject == this && m_flipTween.Active == true) + m_flipTween.StopTween(false); + + //float storedX = m_internalScale.X; + float storedX = this.ScaleY; // Uses ScaleY to support flip for shrunken blobs. + this.ScaleX = 0; + m_flipTween = Tween.To(this, 0.15f, Tweener.Tween.EaseNone, "ScaleX", storedX.ToString()); + } + } + base.Flip = value; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_BallAndChain.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_BallAndChain.cs new file mode 100644 index 0000000..e9ab6e7 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_BallAndChain.cs @@ -0,0 +1,538 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_BallAndChain : EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + + private ProjectileObj m_ballAndChain, m_ballAndChain2; + private SpriteObj m_chain; + public float ChainSpeed { get; set; } + public float ChainSpeed2Modifier { get; set; } + + private int m_numChainLinks = 10;//15; + private List m_chainLinksList; + private List m_chainLinks2List; + private float m_chainRadius; + private float m_actualChainRadius; // The radius of the actual chain as it grows to reach m_chainRadius. + private float m_ballAngle = 0; + private float m_chainLinkDistance; + private float m_BallSpeedDivider = 1.5f; //The amount the ball speeds get slowed down by (divided). + private FrameSoundObj m_walkSound, m_walkSound2; + + protected override void InitializeEV() + { + ChainSpeed = 2.5f; + ChainRadius = 260; + ChainSpeed2Modifier = 1.5f; + + #region Basic Variables - General + Name = EnemyEV.BallAndChain_Basic_Name; + LocStringID = EnemyEV.BallAndChain_Basic_Name_locID; + + MaxHealth = EnemyEV.BallAndChain_Basic_MaxHealth; + Damage = EnemyEV.BallAndChain_Basic_Damage; + XPValue = EnemyEV.BallAndChain_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.BallAndChain_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.BallAndChain_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.BallAndChain_Basic_DropChance; + + Speed = EnemyEV.BallAndChain_Basic_Speed; + TurnSpeed = EnemyEV.BallAndChain_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.BallAndChain_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.BallAndChain_Basic_Jump; + CooldownTime = EnemyEV.BallAndChain_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.BallAndChain_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.BallAndChain_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.BallAndChain_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.BallAndChain_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.BallAndChain_Basic_IsWeighted; + + Scale = EnemyEV.BallAndChain_Basic_Scale; + ProjectileScale = EnemyEV.BallAndChain_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.BallAndChain_Basic_Tint; + + MeleeRadius = EnemyEV.BallAndChain_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.BallAndChain_Basic_ProjectileRadius; + EngageRadius = EnemyEV.BallAndChain_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.BallAndChain_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.BallAndChain_Miniboss_Name; + LocStringID = EnemyEV.BallAndChain_Miniboss_Name_locID; + + MaxHealth = EnemyEV.BallAndChain_Miniboss_MaxHealth; + Damage = EnemyEV.BallAndChain_Miniboss_Damage; + XPValue = EnemyEV.BallAndChain_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.BallAndChain_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.BallAndChain_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.BallAndChain_Miniboss_DropChance; + + Speed = EnemyEV.BallAndChain_Miniboss_Speed; + TurnSpeed = EnemyEV.BallAndChain_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.BallAndChain_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.BallAndChain_Miniboss_Jump; + CooldownTime = EnemyEV.BallAndChain_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.BallAndChain_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.BallAndChain_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.BallAndChain_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.BallAndChain_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.BallAndChain_Miniboss_IsWeighted; + + Scale = EnemyEV.BallAndChain_Miniboss_Scale; + ProjectileScale = EnemyEV.BallAndChain_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.BallAndChain_Miniboss_Tint; + + MeleeRadius = EnemyEV.BallAndChain_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.BallAndChain_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.BallAndChain_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.BallAndChain_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + ChainRadius = 350; + ChainSpeed2Modifier = 1.5f; + + #region Expert Variables - General + Name = EnemyEV.BallAndChain_Expert_Name; + LocStringID = EnemyEV.BallAndChain_Expert_Name_locID; + + MaxHealth = EnemyEV.BallAndChain_Expert_MaxHealth; + Damage = EnemyEV.BallAndChain_Expert_Damage; + XPValue = EnemyEV.BallAndChain_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.BallAndChain_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.BallAndChain_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.BallAndChain_Expert_DropChance; + + Speed = EnemyEV.BallAndChain_Expert_Speed; + TurnSpeed = EnemyEV.BallAndChain_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.BallAndChain_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.BallAndChain_Expert_Jump; + CooldownTime = EnemyEV.BallAndChain_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.BallAndChain_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.BallAndChain_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.BallAndChain_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.BallAndChain_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.BallAndChain_Expert_IsWeighted; + + Scale = EnemyEV.BallAndChain_Expert_Scale; + ProjectileScale = EnemyEV.BallAndChain_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.BallAndChain_Expert_Tint; + + MeleeRadius = EnemyEV.BallAndChain_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.BallAndChain_Expert_ProjectileRadius; + EngageRadius = EnemyEV.BallAndChain_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.BallAndChain_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + ChainRadius = 275; + #region Advanced Variables - General + Name = EnemyEV.BallAndChain_Advanced_Name; + LocStringID = EnemyEV.BallAndChain_Advanced_Name_locID; + + MaxHealth = EnemyEV.BallAndChain_Advanced_MaxHealth; + Damage = EnemyEV.BallAndChain_Advanced_Damage; + XPValue = EnemyEV.BallAndChain_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.BallAndChain_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.BallAndChain_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.BallAndChain_Advanced_DropChance; + + Speed = EnemyEV.BallAndChain_Advanced_Speed; + TurnSpeed = EnemyEV.BallAndChain_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.BallAndChain_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.BallAndChain_Advanced_Jump; + CooldownTime = EnemyEV.BallAndChain_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.BallAndChain_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.BallAndChain_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.BallAndChain_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.BallAndChain_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.BallAndChain_Advanced_IsWeighted; + + Scale = EnemyEV.BallAndChain_Advanced_Scale; + ProjectileScale = EnemyEV.BallAndChain_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.BallAndChain_Advanced_Tint; + + MeleeRadius = EnemyEV.BallAndChain_Advanced_MeleeRadius; + EngageRadius = EnemyEV.BallAndChain_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.BallAndChain_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.BallAndChain_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + // Ball and chain has 2 tintable colour parts. + _objectList[1].TextureColor = TintablePart.TextureColor; + + m_ballAndChain.Damage = Damage; + m_ballAndChain.Scale = ProjectileScale; + + m_ballAndChain2.Damage = Damage; + m_ballAndChain2.Scale = ProjectileScale; + } + + protected override void InitializeLogic() + { + LogicSet walkTowardsLS = new LogicSet(this); + //walkTowardsLS.AddAction(new PlayAnimationLogicAction(true)); + walkTowardsLS.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsLS.AddAction(new DelayLogicAction(1.25f, 2.75f)); + + LogicSet walkAwayLS = new LogicSet(this); + //walkAwayLS.AddAction(new PlayAnimationLogicAction(true)); + walkAwayLS.AddAction(new MoveLogicAction(m_target, false)); + walkAwayLS.AddAction(new DelayLogicAction(1.25f, 2.75f)); + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new StopAnimationLogicAction()); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(1.0f, 1.5f)); + + m_generalBasicLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS); + m_generalCooldownLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + + SetCooldownLogicBlock(m_generalCooldownLB, 40, 40, 20); //walkTowardsLS, walkAwayLS, walkStopLS + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 60, 20, 20); //walkTowardsLS, walkAwayLS, walkStopLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100); //walkTowardsLS, walkAwayLS, walkStopLS + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 60, 20, 20); //walkTowardsLS, walkAwayLS, walkStopLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100); //walkTowardsLS, walkAwayLS, walkStopLS + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 60, 20, 20); //walkTowardsLS, walkAwayLS, walkStopLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100); //walkTowardsLS, walkAwayLS, walkStopLS + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + public EnemyObj_BallAndChain(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyFlailKnight_Character", target, physicsManager, levelToAttachTo, difficulty) + { + m_ballAndChain = new ProjectileObj("EnemyFlailKnightBall_Sprite"); // At this point, physicsManager is null. + m_ballAndChain.IsWeighted = false; + m_ballAndChain.CollidesWithTerrain = false; + m_ballAndChain.IgnoreBoundsCheck = true; + m_ballAndChain.OutlineWidth = 2; + + m_ballAndChain2 = m_ballAndChain.Clone() as ProjectileObj; + + m_chain = new SpriteObj("EnemyFlailKnightLink_Sprite"); + + m_chainLinksList = new List(); + m_chainLinks2List = new List(); + for (int i = 0; i < m_numChainLinks; i++) + { + m_chainLinksList.Add(new Vector2()); + } + + for (int i = 0; i < (int)(m_numChainLinks / 2); i++) + { + m_chainLinks2List.Add(new Vector2()); + } + this.Type = EnemyType.BallAndChain; + + this.TintablePart = _objectList[3]; + + m_walkSound = new FrameSoundObj(this, m_target, 1, "KnightWalk1", "KnightWalk2"); + m_walkSound2 = new FrameSoundObj(this, m_target, 6, "KnightWalk1", "KnightWalk2"); + } + + public override void Update(GameTime gameTime) + { + if (IsPaused == false) + { + if (IsKilled == false && m_initialDelayCounter <= 0) + { + float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds; + + if (m_actualChainRadius < ChainRadius) + { + m_actualChainRadius += elapsedSeconds * 200; + m_chainLinkDistance = m_actualChainRadius / m_numChainLinks; + } + + float distance = 0; + m_ballAndChain.Position = CDGMath.GetCirclePosition(m_ballAngle, m_actualChainRadius, new Vector2(this.X, this.Bounds.Top)); + for (int i = 0; i < m_chainLinksList.Count; i++) + { + m_chainLinksList[i] = CDGMath.GetCirclePosition(m_ballAngle, distance, new Vector2(this.X, this.Bounds.Top)); + distance += m_chainLinkDistance; + } + + distance = 0; + if (Difficulty == GameTypes.EnemyDifficulty.ADVANCED) + m_ballAndChain2.Position = CDGMath.GetCirclePosition(m_ballAngle * ChainSpeed2Modifier, m_actualChainRadius / 2, new Vector2(this.X, this.Bounds.Top)); + else if (Difficulty == GameTypes.EnemyDifficulty.EXPERT) + m_ballAndChain2.Position = CDGMath.GetCirclePosition(-m_ballAngle * ChainSpeed2Modifier, -m_actualChainRadius / 2, new Vector2(this.X, this.Bounds.Top)); + for (int i = 0; i < m_chainLinks2List.Count; i++) + { + if (Difficulty == GameTypes.EnemyDifficulty.ADVANCED) + m_chainLinks2List[i] = CDGMath.GetCirclePosition(m_ballAngle * ChainSpeed2Modifier, distance, new Vector2(this.X, this.Bounds.Top)); + else if (Difficulty == GameTypes.EnemyDifficulty.EXPERT) + m_chainLinks2List[i] = CDGMath.GetCirclePosition(-m_ballAngle * ChainSpeed2Modifier, -distance, new Vector2(this.X, this.Bounds.Top)); + distance += m_chainLinkDistance; + } + + m_ballAngle += (ChainSpeed * 60 * elapsedSeconds); + + if (this.IsAnimating == false && this.CurrentSpeed != 0) + this.PlayAnimation(true); + } + + if (this.SpriteName == "EnemyFlailKnight_Character") + { + m_walkSound.Update(); + m_walkSound2.Update(); + } + } + base.Update(gameTime); + } + + public override void Draw(Camera2D camera) + { + if (IsKilled == false) + { + foreach (Vector2 chain in m_chainLinksList) + { + m_chain.Position = chain; + m_chain.Draw(camera); + } + m_ballAndChain.Draw(camera); + + if (Difficulty > GameTypes.EnemyDifficulty.BASIC) + { + foreach (Vector2 chain in m_chainLinks2List) + { + m_chain.Position = chain; + m_chain.Draw(camera); + } + m_ballAndChain2.Draw(camera); + } + + } + base.Draw(camera); + } + + public override void Kill(bool giveXP = true) + { + m_levelScreen.PhysicsManager.RemoveObject(m_ballAndChain); + EnemyObj_BouncySpike spike = new EnemyObj_BouncySpike(m_target, null, m_levelScreen, this.Difficulty); + spike.SavedStartingPos = this.Position; + spike.Position = this.Position; // Set the spike's position to this, so that when the room respawns, the ball appears where the enemy was. + m_levelScreen.AddEnemyToCurrentRoom(spike); + spike.Position = m_ballAndChain.Position; + spike.Speed = ChainSpeed * 200 / m_BallSpeedDivider; + + // Must be called afterward since AddEnemyToCurrentRoom overrides heading. + spike.HeadingX = (float)Math.Cos(MathHelper.WrapAngle(MathHelper.ToRadians(m_ballAngle + 90))); + spike.HeadingY = (float)Math.Sin(MathHelper.WrapAngle(MathHelper.ToRadians(m_ballAngle + 90))); + + if (Difficulty > GameTypes.EnemyDifficulty.BASIC) + { + m_levelScreen.PhysicsManager.RemoveObject(m_ballAndChain2); + + EnemyObj_BouncySpike spike2 = new EnemyObj_BouncySpike(m_target, null, m_levelScreen, this.Difficulty); + spike2.SavedStartingPos = this.Position; + spike2.Position = this.Position; + m_levelScreen.AddEnemyToCurrentRoom(spike2); + spike2.Position = m_ballAndChain2.Position; + spike2.Speed = ChainSpeed * 200 * ChainSpeed2Modifier / m_BallSpeedDivider; + + if (Difficulty == GameTypes.EnemyDifficulty.ADVANCED) + { + spike2.HeadingX = (float)Math.Cos(MathHelper.WrapAngle(MathHelper.ToRadians(m_ballAngle * ChainSpeed2Modifier + 90))); + spike2.HeadingY = (float)Math.Sin(MathHelper.WrapAngle(MathHelper.ToRadians(m_ballAngle * ChainSpeed2Modifier + 90))); + } + else if (Difficulty == GameTypes.EnemyDifficulty.EXPERT) + { + spike2.HeadingX = (float)Math.Cos(MathHelper.WrapAngle(MathHelper.ToRadians(-m_ballAngle * ChainSpeed2Modifier + 90))); + spike2.HeadingY = (float)Math.Sin(MathHelper.WrapAngle(MathHelper.ToRadians(-m_ballAngle * ChainSpeed2Modifier + 90))); + } + + spike2.SpawnRoom = m_levelScreen.CurrentRoom; + spike2.SaveToFile = false; + + if (this.IsPaused) + spike2.PauseEnemy(); + } + + spike.SpawnRoom = m_levelScreen.CurrentRoom; + spike.SaveToFile = false; + + if (this.IsPaused) + spike.PauseEnemy(); + + base.Kill(giveXP); + } + + public override void ResetState() + { + base.ResetState(); + + m_actualChainRadius = 0; + m_chainLinkDistance = m_actualChainRadius / m_numChainLinks; + + float distance = 0; + m_ballAndChain.Position = CDGMath.GetCirclePosition(m_ballAngle, m_actualChainRadius, new Vector2(this.X, this.Bounds.Top)); + for (int i = 0; i < m_chainLinksList.Count; i++) + { + m_chainLinksList[i] = CDGMath.GetCirclePosition(m_ballAngle, distance, new Vector2(this.X, this.Bounds.Top)); + distance += m_chainLinkDistance; + } + + distance = 0; + if (Difficulty == GameTypes.EnemyDifficulty.ADVANCED) + m_ballAndChain2.Position = CDGMath.GetCirclePosition(m_ballAngle * ChainSpeed2Modifier, m_actualChainRadius / 2, new Vector2(this.X, this.Bounds.Top)); + else if (Difficulty == GameTypes.EnemyDifficulty.EXPERT) + m_ballAndChain2.Position = CDGMath.GetCirclePosition(-m_ballAngle * ChainSpeed2Modifier, -m_actualChainRadius / 2, new Vector2(this.X, this.Bounds.Top)); + for (int i = 0; i < m_chainLinks2List.Count; i++) + { + if (Difficulty == GameTypes.EnemyDifficulty.ADVANCED) + m_chainLinks2List[i] = CDGMath.GetCirclePosition(m_ballAngle * ChainSpeed2Modifier, distance, new Vector2(this.X, this.Bounds.Top)); + else if (Difficulty == GameTypes.EnemyDifficulty.EXPERT) + m_chainLinks2List[i] = CDGMath.GetCirclePosition(-m_ballAngle * ChainSpeed2Modifier, -distance, new Vector2(this.X, this.Bounds.Top)); + distance += m_chainLinkDistance; + } + } + + public override void HitEnemy(int damage, Vector2 position, bool isPlayer) + { + SoundManager.Play3DSound(this, m_target, "Knight_Hit01", "Knight_Hit02", "Knight_Hit03"); + base.HitEnemy(damage, position, isPlayer); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_chain.Dispose(); + m_chain = null; + m_ballAndChain.Dispose(); + m_ballAndChain = null; + m_ballAndChain2.Dispose(); + m_ballAndChain2 = null; + m_chainLinksList.Clear(); + m_chainLinksList = null; + m_chainLinks2List.Clear(); + m_chainLinks2List = null; + m_walkSound.Dispose(); + m_walkSound = null; + m_walkSound2.Dispose(); + m_walkSound2 = null; + base.Dispose(); + } + } + + private float ChainRadius + { + get { return m_chainRadius; } + set + { + m_chainRadius = value; + //m_chainLinkDistance = m_chainRadius / m_numChainLinks; + } + } + + public ProjectileObj BallAndChain + { + get { return m_ballAndChain; } + } + + public ProjectileObj BallAndChain2 + { + get { return m_ballAndChain2; } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Blob.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Blob.cs new file mode 100644 index 0000000..cf9aa37 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Blob.cs @@ -0,0 +1,960 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; + +namespace RogueCastle +{ + public class EnemyObj_Blob: EnemyObj + { + //private float SeparationDistance = 50f; // The distance that blobs stay away from other enemies. + + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + private LogicBlock m_generalBossCooldownLB = new LogicBlock(); + + private LogicBlock m_generalNeoLB = new LogicBlock(); + + private int NumHits = 0; // Number of time blobs can split. + + private Vector2 BlobSizeChange = new Vector2(0.4f, 0.4f); + private float BlobSpeedChange = 1.2f; + + private float ExpertBlobProjectileDuration = 5.0f; + + public bool MainBlob { get; set; } + public Vector2 SavedStartingPos { get; set; } + private float JumpDelay = 0.4f; + + public RoomObj SpawnRoom; + + //6500 + private int m_bossCoins = 40; + private int m_bossMoneyBags = 11; + private int m_bossDiamonds = 5; + + private int m_bossEarthWizardLevelReduction = 12;//11; //The amount of levels reduced from earth wizard when spawned from the blob boss. + + private bool m_isNeo = false; + + protected override void InitializeEV() + { + SetNumberOfHits(2); //3 + BlobSizeChange = new Vector2(0.725f, 0.725f); + BlobSpeedChange = 2.0f; + + #region Basic Variables - General + Name = EnemyEV.Blob_Basic_Name; + LocStringID = EnemyEV.Blob_Basic_Name_locID; + + MaxHealth = EnemyEV.Blob_Basic_MaxHealth; + Damage = EnemyEV.Blob_Basic_Damage; + XPValue = EnemyEV.Blob_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Blob_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Blob_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Blob_Basic_DropChance; + + Speed = EnemyEV.Blob_Basic_Speed; + TurnSpeed = EnemyEV.Blob_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Blob_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Blob_Basic_Jump; + CooldownTime = EnemyEV.Blob_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Blob_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Blob_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Blob_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Blob_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Blob_Basic_IsWeighted; + + Scale = EnemyEV.Blob_Basic_Scale; + ProjectileScale = EnemyEV.Blob_Basic_ProjectileScale; + //TintablePart.TextureColor = EnemyEV.Blob_Basic_Tint; + + MeleeRadius = EnemyEV.Blob_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Blob_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Blob_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Blob_Basic_KnockBack; + #endregion + + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + + SetNumberOfHits(5); //6 + BlobSizeChange = new Vector2(0.6f, 0.6f); + BlobSpeedChange = 2.0f;//2.25f; + ForceDraw = true; + #region Miniboss Variables - General + Name = EnemyEV.Blob_Miniboss_Name; + LocStringID = EnemyEV.Blob_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Blob_Miniboss_MaxHealth; + Damage = EnemyEV.Blob_Miniboss_Damage; + XPValue = EnemyEV.Blob_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Blob_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Blob_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Blob_Miniboss_DropChance; + + Speed = EnemyEV.Blob_Miniboss_Speed; + TurnSpeed = EnemyEV.Blob_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Blob_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Blob_Miniboss_Jump; + CooldownTime = EnemyEV.Blob_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Blob_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Blob_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Blob_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Blob_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Blob_Miniboss_IsWeighted; + + Scale = EnemyEV.Blob_Miniboss_Scale; + ProjectileScale = EnemyEV.Blob_Miniboss_ProjectileScale; + //TintablePart.TextureColor = EnemyEV.Blob_Miniboss_Tint; + + MeleeRadius = EnemyEV.Blob_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Blob_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Blob_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Blob_Miniboss_KnockBack; + #endregion + if (LevelEV.WEAKEN_BOSSES == true) + { + this.MaxHealth = 1; + SetNumberOfHits(1); + } + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + SetNumberOfHits(4); //5 + BlobSizeChange = new Vector2(0.65f, 0.65f); + BlobSpeedChange = 2.25f; + + #region Expert Variables - General + Name = EnemyEV.Blob_Expert_Name; + LocStringID = EnemyEV.Blob_Expert_Name_locID; + + MaxHealth = EnemyEV.Blob_Expert_MaxHealth; + Damage = EnemyEV.Blob_Expert_Damage; + XPValue = EnemyEV.Blob_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Blob_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Blob_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Blob_Expert_DropChance; + + Speed = EnemyEV.Blob_Expert_Speed; + TurnSpeed = EnemyEV.Blob_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Blob_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Blob_Expert_Jump; + CooldownTime = EnemyEV.Blob_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Blob_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Blob_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Blob_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Blob_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Blob_Expert_IsWeighted; + + Scale = EnemyEV.Blob_Expert_Scale; + ProjectileScale = EnemyEV.Blob_Expert_ProjectileScale; + //TintablePart.TextureColor = EnemyEV.Blob_Expert_Tint; + + MeleeRadius = EnemyEV.Blob_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Blob_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Blob_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Blob_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + SetNumberOfHits(3); //4; + BlobSizeChange = new Vector2(0.6f, 0.6f); + BlobSpeedChange = 2.25f; + + #region Advanced Variables - General + Name = EnemyEV.Blob_Advanced_Name; + LocStringID = EnemyEV.Blob_Advanced_Name_locID; + + MaxHealth = EnemyEV.Blob_Advanced_MaxHealth; + Damage = EnemyEV.Blob_Advanced_Damage; + XPValue = EnemyEV.Blob_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Blob_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Blob_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Blob_Advanced_DropChance; + + Speed = EnemyEV.Blob_Advanced_Speed; + TurnSpeed = EnemyEV.Blob_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Blob_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Blob_Advanced_Jump; + CooldownTime = EnemyEV.Blob_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Blob_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Blob_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Blob_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Blob_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Blob_Advanced_IsWeighted; + + Scale = EnemyEV.Blob_Advanced_Scale; + ProjectileScale = EnemyEV.Blob_Advanced_ProjectileScale; + //TintablePart.TextureColor = EnemyEV.Blob_Advanced_Tint; + + MeleeRadius = EnemyEV.Blob_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Blob_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Blob_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Blob_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + //this.Scale = new Vector2(2.4f, 2.4f); + break; + default: + break; + } + + if (this.Difficulty == GameTypes.EnemyDifficulty.BASIC) + { + _objectList[0].TextureColor = Color.Green; + _objectList[2].TextureColor = Color.LightGreen; + _objectList[2].Opacity = 0.8f; + (_objectList[1] as SpriteObj).OutlineColour = Color.Red; + _objectList[1].TextureColor = Color.Red; + } + + else if (this.Difficulty == GameTypes.EnemyDifficulty.ADVANCED) + { + _objectList[0].TextureColor = Color.Yellow; + _objectList[2].TextureColor = Color.LightYellow; + _objectList[2].Opacity = 0.8f; + (_objectList[1] as SpriteObj).OutlineColour = Color.Pink; + _objectList[1].TextureColor = Color.Pink; + } + else if (this.Difficulty == GameTypes.EnemyDifficulty.EXPERT) + { + _objectList[0].TextureColor = Color.Red; + _objectList[2].TextureColor = Color.Pink; + _objectList[2].Opacity = 0.8f; + (_objectList[1] as SpriteObj).OutlineColour = Color.Yellow; + _objectList[1].TextureColor = Color.Yellow; + } + + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + m_resetSpriteName = "EnemyBlobBossIdle_Character"; + } + + protected override void InitializeLogic() + { + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Blob_Move01", "Blob_Move02", "Blob_Move03", "Blank", "Blank", "Blank", "Blank", "Blank")); + walkTowardsLS.AddAction(new DelayLogicAction(1.10f, 1.9f)); + + LogicSet walkAwayLS = new LogicSet(this); + walkAwayLS.AddAction(new MoveLogicAction(m_target, false)); + walkAwayLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Blob_Move01", "Blob_Move02", "Blob_Move03", "Blank", "Blank", "Blank", "Blank", "Blank")); + walkAwayLS.AddAction(new DelayLogicAction(1.0f, 1.5f)); + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(0.5f,0.9f)); + + LogicSet jumpLS = new LogicSet(this); + jumpLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpLS.AddAction(new GroundCheckLogicAction()); + jumpLS.AddAction(new MoveLogicAction(m_target, true, 0)); + jumpLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobJump_Character", false, false)); + jumpLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeJump", false)); + jumpLS.AddAction(new DelayLogicAction(JumpDelay)); + jumpLS.AddAction(new MoveLogicAction(m_target, true, Speed * 6.75f)); + jumpLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Blob_Jump")); + jumpLS.AddAction(new JumpLogicAction()); + jumpLS.AddAction(new LockFaceDirectionLogicAction(true)); + jumpLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobAir_Character", true, true)); + jumpLS.AddAction(new DelayLogicAction(0.2f)); // Needs a delay before checking ground collision, otherwise it won't be off the ground before it's flagged as true. + jumpLS.AddAction(new GroundCheckLogicAction()); + jumpLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Blob_Land")); + jumpLS.AddAction(new MoveLogicAction(m_target, true, Speed)); //Reverting speed back + jumpLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobJump_Character", false, false)); + jumpLS.AddAction(new PlayAnimationLogicAction("Start", "Jump", false)); + jumpLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobIdle_Character", true, true)); + jumpLS.AddAction(new DelayLogicAction(0.2f)); + jumpLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpLS.Tag = GameTypes.LogicSetType_ATTACK; + + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "SpellDamageShield_Sprite", + SourceAnchor = new Vector2(0, 10), + //Target = m_target, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + Angle = new Vector2(0, 0), + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = ProjectileScale, + Lifespan = ExpertBlobProjectileDuration, + LockPosition = true, + }; + + LogicSet jumpAdvancedLS = new LogicSet(this); + jumpAdvancedLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpAdvancedLS.AddAction(new GroundCheckLogicAction()); + jumpAdvancedLS.AddAction(new MoveLogicAction(m_target, true, 0)); + jumpAdvancedLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobJump_Character", false, false)); + jumpAdvancedLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeJump", false)); + jumpAdvancedLS.AddAction(new DelayLogicAction(JumpDelay)); + jumpAdvancedLS.AddAction(new MoveLogicAction(m_target, true, Speed * 6.75f)); + jumpAdvancedLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Blob_Jump")); + jumpAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + jumpAdvancedLS.AddAction(new JumpLogicAction()); + jumpAdvancedLS.AddAction(new LockFaceDirectionLogicAction(true)); + jumpAdvancedLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobAir_Character", true, true)); + jumpAdvancedLS.AddAction(new DelayLogicAction(0.2f)); // Needs a delay before checking ground collision, otherwise it won't be off the ground before it's flagged as true. + jumpAdvancedLS.AddAction(new GroundCheckLogicAction()); + jumpAdvancedLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Blob_Land")); + jumpAdvancedLS.AddAction(new MoveLogicAction(m_target, true, Speed)); //Reverting speed back + jumpAdvancedLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobJump_Character", false, false)); + jumpAdvancedLS.AddAction(new PlayAnimationLogicAction("Start", "Jump", false)); + jumpAdvancedLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobIdle_Character", true, true)); + jumpAdvancedLS.AddAction(new DelayLogicAction(0.2f)); + jumpAdvancedLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpAdvancedLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet jumpExpertLS = new LogicSet(this); + jumpExpertLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpExpertLS.AddAction(new GroundCheckLogicAction()); + jumpExpertLS.AddAction(new MoveLogicAction(m_target, true, 0)); + jumpExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobJump_Character", false, false)); + jumpExpertLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeJump", false)); + jumpExpertLS.AddAction(new DelayLogicAction(JumpDelay)); + jumpExpertLS.AddAction(new MoveLogicAction(m_target, true, Speed * 6.75f)); + jumpExpertLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Blob_Jump")); + jumpExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + jumpExpertLS.AddAction(new JumpLogicAction()); + jumpExpertLS.AddAction(new LockFaceDirectionLogicAction(true)); + jumpExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobAir_Character", true, true)); + jumpExpertLS.AddAction(new DelayLogicAction(0.2f)); + jumpExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + jumpExpertLS.AddAction(new DelayLogicAction(0.2f)); + jumpExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + jumpExpertLS.AddAction(new DelayLogicAction(0.2f)); // Needs a delay before checking ground collision, otherwise it won't be off the ground before it's flagged as true. + jumpExpertLS.AddAction(new GroundCheckLogicAction()); + jumpExpertLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Blob_Land")); + jumpExpertLS.AddAction(new MoveLogicAction(m_target, true, Speed)); //Reverting speed back + jumpExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobJump_Character", false, false)); + jumpExpertLS.AddAction(new PlayAnimationLogicAction("Start", "Jump", false)); + jumpExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobIdle_Character", true, true)); + jumpExpertLS.AddAction(new DelayLogicAction(0.2f)); + jumpExpertLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpExpertLS.Tag = GameTypes.LogicSetType_ATTACK; + + ///////////////// BOSS LOGIC SETS ///////////////////////// + + LogicSet walkTowardsBossLS = new LogicSet(this); + walkTowardsBossLS.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsBossLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Blob_Move01", "Blob_Move02", "Blob_Move03", "Blank", "Blank", "Blank", "Blank", "Blank")); + walkTowardsBossLS.AddAction(new DelayLogicAction(1.10f, 1.9f)); + + LogicSet walkAwayBossLS = new LogicSet(this); + walkAwayBossLS.AddAction(new MoveLogicAction(m_target, false)); + walkAwayBossLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Blob_Move01", "Blob_Move02", "Blob_Move03", "Blank", "Blank", "Blank", "Blank", "Blank")); + walkAwayBossLS.AddAction(new DelayLogicAction(1.0f, 1.5f)); + + LogicSet walkStopBossLS = new LogicSet(this); + walkStopBossLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopBossLS.AddAction(new DelayLogicAction(0.5f, 0.9f)); + + LogicSet jumpBossLS = new LogicSet(this); + jumpBossLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpBossLS.AddAction(new GroundCheckLogicAction()); + jumpBossLS.AddAction(new MoveLogicAction(m_target, true, 0)); + jumpBossLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobBossJump_Character", false, false)); + jumpBossLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeJump", false)); + jumpBossLS.AddAction(new DelayLogicAction(JumpDelay)); + jumpBossLS.AddAction(new MoveLogicAction(m_target, true, Speed * 6.75f)); + jumpBossLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Blob_Jump")); + jumpBossLS.AddAction(new JumpLogicAction()); + jumpBossLS.AddAction(new LockFaceDirectionLogicAction(true)); + jumpBossLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobBossAir_Character", true, true)); + jumpBossLS.AddAction(new DelayLogicAction(0.2f)); // Needs a delay before checking ground collision, otherwise it won't be off the ground before it's flagged as true. + jumpBossLS.AddAction(new GroundCheckLogicAction()); + jumpBossLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Blob_Land")); + jumpBossLS.AddAction(new MoveLogicAction(m_target, true, Speed)); //Reverting speed back + jumpBossLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobBossJump_Character", false, false)); + jumpBossLS.AddAction(new PlayAnimationLogicAction("Start", "Jump", false)); + jumpBossLS.AddAction(new ChangeSpriteLogicAction("EnemyBlobBossIdle_Character", true, true)); + jumpBossLS.AddAction(new DelayLogicAction(0.2f)); + jumpBossLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpBossLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet neoChaseLB = new LogicSet(this); + neoChaseLB.AddAction(new ChangeSpriteLogicAction("EnemyBlobBossAir_Character", true, true)); + neoChaseLB.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "FairyMove1", "FairyMove2", "FairyMove3")); + neoChaseLB.AddAction(new ChaseLogicAction(m_target, true, 1.0f)); + + m_generalBasicLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, jumpLS); + m_generalAdvancedLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, jumpAdvancedLS); + m_generalExpertLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, jumpExpertLS); + m_generalCooldownLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS); + + m_generalMiniBossLB.AddLogicSet(walkTowardsBossLS, walkAwayBossLS, walkStopBossLS, jumpBossLS); + + m_generalNeoLB.AddLogicSet(neoChaseLB); + + m_generalBossCooldownLB.AddLogicSet(walkTowardsBossLS, walkAwayBossLS, walkStopBossLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + logicBlocksToDispose.Add(m_generalNeoLB); + + logicBlocksToDispose.Add(m_generalMiniBossLB); + logicBlocksToDispose.Add(m_generalBossCooldownLB); + + if (Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + { + SetCooldownLogicBlock(m_generalBossCooldownLB, 40, 40, 20); //walkTowardsLS, walkAwayLS, walkStopLS + this.ChangeSprite("EnemyBlobBossIdle_Character"); + } + else + SetCooldownLogicBlock(m_generalCooldownLB, 40, 40, 20); //walkTowardsLS, walkAwayLS, walkStopLS + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + if (m_isTouchingGround == true) + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 45, 0, 0, 55); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 10, 10, 75, 5); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS + break; + default: + break; + } + } + } + + protected override void RunAdvancedLogic() + { + if (m_isTouchingGround == true) + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 45, 0, 0, 55); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalAdvancedLB, 10, 10, 75, 5); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS + break; + default: + break; + } + } + } + + protected override void RunExpertLogic() + { + if (m_isTouchingGround == true) + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 45, 0, 0, 55); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalExpertLB, 10, 10, 75, 5); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS + break; + default: + break; + } + } + } + + protected override void RunMinibossLogic() + { + if (m_isTouchingGround) + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + if (IsNeo == false) + RunLogicBlock(true, m_generalMiniBossLB, 45, 0, 0, 55); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS + break; + default: + break; + } + } + else + { + if (IsNeo == true) + { + this.AnimationDelay = 1 / 10f; + RunLogicBlock(true, m_generalNeoLB, 100); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS + } + } + + } + + public EnemyObj_Blob(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyBlobIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + MainBlob = true; + this.TintablePart = _objectList[0]; + this.PlayAnimation(true); + m_invincibleCounter = 0.5f; // Hack to make sure newly created blobs are invincible for a short period. + this.Type = EnemyType.Blob; + } + + + public void SetNumberOfHits(int hits) + { + this.NumHits = hits; + } + + private void CreateBlob(GameTypes.EnemyDifficulty difficulty, int numHits, bool isNeo = false) + { + EnemyObj_Blob blob = new EnemyObj_Blob(null, null, null, difficulty); + blob.InitializeEV(); + blob.Position = this.Position; + if (m_target.X < blob.X) + blob.Orientation = MathHelper.ToRadians(0); + else + blob.Orientation = MathHelper.ToRadians(180); + + // Each subsequent blob gets smaller and faster. + blob.Level = this.Level; // Must be called before AddEnemyToCurrentRoom() to initialize levels properly. + m_levelScreen.AddEnemyToCurrentRoom(blob); + blob.Scale = new Vector2(ScaleX * BlobSizeChange.X, ScaleY * BlobSizeChange.Y); + blob.SetNumberOfHits(numHits); // Must be set after the call to AddEnemyToCurrentRoom because it calls Initialize(), which overrides SetNumberOfHits. + blob.Speed *= BlobSpeedChange; + blob.MainBlob = false; + blob.SavedStartingPos = blob.Position; + + blob.IsNeo = isNeo; + if (isNeo == true) + { + blob.Name = this.Name; + blob.LocStringID = this.LocStringID; + blob.IsWeighted = false; + blob.TurnSpeed = this.TurnSpeed; + blob.Speed = this.Speed * BlobSpeedChange; + blob.Level = this.Level; + blob.MaxHealth = this.MaxHealth; + blob.CurrentHealth = blob.MaxHealth; + blob.Damage = this.Damage; + blob.ChangeNeoStats(BlobSizeChange.X, BlobSpeedChange, numHits); + } + + int randXKnockback = CDGMath.RandomInt(-500, -300); + int randYKnockback = CDGMath.RandomInt(300, 700); + + if (blob.X < m_target.X) + blob.AccelerationX += -(m_target.EnemyKnockBack.X + randXKnockback); + else + blob.AccelerationX += (m_target.EnemyKnockBack.X + randXKnockback); + blob.AccelerationY += -(m_target.EnemyKnockBack.Y + randYKnockback); + + if (blob.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + { + for (int i = 0; i < this.NumChildren; i++) + { + blob.GetChildAt(i).Opacity = this.GetChildAt(i).Opacity; + blob.GetChildAt(i).TextureColor = this.GetChildAt(i).TextureColor; + } + blob.ChangeSprite("EnemyBlobBossAir_Character"); + } + else + blob.ChangeSprite("EnemyBlobAir_Character"); + blob.PlayAnimation(true); + if (LevelEV.SHOW_ENEMY_RADII == true) + blob.InitializeDebugRadii(); + blob.SaveToFile = false; + blob.SpawnRoom = m_levelScreen.CurrentRoom; + blob.GivesLichHealth = false; + + //if (this.IsPaused) + // blob.PauseEnemy(); + } + + public void CreateWizard() + { + EnemyObj_EarthWizard wizard = new EnemyObj_EarthWizard(null, null, null, GameTypes.EnemyDifficulty.ADVANCED); + + //int randomUnit = CDGMath.RandomInt(1, 3); + //if (randomUnit == 1) + // wizard = new EnemyObj_EarthWizard(null, null, null, GameTypes.EnemyDifficulty.ADVANCED); + //else if (randomUnit == 2) + // wizard = new EnemyObj_FireWizard(null, null, null, GameTypes.EnemyDifficulty.ADVANCED); + //else + // wizard = new EnemyObj_IceWizard(null, null, null, GameTypes.EnemyDifficulty.ADVANCED); + + wizard.PublicInitializeEV(); + wizard.Position = this.Position; + if (m_target.X < wizard.X) + wizard.Orientation = MathHelper.ToRadians(0); + else + wizard.Orientation = MathHelper.ToRadians(180); + + // Each subsequent blob gets smaller and faster. + wizard.Level = this.Level; // Must be called before AddEnemyToCurrentRoom() to initialize levels properly. + wizard.Level -= m_bossEarthWizardLevelReduction; + m_levelScreen.AddEnemyToCurrentRoom(wizard); + wizard.SavedStartingPos = wizard.Position; + + int randXKnockback = CDGMath.RandomInt(-500, -300); + int randYKnockback = CDGMath.RandomInt(300, 700); + + if (wizard.X < m_target.X) + wizard.AccelerationX += -(m_target.EnemyKnockBack.X + randXKnockback); + else + wizard.AccelerationX += (m_target.EnemyKnockBack.X + randXKnockback); + wizard.AccelerationY += -(m_target.EnemyKnockBack.Y + randYKnockback); + + wizard.PlayAnimation(true); + if (LevelEV.SHOW_ENEMY_RADII == true) + wizard.InitializeDebugRadii(); + wizard.SaveToFile = false; + wizard.SpawnRoom = m_levelScreen.CurrentRoom; + wizard.GivesLichHealth = false; + + //if (this.IsPaused) + // wizard.PauseEnemy(); + } + + //public override void Update(GameTime gameTime) + //{ + // foreach (GameObj obj in m_levelScreen.CurrentRoom.ObjectList) + // { + // EnemyObj_Blob blob = obj as EnemyObj_Blob; + // if (blob != null && blob != this) + // { + // float distanceFromOtherEnemy = Vector2.Distance(this.Position, blob.Position); + // if (distanceFromOtherEnemy < this.SeparationDistance) + // { + // Vector2 seekPosition = 2 * this.Position - blob.Position; + // CDGMath.TurnToFace(this, seekPosition); + // } + // } + // } + + // base.Update(gameTime); + //} + + public override void Update(GameTime gameTime) + { + // Maintains the enemy's speed in the air so that he can jump onto platforms. + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + { + if (m_isTouchingGround == false && IsWeighted == true && CurrentSpeed == 0 && this.SpriteName == "EnemyBlobBossAir_Character") + this.CurrentSpeed = this.Speed; + + if (m_currentActiveLB.IsActive == false && m_isTouchingGround == true && SpriteName != "EnemyBlobBossIdle_Character") + { + this.ChangeSprite("EnemyBlobBossIdle_Character"); + this.PlayAnimation(true); + } + } + else + { + if (m_isTouchingGround == false && IsWeighted == true && CurrentSpeed == 0 && this.SpriteName == "EnemyBlobAir_Character") + this.CurrentSpeed = this.Speed; + + if (m_currentActiveLB.IsActive == false && m_isTouchingGround == true && SpriteName != "EnemyBlobIdle_Character") + { + this.ChangeSprite("EnemyBlobIdle_Character"); + this.PlayAnimation(true); + } + } + + if (IsNeo == true) // Anti-flocking logic. + { + foreach (EnemyObj enemy in m_levelScreen.CurrentRoom.EnemyList) + { + if (enemy != this && enemy is EnemyObj_Blob) + { + float distanceFromOtherEnemy = Vector2.Distance(this.Position, enemy.Position); + if (distanceFromOtherEnemy < 150) + { + Vector2 seekPosition = 2 * this.Position - enemy.Position; + CDGMath.TurnToFace(this, seekPosition); + } + } + } + + foreach (EnemyObj enemy in m_levelScreen.CurrentRoom.TempEnemyList) + { + if (enemy != this && enemy is EnemyObj_Blob) + { + float distanceFromOtherEnemy = Vector2.Distance(this.Position, enemy.Position); + if (distanceFromOtherEnemy < 150) + { + Vector2 seekPosition = 2 * this.Position - enemy.Position; + CDGMath.TurnToFace(this, seekPosition); + } + } + } + } + + base.Update(gameTime); + } + + public override void HitEnemy(int damage, Vector2 position, bool isPlayer = true) + { + if (m_target != null && m_target.CurrentHealth > 0) + { + if (m_bossVersionKilled == false) + { + base.HitEnemy(damage, position, isPlayer); + + if (CurrentHealth <= 0) + { + CurrentHealth = MaxHealth; + NumHits--; + + if (IsKilled == false && NumHits > 0) + { + if (IsNeo == false) + { + if (m_flipTween != null && m_flipTween.TweenedObject == this && m_flipTween.Active == true) + m_flipTween.StopTween(false); + this.ScaleX = this.ScaleY; // This is to fix splitting a blob when it's stereoblind flipping. + + CreateBlob(this.Difficulty, NumHits); + this.Scale = new Vector2(ScaleX * BlobSizeChange.X, ScaleY * BlobSizeChange.Y); + this.Speed *= BlobSpeedChange; + + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + CreateWizard(); + } + else + { + if (m_flipTween != null && m_flipTween.TweenedObject == this && m_flipTween.Active == true) + m_flipTween.StopTween(false); + this.ScaleX = this.ScaleY; // This is to fix splitting a blob when it's stereoblind flipping. + + CreateBlob(this.Difficulty, NumHits, true); + this.Scale = new Vector2(ScaleX * BlobSizeChange.X, ScaleY * BlobSizeChange.Y); + this.Speed *= BlobSpeedChange; + } + } + } + + if (NumHits <= 0) + Kill(true); + } + } + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + // Hits the player in Tanooki mode. + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS && m_bossVersionKilled == false) + { + PlayerObj player = otherBox.AbsParent as PlayerObj; + if (player != null && otherBox.Type == Consts.WEAPON_HITBOX && player.IsInvincible == false && player.State == PlayerObj.STATE_TANOOKI) + player.HitPlayer(this); + } + + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + public override void Kill(bool giveXP = true) + { + if (Difficulty != GameTypes.EnemyDifficulty.MINIBOSS) + base.Kill(giveXP); + else + { + if (m_target.CurrentHealth > 0) + { + BlobBossRoom bossRoom = m_levelScreen.CurrentRoom as BlobBossRoom; + BlobChallengeRoom challengeRoom = m_levelScreen.CurrentRoom as BlobChallengeRoom; + + if (((bossRoom != null && bossRoom.NumActiveBlobs == 1) || (challengeRoom != null && challengeRoom.NumActiveBlobs == 1)) && m_bossVersionKilled == false) + { + Game.PlayerStats.BlobBossBeaten = true; + + SoundManager.StopMusic(0); + //SoundManager.Play3DSound(this, Game.ScreenManager.Player,"PressStart"); + m_bossVersionKilled = true; + m_target.LockControls(); + m_levelScreen.PauseScreen(); + m_levelScreen.ProjectileManager.DestroyAllProjectiles(false); + m_levelScreen.RunWhiteSlashEffect(); + Tween.RunFunction(1f, this, "Part2"); + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "Boss_Flash"); + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "Boss_Eyeball_Freeze"); + + GameUtil.UnlockAchievement("FEAR_OF_SLIME"); + + if (IsNeo == true) + { + Tween.To(m_target.AttachedLevel.Camera, 0.5f, Tweener.Ease.Quad.EaseInOut, "Zoom", "1", "X", m_target.X.ToString(), "Y", m_target.Y.ToString()); + Tween.AddEndHandlerToLastTween(this, "LockCamera"); + } + } + else + base.Kill(giveXP); + } + } + } + + public void LockCamera() + { + m_target.AttachedLevel.CameraLockedToPlayer = true; + } + + public void Part2() + { + m_levelScreen.UnpauseScreen(); + m_target.UnlockControls(); + + if (m_currentActiveLB != null) + m_currentActiveLB.StopLogicBlock(); + + m_target.CurrentSpeed = 0; + m_target.ForceInvincible = true; + + foreach (EnemyObj enemy in m_levelScreen.CurrentRoom.TempEnemyList) + { + if (enemy.IsKilled == false) + enemy.Kill(true); + } + + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Boss_Blob_Death"); + + base.Kill(true); + + if (IsNeo == false) + { + int totalGold = m_bossCoins + m_bossMoneyBags + m_bossDiamonds; + List goldArray = new List(); + + for (int i = 0; i < m_bossCoins; i++) + goldArray.Add(0); + for (int i = 0; i < m_bossMoneyBags; i++) + goldArray.Add(1); + for (int i = 0; i < m_bossDiamonds; i++) + goldArray.Add(2); + + CDGMath.Shuffle(goldArray); + float coinDelay = 0;// 2.5f / goldArray.Count; // The enemy dies for 2.5 seconds. + + for (int i = 0; i < goldArray.Count; i++) + { + Vector2 goldPos = this.Position; + if (goldArray[i] == 0) + Tween.RunFunction(i * coinDelay, m_levelScreen.ItemDropManager, "DropItemWide", goldPos, ItemDropType.Coin, ItemDropType.CoinAmount); + else if (goldArray[i] == 1) + Tween.RunFunction(i * coinDelay, m_levelScreen.ItemDropManager, "DropItemWide", goldPos, ItemDropType.MoneyBag, ItemDropType.MoneyBagAmount); + else + Tween.RunFunction(i * coinDelay, m_levelScreen.ItemDropManager, "DropItemWide", goldPos, ItemDropType.Diamond, ItemDropType.DiamondAmount); + } + } + } + + public override void Reset() + { + if (MainBlob == false) + { + //m_levelScreen.RemoveEnemyFromCurrentRoom(this, this.SavedStartingPos); + m_levelScreen.RemoveEnemyFromRoom(this, SpawnRoom, this.SavedStartingPos); + this.Dispose(); + } + else + { + //this.Scale = new Vector2(1, 1); + switch (this.Difficulty) + { + case (GameTypes.EnemyDifficulty.BASIC): + this.Speed = EnemyEV.Blob_Basic_Speed; // Should not be hardcoded. + this.Scale = EnemyEV.Blob_Basic_Scale; + this.NumHits = 2; + break; + case (GameTypes.EnemyDifficulty.ADVANCED): + this.Speed = EnemyEV.Blob_Advanced_Speed; // Should not be hardcoded. + this.Scale = EnemyEV.Blob_Advanced_Scale; + this.NumHits = 3; + break; + case (GameTypes.EnemyDifficulty.EXPERT): + this.Speed = EnemyEV.Blob_Expert_Speed; // Should not be hardcoded. + this.Scale = EnemyEV.Blob_Expert_Scale; + this.NumHits = 4; + break; + case (GameTypes.EnemyDifficulty.MINIBOSS): + this.Speed = EnemyEV.Blob_Miniboss_Speed; // Should not be hardcoded. + this.NumHits = 6; + break; + } + base.Reset(); + } + } + + public override void Dispose() + { + if (this.IsDisposed == false) + { + // Done + SpawnRoom = null; + base.Dispose(); + } + } + + public void ChangeNeoStats(float blobSizeChange, float blobSpeedChange, int numHits) + { + NumHits = numHits; + BlobSizeChange = new Vector2(blobSizeChange, blobSizeChange); + BlobSpeedChange = blobSpeedChange; + } + + public bool IsNeo + { + get { return m_isNeo; } + set + { + m_isNeo = value; + if (value == true) + { + HealthGainPerLevel = 0; + DamageGainPerLevel = 0; + MoneyDropChance = 0; + ItemDropChance = 0; + m_saveToEnemiesKilledList = false; + } + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_BouncySpike.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_BouncySpike.cs new file mode 100644 index 0000000..932e220 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_BouncySpike.cs @@ -0,0 +1,363 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_BouncySpike : EnemyObj + { + private float RotationSpeed = 250;//600; + private float m_internalOrientation; + + public Vector2 SavedStartingPos { get; set; } + public RoomObj SpawnRoom; + + private float m_selfDestructTimer = 0.7f;//1; + private int m_selfDestructCounter = 0; + private int m_selfDestructTotalBounces = 12;//14;//11;//7; //Total bounce needed in 1 second to destroy a spike. + + protected override void InitializeEV() + { + //this.Orientation = CDGMath.RandomInt(-180, 180); + int randomizer = CDGMath.RandomInt(0,11); + if (randomizer >= 9) + this.Orientation = 0; + else if (randomizer >= 6) + this.Orientation = 180; + else if (randomizer >= 4) + this.Orientation = 90; + else if (randomizer >= 1) + this.Orientation = 270; + else + this.Orientation = 45; + + m_internalOrientation = this.Orientation; + + this.HeadingX = (float)Math.Cos(MathHelper.ToRadians(this.Orientation)); + this.HeadingY = (float)Math.Sin(MathHelper.ToRadians(this.Orientation)); + + #region Basic Variables - General + Name = EnemyEV.BouncySpike_Basic_Name; + LocStringID = EnemyEV.BouncySpike_Basic_Name_locID; + + MaxHealth = EnemyEV.BouncySpike_Basic_MaxHealth; + Damage = EnemyEV.BouncySpike_Basic_Damage; + XPValue = EnemyEV.BouncySpike_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.BouncySpike_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.BouncySpike_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.BouncySpike_Basic_DropChance; + + Speed = EnemyEV.BouncySpike_Basic_Speed; + TurnSpeed = EnemyEV.BouncySpike_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.BouncySpike_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.BouncySpike_Basic_Jump; + CooldownTime = EnemyEV.BouncySpike_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.BouncySpike_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.BouncySpike_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.BouncySpike_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.BouncySpike_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.BouncySpike_Basic_IsWeighted; + + Scale = EnemyEV.BouncySpike_Basic_Scale; + ProjectileScale = EnemyEV.BouncySpike_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.BouncySpike_Basic_Tint; + + MeleeRadius = EnemyEV.BouncySpike_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.BouncySpike_Basic_ProjectileRadius; + EngageRadius = EnemyEV.BouncySpike_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = new Vector2(1, 2); + LockFlip = true; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.BouncySpike_Miniboss_Name; + LocStringID = EnemyEV.BouncySpike_Miniboss_Name_locID; + + MaxHealth = EnemyEV.BouncySpike_Miniboss_MaxHealth; + Damage = EnemyEV.BouncySpike_Miniboss_Damage; + XPValue = EnemyEV.BouncySpike_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.BouncySpike_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.BouncySpike_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.BouncySpike_Miniboss_DropChance; + + Speed = EnemyEV.BouncySpike_Miniboss_Speed; + TurnSpeed = EnemyEV.BouncySpike_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.BouncySpike_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.BouncySpike_Miniboss_Jump; + CooldownTime = EnemyEV.BouncySpike_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.BouncySpike_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.BouncySpike_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.BouncySpike_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.BouncySpike_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.BouncySpike_Miniboss_IsWeighted; + + Scale = EnemyEV.BouncySpike_Miniboss_Scale; + ProjectileScale = EnemyEV.BouncySpike_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.BouncySpike_Miniboss_Tint; + + MeleeRadius = EnemyEV.BouncySpike_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.BouncySpike_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.BouncySpike_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = new Vector2(1, 2); + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.BouncySpike_Expert_Name; + LocStringID = EnemyEV.BouncySpike_Expert_Name_locID; + + MaxHealth = EnemyEV.BouncySpike_Expert_MaxHealth; + Damage = EnemyEV.BouncySpike_Expert_Damage; + XPValue = EnemyEV.BouncySpike_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.BouncySpike_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.BouncySpike_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.BouncySpike_Expert_DropChance; + + Speed = EnemyEV.BouncySpike_Expert_Speed; + TurnSpeed = EnemyEV.BouncySpike_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.BouncySpike_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.BouncySpike_Expert_Jump; + CooldownTime = EnemyEV.BouncySpike_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.BouncySpike_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.BouncySpike_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.BouncySpike_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.BouncySpike_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.BouncySpike_Expert_IsWeighted; + + Scale = EnemyEV.BouncySpike_Expert_Scale; + ProjectileScale = EnemyEV.BouncySpike_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.BouncySpike_Expert_Tint; + + MeleeRadius = EnemyEV.BouncySpike_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.BouncySpike_Expert_ProjectileRadius; + EngageRadius = EnemyEV.BouncySpike_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = new Vector2(1, 2); + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.BouncySpike_Advanced_Name; + LocStringID = EnemyEV.BouncySpike_Advanced_Name_locID; + + MaxHealth = EnemyEV.BouncySpike_Advanced_MaxHealth; + Damage = EnemyEV.BouncySpike_Advanced_Damage; + XPValue = EnemyEV.BouncySpike_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.BouncySpike_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.BouncySpike_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.BouncySpike_Advanced_DropChance; + + Speed = EnemyEV.BouncySpike_Advanced_Speed; + TurnSpeed = EnemyEV.BouncySpike_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.BouncySpike_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.BouncySpike_Advanced_Jump; + CooldownTime = EnemyEV.BouncySpike_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.BouncySpike_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.BouncySpike_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.BouncySpike_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.BouncySpike_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.BouncySpike_Advanced_IsWeighted; + + Scale = EnemyEV.BouncySpike_Advanced_Scale; + ProjectileScale = EnemyEV.BouncySpike_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.BouncySpike_Advanced_Tint; + + MeleeRadius = EnemyEV.BouncySpike_Advanced_MeleeRadius; + EngageRadius = EnemyEV.BouncySpike_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.BouncySpike_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = new Vector2(1, 2); + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + public override void Update(GameTime gameTime) + { + if (IsPaused == false) + { + float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds; + + // Checking for boundary bounces. + Vector2 boundaryMTD = Vector2.Zero; + Rectangle roomBounds = m_levelScreen.CurrentRoom.Bounds; + + if (this.Y < roomBounds.Top + 10) + boundaryMTD = CollisionMath.CalculateMTD(this.Bounds, new Rectangle(roomBounds.Left, roomBounds.Top, roomBounds.Width, 10)); + else if (this.Y > roomBounds.Bottom - 10) + boundaryMTD = CollisionMath.CalculateMTD(this.Bounds, new Rectangle(roomBounds.Left, roomBounds.Bottom - 10, roomBounds.Width, 10)); + + if (this.X > roomBounds.Right - 10) + boundaryMTD = CollisionMath.CalculateMTD(this.Bounds, new Rectangle(roomBounds.Right - 10, roomBounds.Top, 10, roomBounds.Height)); + else if (this.X < roomBounds.Left + 10) + boundaryMTD = CollisionMath.CalculateMTD(this.Bounds, new Rectangle(roomBounds.Left, roomBounds.Top, 10, roomBounds.Height)); + + if (boundaryMTD != Vector2.Zero) + { + Vector2 v = Heading; + Vector2 l = new Vector2(boundaryMTD.Y, boundaryMTD.X * -1); // The angle of the side the vector hit is the normal to the MTD. + Vector2 newHeading = ((2 * (CDGMath.DotProduct(v, l) / CDGMath.DotProduct(l, l)) * l) - v); + this.Heading = newHeading; + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "GiantSpike_Bounce_01", "GiantSpike_Bounce_02", "GiantSpike_Bounce_03"); + m_selfDestructCounter++; + m_selfDestructTimer = 1; + } + + if (m_selfDestructTimer > 0) + { + m_selfDestructTimer -= elapsedTime; + if (m_selfDestructTimer <= 0) + m_selfDestructCounter = 0; + } + + if (m_selfDestructCounter >= m_selfDestructTotalBounces) + this.Kill(false); + + if (CurrentSpeed == 0) + CurrentSpeed = Speed; + + if (this.HeadingX > 0) + this.Rotation += RotationSpeed * elapsedTime; + else + this.Rotation -= RotationSpeed * elapsedTime; + } + base.Update(gameTime); + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + TerrainObj terrain = otherBox.Parent as TerrainObj; + + if (terrain != null && (terrain is DoorObj) == false) + { + if (terrain.CollidesBottom == true && terrain.CollidesLeft == true && terrain.CollidesRight == true && terrain.CollidesTop == true) + { + Vector2 mtd = CollisionMath.RotatedRectIntersectsMTD(thisBox.AbsRect, (int)thisBox.AbsRotation, Vector2.Zero, otherBox.AbsRect, (int)otherBox.AbsRotation, Vector2.Zero); + if (mtd != Vector2.Zero) + { + Vector2 v = Heading; + Vector2 l = new Vector2(mtd.Y, mtd.X * -1); // The angle of the side the vector hit is the normal to the MTD. + Vector2 newHeading = ((2 * (CDGMath.DotProduct(v, l) / CDGMath.DotProduct(l, l)) * l) - v); + this.X += mtd.X; + this.Y += mtd.Y; + this.Heading = newHeading; + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"GiantSpike_Bounce_01", "GiantSpike_Bounce_02", "GiantSpike_Bounce_03"); + m_selfDestructCounter++; + m_selfDestructTimer = 1; + } + } + } + } + + public override void Reset() + { + if (SpawnRoom != null) + { + m_levelScreen.RemoveEnemyFromRoom(this, SpawnRoom, this.SavedStartingPos); + this.Dispose(); + } + else + { + this.Orientation = m_internalOrientation; + base.Reset(); + } + } + + public EnemyObj_BouncySpike(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyBouncySpike_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.BouncySpike; + NonKillable = true; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + SpawnRoom = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Chicken.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Chicken.cs new file mode 100644 index 0000000..afc593b --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Chicken.cs @@ -0,0 +1,284 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_Chicken : EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + + protected override void InitializeEV() + { + this.LockFlip = true; + + #region Basic Variables - General + Name = EnemyEV.Chicken_Basic_Name; + LocStringID = EnemyEV.Chicken_Basic_Name_locID; + + MaxHealth = EnemyEV.Chicken_Basic_MaxHealth; + Damage = EnemyEV.Chicken_Basic_Damage; + XPValue = EnemyEV.Chicken_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Chicken_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Chicken_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Chicken_Basic_DropChance; + + Speed = EnemyEV.Chicken_Basic_Speed; + TurnSpeed = EnemyEV.Chicken_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Chicken_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Chicken_Basic_Jump; + CooldownTime = EnemyEV.Chicken_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Chicken_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Chicken_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Chicken_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Chicken_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Chicken_Basic_IsWeighted; + + Scale = EnemyEV.Chicken_Basic_Scale; + ProjectileScale = EnemyEV.Chicken_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Chicken_Basic_Tint; + + MeleeRadius = EnemyEV.Chicken_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Chicken_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Chicken_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Chicken_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Chicken_Miniboss_Name; + LocStringID = EnemyEV.Chicken_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Chicken_Miniboss_MaxHealth; + Damage = EnemyEV.Chicken_Miniboss_Damage; + XPValue = EnemyEV.Chicken_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Chicken_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Chicken_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Chicken_Miniboss_DropChance; + + Speed = EnemyEV.Chicken_Miniboss_Speed; + TurnSpeed = EnemyEV.Chicken_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Chicken_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Chicken_Miniboss_Jump; + CooldownTime = EnemyEV.Chicken_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Chicken_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Chicken_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Chicken_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Chicken_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Chicken_Miniboss_IsWeighted; + + Scale = EnemyEV.Chicken_Miniboss_Scale; + ProjectileScale = EnemyEV.Chicken_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Chicken_Miniboss_Tint; + + MeleeRadius = EnemyEV.Chicken_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Chicken_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Chicken_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Chicken_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.Chicken_Expert_Name; + LocStringID = EnemyEV.Chicken_Expert_Name_locID; + + MaxHealth = EnemyEV.Chicken_Expert_MaxHealth; + Damage = EnemyEV.Chicken_Expert_Damage; + XPValue = EnemyEV.Chicken_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Chicken_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Chicken_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Chicken_Expert_DropChance; + + Speed = EnemyEV.Chicken_Expert_Speed; + TurnSpeed = EnemyEV.Chicken_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Chicken_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Chicken_Expert_Jump; + CooldownTime = EnemyEV.Chicken_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Chicken_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Chicken_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Chicken_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Chicken_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Chicken_Expert_IsWeighted; + + Scale = EnemyEV.Chicken_Expert_Scale; + ProjectileScale = EnemyEV.Chicken_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Chicken_Expert_Tint; + + MeleeRadius = EnemyEV.Chicken_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Chicken_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Chicken_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Chicken_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.Chicken_Advanced_Name; + LocStringID = EnemyEV.Chicken_Advanced_Name_locID; + + MaxHealth = EnemyEV.Chicken_Advanced_MaxHealth; + Damage = EnemyEV.Chicken_Advanced_Damage; + XPValue = EnemyEV.Chicken_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Chicken_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Chicken_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Chicken_Advanced_DropChance; + + Speed = EnemyEV.Chicken_Advanced_Speed; + TurnSpeed = EnemyEV.Chicken_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Chicken_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Chicken_Advanced_Jump; + CooldownTime = EnemyEV.Chicken_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Chicken_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Chicken_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Chicken_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Chicken_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Chicken_Advanced_IsWeighted; + + Scale = EnemyEV.Chicken_Advanced_Scale; + ProjectileScale = EnemyEV.Chicken_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Chicken_Advanced_Tint; + + MeleeRadius = EnemyEV.Chicken_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Chicken_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Chicken_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Chicken_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + this.Scale = new Vector2(2, 2); + break; + } + + IsWeighted = true; + } + + protected override void InitializeLogic() + { + LogicSet walkLeftLS = new LogicSet(this); + walkLeftLS.AddAction(new ChangeSpriteLogicAction("EnemyChickenRun_Character", true, true)); + walkLeftLS.AddAction(new ChangePropertyLogicAction(this, "Flip", Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally)); + walkLeftLS.AddAction(new MoveDirectionLogicAction()); + walkLeftLS.AddAction(new DelayLogicAction(0.5f, 1.0f)); + + LogicSet walkRightLS = new LogicSet(this); + walkRightLS.AddAction(new ChangeSpriteLogicAction("EnemyChickenRun_Character", true, true)); + walkRightLS.AddAction(new ChangePropertyLogicAction(this, "Flip", Microsoft.Xna.Framework.Graphics.SpriteEffects.None)); + walkRightLS.AddAction(new MoveDirectionLogicAction()); + walkRightLS.AddAction(new DelayLogicAction(0.5f, 1.0f)); + + m_generalBasicLB.AddLogicSet(walkLeftLS, walkRightLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + RunLogicBlock(true, m_generalBasicLB, 50, 50); + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + RunLogicBlock(true, m_generalBasicLB, 50, 50); + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + RunLogicBlock(true, m_generalBasicLB, 50, 50); + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + RunLogicBlock(true, m_generalBasicLB, 50, 50); + break; + } + } + + public void MakeCollideable() + { + this.IsCollidable = true; + } + + public override void Update(GameTime gameTime) + { + if (m_levelScreen != null && m_levelScreen.CurrentRoom != null) + { + if (this.IsKilled == false && CollisionMath.Intersects(this.TerrainBounds, this.m_levelScreen.CurrentRoom.Bounds) == false) + this.Kill(true); + } + + base.Update(gameTime); + } + + public EnemyObj_Chicken(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyChickenRun_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.Chicken; + } + + public override void HitEnemy(int damage, Vector2 collisionPt, bool isPlayer) + { + SoundManager.Play3DSound(this, m_target, "Chicken_Cluck_01", "Chicken_Cluck_02", "Chicken_Cluck_03"); + base.HitEnemy(damage, collisionPt, isPlayer); + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Dummy.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Dummy.cs new file mode 100644 index 0000000..186bdfc --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Dummy.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; + +namespace RogueCastle +{ + public class EnemyObj_Dummy: EnemyObj + { + protected override void InitializeEV() + { + Scale = new Vector2(2.2f, 2.2f); + AnimationDelay = 1 / 60f; + Speed = 200.0f; + MaxHealth = 999; + EngageRadius = 30; + ProjectileRadius = 20; + MeleeRadius = 10; + CooldownTime = 2.0f; + KnockBack = new Vector2(1, 2); + Damage = 25; + JumpHeight = 20.5f; + AlwaysFaceTarget = false; + CanFallOffLedges = false; + XPValue = 2; + CanBeKnockedBack = false; + this.Name = "Training Dummy"; + this.LocStringID = "LOC_ID_TRAINING_DUMMY_1"; + + this.IsWeighted = false; + this.LockFlip = true; + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + case (GameTypes.EnemyDifficulty.EXPERT): + case (GameTypes.EnemyDifficulty.ADVANCED): + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + } + + public override void HitEnemy(int damage, Vector2 collisionPt, bool isPlayer) + { + if (m_target != null && m_target.CurrentHealth > 0) + { + this.ChangeSprite("DummySad_Character"); + this.PlayAnimation(false); + + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "EnemyHit1", "EnemyHit2", "EnemyHit3", "EnemyHit4", "EnemyHit5", "EnemyHit6"); + Blink(Color.Red, 0.1f); + this.m_levelScreen.ImpactEffectPool.DisplayEnemyImpactEffect(collisionPt); + this.m_levelScreen.ImpactEffectPool.WoodChipEffect(new Vector2(this.X, this.Bounds.Center.Y)); + + if (isPlayer == true) // Only perform these checks if the object hitting the enemy is the player. + { + m_target.NumSequentialAttacks++; + + if (m_target.IsAirAttacking == true) + { + m_target.IsAirAttacking = false; // Only allow one object to perform upwards air knockback on the player. + m_target.AccelerationY = -m_target.AirAttackKnockBack; + m_target.NumAirBounces++; + } + } + + m_levelScreen.TextManager.DisplayNumberText(damage, Color.Red, new Vector2(this.X, this.Bounds.Top)); + m_levelScreen.SetLastEnemyHit(this); + RandomizeName(); + } + } + + private void RandomizeName() + { + string[] nameIDs = new string[] + { + "LOC_ID_TRAINING_DUMMY_2", + "LOC_ID_TRAINING_DUMMY_3", + "LOC_ID_TRAINING_DUMMY_4", + "LOC_ID_TRAINING_DUMMY_5", + "LOC_ID_TRAINING_DUMMY_1", + "LOC_ID_TRAINING_DUMMY_6", + "LOC_ID_TRAINING_DUMMY_7", + "LOC_ID_TRAINING_DUMMY_8", + "LOC_ID_TRAINING_DUMMY_9", + "LOC_ID_TRAINING_DUMMY_10", + "LOC_ID_TRAINING_DUMMY_11", + "LOC_ID_TRAINING_DUMMY_12", + "LOC_ID_TRAINING_DUMMY_13", + "LOC_ID_TRAINING_DUMMY_14", + "LOC_ID_TRAINING_DUMMY_15", + "LOC_ID_TRAINING_DUMMY_16", + "LOC_ID_TRAINING_DUMMY_17", + "LOC_ID_TRAINING_DUMMY_18", + "LOC_ID_TRAINING_DUMMY_19", + "LOC_ID_TRAINING_DUMMY_20", + "LOC_ID_TRAINING_DUMMY_21", + "LOC_ID_TRAINING_DUMMY_22" + }; + this.Name = "";// names[CDGMath.RandomInt(0, names.Length - 1)]; + this.LocStringID = nameIDs[CDGMath.RandomInt(0, nameIDs.Length - 1)]; + } + + public EnemyObj_Dummy(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("Dummy_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.Dummy; + //NonKillable = true; + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Eagle.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Eagle.cs new file mode 100644 index 0000000..57f17a5 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Eagle.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_Eagle: EnemyObj + { + private bool m_flyingLeft = false; + private LogicBlock m_basicAttackLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + + + protected override void InitializeEV() + { + MaxHealth = 10; + Damage = 10; + XPValue = 5; + + HealthGainPerLevel = 2; + DamageGainPerLevel = 2; + XPBonusPerLevel = 1; + + this.IsWeighted = false; + Speed = 6f; + EngageRadius = 1900; + ProjectileRadius = 1600; + MeleeRadius = 650; + CooldownTime = 2.0f; + CanBeKnockedBack = false; + JumpHeight = 20.5f; + CanFallOffLedges = true; + TurnSpeed = 0.0175f; //0.02f; + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + case (GameTypes.EnemyDifficulty.EXPERT): + case (GameTypes.EnemyDifficulty.ADVANCED): + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + } + protected override void InitializeLogic() + { + LogicSet basicFlyRight = new LogicSet(this); + basicFlyRight.AddAction(new MoveDirectionLogicAction(new Vector2(1, 0))); + basicFlyRight.AddAction(new DelayLogicAction(1)); + + LogicSet basicFlyLeft = new LogicSet(this); + basicFlyLeft.AddAction(new MoveDirectionLogicAction(new Vector2(-1,0))); + basicFlyLeft.AddAction(new DelayLogicAction(1)); + + m_basicAttackLB.AddLogicSet(basicFlyLeft, basicFlyRight); + + logicBlocksToDispose.Add(m_basicAttackLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + if (m_flyingLeft == true) + RunLogicBlock(false, m_basicAttackLB, 100, 0); + else + RunLogicBlock(false, m_basicAttackLB, 0, 100); + + if (this.X > m_levelScreen.CurrentRoom.Bounds.Right) + { + this.Y = m_levelScreen.CurrentRoom.Y + CDGMath.RandomInt(100, m_levelScreen.CurrentRoom.Height - 100); + m_flyingLeft = true; + } + else if (this.X < m_levelScreen.CurrentRoom.Bounds.Left) + { + this.Y = m_levelScreen.CurrentRoom.Y + CDGMath.RandomInt(100, m_levelScreen.CurrentRoom.Height - 100); + m_flyingLeft = false; + } + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + public override void Update(GameTime gameTime) + { + if (IsAnimating == false) + PlayAnimation(true); + base.Update(gameTime); + } + + public EnemyObj_Eagle(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("Dummy_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.Eagle; + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_EarthWizard.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_EarthWizard.cs new file mode 100644 index 0000000..84f06e1 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_EarthWizard.cs @@ -0,0 +1,872 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_EarthWizard : EnemyObj + { + + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + + private float SpellDelay = 0.3f; + private float SpellDuration = 0.75f; + private int SpellIceProjectileCount = 24;//21; + + private float SpellFireDelay = 1.5f; + private float SpellFireInterval = 0.2f; + + private Vector2 MiniBossFireballSize = new Vector2(2.0f, 2.0f); + private Vector2 MiniBossIceSize = new Vector2(1.5f, 1.5f); + + private ProjectileObj m_fireballSummon; + private ProjectileObj m_iceballSummon; + + private SpriteObj m_earthSummonInSprite; + private SpriteObj m_earthSummonOutSprite; + private ProjectileObj m_earthProjectileObj; + + public Vector2 SavedStartingPos { get; set; } + public RoomObj SpawnRoom; + + private Vector2 m_spellOffset = new Vector2(40, -80); + + private float TeleportDelay = 0.5f; + private float TeleportDuration = 1.0f; + + private float MoveDuration = 1.0f; + private float m_earthParticleEffectCounter = 0.5f; + private int m_effectCycle = 0; + + protected override void InitializeEV() + { + #region Basic Variables - General + Name = EnemyEV.EarthWizard_Basic_Name; + LocStringID = EnemyEV.EarthWizard_Basic_Name_locID; + + MaxHealth = EnemyEV.EarthWizard_Basic_MaxHealth; + Damage = EnemyEV.EarthWizard_Basic_Damage; + XPValue = EnemyEV.EarthWizard_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.EarthWizard_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.EarthWizard_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.EarthWizard_Basic_DropChance; + + Speed = EnemyEV.EarthWizard_Basic_Speed; + TurnSpeed = EnemyEV.EarthWizard_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.EarthWizard_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.EarthWizard_Basic_Jump; + CooldownTime = EnemyEV.EarthWizard_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.EarthWizard_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.EarthWizard_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.EarthWizard_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.EarthWizard_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.EarthWizard_Basic_IsWeighted; + + Scale = EnemyEV.EarthWizard_Basic_Scale; + ProjectileScale = EnemyEV.EarthWizard_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.EarthWizard_Basic_Tint; + + MeleeRadius = EnemyEV.EarthWizard_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.EarthWizard_Basic_ProjectileRadius; + EngageRadius = EnemyEV.EarthWizard_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.EarthWizard_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + SpellDelay = 0.85f; + SpellDuration = 2.0f; + m_spellOffset = new Vector2(40, -140); + #region Miniboss Variables - General + Name = EnemyEV.EarthWizard_Miniboss_Name; + LocStringID = EnemyEV.EarthWizard_Miniboss_Name_locID; + + MaxHealth = EnemyEV.EarthWizard_Miniboss_MaxHealth; + Damage = EnemyEV.EarthWizard_Miniboss_Damage; + XPValue = EnemyEV.EarthWizard_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.EarthWizard_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.EarthWizard_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.EarthWizard_Miniboss_DropChance; + + Speed = EnemyEV.EarthWizard_Miniboss_Speed; + TurnSpeed = EnemyEV.EarthWizard_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.EarthWizard_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.EarthWizard_Miniboss_Jump; + CooldownTime = EnemyEV.EarthWizard_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.EarthWizard_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.EarthWizard_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.EarthWizard_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.EarthWizard_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.EarthWizard_Miniboss_IsWeighted; + + Scale = EnemyEV.EarthWizard_Miniboss_Scale; + ProjectileScale = EnemyEV.EarthWizard_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.EarthWizard_Miniboss_Tint; + + MeleeRadius = EnemyEV.EarthWizard_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.EarthWizard_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.EarthWizard_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.EarthWizard_Miniboss_KnockBack; + #endregion + break; + + + case (GameTypes.EnemyDifficulty.EXPERT): + SpellDelay = 0.7f; + SpellDuration = 3.5f; + #region Expert Variables - General + Name = EnemyEV.EarthWizard_Expert_Name; + LocStringID = EnemyEV.EarthWizard_Expert_Name_locID; + + MaxHealth = EnemyEV.EarthWizard_Expert_MaxHealth; + Damage = EnemyEV.EarthWizard_Expert_Damage; + XPValue = EnemyEV.EarthWizard_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.EarthWizard_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.EarthWizard_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.EarthWizard_Expert_DropChance; + + Speed = EnemyEV.EarthWizard_Expert_Speed; + TurnSpeed = EnemyEV.EarthWizard_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.EarthWizard_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.EarthWizard_Expert_Jump; + CooldownTime = EnemyEV.EarthWizard_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.EarthWizard_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.EarthWizard_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.EarthWizard_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.EarthWizard_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.EarthWizard_Expert_IsWeighted; + + Scale = EnemyEV.EarthWizard_Expert_Scale; + ProjectileScale = EnemyEV.EarthWizard_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.EarthWizard_Expert_Tint; + + MeleeRadius = EnemyEV.EarthWizard_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.EarthWizard_Expert_ProjectileRadius; + EngageRadius = EnemyEV.EarthWizard_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.EarthWizard_Expert_KnockBack; + #endregion + + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + SpellDelay = 0.5f; + SpellDuration = 1.0f; + + #region Advanced Variables - General + Name = EnemyEV.EarthWizard_Advanced_Name; + LocStringID = EnemyEV.EarthWizard_Advanced_Name_locID; + + MaxHealth = EnemyEV.EarthWizard_Advanced_MaxHealth; + Damage = EnemyEV.EarthWizard_Advanced_Damage; + XPValue = EnemyEV.EarthWizard_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.EarthWizard_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.EarthWizard_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.EarthWizard_Advanced_DropChance; + + Speed = EnemyEV.EarthWizard_Advanced_Speed; + TurnSpeed = EnemyEV.EarthWizard_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.EarthWizard_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.EarthWizard_Advanced_Jump; + CooldownTime = EnemyEV.EarthWizard_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.EarthWizard_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.EarthWizard_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.EarthWizard_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.EarthWizard_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.EarthWizard_Advanced_IsWeighted; + + Scale = EnemyEV.EarthWizard_Advanced_Scale; + ProjectileScale = EnemyEV.EarthWizard_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.EarthWizard_Advanced_Tint; + + MeleeRadius = EnemyEV.EarthWizard_Advanced_MeleeRadius; + EngageRadius = EnemyEV.EarthWizard_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.EarthWizard_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.EarthWizard_Advanced_KnockBack; + #endregion + + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + } + + // Special method for the blob miniboss to initialize the enemy's EV. + public void PublicInitializeEV() + { + InitializeEV(); + } + + protected override void InitializeLogic() + { + InitializeProjectiles(); + + LogicSet moveTowardsLS = new LogicSet(this); + moveTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardIdle_Character", true, true)); + moveTowardsLS.AddAction(new ChaseLogicAction(m_target, new Vector2(-255, -175), new Vector2(255, -75), true, MoveDuration)); + + LogicSet moveAwayLS = new LogicSet(this); + moveAwayLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardIdle_Character", true, true)); + moveAwayLS.AddAction(new ChaseLogicAction(m_target, false, 1f)); + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardIdle_Character", true, true)); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(0.5f)); + + LogicSet castSpellLS = new LogicSet(this); + castSpellLS.AddAction(new MoveLogicAction(m_target, true, 0)); + castSpellLS.AddAction(new LockFaceDirectionLogicAction(true)); + castSpellLS.AddAction(new RunFunctionLogicAction(this, "CancelEarthSpell")); + castSpellLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardSpell_Character")); + castSpellLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeSpell")); + castSpellLS.AddAction(new RunFunctionLogicAction(this, "CastEarthSpellIn")); + castSpellLS.AddAction(new DelayLogicAction(0.5f)); + castSpellLS.AddAction(new RunFunctionLogicAction(this, "CastEarthSpellOut")); + castSpellLS.AddAction(new DelayLogicAction(SpellDelay)); + castSpellLS.AddAction(new PlayAnimationLogicAction("CastSpell", "End"), Types.Sequence.Parallel); + castSpellLS.AddAction(new DelayLogicAction(0.2f)); + castSpellLS.AddAction(new RunFunctionLogicAction(this, "CastEarthSpell", SpellDuration)); + castSpellLS.AddAction(new DelayLogicAction(0.2f)); + castSpellLS.AddAction(new RunFunctionLogicAction(this, "CancelEarthSpellIn")); + castSpellLS.AddAction(new DelayLogicAction(0.5f)); + castSpellLS.AddAction(new LockFaceDirectionLogicAction(false)); + castSpellLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet castMiniBossFireSpellLS = new LogicSet(this); + castMiniBossFireSpellLS.AddAction(new MoveLogicAction(m_target, true, 0)); + castMiniBossFireSpellLS.AddAction(new LockFaceDirectionLogicAction(true)); + castMiniBossFireSpellLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardSpell_Character")); + castMiniBossFireSpellLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeSpell")); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "SummonFireball", null)); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireDelay)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireInterval)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireInterval)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireInterval)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireInterval)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireInterval)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireInterval)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireInterval)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireInterval)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireInterval)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireInterval)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireInterval)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireInterval)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireInterval)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(SpellFireInterval)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "ResetFireball", null)); + castMiniBossFireSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castMiniBossFireSpellLS.AddAction(new DelayLogicAction(0.5f)); + castMiniBossFireSpellLS.AddAction(new LockFaceDirectionLogicAction(false)); + castMiniBossFireSpellLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet CastMiniBossIceSpellLS = new LogicSet(this); + CastMiniBossIceSpellLS.AddAction(new MoveLogicAction(m_target, true, 0)); + CastMiniBossIceSpellLS.AddAction(new LockFaceDirectionLogicAction(true)); + CastMiniBossIceSpellLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardSpell_Character")); + CastMiniBossIceSpellLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeSpell")); + CastMiniBossIceSpellLS.AddAction(new RunFunctionLogicAction(this, "SummonIceball", null)); + CastMiniBossIceSpellLS.AddAction(new DelayLogicAction(SpellDelay)); + CastMiniBossIceSpellLS.AddAction(new RunFunctionLogicAction(this, "ShatterIceball", SpellIceProjectileCount)); + CastMiniBossIceSpellLS.AddAction(new PlayAnimationLogicAction("CastSpell", "End"), Types.Sequence.Parallel); + CastMiniBossIceSpellLS.AddAction(new DelayLogicAction(0.5f)); + CastMiniBossIceSpellLS.AddAction(new RunFunctionLogicAction(this, "ResetIceball", null)); + CastMiniBossIceSpellLS.AddAction(new DelayLogicAction(0.5f)); + CastMiniBossIceSpellLS.AddAction(new LockFaceDirectionLogicAction(false)); + CastMiniBossIceSpellLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet teleportLS = new LogicSet(this); + teleportLS.AddAction(new MoveLogicAction(m_target, true, 0)); + teleportLS.AddAction(new LockFaceDirectionLogicAction(true)); + teleportLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 30f)); + teleportLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardTeleportOut_Character", false, false)); + teleportLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeTeleport")); + teleportLS.AddAction(new DelayLogicAction(TeleportDelay)); + teleportLS.AddAction(new PlayAnimationLogicAction("TeleportStart", "End")); + teleportLS.AddAction(new ChangePropertyLogicAction(this, "IsCollidable", false)); + teleportLS.AddAction(new DelayLogicAction(TeleportDuration)); + teleportLS.AddAction(new TeleportLogicAction(m_target, new Vector2(-400, -400), new Vector2(400, 400))); + teleportLS.AddAction(new ChangePropertyLogicAction(this, "IsCollidable", true)); + teleportLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardTeleportIn_Character", true, false)); + teleportLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 10f)); + teleportLS.AddAction(new LockFaceDirectionLogicAction(false)); + teleportLS.AddAction(new DelayLogicAction(0.5f)); + + m_generalBasicLB.AddLogicSet(moveTowardsLS, moveAwayLS, walkStopLS, castSpellLS, teleportLS); + m_generalAdvancedLB.AddLogicSet(moveTowardsLS, moveAwayLS, walkStopLS, castSpellLS, teleportLS); + m_generalExpertLB.AddLogicSet(moveTowardsLS, moveAwayLS, walkStopLS, castSpellLS, teleportLS); + m_generalMiniBossLB.AddLogicSet(moveTowardsLS, moveAwayLS, walkStopLS, castSpellLS, castMiniBossFireSpellLS, CastMiniBossIceSpellLS, teleportLS); + m_generalCooldownLB.AddLogicSet(moveTowardsLS, moveAwayLS, walkStopLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalMiniBossLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + + SetCooldownLogicBlock(m_generalCooldownLB, 100, 0, 0); //moveTowardsLS, moveAwayLS, walkStopLS + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 40, 0, 0, 60, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 40, 0, 0, 60, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 40, 0, 0, 60, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalMiniBossLB, 34, 0, 0, 22, 22, 22, 0); // (moveTowardsLS, moveAwayLS, walkStopLS, castSpellLS, castMiniBossFireSpellLS, CastMiniBossIceSpellLS, teleportLS); + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalMiniBossLB, 100, 0, 0, 0, 0, 0, 0); //(moveTowardsLS, moveAwayLS, walkStopLS, castSpellLS, castMiniBossFireSpellLS, CastMiniBossIceSpellLS, teleportLS); + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalMiniBossLB, 60, 10, 30, 0, 0, 0, 0); // (moveTowardsLS, moveAwayLS, walkStopLS, castSpellLS, castMiniBossFireSpellLS, CastMiniBossIceSpellLS, teleportLS); + break; + default: + break; + } + } + + public EnemyObj_EarthWizard(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyWizardIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.PlayAnimation(true); + TintablePart = _objectList[0]; + this.Type = EnemyType.EarthWizard; + } + + private void InitializeProjectiles() + { + m_earthSummonInSprite = new ProjectileObj("WizardEarthSpellCast_Sprite"); + m_earthSummonInSprite.AnimationDelay = 1 / 10f; + m_earthSummonInSprite.PlayAnimation(true); + m_earthSummonInSprite.Scale = Vector2.Zero; + + m_earthSummonOutSprite = m_earthSummonInSprite.Clone() as SpriteObj; + m_earthSummonOutSprite.PlayAnimation(true); + + m_earthProjectileObj = new ProjectileObj("WizardEarthSpell_Sprite"); + m_earthProjectileObj.IsWeighted = false; + m_earthProjectileObj.CollidesWithTerrain = false; + m_earthProjectileObj.DestroysWithEnemy = false; + m_earthProjectileObj.Damage = Damage; + m_earthProjectileObj.Scale = ProjectileScale; + m_earthProjectileObj.AnimationDelay = 1 / 20f; + m_earthProjectileObj.Rotation = 0; + m_earthProjectileObj.CanBeFusRohDahed = false; + } + + public void CancelEarthSpell() + { + Tweener.Tween.StopAllContaining(m_earthSummonOutSprite, false); + Tweener.Tween.StopAllContaining(this, false); + Tweener.Tween.To(m_earthSummonOutSprite, 0.5f, Tweener.Ease.Linear.EaseNone, "ScaleX", "0", "ScaleY", "0"); + if (m_earthProjectileObj.CurrentFrame != 1 && m_earthProjectileObj.CurrentFrame != m_earthProjectileObj.TotalFrames) + { + SoundManager.Play3DSound(this, m_target, "Earth_Wizard_Fall"); + m_earthProjectileObj.PlayAnimation("Grown", "End"); + } + m_levelScreen.PhysicsManager.RemoveObject(m_earthProjectileObj); + } + + public void CancelEarthSpellIn() + { + Tweener.Tween.StopAllContaining(m_earthSummonInSprite, false); + Tweener.Tween.To(m_earthSummonInSprite, 0.5f, Tweener.Ease.Linear.EaseNone, "ScaleX", "0", "ScaleY", "0"); + } + + public void CastEarthSpellIn() + { + SoundManager.Play3DSound(this, m_target, "Earth_Wizard_Form"); + m_earthSummonInSprite.Scale = Vector2.Zero; + Tweener.Tween.To(m_earthSummonInSprite, 0.5f, Tweener.Ease.Back.EaseOut, "ScaleX", "1", "ScaleY", "1"); + } + + public void CastEarthSpellOut() + { + //SoundManager.PlaySound("Earth_Wizard_Form"); + m_earthSummonOutSprite.Scale = Vector2.Zero; + m_earthSummonOutSprite.X = m_target.X; + + int closestDistance = int.MaxValue; + TerrainObj closestObj = null; + foreach (TerrainObj obj in m_levelScreen.CurrentRoom.TerrainObjList) + { + if (CollisionMath.Intersects(new Rectangle((int)m_target.X, (int)m_target.Y, 2, 720), obj.Bounds)) + { + int distanceBetween = obj.Bounds.Top - m_target.TerrainBounds.Bottom; + if (distanceBetween < closestDistance) + { + closestDistance = distanceBetween; + closestObj = obj; + } + } + } + + if (closestObj != null) + { + if (closestObj.Rotation == 0) + m_earthSummonOutSprite.Y = closestObj.Bounds.Top; + else + { + float y1 = float.MaxValue; + Vector2 pt1, pt2; + if (closestObj.Width > closestObj.Height) // If rotated objects are done correctly. + { + pt1 = CollisionMath.UpperLeftCorner(closestObj.TerrainBounds, closestObj.Rotation, Vector2.Zero); + pt2 = CollisionMath.UpperRightCorner(closestObj.TerrainBounds, closestObj.Rotation, Vector2.Zero); + } + else // If rotated objects are done Teddy's incorrect way. + { + //if (closestObj.Rotation == 45) + if (closestObj.Rotation > 0) // ROTCHECK + { + pt1 = CollisionMath.LowerLeftCorner(closestObj.TerrainBounds, closestObj.Rotation, Vector2.Zero); + pt2 = CollisionMath.UpperLeftCorner(closestObj.TerrainBounds, closestObj.Rotation, Vector2.Zero); + } + else + { + pt1 = CollisionMath.UpperRightCorner(closestObj.TerrainBounds, closestObj.Rotation, Vector2.Zero); + pt2 = CollisionMath.LowerRightCorner(closestObj.TerrainBounds, closestObj.Rotation, Vector2.Zero); + } + } + + //if (this.X > pt1.X + 10 && this.X < pt2.X - 10) + { + float u = pt2.X - pt1.X; + float v = pt2.Y - pt1.Y; + float x = pt1.X; + float y = pt1.Y; + float x1 = m_earthSummonOutSprite.X; + + y1 = y + (x1 - x) * (v / u); + y1 -= (m_earthSummonOutSprite.Bounds.Bottom - m_earthSummonOutSprite.Y); + m_earthSummonOutSprite.Y = (float)Math.Round(y1, MidpointRounding.ToEven); + } + } + } + + Tweener.Tween.To(m_earthSummonOutSprite, 0.5f, Tweener.Ease.Back.EaseOut, "Opacity", "1", "ScaleX", ProjectileScale.X.ToString(), "ScaleY", "1"); + } + + public void CastEarthSpell(float duration) + { + m_levelScreen.PhysicsManager.AddObject(m_earthProjectileObj); + m_earthProjectileObj.Scale = ProjectileScale; + m_earthProjectileObj.StopAnimation(); + m_earthProjectileObj.Position = m_earthSummonOutSprite.Position; + m_earthProjectileObj.PlayAnimation("Start", "Grown"); + SoundManager.Play3DSound(this, m_target, "Earth_Wizard_Attack"); + + Tweener.Tween.RunFunction(duration, this, "CancelEarthSpell"); + } + + public override void Update(GameTime gameTime) + { + base.Update(gameTime); + //if (m_earthSummonIn != null) + { + if (this.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.None) + m_earthSummonInSprite.Position = new Vector2(this.X + m_spellOffset.X, this.Y + m_spellOffset.Y); + else + m_earthSummonInSprite.Position = new Vector2(this.X - m_spellOffset.X, this.Y + m_spellOffset.Y); + } + + if (m_fireballSummon != null) + { + if (this.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.None) + m_fireballSummon.Position = new Vector2(this.X + m_spellOffset.X, this.Y + m_spellOffset.Y); + else + m_fireballSummon.Position = new Vector2(this.X - m_spellOffset.X, this.Y + m_spellOffset.Y); + } + + if (m_iceballSummon != null) + { + if (this.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.None) + m_iceballSummon.Position = new Vector2(this.X + m_spellOffset.X, this.Y + m_spellOffset.Y); + else + m_iceballSummon.Position = new Vector2(this.X - m_spellOffset.X, this.Y + m_spellOffset.Y); + } + + + if (m_earthParticleEffectCounter > 0) + { + m_earthParticleEffectCounter -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_earthParticleEffectCounter <= 0) + { + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + { + if (m_effectCycle == 0) + m_levelScreen.ImpactEffectPool.DisplayEarthParticleEffect(this); + else if (m_effectCycle == 1) + m_levelScreen.ImpactEffectPool.DisplayFireParticleEffect(this); + else + m_levelScreen.ImpactEffectPool.DisplayIceParticleEffect(this); + m_effectCycle++; + if (m_effectCycle > 2) + m_effectCycle = 0; + } + else + m_levelScreen.ImpactEffectPool.DisplayEarthParticleEffect(this); + m_earthParticleEffectCounter = 0.15f; + } + } + } + + #region Fireball Spell Stuff + + public void CastFireball() + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "WizardFireballProjectile_Sprite", + SourceAnchor = m_spellOffset, + Target = m_target, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = MiniBossFireballSize, + }; + + if (this.Difficulty == GameTypes.EnemyDifficulty.ADVANCED) + projData.AngleOffset = CDGMath.RandomInt(-25, 25); + + if (this.Difficulty == GameTypes.EnemyDifficulty.EXPERT) + projData.SpriteName = "GhostBossProjectile_Sprite"; + + SoundManager.Play3DSound(this, m_target, "FireWizard_Attack_01", "FireWizard_Attack_02", "FireWizard_Attack_03", "FireWizard_Attack_04"); + ProjectileObj fireball = m_levelScreen.ProjectileManager.FireProjectile(projData); + fireball.Rotation = 0; + Tweener.Tween.RunFunction(0.15f, this, "ChangeFireballState", fireball); + } + + public void ChangeFireballState(ProjectileObj fireball) + { + fireball.CollidesWithTerrain = true; + } + + public void SummonFireball() + { + ResetFireball(); + + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "WizardFireballProjectile_Sprite", + SourceAnchor = m_spellOffset, + Target = m_target, + Speed = new Vector2(0, 0), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = MiniBossFireballSize, + }; + + if (this.Difficulty == GameTypes.EnemyDifficulty.EXPERT) + projData.SpriteName = "GhostBossProjectile_Sprite"; + + SoundManager.Play3DSound(this, m_target, "Fire_Wizard_Form"); + //m_fireballSummon = m_levelScreen.ProjectileManager.FireProjectile("WizardFireballProjectile_Sprite", this, m_spellOffset, 0, 0, false, 0, ProjectileDamage); + m_fireballSummon = m_levelScreen.ProjectileManager.FireProjectile(projData); + m_fireballSummon.Opacity = 0; + m_fireballSummon.Scale = Vector2.Zero; + m_fireballSummon.AnimationDelay = 1 / 10f; + m_fireballSummon.PlayAnimation(true); + m_fireballSummon.Rotation = 0; + + Tweener.Tween.To(m_fireballSummon, 0.5f, Tweener.Ease.Back.EaseOut, "Opacity", "1", "ScaleX", MiniBossFireballSize.X.ToString(), "ScaleY", MiniBossFireballSize.Y.ToString()); + + projData.Dispose(); + } + + public void ResetFireball() + { + if (m_fireballSummon != null) + { + m_levelScreen.ProjectileManager.DestroyProjectile(m_fireballSummon); + m_fireballSummon = null; + } + } + #endregion + + + #region Ice Spell Stuff + public void SummonIceball() + { + ResetIceball(); + + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "WizardIceSpell_Sprite", + SourceAnchor = m_spellOffset, + Target = null, + Speed = new Vector2(0, 0), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = MiniBossIceSize, + }; + + SoundManager.Play3DSound(this, m_target, "Ice_Wizard_Form"); + //m_iceballSummon = m_levelScreen.ProjectileManager.FireProjectile("WizardIceSpell_Sprite", this, m_spellOffset, 0, 0, false, 0, ProjectileDamage); + m_iceballSummon = m_levelScreen.ProjectileManager.FireProjectile(projData); + m_iceballSummon.PlayAnimation("Start", "Grown"); + + projData.Dispose(); + } + + public void ShatterIceball(int numIceballs) + { + SoundManager.Play3DSound(this, m_target, "Ice_Wizard_Attack_Glass"); + + if (m_iceballSummon.SpriteName == "WizardIceSpell_Sprite") // Temporary hack fix for crashing iceballs. + m_iceballSummon.PlayAnimation("Grown", "End"); + + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "WizardIceProjectile_Sprite", + SourceAnchor = m_spellOffset, + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = MiniBossIceSize, + }; + + float angle = 0; + float angleDiff = 360 / numIceballs; + + for (int i = 0; i < numIceballs; i++) + { + projData.Angle = new Vector2(angle, angle); + ProjectileObj iceball = m_levelScreen.ProjectileManager.FireProjectile(projData); + Tweener.Tween.RunFunction(0.15f, this, "ChangeIceballState", iceball); + angle += angleDiff; + } + + projData.Dispose(); + } + + public void ChangeIceballState(ProjectileObj iceball) + { + iceball.CollidesWithTerrain = true; + } + + public void ResetIceball() + { + if (m_iceballSummon != null) + { + m_levelScreen.ProjectileManager.DestroyProjectile(m_iceballSummon); + m_iceballSummon = null; + } + } + #endregion + + //public override void HitEnemy(int damage, Vector2 position, bool isPlayer = true) + //{ + // base.HitEnemy(damage, position, isPlayer); + // if (m_currentActiveLB != null && m_currentActiveLB.IsActive == true) + // { + // m_currentActiveLB.StopLogicBlock(); + // DestroyEarthSpell(); + + // //Ensures he doesn't cast a spell immediately after getting hit (since the destroy spell animation is still running). + // RunLogicBlock(false, m_generalBasicLB, 100, 0, 0, 0, 0); // moveTowardsLS, moveAwayLS, castSpellLS + // } + //} + + public override void Kill(bool giveXP = true) + { + if (m_currentActiveLB != null && m_currentActiveLB.IsActive == true) + { + CancelEarthSpell(); + CancelEarthSpellIn(); + + m_currentActiveLB.StopLogicBlock(); + + //Ensures he doesn't cast a spell immediately after getting hit (since the destroy spell animation is still running). + //RunLogicBlock(false, m_generalBasicLB, 100, 0, 0, 0, 0); // moveTowardsLS, moveAwayLS, castSpellLS + } + base.Kill(giveXP); + } + + public override void Draw(Camera2D camera) + { + m_earthSummonInSprite.Draw(camera); + m_earthSummonOutSprite.Draw(camera); + m_earthProjectileObj.Draw(camera); + base.Draw(camera); + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + if (otherBox.AbsParent is PlayerObj) + this.CurrentSpeed = 0; + if (collisionResponseType != Consts.COLLISIONRESPONSE_TERRAIN) + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + else if ((otherBox.AbsParent is PlayerObj) == false)// Add this else to turn on terrain collision. + { + IPhysicsObj otherPhysicsObj = otherBox.AbsParent as IPhysicsObj; + if (otherPhysicsObj.CollidesBottom == true && otherPhysicsObj.CollidesTop == true && otherPhysicsObj.CollidesLeft == true && otherPhysicsObj.CollidesRight == true) + this.Position += CollisionMath.RotatedRectIntersectsMTD(thisBox.AbsRect, thisBox.AbsRotation, Vector2.Zero, otherBox.AbsRect, otherBox.AbsRotation, Vector2.Zero); + } + } + + public override void ResetState() + { + Tweener.Tween.StopAllContaining(this, false); + Tweener.Tween.StopAllContaining(m_earthSummonOutSprite, false); + Tweener.Tween.StopAllContaining(m_earthSummonInSprite, false); + m_earthSummonInSprite.Scale = Vector2.Zero; + m_earthSummonOutSprite.Scale = Vector2.Zero; + m_earthProjectileObj.StopAnimation(); + m_earthProjectileObj.GoToFrame(m_earthProjectileObj.TotalFrames); + + ResetFireball(); + ResetIceball(); + base.ResetState(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_fireballSummon = null; + m_iceballSummon = null; + + if (m_earthSummonInSprite != null) + { + m_earthSummonInSprite.Dispose(); + m_earthSummonInSprite = null; + } + + if (m_earthSummonOutSprite != null) + { + m_earthSummonOutSprite.Dispose(); + m_earthSummonOutSprite = null; + } + + if (m_earthProjectileObj != null) + { + m_earthProjectileObj.Dispose(); + m_earthProjectileObj = null; + } + + SpawnRoom = null; + base.Dispose(); + } + } + + public SpriteObj EarthProjectile + { + get { return m_earthProjectileObj; } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Energon.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Energon.cs new file mode 100644 index 0000000..ea5d564 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Energon.cs @@ -0,0 +1,470 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_Energon : EnemyObj + { + private const byte TYPE_SWORD = 0; + private const byte TYPE_SHIELD = 1; + private const byte TYPE_DOWNSWORD = 2; + + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + + private SpriteObj m_shield; + private DS2DPool m_projectilePool; + private byte m_poolSize = 10; + private byte m_currentAttackType = TYPE_SWORD; + + protected override void InitializeEV() + { + #region Basic Variables - General + Name = EnemyEV.Energon_Basic_Name; + LocStringID = EnemyEV.Energon_Basic_Name_locID; + + MaxHealth = EnemyEV.Energon_Basic_MaxHealth; + Damage = EnemyEV.Energon_Basic_Damage; + XPValue = EnemyEV.Energon_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Energon_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Energon_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Energon_Basic_DropChance; + + Speed = EnemyEV.Energon_Basic_Speed; + TurnSpeed = EnemyEV.Energon_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Energon_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Energon_Basic_Jump; + CooldownTime = EnemyEV.Energon_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Energon_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Energon_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Energon_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Energon_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Energon_Basic_IsWeighted; + + Scale = EnemyEV.Energon_Basic_Scale; + ProjectileScale = EnemyEV.Energon_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Energon_Basic_Tint; + + MeleeRadius = EnemyEV.Energon_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Energon_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Energon_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Energon_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Energon_Miniboss_Name; + LocStringID = EnemyEV.Energon_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Energon_Miniboss_MaxHealth; + Damage = EnemyEV.Energon_Miniboss_Damage; + XPValue = EnemyEV.Energon_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Energon_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Energon_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Energon_Miniboss_DropChance; + + Speed = EnemyEV.Energon_Miniboss_Speed; + TurnSpeed = EnemyEV.Energon_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Energon_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Energon_Miniboss_Jump; + CooldownTime = EnemyEV.Energon_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Energon_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Energon_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Energon_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Energon_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Energon_Miniboss_IsWeighted; + + Scale = EnemyEV.Energon_Miniboss_Scale; + ProjectileScale = EnemyEV.Energon_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Energon_Miniboss_Tint; + + MeleeRadius = EnemyEV.Energon_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Energon_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Energon_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Energon_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.Energon_Expert_Name; + LocStringID = EnemyEV.Energon_Expert_Name_locID; + + MaxHealth = EnemyEV.Energon_Expert_MaxHealth; + Damage = EnemyEV.Energon_Expert_Damage; + XPValue = EnemyEV.Energon_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Energon_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Energon_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Energon_Expert_DropChance; + + Speed = EnemyEV.Energon_Expert_Speed; + TurnSpeed = EnemyEV.Energon_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Energon_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Energon_Expert_Jump; + CooldownTime = EnemyEV.Energon_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Energon_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Energon_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Energon_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Energon_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Energon_Expert_IsWeighted; + + Scale = EnemyEV.Energon_Expert_Scale; + ProjectileScale = EnemyEV.Energon_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Energon_Expert_Tint; + + MeleeRadius = EnemyEV.Energon_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Energon_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Energon_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Energon_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.Energon_Advanced_Name; + LocStringID = EnemyEV.Energon_Advanced_Name_locID; + + MaxHealth = EnemyEV.Energon_Advanced_MaxHealth; + Damage = EnemyEV.Energon_Advanced_Damage; + XPValue = EnemyEV.Energon_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Energon_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Energon_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Energon_Advanced_DropChance; + + Speed = EnemyEV.Energon_Advanced_Speed; + TurnSpeed = EnemyEV.Energon_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Energon_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Energon_Advanced_Jump; + CooldownTime = EnemyEV.Energon_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Energon_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Energon_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Energon_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Energon_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Energon_Advanced_IsWeighted; + + Scale = EnemyEV.Energon_Advanced_Scale; + ProjectileScale = EnemyEV.Energon_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Energon_Advanced_Tint; + + MeleeRadius = EnemyEV.Energon_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Energon_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Energon_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Energon_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + + } + + protected override void InitializeLogic() + { + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemyEnergonWalk_Character", true, true)); + walkTowardsLS.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsLS.AddAction(new DelayLogicAction(0.2f, 0.75f)); + + LogicSet walkAwayLS = new LogicSet(this); + walkAwayLS.AddAction(new ChangeSpriteLogicAction("EnemyEnergonWalk_Character", true, true)); + walkAwayLS.AddAction(new MoveLogicAction(m_target, false)); + walkAwayLS.AddAction(new DelayLogicAction(0.2f, 0.75f)); + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new ChangeSpriteLogicAction("EnemyEnergonIdle_Character", true, true)); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(0.2f, 0.75f)); + + LogicSet fireProjectile = new LogicSet(this); + fireProjectile.AddAction(new ChangePropertyLogicAction(this, "CurrentSpeed", 0)); + fireProjectile.AddAction(new ChangeSpriteLogicAction("EnemyEnergonAttack_Character", false, false)); + fireProjectile.AddAction(new PlayAnimationLogicAction("Start", "BeforeAttack")); + fireProjectile.AddAction(new RunFunctionLogicAction(this, "FireCurrentTypeProjectile")); + fireProjectile.AddAction(new PlayAnimationLogicAction("Attack", "End")); + fireProjectile.AddAction(new ChangeSpriteLogicAction("EnemyEnergonIdle_Character", true, true)); + fireProjectile.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet changeAttackType = new LogicSet(this); + changeAttackType.AddAction(new ChangePropertyLogicAction(this, "CurrentSpeed", 0)); + changeAttackType.AddAction(new ChangeSpriteLogicAction("EnemyEnergonAttack_Character", false, false)); + changeAttackType.AddAction(new PlayAnimationLogicAction("Start", "BeforeAttack")); + changeAttackType.AddAction(new RunFunctionLogicAction(this, "SwitchRandomType")); + changeAttackType.AddAction(new PlayAnimationLogicAction("Attack", "End")); + changeAttackType.AddAction(new ChangeSpriteLogicAction("EnemyEnergonIdle_Character", true, true)); + changeAttackType.AddAction(new DelayLogicAction(2.0f)); + + m_generalBasicLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, fireProjectile, changeAttackType); + m_generalCooldownLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalMiniBossLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + + SetCooldownLogicBlock(m_generalCooldownLB, 0, 0, 100); //walkTowardsLS, walkAwayLS, walkStopLS + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 30, 60, 10); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectile, changeAttackType + break; + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + public void FireCurrentTypeProjectile() + { + FireProjectile(m_currentAttackType); + } + + public void FireProjectile(byte type) + { + EnergonProjectileObj projectile = m_projectilePool.CheckOut(); + projectile.SetType(type); + PhysicsMngr.AddObject(projectile); + projectile.Target = m_target; + projectile.Visible = true; + projectile.Position = this.Position; + projectile.CurrentSpeed = ProjectileSpeed; + projectile.Flip = this.Flip; + projectile.Scale = ProjectileScale; + projectile.Opacity = 0.8f; + projectile.Damage = this.Damage; + projectile.PlayAnimation(true); + //projectile.TurnSpeed = TurnSpeed; + } + + public void DestroyProjectile(EnergonProjectileObj projectile) + { + if (m_projectilePool.ActiveObjsList.Contains(projectile)) // Only destroy projectiles if they haven't already been destroyed. It is possible for two objects to call Destroy on the same projectile. + { + projectile.Visible = false; + projectile.Scale = new Vector2(1, 1); + projectile.CollisionTypeTag = GameTypes.CollisionType_ENEMY; + PhysicsMngr.RemoveObject(projectile); // Might be better to keep them in the physics manager and just turn off their collision detection. + m_projectilePool.CheckIn(projectile); + } + } + + public void DestroyAllProjectiles() + { + ProjectileObj[] activeProjectilesArray = m_projectilePool.ActiveObjsList.ToArray(); + foreach (EnergonProjectileObj projectile in activeProjectilesArray) + { + DestroyProjectile(projectile); + } + } + + public void SwitchRandomType() + { + byte storedAttackType = m_currentAttackType; + while (storedAttackType == m_currentAttackType) + storedAttackType = (byte)CDGMath.RandomInt(0, 2); + SwitchType(storedAttackType); + } + + public void SwitchType(byte type) + { + m_currentAttackType = type; + switch (type) + { + case (TYPE_SWORD): + m_shield.ChangeSprite("EnergonSwordShield_Sprite"); + break; + case (TYPE_SHIELD): + m_shield.ChangeSprite("EnergonShieldShield_Sprite"); + break; + case (TYPE_DOWNSWORD): + m_shield.ChangeSprite("EnergonDownSwordShield_Sprite"); + break; + } + m_shield.PlayAnimation(true); + } + + public override void Update(GameTime gameTime) + { + foreach (EnergonProjectileObj projectile in m_projectilePool.ActiveObjsList) + projectile.Update(gameTime); + base.Update(gameTime); + } + + public override void Draw(Camera2D camera) + { + base.Draw(camera); + m_shield.Position = this.Position; + m_shield.Flip = this.Flip; + m_shield.Draw(camera); + foreach (ProjectileObj projectile in m_projectilePool.ActiveObjsList) + projectile.Draw(camera); + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + if ((collisionResponseType == Consts.COLLISIONRESPONSE_FIRSTBOXHIT) && m_invincibleCounter <= 0 && otherBox.AbsParent is PlayerObj) + { + if (m_target.Bounds.Left + m_target.Bounds.Width / 2 < this.X) + m_target.AccelerationX = -m_target.EnemyKnockBack.X; + else + m_target.AccelerationX = m_target.EnemyKnockBack.X; + m_target.AccelerationY = -m_target.EnemyKnockBack.Y; + + //m_target.CancelAttack(); + Point intersectPt = Rectangle.Intersect(thisBox.AbsRect, otherBox.AbsRect).Center; + Vector2 impactPosition = new Vector2(intersectPt.X, intersectPt.Y); + + m_levelScreen.ImpactEffectPool.DisplayBlockImpactEffect(impactPosition, Vector2.One); + m_levelScreen.SetLastEnemyHit(this); + m_invincibleCounter = InvincibilityTime; + Blink(Color.LightBlue, 0.1f); + + ProjectileObj projectile = otherBox.AbsParent as ProjectileObj; + if (projectile != null) + m_levelScreen.ProjectileManager.DestroyProjectile(projectile); + } + else if (otherBox.AbsParent is EnergonProjectileObj) + { + //base.CollisionResponse(thisBox, otherBox, collisionResponseType); + + EnergonProjectileObj projectile = otherBox.AbsParent as EnergonProjectileObj; + if (projectile != null) + { + Point intersectPt = Rectangle.Intersect(thisBox.AbsRect, otherBox.AbsRect).Center; + Vector2 impactPosition = new Vector2(intersectPt.X, intersectPt.Y); + + DestroyProjectile(projectile); + if (projectile.AttackType == m_currentAttackType) + HitEnemy(projectile.Damage, impactPosition, true); + else + m_levelScreen.ImpactEffectPool.DisplayBlockImpactEffect(impactPosition, Vector2.One); + } + } + else + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + public override void Kill(bool giveXP = true) + { + m_shield.Visible = false; + DestroyAllProjectiles(); + base.Kill(giveXP); + } + + public override void Reset() + { + m_shield.Visible = true; + base.Reset(); + } + + public EnemyObj_Energon(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyEnergonIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.Energon; + m_shield = new SpriteObj("EnergonSwordShield_Sprite"); + m_shield.AnimationDelay = 1 / 10f; + m_shield.PlayAnimation(true); + m_shield.Opacity = 0.5f; + m_shield.Scale = new Vector2(1.2f, 1.2f); + + m_projectilePool = new DS2DPool(); + + for (int i = 0; i < m_poolSize; i++) + { + EnergonProjectileObj projectile = new EnergonProjectileObj("EnergonSwordProjectile_Sprite", this); + projectile.Visible = false; + projectile.CollidesWithTerrain = false; + projectile.PlayAnimation(true); + projectile.AnimationDelay = 1 / 20f; + m_projectilePool.AddToPool(projectile); + } + } + + public override void Dispose() + { + if (IsDisposed == false) + { + m_projectilePool.Dispose(); + m_projectilePool = null; + m_shield.Dispose(); + m_shield = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Eyeball.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Eyeball.cs new file mode 100644 index 0000000..a476e2f --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Eyeball.cs @@ -0,0 +1,913 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Microsoft.Xna.Framework.Audio; + +namespace RogueCastle +{ + public class EnemyObj_Eyeball: EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + private LogicBlock m_generalNeoLB = new LogicBlock(); + + private SpriteObj m_pupil; + private FrameSoundObj m_squishSound; + public int PupilOffset { get; set; } + + private bool m_shake = false; + private bool m_shookLeft = false; + + private float FireballDelay = 0.5f; + private float m_shakeTimer = 0; + private float m_shakeDuration = 0.03f; + + //2000 + private int m_bossCoins = 30; + private int m_bossMoneyBags = 7; + private int m_bossDiamonds = 1; + + private Cue m_deathLoop; + private bool m_playDeathLoop; + private bool m_isNeo = false; + + protected override void InitializeEV() + { + #region Basic Variables - General + Name = EnemyEV.Eyeball_Basic_Name; + LocStringID = EnemyEV.Eyeball_Basic_Name_locID; + + MaxHealth = EnemyEV.Eyeball_Basic_MaxHealth; + Damage = EnemyEV.Eyeball_Basic_Damage; + XPValue = EnemyEV.Eyeball_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Eyeball_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Eyeball_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Eyeball_Basic_DropChance; + + Speed = EnemyEV.Eyeball_Basic_Speed; + TurnSpeed = EnemyEV.Eyeball_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Eyeball_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Eyeball_Basic_Jump; + CooldownTime = EnemyEV.Eyeball_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Eyeball_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Eyeball_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Eyeball_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Eyeball_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Eyeball_Basic_IsWeighted; + + Scale = EnemyEV.Eyeball_Basic_Scale; + ProjectileScale = EnemyEV.Eyeball_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Eyeball_Basic_Tint; + + MeleeRadius = EnemyEV.Eyeball_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Eyeball_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Eyeball_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Eyeball_Basic_KnockBack; + #endregion + PupilOffset = 4; + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Eyeball_Miniboss_Name; + LocStringID = EnemyEV.Eyeball_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Eyeball_Miniboss_MaxHealth; + Damage = EnemyEV.Eyeball_Miniboss_Damage; + XPValue = EnemyEV.Eyeball_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Eyeball_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Eyeball_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Eyeball_Miniboss_DropChance; + + Speed = EnemyEV.Eyeball_Miniboss_Speed; + TurnSpeed = EnemyEV.Eyeball_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Eyeball_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Eyeball_Miniboss_Jump; + CooldownTime = EnemyEV.Eyeball_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Eyeball_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Eyeball_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Eyeball_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Eyeball_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Eyeball_Miniboss_IsWeighted; + + Scale = EnemyEV.Eyeball_Miniboss_Scale; + ProjectileScale = EnemyEV.Eyeball_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Eyeball_Miniboss_Tint; + + MeleeRadius = EnemyEV.Eyeball_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Eyeball_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Eyeball_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Eyeball_Miniboss_KnockBack; + #endregion + PupilOffset = 0; + if (LevelEV.WEAKEN_BOSSES == true) + this.MaxHealth = 1; + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.Eyeball_Expert_Name; + LocStringID = EnemyEV.Eyeball_Expert_Name_locID; + + MaxHealth = EnemyEV.Eyeball_Expert_MaxHealth; + Damage = EnemyEV.Eyeball_Expert_Damage; + XPValue = EnemyEV.Eyeball_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Eyeball_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Eyeball_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Eyeball_Expert_DropChance; + + Speed = EnemyEV.Eyeball_Expert_Speed; + TurnSpeed = EnemyEV.Eyeball_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Eyeball_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Eyeball_Expert_Jump; + CooldownTime = EnemyEV.Eyeball_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Eyeball_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Eyeball_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Eyeball_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Eyeball_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Eyeball_Expert_IsWeighted; + + Scale = EnemyEV.Eyeball_Expert_Scale; + ProjectileScale = EnemyEV.Eyeball_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Eyeball_Expert_Tint; + + MeleeRadius = EnemyEV.Eyeball_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Eyeball_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Eyeball_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Eyeball_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.Eyeball_Advanced_Name; + LocStringID = EnemyEV.Eyeball_Advanced_Name_locID; + + MaxHealth = EnemyEV.Eyeball_Advanced_MaxHealth; + Damage = EnemyEV.Eyeball_Advanced_Damage; + XPValue = EnemyEV.Eyeball_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Eyeball_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Eyeball_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Eyeball_Advanced_DropChance; + + Speed = EnemyEV.Eyeball_Advanced_Speed; + TurnSpeed = EnemyEV.Eyeball_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Eyeball_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Eyeball_Advanced_Jump; + CooldownTime = EnemyEV.Eyeball_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Eyeball_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Eyeball_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Eyeball_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Eyeball_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Eyeball_Advanced_IsWeighted; + + Scale = EnemyEV.Eyeball_Advanced_Scale; + ProjectileScale = EnemyEV.Eyeball_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Eyeball_Advanced_Tint; + + MeleeRadius = EnemyEV.Eyeball_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Eyeball_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Eyeball_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Eyeball_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + m_resetSpriteName = "EnemyEyeballBossEye_Character"; + } + + protected override void InitializeLogic() + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "EyeballProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = m_target, + Speed = new Vector2(this.ProjectileSpeed, this.ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = ProjectileScale, + + }; + + LogicSet fireProjectileBasicLS = new LogicSet(this); + fireProjectileBasicLS.AddAction(new ChangeSpriteLogicAction("EnemyEyeballFire_Character", true, true)); + fireProjectileBasicLS.AddAction(new DelayLogicAction(FireballDelay)); + fireProjectileBasicLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Eyeball_ProjectileAttack")); + fireProjectileBasicLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileBasicLS.AddAction(new ChangeSpriteLogicAction("EnemyEyeballIdle_Character", false, false)); + fireProjectileBasicLS.AddAction(new DelayLogicAction(1.0f, 3.0f)); + fireProjectileBasicLS.Tag = GameTypes.LogicSetType_ATTACK; + + + LogicSet fireProjectileAdvancedLS = new LogicSet(this); + fireProjectileAdvancedLS.AddAction(new ChangeSpriteLogicAction("EnemyEyeballFire_Character", true, true)); + fireProjectileAdvancedLS.AddAction(new DelayLogicAction(FireballDelay)); + fireProjectileAdvancedLS.AddAction(new Play3DSoundLogicAction(this, m_target, "EyeballFire1")); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileAdvancedLS.AddAction(new DelayLogicAction(0.15f)); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileAdvancedLS.AddAction(new DelayLogicAction(0.15f)); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileAdvancedLS.AddAction(new DelayLogicAction(0.15f)); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + //fireProjectileAdvancedLS.AddAction(new DelayLogicAction(0.15f)); + //fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileAdvancedLS.AddAction(new ChangeSpriteLogicAction("EnemyEyeballIdle_Character", false, false)); + fireProjectileAdvancedLS.AddAction(new DelayLogicAction(0.75f, 2.0f)); + fireProjectileAdvancedLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet fireProjectileExpertLS = new LogicSet(this); + fireProjectileExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyEyeballFire_Character", true, true)); + fireProjectileExpertLS.AddAction(new DelayLogicAction(FireballDelay)); + fireProjectileExpertLS.AddAction(new Play3DSoundLogicAction(this, m_target, "EyeballFire1")); + fireProjectileExpertLS.AddAction(new DelayLogicAction(0.1f)); + ThrowThreeProjectiles(fireProjectileExpertLS); + fireProjectileExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyEyeballIdle_Character", false, false)); + fireProjectileExpertLS.AddAction(new DelayLogicAction(1.0f, 3.0f)); + fireProjectileExpertLS.Tag = GameTypes.LogicSetType_ATTACK; + + + ////////////////// MINI BOSS LOGIC ////////////////////////////// + LogicSet fireProjectileCardinalSpinLS = new LogicSet(this); + fireProjectileCardinalSpinLS.AddAction(new ChangeSpriteLogicAction("EnemyEyeballBossFire_Character", true, true)); + fireProjectileCardinalSpinLS.AddAction(new RunFunctionLogicAction(this, "LockEyeball")); + fireProjectileCardinalSpinLS.AddAction(new RunFunctionLogicAction(m_pupil, "ChangeSprite", "EnemyEyeballBossPupilFire_Sprite")); + fireProjectileCardinalSpinLS.AddAction(new DelayLogicAction(FireballDelay)); + fireProjectileCardinalSpinLS.AddAction(new Play3DSoundLogicAction(this, m_target, "EyeballFire1")); + fireProjectileCardinalSpinLS.AddAction(new DelayLogicAction(0.1f)); + //ThrowCardinalProjectiles(fireProjectileCardinalSpinLS); + fireProjectileCardinalSpinLS.AddAction(new RunFunctionLogicAction(this, "ThrowCardinalProjectiles", 0, true, 0)); + fireProjectileCardinalSpinLS.AddAction(new DelayLogicAction(3.15f)); + fireProjectileCardinalSpinLS.AddAction(new ChangeSpriteLogicAction("EnemyEyeballBossEye_Character", false, false)); + fireProjectileCardinalSpinLS.AddAction(new RunFunctionLogicAction(m_pupil, "ChangeSprite", "EnemyEyeballBossPupil_Sprite")); + fireProjectileCardinalSpinLS.AddAction(new RunFunctionLogicAction(this, "UnlockEyeball")); + //fireProjectileCardinalSpinLS.AddAction(new DelayLogicAction(2.5f, 3.5f)); + fireProjectileCardinalSpinLS.Tag = GameTypes.LogicSetType_ATTACK; + + #region Neo Version + LogicSet fireProjectileCardinalSpinNeoLS = new LogicSet(this); + fireProjectileCardinalSpinNeoLS.AddAction(new ChangeSpriteLogicAction("EnemyEyeballBossFire_Character", true, true)); + fireProjectileCardinalSpinNeoLS.AddAction(new RunFunctionLogicAction(this, "LockEyeball")); + fireProjectileCardinalSpinNeoLS.AddAction(new RunFunctionLogicAction(m_pupil, "ChangeSprite", "EnemyEyeballBossPupilFire_Sprite")); + fireProjectileCardinalSpinNeoLS.AddAction(new DelayLogicAction(FireballDelay)); + fireProjectileCardinalSpinNeoLS.AddAction(new Play3DSoundLogicAction(this, m_target, "EyeballFire1")); + fireProjectileCardinalSpinNeoLS.AddAction(new DelayLogicAction(0.1f)); + //ThrowCardinalProjectiles(fireProjectileCardinalSpinLS); + fireProjectileCardinalSpinNeoLS.AddAction(new RunFunctionLogicAction(this, "ThrowCardinalProjectilesNeo", 0, true, 0)); + fireProjectileCardinalSpinNeoLS.AddAction(new DelayLogicAction(3.0f));//(3.15f)); + fireProjectileCardinalSpinNeoLS.AddAction(new ChangeSpriteLogicAction("EnemyEyeballBossEye_Character", false, false)); + fireProjectileCardinalSpinNeoLS.AddAction(new RunFunctionLogicAction(m_pupil, "ChangeSprite", "EnemyEyeballBossPupil_Sprite")); + fireProjectileCardinalSpinNeoLS.AddAction(new RunFunctionLogicAction(this, "UnlockEyeball")); + //fireProjectileCardinalSpinLS.AddAction(new DelayLogicAction(2.5f, 3.5f)); + fireProjectileCardinalSpinNeoLS.Tag = GameTypes.LogicSetType_ATTACK; + + #endregion + + + LogicSet fireProjectileSprayLS = new LogicSet(this); + fireProjectileSprayLS.AddAction(new ChangeSpriteLogicAction("EnemyEyeballBossFire_Character", true, true)); + fireProjectileSprayLS.AddAction(new RunFunctionLogicAction(this, "LockEyeball")); + fireProjectileSprayLS.AddAction(new RunFunctionLogicAction(m_pupil, "ChangeSprite", "EnemyEyeballBossPupilFire_Sprite")); + fireProjectileSprayLS.AddAction(new DelayLogicAction(FireballDelay)); + fireProjectileSprayLS.AddAction(new Play3DSoundLogicAction(this, m_target, "EyeballFire1")); + fireProjectileSprayLS.AddAction(new DelayLogicAction(0.1f)); + //ThrowSprayProjectiles(fireProjectileSprayLS); + fireProjectileSprayLS.AddAction(new RunFunctionLogicAction(this, "ThrowSprayProjectiles", true)); + fireProjectileSprayLS.AddAction(new DelayLogicAction(1.6f)); + fireProjectileSprayLS.AddAction(new RunFunctionLogicAction(this, "ThrowSprayProjectiles", true)); + fireProjectileSprayLS.AddAction(new DelayLogicAction(1.6f)); + fireProjectileSprayLS.AddAction(new ChangeSpriteLogicAction("EnemyEyeballBossEye_Character", false, false)); + fireProjectileSprayLS.AddAction(new RunFunctionLogicAction(m_pupil, "ChangeSprite", "EnemyEyeballBossPupil_Sprite")); + fireProjectileSprayLS.AddAction(new RunFunctionLogicAction(this, "UnlockEyeball")); + fireProjectileSprayLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet fireProjectileRandomLS = new LogicSet(this); + fireProjectileRandomLS.AddAction(new ChangeSpriteLogicAction("EnemyEyeballBossFire_Character", true, true)); + fireProjectileRandomLS.AddAction(new RunFunctionLogicAction(this, "LockEyeball")); + fireProjectileRandomLS.AddAction(new RunFunctionLogicAction(m_pupil, "ChangeSprite", "EnemyEyeballBossPupilFire_Sprite")); + fireProjectileRandomLS.AddAction(new DelayLogicAction(FireballDelay)); + fireProjectileRandomLS.AddAction(new Play3DSoundLogicAction(this, m_target, "EyeballFire1")); + fireProjectileRandomLS.AddAction(new DelayLogicAction(0.1f)); + //ThrowRandomProjectiles(fireProjectileRandomLS); + fireProjectileRandomLS.AddAction(new RunFunctionLogicAction(this, "ThrowRandomProjectiles")); + fireProjectileRandomLS.AddAction(new DelayLogicAction(0.575f)); + fireProjectileRandomLS.AddAction(new RunFunctionLogicAction(this, "ThrowRandomProjectiles")); + fireProjectileRandomLS.AddAction(new DelayLogicAction(0.575f)); + fireProjectileRandomLS.AddAction(new RunFunctionLogicAction(this, "ThrowRandomProjectiles")); + fireProjectileRandomLS.AddAction(new DelayLogicAction(0.575f)); + fireProjectileRandomLS.AddAction(new RunFunctionLogicAction(this, "ThrowRandomProjectiles")); + fireProjectileRandomLS.AddAction(new DelayLogicAction(0.575f)); + fireProjectileRandomLS.AddAction(new RunFunctionLogicAction(this, "ThrowRandomProjectiles")); + fireProjectileRandomLS.AddAction(new DelayLogicAction(0.575f)); + fireProjectileRandomLS.AddAction(new ChangeSpriteLogicAction("EnemyEyeballBossEye_Character", false, false)); + fireProjectileRandomLS.AddAction(new RunFunctionLogicAction(m_pupil, "ChangeSprite", "EnemyEyeballBossPupil_Sprite")); + fireProjectileRandomLS.AddAction(new RunFunctionLogicAction(this, "UnlockEyeball")); + fireProjectileRandomLS.Tag = GameTypes.LogicSetType_ATTACK; + + + LogicSet doNothing = new LogicSet(this); + doNothing.AddAction(new DelayLogicAction(0.2f, 0.5f)); + + + m_generalBasicLB.AddLogicSet(fireProjectileBasicLS, doNothing); + m_generalAdvancedLB.AddLogicSet(fireProjectileAdvancedLS, doNothing); + m_generalExpertLB.AddLogicSet(fireProjectileExpertLS, doNothing); + m_generalMiniBossLB.AddLogicSet(fireProjectileCardinalSpinLS, fireProjectileSprayLS, fireProjectileRandomLS, doNothing); + m_generalCooldownLB.AddLogicSet(doNothing); + + m_generalNeoLB.AddLogicSet(fireProjectileCardinalSpinNeoLS, fireProjectileSprayLS, fireProjectileRandomLS, doNothing); + + + logicBlocksToDispose.Add(m_generalNeoLB); + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalMiniBossLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + + + SetCooldownLogicBlock(m_generalCooldownLB, 100); //doNothing + + projData.Dispose(); // Don't forget to dispose the projectile data object. + + base.InitializeLogic(); + } + + private void ThrowThreeProjectiles(LogicSet ls) + { + ProjectileData expertData = new ProjectileData(this) + { + SpriteName = "EyeballProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = m_target, + Speed = new Vector2(this.ProjectileSpeed, this.ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = ProjectileScale, + Angle = new Vector2(0, 0), + }; + for (int i = 0; i <= 3; i++) + { + expertData.AngleOffset = 0; + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, expertData)); + expertData.AngleOffset = 45; + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, expertData)); + expertData.AngleOffset = -45; + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, expertData)); + ls.AddAction(new DelayLogicAction(0.1f)); + } + expertData.Dispose(); + } + + private void ThrowCardinalProjectiles(LogicSet ls) + { + ProjectileData cardinalData = new ProjectileData(this) + { + SpriteName = "EyeballProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(this.ProjectileSpeed, this.ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Scale = ProjectileScale, + CollidesWithTerrain = false, + Angle = new Vector2(0, 0), + }; + + int flipper = CDGMath.RandomPlusMinus(); + for (int i = 0; i <= 170; i = i + 10) + { + cardinalData.AngleOffset = 0 + i * flipper; + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, cardinalData)); + cardinalData.AngleOffset = 90 + i * flipper; + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, cardinalData)); + cardinalData.AngleOffset = 180 + i * flipper; + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, cardinalData)); + cardinalData.AngleOffset = 270 + i * flipper; + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, cardinalData)); + ls.AddAction(new DelayLogicAction(0.175f)); + } + + cardinalData.Dispose(); + } + + public void ThrowCardinalProjectiles(int startProjIndex, bool randomizeFlipper, int flipper) + { + if (startProjIndex < 17) + { + ProjectileData cardinalData = new ProjectileData(this) + { + SpriteName = "EyeballProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(this.ProjectileSpeed, this.ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Scale = ProjectileScale, + CollidesWithTerrain = false, + Angle = new Vector2(0, 0), + }; + + if (randomizeFlipper == true) + flipper = CDGMath.RandomPlusMinus(); + + cardinalData.AngleOffset = -10 + (startProjIndex * 10) * flipper; + m_levelScreen.ProjectileManager.FireProjectile(cardinalData); + cardinalData.AngleOffset = 80 + (startProjIndex * 10) * flipper; + m_levelScreen.ProjectileManager.FireProjectile(cardinalData); + cardinalData.AngleOffset = 170 + (startProjIndex * 10) * flipper; + m_levelScreen.ProjectileManager.FireProjectile(cardinalData); + cardinalData.AngleOffset = 260 + (startProjIndex * 10) * flipper; + m_levelScreen.ProjectileManager.FireProjectile(cardinalData); + + cardinalData.Dispose(); + + startProjIndex++; + Tween.RunFunction(0.12f, this, "ThrowCardinalProjectiles", startProjIndex, false, flipper); + } + } + + public void ThrowCardinalProjectilesNeo(int startProjIndex, bool randomizeFlipper, int flipper) + { + if (startProjIndex < 13)//12)//17) + { + ProjectileData cardinalData = new ProjectileData(this) + { + SpriteName = "EyeballProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(this.ProjectileSpeed, this.ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Scale = ProjectileScale, + CollidesWithTerrain = false, + Angle = new Vector2(0, 0), + }; + + if (randomizeFlipper == true) + flipper = CDGMath.RandomPlusMinus(); + + cardinalData.AngleOffset = -10 + (startProjIndex * 17) * flipper; + m_levelScreen.ProjectileManager.FireProjectile(cardinalData); + cardinalData.AngleOffset = 80 + (startProjIndex * 17) * flipper; + m_levelScreen.ProjectileManager.FireProjectile(cardinalData); + cardinalData.AngleOffset = 170 + (startProjIndex * 17) * flipper; + m_levelScreen.ProjectileManager.FireProjectile(cardinalData); + cardinalData.AngleOffset = 260 + (startProjIndex * 17) * flipper; + m_levelScreen.ProjectileManager.FireProjectile(cardinalData); + + cardinalData.Dispose(); + + startProjIndex++; + Tween.RunFunction(0.12f, this, "ThrowCardinalProjectilesNeo", startProjIndex, false, flipper); + } + } + + + public void LockEyeball() + { + Tweener.Tween.To(this, 0.5f, Tweener.Ease.Quad.EaseInOut, "PupilOffset", "0"); + } + + public void UnlockEyeball() + { + Tweener.Tween.To(this, 0.5f, Tweener.Ease.Quad.EaseInOut, "PupilOffset", "30"); + } + + public void ChangeToBossPupil() + { + m_pupil.ChangeSprite("EnemyEyeballBossPupil_Sprite"); + m_pupil.Scale = new Vector2(0.9f, 0.9f); + } + + public void ThrowSprayProjectiles(bool firstShot) + { + ProjectileData starData = new ProjectileData(this) + { + SpriteName = "EyeballProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(this.ProjectileSpeed, this.ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(0, 0), + CollidesWithTerrain = false, + Scale = ProjectileScale, + }; + + int y = 360 / 12; + for (int i = 0; i <= 360; i = i + y) + { + if (firstShot== true) + starData.AngleOffset = 10 + i; + else + starData.AngleOffset = 20 + i; + + m_levelScreen.ProjectileManager.FireProjectile(starData); + } + + if (firstShot == true) + { + Tween.RunFunction(0.8f, this, "ThrowSprayProjectiles", false); + } + + //int y = 360 / 12; //12; + //for (int k = 0; k < 2; k++) + //{ + // starData.AngleOffset = 0; + // for (int i = 0; i <= 360; i = i + y) + // { + // starData.AngleOffset = 10 + i; + // m_levelScreen.ProjectileManager.FireProjectile(starData); + // //ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, starData)); + + // } + + // ls.AddAction(new DelayLogicAction(0.8f)); + // for (int i = 0; i <= 360; i = i + y) + // { + // starData.AngleOffset = 20 + i; + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, starData)); + // } + // ls.AddAction(new DelayLogicAction(0.8f)); + //} + starData.Dispose(); + } + + public void ThrowRandomProjectiles() + { + ProjectileData RandomBullet = new ProjectileData(this) + { + SpriteName = "EyeballProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(this.ProjectileSpeed, this.ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(0, 0), + CollidesWithTerrain = false, + Scale = ProjectileScale, + }; + + //for (int k = 0; k < 5; k++) + { + RandomBullet.Angle = new Vector2(0, 44); + m_levelScreen.ProjectileManager.FireProjectile(RandomBullet); + RandomBullet.Angle = new Vector2(45, 89); + m_levelScreen.ProjectileManager.FireProjectile(RandomBullet); + RandomBullet.Angle = new Vector2(90, 134); + m_levelScreen.ProjectileManager.FireProjectile(RandomBullet); + RandomBullet.Angle = new Vector2(135, 179); + m_levelScreen.ProjectileManager.FireProjectile(RandomBullet); + RandomBullet.Angle = new Vector2(180, 224); + m_levelScreen.ProjectileManager.FireProjectile(RandomBullet); + RandomBullet.Angle = new Vector2(225, 269); + m_levelScreen.ProjectileManager.FireProjectile(RandomBullet); + RandomBullet.Angle = new Vector2(270, 314); + m_levelScreen.ProjectileManager.FireProjectile(RandomBullet); + RandomBullet.Angle = new Vector2(315, 359); + m_levelScreen.ProjectileManager.FireProjectile(RandomBullet); +// ls.AddAction(new DelayLogicAction(0.575f)); + } + RandomBullet.Dispose(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 100, 0); + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 100); + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 100, 0); + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalAdvancedLB, 0, 100); + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 100, 0); + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalExpertLB, 0, 100); + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + if (IsNeo == false) + RunLogicBlock(true, m_generalMiniBossLB, 40, 20, 40, 0); //fireProjectileCardinalSpinLS, fireProjectileSprayLS, fireProjectileRandomLS, doNothing + else + RunLogicBlock(false, m_generalNeoLB, 53, 12, 35, 0); //fireProjectileCardinalSpinLS, fireProjectileSprayLS, fireProjectileRandomLS, doNothing + break; + default: + break; + } + } + + public EnemyObj_Eyeball(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyEyeballIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + m_pupil = new SpriteObj("EnemyEyeballPupil_Sprite"); + this.AddChild(m_pupil); + //m_squishSound = new FrameSoundObj(this, 2, "EyeballSquish1", "EyeballSquish2", "EyeballSquish3"); + m_squishSound = new FrameSoundObj(this, m_target, 2, "Eyeball_Prefire"); + this.Type = EnemyType.Eyeball; + this.DisableCollisionBoxRotations = false; + } + + public override void Update(GameTime gameTime) + { + if (m_playDeathLoop == true) + { + if (m_deathLoop == null || m_deathLoop.IsPlaying == false) + m_deathLoop = SoundManager.PlaySound("Boss_Eyeball_Death_Loop"); + } + + float y = m_target.Y - this.Y; + float x = m_target.X - this.X; + float angle = (float)Math.Atan2(y, x); + + m_pupil.X = (float)Math.Cos(angle) * PupilOffset; + m_pupil.Y = (float)Math.Sin(angle) * PupilOffset; + + if (m_shake == true) + { + if (m_shakeTimer > 0) + { + m_shakeTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_shakeTimer <= 0) + { + m_shakeTimer = m_shakeDuration; + if (m_shookLeft == true) + { + m_shookLeft = false; + this.X += 5; + } + else + { + this.X -= 5; + m_shookLeft = true; + } + } + } + } + + m_squishSound.Update(); + + base.Update(gameTime); + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + // Hits the player in Tanooki mode. + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS && m_bossVersionKilled == false) + { + PlayerObj player = otherBox.AbsParent as PlayerObj; + if (player != null && otherBox.Type == Consts.WEAPON_HITBOX && player.IsInvincible == false && player.State == PlayerObj.STATE_TANOOKI) + player.HitPlayer(this); + } + + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + public override void HitEnemy(int damage, Vector2 position, bool isPlayer) + { + if (m_bossVersionKilled == false) + { + SoundManager.PlaySound("EyeballSquish1", "EyeballSquish2", "EyeballSquish3"); + base.HitEnemy(damage, position, isPlayer); + } + } + + public override void Kill(bool giveXP = true) + { + if (Difficulty != GameTypes.EnemyDifficulty.MINIBOSS) + { + //SoundManager.PlaySound("EyeballDeath1", "EyeballDeath2"); + base.Kill(giveXP); + } + else + { + if (m_target.CurrentHealth > 0) + { + Game.PlayerStats.EyeballBossBeaten = true; + + Tween.StopAllContaining(this, false); + if (m_currentActiveLB != null && m_currentActiveLB.IsActive == true) + m_currentActiveLB.StopLogicBlock(); + + SoundManager.StopMusic(0); + m_bossVersionKilled = true; + m_target.LockControls(); + m_levelScreen.PauseScreen(); + m_levelScreen.ProjectileManager.DestroyAllProjectiles(false); + m_levelScreen.RunWhiteSlashEffect(); + SoundManager.PlaySound("Boss_Flash"); + SoundManager.PlaySound("Boss_Eyeball_Freeze"); + Tween.RunFunction(1f, this, "Part2"); + + GameUtil.UnlockAchievement("FEAR_OF_EYES"); + } + } + } + + public void Part2() + { + m_levelScreen.UnpauseScreen(); + m_target.UnlockControls(); + + if (m_currentActiveLB != null) + m_currentActiveLB.StopLogicBlock(); + + LockEyeball(); + this.PauseEnemy(true); + this.ChangeSprite("EnemyEyeballBossFire_Character"); + this.PlayAnimation(true); + m_target.CurrentSpeed = 0; + m_target.ForceInvincible = true; + + if (IsNeo == true) + m_target.InvincibleToSpikes = true; + + Tween.To(m_levelScreen.Camera, 0.5f, Tweener.Ease.Quad.EaseInOut, "X", m_levelScreen.CurrentRoom.Bounds.Center.X.ToString(), "Y", m_levelScreen.CurrentRoom.Bounds.Center.Y.ToString()); + m_shake = true; + m_shakeTimer = m_shakeDuration; + m_playDeathLoop = true; + + for (int i = 0; i < 40; i++) + { + Vector2 explosionPos = new Vector2(CDGMath.RandomInt(this.Bounds.Left, this.Bounds.Right), CDGMath.RandomInt(this.Bounds.Top, this.Bounds.Bottom)); + Tween.RunFunction(i * 0.1f, typeof(SoundManager), "Play3DSound", this, m_target, new string[]{"Boss_Explo_01", "Boss_Explo_02", "Boss_Explo_03"}); + Tween.RunFunction(i * 0.1f, m_levelScreen.ImpactEffectPool, "DisplayExplosionEffect", explosionPos); + } + + Tween.AddEndHandlerToLastTween(this, "Part3"); + + if (IsNeo == false) + { + int totalGold = m_bossCoins + m_bossMoneyBags + m_bossDiamonds; + List goldArray = new List(); + + for (int i = 0; i < m_bossCoins; i++) + goldArray.Add(0); + for (int i = 0; i < m_bossMoneyBags; i++) + goldArray.Add(1); + for (int i = 0; i < m_bossDiamonds; i++) + goldArray.Add(2); + + CDGMath.Shuffle(goldArray); + float coinDelay = 2.5f / goldArray.Count; // The enemy dies for 2.5 seconds. + + for (int i = 0; i < goldArray.Count; i++) + { + Vector2 goldPos = new Vector2(CDGMath.RandomInt(m_pupil.AbsBounds.Left, m_pupil.AbsBounds.Right), CDGMath.RandomInt(m_pupil.AbsBounds.Top, m_pupil.AbsBounds.Bottom)); + if (goldArray[i] == 0) + Tween.RunFunction(i * coinDelay, m_levelScreen.ItemDropManager, "DropItem", goldPos, ItemDropType.Coin, ItemDropType.CoinAmount); + else if (goldArray[i] == 1) + Tween.RunFunction(i * coinDelay, m_levelScreen.ItemDropManager, "DropItem", goldPos, ItemDropType.MoneyBag, ItemDropType.MoneyBagAmount); + else + Tween.RunFunction(i * coinDelay, m_levelScreen.ItemDropManager, "DropItem", goldPos, ItemDropType.Diamond, ItemDropType.DiamondAmount); + } + } + } + + public void Part3() + { + SoundManager.PlaySound("Boss_Eyeball_Death"); + m_playDeathLoop = false; + if (m_deathLoop != null && m_deathLoop.IsPlaying == true) + m_deathLoop.Stop(AudioStopOptions.Immediate); + this.GoToFrame(1); + this.StopAnimation(); + Tween.To(this, 2, Tweener.Tween.EaseNone, "Rotation", "-1080"); + Tween.To(this, 2, Tweener.Ease.Quad.EaseInOut, "ScaleX", "0.1", "ScaleY", "0.1"); + Tween.AddEndHandlerToLastTween(this, "DeathComplete"); + } + + public void DeathComplete() + { + SoundManager.PlaySound("Boss_Explo_01", "Boss_Explo_02", "Boss_Explo_03"); + base.Kill(); + } + + public bool BossVersionKilled + { + get { return m_bossVersionKilled; } + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_pupil.Dispose(); + m_pupil = null; + m_squishSound.Dispose(); + m_squishSound = null; + if (m_deathLoop != null && m_deathLoop.IsDisposed == false) + m_deathLoop.Dispose(); + m_deathLoop = null; + base.Dispose(); + } + } + + public bool IsNeo + { + get { return m_isNeo; } + set + { + if (value == true) + { + HealthGainPerLevel = 0; + DamageGainPerLevel = 0; + MoneyDropChance = 0; + ItemDropChance = 0; + m_saveToEnemiesKilledList = false; + } + m_isNeo = value; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Fairy.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Fairy.cs new file mode 100644 index 0000000..7691a21 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Fairy.cs @@ -0,0 +1,894 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Microsoft.Xna.Framework.Audio; + +namespace RogueCastle +{ + public class EnemyObj_Fairy : EnemyObj + { + //private float SeparationDistance = 650f; // The distance that bats stay away from other enemies. + + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + private LogicBlock m_generalNeoLB = new LogicBlock(); + + private bool m_isNeo = false; + + private float AttackDelay = 0.5f; + + public bool MainFairy { get; set; } + public RoomObj SpawnRoom; + public Vector2 SavedStartingPos { get; set; } + public int NumHits = 1; + + private bool m_shake = false; + private bool m_shookLeft = false; + private float m_shakeTimer = 0; + private float m_shakeDuration = 0.03f; + + //3500 + private int m_bossCoins = 30; + private int m_bossMoneyBags = 12; + private int m_bossDiamonds = 2; + + private Cue m_deathLoop; + private bool m_playDeathLoop; + + private int m_numSummons = 22;//25;//30; + private float m_summonTimer = 6; + private float m_summonCounter = 6; + private float m_summonTimerNeo = 3;//3;//10000; + + protected override void InitializeEV() + { + #region Basic Variables - General + Name = EnemyEV.Fairy_Basic_Name; + LocStringID = EnemyEV.Fairy_Basic_Name_locID; + + MaxHealth = EnemyEV.Fairy_Basic_MaxHealth; + Damage = EnemyEV.Fairy_Basic_Damage; + XPValue = EnemyEV.Fairy_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Fairy_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Fairy_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Fairy_Basic_DropChance; + + Speed = EnemyEV.Fairy_Basic_Speed; + TurnSpeed = EnemyEV.Fairy_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Fairy_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Fairy_Basic_Jump; + CooldownTime = EnemyEV.Fairy_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Fairy_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Fairy_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Fairy_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Fairy_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Fairy_Basic_IsWeighted; + + Scale = EnemyEV.Fairy_Basic_Scale; + ProjectileScale = EnemyEV.Fairy_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Fairy_Basic_Tint; + + MeleeRadius = EnemyEV.Fairy_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Fairy_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Fairy_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Fairy_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Fairy_Miniboss_Name; + LocStringID = EnemyEV.Fairy_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Fairy_Miniboss_MaxHealth; + Damage = EnemyEV.Fairy_Miniboss_Damage; + XPValue = EnemyEV.Fairy_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Fairy_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Fairy_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Fairy_Miniboss_DropChance; + + Speed = EnemyEV.Fairy_Miniboss_Speed; + TurnSpeed = EnemyEV.Fairy_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Fairy_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Fairy_Miniboss_Jump; + CooldownTime = EnemyEV.Fairy_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Fairy_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Fairy_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Fairy_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Fairy_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Fairy_Miniboss_IsWeighted; + + Scale = new Vector2(2.5f, 2.5f);//EnemyEV.Fairy_Miniboss_Scale; + ProjectileScale = new Vector2(2f,2f);//EnemyEV.Fairy_Miniboss_ProjectileScale; + //TintablePart.TextureColor = EnemyEV.Fairy_Miniboss_Tint; + + MeleeRadius = EnemyEV.Fairy_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Fairy_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Fairy_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Fairy_Miniboss_KnockBack; + + NumHits = 1; + #endregion + if (LevelEV.WEAKEN_BOSSES == true) + this.MaxHealth = 1; + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.Fairy_Expert_Name; + LocStringID = EnemyEV.Fairy_Expert_Name_locID; + + MaxHealth = EnemyEV.Fairy_Expert_MaxHealth; + Damage = EnemyEV.Fairy_Expert_Damage; + XPValue = EnemyEV.Fairy_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Fairy_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Fairy_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Fairy_Expert_DropChance; + + Speed = EnemyEV.Fairy_Expert_Speed; + TurnSpeed = EnemyEV.Fairy_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Fairy_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Fairy_Expert_Jump; + CooldownTime = EnemyEV.Fairy_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Fairy_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Fairy_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Fairy_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Fairy_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Fairy_Expert_IsWeighted; + + Scale = EnemyEV.Fairy_Expert_Scale; + ProjectileScale = EnemyEV.Fairy_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Fairy_Expert_Tint; + + MeleeRadius = EnemyEV.Fairy_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Fairy_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Fairy_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Fairy_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.Fairy_Advanced_Name; + LocStringID = EnemyEV.Fairy_Advanced_Name_locID; + + MaxHealth = EnemyEV.Fairy_Advanced_MaxHealth; + Damage = EnemyEV.Fairy_Advanced_Damage; + XPValue = EnemyEV.Fairy_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Fairy_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Fairy_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Fairy_Advanced_DropChance; + + Speed = EnemyEV.Fairy_Advanced_Speed; + TurnSpeed = EnemyEV.Fairy_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Fairy_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Fairy_Advanced_Jump; + CooldownTime = EnemyEV.Fairy_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Fairy_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Fairy_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Fairy_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Fairy_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Fairy_Advanced_IsWeighted; + + Scale = EnemyEV.Fairy_Advanced_Scale; + ProjectileScale = EnemyEV.Fairy_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Fairy_Advanced_Tint; + + MeleeRadius = EnemyEV.Fairy_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Fairy_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Fairy_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Fairy_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + m_resetSpriteName = "EnemyFairyGhostBossIdle_Character"; + } + + protected override void InitializeLogic() + { + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostMove_Character", true, true)); + walkTowardsLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"FairyMove1", "FairyMove2", "FairyMove3")); + walkTowardsLS.AddAction(new ChaseLogicAction(m_target, true, 1.0f)); + + LogicSet walkAwayLS = new LogicSet(this); + walkAwayLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostIdle_Character", true, true)); + walkAwayLS.AddAction(new ChaseLogicAction(m_target, false, 0.5f)); + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(0.5f, 0.75f)); + + LogicSet fireProjectilesLS = new LogicSet(this); + fireProjectilesLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostIdle_Character", true, true)); + fireProjectilesLS.AddAction(new MoveLogicAction(m_target, true, 0)); + fireProjectilesLS.AddAction(new LockFaceDirectionLogicAction(true)); + fireProjectilesLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostShoot_Character", false, false)); + fireProjectilesLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + fireProjectilesLS.AddAction(new DelayLogicAction(AttackDelay)); + fireProjectilesLS.AddAction(new RunFunctionLogicAction(this, "ThrowFourProjectiles", false)); + fireProjectilesLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + fireProjectilesLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostIdle_Character", true, true)); + fireProjectilesLS.AddAction(new DelayLogicAction(0.25f)); + fireProjectilesLS.AddAction(new LockFaceDirectionLogicAction(false)); + fireProjectilesLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet fireProjectilesAdvancedLS = new LogicSet(this); + fireProjectilesAdvancedLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostIdle_Character", true, true)); + fireProjectilesAdvancedLS.AddAction(new MoveLogicAction(m_target, true, 0)); + fireProjectilesAdvancedLS.AddAction(new LockFaceDirectionLogicAction(true)); + fireProjectilesAdvancedLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostShoot_Character", false, false)); + fireProjectilesAdvancedLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + fireProjectilesAdvancedLS.AddAction(new DelayLogicAction(AttackDelay)); + fireProjectilesAdvancedLS.AddAction(new RunFunctionLogicAction(this, "ThrowFourProjectiles", false)); + fireProjectilesAdvancedLS.AddAction(new DelayLogicAction(0.15f)); + fireProjectilesAdvancedLS.AddAction(new RunFunctionLogicAction(this, "ThrowFourProjectiles", false)); + fireProjectilesAdvancedLS.AddAction(new DelayLogicAction(0.15f)); + fireProjectilesAdvancedLS.AddAction(new RunFunctionLogicAction(this, "ThrowFourProjectiles", false)); + fireProjectilesAdvancedLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + fireProjectilesAdvancedLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostIdle_Character", true, true)); + fireProjectilesAdvancedLS.AddAction(new DelayLogicAction(0.25f)); + fireProjectilesAdvancedLS.AddAction(new LockFaceDirectionLogicAction(false)); + fireProjectilesAdvancedLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet fireProjectilesExpertLS = new LogicSet(this); + fireProjectilesExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostIdle_Character", true, true)); + fireProjectilesExpertLS.AddAction(new MoveLogicAction(m_target, true, 0)); + fireProjectilesExpertLS.AddAction(new LockFaceDirectionLogicAction(true)); + fireProjectilesExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostShoot_Character", false, false)); + fireProjectilesExpertLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + fireProjectilesExpertLS.AddAction(new DelayLogicAction(AttackDelay)); + ThrowEightProjectiles(fireProjectilesExpertLS); + fireProjectilesExpertLS.AddAction(new DelayLogicAction(0.25f)); + ThrowEightProjectiles(fireProjectilesExpertLS); + fireProjectilesExpertLS.AddAction(new DelayLogicAction(0.25f)); + ThrowEightProjectiles(fireProjectilesExpertLS); + fireProjectilesExpertLS.AddAction(new DelayLogicAction(0.25f)); + ThrowEightProjectiles(fireProjectilesExpertLS); + fireProjectilesExpertLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + + fireProjectilesExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostIdle_Character", true, true)); + fireProjectilesExpertLS.AddAction(new DelayLogicAction(0.25f)); + fireProjectilesExpertLS.AddAction(new LockFaceDirectionLogicAction(false)); + fireProjectilesExpertLS.Tag = GameTypes.LogicSetType_ATTACK; + + // MINIBOSS CODE + + LogicSet walkTowardsMinibossLS = new LogicSet(this); + walkTowardsMinibossLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostBossMove_Character", true, true)); + walkTowardsMinibossLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"FairyMove1", "FairyMove2", "FairyMove3")); + walkTowardsMinibossLS.AddAction(new ChaseLogicAction(m_target, true, 1.0f)); + + LogicSet walkAwayMinibossLS = new LogicSet(this); + walkAwayMinibossLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostBossIdle_Character", true, true)); + walkAwayMinibossLS.AddAction(new ChaseLogicAction(m_target, false, 0.5f)); + + LogicSet walkStopMinibossLS = new LogicSet(this); + walkStopMinibossLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopMinibossLS.AddAction(new DelayLogicAction(0.5f, 0.75f)); + + LogicSet fireProjectilesMinibossLS = new LogicSet(this); + fireProjectilesMinibossLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostBossIdle_Character", true, true)); + fireProjectilesMinibossLS.AddAction(new MoveLogicAction(m_target, true, 0)); + fireProjectilesMinibossLS.AddAction(new LockFaceDirectionLogicAction(true)); + fireProjectilesMinibossLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostBossShoot_Character", false, false)); + fireProjectilesMinibossLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + fireProjectilesMinibossLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostBossIdle_Character", true, true)); + fireProjectilesMinibossLS.AddAction(new DelayLogicAction(AttackDelay)); + fireProjectilesMinibossLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostBossShoot_Character", false, false)); + fireProjectilesMinibossLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + fireProjectilesMinibossLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostBossMove_Character", true, true)); + fireProjectilesMinibossLS.AddAction(new RunFunctionLogicAction(this, "ThrowFourProjectiles", true)); + fireProjectilesMinibossLS.AddAction(new DelayLogicAction(0.25f)); + fireProjectilesMinibossLS.AddAction(new RunFunctionLogicAction(this, "ThrowFourProjectiles", true)); + fireProjectilesMinibossLS.AddAction(new DelayLogicAction(0.25f)); + fireProjectilesMinibossLS.AddAction(new RunFunctionLogicAction(this, "ThrowFourProjectiles", true)); + fireProjectilesMinibossLS.AddAction(new DelayLogicAction(0.25f)); + fireProjectilesMinibossLS.AddAction(new RunFunctionLogicAction(this, "ThrowFourProjectiles", true)); + fireProjectilesMinibossLS.AddAction(new DelayLogicAction(0.25f)); + fireProjectilesMinibossLS.AddAction(new RunFunctionLogicAction(this, "ThrowFourProjectiles", true)); + fireProjectilesMinibossLS.AddAction(new DelayLogicAction(0.25f)); + fireProjectilesMinibossLS.AddAction(new RunFunctionLogicAction(this, "ThrowFourProjectiles", true)); + fireProjectilesMinibossLS.AddAction(new ChangeSpriteLogicAction("EnemyFairyGhostBossIdle_Character", true, true)); + fireProjectilesMinibossLS.AddAction(new DelayLogicAction(0.25f)); + fireProjectilesMinibossLS.AddAction(new LockFaceDirectionLogicAction(false)); + fireProjectilesMinibossLS.Tag = GameTypes.LogicSetType_ATTACK; + + m_generalBasicLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesLS); + m_generalAdvancedLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesAdvancedLS); + m_generalExpertLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesExpertLS); + m_generalMiniBossLB.AddLogicSet(walkTowardsMinibossLS, walkAwayMinibossLS, walkStopMinibossLS, fireProjectilesMinibossLS); + + m_generalNeoLB.AddLogicSet(walkTowardsMinibossLS, walkAwayMinibossLS, walkStopMinibossLS, fireProjectilesMinibossLS); + + if (Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + m_generalCooldownLB.AddLogicSet(walkTowardsMinibossLS, walkAwayMinibossLS, walkStopMinibossLS); + else + m_generalCooldownLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalMiniBossLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + logicBlocksToDispose.Add(m_generalNeoLB); + + SetCooldownLogicBlock(m_generalCooldownLB, 70, 30, 0); //walkTowardsLS, walkAwayLS, walkStopLS + + base.InitializeLogic(); + } + + public void ThrowFourProjectiles(bool useBossProjectile) + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "GhostProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(0, 0), + CollidesWithTerrain = false, + Scale = ProjectileScale, + + }; + + if (useBossProjectile == true) + projData.SpriteName = "GhostProjectileBoss_Sprite"; + + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "Boss_Flameskull_Roar_01", "Boss_Flameskull_Roar_02", "Boss_Flameskull_Roar_03"); + else + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "FairyAttack1"); + + m_levelScreen.ProjectileManager.FireProjectile(projData); + projData.Angle = new Vector2(90, 90); + m_levelScreen.ProjectileManager.FireProjectile(projData); + projData.Angle = new Vector2(180, 180); + m_levelScreen.ProjectileManager.FireProjectile(projData); + projData.Angle = new Vector2(-90, -90); + m_levelScreen.ProjectileManager.FireProjectile(projData); + + projData.Dispose(); + } + + //private void ThrowFourProjectiles(LogicSet ls, bool useBossProjectile = false) + //{ + // ProjectileData projData = new ProjectileData(this) + // { + // SpriteName = "GhostProjectile_Sprite", + // SourceAnchor = Vector2.Zero, + // Target = null, + // Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + // IsWeighted = false, + // RotationSpeed = 0, + // Damage = Damage, + // AngleOffset = 0, + // Angle = new Vector2(0, 0), + // CollidesWithTerrain = false, + // Scale = ProjectileScale, + + // }; + + // if (useBossProjectile == true) + // projData.SpriteName = "GhostProjectileBoss_Sprite"; + + // if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + // ls.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "Boss_Flameskull_Roar_01", "Boss_Flameskull_Roar_02", "Boss_Flameskull_Roar_03")); + // else + // ls.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "FairyAttack1")); + + // ls.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"FairyAttack1")); + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // projData.Angle = new Vector2(90, 90); + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // projData.Angle = new Vector2(180, 180); + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // projData.Angle = new Vector2(-90, -90); + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // //ls.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnightAttack1")); + // projData.Dispose(); + //} + + + private void ThrowEightProjectiles(LogicSet ls) + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "GhostProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(0, 0), + CollidesWithTerrain = false, + Scale = ProjectileScale, + }; + + ls.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"FairyAttack1")); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(90, 90); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(180, 180); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-90, -90); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + + ls.AddAction(new DelayLogicAction(0.125f)); + ls.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"FairyAttack1")); + projData.Angle = new Vector2(135, 135); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(45, 45); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-45, -45); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-135, -135); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Dispose(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 50, 10, 0, 40); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100, 0); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesLS + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 50, 10, 0, 40); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesAdvancedLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 100, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesAdvancedLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalAdvancedLB, 0, 0, 100, 0); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesAdvancedLS + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 50, 10, 0, 40); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesAdvancedLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 100, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesAdvancedLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalExpertLB, 0, 0, 100, 0); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesAdvancedLS + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + if (IsNeo == false) + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalMiniBossLB, 50, 10, 0, 40); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalMiniBossLB, 100, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalMiniBossLB, 80, 20, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesLS + break; + default: + break; + } + } + else + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalNeoLB, 50, 10, 0, 40); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalNeoLB, 100, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalNeoLB, 80, 20, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, fireProjectilesLS + break; + default: + break; + } + } + } + + public override void Update(GameTime gameTime) + { + float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds; + + if (Difficulty == GameTypes.EnemyDifficulty.MINIBOSS && IsPaused == false) + { + if (m_summonCounter > 0) + { + m_summonCounter -= elapsedTime; + if (m_summonCounter <= 0) + { + if (IsNeo == true) + m_summonTimer = m_summonTimerNeo; + m_summonCounter = m_summonTimer; + NumHits--; + if (IsKilled == false && NumHits <= 0 && m_levelScreen.CurrentRoom.ActiveEnemies <= m_numSummons + 1) + { + if (Game.PlayerStats.TimesCastleBeaten <= 0 || this.IsNeo == true) + { + CreateFairy(GameTypes.EnemyDifficulty.BASIC); + CreateFairy(GameTypes.EnemyDifficulty.BASIC); + } + else + { + CreateFairy(GameTypes.EnemyDifficulty.ADVANCED); + CreateFairy(GameTypes.EnemyDifficulty.ADVANCED); + } + NumHits = 1; + } + } + } + + // Make sure Alexander doesn't move too much around the borders of the room. + RoomObj currentRoom = m_levelScreen.CurrentRoom; + Rectangle enemyBounds = this.Bounds; + Rectangle roomBounds = currentRoom.Bounds; + + int rightBounds = enemyBounds.Right - roomBounds.Right; + int leftBounds = enemyBounds.Left - roomBounds.Left; + //int topBounds = enemyBounds.Top - roomBounds.Top - 20; + int bottomBounds = enemyBounds.Bottom - roomBounds.Bottom; + + if (rightBounds > 0) + this.X -= rightBounds; + if (leftBounds < 0) + this.X -= leftBounds; + //if (topBounds < 0) + // this.Y -= topBounds; + if (bottomBounds > 0) + this.Y -= bottomBounds; + } + + //// Flocking code for flying bats. + //foreach (EnemyObj enemyToAvoid in m_levelScreen.EnemyList) // Can speed up efficiency if the level had a property that returned the number of enemies in a single room. + //{ + // if (enemyToAvoid != this) + // { + // float distanceFromOtherEnemy = Vector2.Distance(this.Position, enemyToAvoid.Position); + // if (distanceFromOtherEnemy < this.SeparationDistance) + // { + // this.CurrentSpeed = .50f * this.Speed; // Move away at half speed. + // Vector2 seekPosition = 2 * this.Position - enemyToAvoid.Position; + // CDGMath.TurnToFace(this, seekPosition); + // } + // } + //} + + //this.Heading = new Vector2( + // (float)Math.Cos(Orientation), (float)Math.Sin(Orientation)); + + if (m_shake == true) + { + if (m_shakeTimer > 0) + { + m_shakeTimer -= elapsedTime; + if (m_shakeTimer <= 0) + { + m_shakeTimer = m_shakeDuration; + if (m_shookLeft == true) + { + m_shookLeft = false; + this.X += 5; + } + else + { + this.X -= 5; + m_shookLeft = true; + } + } + } + } + + if (m_playDeathLoop == true) + { + if (m_deathLoop != null && m_deathLoop.IsPlaying == false) + m_deathLoop = SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Boss_Flameskull_Death_Loop"); + } + + base.Update(gameTime); + } + + public EnemyObj_Fairy(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyFairyGhostIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.PlayAnimation(true); + MainFairy = true; + TintablePart = _objectList[0]; + this.Type = EnemyType.Fairy; + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + // Hits the player in Tanooki mode. + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS && m_bossVersionKilled == false) + { + PlayerObj player = otherBox.AbsParent as PlayerObj; + if (player != null && otherBox.Type == Consts.WEAPON_HITBOX && player.IsInvincible == false && player.State == PlayerObj.STATE_TANOOKI) + player.HitPlayer(this); + } + + + if (collisionResponseType != Consts.COLLISIONRESPONSE_TERRAIN) // Disable terrain collision + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + private void CreateFairy(GameTypes.EnemyDifficulty difficulty) + { + EnemyObj_Fairy fairy = new EnemyObj_Fairy(null, null, null, difficulty); + fairy.Position = this.Position; + fairy.DropsItem = false; + if (m_target.X < fairy.X) + fairy.Orientation = MathHelper.ToRadians(0); + else + fairy.Orientation = MathHelper.ToRadians(180); + + fairy.Level = this.Level - LevelEV.ENEMY_MINIBOSS_LEVEL_MOD - 1; // Must be called before AddEnemyToCurrentRoom() to initialize levels properly. + m_levelScreen.AddEnemyToCurrentRoom(fairy); + fairy.PlayAnimation(true); + + fairy.MainFairy = false; + fairy.SavedStartingPos = fairy.Position; + fairy.SaveToFile = false; + if (LevelEV.SHOW_ENEMY_RADII == true) + fairy.InitializeDebugRadii(); + fairy.SpawnRoom = m_levelScreen.CurrentRoom; + fairy.GivesLichHealth = false; + + //if (this.IsPaused) + // fairy.PauseEnemy(); + } + + public override void HitEnemy(int damage, Vector2 position, bool isPlayer) + { + if (m_bossVersionKilled == false) + { + base.HitEnemy(damage, position, isPlayer); + + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "SkeletonAttack1"); + //if (Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + //{ + // NumHits--; + // if (IsKilled == false && NumHits <= 0 && m_levelScreen.CurrentRoom.ActiveEnemies <= m_numSummons + 1) + // { + // CreateFairy(GameTypes.EnemyDifficulty.BASIC); + // CreateFairy(GameTypes.EnemyDifficulty.BASIC); + // NumHits = 1; + // } + //} + //else if (Difficulty == GameTypes.EnemyDifficulty.EXPERT) + //{ + // //m_levelScreen.ProjectileManager.FireProjectile("GhostProjectile_Sprite", this, Vector2.Zero, 0, ProjectileSpeed, false, 0, ProjectileDamage); + // //m_levelScreen.ProjectileManager.FireProjectile("GhostProjectile_Sprite", this, Vector2.Zero, 90, ProjectileSpeed, false, 0, ProjectileDamage); + // //m_levelScreen.ProjectileManager.FireProjectile("GhostProjectile_Sprite", this, Vector2.Zero, 180, ProjectileSpeed, false, 0, ProjectileDamage); + // //m_levelScreen.ProjectileManager.FireProjectile("GhostProjectile_Sprite", this, Vector2.Zero, -90, ProjectileSpeed, false, 0, ProjectileDamage); + + //} + } + } + + public override void Kill(bool giveXP = true) + { + if (Difficulty != GameTypes.EnemyDifficulty.MINIBOSS) + { + //SoundManager.Play3DSound(this, Game.ScreenManager.Player,"EyeballDeath1", "EyeballDeath2"); + base.Kill(giveXP); + } + else + { + if (m_target.CurrentHealth > 0) + { + Game.PlayerStats.FairyBossBeaten = true; + + SoundManager.StopMusic(0); + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "PressStart"); + m_bossVersionKilled = true; + m_target.LockControls(); + m_levelScreen.PauseScreen(); + m_levelScreen.ProjectileManager.DestroyAllProjectiles(false); + m_levelScreen.RunWhiteSlashEffect(); + Tween.RunFunction(1f, this, "Part2"); + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "Boss_Flash"); + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "Boss_Flameskull_Freeze"); + + GameUtil.UnlockAchievement("FEAR_OF_GHOSTS"); + } + } + } + + public void Part2() + { + m_playDeathLoop = true; + + foreach (EnemyObj enemy in m_levelScreen.CurrentRoom.TempEnemyList) + { + if (enemy.IsKilled == false) + enemy.Kill(true); + } + + m_levelScreen.UnpauseScreen(); + m_target.UnlockControls(); + + if (m_currentActiveLB != null) + m_currentActiveLB.StopLogicBlock(); + + this.PauseEnemy(true); + this.ChangeSprite("EnemyFairyGhostBossShoot_Character"); + this.PlayAnimation(true); + m_target.CurrentSpeed = 0; + m_target.ForceInvincible = true; + + if (IsNeo == true) + m_target.InvincibleToSpikes = true; + + Tween.To(m_levelScreen.Camera, 0.5f, Tweener.Ease.Quad.EaseInOut, "X", this.X.ToString(), "Y", this.Y.ToString()); + m_shake = true; + m_shakeTimer = m_shakeDuration; + + for (int i = 0; i < 40; i++) + { + Vector2 explosionPos = new Vector2(CDGMath.RandomInt(this.Bounds.Left, this.Bounds.Right), CDGMath.RandomInt(this.Bounds.Top, this.Bounds.Bottom)); + Tween.RunFunction(i * 0.1f, typeof(SoundManager), "Play3DSound", this, m_target, new string[] { "Boss_Explo_01", "Boss_Explo_02", "Boss_Explo_03" }); + Tween.RunFunction(i * 0.1f, m_levelScreen.ImpactEffectPool, "DisplayExplosionEffect", explosionPos); + } + + Tween.AddEndHandlerToLastTween(this, "Part3"); + + if (IsNeo == false) + { + int totalGold = m_bossCoins + m_bossMoneyBags + m_bossDiamonds; + List goldArray = new List(); + + for (int i = 0; i < m_bossCoins; i++) + goldArray.Add(0); + for (int i = 0; i < m_bossMoneyBags; i++) + goldArray.Add(1); + for (int i = 0; i < m_bossDiamonds; i++) + goldArray.Add(2); + + CDGMath.Shuffle(goldArray); + float coinDelay = 2.5f / goldArray.Count; // The enemy dies for 2.5 seconds. + + for (int i = 0; i < goldArray.Count; i++) + { + Vector2 goldPos = this.Position; + if (goldArray[i] == 0) + Tween.RunFunction(i * coinDelay, m_levelScreen.ItemDropManager, "DropItem", goldPos, ItemDropType.Coin, ItemDropType.CoinAmount); + else if (goldArray[i] == 1) + Tween.RunFunction(i * coinDelay, m_levelScreen.ItemDropManager, "DropItem", goldPos, ItemDropType.MoneyBag, ItemDropType.MoneyBagAmount); + else + Tween.RunFunction(i * coinDelay, m_levelScreen.ItemDropManager, "DropItem", goldPos, ItemDropType.Diamond, ItemDropType.DiamondAmount); + } + } + } + + public void Part3() + { + m_playDeathLoop = false; + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Boss_Flameskull_Death"); + if (m_deathLoop != null && m_deathLoop.IsPlaying == true) + m_deathLoop.Stop(AudioStopOptions.Immediate); + + m_levelScreen.RunWhiteSlash2(); + base.Kill(); + } + + + public override void Reset() + { + if (MainFairy == false) + { + m_levelScreen.RemoveEnemyFromRoom(this, SpawnRoom, this.SavedStartingPos); + this.Dispose(); + } + else + { + NumHits = 1; + base.Reset(); + } + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + SpawnRoom = null; + if (m_deathLoop != null && m_deathLoop.IsDisposed == false) + m_deathLoop.Dispose(); + m_deathLoop = null; + base.Dispose(); + } + } + + public bool IsNeo + { + get { return m_isNeo; } + set + { + m_isNeo = value; + if (value == true) + { + HealthGainPerLevel = 0; + DamageGainPerLevel = 0; + MoneyDropChance = 0; + ItemDropChance = 0; + m_saveToEnemiesKilledList = false; + } + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_FireWizard.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_FireWizard.cs new file mode 100644 index 0000000..e42d7b1 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_FireWizard.cs @@ -0,0 +1,535 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_FireWizard : EnemyObj + { + + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + + private float SpellDelay = 0.7f; + private float SpellInterval = 0.5f; + + private ProjectileObj m_fireballSummon; + private Vector2 m_spellOffset = new Vector2(40, -80); + private float TeleportDelay = 0.5f; + private float TeleportDuration = 1.0f; + private float MoveDuration = 1.0f; + private float m_fireParticleEffectCounter = 0.5f; + + protected override void InitializeEV() + { + SpellInterval = 0.5f; + + #region Basic Variables - General + Name = EnemyEV.FireWizard_Basic_Name; + LocStringID = EnemyEV.FireWizard_Basic_Name_locID; + + MaxHealth = EnemyEV.FireWizard_Basic_MaxHealth; + Damage = EnemyEV.FireWizard_Basic_Damage; + XPValue = EnemyEV.FireWizard_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.FireWizard_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.FireWizard_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.FireWizard_Basic_DropChance; + + Speed = EnemyEV.FireWizard_Basic_Speed; + TurnSpeed = EnemyEV.FireWizard_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.FireWizard_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.FireWizard_Basic_Jump; + CooldownTime = EnemyEV.FireWizard_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.FireWizard_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.FireWizard_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.FireWizard_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.FireWizard_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.FireWizard_Basic_IsWeighted; + + Scale = EnemyEV.FireWizard_Basic_Scale; + ProjectileScale = EnemyEV.FireWizard_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.FireWizard_Basic_Tint; + + MeleeRadius = EnemyEV.FireWizard_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.FireWizard_Basic_ProjectileRadius; + EngageRadius = EnemyEV.FireWizard_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.FireWizard_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.FireWizard_Miniboss_Name; + LocStringID = EnemyEV.FireWizard_Miniboss_Name_locID; + + MaxHealth = EnemyEV.FireWizard_Miniboss_MaxHealth; + Damage = EnemyEV.FireWizard_Miniboss_Damage; + XPValue = EnemyEV.FireWizard_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.FireWizard_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.FireWizard_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.FireWizard_Miniboss_DropChance; + + Speed = EnemyEV.FireWizard_Miniboss_Speed; + TurnSpeed = EnemyEV.FireWizard_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.FireWizard_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.FireWizard_Miniboss_Jump; + CooldownTime = EnemyEV.FireWizard_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.FireWizard_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.FireWizard_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.FireWizard_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.FireWizard_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.FireWizard_Miniboss_IsWeighted; + + Scale = EnemyEV.FireWizard_Miniboss_Scale; + ProjectileScale = EnemyEV.FireWizard_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.FireWizard_Miniboss_Tint; + + MeleeRadius = EnemyEV.FireWizard_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.FireWizard_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.FireWizard_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.FireWizard_Miniboss_KnockBack; + #endregion + break; + + + case (GameTypes.EnemyDifficulty.EXPERT): + m_spellOffset = new Vector2(40, -130); + SpellDelay = 1.0f; + SpellInterval = 1.0f;//0.5f; + + #region Expert Variables - General + Name = EnemyEV.FireWizard_Expert_Name; + LocStringID = EnemyEV.FireWizard_Expert_Name_locID; + + MaxHealth = EnemyEV.FireWizard_Expert_MaxHealth; + Damage = EnemyEV.FireWizard_Expert_Damage; + XPValue = EnemyEV.FireWizard_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.FireWizard_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.FireWizard_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.FireWizard_Expert_DropChance; + + Speed = EnemyEV.FireWizard_Expert_Speed; + TurnSpeed = EnemyEV.FireWizard_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.FireWizard_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.FireWizard_Expert_Jump; + CooldownTime = EnemyEV.FireWizard_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.FireWizard_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.FireWizard_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.FireWizard_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.FireWizard_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.FireWizard_Expert_IsWeighted; + + Scale = EnemyEV.FireWizard_Expert_Scale; + ProjectileScale = EnemyEV.FireWizard_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.FireWizard_Expert_Tint; + + MeleeRadius = EnemyEV.FireWizard_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.FireWizard_Expert_ProjectileRadius; + EngageRadius = EnemyEV.FireWizard_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.FireWizard_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + SpellInterval = 0.15f; + + #region Advanced Variables - General + Name = EnemyEV.FireWizard_Advanced_Name; + LocStringID = EnemyEV.FireWizard_Advanced_Name_locID; + + MaxHealth = EnemyEV.FireWizard_Advanced_MaxHealth; + Damage = EnemyEV.FireWizard_Advanced_Damage; + XPValue = EnemyEV.FireWizard_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.FireWizard_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.FireWizard_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.FireWizard_Advanced_DropChance; + + Speed = EnemyEV.FireWizard_Advanced_Speed; + TurnSpeed = EnemyEV.FireWizard_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.FireWizard_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.FireWizard_Advanced_Jump; + CooldownTime = EnemyEV.FireWizard_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.FireWizard_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.FireWizard_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.FireWizard_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.FireWizard_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.FireWizard_Advanced_IsWeighted; + + Scale = EnemyEV.FireWizard_Advanced_Scale; + ProjectileScale = EnemyEV.FireWizard_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.FireWizard_Advanced_Tint; + + MeleeRadius = EnemyEV.FireWizard_Advanced_MeleeRadius; + EngageRadius = EnemyEV.FireWizard_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.FireWizard_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.FireWizard_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + } + + protected override void InitializeLogic() + { + LogicSet moveTowardsLS = new LogicSet(this); + moveTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardIdle_Character", true, true)); + moveTowardsLS.AddAction(new ChaseLogicAction(m_target, new Vector2(-255, -175), new Vector2(255, -75), true, MoveDuration)); + + LogicSet moveAwayLS = new LogicSet(this); + moveAwayLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardIdle_Character", true, true)); + moveAwayLS.AddAction(new ChaseLogicAction(m_target, false, MoveDuration)); + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardIdle_Character", true, true)); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(0.5f)); + + LogicSet castSpellLS = new LogicSet(this); + castSpellLS.AddAction(new MoveLogicAction(m_target, true, 0)); + castSpellLS.AddAction(new LockFaceDirectionLogicAction(true)); + castSpellLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardSpell_Character")); + castSpellLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeSpell")); + castSpellLS.AddAction(new RunFunctionLogicAction(this, "SummonFireball", null)); + castSpellLS.AddAction(new DelayLogicAction(SpellDelay)); + castSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castSpellLS.AddAction(new DelayLogicAction(SpellInterval)); + castSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castSpellLS.AddAction(new DelayLogicAction(SpellInterval)); + castSpellLS.AddAction(new RunFunctionLogicAction(this, "ResetFireball", null)); + castSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castSpellLS.AddAction(new DelayLogicAction(0.5f)); + castSpellLS.AddAction(new LockFaceDirectionLogicAction(false)); + castSpellLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet castAdvancedSpellLS = new LogicSet(this); + castAdvancedSpellLS.AddAction(new MoveLogicAction(m_target, true, 0)); + castAdvancedSpellLS.AddAction(new LockFaceDirectionLogicAction(true)); + castAdvancedSpellLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardSpell_Character")); + castAdvancedSpellLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeSpell")); + castAdvancedSpellLS.AddAction(new RunFunctionLogicAction(this, "SummonFireball", null)); + castAdvancedSpellLS.AddAction(new DelayLogicAction(SpellDelay)); + castAdvancedSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castAdvancedSpellLS.AddAction(new DelayLogicAction(SpellInterval)); + castAdvancedSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castAdvancedSpellLS.AddAction(new DelayLogicAction(SpellInterval)); + castAdvancedSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castAdvancedSpellLS.AddAction(new DelayLogicAction(SpellInterval)); + castAdvancedSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castAdvancedSpellLS.AddAction(new DelayLogicAction(SpellInterval)); + castAdvancedSpellLS.AddAction(new RunFunctionLogicAction(this, "ResetFireball", null)); + castAdvancedSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castAdvancedSpellLS.AddAction(new DelayLogicAction(0.5f)); + castAdvancedSpellLS.AddAction(new LockFaceDirectionLogicAction(false)); + castAdvancedSpellLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet castExpertSpellLS = new LogicSet(this); + castExpertSpellLS.AddAction(new MoveLogicAction(m_target, true, 0)); + castExpertSpellLS.AddAction(new LockFaceDirectionLogicAction(true)); + castExpertSpellLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardSpell_Character")); + castExpertSpellLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeSpell")); + castExpertSpellLS.AddAction(new RunFunctionLogicAction(this, "SummonFireball", null)); + castExpertSpellLS.AddAction(new DelayLogicAction(SpellDelay)); + castExpertSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castExpertSpellLS.AddAction(new DelayLogicAction(SpellInterval)); + castExpertSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castExpertSpellLS.AddAction(new DelayLogicAction(SpellInterval)); + castExpertSpellLS.AddAction(new RunFunctionLogicAction(this, "ResetFireball", null)); + castExpertSpellLS.AddAction(new RunFunctionLogicAction(this, "CastFireball")); + castExpertSpellLS.AddAction(new DelayLogicAction(0.5f)); + castExpertSpellLS.AddAction(new LockFaceDirectionLogicAction(false)); + castExpertSpellLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet teleportLS = new LogicSet(this); + teleportLS.AddAction(new MoveLogicAction(m_target, true, 0)); + teleportLS.AddAction(new LockFaceDirectionLogicAction(true)); + teleportLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 30f)); + teleportLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardTeleportOut_Character", false, false)); + teleportLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeTeleport")); + teleportLS.AddAction(new DelayLogicAction(TeleportDelay)); + teleportLS.AddAction(new PlayAnimationLogicAction("TeleportStart", "End")); + teleportLS.AddAction(new ChangePropertyLogicAction(this, "IsCollidable", false)); + teleportLS.AddAction(new DelayLogicAction(TeleportDuration)); + teleportLS.AddAction(new TeleportLogicAction(m_target, new Vector2(-400, -400), new Vector2(400, 400))); + teleportLS.AddAction(new ChangePropertyLogicAction(this, "IsCollidable", true)); + teleportLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardTeleportIn_Character", true, false)); + teleportLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 10f)); + teleportLS.AddAction(new LockFaceDirectionLogicAction(false)); + teleportLS.AddAction(new DelayLogicAction(0.5f)); + + m_generalBasicLB.AddLogicSet(moveTowardsLS, moveAwayLS, walkStopLS, castSpellLS, teleportLS); + m_generalAdvancedLB.AddLogicSet(moveTowardsLS, moveAwayLS, walkStopLS, castAdvancedSpellLS, teleportLS); + m_generalExpertLB.AddLogicSet(moveTowardsLS, moveAwayLS, walkStopLS, castExpertSpellLS, teleportLS); + m_generalCooldownLB.AddLogicSet(moveTowardsLS, moveAwayLS, walkStopLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + + SetCooldownLogicBlock(m_generalCooldownLB, 100, 0, 0); //moveTowardsLS, moveAwayLS, walkStopLS + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 40, 0, 0, 60, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 40, 0, 0, 60, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 100, 0, 0, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalAdvancedLB, 0, 0, 100, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 40, 0, 0, 60, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 100, 0, 0, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalExpertLB, 0, 0, 100, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + public EnemyObj_FireWizard(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyWizardIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.FireWizard; + this.PlayAnimation(true); + this.TintablePart = _objectList[0]; + } + + public override void Update(GameTime gameTime) + { + base.Update(gameTime); + if (m_fireballSummon != null) + { + if (this.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.None) + m_fireballSummon.Position = new Vector2(this.X + m_spellOffset.X, this.Y + m_spellOffset.Y); + else + m_fireballSummon.Position = new Vector2(this.X - m_spellOffset.X, this.Y + m_spellOffset.Y); + } + + if (m_fireParticleEffectCounter > 0) + { + m_fireParticleEffectCounter -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_fireParticleEffectCounter <= 0) + { + m_levelScreen.ImpactEffectPool.DisplayFireParticleEffect(this); + m_fireParticleEffectCounter = 0.15f; + } + } + } + + public void CastFireball() + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "WizardFireballProjectile_Sprite", + SourceAnchor = m_spellOffset, + Target = m_target, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = ProjectileScale, + }; + + if (this.Difficulty == GameTypes.EnemyDifficulty.ADVANCED) + projData.AngleOffset = CDGMath.RandomInt(-25, 25); + + if (this.Difficulty == GameTypes.EnemyDifficulty.EXPERT) + { + projData.SpriteName = "GhostBossProjectile_Sprite"; + projData.CollidesWithTerrain = false; + } + + SoundManager.Play3DSound(this, m_target, "FireWizard_Attack_01", "FireWizard_Attack_02", "FireWizard_Attack_03", "FireWizard_Attack_04"); + ProjectileObj fireball = m_levelScreen.ProjectileManager.FireProjectile(projData); + fireball.Rotation = 0; + if (this.Difficulty != GameTypes.EnemyDifficulty.EXPERT) + Tweener.Tween.RunFunction(0.15f, this, "ChangeFireballState", fireball); + } + + public void ChangeFireballState(ProjectileObj fireball) + { + fireball.CollidesWithTerrain = true; + } + + public void SummonFireball() + { + ResetFireball(); + + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "WizardFireballProjectile_Sprite", + SourceAnchor = m_spellOffset, + Target = m_target, + Speed = new Vector2(0, 0), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = false, + DestroysWithEnemy = false, + Scale = ProjectileScale, + }; + + if (this.Difficulty == GameTypes.EnemyDifficulty.EXPERT) + { + projData.SpriteName = "GhostBossProjectile_Sprite"; + projData.CollidesWithTerrain = false; + } + + //m_fireballSummon = m_levelScreen.ProjectileManager.FireProjectile("WizardFireballProjectile_Sprite", this, m_spellOffset, 0, 0, false, 0, ProjectileDamage); + SoundManager.Play3DSound(this, m_target, "Fire_Wizard_Form"); + m_fireballSummon = m_levelScreen.ProjectileManager.FireProjectile(projData); + m_fireballSummon.Opacity = 0; + m_fireballSummon.Scale = Vector2.Zero; + m_fireballSummon.AnimationDelay = 1 / 10f; + m_fireballSummon.PlayAnimation(true); + m_fireballSummon.Rotation = 0; + + Tweener.Tween.To(m_fireballSummon, 0.5f, Tweener.Ease.Back.EaseOut, "Opacity", "1", "ScaleX", ProjectileScale.X.ToString(), "ScaleY", ProjectileScale.Y.ToString()); + + projData.Dispose(); + } + + public void ResetFireball() + { + if (m_fireballSummon != null) + { + m_levelScreen.ProjectileManager.DestroyProjectile(m_fireballSummon); + m_fireballSummon = null; + } + } + + //public override void HitEnemy(int damage, Vector2 position, bool isPlayer) + //{ + // base.HitEnemy(damage, position, isPlayer); + // if (m_currentActiveLB != null && m_currentActiveLB.IsActive == true) + // { + // m_currentActiveLB.StopLogicBlock(); + // ResetFireball(); + // } + //} + + public override void Kill(bool giveXP = true) + { + if (m_currentActiveLB != null && m_currentActiveLB.IsActive == true) + { + m_currentActiveLB.StopLogicBlock(); + ResetFireball(); + } + base.Kill(giveXP); + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + if (otherBox.AbsParent is PlayerObj) + this.CurrentSpeed = 0; + if (collisionResponseType != Consts.COLLISIONRESPONSE_TERRAIN) + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + else if ((otherBox.AbsParent is PlayerObj) == false)// Add this else to turn on terrain collision. + { + IPhysicsObj otherPhysicsObj = otherBox.AbsParent as IPhysicsObj; + if (otherPhysicsObj.CollidesBottom == true && otherPhysicsObj.CollidesTop == true && otherPhysicsObj.CollidesLeft == true && otherPhysicsObj.CollidesRight == true) + this.Position += CollisionMath.RotatedRectIntersectsMTD(thisBox.AbsRect, thisBox.AbsRotation, Vector2.Zero, otherBox.AbsRect, otherBox.AbsRotation, Vector2.Zero); + } + } + + public override void ResetState() + { + ResetFireball(); + base.ResetState(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_fireballSummon = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Fireball.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Fireball.cs new file mode 100644 index 0000000..bd5848d --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Fireball.cs @@ -0,0 +1,707 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; + +namespace RogueCastle +{ + public class EnemyObj_Fireball: EnemyObj + { + //private float SeparationDistance = 150f; // The distance that bats stay away from other enemies. + + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + private LogicBlock m_generalNeoLB = new LogicBlock(); + + private Color FlameColour = Color.OrangeRed; + private float DashDelay = 0; + private float DashSpeed = 0; + private float DashDuration = 0; + + private float m_minibossFireTimeCounter = 0.6f;//0.5f;//0.35f; + private float m_minibossFireTime = 0.6f;//0.5f;//0.35f; + private float m_MinibossProjectileLifspan = 11f;//12f;//12f; + + private float m_MinibossProjectileLifspanNeo = 20f;//19f;//18f; + + private bool m_shake = false; + private bool m_shookLeft = false; + private float m_shakeTimer = 0; + private float m_shakeDuration = 0.03f; + + //5000 + private int m_bossCoins = 30; + private int m_bossMoneyBags = 17; + private int m_bossDiamonds = 4; + + private bool m_isNeo = false; + + protected override void InitializeEV() + { + DashDelay = 0.75f; + DashDuration = 0.5f; + DashSpeed = 900; + + #region Basic Variables - General + Name = EnemyEV.Fireball_Basic_Name; + LocStringID = EnemyEV.Fireball_Basic_Name_locID; + + MaxHealth = EnemyEV.Fireball_Basic_MaxHealth; + Damage = EnemyEV.Fireball_Basic_Damage; + XPValue = EnemyEV.Fireball_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Fireball_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Fireball_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Fireball_Basic_DropChance; + + Speed = EnemyEV.Fireball_Basic_Speed; + TurnSpeed = EnemyEV.Fireball_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Fireball_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Fireball_Basic_Jump; + CooldownTime = EnemyEV.Fireball_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Fireball_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Fireball_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Fireball_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Fireball_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Fireball_Basic_IsWeighted; + + Scale = EnemyEV.Fireball_Basic_Scale; + ProjectileScale = EnemyEV.Fireball_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Fireball_Basic_Tint; + + MeleeRadius = EnemyEV.Fireball_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Fireball_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Fireball_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Fireball_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Fireball_Miniboss_Name; + LocStringID = EnemyEV.Fireball_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Fireball_Miniboss_MaxHealth; + Damage = EnemyEV.Fireball_Miniboss_Damage; + XPValue = EnemyEV.Fireball_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Fireball_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Fireball_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Fireball_Miniboss_DropChance; + + Speed = EnemyEV.Fireball_Miniboss_Speed; + TurnSpeed = EnemyEV.Fireball_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Fireball_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Fireball_Miniboss_Jump; + CooldownTime = EnemyEV.Fireball_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Fireball_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Fireball_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Fireball_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Fireball_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Fireball_Miniboss_IsWeighted; + + Scale = EnemyEV.Fireball_Miniboss_Scale; + ProjectileScale = EnemyEV.Fireball_Miniboss_ProjectileScale; + //TintablePart.TextureColor = EnemyEV.Fireball_Miniboss_Tint; + + MeleeRadius = EnemyEV.Fireball_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Fireball_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Fireball_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Fireball_Miniboss_KnockBack; + #endregion + if (LevelEV.WEAKEN_BOSSES == true) + this.MaxHealth = 1; + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.Fireball_Expert_Name; + LocStringID = EnemyEV.Fireball_Expert_Name_locID; + + MaxHealth = EnemyEV.Fireball_Expert_MaxHealth; + Damage = EnemyEV.Fireball_Expert_Damage; + XPValue = EnemyEV.Fireball_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Fireball_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Fireball_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Fireball_Expert_DropChance; + + Speed = EnemyEV.Fireball_Expert_Speed; + TurnSpeed = EnemyEV.Fireball_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Fireball_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Fireball_Expert_Jump; + CooldownTime = EnemyEV.Fireball_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Fireball_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Fireball_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Fireball_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Fireball_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Fireball_Expert_IsWeighted; + + Scale = EnemyEV.Fireball_Expert_Scale; + ProjectileScale = EnemyEV.Fireball_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Fireball_Expert_Tint; + + MeleeRadius = EnemyEV.Fireball_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Fireball_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Fireball_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Fireball_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.Fireball_Advanced_Name; + LocStringID = EnemyEV.Fireball_Advanced_Name_locID; + + MaxHealth = EnemyEV.Fireball_Advanced_MaxHealth; + Damage = EnemyEV.Fireball_Advanced_Damage; + XPValue = EnemyEV.Fireball_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Fireball_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Fireball_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Fireball_Advanced_DropChance; + + Speed = EnemyEV.Fireball_Advanced_Speed; + TurnSpeed = EnemyEV.Fireball_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Fireball_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Fireball_Advanced_Jump; + CooldownTime = EnemyEV.Fireball_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Fireball_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Fireball_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Fireball_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Fireball_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Fireball_Advanced_IsWeighted; + + Scale = EnemyEV.Fireball_Advanced_Scale; + ProjectileScale = EnemyEV.Fireball_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Fireball_Advanced_Tint; + + MeleeRadius = EnemyEV.Fireball_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Fireball_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Fireball_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Fireball_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + m_resetSpriteName = "EnemyGhostBossIdle_Character"; + } + + protected override void InitializeLogic() + { + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemyGhostChase_Character", true, true)); + walkTowardsLS.AddAction(new ChaseLogicAction(m_target, true, 2.0f)); + + LogicSet walkAwayLS = new LogicSet(this); + walkAwayLS.AddAction(new ChangeSpriteLogicAction("EnemyGhostChase_Character", true, true)); + walkAwayLS.AddAction(new ChaseLogicAction(m_target, false, 1.0f)); + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new ChangeSpriteLogicAction("EnemyGhostIdle_Character", true, true)); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(1.0f, 2.0f)); + //walkStopLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet autoCoolDownLS = new LogicSet(this); + autoCoolDownLS.AddAction(new MoveLogicAction(m_target, true)); + autoCoolDownLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet dashTowardsLS = new LogicSet(this); + dashTowardsLS.AddAction(new MoveLogicAction(m_target, true, 0)); + dashTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemyGhostDashPrep_Character", true, true)); + //dashTowardsLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Flameball_Attack_Pause")); + dashTowardsLS.AddAction(new DelayLogicAction(DashDelay)); + dashTowardsLS.AddAction(new RunFunctionLogicAction(this, "TurnToPlayer", null)); + dashTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemyGhostDash_Character", true, true)); + dashTowardsLS.AddAction(new LockFaceDirectionLogicAction(true)); + //dashTowardsLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Flameball_Attack")); + dashTowardsLS.AddAction(new MoveLogicAction(m_target, true, DashSpeed)); + dashTowardsLS.AddAction(new DelayLogicAction(DashDuration)); + dashTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemyGhostIdle_Character", true, true)); + dashTowardsLS.AddAction(new MoveLogicAction(m_target, true, 0)); + dashTowardsLS.AddAction(new LockFaceDirectionLogicAction(false)); + dashTowardsLS.AddAction(new DelayLogicAction(0.75f)); + dashTowardsLS.Tag = GameTypes.LogicSetType_ATTACK; + + + LogicSet dashTowardsFourProjectilesLS = new LogicSet(this); + dashTowardsFourProjectilesLS.AddAction(new MoveLogicAction(m_target, true, 0)); + dashTowardsFourProjectilesLS.AddAction(new ChangeSpriteLogicAction("EnemyGhostDashPrep_Character", true, true)); + dashTowardsFourProjectilesLS.AddAction(new DelayLogicAction(DashDelay)); + dashTowardsFourProjectilesLS.AddAction(new RunFunctionLogicAction(this, "TurnToPlayer", null)); + dashTowardsFourProjectilesLS.AddAction(new ChangeSpriteLogicAction("EnemyGhostDash_Character", true, true)); + ThrowProjectiles(dashTowardsFourProjectilesLS, true); + dashTowardsFourProjectilesLS.AddAction(new LockFaceDirectionLogicAction(true)); + dashTowardsFourProjectilesLS.AddAction(new MoveLogicAction(m_target, true, DashSpeed)); + dashTowardsFourProjectilesLS.AddAction(new DelayLogicAction(DashDuration)); + dashTowardsFourProjectilesLS.AddAction(new ChangeSpriteLogicAction("EnemyGhostIdle_Character", true, true)); + dashTowardsFourProjectilesLS.AddAction(new MoveLogicAction(m_target, true, 0)); + dashTowardsFourProjectilesLS.AddAction(new LockFaceDirectionLogicAction(false)); + dashTowardsFourProjectilesLS.AddAction(new DelayLogicAction(0.75f)); + dashTowardsFourProjectilesLS.Tag = GameTypes.LogicSetType_ATTACK; + + + ////////////// MINIBOSS LOGIC ////////////////// + + LogicSet walkTowardsBossLS = new LogicSet(this); + walkTowardsBossLS.AddAction(new ChangeSpriteLogicAction("EnemyGhostBossIdle_Character", true, true)); + walkTowardsBossLS.AddAction(new ChaseLogicAction(m_target, true, 2.0f)); + + LogicSet walkStopBossLS = new LogicSet(this); + walkStopBossLS.AddAction(new ChangeSpriteLogicAction("EnemyGhostBossIdle_Character", true, true)); + walkStopBossLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopBossLS.AddAction(new DelayLogicAction(1.0f, 2.0f)); + //walkStopLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet dashTowardsBossLS = new LogicSet(this); + dashTowardsBossLS.AddAction(new MoveLogicAction(m_target, true, 0)); + dashTowardsBossLS.AddAction(new LockFaceDirectionLogicAction(true)); + dashTowardsBossLS.AddAction(new ChangeSpriteLogicAction("EnemyGhostBossDashPrep_Character", true, true)); + dashTowardsBossLS.AddAction(new DelayLogicAction(DashDelay)); + dashTowardsBossLS.AddAction(new RunFunctionLogicAction(this, "TurnToPlayer", null)); + dashTowardsBossLS.AddAction(new ChangeSpriteLogicAction("EnemyGhostBossIdle_Character", true, true)); + dashTowardsBossLS.AddAction(new RunFunctionLogicAction(this, "ChangeFlameDirection")); + dashTowardsBossLS.AddAction(new MoveLogicAction(m_target, true, DashSpeed)); + dashTowardsBossLS.AddAction(new DelayLogicAction(DashDuration)); + dashTowardsBossLS.AddAction(new ChangePropertyLogicAction(_objectList[0], "Rotation", 0)); + dashTowardsBossLS.AddAction(new MoveLogicAction(m_target, true, 0)); + dashTowardsBossLS.AddAction(new LockFaceDirectionLogicAction(false)); + dashTowardsBossLS.AddAction(new DelayLogicAction(0.75f)); + dashTowardsLS.Tag = GameTypes.LogicSetType_ATTACK; + + + + m_generalBasicLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsLS); + m_generalAdvancedLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsLS); + m_generalExpertLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsFourProjectilesLS); + m_generalMiniBossLB.AddLogicSet(walkTowardsBossLS, walkAwayLS, walkStopBossLS, autoCoolDownLS, dashTowardsBossLS); + + m_generalNeoLB.AddLogicSet(walkTowardsBossLS, walkAwayLS, walkStopBossLS, autoCoolDownLS, dashTowardsBossLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalMiniBossLB); + logicBlocksToDispose.Add(m_generalNeoLB); + + SetCooldownLogicBlock(m_generalBasicLB, 100, 0, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsLS + + + base.InitializeLogic(); + } + + public void ChangeFlameDirection() + { + if (m_target.X < this.X) + _objectList[0].Rotation = 90; + else + _objectList[0].Rotation = -90; + } + + + private void ThrowProjectiles(LogicSet ls, bool useBossProjectile = false) + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "GhostProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(0, 0), + CollidesWithTerrain = false, + Scale = ProjectileScale, + }; + + if (useBossProjectile == true) + projData.SpriteName = "GhostProjectile_Sprite"; + + ls.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"FairyAttack1")); + projData.Angle = new Vector2(60, 60); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(30, 30); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(120, 120); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(150, 150); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-60, -60); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-30, -30); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-120, -120); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-150, -150); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + //ls.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnightAttack1")); + projData.Dispose(); + } + + + private void ThrowStandingProjectile(bool useBossProjectile = false) + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "GhostProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(0, 0), + CollidesWithTerrain = false, + Scale = ProjectileScale, + Lifespan = m_MinibossProjectileLifspan, + }; + + if (IsNeo == true) + projData.Lifespan = m_MinibossProjectileLifspanNeo; + + if (useBossProjectile == true) + projData.SpriteName = "GhostBossProjectile_Sprite"; + ProjectileObj ball = m_levelScreen.ProjectileManager.FireProjectile(projData); + ball.Rotation = 0; // Why is this needed? Because lockposition does some funky stuff. + if (IsNeo == true) + ball.TextureColor = Color.MediumSpringGreen; + projData.Dispose(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsLS + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 40, 0, 0, 0, 60); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsLS + break; + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 100, 0, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalAdvancedLB, 0, 0, 100, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsLS + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 40, 0, 0, 0, 60); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsFourProjectilesLS + break; + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 100, 0, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsFourProjectilesLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalExpertLB, 0, 0, 100, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsFourProjectilesLS + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + if (IsNeo == false) + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(true, m_generalMiniBossLB, 52, 0, 0, 0, 48); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsLS + break; + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalMiniBossLB, 100, 0, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalMiniBossLB, 100, 0, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsLS + break; + default: + break; + } + } + else + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(true, m_generalNeoLB, 45, 0, 0, 0, 55); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsLS + break; + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalNeoLB, 100, 0, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalNeoLB, 100, 0, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, autoCoolDownLS, dashTowardsLS + break; + default: + break; + } + } + } + + public override void Update(GameTime gameTime) + { + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS && this.IsPaused == false) + { + if (m_minibossFireTimeCounter > 0 && m_bossVersionKilled == false) + { + m_minibossFireTimeCounter -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_minibossFireTimeCounter <= 0) + { + ThrowStandingProjectile(true); + m_minibossFireTimeCounter = m_minibossFireTime; + } + } + } + + if (m_shake == true) + { + if (m_shakeTimer > 0) + { + m_shakeTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_shakeTimer <= 0) + { + m_shakeTimer = m_shakeDuration; + if (m_shookLeft == true) + { + m_shookLeft = false; + this.X += 5; + } + else + { + this.X -= 5; + m_shookLeft = true; + } + } + } + } + + // Flocking code for flying bats. + //foreach (EnemyObj enemyToAvoid in m_levelScreen.EnemyList) // Can speed up efficiency if the level had a property that returned the number of enemies in a single room. + //{ + // if (enemyToAvoid != this) + // { + // float distanceFromOtherEnemy = Vector2.Distance(this.Position, enemyToAvoid.Position); + // if (distanceFromOtherEnemy < this.SeparationDistance) + // { + // this.CurrentSpeed = .50f * this.Speed; // Move away at half speed. + // Vector2 seekPosition = 2 * this.Position - enemyToAvoid.Position; + // CDGMath.TurnToFace(this, seekPosition); + // } + // } + //} + //if (m_playingAnim == false) + //{ + // m_playingAnim = true; + // Tweener.Tween.To(this, CDGMath.RandomFloat(0,3), Tweener.Ease.Linear.EaseNone, "Opacity", "1"); + // Tweener.Tween.AddEndHandlerToLastTween(this, "PlayAnimation", true); + //} + + //this.Heading = new Vector2( + // (float)Math.Cos(Orientation), (float)Math.Sin(Orientation)); + base.Update(gameTime); + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + // Hits the player in Tanooki mode. + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS && m_bossVersionKilled == false) + { + PlayerObj player = otherBox.AbsParent as PlayerObj; + if (player != null && otherBox.Type == Consts.WEAPON_HITBOX && player.IsInvincible == false && player.State == PlayerObj.STATE_TANOOKI) + player.HitPlayer(this); + } + + if (collisionResponseType != Consts.COLLISIONRESPONSE_TERRAIN) + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + public void TurnToPlayer() + { + float previousTurnspeed = TurnSpeed; + this.TurnSpeed = 2; + CDGMath.TurnToFace(this, m_target.Position); + this.TurnSpeed = previousTurnspeed; + } + + public override void HitEnemy(int damage, Vector2 collisionPt, bool isPlayer) + { + if (m_bossVersionKilled == false) + { + //SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Flameball_Hit_03", "Flameball_Hit_02"); + base.HitEnemy(damage, collisionPt, isPlayer); + } + } + + public override void Kill(bool giveXP = true) + { + if (Difficulty != GameTypes.EnemyDifficulty.MINIBOSS) + { + base.Kill(giveXP); + } + else + { + if (m_target.CurrentHealth > 0) + { + Game.PlayerStats.FireballBossBeaten = true; + + SoundManager.StopMusic(0); + SoundManager.PlaySound("PressStart"); + m_bossVersionKilled = true; + m_target.LockControls(); + m_levelScreen.PauseScreen(); + m_levelScreen.ProjectileManager.DestroyAllProjectiles(false); + m_levelScreen.RunWhiteSlashEffect(); + Tween.RunFunction(1f, this, "Part2"); + SoundManager.PlaySound("Boss_Flash"); + SoundManager.PlaySound("Boss_Fireball_Freeze"); + + GameUtil.UnlockAchievement("FEAR_OF_FIRE"); + } + } + } + + public void Part2() + { + m_levelScreen.UnpauseScreen(); + m_target.UnlockControls(); + + if (m_currentActiveLB != null) + m_currentActiveLB.StopLogicBlock(); + + this.PauseEnemy(true); + this.ChangeSprite("EnemyGhostBossIdle_Character"); + this.PlayAnimation(true); + m_target.CurrentSpeed = 0; + m_target.ForceInvincible = true; + + Tween.To(m_levelScreen.Camera, 0.5f, Tweener.Ease.Quad.EaseInOut, "X", this.X.ToString(), "Y", this.Y.ToString()); + m_shake = true; + m_shakeTimer = m_shakeDuration; + + for (int i = 0; i < 40; i++) + { + Vector2 explosionPos = new Vector2(CDGMath.RandomInt(this.Bounds.Left, this.Bounds.Right), CDGMath.RandomInt(this.Bounds.Top, this.Bounds.Bottom)); + Tween.RunFunction(i * 0.1f, typeof(SoundManager), "Play3DSound", this, m_target, new string[] { "Boss_Explo_01", "Boss_Explo_02", "Boss_Explo_03" }); + Tween.RunFunction(i * 0.1f, m_levelScreen.ImpactEffectPool, "DisplayExplosionEffect", explosionPos); + } + + Tween.AddEndHandlerToLastTween(this, "Part3"); + + if (IsNeo == false) + { + int totalGold = m_bossCoins + m_bossMoneyBags + m_bossDiamonds; + List goldArray = new List(); + + for (int i = 0; i < m_bossCoins; i++) + goldArray.Add(0); + for (int i = 0; i < m_bossMoneyBags; i++) + goldArray.Add(1); + for (int i = 0; i < m_bossDiamonds; i++) + goldArray.Add(2); + + CDGMath.Shuffle(goldArray); + float coinDelay = 2.5f / goldArray.Count; // The enemy dies for 2.5 seconds. + + for (int i = 0; i < goldArray.Count; i++) + { + Vector2 goldPos = this.Position; + if (goldArray[i] == 0) + Tween.RunFunction(i * coinDelay, m_levelScreen.ItemDropManager, "DropItem", goldPos, ItemDropType.Coin, ItemDropType.CoinAmount); + else if (goldArray[i] == 1) + Tween.RunFunction(i * coinDelay, m_levelScreen.ItemDropManager, "DropItem", goldPos, ItemDropType.MoneyBag, ItemDropType.MoneyBagAmount); + else + Tween.RunFunction(i * coinDelay, m_levelScreen.ItemDropManager, "DropItem", goldPos, ItemDropType.Diamond, ItemDropType.DiamondAmount); + } + } + } + + public void Part3() + { + SoundManager.PlaySound("Boss_Fireball_Death"); + m_levelScreen.ImpactEffectPool.DestroyFireballBoss(this.Position); + base.Kill(); + } + + public bool BossVersionKilled + { + get { return m_bossVersionKilled; } + } + + public EnemyObj_Fireball(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyGhostIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + //this.PlayAnimation(); + this.Type = EnemyType.Fireball; + TintablePart = _objectList[0]; + } + + public bool IsNeo + { + get { return m_isNeo; } + set + { + m_isNeo = value; + if (value == true) + { + HealthGainPerLevel = 0; + DamageGainPerLevel = 0; + MoneyDropChance = 0; + ItemDropChance = 0; + m_saveToEnemiesKilledList = false; + } + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_HomingTurret.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_HomingTurret.cs new file mode 100644 index 0000000..a03cbd0 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_HomingTurret.cs @@ -0,0 +1,358 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_HomingTurret : EnemyObj + { + private float FireDelay = 5; + + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + + protected override void InitializeEV() + { + LockFlip = false; + FireDelay = 2.0f;//5; + + #region Basic Variables - General + Name = EnemyEV.HomingTurret_Basic_Name; + LocStringID = EnemyEV.HomingTurret_Basic_Name_locID; + + MaxHealth = EnemyEV.HomingTurret_Basic_MaxHealth; + Damage = EnemyEV.HomingTurret_Basic_Damage; + XPValue = EnemyEV.HomingTurret_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.HomingTurret_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.HomingTurret_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.HomingTurret_Basic_DropChance; + + Speed = EnemyEV.HomingTurret_Basic_Speed; + TurnSpeed = EnemyEV.HomingTurret_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.HomingTurret_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.HomingTurret_Basic_Jump; + CooldownTime = EnemyEV.HomingTurret_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.HomingTurret_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.HomingTurret_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.HomingTurret_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.HomingTurret_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.HomingTurret_Basic_IsWeighted; + + Scale = EnemyEV.HomingTurret_Basic_Scale; + ProjectileScale = EnemyEV.HomingTurret_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.HomingTurret_Basic_Tint; + + MeleeRadius = EnemyEV.HomingTurret_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.HomingTurret_Basic_ProjectileRadius; + EngageRadius = EnemyEV.HomingTurret_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.HomingTurret_Basic_KnockBack; + #endregion + + InitialLogicDelay = 1; + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.HomingTurret_Miniboss_Name; + LocStringID = EnemyEV.HomingTurret_Miniboss_Name_locID; + + MaxHealth = EnemyEV.HomingTurret_Miniboss_MaxHealth; + Damage = EnemyEV.HomingTurret_Miniboss_Damage; + XPValue = EnemyEV.HomingTurret_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.HomingTurret_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.HomingTurret_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.HomingTurret_Miniboss_DropChance; + + Speed = EnemyEV.HomingTurret_Miniboss_Speed; + TurnSpeed = EnemyEV.HomingTurret_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.HomingTurret_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.HomingTurret_Miniboss_Jump; + CooldownTime = EnemyEV.HomingTurret_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.HomingTurret_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.HomingTurret_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.HomingTurret_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.HomingTurret_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.HomingTurret_Miniboss_IsWeighted; + + Scale = EnemyEV.HomingTurret_Miniboss_Scale; + ProjectileScale = EnemyEV.HomingTurret_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.HomingTurret_Miniboss_Tint; + + MeleeRadius = EnemyEV.HomingTurret_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.HomingTurret_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.HomingTurret_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.HomingTurret_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + FireDelay = 2.25f;//5; + #region Expert Variables - General + Name = EnemyEV.HomingTurret_Expert_Name; + LocStringID = EnemyEV.HomingTurret_Expert_Name_locID; + + MaxHealth = EnemyEV.HomingTurret_Expert_MaxHealth; + Damage = EnemyEV.HomingTurret_Expert_Damage; + XPValue = EnemyEV.HomingTurret_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.HomingTurret_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.HomingTurret_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.HomingTurret_Expert_DropChance; + + Speed = EnemyEV.HomingTurret_Expert_Speed; + TurnSpeed = EnemyEV.HomingTurret_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.HomingTurret_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.HomingTurret_Expert_Jump; + CooldownTime = EnemyEV.HomingTurret_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.HomingTurret_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.HomingTurret_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.HomingTurret_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.HomingTurret_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.HomingTurret_Expert_IsWeighted; + + Scale = EnemyEV.HomingTurret_Expert_Scale; + ProjectileScale = EnemyEV.HomingTurret_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.HomingTurret_Expert_Tint; + + MeleeRadius = EnemyEV.HomingTurret_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.HomingTurret_Expert_ProjectileRadius; + EngageRadius = EnemyEV.HomingTurret_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.HomingTurret_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + FireDelay = 1.5f;//5; + #region Advanced Variables - General + Name = EnemyEV.HomingTurret_Advanced_Name; + LocStringID = EnemyEV.HomingTurret_Advanced_Name_locID; + + MaxHealth = EnemyEV.HomingTurret_Advanced_MaxHealth; + Damage = EnemyEV.HomingTurret_Advanced_Damage; + XPValue = EnemyEV.HomingTurret_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.HomingTurret_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.HomingTurret_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.HomingTurret_Advanced_DropChance; + + Speed = EnemyEV.HomingTurret_Advanced_Speed; + TurnSpeed = EnemyEV.HomingTurret_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.HomingTurret_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.HomingTurret_Advanced_Jump; + CooldownTime = EnemyEV.HomingTurret_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.HomingTurret_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.HomingTurret_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.HomingTurret_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.HomingTurret_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.HomingTurret_Advanced_IsWeighted; + + Scale = EnemyEV.HomingTurret_Advanced_Scale; + ProjectileScale = EnemyEV.HomingTurret_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.HomingTurret_Advanced_Tint; + + MeleeRadius = EnemyEV.HomingTurret_Advanced_MeleeRadius; + EngageRadius = EnemyEV.HomingTurret_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.HomingTurret_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.HomingTurret_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + } + + protected override void InitializeLogic() + { + float angle = this.Rotation; + float delay = this.ParseTagToFloat("delay"); + float speed = this.ParseTagToFloat("speed"); + if (delay == 0) + { + Console.WriteLine("ERROR: Turret set with delay of 0. Shoots too fast."); + delay = FireDelay; + } + + if (speed == 0) + speed = ProjectileSpeed; + + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "HomingProjectile_Sprite", + SourceAnchor = new Vector2(35,0), + //Target = m_target, + Speed = new Vector2(speed, speed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = true, + Scale = ProjectileScale, + FollowArc = false, + ChaseTarget = false, + TurnSpeed = 0f,//0.02f, + StartingRotation = 0, + Lifespan = 10f, + }; + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new DelayLogicAction(0.5f)); + + LogicSet fireProjectileLS = new LogicSet(this); + fireProjectileLS.AddAction(new PlayAnimationLogicAction(false), Types.Sequence.Parallel); + fireProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileLS.AddAction(new RunFunctionLogicAction(this, "FireProjectileEffect")); + fireProjectileLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Turret_Attack01", "Turret_Attack02", "Turret_Attack03")); + fireProjectileLS.AddAction(new DelayLogicAction(delay)); + + LogicSet fireProjectileAdvancedLS = new LogicSet(this); + fireProjectileAdvancedLS.AddAction(new PlayAnimationLogicAction(false), Types.Sequence.Parallel); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileAdvancedLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Turret_Attack01", "Turret_Attack02", "Turret_Attack03")); + fireProjectileAdvancedLS.AddAction(new DelayLogicAction(0.1f)); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileAdvancedLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Turret_Attack01", "Turret_Attack02", "Turret_Attack03")); + fireProjectileAdvancedLS.AddAction(new DelayLogicAction(0.1f)); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileAdvancedLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Turret_Attack01", "Turret_Attack02", "Turret_Attack03")); + fireProjectileAdvancedLS.AddAction(new RunFunctionLogicAction(this, "FireProjectileEffect")); + fireProjectileAdvancedLS.AddAction(new DelayLogicAction(delay)); + + LogicSet fireProjectileExpertLS = new LogicSet(this); + fireProjectileExpertLS.AddAction(new PlayAnimationLogicAction(false), Types.Sequence.Parallel); + projData.ChaseTarget = true; + projData.Target = m_target; + projData.TurnSpeed = 0.02f;//0.065f; + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileExpertLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Turret_Attack01", "Turret_Attack02", "Turret_Attack03")); + fireProjectileExpertLS.AddAction(new RunFunctionLogicAction(this, "FireProjectileEffect")); + fireProjectileExpertLS.AddAction(new DelayLogicAction(delay)); + + m_generalBasicLB.AddLogicSet(fireProjectileLS, walkStopLS); + m_generalAdvancedLB.AddLogicSet(fireProjectileAdvancedLS, walkStopLS); + m_generalExpertLB.AddLogicSet(fireProjectileExpertLS, walkStopLS); + m_generalMiniBossLB.AddLogicSet(fireProjectileLS, walkStopLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalMiniBossLB); + + projData.Dispose(); + + base.InitializeLogic(); + } + + public void FireProjectileEffect() + { + Vector2 pos = this.Position; + if (this.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.None) + pos.X += 30; + else + pos.X -= 30; + m_levelScreen.ImpactEffectPool.TurretFireEffect(pos, new Vector2(0.5f, 0.5f)); + m_levelScreen.ImpactEffectPool.TurretFireEffect(pos, new Vector2(0.5f, 0.5f)); + m_levelScreen.ImpactEffectPool.TurretFireEffect(pos, new Vector2(0.5f, 0.5f)); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(false, m_generalBasicLB, 100, 0); + break; + case (STATE_WANDER): + default: + RunLogicBlock(false, m_generalBasicLB, 100, 0); + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(false, m_generalAdvancedLB, 100, 0); + break; + case (STATE_WANDER): + default: + RunLogicBlock(false, m_generalAdvancedLB, 100, 0); + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(false, m_generalExpertLB, 100, 0); + break; + case (STATE_WANDER): + default: + RunLogicBlock(false, m_generalExpertLB, 0, 100); + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(false, m_generalBasicLB, 100, 0); + break; + case (STATE_WANDER): + default: + RunLogicBlock(false, m_generalBasicLB, 100, 0); + break; + } + } + + public override void Update(GameTime gameTime) + { + base.Update(gameTime); + } + + public EnemyObj_HomingTurret(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyHomingTurret_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.StopAnimation(); + ForceDraw = true; + this.Type = EnemyType.HomingTurret; + this.PlayAnimationOnRestart = false; + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Horse.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Horse.cs new file mode 100644 index 0000000..23fbe88 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Horse.cs @@ -0,0 +1,611 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class EnemyObj_Horse : EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + + private LogicBlock m_turnLB = new LogicBlock(); + + private int m_wallDistanceCheck = 430; + + private float m_collisionCheckTimer = 0.5f; + private float m_fireDropTimer = 0.5f; + private float m_fireDropInterval = 0.075f; + private float m_fireDropLifespan = 0.75f;//2; + + private int m_numFireShieldObjs = 2;//4;//2; + private float m_fireDistance = 110; + private float m_fireRotationSpeed = 1.5f;//0;//1.5f; + private float m_fireShieldScale = 2.5f; + private List m_fireShieldList; + + private FrameSoundObj m_gallopSound; + + private bool m_turning = false; // Ensures the horse doesn't turn multiple times in a single update. + + protected override void InitializeEV() + { + LockFlip = true; + #region Basic Variables - General + Name = EnemyEV.Horse_Basic_Name; + LocStringID = EnemyEV.Horse_Basic_Name_locID; + + MaxHealth = EnemyEV.Horse_Basic_MaxHealth; + Damage = EnemyEV.Horse_Basic_Damage; + XPValue = EnemyEV.Horse_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Horse_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Horse_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Horse_Basic_DropChance; + + Speed = EnemyEV.Horse_Basic_Speed; + TurnSpeed = EnemyEV.Horse_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Horse_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Horse_Basic_Jump; + CooldownTime = EnemyEV.Horse_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Horse_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Horse_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Horse_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Horse_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Horse_Basic_IsWeighted; + + Scale = EnemyEV.Horse_Basic_Scale; + ProjectileScale = EnemyEV.Horse_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Horse_Basic_Tint; + + MeleeRadius = EnemyEV.Horse_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Horse_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Horse_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Horse_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Horse_Miniboss_Name; + LocStringID = EnemyEV.Horse_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Horse_Miniboss_MaxHealth; + Damage = EnemyEV.Horse_Miniboss_Damage; + XPValue = EnemyEV.Horse_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Horse_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Horse_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Horse_Miniboss_DropChance; + + Speed = EnemyEV.Horse_Miniboss_Speed; + TurnSpeed = EnemyEV.Horse_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Horse_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Horse_Miniboss_Jump; + CooldownTime = EnemyEV.Horse_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Horse_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Horse_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Horse_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Horse_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Horse_Miniboss_IsWeighted; + + Scale = EnemyEV.Horse_Miniboss_Scale; + ProjectileScale = EnemyEV.Horse_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Horse_Miniboss_Tint; + + MeleeRadius = EnemyEV.Horse_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Horse_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Horse_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Horse_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.Horse_Expert_Name; + LocStringID = EnemyEV.Horse_Expert_Name_locID; + + MaxHealth = EnemyEV.Horse_Expert_MaxHealth; + Damage = EnemyEV.Horse_Expert_Damage; + XPValue = EnemyEV.Horse_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Horse_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Horse_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Horse_Expert_DropChance; + + Speed = EnemyEV.Horse_Expert_Speed; + TurnSpeed = EnemyEV.Horse_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Horse_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Horse_Expert_Jump; + CooldownTime = EnemyEV.Horse_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Horse_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Horse_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Horse_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Horse_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Horse_Expert_IsWeighted; + + Scale = EnemyEV.Horse_Expert_Scale; + ProjectileScale = EnemyEV.Horse_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Horse_Expert_Tint; + + MeleeRadius = EnemyEV.Horse_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Horse_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Horse_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Horse_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.Horse_Advanced_Name; + LocStringID = EnemyEV.Horse_Advanced_Name_locID; + + MaxHealth = EnemyEV.Horse_Advanced_MaxHealth; + Damage = EnemyEV.Horse_Advanced_Damage; + XPValue = EnemyEV.Horse_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Horse_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Horse_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Horse_Advanced_DropChance; + + Speed = EnemyEV.Horse_Advanced_Speed; + TurnSpeed = EnemyEV.Horse_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Horse_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Horse_Advanced_Jump; + CooldownTime = EnemyEV.Horse_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Horse_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Horse_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Horse_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Horse_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Horse_Advanced_IsWeighted; + + Scale = EnemyEV.Horse_Advanced_Scale; + ProjectileScale = EnemyEV.Horse_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Horse_Advanced_Tint; + + MeleeRadius = EnemyEV.Horse_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Horse_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Horse_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Horse_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + } + + protected override void InitializeLogic() + { + + LogicSet runLeftLS = new LogicSet(this); + runLeftLS.AddAction(new ChangeSpriteLogicAction("EnemyHorseRun_Character", true, true)); + runLeftLS.AddAction(new MoveDirectionLogicAction(new Vector2(-1,0))); + runLeftLS.AddAction(new DelayLogicAction(0.5f)); + + LogicSet runRightLS = new LogicSet(this); + runRightLS.AddAction(new ChangeSpriteLogicAction("EnemyHorseRun_Character", true, true)); + runRightLS.AddAction(new MoveDirectionLogicAction(new Vector2(1, 0))); + runRightLS.AddAction(new DelayLogicAction(0.5f)); + + LogicSet turnRightLS = new LogicSet(this); + turnRightLS.AddAction(new ChangeSpriteLogicAction("EnemyHorseTurn_Character", true, true)); + turnRightLS.AddAction(new MoveDirectionLogicAction(new Vector2(-1, 0))); + turnRightLS.AddAction(new DelayLogicAction(0.25f)); + turnRightLS.AddAction(new ChangePropertyLogicAction(this, "Flip", SpriteEffects.None)); + turnRightLS.AddAction(new RunFunctionLogicAction(this, "ResetTurn")); + + LogicSet turnLeftLS = new LogicSet(this); + turnLeftLS.AddAction(new ChangeSpriteLogicAction("EnemyHorseTurn_Character", true, true)); + turnLeftLS.AddAction(new MoveDirectionLogicAction(new Vector2(1, 0))); + turnLeftLS.AddAction(new DelayLogicAction(0.25f)); + turnLeftLS.AddAction(new ChangePropertyLogicAction(this, "Flip", SpriteEffects.FlipHorizontally)); + turnLeftLS.AddAction(new RunFunctionLogicAction(this, "ResetTurn")); + + LogicSet runLeftExpertLS = new LogicSet(this); + runLeftExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyHorseRun_Character", true, true)); + runLeftExpertLS.AddAction(new MoveDirectionLogicAction(new Vector2(-1, 0))); + ThrowStandingProjectiles(runLeftExpertLS, true); + //runLeftExpertLS.AddAction(new DelayLogicAction(0.5f)); + + LogicSet runRightExpertLS = new LogicSet(this); + runRightExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyHorseRun_Character", true, true)); + runRightExpertLS.AddAction(new MoveDirectionLogicAction(new Vector2(1, 0))); + ThrowStandingProjectiles(runRightExpertLS, true); + //runRightExpertLS.AddAction(new DelayLogicAction(0.0f)); + + + m_generalBasicLB.AddLogicSet(runLeftLS, runRightLS); + //m_generalExpertLB.AddLogicSet(runLeftExpertLS, runRightExpertLS); + + m_turnLB.AddLogicSet(turnLeftLS, turnRightLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_turnLB); + + m_gallopSound = new FrameSoundObj(this, m_target, 2, "Enemy_Horse_Gallop_01", "Enemy_Horse_Gallop_02", "Enemy_Horse_Gallop_03"); + + base.InitializeLogic(); + } + + private void ThrowStandingProjectiles(LogicSet ls, bool useBossProjectile = false) + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "SpellDamageShield_Sprite", + SourceAnchor = new Vector2(0, 60),//Vector2.Zero, + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(0, 0), + CollidesWithTerrain = false, + Scale = ProjectileScale, + Lifespan = 0.75f,//0.65f,//0.75f + }; + + ls.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"FairyAttack1")); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + ls.AddAction(new DelayLogicAction(0.075f)); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + ls.AddAction(new DelayLogicAction(0.075f)); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Dispose(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + if (this.Flip == SpriteEffects.FlipHorizontally) + RunLogicBlock(true, m_generalBasicLB, 100, 0); // Run to the left. + else + RunLogicBlock(true, m_generalBasicLB, 0, 100); // Run to the right + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + if (this.Flip == SpriteEffects.FlipHorizontally) + RunLogicBlock(true, m_generalBasicLB, 100, 0); // Run to the left. + else + RunLogicBlock(true, m_generalBasicLB, 0, 100); // Run to the right + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + if (this.Flip == SpriteEffects.FlipHorizontally) + RunLogicBlock(true, m_generalBasicLB, 100, 0); // Run to the left. + else + RunLogicBlock(true, m_generalBasicLB, 0, 100); // Run to the right + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + if (this.Flip == SpriteEffects.FlipHorizontally) + RunLogicBlock(true, m_generalBasicLB, 100, 0); // Run to the left. + else + RunLogicBlock(true, m_generalBasicLB, 0, 100); // Run to the right + break; + default: + break; + } + } + + public override void Update(GameTime gameTime) + { + //m_collidingWithGround = false; + //m_collidingWithWall = false; + + //foreach (TerrainObj obj in m_levelScreen.CurrentRoom.TerrainObjList) + //{ + // if (obj.Rotation == 0) + // { + // if (CollisionMath.Intersects(obj.Bounds, WallCollisionPoint) == true) + // m_collidingWithWall = true; + // if (CollisionMath.Intersects(obj.Bounds, GroundCollisionPoint) == true) + // m_collidingWithGround = true; + // } + //} + + //if (m_currentActiveLB != m_turnLB) + //{ + // if (m_collidingWithWall == true || m_collidingWithGround == false) + // { + // if (this.HeadingX < 0) + // { + // m_currentActiveLB.StopLogicBlock(); + // RunLogicBlock(false, m_turnLB, 0, 100); + // } + // else + // { + // m_currentActiveLB.StopLogicBlock(); + // RunLogicBlock(false, m_turnLB, 100, 0); + // } + // } + //} + + if (m_target.AttachedLevel.CurrentRoom.Name != "Ending") + m_gallopSound.Update(); + + float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds; + + if (this.Difficulty >= GameTypes.EnemyDifficulty.ADVANCED) + { + if (m_fireDropTimer > 0) + { + m_fireDropTimer -= elapsedTime; + if (m_fireDropTimer <= 0) + { + DropFireProjectile(); + m_fireDropTimer = m_fireDropInterval; + } + } + } + + if (this.Difficulty == GameTypes.EnemyDifficulty.EXPERT && this.IsPaused == false) + { + if (m_fireShieldList.Count < 1) + CastFireShield(m_numFireShieldObjs); + } + + if (((this.Bounds.Left < m_levelScreen.CurrentRoom.Bounds.Left) || (this.Bounds.Right > m_levelScreen.CurrentRoom.Bounds.Right)) && m_collisionCheckTimer <= 0) + TurnHorse(); + + Rectangle collPt = new Rectangle(); + Rectangle collPt2 = new Rectangle(); // Pt2 is to check for sloped collisions. + if (this.Flip == SpriteEffects.FlipHorizontally) + { + collPt = new Rectangle(this.Bounds.Left - 10, this.Bounds.Bottom + 20, 5, 5); + collPt2 = new Rectangle(this.Bounds.Right + 50, this.Bounds.Bottom - 20, 5, 5); + } + else + { + collPt = new Rectangle(this.Bounds.Right + 10, this.Bounds.Bottom + 20, 5, 5); + collPt2 = new Rectangle(this.Bounds.Left - 50, this.Bounds.Bottom - 20, 5, 5); + } + + + bool turn = true; + foreach (TerrainObj terrain in m_levelScreen.CurrentRoom.TerrainObjList) + { + if (CollisionMath.Intersects(terrain.Bounds, collPt) || CollisionMath.Intersects(terrain.Bounds, collPt2)) + { + turn = false; + break; + } + } + + if (turn == true) + TurnHorse(); + + if (m_collisionCheckTimer > 0) + m_collisionCheckTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds; + + base.Update(gameTime); + } + + public void ResetTurn() + { + m_turning = false; + } + + private void DropFireProjectile() + { + this.UpdateCollisionBoxes(); + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "SpellDamageShield_Sprite", + SourceAnchor = new Vector2(0, (this.Bounds.Bottom - this.Y) - 10), + //Target = m_target, + Speed = new Vector2(0, 0), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + Angle = new Vector2(0, 0), + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = ProjectileScale, + Lifespan = m_fireDropLifespan, + LockPosition = true, + }; + + m_levelScreen.ProjectileManager.FireProjectile(projData); + projData.Dispose(); + } + + private void CastFireShield(int numFires) + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "SpellDamageShield_Sprite", + SourceAnchor = new Vector2(0, (this.Bounds.Bottom - this.Y) - 10), + //Target = m_target, + Speed = new Vector2(m_fireRotationSpeed, m_fireRotationSpeed), + IsWeighted = false, + RotationSpeed = 0, + Target = this, + Damage = Damage, + Angle = new Vector2(0, 0), + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = new Vector2(m_fireShieldScale, m_fireShieldScale), + Lifespan = 999999, + DestroysWithEnemy = false, + LockPosition = true, + }; + + SoundManager.PlaySound("Cast_FireShield"); + float projectileDistance = m_fireDistance; + for (int i = 0; i < (int)numFires; i++) + { + float angle = (360f / numFires) * i; + + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(projData); + proj.AltX = angle; // AltX and AltY are used as holders to hold the projectiles angle and distance from player respectively. + proj.AltY = projectileDistance; + proj.Spell = SpellType.DamageShield; + proj.CanBeFusRohDahed = false; + proj.AccelerationXEnabled = false; + proj.AccelerationYEnabled = false; + proj.IgnoreBoundsCheck = true; + + m_fireShieldList.Add(proj); + } + } + + private void TurnHorse() + { + if (m_turning == false) + { + m_turning = true; + if (this.HeadingX < 0) + { + m_currentActiveLB.StopLogicBlock(); + RunLogicBlock(false, m_turnLB, 0, 100); + } + else + { + m_currentActiveLB.StopLogicBlock(); + RunLogicBlock(false, m_turnLB, 100, 0); + } + m_collisionCheckTimer = 0.5f; + } + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + TerrainObj terrain = otherBox.AbsParent as TerrainObj; + if (otherBox.AbsParent.Bounds.Top < this.TerrainBounds.Bottom - 20 && terrain != null && terrain.CollidesLeft == true && terrain.CollidesRight == true && terrain.CollidesBottom == true) + { + if (collisionResponseType == Consts.COLLISIONRESPONSE_TERRAIN && otherBox.AbsRotation == 0 && m_collisionCheckTimer <= 0) + { + Vector2 mtd = CollisionMath.CalculateMTD(thisBox.AbsRect, otherBox.AbsRect); + if (mtd.X != 0) + TurnHorse(); + } + } + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + public override void HitEnemy(int damage, Vector2 collisionPt, bool isPlayer) + { + SoundManager.Play3DSound(this, m_target, "Enemy_Horse_Hit_01", "Enemy_Horse_Hit_02", "Enemy_Horse_Hit_03"); + base.HitEnemy(damage, collisionPt, isPlayer); + } + + public override void Kill(bool giveXP = true) + { + foreach (ProjectileObj projectile in m_fireShieldList) + projectile.RunDestroyAnimation(false); + + m_fireShieldList.Clear(); + + SoundManager.Play3DSound(this, m_target, "Enemy_Horse_Dead"); + base.Kill(giveXP); + } + + public override void ResetState() + { + m_fireShieldList.Clear(); + base.ResetState(); + } + + public EnemyObj_Horse(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyHorseRun_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.Horse; + m_fireShieldList = new List(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + if (m_gallopSound != null) + m_gallopSound.Dispose(); + m_gallopSound = null; + base.Dispose(); + } + } + + private Rectangle WallCollisionPoint + { + get + { + if (this.HeadingX < 0) + return new Rectangle((int)this.X - m_wallDistanceCheck, (int)this.Y, 2, 2); + else + return new Rectangle((int)this.X + m_wallDistanceCheck, (int)this.Y, 2, 2); + } + } + + private Rectangle GroundCollisionPoint + { + get + { + if (this.HeadingX < 0) + return new Rectangle((int)(this.X - (m_wallDistanceCheck * this.ScaleX)), (int)(this.Y + (60 * this.ScaleY)), 2, 2); + else + return new Rectangle((int)(this.X + (m_wallDistanceCheck * this.ScaleX)), (int)(this.Y + (60 * this.ScaleY)), 2, 2); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_IceWizard.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_IceWizard.cs new file mode 100644 index 0000000..8cab816 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_IceWizard.cs @@ -0,0 +1,562 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_IceWizard : EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + + private float SpellDelay = 0.8f; + //private float SpellInterval = 0.5f; + + private int SpellProjectileCount = 7;//10; + private ProjectileObj m_iceballSummon; + private Vector2 m_spellOffset = new Vector2(40, -80); + + private float TeleportDelay = 0.5f; + private float TeleportDuration = 1.0f; + + private float MoveDuration = 1.0f; + private Vector2 IceScale = Vector2.One; + + private float m_iceParticleEffectCounter = 0.5f; + + protected override void InitializeEV() + { + SpellProjectileCount = 7; + #region Basic Variables - General + Name = EnemyEV.IceWizard_Basic_Name; + LocStringID = EnemyEV.IceWizard_Basic_Name_locID; + + MaxHealth = EnemyEV.IceWizard_Basic_MaxHealth; + Damage = EnemyEV.IceWizard_Basic_Damage; + XPValue = EnemyEV.IceWizard_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.IceWizard_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.IceWizard_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.IceWizard_Basic_DropChance; + + Speed = EnemyEV.IceWizard_Basic_Speed; + TurnSpeed = EnemyEV.IceWizard_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.IceWizard_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.IceWizard_Basic_Jump; + CooldownTime = EnemyEV.IceWizard_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.IceWizard_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.IceWizard_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.IceWizard_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.IceWizard_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.IceWizard_Basic_IsWeighted; + + Scale = EnemyEV.IceWizard_Basic_Scale; + ProjectileScale = EnemyEV.IceWizard_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.IceWizard_Basic_Tint; + + MeleeRadius = EnemyEV.IceWizard_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.IceWizard_Basic_ProjectileRadius; + EngageRadius = EnemyEV.IceWizard_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.IceWizard_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.IceWizard_Miniboss_Name; + LocStringID = EnemyEV.IceWizard_Miniboss_Name_locID; + + MaxHealth = EnemyEV.IceWizard_Miniboss_MaxHealth; + Damage = EnemyEV.IceWizard_Miniboss_Damage; + XPValue = EnemyEV.IceWizard_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.IceWizard_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.IceWizard_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.IceWizard_Miniboss_DropChance; + + Speed = EnemyEV.IceWizard_Miniboss_Speed; + TurnSpeed = EnemyEV.IceWizard_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.IceWizard_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.IceWizard_Miniboss_Jump; + CooldownTime = EnemyEV.IceWizard_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.IceWizard_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.IceWizard_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.IceWizard_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.IceWizard_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.IceWizard_Miniboss_IsWeighted; + + Scale = EnemyEV.IceWizard_Miniboss_Scale; + ProjectileScale = EnemyEV.IceWizard_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.IceWizard_Miniboss_Tint; + + MeleeRadius = EnemyEV.IceWizard_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.IceWizard_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.IceWizard_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.IceWizard_Miniboss_KnockBack; + #endregion + + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + SpellProjectileCount = 8;//14; + SpellDelay = 1.0f; + m_spellOffset = new Vector2(40, -130); + #region Expert Variables - General + Name = EnemyEV.IceWizard_Expert_Name; + LocStringID = EnemyEV.IceWizard_Expert_Name_locID; + + MaxHealth = EnemyEV.IceWizard_Expert_MaxHealth; + Damage = EnemyEV.IceWizard_Expert_Damage; + XPValue = EnemyEV.IceWizard_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.IceWizard_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.IceWizard_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.IceWizard_Expert_DropChance; + + Speed = EnemyEV.IceWizard_Expert_Speed; + TurnSpeed = EnemyEV.IceWizard_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.IceWizard_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.IceWizard_Expert_Jump; + CooldownTime = EnemyEV.IceWizard_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.IceWizard_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.IceWizard_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.IceWizard_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.IceWizard_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.IceWizard_Expert_IsWeighted; + + Scale = EnemyEV.IceWizard_Expert_Scale; + ProjectileScale = EnemyEV.IceWizard_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.IceWizard_Expert_Tint; + + MeleeRadius = EnemyEV.IceWizard_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.IceWizard_Expert_ProjectileRadius; + EngageRadius = EnemyEV.IceWizard_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.IceWizard_Expert_KnockBack; + #endregion + IceScale = new Vector2(2, 2); + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + + SpellProjectileCount = 14; //14; + #region Advanced Variables - General + Name = EnemyEV.IceWizard_Advanced_Name; + LocStringID = EnemyEV.IceWizard_Advanced_Name_locID; + + MaxHealth = EnemyEV.IceWizard_Advanced_MaxHealth; + Damage = EnemyEV.IceWizard_Advanced_Damage; + XPValue = EnemyEV.IceWizard_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.IceWizard_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.IceWizard_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.IceWizard_Advanced_DropChance; + + Speed = EnemyEV.IceWizard_Advanced_Speed; + TurnSpeed = EnemyEV.IceWizard_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.IceWizard_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.IceWizard_Advanced_Jump; + CooldownTime = EnemyEV.IceWizard_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.IceWizard_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.IceWizard_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.IceWizard_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.IceWizard_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.IceWizard_Advanced_IsWeighted; + + Scale = EnemyEV.IceWizard_Advanced_Scale; + ProjectileScale = EnemyEV.IceWizard_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.IceWizard_Advanced_Tint; + + MeleeRadius = EnemyEV.IceWizard_Advanced_MeleeRadius; + EngageRadius = EnemyEV.IceWizard_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.IceWizard_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.IceWizard_Advanced_KnockBack; + #endregion + m_spellOffset = new Vector2(40, -100); + IceScale = new Vector2(1.5f, 1.5f); + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + } + + protected override void InitializeLogic() + { + LogicSet moveTowardsLS = new LogicSet(this); + moveTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardIdle_Character", true, true)); + moveTowardsLS.AddAction(new ChaseLogicAction(m_target, new Vector2(-255, -175), new Vector2(255, -75), true, MoveDuration)); + + LogicSet moveAwayLS = new LogicSet(this); + moveAwayLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardIdle_Character", true, true)); + moveAwayLS.AddAction(new ChaseLogicAction(m_target, false, 1f)); + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardIdle_Character", true, true)); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(0.5f)); + + LogicSet castSpellLS = new LogicSet(this); + castSpellLS.AddAction(new MoveLogicAction(m_target, true, 0)); + castSpellLS.AddAction(new LockFaceDirectionLogicAction(true)); + castSpellLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardSpell_Character")); + castSpellLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeSpell")); + castSpellLS.AddAction(new RunFunctionLogicAction(this, "SummonIceball", null)); + castSpellLS.AddAction(new DelayLogicAction(SpellDelay)); + castSpellLS.AddAction(new RunFunctionLogicAction(this, "ShatterIceball", SpellProjectileCount)); + castSpellLS.AddAction(new PlayAnimationLogicAction("CastSpell", "End"), Types.Sequence.Parallel); + castSpellLS.AddAction(new DelayLogicAction(0.5f)); + castSpellLS.AddAction(new RunFunctionLogicAction(this, "ResetIceball", null)); + castSpellLS.AddAction(new DelayLogicAction(0.5f)); + castSpellLS.AddAction(new LockFaceDirectionLogicAction(false)); + castSpellLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet castSpellExpertLS = new LogicSet(this); + castSpellExpertLS.AddAction(new MoveLogicAction(m_target, true, 0)); + castSpellExpertLS.AddAction(new LockFaceDirectionLogicAction(true)); + castSpellExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardSpell_Character")); + castSpellExpertLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeSpell")); + castSpellExpertLS.AddAction(new RunFunctionLogicAction(this, "SummonIceball", null)); + castSpellExpertLS.AddAction(new DelayLogicAction(SpellDelay)); + castSpellExpertLS.AddAction(new RunFunctionLogicAction(this, "ShatterExpertIceball", SpellProjectileCount)); + castSpellExpertLS.AddAction(new DelayLogicAction(0.135f)); + castSpellExpertLS.AddAction(new RunFunctionLogicAction(this, "ShatterExpertIceball", SpellProjectileCount)); + castSpellExpertLS.AddAction(new DelayLogicAction(0.135f)); + castSpellExpertLS.AddAction(new RunFunctionLogicAction(this, "ShatterExpertIceball", SpellProjectileCount)); + castSpellExpertLS.AddAction(new DelayLogicAction(0.135f)); + castSpellExpertLS.AddAction(new RunFunctionLogicAction(this, "ShatterExpertIceball", SpellProjectileCount)); + castSpellExpertLS.AddAction(new DelayLogicAction(0.135f)); + castSpellExpertLS.AddAction(new RunFunctionLogicAction(this, "ShatterExpertIceball", SpellProjectileCount)); + castSpellExpertLS.AddAction(new DelayLogicAction(0.135f)); + castSpellExpertLS.AddAction(new RunFunctionLogicAction(this, "ShatterExpertIceball", SpellProjectileCount)); + castSpellExpertLS.AddAction(new DelayLogicAction(0.135f)); + castSpellExpertLS.AddAction(new RunFunctionLogicAction(this, "ShatterExpertIceball", SpellProjectileCount)); + castSpellExpertLS.AddAction(new PlayAnimationLogicAction("CastSpell", "End"), Types.Sequence.Parallel); + castSpellExpertLS.AddAction(new DelayLogicAction(0.5f)); + castSpellExpertLS.AddAction(new RunFunctionLogicAction(this, "ResetIceball", null)); + castSpellExpertLS.AddAction(new DelayLogicAction(0.5f)); + castSpellExpertLS.AddAction(new LockFaceDirectionLogicAction(false)); + castSpellExpertLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet teleportLS = new LogicSet(this); + teleportLS.AddAction(new MoveLogicAction(m_target, true, 0)); + teleportLS.AddAction(new LockFaceDirectionLogicAction(true)); + teleportLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 30f)); + teleportLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardTeleportOut_Character", false, false)); + teleportLS.AddAction(new PlayAnimationLogicAction("Start", "BeforeTeleport")); + teleportLS.AddAction(new DelayLogicAction(TeleportDelay)); + teleportLS.AddAction(new PlayAnimationLogicAction("TeleportStart", "End")); + teleportLS.AddAction(new ChangePropertyLogicAction(this, "IsCollidable", false)); + teleportLS.AddAction(new DelayLogicAction(TeleportDuration)); + teleportLS.AddAction(new TeleportLogicAction(m_target, new Vector2(-400, -400), new Vector2(400, 400))); + teleportLS.AddAction(new ChangePropertyLogicAction(this, "IsCollidable", true)); + teleportLS.AddAction(new ChangeSpriteLogicAction("EnemyWizardTeleportIn_Character", true, false)); + teleportLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 10f)); + teleportLS.AddAction(new LockFaceDirectionLogicAction(false)); + teleportLS.AddAction(new DelayLogicAction(0.5f)); + + + m_generalBasicLB.AddLogicSet(moveTowardsLS, moveAwayLS, walkStopLS, castSpellLS, teleportLS); + m_generalAdvancedLB.AddLogicSet(moveTowardsLS, moveAwayLS, walkStopLS, castSpellLS, teleportLS); + m_generalExpertLB.AddLogicSet(moveTowardsLS, moveAwayLS, walkStopLS, castSpellExpertLS, teleportLS); + m_generalCooldownLB.AddLogicSet(moveTowardsLS, moveAwayLS, walkStopLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + + SetCooldownLogicBlock(m_generalCooldownLB, 100, 0, 0); //moveTowardsLS, moveAwayLS, walkStopLS + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 40, 0, 0, 60, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 40, 0, 0, 60, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 40, 0, 0, 60, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 100, 0, 0, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalExpertLB, 0, 0, 100, 0, 0); // moveTowardsLS, moveAwayLS, walkStopLS castSpellLS, teleportLS + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + public EnemyObj_IceWizard(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyWizardIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.PlayAnimation(true); + this.TintablePart = _objectList[0]; + this.Type = EnemyType.IceWizard; + } + + public override void Update(GameTime gameTime) + { + base.Update(gameTime); + if (m_iceballSummon != null) + { + if (this.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.None) + m_iceballSummon.Position = new Vector2(this.X + m_spellOffset.X, this.Y + m_spellOffset.Y); + else + m_iceballSummon.Position = new Vector2(this.X - m_spellOffset.X, this.Y + m_spellOffset.Y); + } + + if (m_iceParticleEffectCounter > 0) + { + m_iceParticleEffectCounter -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_iceParticleEffectCounter <= 0) + { + m_levelScreen.ImpactEffectPool.DisplayIceParticleEffect(this); + m_iceParticleEffectCounter = 0.15f; + } + } + } + + public void SummonIceball() + { + ResetIceball(); + + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "WizardIceSpell_Sprite", + SourceAnchor = m_spellOffset, + Target = null, + Speed = new Vector2(0, 0), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = false, + DestroysWithEnemy = false, + Scale = IceScale, + LockPosition = true, + }; + + SoundManager.Play3DSound(this, m_target,"Ice_Wizard_Form"); + //SoundManager.PlaySound(this, m_target, "Ice_Wizard_Form"); + + //m_iceballSummon = m_levelScreen.ProjectileManager.FireProjectile("WizardIceSpell_Sprite", this, m_spellOffset, 0, 0, false, 0, ProjectileDamage); + m_iceballSummon = m_levelScreen.ProjectileManager.FireProjectile(projData); + m_iceballSummon.PlayAnimation("Start", "Grown"); + + projData.Dispose(); + } + + public void ShatterIceball(int numIceballs) + { + SoundManager.Play3DSound(this, m_target, "Ice_Wizard_Attack_Glass"); + + if (m_iceballSummon.SpriteName == "WizardIceSpell_Sprite") // Temporary hack fix for crashing iceballs. + m_iceballSummon.PlayAnimation("Grown", "End"); + + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "WizardIceProjectile_Sprite", + SourceAnchor = m_spellOffset, + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = ProjectileScale, + }; + + float angle = 0; + float angleDiff = 360 / numIceballs; + + for (int i = 0; i < numIceballs; i++) + { + projData.Angle = new Vector2(angle, angle); + ProjectileObj iceball = m_levelScreen.ProjectileManager.FireProjectile(projData); + Tweener.Tween.RunFunction(0.15f, this, "ChangeIceballState", iceball); + angle += angleDiff; + + } + + projData.Dispose(); + } + + public void ShatterExpertIceball(int numIceballs) + { + SoundManager.Play3DSound(this, m_target, "Ice_Wizard_Attack"); + + if (m_iceballSummon.SpriteName == "WizardIceSpell_Sprite") // Temporary hack fix for crashing iceballs. + m_iceballSummon.PlayAnimation("Grown", "End"); + + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "WizardIceProjectile_Sprite", + SourceAnchor = m_spellOffset, + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = ProjectileScale, + }; + + float angle = 0; + float angleDiff = 60; + + + for (int i = 0; i < numIceballs; i++) + { + angle = CDGMath.RandomInt(0, 360); + projData.Angle = new Vector2(angle, angle); + + ProjectileObj iceball = m_levelScreen.ProjectileManager.FireProjectile(projData); + Tweener.Tween.RunFunction(0.15f, this, "ChangeIceballState", iceball); + angle += angleDiff; + + } + + projData.Dispose(); + } + + public void ChangeIceballState(ProjectileObj iceball) + { + iceball.CollidesWithTerrain = true; + } + + public void ResetIceball() + { + if (m_iceballSummon != null) + { + m_levelScreen.ProjectileManager.DestroyProjectile(m_iceballSummon); + m_iceballSummon = null; + } + } + + //public override void HitEnemy(int damage, Vector2 position, bool isPlayer) + //{ + // base.HitEnemy(damage, position, isPlayer); + // if (m_currentActiveLB != null && m_currentActiveLB.IsActive == true) + // { + // m_currentActiveLB.StopLogicBlock(); + // ResetIceball(); + // } + //} + + public override void Kill(bool giveXP = true) + { + if (m_currentActiveLB != null && m_currentActiveLB.IsActive == true) + { + m_currentActiveLB.StopLogicBlock(); + ResetIceball(); + } + base.Kill(giveXP); + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + if (otherBox.AbsParent is PlayerObj) + this.CurrentSpeed = 0; + if (collisionResponseType != Consts.COLLISIONRESPONSE_TERRAIN) + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + else if ((otherBox.AbsParent is PlayerObj) == false)// Add this else to turn on terrain collision. + { + IPhysicsObj otherPhysicsObj = otherBox.AbsParent as IPhysicsObj; + if (otherPhysicsObj.CollidesBottom == true && otherPhysicsObj.CollidesTop == true && otherPhysicsObj.CollidesLeft == true && otherPhysicsObj.CollidesRight == true) + this.Position += CollisionMath.RotatedRectIntersectsMTD(thisBox.AbsRect, thisBox.AbsRotation, Vector2.Zero, otherBox.AbsRect, otherBox.AbsRotation, Vector2.Zero); + } + } + + public override void ResetState() + { + ResetIceball(); + base.ResetState(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_iceballSummon = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Knight.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Knight.cs new file mode 100644 index 0000000..4468770 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Knight.cs @@ -0,0 +1,659 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_Knight : EnemyObj + { + + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + + private float AttackThrustDelay = 0.65f; + private float AttackThrustSpeed = 1850; + private float AttackThrustDuration = 0.4f; + + private float AttackProjectileDelay = 0.35f; + + private float AttackThrustDelayExpert = 0.65f; + private float AttackThrustSpeedExpert = 1750; + private float AttackThrustDurationExpert = 0.25f; + + private float AttackProjectileExpertDelay = 0.425f; + + private float AttackThrustDelayMiniBoss = 0.65f; + private float AttackThrustSpeedMiniBoss = 2300; + private float AttackThrustDurationMiniBoss = 0.25f; + + private float AttackProjectileMinibossDelay = 0.5f; + + private FrameSoundObj m_walkSound, m_walkSound2; + + protected override void InitializeEV() + { + #region Basic Variables - General + Name = EnemyEV.Knight_Basic_Name; + LocStringID = EnemyEV.Knight_Basic_Name_locID; + + MaxHealth = EnemyEV.Knight_Basic_MaxHealth; + Damage = EnemyEV.Knight_Basic_Damage; + XPValue = EnemyEV.Knight_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Knight_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Knight_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Knight_Basic_DropChance; + + Speed = EnemyEV.Knight_Basic_Speed; + TurnSpeed = EnemyEV.Knight_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Knight_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Knight_Basic_Jump; + CooldownTime = EnemyEV.Knight_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Knight_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Knight_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Knight_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Knight_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Knight_Basic_IsWeighted; + + Scale = EnemyEV.Knight_Basic_Scale; + ProjectileScale = EnemyEV.Knight_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Knight_Basic_Tint; + + MeleeRadius = EnemyEV.Knight_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Knight_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Knight_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Knight_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Knight_Miniboss_Name; + LocStringID = EnemyEV.Knight_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Knight_Miniboss_MaxHealth; + Damage = EnemyEV.Knight_Miniboss_Damage; + XPValue = EnemyEV.Knight_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Knight_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Knight_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Knight_Miniboss_DropChance; + + Speed = EnemyEV.Knight_Miniboss_Speed; + TurnSpeed = EnemyEV.Knight_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Knight_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Knight_Miniboss_Jump; + CooldownTime = EnemyEV.Knight_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Knight_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Knight_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Knight_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Knight_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Knight_Miniboss_IsWeighted; + + Scale = EnemyEV.Knight_Miniboss_Scale; + ProjectileScale = EnemyEV.Knight_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Knight_Miniboss_Tint; + + MeleeRadius = EnemyEV.Knight_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Knight_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Knight_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Knight_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.Knight_Expert_Name; + LocStringID = EnemyEV.Knight_Expert_Name_locID; + + MaxHealth = EnemyEV.Knight_Expert_MaxHealth; + Damage = EnemyEV.Knight_Expert_Damage; + XPValue = EnemyEV.Knight_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Knight_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Knight_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Knight_Expert_DropChance; + + Speed = EnemyEV.Knight_Expert_Speed; + TurnSpeed = EnemyEV.Knight_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Knight_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Knight_Expert_Jump; + CooldownTime = EnemyEV.Knight_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Knight_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Knight_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Knight_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Knight_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Knight_Expert_IsWeighted; + + Scale = EnemyEV.Knight_Expert_Scale; + ProjectileScale = EnemyEV.Knight_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Knight_Expert_Tint; + + MeleeRadius = EnemyEV.Knight_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Knight_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Knight_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Knight_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.Knight_Advanced_Name; + LocStringID = EnemyEV.Knight_Advanced_Name_locID; + + MaxHealth = EnemyEV.Knight_Advanced_MaxHealth; + Damage = EnemyEV.Knight_Advanced_Damage; + XPValue = EnemyEV.Knight_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Knight_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Knight_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Knight_Advanced_DropChance; + + Speed = EnemyEV.Knight_Advanced_Speed; + TurnSpeed = EnemyEV.Knight_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Knight_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Knight_Advanced_Jump; + CooldownTime = EnemyEV.Knight_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Knight_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Knight_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Knight_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Knight_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Knight_Advanced_IsWeighted; + + Scale = EnemyEV.Knight_Advanced_Scale; + ProjectileScale = EnemyEV.Knight_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Knight_Advanced_Tint; + + MeleeRadius = EnemyEV.Knight_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Knight_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Knight_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Knight_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + } + + protected override void InitializeLogic() + { + //////////////// Movement Logic //////////////////////// + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightWalk_Character", true, true)); + walkTowardsLS.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsLS.AddAction(new DelayLogicAction(0.2f, 1.0f)); + + LogicSet walkAwayLS = new LogicSet(this); + walkAwayLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightWalk_Character", true, true)); + walkAwayLS.AddAction(new MoveLogicAction(m_target, false)); + walkAwayLS.AddAction(new DelayLogicAction(0.2f, 1.0f)); + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightIdle_Character", true, true)); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(0.2f, 1.0f)); + ///////////////////////////////////////////////////////// + + //////////////// Attack Logic //////////////////// + LogicSet attackThrustLS = new LogicSet(this); + attackThrustLS.AddAction(new MoveLogicAction(m_target, true, 0)); // Sets the enemy to face the player. + attackThrustLS.AddAction(new LockFaceDirectionLogicAction(true)); // Lock his facing direction. + attackThrustLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightAttack_Character")); + attackThrustLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + attackThrustLS.AddAction(new DelayLogicAction(AttackThrustDelay)); //The tell + attackThrustLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnightAttack1")); + //attackThrustLS.AddAction(new MoveLogicAction(null, true, AttackThrustSpeed)); //The speed of his thrust. + attackThrustLS.AddAction(new MoveDirectionLogicAction(AttackThrustSpeed)); + attackThrustLS.AddAction(new RunFunctionLogicAction(m_levelScreen.ImpactEffectPool, "DisplayThrustDustEffect", this, 20, 0.3f)); + attackThrustLS.AddAction(new PlayAnimationLogicAction("AttackStart","End", false), Types.Sequence.Parallel); + attackThrustLS.AddAction(new DelayLogicAction(AttackThrustDuration)); //The length of his thrust. + attackThrustLS.AddAction(new MoveLogicAction(null, true, 0)); + attackThrustLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightIdle_Character", true, true)); + attackThrustLS.AddAction(new DelayLogicAction(0.3f)); + attackThrustLS.AddAction(new LockFaceDirectionLogicAction(false)); + attackThrustLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet attackThrustExpertLS = new LogicSet(this); + attackThrustExpertLS.AddAction(new MoveLogicAction(m_target, true, 0)); + attackThrustExpertLS.AddAction(new LockFaceDirectionLogicAction(true)); + attackThrustExpertLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightAttack_Character")); + attackThrustExpertLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + attackThrustExpertLS.AddAction(new DelayLogicAction(AttackThrustDelayExpert)); //The tell + attackThrustExpertLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnightAttack1")); + attackThrustExpertLS.AddAction(new MoveDirectionLogicAction(AttackThrustSpeedExpert)); + attackThrustExpertLS.AddAction(new RunFunctionLogicAction(m_levelScreen.ImpactEffectPool, "DisplayThrustDustEffect", this, 20, 0.3f)); + attackThrustExpertLS.AddAction(new PlayAnimationLogicAction("AttackStart","End", false), Types.Sequence.Parallel); + attackThrustExpertLS.AddAction(new DelayLogicAction(AttackThrustDurationExpert)); //The length of his thrust. + attackThrustExpertLS.AddAction(new MoveLogicAction(null, true, 0)); + attackThrustExpertLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightIdle_Character", true, true)); + attackThrustExpertLS.AddAction(new DelayLogicAction(0.3f)); + attackThrustExpertLS.AddAction(new LockFaceDirectionLogicAction(false)); + attackThrustExpertLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet attackThrustMinibossLS = new LogicSet(this); + attackThrustMinibossLS.AddAction(new MoveLogicAction(m_target, true, 0)); + attackThrustMinibossLS.AddAction(new LockFaceDirectionLogicAction(true)); + attackThrustMinibossLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightAttack_Character")); + attackThrustMinibossLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + attackThrustMinibossLS.AddAction(new DelayLogicAction(AttackThrustDelayMiniBoss)); //The tell + attackThrustMinibossLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnightAttack1")); + attackThrustMinibossLS.AddAction(new MoveDirectionLogicAction(AttackThrustSpeedMiniBoss)); + attackThrustMinibossLS.AddAction(new RunFunctionLogicAction(m_levelScreen.ImpactEffectPool, "DisplayThrustDustEffect", this, 20, 0.3f)); + attackThrustMinibossLS.AddAction(new PlayAnimationLogicAction("AttackStart", "End", false), Types.Sequence.Parallel); + attackThrustMinibossLS.AddAction(new DelayLogicAction(AttackThrustDurationMiniBoss)); //The length of his thrust. + attackThrustMinibossLS.AddAction(new MoveLogicAction(null, true, 0)); + attackThrustMinibossLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightIdle_Character", true, true)); + attackThrustMinibossLS.AddAction(new LockFaceDirectionLogicAction(false)); + attackThrustMinibossLS.AddAction(new MoveLogicAction(m_target, true, 0)); + attackThrustMinibossLS.AddAction(new LockFaceDirectionLogicAction(true)); + // + attackThrustMinibossLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightAttack_Character")); + attackThrustMinibossLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + attackThrustMinibossLS.AddAction(new DelayLogicAction(0.25f)); //The tell + attackThrustMinibossLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnightAttack1")); + attackThrustMinibossLS.AddAction(new MoveDirectionLogicAction(AttackThrustSpeedMiniBoss)); + attackThrustMinibossLS.AddAction(new RunFunctionLogicAction(m_levelScreen.ImpactEffectPool, "DisplayThrustDustEffect", this, 20, 0.3f)); + attackThrustMinibossLS.AddAction(new PlayAnimationLogicAction("AttackStart", "End", false), Types.Sequence.Parallel); + attackThrustMinibossLS.AddAction(new DelayLogicAction(AttackThrustDurationMiniBoss)); //The length of his thrust. + attackThrustMinibossLS.AddAction(new MoveLogicAction(null, true, 0)); + attackThrustMinibossLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightIdle_Character", true, true)); + attackThrustMinibossLS.AddAction(new LockFaceDirectionLogicAction(false)); + attackThrustMinibossLS.AddAction(new MoveLogicAction(m_target, true, 0)); + attackThrustMinibossLS.AddAction(new LockFaceDirectionLogicAction(true)); + // + attackThrustMinibossLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightAttack_Character")); + attackThrustMinibossLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + attackThrustMinibossLS.AddAction(new DelayLogicAction(0.25f)); //The tell + attackThrustMinibossLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnightAttack1")); + attackThrustMinibossLS.AddAction(new MoveDirectionLogicAction(AttackThrustSpeedMiniBoss)); + attackThrustMinibossLS.AddAction(new RunFunctionLogicAction(m_levelScreen.ImpactEffectPool, "DisplayThrustDustEffect", this, 20, 0.3f)); + attackThrustMinibossLS.AddAction(new PlayAnimationLogicAction("AttackStart", "End", false), Types.Sequence.Parallel); + attackThrustMinibossLS.AddAction(new DelayLogicAction(AttackThrustDurationMiniBoss)); //The length of his thrust. + attackThrustMinibossLS.AddAction(new MoveLogicAction(null, true, 0)); + attackThrustMinibossLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightIdle_Character", true, true)); + attackThrustMinibossLS.AddAction(new DelayLogicAction(0.3f)); + attackThrustMinibossLS.AddAction(new LockFaceDirectionLogicAction(false)); + attackThrustMinibossLS.Tag = GameTypes.LogicSetType_ATTACK; + + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "EnemySpearKnightWave_Sprite", + SourceAnchor = new Vector2(30, 0), + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(0,0), + Scale = ProjectileScale, + }; + + LogicSet throwSpearLS = new LogicSet(this); + throwSpearLS.AddAction(new MoveLogicAction(m_target, true, 0)); + throwSpearLS.AddAction(new LockFaceDirectionLogicAction(true)); + throwSpearLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightAttack2_Character")); + throwSpearLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + throwSpearLS.AddAction(new DelayLogicAction(AttackProjectileDelay)); + throwSpearLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnightAttack1")); + throwSpearLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnight_Projectile")); + throwSpearLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + //throwSpearLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "EnemySpearKnightWave_Sprite", new Vector2(30, 0), 0, ProjectileSpeed, false, 0, Damage)); + throwSpearLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + throwSpearLS.AddAction(new DelayLogicAction(0.3f)); + throwSpearLS.AddAction(new LockFaceDirectionLogicAction(false)); + throwSpearLS.Tag = GameTypes.LogicSetType_ATTACK; + + + + LogicSet throwSpearExpertLS = new LogicSet(this); + throwSpearExpertLS.AddAction(new MoveLogicAction(m_target, true, 0)); + throwSpearExpertLS.AddAction(new LockFaceDirectionLogicAction(true)); + throwSpearExpertLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightAttack2_Character")); + throwSpearExpertLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + throwSpearExpertLS.AddAction(new DelayLogicAction(AttackProjectileExpertDelay)); + ThrowThreeProjectiles(throwSpearExpertLS); + throwSpearExpertLS.AddAction(new DelayLogicAction(0.3f)); + throwSpearExpertLS.AddAction(new LockFaceDirectionLogicAction(false)); + throwSpearExpertLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet throwSpearMiniBossLS = new LogicSet(this); + throwSpearMiniBossLS.AddAction(new MoveLogicAction(m_target, true, 0)); + throwSpearMiniBossLS.AddAction(new LockFaceDirectionLogicAction(true)); + throwSpearMiniBossLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightAttack2_Character")); + throwSpearMiniBossLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + throwSpearMiniBossLS.AddAction(new DelayLogicAction(AttackProjectileMinibossDelay)); + throwSpearMiniBossLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnight_Projectile")); + throwSpearMiniBossLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 30f)); + ThrowTwoProjectiles(throwSpearMiniBossLS); + // + throwSpearMiniBossLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightAttack2_Character")); + throwSpearMiniBossLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + throwSpearMiniBossLS.AddAction(new DelayLogicAction(0.05f)); + ThrowThreeProjectiles(throwSpearMiniBossLS); + throwSpearMiniBossLS.AddAction(new DelayLogicAction(0.05f)); + // + throwSpearMiniBossLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightAttack2_Character")); + throwSpearMiniBossLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + throwSpearMiniBossLS.AddAction(new DelayLogicAction(0.05f)); + ThrowTwoProjectiles(throwSpearMiniBossLS); + throwSpearMiniBossLS.AddAction(new DelayLogicAction(0.5f)); + // + throwSpearMiniBossLS.AddAction(new LockFaceDirectionLogicAction(false)); + throwSpearMiniBossLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / EnemyEV.Knight_Miniboss_AnimationDelay)); + throwSpearMiniBossLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet throwSpearMiniBossAltLS = new LogicSet(this); + throwSpearMiniBossAltLS.AddAction(new MoveLogicAction(m_target, true, 0)); + throwSpearMiniBossAltLS.AddAction(new LockFaceDirectionLogicAction(true)); + throwSpearMiniBossAltLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightAttack2_Character")); + throwSpearMiniBossAltLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + throwSpearMiniBossAltLS.AddAction(new DelayLogicAction(AttackProjectileMinibossDelay)); + throwSpearMiniBossAltLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnight_Projectile")); + throwSpearMiniBossAltLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 30f)); + ThrowThreeProjectiles(throwSpearMiniBossAltLS); + // + throwSpearMiniBossAltLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightAttack2_Character")); + throwSpearMiniBossAltLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + throwSpearMiniBossAltLS.AddAction(new DelayLogicAction(0.05f)); + ThrowTwoProjectiles(throwSpearMiniBossAltLS); + throwSpearMiniBossAltLS.AddAction(new DelayLogicAction(0.05f)); + // + throwSpearMiniBossAltLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightAttack2_Character")); + throwSpearMiniBossAltLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + throwSpearMiniBossAltLS.AddAction(new DelayLogicAction(0.05f)); + ThrowThreeProjectiles(throwSpearMiniBossAltLS); + throwSpearMiniBossAltLS.AddAction(new DelayLogicAction(0.5f)); + // + throwSpearMiniBossAltLS.AddAction(new LockFaceDirectionLogicAction(false)); + throwSpearMiniBossAltLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / EnemyEV.Knight_Miniboss_AnimationDelay)); + throwSpearMiniBossAltLS.Tag = GameTypes.LogicSetType_ATTACK; + #region - OLD THROW EXPERT SPEAR CODE + + /* + LogicSet throwSpearExpertLS = new LogicSet(this); + throwSpearExpertLS.AddAction(new MoveLogicAction(m_target, true, 0)); + throwSpearExpertLS.AddAction(new LockFaceDirectionLogicAction(true)); + throwSpearExpertLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightAttack2_Character")); + throwSpearExpertLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + throwSpearExpertLS.AddAction(new DelayLogicAction(AttackProjectileDelay)); + throwSpearExpertLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + throwSpearExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "EnemySpearKnightWave_Sprite", new Vector2(30, 0), 0, ProjectileSpeed, false, 0, Damage)); + throwSpearExpertLS.AddAction(new DelayLogicAction(0.3f)); + throwSpearExpertLS.AddAction(new JumpLogicAction()); + throwSpearExpertLS.AddAction(new DelayLogicAction(0.1f)); + throwSpearExpertLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + throwSpearExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "EnemySpearKnightWave_Sprite", new Vector2(30, 0), 0, ProjectileSpeed, false, 0, Damage)); + throwSpearExpertLS.AddAction(new GroundCheckLogicAction()); + throwSpearExpertLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + throwSpearExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "EnemySpearKnightWave_Sprite", new Vector2(30, 0), 0, ProjectileSpeed, false, 0, Damage)); + */ + # endregion + ///////////////////////////////////////////////////////// + + #region Old Jump spear logic + LogicSet jumpSpearMany = new LogicSet(this); + attackThrustLS.AddAction(new ChangeSpriteLogicAction("EnemySpearKnightIdle_Character", true, true)); + jumpSpearMany.AddAction(new MoveLogicAction(m_target, false, 300)); + jumpSpearMany.AddAction(new JumpLogicAction()); + jumpSpearMany.AddAction(new DelayLogicAction(0.3f)); + jumpSpearMany.AddAction(new GroundCheckLogicAction()); + jumpSpearMany.AddAction(new JumpLogicAction()); + ThrowRapidProjectiles(jumpSpearMany); + ThrowRapidProjectiles(jumpSpearMany); + ThrowRapidProjectiles(jumpSpearMany); + jumpSpearMany.AddAction(new GroundCheckLogicAction()); + jumpSpearMany.AddAction(new MoveLogicAction(m_target, true, 0)); + jumpSpearMany.AddAction(new DelayLogicAction(0.1f)); + jumpSpearMany.AddAction(new JumpLogicAction()); + ThrowRapidProjectiles(jumpSpearMany); + ThrowRapidProjectiles(jumpSpearMany); + ThrowRapidProjectiles(jumpSpearMany); + jumpSpearMany.AddAction(new GroundCheckLogicAction()); + jumpSpearMany.AddAction(new MoveLogicAction(m_target, true, 0)); + //jumpSpearMany.AddAction(new DelayLogicAction(1.0f)); + jumpSpearMany.Tag = GameTypes.LogicSetType_ATTACK; + #endregion + + + m_generalBasicLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, attackThrustLS, throwSpearLS); + m_generalAdvancedLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, attackThrustLS, throwSpearLS); + m_generalExpertLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, attackThrustExpertLS, throwSpearExpertLS); + m_generalMiniBossLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, attackThrustMinibossLS, throwSpearMiniBossLS, throwSpearMiniBossAltLS); + m_generalCooldownLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalMiniBossLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + + SetCooldownLogicBlock(m_generalCooldownLB, 55, 25, 20); //walkTowardsLS, walkAwayLS, walkStopLS + + projData.Dispose(); + + base.InitializeLogic(); + + } + + private void ThrowThreeProjectiles(LogicSet ls) + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "EnemySpearKnightWave_Sprite", + SourceAnchor = new Vector2(30, 0), + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(0, 0), + Scale = ProjectileScale, + }; + + ls.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnight_Projectile")); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(45, 45); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-45, -45); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + //ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "EnemySpearKnightWave_Sprite", new Vector2(30, 0), 0, ProjectileSpeed, false, 0, Damage)); + //ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "EnemySpearKnightWave_Sprite", new Vector2(30, 0), 45, ProjectileSpeed, false, 0, Damage)); + //ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "EnemySpearKnightWave_Sprite", new Vector2(30, 0), -45, ProjectileSpeed, false, 0, Damage)); + ls.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + + projData.Dispose(); + } + + private void ThrowTwoProjectiles(LogicSet ls) + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "EnemySpearKnightWave_Sprite", + SourceAnchor = new Vector2(30, 0), + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(22, 22), + }; + + ls.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnightAttack1")); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-22, -22); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + //ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "EnemySpearKnightWave_Sprite", new Vector2(30, 0), 22, ProjectileSpeed, false, 0, Damage)); + //ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "EnemySpearKnightWave_Sprite", new Vector2(30, 0), -22, ProjectileSpeed, false, 0, Damage)); + ls.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + projData.Dispose(); + } + + private void ThrowRapidProjectiles(LogicSet ls) + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "EnemySpearKnightWave_Sprite", + SourceAnchor = new Vector2(130, -28), + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = Vector2.Zero, + }; + + + ls.AddAction(new DelayLogicAction(0.2f, 0.35f)); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + //ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "EnemySpearKnightWave_Sprite", new Vector2(130, -28), 0, ProjectileSpeed, false, 0, Damage)); + ls.AddAction(new DelayLogicAction(0.2f, 0.35f)); + projData.SourceAnchor = new Vector2(130, 28); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + //ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "EnemySpearnightWave_Sprite", new Vector2(130, 28), 0, ProjectileSpeed, false, 0, Damage)); + + projData.Dispose(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 20, 15, 0, 0, 65); //walkTowardsLS, walkAwayLS, walkStopLS, attackThrustLS,throwSpearLS + break; + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 20, 20, 10, 0, 50); //walkTowardsLS, walkAwayLS, walkStopLS, attackThrustLS, throwSpearLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 55, 30, 0, 0, 15); //walkTowardsLS, walkAwayLS, walkStopLS, attackThrustLS, throwSpearLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, attackThrustLS, throwSpearLS + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 15, 10, 0, 60, 15); //walkTowardsLS, walkAwayLS, walkStopLS, attackThrustLS,throwSpearLS + break; + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 15, 15, 10, 15, 45); //walkTowardsLS, walkAwayLS, walkStopLS, attackThrustLS, throwSpearLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 55, 30, 0, 0, 15); //walkTowardsLS, walkAwayLS, walkStopLS, attackThrustLS, throwSpearLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalAdvancedLB, 0, 0, 100, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, attackThrustLS, throwSpearLS + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 15, 10, 0, 60, 15); //walkTowardsLS, walkAwayLS, walkStopLS, attackThrustLS,throwSpearLS + break; + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 15, 15, 10, 15, 45); //walkTowardsLS, walkAwayLS, walkStopLS, attackThrustLS, throwSpearLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 55, 30, 0, 0, 15); //walkTowardsLS, walkAwayLS, walkStopLS, attackThrustLS, throwSpearLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalExpertLB, 0, 0, 100, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, attackThrustLS, throwSpearLS + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + RunLogicBlock(true, m_generalMiniBossLB, 14, 13, 11, 26, 18, 18); //walkTowardsLS, walkAwayLS, walkStopLS, attackThrustMinibossLS, throwSpearMiniBossLS, throwSpearMiniBossAltLS + break; + default: + break; + } + } + + public override void Update(GameTime gameTime) + { + if (this.SpriteName == "EnemySpearKnightWalk_Character") + { + m_walkSound.Update(); + m_walkSound2.Update(); + } + base.Update(gameTime); + } + + public override void HitEnemy(int damage, Vector2 position, bool isPlayer) + { + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Knight_Hit01", "Knight_Hit02", "Knight_Hit03"); + base.HitEnemy(damage, position, isPlayer); + } + + + public EnemyObj_Knight(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemySpearKnightIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + TintablePart = _objectList[1]; + this.Type = EnemyType.Knight; + m_walkSound = new FrameSoundObj(this, m_target, 1, "KnightWalk1", "KnightWalk2"); + m_walkSound2 = new FrameSoundObj(this, m_target, 6, "KnightWalk1", "KnightWalk2"); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_walkSound.Dispose(); + m_walkSound = null; + m_walkSound2.Dispose(); + m_walkSound2 = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_LastBoss.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_LastBoss.cs new file mode 100644 index 0000000..309cae8 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_LastBoss.cs @@ -0,0 +1,1904 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Microsoft.Xna.Framework.Graphics; +using Tweener.Ease; + +namespace RogueCastle +{ + public class EnemyObj_LastBoss : EnemyObj + { + private FrameSoundObj m_walkUpSoundFinalBoss; + private FrameSoundObj m_walkDownSoundFinalBoss; + + private Vector2 AxeSpellScale = new Vector2(3.0f, 3.0f); + private float AxeProjectileSpeed = 1100; + + private Vector2 DaggerSpellScale = new Vector2(3.5f, 3.5f); + private float DaggerProjectileSpeed = 900;//875;//750; + + private float m_Spell_Close_Lifespan = 6;//8; + private float m_Spell_Close_Scale = 3.5f; + + private int MegaFlyingDaggerProjectileSpeed = 2350;//2250;//2500; //3000 + private int MegaFlyingSwordAmount = 29;//31;//35;//35;//50; + + private int MegaUpwardSwordProjectileSpeed = 2450;//2250; + private int MegaUpwardSwordProjectileAmount = 8;//7;//8;//15; + + + private int m_Mega_Shield_Distance = 525;//550;//650;//500;//400; + private float m_Mega_Shield_Scale = 4.0f;//3.0f;//400; + private float m_Mega_Shield_Speed = 1.0f;//1.15f;//1.25f; + + private int m_numSpears = 26; + private float m_spearDuration = 1.75f;//2.25f;//3;//5; + + private bool m_isHurt; + private bool m_isDashing; + private bool m_inSecondForm; + private float m_smokeCounter = 0.05f; + private float m_castDelay = 0.25f;//0.5f; + private int m_orbsEasy = 1;//1; + private int m_orbsNormal = 2;//3; + private int m_orbsHard = 3;//3;//5; + private float m_lastBossAttackDelay = 0.35f;//0.25f; + + private bool m_shake = false; + private bool m_shookLeft = false; + + private float m_shakeTimer = 0; + private float m_shakeDuration = 0.03f; + + private List m_damageShieldProjectiles; + + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_damageShieldLB = new LogicBlock(); + private LogicBlock m_cooldownLB = new LogicBlock(); + private LogicBlock m_secondFormCooldownLB = new LogicBlock(); + private LogicBlock m_firstFormDashAwayLB = new LogicBlock(); + + private LogicBlock m_generalBasicNeoLB = new LogicBlock(); + + + private bool m_firstFormDying = false; + private float m_teleportDuration = 0; + private BlankObj m_delayObj; + + private bool m_isNeo = false; + private bool m_neoDying = false; + + private ProjectileData m_daggerProjData; + private ProjectileData m_axeProjData; + + protected override void InitializeEV() + { + #region Basic Variables - General + Name = EnemyEV.LastBoss_Basic_Name; + LocStringID = EnemyEV.LastBoss_Basic_Name_locID; + + MaxHealth = EnemyEV.LastBoss_Basic_MaxHealth; + Damage = EnemyEV.LastBoss_Basic_Damage; + XPValue = EnemyEV.LastBoss_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.LastBoss_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.LastBoss_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.LastBoss_Basic_DropChance; + + Speed = EnemyEV.LastBoss_Basic_Speed; + TurnSpeed = EnemyEV.LastBoss_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.LastBoss_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.LastBoss_Basic_Jump; + CooldownTime = EnemyEV.LastBoss_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.LastBoss_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.LastBoss_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.LastBoss_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.LastBoss_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.LastBoss_Basic_IsWeighted; + + Scale = EnemyEV.LastBoss_Basic_Scale; + ProjectileScale = EnemyEV.LastBoss_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.LastBoss_Basic_Tint; + + MeleeRadius = EnemyEV.LastBoss_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.LastBoss_Basic_ProjectileRadius; + EngageRadius = EnemyEV.LastBoss_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.LastBoss_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.LastBoss_Miniboss_Name; + LocStringID = EnemyEV.LastBoss_Miniboss_Name_locID; + + MaxHealth = EnemyEV.LastBoss_Miniboss_MaxHealth; + Damage = EnemyEV.LastBoss_Miniboss_Damage; + XPValue = EnemyEV.LastBoss_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.LastBoss_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.LastBoss_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.LastBoss_Miniboss_DropChance; + + Speed = EnemyEV.LastBoss_Miniboss_Speed; + TurnSpeed = EnemyEV.LastBoss_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.LastBoss_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.LastBoss_Miniboss_Jump; + CooldownTime = EnemyEV.LastBoss_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.LastBoss_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.LastBoss_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.LastBoss_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.LastBoss_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.LastBoss_Miniboss_IsWeighted; + + Scale = EnemyEV.LastBoss_Miniboss_Scale; + ProjectileScale = EnemyEV.LastBoss_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.LastBoss_Miniboss_Tint; + + MeleeRadius = EnemyEV.LastBoss_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.LastBoss_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.LastBoss_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.LastBoss_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.LastBoss_Expert_Name; + LocStringID = EnemyEV.LastBoss_Expert_Name_locID; + + MaxHealth = EnemyEV.LastBoss_Expert_MaxHealth; + Damage = EnemyEV.LastBoss_Expert_Damage; + XPValue = EnemyEV.LastBoss_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.LastBoss_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.LastBoss_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.LastBoss_Expert_DropChance; + + Speed = EnemyEV.LastBoss_Expert_Speed; + TurnSpeed = EnemyEV.LastBoss_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.LastBoss_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.LastBoss_Expert_Jump; + CooldownTime = EnemyEV.LastBoss_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.LastBoss_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.LastBoss_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.LastBoss_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.LastBoss_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.LastBoss_Expert_IsWeighted; + + Scale = EnemyEV.LastBoss_Expert_Scale; + ProjectileScale = EnemyEV.LastBoss_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.LastBoss_Expert_Tint; + + MeleeRadius = EnemyEV.LastBoss_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.LastBoss_Expert_ProjectileRadius; + EngageRadius = EnemyEV.LastBoss_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.LastBoss_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.LastBoss_Advanced_Name; + LocStringID = EnemyEV.LastBoss_Advanced_Name_locID; + + MaxHealth = EnemyEV.LastBoss_Advanced_MaxHealth; + Damage = EnemyEV.LastBoss_Advanced_Damage; + XPValue = EnemyEV.LastBoss_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.LastBoss_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.LastBoss_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.LastBoss_Advanced_DropChance; + + Speed = EnemyEV.LastBoss_Advanced_Speed; + TurnSpeed = EnemyEV.LastBoss_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.LastBoss_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.LastBoss_Advanced_Jump; + CooldownTime = EnemyEV.LastBoss_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.LastBoss_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.LastBoss_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.LastBoss_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.LastBoss_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.LastBoss_Advanced_IsWeighted; + + Scale = EnemyEV.LastBoss_Advanced_Scale; + ProjectileScale = EnemyEV.LastBoss_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.LastBoss_Advanced_Tint; + + MeleeRadius = EnemyEV.LastBoss_Advanced_MeleeRadius; + EngageRadius = EnemyEV.LastBoss_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.LastBoss_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.LastBoss_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + this.AnimationDelay = 1 / 10f; + if (LevelEV.WEAKEN_BOSSES == true) + this.MaxHealth = 1; + break; + } + + + } + + protected override void InitializeLogic() + { + #region First Form Logic + //////////////////////////////// FIRST FORM LOGIC + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new DebugTraceLogicAction("WalkTowardSLS")); + walkTowardsLS.AddAction(new ChangePropertyLogicAction(this, "CanBeKnockedBack", true)); + walkTowardsLS.AddAction(new GroundCheckLogicAction()); + walkTowardsLS.AddAction(new ChangeSpriteLogicAction("PlayerWalking_Character", true, true)); + walkTowardsLS.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsLS.AddAction(new LockFaceDirectionLogicAction(true)); + walkTowardsLS.AddAction(new DelayLogicAction(0.3f, 0.75f)); + walkTowardsLS.AddAction(new LockFaceDirectionLogicAction(false)); + + LogicSet walkAwayLS = new LogicSet(this); + walkAwayLS.AddAction(new DebugTraceLogicAction("WalkAway")); + walkAwayLS.AddAction(new ChangePropertyLogicAction(this, "CanBeKnockedBack", true)); + walkAwayLS.AddAction(new GroundCheckLogicAction()); + walkAwayLS.AddAction(new ChangeSpriteLogicAction("PlayerWalking_Character", true, true)); + walkAwayLS.AddAction(new MoveLogicAction(m_target, false)); + //walkAwayLS.AddAction(new LockFaceDirectionLogicAction(true)); + walkAwayLS.AddAction(new DelayLogicAction(0.2f, 0.75f)); + walkAwayLS.AddAction(new LockFaceDirectionLogicAction(false)); + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new DebugTraceLogicAction("walkStop")); + walkStopLS.AddAction(new ChangePropertyLogicAction(this, "CanBeKnockedBack", true)); + walkStopLS.AddAction(new GroundCheckLogicAction()); + walkStopLS.AddAction(new ChangeSpriteLogicAction("PlayerIdle_Character", true, true)); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(0.25f, 0.5f)); + + LogicSet attackLS = new LogicSet(this); + attackLS.AddAction(new DebugTraceLogicAction("attack")); + attackLS.AddAction(new ChangePropertyLogicAction(this, "CanBeKnockedBack", true)); + attackLS.AddAction(new MoveLogicAction(m_target, true, 0)); + attackLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 20f)); + attackLS.AddAction(new LockFaceDirectionLogicAction(true)); + attackLS.AddAction(new ChangeSpriteLogicAction("PlayerAttacking3_Character", false, false)); + attackLS.AddAction(new PlayAnimationLogicAction(2, 4)); + attackLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Player_Attack01", "Player_Attack02")); + attackLS.AddAction(new PlayAnimationLogicAction("AttackStart", "End")); + attackLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 10f)); + attackLS.AddAction(new ChangeSpriteLogicAction("PlayerIdle_Character", true, true)); + attackLS.AddAction(new LockFaceDirectionLogicAction(false)); + attackLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet moveAttackLS = new LogicSet(this); + moveAttackLS.AddAction(new DebugTraceLogicAction("moveattack")); + moveAttackLS.AddAction(new ChangePropertyLogicAction(this, "CanBeKnockedBack", true)); + moveAttackLS.AddAction(new MoveLogicAction(m_target, true)); + moveAttackLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 20f)); + moveAttackLS.AddAction(new LockFaceDirectionLogicAction(true)); + moveAttackLS.AddAction(new ChangeSpriteLogicAction("PlayerAttacking3_Character", false, false)); + moveAttackLS.AddAction(new PlayAnimationLogicAction(2, 4)); + moveAttackLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Player_Attack01", "Player_Attack02")); + moveAttackLS.AddAction(new PlayAnimationLogicAction("AttackStart", "End")); + moveAttackLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 10f)); + moveAttackLS.AddAction(new ChangeSpriteLogicAction("PlayerIdle_Character", true, true)); + moveAttackLS.AddAction(new LockFaceDirectionLogicAction(false)); + moveAttackLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet throwShieldLS = new LogicSet(this); + throwShieldLS.AddAction(new DebugTraceLogicAction("Throwing Daggers")); + throwShieldLS.AddAction(new MoveLogicAction(m_target, true, 0)); + throwShieldLS.AddAction(new LockFaceDirectionLogicAction(true)); + throwShieldLS.AddAction(new ChangeSpriteLogicAction("PlayerLevelUp_Character")); + throwShieldLS.AddAction(new PlayAnimationLogicAction(false)); + //CastCloseShield(throwShieldLS); + throwShieldLS.AddAction(new RunFunctionLogicAction(this, "CastCloseShield")); + throwShieldLS.AddAction(new LockFaceDirectionLogicAction(false)); + throwShieldLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet throwDaggerLS = new LogicSet(this); + throwDaggerLS.AddAction(new DebugTraceLogicAction("Throwing Daggers")); + throwDaggerLS.AddAction(new ChangePropertyLogicAction(this, "CanBeKnockedBack", true)); + throwDaggerLS.AddAction(new MoveLogicAction(m_target, true, 0)); + throwDaggerLS.AddAction(new LockFaceDirectionLogicAction(true)); + throwDaggerLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 30f)); + throwDaggerLS.AddAction(new ChangePropertyLogicAction(this, "CanBeKnockedBack", false)); + throwDaggerLS.AddAction(new ChangeSpriteLogicAction("PlayerLevelUp_Character")); + throwDaggerLS.AddAction(new PlayAnimationLogicAction(false)); + throwDaggerLS.AddAction(new RunFunctionLogicAction(this, "ThrowDaggerProjectiles")); + throwDaggerLS.AddAction(new DelayLogicAction(0.25f)); + throwDaggerLS.AddAction(new ChangePropertyLogicAction(this, "CanBeKnockedBack", true)); + throwDaggerLS.AddAction(new LockFaceDirectionLogicAction(false)); + throwDaggerLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 10f)); + throwDaggerLS.Tag = GameTypes.LogicSetType_ATTACK; + + #region NEODaggers + LogicSet throwDaggerNeoLS = new LogicSet(this); + throwDaggerNeoLS.AddAction(new DebugTraceLogicAction("Throwing Daggers")); + throwDaggerNeoLS.AddAction(new ChangePropertyLogicAction(this, "CanBeKnockedBack", true)); + throwDaggerNeoLS.AddAction(new MoveLogicAction(m_target, true, 0)); + throwDaggerNeoLS.AddAction(new LockFaceDirectionLogicAction(true)); + throwDaggerNeoLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 30f)); + throwDaggerNeoLS.AddAction(new ChangePropertyLogicAction(this, "CanBeKnockedBack", false)); + throwDaggerNeoLS.AddAction(new ChangeSpriteLogicAction("PlayerLevelUp_Character")); + throwDaggerNeoLS.AddAction(new PlayAnimationLogicAction(false)); + throwDaggerNeoLS.AddAction(new RunFunctionLogicAction(this, "ThrowDaggerProjectilesNeo")); + throwDaggerNeoLS.AddAction(new DelayLogicAction(0.25f)); + throwDaggerNeoLS.AddAction(new ChangePropertyLogicAction(this, "CanBeKnockedBack", true)); + throwDaggerNeoLS.AddAction(new LockFaceDirectionLogicAction(false)); + throwDaggerNeoLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 10f)); + throwDaggerNeoLS.Tag = GameTypes.LogicSetType_ATTACK; + #endregion + + LogicSet jumpLS = new LogicSet(this); + jumpLS.AddAction(new DebugTraceLogicAction("jumpLS")); + jumpLS.AddAction(new ChangePropertyLogicAction(this, "CanBeKnockedBack", true)); + jumpLS.AddAction(new GroundCheckLogicAction()); + jumpLS.AddAction(new MoveLogicAction(m_target, true)); + jumpLS.AddAction(new LockFaceDirectionLogicAction(true)); + jumpLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Player_Jump")); + jumpLS.AddAction(new JumpLogicAction()); + jumpLS.AddAction(new DelayLogicAction(0.2f)); + //ThrowAxeProjectiles(jumpLS); + jumpLS.AddAction(new RunFunctionLogicAction(this, "ThrowAxeProjectiles")); + jumpLS.AddAction(new DelayLogicAction(0.75f)); + jumpLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpLS.AddAction(new GroundCheckLogicAction()); + + #region NEOJump + LogicSet jumpNeoLS = new LogicSet(this); + jumpNeoLS.AddAction(new DebugTraceLogicAction("jumpLS")); + jumpNeoLS.AddAction(new ChangePropertyLogicAction(this, "CanBeKnockedBack", true)); + jumpNeoLS.AddAction(new GroundCheckLogicAction()); + jumpNeoLS.AddAction(new MoveLogicAction(m_target, true)); + jumpNeoLS.AddAction(new LockFaceDirectionLogicAction(true)); + jumpNeoLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Player_Jump")); + jumpNeoLS.AddAction(new JumpLogicAction()); + jumpNeoLS.AddAction(new DelayLogicAction(0.2f)); + //ThrowAxeProjectiles(jumpLS); + jumpNeoLS.AddAction(new RunFunctionLogicAction(this, "ThrowAxeProjectilesNeo")); + jumpNeoLS.AddAction(new DelayLogicAction(0.75f)); + jumpNeoLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpNeoLS.AddAction(new GroundCheckLogicAction()); + #endregion + + LogicSet dashLS = new LogicSet(this); + dashLS.AddAction(new DebugTraceLogicAction("dashLS")); + //CastCloseShield(dashLS); + dashLS.AddAction(new RunFunctionLogicAction(this, "CastCloseShield")); + dashLS.AddAction(new RunFunctionLogicAction(this, "Dash", 0)); + dashLS.AddAction(new DelayLogicAction(0.25f)); + dashLS.AddAction(new RunFunctionLogicAction(this, "DashComplete")); + + LogicSet dashRightLS = new LogicSet(this); + dashRightLS.AddAction(new DebugTraceLogicAction("dashAwayRightLS")); + dashRightLS.AddAction(new RunFunctionLogicAction(this, "Dash", 1)); + dashRightLS.AddAction(new DelayLogicAction(0.25f)); + dashRightLS.AddAction(new RunFunctionLogicAction(this, "DashComplete")); + + LogicSet dashLeftLS = new LogicSet(this); + dashLeftLS.AddAction(new DebugTraceLogicAction("dashAwayLeftLS")); + dashLeftLS.AddAction(new RunFunctionLogicAction(this, "Dash", -1)); + dashLeftLS.AddAction(new DelayLogicAction(0.25f)); + dashLeftLS.AddAction(new RunFunctionLogicAction(this, "DashComplete")); + + #endregion + + + #region SecondBoss + ////////////////////////////// SECOND FORM LOGIC + LogicSet walkTowardsSF = new LogicSet(this); + walkTowardsSF.AddAction(new GroundCheckLogicAction()); + walkTowardsSF.AddAction(new ChangeSpriteLogicAction("EnemyLastBossRun_Character", true, true)); + walkTowardsSF.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsSF.AddAction(new LockFaceDirectionLogicAction(true)); + walkTowardsSF.AddAction(new DelayLogicAction(0.35f, 1.15f)); + walkTowardsSF.AddAction(new LockFaceDirectionLogicAction(false)); + + LogicSet walkAwaySF = new LogicSet(this); + walkAwaySF.AddAction(new GroundCheckLogicAction()); + walkAwaySF.AddAction(new ChangeSpriteLogicAction("EnemyLastBossRun_Character", true, true)); + walkAwaySF.AddAction(new MoveLogicAction(m_target, false)); + //walkAwayLS.AddAction(new LockFaceDirectionLogicAction(true)); + walkAwaySF.AddAction(new DelayLogicAction(0.2f, 1.0f)); + walkAwaySF.AddAction(new LockFaceDirectionLogicAction(false)); + + LogicSet walkStopSF = new LogicSet(this); + walkStopSF.AddAction(new GroundCheckLogicAction()); + walkStopSF.AddAction(new ChangeSpriteLogicAction("EnemyLastBossIdle_Character", true, true)); + walkStopSF.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopSF.AddAction(new DelayLogicAction(0.2f, 0.5f)); + + LogicSet attackSF = new LogicSet(this); + attackSF.AddAction(new MoveLogicAction(m_target, true, 0)); + attackSF.AddAction(new LockFaceDirectionLogicAction(true)); + attackSF.AddAction(new ChangeSpriteLogicAction("EnemyLastBossAttack_Character", false, false)); + attackSF.AddAction(new PlayAnimationLogicAction("Start", "BeforeAttack", false)); + attackSF.AddAction(new DelayLogicAction(m_lastBossAttackDelay)); + attackSF.AddAction(new Play3DSoundLogicAction(this, m_target, "FinalBoss_St2_SwordSwing")); + attackSF.AddAction(new Play3DSoundLogicAction(this, m_target, "FinalBoss_St2_Effort_01", "FinalBoss_St2_Effort_02", "FinalBoss_St2_Effort_03", "FinalBoss_St2_Effort_04", "FinalBoss_St2_Effort_05")); + attackSF.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + attackSF.AddAction(new ChangeSpriteLogicAction("EnemyLastBossIdle_Character", true, true)); + attackSF.AddAction(new LockFaceDirectionLogicAction(false)); + + LogicSet castSpearsSF = new LogicSet(this); + RunTeleportLS(castSpearsSF, "Centre"); + castSpearsSF.AddAction(new ChangeSpriteLogicAction("EnemyLastBossSpell_Character", false, false)); + castSpearsSF.AddAction(new Play3DSoundLogicAction(this, m_target, "FinalBoss_St2_SwordSlam_Prime")); + castSpearsSF.AddAction(new PlayAnimationLogicAction("Start", "BeforeCast")); + castSpearsSF.AddAction(new DelayLogicAction(m_castDelay)); + castSpearsSF.AddAction(new RunFunctionLogicAction(this, "CastSpears", m_numSpears, m_spearDuration)); + castSpearsSF.AddAction(new Play3DSoundLogicAction(this, m_target, "FinalBoss_St2_SwordSlam")); + castSpearsSF.AddAction(new PlayAnimationLogicAction("BeforeCast", "End")); + castSpearsSF.AddAction(new DelayLogicAction(m_spearDuration + 1)); + + LogicSet castRandomSwordsSF = new LogicSet(this); + castRandomSwordsSF.AddAction(new ChangePropertyLogicAction(this, "CurrentSpeed", 0)); + castRandomSwordsSF.AddAction(new ChangeSpriteLogicAction("EnemyLastBossSpell2_Character", false, false)); + castRandomSwordsSF.AddAction(new Play3DSoundLogicAction(this, m_target, "FinalBoss_St2_SwordSummon_a")); + castRandomSwordsSF.AddAction(new PlayAnimationLogicAction("Start", "Cast")); + castRandomSwordsSF.AddAction(new DelayLogicAction(m_castDelay)); + castRandomSwordsSF.AddAction(new RunFunctionLogicAction(this, "CastSwordsRandom")); + castRandomSwordsSF.AddAction(new PlayAnimationLogicAction("Cast", "End")); + castRandomSwordsSF.AddAction(new DelayLogicAction(1)); + + LogicSet castSwordsLeftSF = new LogicSet(this); + castSwordsLeftSF.AddAction(new LockFaceDirectionLogicAction(true, 1)); + RunTeleportLS(castSwordsLeftSF, "Left"); + castSwordsLeftSF.AddAction(new ChangeSpriteLogicAction("EnemyLastBossSpell_Character", false, false)); + castSwordsLeftSF.AddAction(new Play3DSoundLogicAction(this, m_target, "FinalBoss_St2_SwordSlam_Prime")); + castSwordsLeftSF.AddAction(new PlayAnimationLogicAction("Start", "BeforeCast")); + castSwordsLeftSF.AddAction(new DelayLogicAction(m_castDelay)); + castSwordsLeftSF.AddAction(new RunFunctionLogicAction(this, "CastSwords", true)); + castSwordsLeftSF.AddAction(new Play3DSoundLogicAction(this, m_target, "FinalBoss_St2_SwordSlam")); + castSwordsLeftSF.AddAction(new PlayAnimationLogicAction("BeforeCast", "End")); + castSwordsLeftSF.AddAction(new DelayLogicAction(1)); + castSwordsLeftSF.AddAction(new LockFaceDirectionLogicAction(false, 0)); + + LogicSet castSwordRightSF = new LogicSet(this); + castSwordRightSF.AddAction(new LockFaceDirectionLogicAction(true, -1)); + RunTeleportLS(castSwordRightSF, "Right"); + castSwordRightSF.AddAction(new ChangeSpriteLogicAction("EnemyLastBossSpell_Character", false, false)); + castSwordRightSF.AddAction(new Play3DSoundLogicAction(this, m_target, "FinalBoss_St2_SwordSlam_Prime")); + castSwordRightSF.AddAction(new PlayAnimationLogicAction("Start", "BeforeCast")); + castSwordRightSF.AddAction(new Play3DSoundLogicAction(this, m_target, "FinalBoss_St2_BlockLaugh")); + castSwordRightSF.AddAction(new DelayLogicAction(m_castDelay)); + castSwordRightSF.AddAction(new RunFunctionLogicAction(this, "CastSwords", false)); + castSwordRightSF.AddAction(new Play3DSoundLogicAction(this, m_target, "FinalBoss_St2_SwordSlam")); + castSwordRightSF.AddAction(new PlayAnimationLogicAction("BeforeCast", "End")); + castSwordRightSF.AddAction(new DelayLogicAction(1)); + castSwordRightSF.AddAction(new LockFaceDirectionLogicAction(false)); + + LogicSet castShield1SF = new LogicSet(this); + //castShield1SF.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 20f)); + //castShield1SF.AddAction(new ChangeSpriteLogicAction("EnemyLastBossSpell_Character", false, false)); + //castShield1SF.AddAction(new PlayAnimationLogicAction("Start", "BeforeCast")); + //castShield1SF.AddAction(new DelayLogicAction(m_castDelay)); + castShield1SF.AddAction(new RunFunctionLogicAction(this, "CastDamageShield", m_orbsEasy)); + //castShield1SF.AddAction(new PlayAnimationLogicAction("BeforeCast", "End")); + //castShield1SF.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 10f)); + //castShield1SF.AddAction(new DelayLogicAction(0)); + castShield1SF.AddAction(new LockFaceDirectionLogicAction(false)); + + LogicSet castShield2SF = new LogicSet(this); + //castShield2SF.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 20f)); + //castShield2SF.AddAction(new ChangeSpriteLogicAction("EnemyLastBossSpell_Character", false, false)); + //castShield2SF.AddAction(new PlayAnimationLogicAction("Start", "BeforeCast")); + //castShield2SF.AddAction(new DelayLogicAction(m_castDelay)); + castShield2SF.AddAction(new RunFunctionLogicAction(this, "CastDamageShield", m_orbsNormal)); + //castShield2SF.AddAction(new PlayAnimationLogicAction("BeforeCast", "End")); + //castShield2SF.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 10f)); + //castShield2SF.AddAction(new DelayLogicAction(0)); + castShield2SF.AddAction(new LockFaceDirectionLogicAction(false)); + + LogicSet castShield3SF = new LogicSet(this); + //castShield3SF.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 20f)); + //castShield3SF.AddAction(new ChangeSpriteLogicAction("EnemyLastBossSpell_Character", false, false)); + //castShield3SF.AddAction(new PlayAnimationLogicAction("Start", "BeforeCast")); + //castShield3SF.AddAction(new DelayLogicAction(m_castDelay)); + castShield3SF.AddAction(new RunFunctionLogicAction(this, "CastDamageShield", m_orbsHard)); + //castShield3SF.AddAction(new PlayAnimationLogicAction("BeforeCast", "End")); + //castShield3SF.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 10f)); + castShield3SF.AddAction(new DelayLogicAction(0)); + castShield3SF.AddAction(new LockFaceDirectionLogicAction(false)); + + #endregion + + + m_generalBasicLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwShieldLS, throwDaggerLS, dashLS); + m_generalAdvancedLB.AddLogicSet(walkTowardsSF, walkAwaySF, walkStopSF, attackSF, castSpearsSF, castRandomSwordsSF, castSwordsLeftSF, castSwordRightSF); + m_damageShieldLB.AddLogicSet(castShield1SF, castShield2SF, castShield3SF); + m_cooldownLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwShieldLS, throwDaggerLS, dashLS); + m_secondFormCooldownLB.AddLogicSet(walkTowardsSF, walkAwaySF, walkStopSF); + + m_generalBasicNeoLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, jumpNeoLS, moveAttackLS, throwShieldLS, throwDaggerNeoLS, dashLS); + + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_damageShieldLB); + logicBlocksToDispose.Add(m_cooldownLB); + logicBlocksToDispose.Add(m_secondFormCooldownLB); + + logicBlocksToDispose.Add(m_generalBasicNeoLB); + + // Special logic block to get out of corners. + m_firstFormDashAwayLB.AddLogicSet(dashLeftLS, dashRightLS); + logicBlocksToDispose.Add(m_firstFormDashAwayLB); + + SetCooldownLogicBlock(m_cooldownLB, 70, 0, 30, 0, 0, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwShieldLS, throwDaggerLS, dashLS + //TEDDY MEGA BOSS COOLDOWN <- Look for that to find boss variant + base.InitializeLogic(); + } + + private void RunTeleportLS(LogicSet logicSet, string roomPosition) + { + //logicSet.AddAction(new GroundCheckLogicAction()); + logicSet.AddAction(new ChangePropertyLogicAction(this, "IsCollidable", false)); + logicSet.AddAction(new ChangePropertyLogicAction(this, "IsWeighted", false)); + logicSet.AddAction(new ChangePropertyLogicAction(this, "Opacity", 0.5f)); + logicSet.AddAction(new ChangePropertyLogicAction(this, "CurrentSpeed", 0)); + logicSet.AddAction(new ChangeSpriteLogicAction("EnemyLastBossTeleport_Character", false, false)); + logicSet.AddAction(new Play3DSoundLogicAction(this, m_target, "FinalBoss_St2_BlockAction")); + logicSet.AddAction(new DelayLogicAction(0.25f)); + logicSet.AddAction(new RunFunctionLogicAction(this, "TeleportTo", roomPosition)); + //logicSet.AddAction(new DelayLogicAction(0.25f)); //1.1f + logicSet.AddAction(new DelayObjLogicAction(m_delayObj)); + logicSet.AddAction(new ChangePropertyLogicAction(this, "IsCollidable", true)); + logicSet.AddAction(new ChangePropertyLogicAction(this, "IsWeighted", true)); + logicSet.AddAction(new ChangePropertyLogicAction(this, "Opacity", 1)); + } + + public void ThrowAxeProjectiles() + { + if (m_axeProjData != null) + { + m_axeProjData.Dispose(); + m_axeProjData = null; + } + + m_axeProjData = new ProjectileData(this) + { + SpriteName = "SpellAxe_Sprite", + SourceAnchor = new Vector2(20, -20), + Target = null, + Speed = new Vector2(AxeProjectileSpeed, AxeProjectileSpeed), + IsWeighted = true, + RotationSpeed = 10, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(-90, -90),//(-72, -72), + CollidesWithTerrain = false, + Scale = AxeSpellScale, + }; + + Tween.RunFunction(0, this, "CastAxe", false); + Tween.RunFunction(0.15f, this, "CastAxe", true); + Tween.RunFunction(0.3f, this, "CastAxe", true); + Tween.RunFunction(0.45f, this, "CastAxe", true); + Tween.RunFunction(0.6f, this, "CastAxe", true); + } + + + public void ThrowAxeProjectilesNeo() + { + if (m_axeProjData != null) + { + m_axeProjData.Dispose(); + m_axeProjData = null; + } + + m_axeProjData = new ProjectileData(this) + { + SpriteName = "SpellAxe_Sprite", + SourceAnchor = new Vector2(20, -20), + Target = null, + Speed = new Vector2(AxeProjectileSpeed, AxeProjectileSpeed), + IsWeighted = true, + RotationSpeed = 10, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(-90, -90),//(-72, -72), + CollidesWithTerrain = false, + Scale = AxeSpellScale, + }; + + //Tween.RunFunction(0, this, "CastAxe", false); + //Tween.RunFunction(0.15f, this, "CastAxe", true); + Tween.RunFunction(0.3f, this, "CastAxe", true); + Tween.RunFunction(0.3f, this, "CastAxe", true); + Tween.RunFunction(0.3f, this, "CastAxe", true); + //Tween.RunFunction(0.45f, this, "CastAxe", true); + //Tween.RunFunction(0.6f, this, "CastAxe", true); + } + + public void CastAxe(bool randomize) + { + if (randomize == true) + m_axeProjData.AngleOffset = CDGMath.RandomInt(-70,70); + m_levelScreen.ProjectileManager.FireProjectile(m_axeProjData); + SoundManager.Play3DSound(this, m_target, "Cast_Axe"); + m_levelScreen.ImpactEffectPool.LastBossSpellCastEffect(this, 45, true); + } + + //private void ThrowAxeProjectiles(LogicSet ls) + //{ + // ProjectileData projData = new ProjectileData(this) + // { + // SpriteName = "SpellAxe_Sprite", + // SourceAnchor = new Vector2(20, -20), + // Target = null, + // Speed = new Vector2(AxeProjectileSpeed, AxeProjectileSpeed), + // IsWeighted = true, + // RotationSpeed = 10, + // Damage = Damage, + // AngleOffset = 0, + // Angle = new Vector2(-90, -90),//(-72, -72), + // CollidesWithTerrain = false, + // Scale = AxeSpellScale, + // }; + + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // ls.AddAction(new Play3DSoundLogicAction(this, m_target, "Cast_Axe")); + // ls.AddAction(new RunFunctionLogicAction(m_levelScreen.ImpactEffectPool, "LastBossSpellCastEffect", this, 45, true)); + // ls.AddAction(new DelayLogicAction(0.15f)); + // projData.AngleOffset = CDGMath.RandomInt(-70, 70); + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // ls.AddAction(new Play3DSoundLogicAction(this, m_target, "Cast_Axe")); + // ls.AddAction(new RunFunctionLogicAction(m_levelScreen.ImpactEffectPool, "LastBossSpellCastEffect", this, 45, true)); + // ls.AddAction(new DelayLogicAction(0.15f)); + // projData.AngleOffset = CDGMath.RandomInt(-70, 70); + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // ls.AddAction(new Play3DSoundLogicAction(this, m_target, "Cast_Axe")); + // ls.AddAction(new RunFunctionLogicAction(m_levelScreen.ImpactEffectPool, "LastBossSpellCastEffect", this, 45, true)); + // projData.AngleOffset = CDGMath.RandomInt(-70, 70); + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // ls.AddAction(new Play3DSoundLogicAction(this, m_target, "Cast_Axe")); + // ls.AddAction(new RunFunctionLogicAction(m_levelScreen.ImpactEffectPool, "LastBossSpellCastEffect", this, 45, true)); + // ls.AddAction(new DelayLogicAction(0.15f)); + // projData.AngleOffset = CDGMath.RandomInt(-70, 70); + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // ls.AddAction(new Play3DSoundLogicAction(this, m_target, "Cast_Axe")); + // ls.AddAction(new RunFunctionLogicAction(m_levelScreen.ImpactEffectPool, "LastBossSpellCastEffect", this, 45, true)); + // ls.AddAction(new DelayLogicAction(0.15f)); + + + // projData.Dispose(); + //} + + //private void ThrowDaggerProjectiles(LogicSet ls) + //{ + // ProjectileData projData = new ProjectileData(this) + // { + // SpriteName = "SpellDagger_Sprite", + // SourceAnchor = Vector2.Zero, + // Target = m_target, + // Speed = new Vector2(DaggerProjectileSpeed, DaggerProjectileSpeed), + // IsWeighted = false, + // RotationSpeed = 0, + // Damage = Damage, + // AngleOffset = 0, + // CollidesWithTerrain = false, + // Scale = DaggerSpellScale, + // }; + + // float rotation = 0; + // float x = m_target.X - this.X; + // float y = m_target.Y - this.Y; + // rotation = MathHelper.ToDegrees((float)Math.Atan2(y, x)); + + // //m_levelScreen.ImpactEffectPool.SpellCastEffect(this.Position, rotation, true); + + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // ls.AddAction(new Play3DSoundLogicAction(this, m_target, "Cast_Dagger")); + // ls.AddAction(new RunFunctionLogicAction(m_levelScreen.ImpactEffectPool, "LastBossSpellCastEffect", this, rotation, true)); + // ls.AddAction(new DelayLogicAction(0.05f)); + // projData.AngleOffset = CDGMath.RandomInt(-8, 8); + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // ls.AddAction(new Play3DSoundLogicAction(this, m_target, "Cast_Dagger")); + // ls.AddAction(new DelayLogicAction(0.05f)); + // projData.AngleOffset = CDGMath.RandomInt(-8, 8); + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // ls.AddAction(new Play3DSoundLogicAction(this, m_target, "Cast_Dagger")); + // ls.AddAction(new DelayLogicAction(0.05f)); + // projData.AngleOffset = CDGMath.RandomInt(-8, 8); + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // ls.AddAction(new Play3DSoundLogicAction(this, m_target, "Cast_Dagger")); + // ls.AddAction(new DelayLogicAction(0.05f)); + // projData.AngleOffset = CDGMath.RandomInt(-8, 8); + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // ls.AddAction(new Play3DSoundLogicAction(this, m_target, "Cast_Dagger")); + + // projData.Dispose(); + //} + + public void ThrowDaggerProjectiles() + { + if (m_daggerProjData != null) + { + m_daggerProjData.Dispose(); + m_daggerProjData = null; + } + + m_daggerProjData = new ProjectileData(this) + { + SpriteName = "SpellDagger_Sprite", + SourceAnchor = Vector2.Zero, + Target = m_target, + Speed = new Vector2(DaggerProjectileSpeed, DaggerProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = DaggerSpellScale, + }; + + //m_levelScreen.ImpactEffectPool.SpellCastEffect(this.Position, rotation, true); + Tween.RunFunction(0, this, "CastDaggers", false); + Tween.RunFunction(0.05f, this, "CastDaggers", true); + Tween.RunFunction(0.1f, this, "CastDaggers", true); + Tween.RunFunction(0.15f, this, "CastDaggers", true); + Tween.RunFunction(0.2f, this, "CastDaggers", true); + } + + public void ThrowDaggerProjectilesNeo() + { + if (m_daggerProjData != null) + { + m_daggerProjData.Dispose(); + m_daggerProjData = null; + } + + m_daggerProjData = new ProjectileData(this) + { + SpriteName = "SpellDagger_Sprite", + SourceAnchor = Vector2.Zero, + Target = m_target, + Speed = new Vector2(DaggerProjectileSpeed - 160, DaggerProjectileSpeed - 160), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = DaggerSpellScale, + }; + + //m_levelScreen.ImpactEffectPool.SpellCastEffect(this.Position, rotation, true); + Tween.RunFunction(0, this, "CastDaggers", false); + Tween.RunFunction(0.05f, this, "CastDaggers", true); + Tween.RunFunction(0.1f, this, "CastDaggers", true); + } + + + public void CastDaggers(bool randomize) + { + if (randomize == true) + m_daggerProjData.AngleOffset = CDGMath.RandomInt(-8, 8); + m_levelScreen.ProjectileManager.FireProjectile(m_daggerProjData); + SoundManager.Play3DSound(this, m_target, "Cast_Dagger"); + m_levelScreen.ImpactEffectPool.LastBossSpellCastEffect(this, 0, true); + } + + public void CastCloseShield() + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "SpellClose_Sprite", + //Angle = new Vector2(90, 90), + //SourceAnchor = new Vector2(120, -60),//(75,-200),//(50, 0), + Speed = new Vector2(0, 0),//(450,450),//(1000, 1000), + IsWeighted = false, + RotationSpeed = 0f, + DestroysWithEnemy = false, + DestroysWithTerrain = false, + CollidesWithTerrain = false, + Scale = new Vector2(m_Spell_Close_Scale, m_Spell_Close_Scale), + Damage = Damage, + Lifespan = m_Spell_Close_Lifespan, + LockPosition = true, + }; + + m_levelScreen.ProjectileManager.FireProjectile(projData); + SoundManager.Play3DSound(this, m_target, "Cast_GiantSword"); + m_levelScreen.ImpactEffectPool.LastBossSpellCastEffect(this, 90, true); + projData.Dispose(); + } + + //private void CastCloseShield(LogicSet ls) + //{ + // ProjectileData projData = new ProjectileData(this) + // { + // SpriteName = "SpellClose_Sprite", + // //Angle = new Vector2(90, 90), + // //SourceAnchor = new Vector2(120, -60),//(75,-200),//(50, 0), + // Speed = new Vector2(0, 0),//(450,450),//(1000, 1000), + // IsWeighted = false, + // RotationSpeed = 0f, + // DestroysWithEnemy = false, + // DestroysWithTerrain = false, + // CollidesWithTerrain = false, + // Scale = new Vector2(m_Spell_Close_Scale, m_Spell_Close_Scale), + // Damage = Damage, + // Lifespan = m_Spell_Close_Lifespan, + // LockPosition = true, + // }; + + // ls.AddAction(new Play3DSoundLogicAction(this, m_target, "Cast_GiantSword")); + // ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + // ls.AddAction(new RunFunctionLogicAction(m_levelScreen.ImpactEffectPool, "LastBossSpellCastEffect", this, 90, true)); + + // projData.Dispose(); + //} + + #region Basic and Advanced Logic + + protected override void RunBasicLogic() + { + if (CurrentHealth > 0) + { + if (m_inSecondForm == false) + { + if (m_isHurt == false) + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + if (IsNeo == false) + RunLogicBlock(true, m_generalBasicLB, 0, 0, 0, 35, 35, 00, 0, 30); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwShieldLS, throwDaggerLS, dashLS + else + RunLogicBlock(true, m_generalBasicNeoLB, 0, 0, 0, 50, 20, 00, 0, 30); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwShieldLS, throwDaggerLS, dashLS + break; + case (STATE_PROJECTILE_ENGAGE): + if (IsNeo == false) + RunLogicBlock(true, m_generalBasicLB, 35, 0, 0, 25, 0, 00, 20, 20); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwShieldLS, throwDaggerLS, dashLS + else + RunLogicBlock(true, m_generalBasicNeoLB, 25, 0, 20, 15, 0, 00, 15, 25); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwShieldLS, throwDaggerLS, dashLS + break; + case (STATE_ENGAGE): + if (IsNeo == false) + RunLogicBlock(true, m_generalBasicLB, 40, 0, 0, 20, 0, 00, 40, 0); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwShieldLS, throwDaggerLS, dashLS + else + RunLogicBlock(true, m_generalBasicNeoLB, 40, 0, 20, 20, 0, 00, 20, 0); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwShieldLS, throwDaggerLS, dashLS + break; + case (STATE_WANDER): + if (IsNeo == false) + RunLogicBlock(true, m_generalBasicLB, 50, 0, 0, 0, 0, 00, 50, 0); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwShieldLS, throwDaggerLS, dashLS + else + RunLogicBlock(true, m_generalBasicNeoLB, 50, 0, 10, 10, 0, 00, 30, 0); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwShieldLS, throwDaggerLS, dashLS + break; + default: + break; + } + } + + } + else + RunAdvancedLogic(); + } + } + + protected override void RunAdvancedLogic() + { + //if ((CurrentHealth < (MaxHealth / 3) * 2) && m_damageShieldProjectiles.Count < m_orbsNormal) + // RunLogicBlock(false, m_damageShieldLB, 0, 100, 0); // castShield1SF, castShield2SF, castShield3SF + //else if ((CurrentHealth < (MaxHealth / 3) * 1) && m_damageShieldProjectiles.Count < m_orbsHard) + // RunLogicBlock(false, m_damageShieldLB, 0, 0, 100); // castShield1SF, castShield2SF, castShield3SF + //else if (m_damageShieldProjectiles.Count < 1) + // RunLogicBlock(false, m_damageShieldLB, 100, 0, 0); // castShield1SF, castShield2SF, castShield3SF + //else + { + //RunLogicBlock(true, m_generalAdvancedLB, 0, 0, 0, 100, 0, 0, 0, 0); + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 31, 15, 0, 26, 3, 13, 6, 6); //walkTowardsSF, walkAwaySF, walkStopSF, attackSF, castSpearsSF, castRandomSwordsSF, castSwordsLeftSF, castSwordRightSF + break; + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 52, 12, 0, 0, 11, 15, 5, 5); //walkTowardsSF, walkAwaySF, walkStopSF, attackSF, castSpearsSF, castRandomSwordsSF, castSwordsLeftSF, castSwordRightSF + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 68, 0, 0, 0, 10, 12, 5, 5); //walkTowardsSF, walkAwaySF, walkStopSF, attackSF, castSpearsSF, castRandomSwordsSF, castSwordsLeftSF, castSwordRightSF + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalAdvancedLB, 63, 0, 0, 0, 15, 12, 5, 5); //walkTowardsSF, walkAwaySF, walkStopSF, attackSF, castSpearsSF, castRandomSwordsSF, castSwordsLeftSF, castSwordRightSF + break; + default: + break; + } + } + } + + #endregion + + #region Expert and Miniboss (Not Used) + + protected override void RunExpertLogic() + { + if (CurrentHealth > 0) + { + if (m_inSecondForm == false) + { + if (m_isHurt == false) + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + if (m_isTouchingGround == true) + RunLogicBlock(true, m_generalBasicLB, 0, 10, 0, 20, 35, 10, 0, 25); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwAxeLS, throwDaggerLS, dashLS + else + RunLogicBlock(true, m_generalBasicLB, 0, 10, 0, 0, 55, 10, 0, 25); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwAxeLS, throwDaggerLS, dashLS + break; + case (STATE_PROJECTILE_ENGAGE): + if (m_target.IsJumping == false) + RunLogicBlock(true, m_generalBasicLB, 20, 0, 10, 10, 0, 15, 20, 10); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwAxeLS, throwDaggerLS, dashLS + else + RunLogicBlock(true, m_generalBasicLB, 40, 0, 15, 0, 0, 15, 20, 10); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwAxeLS, throwDaggerLS, dashLS + break; + case (STATE_ENGAGE): + if (m_target.IsJumping == false) + RunLogicBlock(true, m_generalBasicLB, 30, 0, 15, 20, 0, 25, 0, 10); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwAxeLS, throwDaggerLS, dashLS + else + RunLogicBlock(true, m_generalBasicLB, 50, 0, 15, 0, 0, 25, 0, 10); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwAxeLS, throwDaggerLS, dashLS + break; + case (STATE_WANDER): + if (m_target.IsJumping == false) + RunLogicBlock(true, m_generalBasicLB, 50, 0, 10, 20, 0, 0, 20, 0); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwAxeLS, throwDaggerLS, dashLS + else + RunLogicBlock(true, m_generalBasicLB, 50, 0, 10, 20, 0, 0, 20, 0); //walkTowardsLS, walkAwayLS, walkStopLS, jumpLS, moveAttackLS, throwAxeLS, throwDaggerLS, dashLS + break; + default: + break; + } + } + } + else + RunAdvancedLogic(); + } + } + + + protected override void RunMinibossLogic() + { + RunLogicBlock(true, m_generalAdvancedLB, 0, 0, 0, 0, 100, 0, 0, 0); //walkTowardsSF, walkAwaySF, walkStopSF, attackSF, castSpearsSF, castRandomSwordsSF, castSwordsLeftSF, castSwordRightSF + //if ((CurrentHealth < (MaxHealth / 3) * 2) && m_damageShieldProjectiles.Count < m_orbsNormal) + // RunLogicBlock(false, m_damageShieldLB, 0, 100, 0); // castShield1SF, castShield2SF, castShield3SF + //else if ((CurrentHealth < (MaxHealth / 3) * 1) && m_damageShieldProjectiles.Count < m_orbsHard) + // RunLogicBlock(false, m_damageShieldLB, 0, 0, 100); // castShield1SF, castShield2SF, castShield3SF + //else if (m_damageShieldProjectiles.Count < 1) + // RunLogicBlock(false, m_damageShieldLB, 100, 0, 0); // castShield1SF, castShield2SF, castShield3SF + //else + //{ + // switch (State) + // { + // case (STATE_MELEE_ENGAGE): + // RunLogicBlock(true, m_generalAdvancedLB, 30, 20, 0, 40, 0, 0, 5, 5); //walkTowardsSF, walkAwaySF, walkStopSF, attackSF, castSpearsSF, castRandomSwordsSF, castSwordsLeftSF, castSwordRightSF + // break; + // case (STATE_PROJECTILE_ENGAGE): + // RunLogicBlock(true, m_generalAdvancedLB, 50, 20, 10, 0, 5, 5, 5, 5); //walkTowardsSF, walkAwaySF, walkStopSF, attackSF, castSpearsSF, castRandomSwordsSF, castSwordsLeftSF, castSwordRightSF + // break; + // case (STATE_ENGAGE): + // RunLogicBlock(true, m_generalAdvancedLB, 80, 0, 0, 0, 10, 10, 0, 0); //walkTowardsSF, walkAwaySF, walkStopSF, attackSF, castSpearsSF, castRandomSwordsSF, castSwordsLeftSF, castSwordRightSF + // break; + // case (STATE_WANDER): + // RunLogicBlock(true, m_generalAdvancedLB, 80, 0, 0, 0, 10, 10, 0, 0); //walkTowardsSF, walkAwaySF, walkStopSF, attackSF, castSpearsSF, castRandomSwordsSF, castSwordsLeftSF, castSwordRightSF + // break; + // default: + // break; + // } + //} + } + + + #endregion + + public void TeleportTo(string roomPosition) + { + Vector2 position = Vector2.Zero; + float xDistance = 0; + + switch (roomPosition) + { + case ("Left"): + xDistance = m_levelScreen.CurrentRoom.Bounds.Left + 200; + break; + case ("Right"): + xDistance = m_levelScreen.CurrentRoom.Bounds.Right - 200; + break; + case ("Centre"): + xDistance = m_levelScreen.CurrentRoom.Bounds.Center.X; + break; + } + position = new Vector2(xDistance, this.Y); + + float totalMovement = Math.Abs(CDGMath.DistanceBetweenPts(this.Position, position)); + m_teleportDuration = totalMovement * 0.001f; + m_delayObj.X = m_teleportDuration; // Delay hack. + Tween.To(this, m_teleportDuration, Quad.EaseInOut, "X", position.X.ToString()); + SoundManager.Play3DSound(this, m_target, "FinalBoss_St2_BlockMove"); + } + + public void CastSwords(bool castLeft) + { + ProjectileData swordData = new ProjectileData(this) + { + SpriteName = "LastBossSwordProjectile_Sprite", + Target = null, + Speed = new Vector2(0, 0), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + StartingRotation = 0, + AngleOffset = 0, + CollidesWithTerrain = false, + DestroysWithEnemy = false, + }; + + float delay = 1; + int projSpeed = MegaFlyingDaggerProjectileSpeed; + if (castLeft == false) + projSpeed = (MegaFlyingDaggerProjectileSpeed * -1); + SoundManager.Play3DSound(this, m_target, "FinalBoss_St2_SwordSummon_b"); + for (int i = 0; i < MegaFlyingSwordAmount; i++) + { + Vector2 spellPos = new Vector2(this.X, this.Y + CDGMath.RandomInt(-1320, 100)); + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(swordData); + proj.Position = spellPos; + Tween.By(proj, 2.5f, Tween.EaseNone, "delay", delay.ToString(), "X", projSpeed.ToString()); + Tween.AddEndHandlerToLastTween(proj, "KillProjectile"); + Tween.RunFunction(delay, typeof(SoundManager), "Play3DSound", this, m_target, new string[]{"FinalBoss_St2_SwordSummon_c_01", "FinalBoss_St2_SwordSummon_c_02", + "FinalBoss_St2_SwordSummon_c_03", "FinalBoss_St2_SwordSummon_c_04", "FinalBoss_St2_SwordSummon_c_05", "FinalBoss_St2_SwordSummon_c_06", + "FinalBoss_St2_SwordSummon_c_07", "FinalBoss_St2_SwordSummon_c_08"}); + m_levelScreen.ImpactEffectPool.SpellCastEffect(spellPos, 0, false); + delay += 0.075f;//0.05f; + } + } + + public void CastSpears(int numSpears, float duration) + { + ProjectileData spearData = new ProjectileData(this) + { + SpriteName = "LastBossSpearProjectile_Sprite", + Target = null, + Speed = new Vector2(0, 0), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + StartingRotation = 0, + AngleOffset = 0, + CollidesWithTerrain = false, + DestroysWithEnemy = false, + ShowIcon = false, + LockPosition = true, + CanBeFusRohDahed = false, + }; + + int xOffsetRight = 0; + int xOffsetLeft = 0; + float delay = 0.5f; + this.UpdateCollisionBoxes(); + Vector2 roomCentre = new Vector2(m_levelScreen.CurrentRoom.Bounds.Center.X, this.Y); + + for (int i = 0; i < numSpears; i++) + { + // Spears spreading right. + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(spearData); + proj.Scale = new Vector2(2, 2); + proj.X = roomCentre.X + 50 + xOffsetRight; + proj.Y = this.Y + (this.Bounds.Bottom - this.Y);// this.Bounds.Bottom + proj.Width / 2f - 10; + proj.StopAnimation(); + //Tween.By(proj, 0.2f, Tween.EaseNone, "delay", delay.ToString(), "Y", (-(proj.Width + 10)).ToString()); + //proj.Y -= proj.Width; + //Tween.By(proj, 0.2f, Tween.EaseNone, "delay", (delay + 1).ToString(), "Y", proj.Width.ToString()); + //proj.Y += proj.Width; + xOffsetRight += proj.Width; + Tween.RunFunction(delay, typeof(SoundManager), "Play3DSound", this, m_target, new string[]{"FinalBoss_St2_Lance_01", "FinalBoss_St2_Lance_02", + "FinalBoss_St2_Lance_03", "FinalBoss_St2_Lance_04", "FinalBoss_St2_Lance_05", "FinalBoss_St2_Lance_06", "FinalBoss_St2_Lance_07", "FinalBoss_St2_Lance_08"}); + Tween.RunFunction(delay, proj, "PlayAnimation", "Before", "End", false); + Tween.RunFunction(delay + duration, proj, "PlayAnimation", "Retract", "RetractComplete", false); + Tween.RunFunction(delay + duration, typeof(SoundManager), "Play3DSound", this, m_target, new string[]{"FinalBoss_St2_Lance_Retract_01", "FinalBoss_St2_Lance_Retract_02", + "FinalBoss_St2_Lance_Retract_03", "FinalBoss_St2_Lance_Retract_04", "FinalBoss_St2_Lance_Retract_05", "FinalBoss_St2_Lance_Retract_06"}); + Tween.RunFunction(delay + duration + 1, proj, "KillProjectile"); + + // Spears spreading left. + ProjectileObj projLeft = m_levelScreen.ProjectileManager.FireProjectile(spearData); + projLeft.Scale = new Vector2(2, 2); + projLeft.X = roomCentre.X - 50 + xOffsetLeft; + projLeft.Y = this.Y + (this.Bounds.Bottom - this.Y); + projLeft.StopAnimation(); + //Tween.By(projLeft, 0.2f, Tween.EaseNone, "delay", delay.ToString(), "Y", (-(projLeft.Width + 10)).ToString()); + //projLeft.Y -= projLeft.Width; + //Tween.By(projLeft, 0.2f, Tween.EaseNone, "delay", (delay + 1).ToString(), "Y", projLeft.Width.ToString()); + //projLeft.Y += projLeft.Width; + xOffsetLeft -= projLeft.Width; + Tween.RunFunction(delay, projLeft, "PlayAnimation", "Before", "End", false); + Tween.RunFunction(delay + duration, projLeft, "PlayAnimation", "Retract", "RetractComplete", false); + Tween.RunFunction(delay + duration + 1, projLeft, "KillProjectile"); + + delay += 0.05f; + } + + spearData.Dispose(); + } + + public void CastSwordsRandom() + { + Vector2 roomCentre = new Vector2(m_levelScreen.CurrentRoom.Bounds.Center.X, this.Y); + this.UpdateCollisionBoxes(); + ProjectileData swordData = new ProjectileData(this) + { + SpriteName = "LastBossSwordVerticalProjectile_Sprite", + Target = null, + Speed = new Vector2(0, 0), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + StartingRotation = 0, + AngleOffset = 0, + CollidesWithTerrain = false, + DestroysWithEnemy = false, + LockPosition = true, + }; + + int projSpeed = MegaUpwardSwordProjectileSpeed; + + int xOffsetRight = 0; + int xOffsetLeft = 0; + float delay = 1; + for (int i = 0; i < MegaUpwardSwordProjectileAmount; i++) + { + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(swordData); + proj.Scale = new Vector2(1.5f, 1.5f); + proj.X = roomCentre.X + 50 + xOffsetRight; + proj.Y = roomCentre.Y + (this.Bounds.Bottom - this.Y) + 120; + proj.Opacity = 0; + Tween.To(proj, 0.25f, Tween.EaseNone, "Opacity", "1"); + Tween.By(proj, 2.5f, Quad.EaseIn, "delay", delay.ToString(), "Y", (-projSpeed).ToString()); + Tween.AddEndHandlerToLastTween(proj, "KillProjectile"); + + xOffsetRight = CDGMath.RandomInt(50, 1000); + + ProjectileObj projLeft = m_levelScreen.ProjectileManager.FireProjectile(swordData); + projLeft.Scale = new Vector2(2, 2); + projLeft.X = roomCentre.X - 50 + xOffsetLeft; + projLeft.Y = roomCentre.Y + (this.Bounds.Bottom - this.Y) + 120; + projLeft.Opacity = 0; + Tween.To(projLeft, 0.25f, Tween.EaseNone, "Opacity", "1"); + Tween.By(projLeft, 2.5f, Quad.EaseIn, "delay", delay.ToString(), "Y", (-projSpeed).ToString()); + Tween.AddEndHandlerToLastTween(proj, "KillProjectile"); + + xOffsetLeft = -CDGMath.RandomInt(50, 1000); + + delay += 0.25f; + } + + swordData.Dispose(); + } + + public void ChangeProjectileSpeed(ProjectileObj proj, float speed, Vector2 heading) + { + proj.AccelerationX = heading.X * speed; + proj.AccelerationY = -heading.Y * speed; + } + + + public void CastDamageShield(int numOrbs) + { + foreach (ProjectileObj projectile in m_damageShieldProjectiles) + projectile.KillProjectile(); + m_damageShieldProjectiles.Clear(); + + ProjectileData orbData = new ProjectileData(this) + { + SpriteName = "LastBossOrbProjectile_Sprite", + Angle = new Vector2(-65, -65), + Speed = new Vector2(m_Mega_Shield_Speed, m_Mega_Shield_Speed),//(1.5f, 1.5f),//(2, 2), + Target = this, + IsWeighted = false, + RotationSpeed = 0, + CollidesWithTerrain = false, + DestroysWithTerrain = false, + DestroysWithEnemy = false, + CanBeFusRohDahed = false, + ShowIcon = false, + Lifespan = 9999, + Damage = Damage / 2, + }; + + SoundManager.Play3DSound(this, m_target, "FinalBoss_St2_SwordSummon_b"); + int projectileDistance = m_Mega_Shield_Distance; + for (int i = 0; i < numOrbs; i++) + { + float angle = (360f / numOrbs) * i; + + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(orbData); + proj.AltX = angle; // AltX and AltY are used as holders to hold the projectiles angle and distance from player respectively. + proj.AltY = projectileDistance; + proj.Spell = SpellType.DamageShield; + proj.AccelerationXEnabled = false; + proj.AccelerationYEnabled = false; + proj.IgnoreBoundsCheck = true; + proj.Scale = new Vector2(m_Mega_Shield_Scale, m_Mega_Shield_Scale); + proj.Position = CDGMath.GetCirclePosition(angle, projectileDistance, this.Position); + m_levelScreen.ImpactEffectPool.SpellCastEffect(proj.Position, proj.Rotation, false); + + m_damageShieldProjectiles.Add(proj); + } + } + + public void Dash(int heading) + { + this.HeadingY = 0; + if (m_target.Position.X < this.X) // to the right of the player. + { + if (heading == 0) + this.HeadingX = 1; + if (this.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.None) + this.ChangeSprite("PlayerFrontDash_Character"); + else + this.ChangeSprite("PlayerDash_Character"); + + m_levelScreen.ImpactEffectPool.DisplayDashEffect(new Vector2(this.X, TerrainBounds.Bottom), false); + } + else // to the left of the player. + { + if (heading == 0) + this.HeadingX = -1; + if (this.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.None) + this.ChangeSprite("PlayerDash_Character"); + else + this.ChangeSprite("PlayerFrontDash_Character"); + + m_levelScreen.ImpactEffectPool.DisplayDashEffect(new Vector2(this.X, TerrainBounds.Bottom), true); + } + + if (heading != 0) + this.HeadingX = heading; + + SoundManager.Play3DSound(this, m_target, "Player_Dash"); + + this.LockFlip = true; + this.AccelerationX = 0; + this.AccelerationY = 0; + this.PlayAnimation(false); + this.CurrentSpeed = 900; + this.AccelerationYEnabled = false; + m_isDashing = true; + } + + public void DashComplete() + { + this.LockFlip = false; + this.CurrentSpeed = 500; + this.AccelerationYEnabled = true; + m_isDashing = false; + this.AnimationDelay = 1 / 10f; + } + + public override void Update(GameTime gameTime) + { + if (m_shake == true) + { + if (m_shakeTimer > 0) + { + m_shakeTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_shakeTimer <= 0) + { + m_shakeTimer = m_shakeDuration; + if (m_shookLeft == true) + { + m_shookLeft = false; + this.X += 5; + } + else + { + this.X -= 5; + m_shookLeft = true; + } + } + } + } + + if (m_smokeCounter > 0 && m_inSecondForm == false) + { + m_smokeCounter -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_smokeCounter <= 0) + { + m_smokeCounter = 0.25f; + if (CurrentSpeed > 0) + m_smokeCounter = 0.05f; + m_levelScreen.ImpactEffectPool.BlackSmokeEffect(this); + } + } + + if (m_inSecondForm == false) + { + if (m_isTouchingGround == false && m_currentActiveLB != null && this.SpriteName != "PlayerAttacking3_Character" && m_isDashing == false && this.SpriteName != "PlayerLevelUp_Character") + { + if (this.AccelerationY < 0 && this.SpriteName != "PlayerJumping_Character") + { + this.ChangeSprite("PlayerJumping_Character"); + this.PlayAnimation(true); + } + else if (this.AccelerationY > 0 && this.SpriteName != "PlayerFalling_Character") + { + this.ChangeSprite("PlayerFalling_Character"); + this.PlayAnimation(true); + } + } + else if (m_isTouchingGround == true && m_currentActiveLB != null && this.SpriteName == "PlayerAttacking3_Character" && this.CurrentSpeed != 0) + { + SpriteObj bossLegs = this.GetChildAt(PlayerPart.Legs) as SpriteObj; + if (bossLegs.SpriteName != "PlayerWalkingLegs_Sprite") + { + bossLegs.ChangeSprite("PlayerWalkingLegs_Sprite"); + bossLegs.PlayAnimation(this.CurrentFrame, this.TotalFrames); + bossLegs.Y += 4; + bossLegs.OverrideParentAnimationDelay = true; + bossLegs.AnimationDelay = 1 / 10f; + } + } + } + else + { + if (this.SpriteName == "EnemyLastBossRun_Character") + { + m_walkUpSoundFinalBoss.Update(); + m_walkDownSoundFinalBoss.Update(); + } + } + + if (m_inSecondForm == false && CurrentHealth <= 0 && m_target.CurrentHealth > 0 && IsNeo == false) + { + // This is the first form death animation. + if (IsTouchingGround == true && m_firstFormDying == false) + { + m_firstFormDying = true; + m_levelScreen.ItemDropManager.DropItemWide(this.Position, ItemDropType.Health, GameEV.ITEM_HEALTHDROP_AMOUNT); + m_levelScreen.ItemDropManager.DropItemWide(this.Position, ItemDropType.Health, GameEV.ITEM_HEALTHDROP_AMOUNT); + m_levelScreen.ItemDropManager.DropItemWide(this.Position, ItemDropType.Health, GameEV.ITEM_HEALTHDROP_AMOUNT); + m_levelScreen.ItemDropManager.DropItemWide(this.Position, ItemDropType.Health, GameEV.ITEM_HEALTHDROP_AMOUNT); + //m_levelScreen.ItemDropManager.DropItemWide(this.Position, ItemDropType.Mana, GameEV.ITEM_MANADROP_AMOUNT); + m_levelScreen.ItemDropManager.DropItemWide(this.Position, ItemDropType.Mana, GameEV.ITEM_MANADROP_AMOUNT); + m_levelScreen.ItemDropManager.DropItemWide(this.Position, ItemDropType.Mana, GameEV.ITEM_MANADROP_AMOUNT); + m_levelScreen.ItemDropManager.DropItemWide(this.Position, ItemDropType.Mana, GameEV.ITEM_MANADROP_AMOUNT); + this.IsWeighted = false; + this.IsCollidable = false; + this.AnimationDelay = 1 / 10f; + this.CurrentSpeed = 0; + this.AccelerationX = 0; + this.AccelerationY = 0; + this.TextureColor = Color.White; + this.ChangeSprite("PlayerDeath_Character"); + SoundManager.PlaySound("Boss_Flash"); + SoundManager.StopMusic(1); + m_target.StopAllSpells(); + m_target.ForceInvincible = true; + + if (m_target.X < this.X) + this.Flip = SpriteEffects.FlipHorizontally; + else + this.Flip = SpriteEffects.None; + + if (m_currentActiveLB != null && m_currentActiveLB.IsActive == true) + m_currentActiveLB.StopLogicBlock(); + } + + // This is the logic to move the player next to the boss. + if (m_target.IsTouchingGround == true && m_inSecondForm == false && this.SpriteName == "PlayerDeath_Character") + MovePlayerTo(); + } + + if ((m_firstFormDying == false && m_inSecondForm == false) || (m_firstFormDying == true && m_inSecondForm == true) || (IsNeo == true && CurrentHealth > 0)) + base.Update(gameTime); + + // Code for the neo version + if (m_inSecondForm == false && CurrentHealth <= 0 && m_target.CurrentHealth > 0 && IsNeo == true && IsTouchingGround == true && m_firstFormDying == false) + { + KillPlayerNeo(); + m_firstFormDying = true; + } + } + + public void MovePlayerTo() + { + m_target.StopAllSpells(); + m_levelScreen.ProjectileManager.DestroyAllProjectiles(true); + m_inSecondForm = true; + m_isKilled = true; + m_levelScreen.RunCinematicBorders(16); + m_currentActiveLB.StopLogicBlock(); + + int xOffset = 250; + + Vector2 targetPos = Vector2.Zero; + + if (m_target.X < this.X && this.X > (m_levelScreen.CurrentRoom.X + 500) || this.X > (m_levelScreen.CurrentRoom.Bounds.Right - 500))//&& this.X < m_levelScreen.CurrentRoom.Bounds.Right - 300) + { + targetPos = new Vector2(this.X - xOffset, this.Y); // Move to the left of the boss. + if (targetPos.X > m_levelScreen.CurrentRoom.Bounds.Right - 500) + targetPos.X = m_levelScreen.CurrentRoom.Bounds.Right - 500; + } + else + targetPos = new Vector2(this.X + xOffset, this.Y); // Move to the right of the boss. + + m_target.Flip = SpriteEffects.None; + if (targetPos.X < m_target.X) + m_target.Flip = SpriteEffects.FlipHorizontally; + + float duration = CDGMath.DistanceBetweenPts(m_target.Position, targetPos) / (float)(m_target.Speed); + + m_target.UpdateCollisionBoxes(); // Necessary check since the OnEnter() is called before m_target can update its collision boxes. + m_target.State = 1; // Force the m_target into a walking state. This state will not update until the logic set is complete. + m_target.IsWeighted = false; + m_target.AccelerationY = 0; + m_target.AccelerationX = 0; + m_target.IsCollidable = false; + m_target.Y = this.m_levelScreen.CurrentRoom.Bounds.Bottom - 60 * 3 - (m_target.Bounds.Bottom - m_target.Y); + m_target.CurrentSpeed = 0; + m_target.LockControls(); + m_target.ChangeSprite("PlayerWalking_Character"); + LogicSet playerMoveLS = new LogicSet(m_target); + playerMoveLS.AddAction(new DelayLogicAction(duration)); + m_target.RunExternalLogicSet(playerMoveLS); + m_target.PlayAnimation(true); + Tween.To(m_target, duration, Tween.EaseNone, "X", targetPos.X.ToString()); + Tween.AddEndHandlerToLastTween(this, "SecondFormDeath"); + } + + // This is where the death animation code needs to go. + public void SecondFormDeath() + { + if (m_target.X < this.X) + m_target.Flip = SpriteEffects.None; + else + m_target.Flip = SpriteEffects.FlipHorizontally; + this.PlayAnimation(false); + SoundManager.PlaySound("FinalBoss_St1_DeathGrunt"); + Tween.RunFunction(0.1f, typeof(SoundManager), "PlaySound", "Player_Death_SwordTwirl"); + Tween.RunFunction(0.7f, typeof(SoundManager), "PlaySound", "Player_Death_SwordLand"); + Tween.RunFunction(1.2f, typeof(SoundManager), "PlaySound", "Player_Death_BodyFall"); + + float delay = 2; + Tween.RunFunction(2, this, "PlayBlackSmokeSounds"); + for (int i = 0; i < 30; i++) + { + Tween.RunFunction(delay, m_levelScreen.ImpactEffectPool, "BlackSmokeEffect", this.Position, new Vector2(1 + (delay * 1), 1 + (delay * 1))); + delay += 0.05f; + } + Tween.RunFunction(3, this, "HideEnemy"); + Tween.RunFunction(6, this, "SecondFormDialogue"); + } + + public void PlayBlackSmokeSounds() + { + SoundManager.PlaySound("Cutsc_Smoke"); + } + + public void HideEnemy() + { + this.Visible = false; + } + + public void SecondFormDialogue() + { + RCScreenManager manager = m_levelScreen.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("FinalBossTalk02"); + manager.DialogueScreen.SetConfirmEndHandler(m_levelScreen.CurrentRoom, "RunFountainCutscene"); + manager.DisplayScreen(ScreenType.Dialogue, true); + } + + public void SecondFormComplete() + { + m_target.ForceInvincible = false; + this.Level += LevelEV.LAST_BOSS_MODE2_LEVEL_MOD; + + this.Flip = SpriteEffects.FlipHorizontally; + this.Visible = true; + this.MaxHealth = EnemyEV.LastBoss_Advanced_MaxHealth; + this.Damage = EnemyEV.LastBoss_Advanced_Damage; + this.CurrentHealth = MaxHealth; + Name = EnemyEV.LastBoss_Advanced_Name; + if (LevelEV.WEAKEN_BOSSES == true) + this.CurrentHealth = 1; + this.MinMoneyDropAmount = EnemyEV.LastBoss_Advanced_MinDropAmount; + this.MaxMoneyDropAmount = EnemyEV.LastBoss_Advanced_MaxDropAmount; + this.MoneyDropChance = EnemyEV.LastBoss_Advanced_DropChance; + + this.Speed = EnemyEV.LastBoss_Advanced_Speed; + this.TurnSpeed = EnemyEV.LastBoss_Advanced_TurnSpeed; + this.ProjectileSpeed = EnemyEV.LastBoss_Advanced_ProjectileSpeed; + this.JumpHeight = EnemyEV.LastBoss_Advanced_Jump; + this.CooldownTime = EnemyEV.LastBoss_Advanced_Cooldown; + this.AnimationDelay = 1 / EnemyEV.LastBoss_Advanced_AnimationDelay; + + this.AlwaysFaceTarget = EnemyEV.LastBoss_Advanced_AlwaysFaceTarget; + this.CanFallOffLedges = EnemyEV.LastBoss_Advanced_CanFallOffLedges; + this.CanBeKnockedBack = EnemyEV.LastBoss_Advanced_CanBeKnockedBack; + + this.ProjectileScale = EnemyEV.LastBoss_Advanced_ProjectileScale; + this.TintablePart.TextureColor = EnemyEV.LastBoss_Advanced_Tint; + + this.MeleeRadius = EnemyEV.LastBoss_Advanced_MeleeRadius; + this.EngageRadius = EnemyEV.LastBoss_Advanced_EngageRadius; + this.ProjectileRadius = EnemyEV.LastBoss_Advanced_ProjectileRadius; + + this.ProjectileDamage = Damage; + this.KnockBack = EnemyEV.LastBoss_Advanced_KnockBack; + this.ChangeSprite("EnemyLastBossIdle_Character"); + //TEDDY MEGA BOSS COOLDOWN + SetCooldownLogicBlock(m_secondFormCooldownLB, 40, 20, 40); //walkTowardsSF, walkAwaySF, walkStopSF + this.PlayAnimation(true); + this.Name = "The Fountain"; + + this.IsWeighted = true; + this.IsCollidable = true; + + //this.Y -= 50; + //Tween.RunFunction(2, this, "SecondFormActive"); + } + + public void SecondFormActive() + { + if (this.IsPaused == true) + this.UnpauseEnemy(true); + m_levelScreen.CameraLockedToPlayer = true; + m_target.UnlockControls(); + m_target.IsWeighted = true; + m_target.IsCollidable = true; + m_isKilled = false; + } + + public override void HitEnemy(int damage, Vector2 collisionPt, bool isPlayer) + { + if (m_inSecondForm == false) + { + if (m_isHurt == false && m_isDashing == false) + { + SoundManager.Play3DSound(this, m_target, "FinalBoss_St1_Dmg_01", "FinalBoss_St1_Dmg_02", "FinalBoss_St1_Dmg_03", "FinalBoss_St1_Dmg_04"); + /* + this.LockFlip = false; + this.AnimationDelay = 1 / 10f; + + if (m_currentActiveLB != null && m_currentActiveLB.IsActive == true) + m_currentActiveLB.StopLogicBlock(); + + this.ChangeSprite("PlayerHurt_Character"); + m_isHurt = true; + */ // TEDDY I REMOVED THIS SO THAT ENEMY DOESNT GO INTO HURT STATE. + base.HitEnemy(damage, collisionPt, isPlayer); + } + } + else + { + SoundManager.Play3DSound(this, m_target, "FinalBoss_St2_Hit_01", "FinalBoss_St2_Hit_03", "FinalBoss_St2_Hit_04"); + SoundManager.Play3DSound(this, m_target, "FinalBoss_St2_DmgVox_01", "FinalBoss_St2_DmgVox_02", "FinalBoss_St2_DmgVox_03", "FinalBoss_St2_DmgVox_04", + "FinalBoss_St2_DmgVox_05", "FinalBoss_St2_DmgVox_06", "FinalBoss_St2_DmgVox_07", "FinalBoss_St2_DmgVox_08", "FinalBoss_St2_DmgVox_09"); + base.HitEnemy(damage, collisionPt, isPlayer); + } + } + + public override void Kill(bool giveXP = true) + { + if (m_target.CurrentHealth > 0) + { + if (m_inSecondForm == true && m_bossVersionKilled == false) + { + m_bossVersionKilled = true; + SetPlayerData(); + + m_levelScreen.PauseScreen(); + m_levelScreen.ProjectileManager.DestroyAllProjectiles(false); + m_target.StopAllSpells(); + m_levelScreen.RunWhiteSlashEffect(); + this.ChangeSprite("EnemyLastBossDeath_Character"); + if (m_target.X < this.X) + this.Flip = SpriteEffects.FlipHorizontally; + else + this.Flip = SpriteEffects.None; + Tween.RunFunction(1f, this, "Part2"); + SoundManager.PlaySound("Boss_Flash"); + SoundManager.PlaySound("Boss_Eyeball_Freeze"); + SoundManager.StopMusic(0); + m_target.LockControls(); + + GameUtil.UnlockAchievement("FEAR_OF_FATHERS"); + + if (Game.PlayerStats.TimesCastleBeaten > 1) + GameUtil.UnlockAchievement("FEAR_OF_TWINS"); + } + + if (IsNeo == true && m_neoDying == false) + { + m_neoDying = true; + m_levelScreen.PauseScreen(); + SoundManager.PauseMusic(); + + m_levelScreen.RunWhiteSlashEffect(); + + SoundManager.PlaySound("Boss_Flash"); + SoundManager.PlaySound("Boss_Eyeball_Freeze"); + Tween.RunFunction(1, m_levelScreen, "UnpauseScreen"); + Tween.RunFunction(1, typeof(SoundManager), "ResumeMusic"); + } + } + //base.Kill(giveXP); + } + + public void KillPlayerNeo() + { + m_isKilled = true; + + if (m_currentActiveLB != null && m_currentActiveLB.IsActive == true) + m_currentActiveLB.StopLogicBlock(); + + this.IsWeighted = false; + this.IsCollidable = false; + this.AnimationDelay = 1 / 10f; + this.CurrentSpeed = 0; + this.AccelerationX = 0; + this.AccelerationY = 0; + + this.ChangeSprite("PlayerDeath_Character"); + this.PlayAnimation(false); + SoundManager.PlaySound("FinalBoss_St1_DeathGrunt"); + Tween.RunFunction(0.1f, typeof(SoundManager), "PlaySound", "Player_Death_SwordTwirl"); + Tween.RunFunction(0.7f, typeof(SoundManager), "PlaySound", "Player_Death_SwordLand"); + Tween.RunFunction(1.2f, typeof(SoundManager), "PlaySound", "Player_Death_BodyFall"); + } + + // This sets all the player data once the last boss has been beaten. + public void SetPlayerData() + { + // Creating a new family tree node and saving. + FamilyTreeNode newNode = new FamilyTreeNode() + { + Name = Game.PlayerStats.PlayerName, + Age = Game.PlayerStats.Age, + ChildAge = Game.PlayerStats.ChildAge, + Class = Game.PlayerStats.Class, + HeadPiece = Game.PlayerStats.HeadPiece, + ChestPiece = Game.PlayerStats.ChestPiece, + ShoulderPiece = Game.PlayerStats.ShoulderPiece, + NumEnemiesBeaten = Game.PlayerStats.NumEnemiesBeaten, + BeatenABoss = true, + Traits = Game.PlayerStats.Traits, + IsFemale = Game.PlayerStats.IsFemale, + RomanNumeral = Game.PlayerStats.RomanNumeral, + }; + Game.PlayerStats.FamilyTreeArray.Add(newNode); + + // Setting necessary after-death flags and saving. + //Game.PlayerStats.IsDead = true; + //Game.PlayerStats.Traits = Vector2.Zero; + Game.PlayerStats.NewBossBeaten = false; + Game.PlayerStats.RerolledChildren = false; + Game.PlayerStats.NumEnemiesBeaten = 0; + Game.PlayerStats.LichHealth = 0; + Game.PlayerStats.LichMana = 0; + Game.PlayerStats.LichHealthMod = 1; + Game.PlayerStats.LoadStartingRoom = true; + + // The important one. These two flags will trigger new game plus at title screen. + Game.PlayerStats.LastbossBeaten = true; + Game.PlayerStats.CharacterFound = false; // This should be the ONLY place this is ever set to false. + Game.PlayerStats.TimesCastleBeaten++; + + // Thanatophobia trait. + if (Game.PlayerStats.ArchitectUsed == false && Game.PlayerStats.TimesDead <= 15) + GameUtil.UnlockAchievement("FEAR_OF_DYING"); + + (m_target.AttachedLevel.ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData); + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + Vector2 mtd = CollisionMath.CalculateMTD(thisBox.AbsRect, otherBox.AbsRect); + + PlayerObj player = otherBox.AbsParent as PlayerObj; + + // Hits the player in Tanooki mode. + if (player != null && otherBox.Type == Consts.TERRAIN_HITBOX && player.IsInvincible == false && player.State != PlayerObj.STATE_HURT) + player.HitPlayer(this); + + if (m_isTouchingGround == true && m_isHurt == true) + { + m_isHurt = false; + if (m_inSecondForm == false) + this.ChangeSprite("PlayerIdle_Character"); + } + + // This has to go before the wall check. + if (otherBox.AbsParent is EnemyObj_Platform == false) + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + + // This code gets him out of corners. + TerrainObj terrain = otherBox.AbsParent as TerrainObj; + if (terrain != null && m_isTouchingGround == false && terrain is DoorObj == false && m_inSecondForm == false) + { + if (m_currentActiveLB != null && m_currentActiveLB.IsActive == true) + m_currentActiveLB.StopLogicBlock(); + + if (mtd.X > 0) // Dash right + RunLogicBlock(true, m_firstFormDashAwayLB, 0, 100); // dashLeftLS, dashRightLS + else if (mtd.X < 0) //Dash left + RunLogicBlock(true, m_firstFormDashAwayLB, 100, 0); // dashLeftLS, dashRightLS + } + } + + public void Part2() + { + SoundManager.PlaySound("FinalBoss_St2_WeatherChange_a"); + m_levelScreen.UnpauseScreen(); + + if (m_currentActiveLB != null) + m_currentActiveLB.StopLogicBlock(); + + this.PauseEnemy(true); + m_target.CurrentSpeed = 0; + m_target.ForceInvincible = true; + + Tween.RunFunction(1, m_levelScreen, "RevealMorning"); + Tween.RunFunction(1, m_levelScreen.CurrentRoom, "ChangeWindowOpacity"); + Tween.RunFunction(5, this, "Part3"); + } + + public void Part3() + { + RCScreenManager manager = m_levelScreen.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("FinalBossTalk03"); + manager.DialogueScreen.SetConfirmEndHandler(this, "Part4"); + manager.DisplayScreen(ScreenType.Dialogue, true); + } + + public void Part4() + { + List dataList = new List(); + dataList.Add(this); + (m_levelScreen.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.GameOverBoss, true, dataList); + } + + public EnemyObj_LastBoss(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("PlayerIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + foreach (GameObj obj in _objectList) + obj.TextureColor = new Color(100, 100, 100); + + this.Type = EnemyType.LastBoss; + + m_damageShieldProjectiles = new List(); + + _objectList[PlayerPart.Boobs].Visible = false; + _objectList[PlayerPart.Extra].Visible = false; + _objectList[PlayerPart.Light].Visible = false; + _objectList[PlayerPart.Glasses].Visible = false; + _objectList[PlayerPart.Bowtie].Visible = false; + _objectList[PlayerPart.Wings].Visible = false; + + string headPart = (_objectList[PlayerPart.Head] as IAnimateableObj).SpriteName; + int numberIndex = headPart.IndexOf("_") - 1; + headPart = headPart.Remove(numberIndex, 1); + headPart = headPart.Replace("_", PlayerPart.IntroHelm + "_"); + _objectList[PlayerPart.Head].ChangeSprite(headPart); + this.PlayAnimation(true); + + m_delayObj = new BlankObj(0, 0); + + m_walkDownSoundFinalBoss = new FrameSoundObj(this, 3, "FinalBoss_St2_Foot_01", "FinalBoss_St2_Foot_02", "FinalBoss_St2_Foot_03"); + m_walkUpSoundFinalBoss = new FrameSoundObj(this, 6, "FinalBoss_St2_Foot_04", "FinalBoss_St2_Foot_05"); + } + + public override void ChangeSprite(string spriteName) + { + base.ChangeSprite(spriteName); + + if (m_inSecondForm == false) + { + string headPart = (_objectList[PlayerPart.Head] as IAnimateableObj).SpriteName; + int numberIndex = headPart.IndexOf("_") - 1; + headPart = headPart.Remove(numberIndex, 1); + headPart = headPart.Replace("_", PlayerPart.IntroHelm + "_"); + _objectList[PlayerPart.Head].ChangeSprite(headPart); + + _objectList[PlayerPart.Boobs].Visible = false; + _objectList[PlayerPart.Extra].Visible = false; + _objectList[PlayerPart.Light].Visible = false; + _objectList[PlayerPart.Glasses].Visible = false; + _objectList[PlayerPart.Bowtie].Visible = false; + _objectList[PlayerPart.Wings].Visible = false; + } + } + + public override void Draw(Camera2D camera) + { + // This here is just awful. But I can't put it in the update because when he's killed he stops updating. + if (IsKilled == true && this.TextureColor != Color.White) + { + m_blinkTimer = 0; + this.TextureColor = Color.White; + } + + base.Draw(camera); + } + + public override void Reset() + { + m_neoDying = false; + m_inSecondForm = false; + m_firstFormDying = false; + CanBeKnockedBack = true; + base.Reset(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_damageShieldProjectiles.Clear(); + m_damageShieldProjectiles = null; + m_delayObj.Dispose(); + m_delayObj = null; + + if (m_daggerProjData != null) + { + m_daggerProjData.Dispose(); + m_daggerProjData = null; + } + + if (m_axeProjData != null) + { + m_axeProjData.Dispose(); + m_axeProjData = null; + } + base.Dispose(); + } + } + + public bool IsSecondForm + { + get { return m_inSecondForm; } + } + + public void ForceSecondForm(bool value) + { + m_inSecondForm = value; + } + + public bool IsNeo + { + get { return m_isNeo; } + set + { + m_isNeo = value; + if (value == true) + { + HealthGainPerLevel = 0; + DamageGainPerLevel = 0; + ItemDropChance = 0; + MoneyDropChance = 0; + m_saveToEnemiesKilledList = false; + CanFallOffLedges = true; //TEDDY - Making Neo last boss fall off ledges. + } + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Mimic.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Mimic.cs new file mode 100644 index 0000000..df3d30b --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Mimic.cs @@ -0,0 +1,336 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_Mimic : EnemyObj + { + private bool m_isAttacking = false; + private LogicBlock m_generalBasicLB = new LogicBlock(); + + private FrameSoundObj m_closeSound; + + protected override void InitializeEV() + { + //this.AnimationDelay = 1 / 20f; + //this.Scale = new Vector2(2, 2); + //this.MaxHealth = 150; + //this.IsWeighted = true; + //this.JumpHeight = 400; + //this.Speed = 400; + + #region Basic Variables - General + Name = EnemyEV.Mimic_Basic_Name; + LocStringID = EnemyEV.Mimic_Basic_Name_locID; + + MaxHealth = EnemyEV.Mimic_Basic_MaxHealth; + Damage = EnemyEV.Mimic_Basic_Damage; + XPValue = EnemyEV.Mimic_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Mimic_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Mimic_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Mimic_Basic_DropChance; + + Speed = EnemyEV.Mimic_Basic_Speed; + TurnSpeed = EnemyEV.Mimic_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Mimic_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Mimic_Basic_Jump; + CooldownTime = EnemyEV.Mimic_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Mimic_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Mimic_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Mimic_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Mimic_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Mimic_Basic_IsWeighted; + + Scale = EnemyEV.Mimic_Basic_Scale; + ProjectileScale = EnemyEV.Mimic_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Mimic_Basic_Tint; + + MeleeRadius = EnemyEV.Mimic_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Mimic_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Mimic_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Mimic_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Mimic_Miniboss_Name; + LocStringID = EnemyEV.Mimic_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Mimic_Miniboss_MaxHealth; + Damage = EnemyEV.Mimic_Miniboss_Damage; + XPValue = EnemyEV.Mimic_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Mimic_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Mimic_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Mimic_Miniboss_DropChance; + + Speed = EnemyEV.Mimic_Miniboss_Speed; + TurnSpeed = EnemyEV.Mimic_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Mimic_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Mimic_Miniboss_Jump; + CooldownTime = EnemyEV.Mimic_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Mimic_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Mimic_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Mimic_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Mimic_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Mimic_Miniboss_IsWeighted; + + Scale = EnemyEV.Mimic_Miniboss_Scale; + ProjectileScale = EnemyEV.Mimic_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Mimic_Miniboss_Tint; + + MeleeRadius = EnemyEV.Mimic_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Mimic_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Mimic_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Mimic_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.Mimic_Expert_Name; + LocStringID = EnemyEV.Mimic_Expert_Name_locID; + + MaxHealth = EnemyEV.Mimic_Expert_MaxHealth; + Damage = EnemyEV.Mimic_Expert_Damage; + XPValue = EnemyEV.Mimic_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Mimic_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Mimic_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Mimic_Expert_DropChance; + + Speed = EnemyEV.Mimic_Expert_Speed; + TurnSpeed = EnemyEV.Mimic_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Mimic_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Mimic_Expert_Jump; + CooldownTime = EnemyEV.Mimic_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Mimic_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Mimic_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Mimic_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Mimic_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Mimic_Expert_IsWeighted; + + Scale = EnemyEV.Mimic_Expert_Scale; + ProjectileScale = EnemyEV.Mimic_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Mimic_Expert_Tint; + + MeleeRadius = EnemyEV.Mimic_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Mimic_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Mimic_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Mimic_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.Mimic_Advanced_Name; + LocStringID = EnemyEV.Mimic_Advanced_Name_locID; + + MaxHealth = EnemyEV.Mimic_Advanced_MaxHealth; + Damage = EnemyEV.Mimic_Advanced_Damage; + XPValue = EnemyEV.Mimic_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Mimic_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Mimic_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Mimic_Advanced_DropChance; + + Speed = EnemyEV.Mimic_Advanced_Speed; + TurnSpeed = EnemyEV.Mimic_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Mimic_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Mimic_Advanced_Jump; + CooldownTime = EnemyEV.Mimic_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Mimic_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Mimic_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Mimic_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Mimic_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Mimic_Advanced_IsWeighted; + + Scale = EnemyEV.Mimic_Advanced_Scale; + ProjectileScale = EnemyEV.Mimic_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Mimic_Advanced_Tint; + + MeleeRadius = EnemyEV.Mimic_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Mimic_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Mimic_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Mimic_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + this.LockFlip = true; + } + + protected override void InitializeLogic() + { + LogicSet basicWarningLS = new LogicSet(this); + basicWarningLS.AddAction(new ChangeSpriteLogicAction("EnemyMimicShake_Character",false, false)); + basicWarningLS.AddAction(new PlayAnimationLogicAction(false)); + basicWarningLS.AddAction(new ChangeSpriteLogicAction("EnemyMimicIdle_Character", true, false)); + basicWarningLS.AddAction(new DelayLogicAction(3)); + + LogicSet jumpTowardsLS = new LogicSet(this); + jumpTowardsLS.AddAction(new GroundCheckLogicAction()); // Make sure it can only jump while touching ground. + jumpTowardsLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpTowardsLS.AddAction(new MoveLogicAction(m_target, true, 0)); + jumpTowardsLS.AddAction(new LockFaceDirectionLogicAction(true)); + jumpTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemyMimicAttack_Character", true, true)); + jumpTowardsLS.AddAction(new MoveDirectionLogicAction()); + jumpTowardsLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Chest_Open_Large")); + jumpTowardsLS.AddAction(new JumpLogicAction()); + jumpTowardsLS.AddAction(new DelayLogicAction(0.3f)); + jumpTowardsLS.AddAction(new GroundCheckLogicAction()); + + LogicSet jumpUpLS = new LogicSet(this); + + m_generalBasicLB.AddLogicSet(basicWarningLS, jumpTowardsLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + if (m_isAttacking == false) + RunLogicBlock(false, m_generalBasicLB, 100, 0); // basicWarningLS, jumpTowardsLS + else + RunLogicBlock(false, m_generalBasicLB, 0, 100); // basicWarningLS, jumpTowardsLS + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + if (m_isAttacking == false) + RunLogicBlock(false, m_generalBasicLB, 100, 0); // basicWarningLS, jumpTowardsLS + else + RunLogicBlock(false, m_generalBasicLB, 0, 100); // basicWarningLS, jumpTowardsLS + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + if (m_isAttacking == false) + RunLogicBlock(false, m_generalBasicLB, 100, 0); // basicWarningLS, jumpTowardsLS + else + RunLogicBlock(false, m_generalBasicLB, 0, 100); // basicWarningLS, jumpTowardsLS + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + if (m_isAttacking == false) + RunLogicBlock(false, m_generalBasicLB, 100, 0); // basicWarningLS, jumpTowardsLS + else + RunLogicBlock(false, m_generalBasicLB, 0, 100); // basicWarningLS, jumpTowardsLS + break; + } + } + + public override void HitEnemy(int damage, Vector2 collisionPt, bool isPlayer) + { + if (m_isAttacking == false) + { + m_currentActiveLB.StopLogicBlock(); + m_isAttacking = true; + LockFlip = false; + } + base.HitEnemy(damage, collisionPt, isPlayer); + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + if (otherBox.AbsParent is PlayerObj) + { + if (m_isAttacking == false) + { + m_currentActiveLB.StopLogicBlock(); + m_isAttacking = true; + LockFlip = false; + } + } + + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + + public EnemyObj_Mimic(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyMimicIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.Mimic; + this.OutlineWidth = 0; + + m_closeSound = new FrameSoundObj(this, m_target, 1, "Chest_Snap"); + } + + public override void Update(GameTime gameTime) + { + if (this.SpriteName == "EnemyMimicAttack_Character") + m_closeSound.Update(); + base.Update(gameTime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + m_closeSound.Dispose(); + m_closeSound = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Ninja.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Ninja.cs new file mode 100644 index 0000000..f4abc68 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Ninja.cs @@ -0,0 +1,569 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_Ninja: EnemyObj + { + private LogicBlock m_basicTeleportAttackLB = new LogicBlock(); + private LogicBlock m_expertTeleportAttackLB = new LogicBlock(); + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + + private RoomObj m_storedRoom; // Used to make sure ninjas don't teleport to the room you're in. + + private SpriteObj m_smoke; + private SpriteObj m_log; + + private float TeleportDelay = 0.35f; + private float ChanceToTeleport = 0.35f; + private float PauseBeforeProjectile = 0.45f; + private float PauseAfterProjectile = 0.45f; + + private float m_teleportDamageReduc = 0.60f; + private TerrainObj m_closestCeiling; + + protected override void InitializeEV() + { + #region Basic Variables - General + Name = EnemyEV.Ninja_Basic_Name; + LocStringID = EnemyEV.Ninja_Basic_Name_locID; + + MaxHealth = EnemyEV.Ninja_Basic_MaxHealth; + Damage = EnemyEV.Ninja_Basic_Damage; + XPValue = EnemyEV.Ninja_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Ninja_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Ninja_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Ninja_Basic_DropChance; + + Speed = EnemyEV.Ninja_Basic_Speed; + TurnSpeed = EnemyEV.Ninja_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Ninja_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Ninja_Basic_Jump; + CooldownTime = EnemyEV.Ninja_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Ninja_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Ninja_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Ninja_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Ninja_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Ninja_Basic_IsWeighted; + + Scale = EnemyEV.Ninja_Basic_Scale; + ProjectileScale = EnemyEV.Ninja_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Ninja_Basic_Tint; + + MeleeRadius = EnemyEV.Ninja_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Ninja_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Ninja_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Ninja_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Ninja_Miniboss_Name; + LocStringID = EnemyEV.Ninja_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Ninja_Miniboss_MaxHealth; + Damage = EnemyEV.Ninja_Miniboss_Damage; + XPValue = EnemyEV.Ninja_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Ninja_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Ninja_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Ninja_Miniboss_DropChance; + + Speed = EnemyEV.Ninja_Miniboss_Speed; + TurnSpeed = EnemyEV.Ninja_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Ninja_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Ninja_Miniboss_Jump; + CooldownTime = EnemyEV.Ninja_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Ninja_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Ninja_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Ninja_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Ninja_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Ninja_Miniboss_IsWeighted; + + Scale = EnemyEV.Ninja_Miniboss_Scale; + ProjectileScale = EnemyEV.Ninja_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Ninja_Miniboss_Tint; + + MeleeRadius = EnemyEV.Ninja_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Ninja_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Ninja_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Ninja_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + + ChanceToTeleport = 0.65f; + #region Expert Variables - General + Name = EnemyEV.Ninja_Expert_Name; + LocStringID = EnemyEV.Ninja_Expert_Name_locID; + + MaxHealth = EnemyEV.Ninja_Expert_MaxHealth; + Damage = EnemyEV.Ninja_Expert_Damage; + XPValue = EnemyEV.Ninja_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Ninja_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Ninja_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Ninja_Expert_DropChance; + + Speed = EnemyEV.Ninja_Expert_Speed; + TurnSpeed = EnemyEV.Ninja_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Ninja_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Ninja_Expert_Jump; + CooldownTime = EnemyEV.Ninja_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Ninja_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Ninja_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Ninja_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Ninja_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Ninja_Expert_IsWeighted; + + Scale = EnemyEV.Ninja_Expert_Scale; + ProjectileScale = EnemyEV.Ninja_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Ninja_Expert_Tint; + + MeleeRadius = EnemyEV.Ninja_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Ninja_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Ninja_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Ninja_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + ChanceToTeleport = 0.50f; + + #region Advanced Variables - General + Name = EnemyEV.Ninja_Advanced_Name; + LocStringID = EnemyEV.Ninja_Advanced_Name_locID; + + MaxHealth = EnemyEV.Ninja_Advanced_MaxHealth; + Damage = EnemyEV.Ninja_Advanced_Damage; + XPValue = EnemyEV.Ninja_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Ninja_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Ninja_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Ninja_Advanced_DropChance; + + Speed = EnemyEV.Ninja_Advanced_Speed; + TurnSpeed = EnemyEV.Ninja_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Ninja_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Ninja_Advanced_Jump; + CooldownTime = EnemyEV.Ninja_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Ninja_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Ninja_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Ninja_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Ninja_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Ninja_Advanced_IsWeighted; + + Scale = EnemyEV.Ninja_Advanced_Scale; + ProjectileScale = EnemyEV.Ninja_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Ninja_Advanced_Tint; + + MeleeRadius = EnemyEV.Ninja_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Ninja_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Ninja_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Ninja_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + } + + protected override void InitializeLogic() + { + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemyNinjaRun_Character", true, true)); + walkTowardsLS.AddAction(new PlayAnimationLogicAction(true)); + walkTowardsLS.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsLS.AddAction(new DelayLogicAction(0.25f, 0.85f)); + + LogicSet walkAwayLS = new LogicSet(this); + walkAwayLS.AddAction(new ChangeSpriteLogicAction("EnemyNinjaRun_Character", true, true)); + walkAwayLS.AddAction(new PlayAnimationLogicAction(true)); + walkAwayLS.AddAction(new MoveLogicAction(m_target, false)); + walkAwayLS.AddAction(new DelayLogicAction(0.25f, 0.85f)); + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new ChangeSpriteLogicAction("EnemyNinjaIdle_Character", true, true)); + walkStopLS.AddAction(new StopAnimationLogicAction()); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(0.25f, 0.85f)); + + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "ShurikenProjectile1_Sprite", + SourceAnchor = new Vector2(15,0), + Target = m_target, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 20, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = true, + Scale = ProjectileScale, + }; + + LogicSet basicThrowShurikenLS = new LogicSet(this); + basicThrowShurikenLS.AddAction(new MoveLogicAction(m_target, true, 0)); + basicThrowShurikenLS.AddAction(new ChangeSpriteLogicAction("EnemyNinjaIdle_Character", true, true)); + basicThrowShurikenLS.AddAction(new DelayLogicAction(PauseBeforeProjectile)); + basicThrowShurikenLS.AddAction(new ChangeSpriteLogicAction("EnemyNinjaThrow_Character", false, false)); + basicThrowShurikenLS.AddAction(new PlayAnimationLogicAction(1, 3, false)); + basicThrowShurikenLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Ninja_ThrowStar_01", "Ninja_ThrowStar_02", "Ninja_ThrowStar_03")); + basicThrowShurikenLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + basicThrowShurikenLS.AddAction(new PlayAnimationLogicAction(4, 5, false)); + basicThrowShurikenLS.AddAction(new DelayLogicAction(PauseAfterProjectile)); + basicThrowShurikenLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet advancedThrowShurikenLS = new LogicSet(this); + advancedThrowShurikenLS.AddAction(new MoveLogicAction(m_target, true, 0)); + advancedThrowShurikenLS.AddAction(new ChangeSpriteLogicAction("EnemyNinjaIdle_Character", true, true)); + advancedThrowShurikenLS.AddAction(new DelayLogicAction(PauseBeforeProjectile)); + advancedThrowShurikenLS.AddAction(new ChangeSpriteLogicAction("EnemyNinjaThrow_Character", false, false)); + advancedThrowShurikenLS.AddAction(new PlayAnimationLogicAction(1, 3, false)); + advancedThrowShurikenLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "Ninja_ThrowStar_01", "Ninja_ThrowStar_02", "Ninja_ThrowStar_03")); + advancedThrowShurikenLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.AngleOffset = -10; + advancedThrowShurikenLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.AngleOffset = 10; + advancedThrowShurikenLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + advancedThrowShurikenLS.AddAction(new PlayAnimationLogicAction(4, 5, false)); + advancedThrowShurikenLS.AddAction(new DelayLogicAction(PauseAfterProjectile)); + advancedThrowShurikenLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet expertThrowShurikenLS = new LogicSet(this); + expertThrowShurikenLS.AddAction(new MoveLogicAction(m_target, true, 0)); + expertThrowShurikenLS.AddAction(new ChangeSpriteLogicAction("EnemyNinjaIdle_Character", true, true)); + expertThrowShurikenLS.AddAction(new DelayLogicAction(PauseBeforeProjectile)); + expertThrowShurikenLS.AddAction(new ChangeSpriteLogicAction("EnemyNinjaThrow_Character", false, false)); + expertThrowShurikenLS.AddAction(new PlayAnimationLogicAction(1, 3, false)); + expertThrowShurikenLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "Ninja_ThrowStar_01", "Ninja_ThrowStar_02", "Ninja_ThrowStar_03")); + projData.AngleOffset = 0; + expertThrowShurikenLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.AngleOffset = -5; + expertThrowShurikenLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.AngleOffset = 5; + expertThrowShurikenLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.AngleOffset = -25; + expertThrowShurikenLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.AngleOffset = 25; + expertThrowShurikenLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + expertThrowShurikenLS.AddAction(new PlayAnimationLogicAction(4, 5, false)); + expertThrowShurikenLS.AddAction(new DelayLogicAction(PauseAfterProjectile)); + expertThrowShurikenLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet teleportAttackLS = new LogicSet(this); + teleportAttackLS.AddAction(new LockFaceDirectionLogicAction(true)); + teleportAttackLS.AddAction(new RunFunctionLogicAction(this, "CreateLog", null)); + teleportAttackLS.AddAction(new DelayLogicAction(TeleportDelay)); + teleportAttackLS.AddAction(new RunFunctionLogicAction(this, "CreateSmoke", null)); + teleportAttackLS.AddAction(new DelayLogicAction(0.15f)); + teleportAttackLS.AddAction(new ChangePropertyLogicAction(this, "IsWeighted", true)); + teleportAttackLS.AddAction(new DelayLogicAction(0.15f)); + teleportAttackLS.AddAction(new GroundCheckLogicAction()); + teleportAttackLS.AddAction(new DelayLogicAction(0.15f)); + teleportAttackLS.AddAction(new LockFaceDirectionLogicAction(false)); + teleportAttackLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet teleportExpertAttackLS = new LogicSet(this); + teleportExpertAttackLS.AddAction(new LockFaceDirectionLogicAction(true)); + teleportExpertAttackLS.AddAction(new RunFunctionLogicAction(this, "CreateLog", null)); + teleportExpertAttackLS.AddAction(new DelayLogicAction(TeleportDelay)); + teleportExpertAttackLS.AddAction(new RunFunctionLogicAction(this, "CreateSmoke", null)); + projData.Target = null; + teleportExpertAttackLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "Ninja_ThrowStar_01", "Ninja_ThrowStar_02", "Ninja_ThrowStar_03")); + projData.AngleOffset = 45; + teleportExpertAttackLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.AngleOffset = 135; + teleportExpertAttackLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.AngleOffset = -45; + teleportExpertAttackLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.AngleOffset = -135; + teleportExpertAttackLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + teleportExpertAttackLS.AddAction(new DelayLogicAction(0.15f)); + teleportExpertAttackLS.AddAction(new ChangePropertyLogicAction(this, "IsWeighted", true)); + teleportExpertAttackLS.AddAction(new DelayLogicAction(0.15f)); + teleportExpertAttackLS.AddAction(new GroundCheckLogicAction()); + teleportExpertAttackLS.AddAction(new DelayLogicAction(0.15f)); + teleportExpertAttackLS.AddAction(new LockFaceDirectionLogicAction(false)); + teleportExpertAttackLS.Tag = GameTypes.LogicSetType_ATTACK; + + m_basicTeleportAttackLB.AddLogicSet(teleportAttackLS); + m_expertTeleportAttackLB.AddLogicSet(teleportExpertAttackLS); + logicBlocksToDispose.Add(m_basicTeleportAttackLB); + logicBlocksToDispose.Add(m_expertTeleportAttackLB); + + m_generalBasicLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, basicThrowShurikenLS); + m_generalAdvancedLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, advancedThrowShurikenLS); + m_generalExpertLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, expertThrowShurikenLS); + m_generalCooldownLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + + SetCooldownLogicBlock(m_generalCooldownLB, 50, 50, 0); //walkTowardsLS, walkAwayLS, walkStopLS + + projData.Dispose(); + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 40, 30, 0, 30); //walkTowardsLS, walkAwayLS, walkStopLS, basicThrowShurikenLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 65, 35, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, basicThrowShurikenLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 50, 50, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, basicThrowShurikenLS + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 40, 30, 0, 30); //walkTowardsLS, walkAwayLS, walkStopLS, basicThrowShurikenLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 65, 35, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, basicThrowShurikenLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalAdvancedLB, 50, 50, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, basicThrowShurikenLS + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 40, 30, 0, 30); //walkTowardsLS, walkAwayLS, walkStopLS, basicThrowShurikenLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 65, 35, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, basicThrowShurikenLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalExpertLB, 50, 50, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, basicThrowShurikenLS + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 40, 30, 0, 30); //walkTowardsLS, walkAwayLS, walkStopLS, basicThrowShurikenLS + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 65, 35, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, basicThrowShurikenLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 50, 50, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, basicThrowShurikenLS + break; + default: + break; + } + } + + public EnemyObj_Ninja(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyNinjaIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.Ninja; + m_smoke = new SpriteObj("NinjaSmoke_Sprite"); + m_smoke.AnimationDelay = 1 / 20f; + m_log = new SpriteObj("Log_Sprite"); + m_smoke.Visible = false; + m_smoke.Scale = new Vector2(5, 5); + m_log.Visible = false; + m_log.OutlineWidth = 2; + } + + public override void Update(GameTime gameTime) + { + if (this.Y < m_levelScreen.CurrentRoom.Y) + this.Y = m_levelScreen.CurrentRoom.Y; + base.Update(gameTime); + } + + public override void HitEnemy(int damage, Vector2 position, bool isPlayer) + { + if (m_target != null && m_target.CurrentHealth > 0) + { + if (m_currentActiveLB != m_basicTeleportAttackLB && m_currentActiveLB != m_expertTeleportAttackLB) + { + if (CDGMath.RandomFloat(0, 1) <= ChanceToTeleport && m_closestCeiling != null) + { + m_closestCeiling = FindClosestCeiling(); + int distance = this.TerrainBounds.Top - m_closestCeiling.Bounds.Bottom; + if (m_closestCeiling != null && distance > 150 && distance < 700) + { + m_currentActiveLB.StopLogicBlock(); + if (this.Difficulty == GameTypes.EnemyDifficulty.EXPERT) + RunLogicBlock(false, m_expertTeleportAttackLB, 100); + else + RunLogicBlock(false, m_basicTeleportAttackLB, 100); + + // Modify damage so that the ninja takes less. + //float damageMod = ; + damage = (int)(Math.Round(damage * (1 - m_teleportDamageReduc), MidpointRounding.AwayFromZero)); + } + } + } + } + + base.HitEnemy(damage, position, isPlayer); + } + + private TerrainObj FindClosestCeiling() + { + int closestDistance = int.MaxValue; + TerrainObj closestObj = null; + + RoomObj room = m_levelScreen.CurrentRoom; + + foreach (TerrainObj terrain in room.TerrainObjList) + { + Rectangle collisionTestRect = new Rectangle(this.Bounds.Left, this.Bounds.Top - 2000, this.Bounds.Width, this.Bounds.Height + 2000); + + if (terrain.CollidesBottom == true && CollisionMath.Intersects(terrain.Bounds, collisionTestRect)) + { + // Only collide with terrain that the displacer would collide with. + float distance = float.MaxValue; + if (terrain.Bounds.Bottom < this.TerrainBounds.Top) + distance = this.TerrainBounds.Top - terrain.Bounds.Bottom; + + if (distance < closestDistance) + { + closestDistance = (int)distance; + closestObj = terrain; + } + } + } + + return closestObj; + } + + public void CreateLog() + { + m_log.Position = this.Position; + m_smoke.Position = this.Position; + m_smoke.Visible = true; + m_log.Visible = true; + m_log.Opacity = 1; + m_smoke.PlayAnimation(false); + + Tweener.Tween.By(m_log, 0.1f, Tweener.Ease.Linear.EaseNone, "delay", "0.2", "Y", "10"); + Tweener.Tween.To(m_log, 0.2f, Tweener.Ease.Linear.EaseNone, "delay", "0.3", "Opacity", "0"); + + SoundManager.Play3DSound(this, m_target, "Ninja_Teleport"); + this.Visible = false; + this.IsCollidable = false; + this.IsWeighted = false; + + m_storedRoom = m_levelScreen.CurrentRoom; + } + + public void CreateSmoke() + { + if (m_levelScreen.CurrentRoom == m_storedRoom && m_closestCeiling != null) + { + //if (this.Y < m_levelScreen.CurrentRoom.Y) + // this.Y = m_levelScreen.CurrentRoom.Y + 60; + + //foreach (TerrainObj obj in m_levelScreen.CurrentRoom.TerrainObjList) + //{ + // if (CollisionMath.Intersects(this.Bounds, obj.Bounds)) + // this.Y = obj.Bounds.Bottom + this.Height / 2; + //} + + this.UpdateCollisionBoxes(); + this.Y = m_closestCeiling.Bounds.Bottom + (this.Y - this.TerrainBounds.Top); + this.X = m_target.X; + this.ChangeSprite("EnemyNinjaAttack_Character"); + this.Visible = true; + this.AccelerationX = 0; + this.AccelerationY = 0; + this.CurrentSpeed = 0; + this.IsCollidable = true; + m_smoke.Position = this.Position; + m_smoke.Visible = true; + m_smoke.PlayAnimation(false); + m_closestCeiling = null; + } + } + + public override void Draw(Camera2D camera) + { + base.Draw(camera); + m_log.Draw(camera); + m_smoke.Draw(camera); + } + + public override void Kill(bool giveXP = true) + { + m_smoke.Visible = false; + m_log.Visible = false; + base.Kill(giveXP); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_storedRoom = null; + m_smoke.Dispose(); + m_smoke = null; + m_log.Dispose(); + m_log = null; + m_closestCeiling = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Plant.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Plant.cs new file mode 100644 index 0000000..3538e81 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Plant.cs @@ -0,0 +1,400 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_Plant : EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + private LogicBlock m_generalCooldownExpertLB = new LogicBlock(); + + protected override void InitializeEV() + { + #region Basic Variables - General + Name = EnemyEV.Plant_Basic_Name; + LocStringID = EnemyEV.Plant_Basic_Name_locID; + + MaxHealth = EnemyEV.Plant_Basic_MaxHealth; + Damage = EnemyEV.Plant_Basic_Damage; + XPValue = EnemyEV.Plant_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Plant_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Plant_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Plant_Basic_DropChance; + + Speed = EnemyEV.Plant_Basic_Speed; + TurnSpeed = EnemyEV.Plant_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Plant_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Plant_Basic_Jump; + CooldownTime = EnemyEV.Plant_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Plant_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Plant_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Plant_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Plant_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Plant_Basic_IsWeighted; + + Scale = EnemyEV.Plant_Basic_Scale; + ProjectileScale = EnemyEV.Plant_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Plant_Basic_Tint; + + MeleeRadius = EnemyEV.Plant_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Plant_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Plant_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Plant_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Plant_Miniboss_Name; + LocStringID = EnemyEV.Plant_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Plant_Miniboss_MaxHealth; + Damage = EnemyEV.Plant_Miniboss_Damage; + XPValue = EnemyEV.Plant_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Plant_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Plant_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Plant_Miniboss_DropChance; + + Speed = EnemyEV.Plant_Miniboss_Speed; + TurnSpeed = EnemyEV.Plant_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Plant_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Plant_Miniboss_Jump; + CooldownTime = EnemyEV.Plant_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Plant_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Plant_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Plant_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Plant_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Plant_Miniboss_IsWeighted; + + Scale = EnemyEV.Plant_Miniboss_Scale; + ProjectileScale = EnemyEV.Plant_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Plant_Miniboss_Tint; + + MeleeRadius = EnemyEV.Plant_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Plant_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Plant_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Plant_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.Plant_Expert_Name; + LocStringID = EnemyEV.Plant_Expert_Name_locID; + + MaxHealth = EnemyEV.Plant_Expert_MaxHealth; + Damage = EnemyEV.Plant_Expert_Damage; + XPValue = EnemyEV.Plant_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Plant_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Plant_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Plant_Expert_DropChance; + + Speed = EnemyEV.Plant_Expert_Speed; + TurnSpeed = EnemyEV.Plant_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Plant_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Plant_Expert_Jump; + CooldownTime = EnemyEV.Plant_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Plant_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Plant_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Plant_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Plant_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Plant_Expert_IsWeighted; + + Scale = EnemyEV.Plant_Expert_Scale; + ProjectileScale = EnemyEV.Plant_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Plant_Expert_Tint; + + MeleeRadius = EnemyEV.Plant_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Plant_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Plant_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Plant_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.Plant_Advanced_Name; + LocStringID = EnemyEV.Plant_Advanced_Name_locID; + + MaxHealth = EnemyEV.Plant_Advanced_MaxHealth; + Damage = EnemyEV.Plant_Advanced_Damage; + XPValue = EnemyEV.Plant_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Plant_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Plant_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Plant_Advanced_DropChance; + + Speed = EnemyEV.Plant_Advanced_Speed; + TurnSpeed = EnemyEV.Plant_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Plant_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Plant_Advanced_Jump; + CooldownTime = EnemyEV.Plant_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Plant_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Plant_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Plant_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Plant_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Plant_Advanced_IsWeighted; + + Scale = EnemyEV.Plant_Advanced_Scale; + ProjectileScale = EnemyEV.Plant_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Plant_Advanced_Tint; + + MeleeRadius = EnemyEV.Plant_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Plant_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Plant_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Plant_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + _objectList[1].TextureColor = new Color(201, 59, 136); + } + + protected override void InitializeLogic() + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "PlantProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = true, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = true, + Scale = ProjectileScale, + //Angle = new Vector2(-100, -100), + }; + + LogicSet spitProjectileLS = new LogicSet(this); + spitProjectileLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Enemy_Venus_Squirm_01", "Enemy_Venus_Squirm_02", "Enemy_Venus_Squirm_03")); + spitProjectileLS.AddAction(new ChangeSpriteLogicAction("EnemyPlantAttack_Character", false, false)); + spitProjectileLS.AddAction(new PlayAnimationLogicAction(1, this.TotalFrames - 1)); + spitProjectileLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Enemy_Venus_Attack_01")); + projData.Angle = new Vector2(-90, -90); + spitProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-75, -75); + spitProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-105, -105); + spitProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + spitProjectileLS.AddAction(new PlayAnimationLogicAction(this.TotalFrames - 1, TotalFrames)); + spitProjectileLS.AddAction(new ChangeSpriteLogicAction("EnemyPlantIdle_Character", true, true)); + //spitProjectileLS.AddAction(new DelayLogicAction(2.0f)); + spitProjectileLS.Tag = GameTypes.LogicSetType_ATTACK; + + + + LogicSet spitAdvancedProjectileLS = new LogicSet(this); + spitAdvancedProjectileLS.AddAction(new ChangeSpriteLogicAction("EnemyPlantAttack_Character", false, false)); + spitAdvancedProjectileLS.AddAction(new PlayAnimationLogicAction(1, this.TotalFrames - 1)); + spitAdvancedProjectileLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Enemy_Venus_Attack_01")); + projData.Angle = new Vector2(-60, -60); + spitAdvancedProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-90, -90); + spitAdvancedProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-75, -75); + spitAdvancedProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-105, -105); + spitAdvancedProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-120, -120); + spitAdvancedProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + spitAdvancedProjectileLS.AddAction(new PlayAnimationLogicAction(this.TotalFrames - 1, TotalFrames)); + spitAdvancedProjectileLS.AddAction(new ChangeSpriteLogicAction("EnemyPlantIdle_Character", true, true)); + //spitAdvancedProjectileLS.AddAction(new DelayLogicAction(2.0f)); + spitAdvancedProjectileLS.Tag = GameTypes.LogicSetType_ATTACK; + + + LogicSet spitExpertProjectileLS = new LogicSet(this); + spitExpertProjectileLS.AddAction(new ChangeSpriteLogicAction("EnemyPlantAttack_Character", false, false)); + spitExpertProjectileLS.AddAction(new PlayAnimationLogicAction(1, this.TotalFrames - 1)); + spitExpertProjectileLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Enemy_Venus_Attack_01")); + + projData.Angle = new Vector2(-45, -45); + spitExpertProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-60, -60); + spitExpertProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-85, -85); + spitExpertProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-90, -90); + spitExpertProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-95, -95); + spitExpertProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-75, -75); + spitExpertProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-105, -105); + spitExpertProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-120, -120); + spitExpertProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-135, -135); + spitExpertProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + spitExpertProjectileLS.AddAction(new PlayAnimationLogicAction(this.TotalFrames - 1, TotalFrames)); + spitExpertProjectileLS.AddAction(new ChangeSpriteLogicAction("EnemyPlantIdle_Character", true, true)); + //spitExpertProjectileLS.AddAction(new DelayLogicAction(2.0f)); + spitExpertProjectileLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet spitMinibossProjectileLS = new LogicSet(this); + spitMinibossProjectileLS.AddAction(new ChangeSpriteLogicAction("EnemyPlantAttack_Character", false, false)); + spitMinibossProjectileLS.AddAction(new PlayAnimationLogicAction(1, this.TotalFrames - 1)); + spitMinibossProjectileLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Enemy_Venus_Attack_01")); + + projData.Angle = new Vector2(-60, -60); + spitMinibossProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-87, -87); + spitMinibossProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-90, -90); + spitMinibossProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-93, -93); + spitMinibossProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-75, -75); + spitMinibossProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-105, -105); + spitMinibossProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-120, -120); + spitMinibossProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + spitMinibossProjectileLS.AddAction(new PlayAnimationLogicAction(this.TotalFrames - 1, TotalFrames)); + spitMinibossProjectileLS.AddAction(new ChangeSpriteLogicAction("EnemyPlantIdle_Character", true, true)); + //spitExpertProjectileLS.AddAction(new DelayLogicAction(2.0f)); + spitMinibossProjectileLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new ChangeSpriteLogicAction("EnemyPlantIdle_Character", true, true)); + //walkStopLS.AddAction(new StopAnimationLogicAction()); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(0.25f)); + + + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Enemy_Venus_Squirm_01", "Enemy_Venus_Squirm_02", "Enemy_Venus_Squirm_03", "Blank", "Blank", "Blank")); + walkTowardsLS.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsLS.AddAction(new DelayLogicAction(0.25f, 0.45f)); + + LogicSet walkAwayLS = new LogicSet(this); + walkAwayLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Enemy_Venus_Squirm_01", "Enemy_Venus_Squirm_02", "Enemy_Venus_Squirm_03", "Blank", "Blank", "Blank")); + walkAwayLS.AddAction(new MoveLogicAction(m_target, false)); + walkAwayLS.AddAction(new DelayLogicAction(0.25f, 0.45f)); + + LogicSet walkStopMiniBossLS = new LogicSet(this); + walkStopMiniBossLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Enemy_Venus_Squirm_01", "Enemy_Venus_Squirm_02", "Enemy_Venus_Squirm_03", "Blank", "Blank", "Blank")); + walkStopMiniBossLS.AddAction(new ChangeSpriteLogicAction("EnemyPlantIdle_Character", true, true)); + //walkStopLS.AddAction(new StopAnimationLogicAction()); + walkStopMiniBossLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopMiniBossLS.AddAction(new DelayLogicAction(0.25f, 0.45f)); + + m_generalBasicLB.AddLogicSet(spitProjectileLS); + m_generalAdvancedLB.AddLogicSet(spitAdvancedProjectileLS); + m_generalExpertLB.AddLogicSet(spitExpertProjectileLS); + m_generalMiniBossLB.AddLogicSet(spitMinibossProjectileLS); + m_generalCooldownLB.AddLogicSet(walkStopLS); + m_generalCooldownExpertLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopMiniBossLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalMiniBossLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + logicBlocksToDispose.Add(m_generalCooldownExpertLB); + + SetCooldownLogicBlock(m_generalCooldownLB, 100); //walkStopLS + if (Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + SetCooldownLogicBlock(m_generalCooldownExpertLB, 50, 50, 0); //walkTowardsLS, walkAwayLS, walkStopLS + + projData.Dispose(); + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 100); + break; + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 100); + break; + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 100); + break; + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + RunLogicBlock(true, m_generalMiniBossLB, 100); + break; + default: + break; + } + } + + public EnemyObj_Plant(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyPlantIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.Plant; + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Platform.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Platform.cs new file mode 100644 index 0000000..05c47d8 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Platform.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_Platform : EnemyObj + { + private bool m_isExtended = false; + private float m_retractCounter = 0; + private bool m_blinkedWarning = false; + + private float RetractDelay = 0f; + + protected override void InitializeEV() + { + Scale = new Vector2(2.0f, 2.0f);//(1.0f, 1.0f); + AnimationDelay = 1 / 30f; + //ProjectileScale = new Vector2(3.0f, 3.0f); + Speed = 0.0f; + MaxHealth = 999; + EngageRadius = 30; + ProjectileRadius = 20; + MeleeRadius = 10; + CooldownTime = 2.0f; + KnockBack = new Vector2(1, 2); + Damage = 25; + JumpHeight = 20.5f; + AlwaysFaceTarget = false; + CanFallOffLedges = false; + XPValue = 2; + CanBeKnockedBack = false; + this.LockFlip = true; + this.IsWeighted = false; + RetractDelay = 3.0f;//5f; + Name = "Platform"; + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + case (GameTypes.EnemyDifficulty.EXPERT): + case (GameTypes.EnemyDifficulty.ADVANCED): + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + if (Game.PlayerStats.Traits.X == TraitType.PlatformsOpen || Game.PlayerStats.Traits.Y == TraitType.PlatformsOpen) + { + m_isExtended = true; + this.PlayAnimation("EndRetract", "EndRetract"); + } + } + + public override void Update(GameTime gameTime) + { + bool forceExtract = false; + if (Game.PlayerStats.Traits.X == TraitType.PlatformsOpen || Game.PlayerStats.Traits.Y == TraitType.PlatformsOpen) + forceExtract = true; + + if (forceExtract == false) + { + if (m_retractCounter > 0) + { + m_retractCounter -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_retractCounter <= 1.5f && m_blinkedWarning == false) + { + m_blinkedWarning = true; + + float delay = 0; + for (int i = 0; i < 10; i++) + { + Tweener.Tween.RunFunction(delay, this, "Blink", Color.Red, 0.05f); + delay += 0.1f; + } + } + + if (m_retractCounter <= 0) + { + m_isExtended = false; + PlayAnimation("StartExtract", "EndExtract"); // Got the naming flipped in the spritesheet. + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "Platform_Activate_03", "Platform_Activate_04"); + } + } + } + else + { + if (m_isExtended == false) + { + m_isExtended = true; + this.PlayAnimation("EndRetract", "EndRetract"); + } + } + + base.Update(gameTime); + } + + public override void HitEnemy(int damage, Vector2 position, bool isPlayer = true) + { + if (m_target.IsAirAttacking == true) + { + if (m_isExtended == false && (this.CurrentFrame == 1 || this.CurrentFrame == TotalFrames)) + { + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"EnemyHit1", "EnemyHit2", "EnemyHit3", "EnemyHit4", "EnemyHit5", "EnemyHit6"); + Blink(Color.Red, 0.1f); + this.m_levelScreen.ImpactEffectPool.DisplayEnemyImpactEffect(position); + + m_isExtended = true; + m_blinkedWarning = false; + PlayAnimation("StartRetract", "EndRetract"); + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "Platform_Activate_01", "Platform_Activate_02"); + m_retractCounter = RetractDelay; + + if (m_target.IsAirAttacking == true) + { + m_target.IsAirAttacking = false; // Only allow one object to perform upwards air knockback on the player. + m_target.AccelerationY = -m_target.AirAttackKnockBack; + m_target.NumAirBounces++; + } + } + } + } + + public override void ResetState() + { + if (Game.PlayerStats.Traits.X == TraitType.PlatformsOpen || Game.PlayerStats.Traits.Y == TraitType.PlatformsOpen) + return; + this.PlayAnimation(1, 1); + m_isExtended = false; + m_blinkedWarning = false; + m_retractCounter = 0; + base.ResetState(); + } + + public override void Reset() + { + if (Game.PlayerStats.Traits.X == TraitType.PlatformsOpen || Game.PlayerStats.Traits.Y == TraitType.PlatformsOpen) + return; + this.PlayAnimation(1, 1); + m_isExtended = false; + m_blinkedWarning = false; + m_retractCounter = 0; + base.Reset(); + this.StopAnimation(); + } + + public EnemyObj_Platform(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyPlatform_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.CollisionTypeTag = GameTypes.CollisionType_WALL; + this.Type = EnemyType.Platform; + this.CollidesBottom = false; + this.CollidesLeft = false; + this.CollidesRight = false; + this.StopAnimation(); + this.PlayAnimationOnRestart = false; + NonKillable = true; + this.DisableCollisionBoxRotations = false; + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Portrait.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Portrait.cs new file mode 100644 index 0000000..eae9921 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Portrait.cs @@ -0,0 +1,510 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; + +namespace RogueCastle +{ + public class EnemyObj_Portrait : EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + + public bool Shake { get; set; } + public bool Chasing { get; set; } + + protected override void InitializeEV() + { + this.LockFlip = true; + + #region Basic Variables - General + Name = EnemyEV.Portrait_Basic_Name; + LocStringID = EnemyEV.Portrait_Basic_Name_locID; + + MaxHealth = EnemyEV.Portrait_Basic_MaxHealth; + Damage = EnemyEV.Portrait_Basic_Damage; + XPValue = EnemyEV.Portrait_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Portrait_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Portrait_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Portrait_Basic_DropChance; + + Speed = EnemyEV.Portrait_Basic_Speed; + TurnSpeed = EnemyEV.Portrait_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Portrait_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Portrait_Basic_Jump; + CooldownTime = EnemyEV.Portrait_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Portrait_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Portrait_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Portrait_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Portrait_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Portrait_Basic_IsWeighted; + + Scale = EnemyEV.Portrait_Basic_Scale; + ProjectileScale = EnemyEV.Portrait_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Portrait_Basic_Tint; + + MeleeRadius = EnemyEV.Portrait_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Portrait_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Portrait_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Portrait_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Portrait_Miniboss_Name; + LocStringID = EnemyEV.Portrait_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Portrait_Miniboss_MaxHealth; + Damage = EnemyEV.Portrait_Miniboss_Damage; + XPValue = EnemyEV.Portrait_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Portrait_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Portrait_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Portrait_Miniboss_DropChance; + + Speed = EnemyEV.Portrait_Miniboss_Speed; + TurnSpeed = EnemyEV.Portrait_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Portrait_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Portrait_Miniboss_Jump; + CooldownTime = EnemyEV.Portrait_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Portrait_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Portrait_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Portrait_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Portrait_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Portrait_Miniboss_IsWeighted; + + Scale = EnemyEV.Portrait_Miniboss_Scale; + ProjectileScale = EnemyEV.Portrait_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Portrait_Miniboss_Tint; + + MeleeRadius = EnemyEV.Portrait_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Portrait_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Portrait_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Portrait_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.Portrait_Expert_Name; + LocStringID = EnemyEV.Portrait_Expert_Name_locID; + + MaxHealth = EnemyEV.Portrait_Expert_MaxHealth; + Damage = EnemyEV.Portrait_Expert_Damage; + XPValue = EnemyEV.Portrait_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Portrait_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Portrait_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Portrait_Expert_DropChance; + + Speed = EnemyEV.Portrait_Expert_Speed; + TurnSpeed = EnemyEV.Portrait_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Portrait_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Portrait_Expert_Jump; + CooldownTime = EnemyEV.Portrait_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Portrait_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Portrait_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Portrait_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Portrait_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Portrait_Expert_IsWeighted; + + Scale = EnemyEV.Portrait_Expert_Scale; + ProjectileScale = EnemyEV.Portrait_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Portrait_Expert_Tint; + + MeleeRadius = EnemyEV.Portrait_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Portrait_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Portrait_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Portrait_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.Portrait_Advanced_Name; + LocStringID = EnemyEV.Portrait_Advanced_Name_locID; + + MaxHealth = EnemyEV.Portrait_Advanced_MaxHealth; + Damage = EnemyEV.Portrait_Advanced_Damage; + XPValue = EnemyEV.Portrait_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Portrait_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Portrait_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Portrait_Advanced_DropChance; + + Speed = EnemyEV.Portrait_Advanced_Speed; + TurnSpeed = EnemyEV.Portrait_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Portrait_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Portrait_Advanced_Jump; + CooldownTime = EnemyEV.Portrait_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Portrait_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Portrait_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Portrait_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Portrait_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Portrait_Advanced_IsWeighted; + + Scale = EnemyEV.Portrait_Advanced_Scale; + ProjectileScale = EnemyEV.Portrait_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Portrait_Advanced_Tint; + + MeleeRadius = EnemyEV.Portrait_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Portrait_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Portrait_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Portrait_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + } + + protected override void InitializeLogic() + { + LogicSet basicWarningLS = new LogicSet(this); + basicWarningLS.AddAction(new ChangePropertyLogicAction(this, "Shake", true)); + basicWarningLS.AddAction(new DelayLogicAction(1)); + basicWarningLS.AddAction(new ChangePropertyLogicAction(this, "Shake", false)); + basicWarningLS.AddAction(new DelayLogicAction(1)); + + LogicSet moveTowardsLS = new LogicSet(this); + moveTowardsLS.AddAction(new ChaseLogicAction(m_target, Vector2.Zero, Vector2.Zero, true, 1)); + + LogicSet moveTowardsAdvancedLS = new LogicSet(this); + moveTowardsAdvancedLS.AddAction(new ChaseLogicAction(m_target, Vector2.Zero, Vector2.Zero, true, 1.75f)); + ThrowAdvancedProjectiles(moveTowardsAdvancedLS, true); + + LogicSet moveTowardsExpertLS = new LogicSet(this); + moveTowardsExpertLS.AddAction(new ChaseLogicAction(m_target, Vector2.Zero, Vector2.Zero, true, 1.75f)); + ThrowExpertProjectiles(moveTowardsExpertLS, true); + + LogicSet moveTowardsMiniBosstLS = new LogicSet(this); + moveTowardsMiniBosstLS.AddAction(new ChaseLogicAction(m_target, Vector2.Zero, Vector2.Zero, true, 1.25f)); + ThrowProjectiles(moveTowardsMiniBosstLS, true); + + m_generalBasicLB.AddLogicSet(basicWarningLS, moveTowardsLS); + m_generalAdvancedLB.AddLogicSet(basicWarningLS, moveTowardsAdvancedLS); + m_generalExpertLB.AddLogicSet(basicWarningLS, moveTowardsExpertLS); + m_generalMiniBossLB.AddLogicSet(basicWarningLS, moveTowardsMiniBosstLS); + m_generalCooldownLB.AddLogicSet(basicWarningLS, moveTowardsLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalMiniBossLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + + base.InitializeLogic(); + + // HACK ALERT + // This is NOT the right way to add collision boxes but it doesn't seem to be working the normal way. This may cause problems though. + this.CollisionBoxes.Clear(); + this.CollisionBoxes.Add(new CollisionBox((int)(-18 * this.ScaleX), (int)(-24 * this.ScaleY), (int)(36 * this.ScaleX), (int)(48 * this.ScaleY), 2, this)); + this.CollisionBoxes.Add(new CollisionBox((int)(-15 * this.ScaleX), (int)(-21 * this.ScaleY), (int)(31 * this.ScaleX), (int)(44 * this.ScaleY), 1, this)); + + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + { + (GetChildAt(0) as SpriteObj).ChangeSprite("GiantPortrait_Sprite"); + this.Scale = new Vector2(2, 2); + SpriteObj pic = new SpriteObj("Portrait" + CDGMath.RandomInt(0, 7) + "_Sprite"); + pic.OverrideParentScale = true; + this.AddChild(pic); + this.CollisionBoxes.Clear(); + this.CollisionBoxes.Add(new CollisionBox(-62 * 2, -88 * 2, 125 * 2, 177 * 2, 2, this)); + this.CollisionBoxes.Add(new CollisionBox(-62 * 2, -88 * 2, 125 * 2, 177 * 2, 1, this)); + } + + } + + private void ThrowProjectiles(LogicSet ls, bool useBossProjectile = false) + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "GhostProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(0, 0), + CollidesWithTerrain = false, + Scale = ProjectileScale, + }; + + //if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + //projData.SpriteName = "GhostProjectileBoss_Sprite"; + + ls.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"FairyAttack1")); + projData.Angle = new Vector2(135, 135); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(45, 45); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-45, -45); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-135, -135); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Dispose(); + } + + private void ThrowExpertProjectiles(LogicSet ls, bool useBossProjectile = false) + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "GhostProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(0, 0), + CollidesWithTerrain = false, + Scale = ProjectileScale, + }; + + //if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + //projData.SpriteName = "GhostProjectileBoss_Sprite"; + + ls.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"FairyAttack1")); + projData.Angle = new Vector2(0, 0); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(90, 90); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-90, -90); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(180, 180); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Dispose(); + } + + private void ThrowAdvancedProjectiles(LogicSet ls, bool useBossProjectile = false) + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "GhostProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(0, 0), + CollidesWithTerrain = false, + Scale = ProjectileScale, + }; + + //if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + //projData.SpriteName = "GhostProjectileBoss_Sprite"; + + ls.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"FairyAttack1")); + projData.Angle = new Vector2(90, 90); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-90, -90); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Dispose(); + } + + protected override void RunBasicLogic() + { + if (Chasing == false) + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + ChasePlayer(); + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 100, 0); + break; + case (STATE_WANDER): + break; + default: + break; + } + } + else + RunLogicBlock(true, m_generalBasicLB, 0, 100); + } + + protected override void RunAdvancedLogic() + { + if (Chasing == false) + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + ChasePlayer(); + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 100, 0); + break; + case (STATE_WANDER): + break; + default: + break; + } + } + else + RunLogicBlock(true, m_generalAdvancedLB, 0, 100); + } + + protected override void RunExpertLogic() + { + if (Chasing == false) + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + ChasePlayer(); + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 100, 0); + break; + case (STATE_WANDER): + break; + default: + break; + } + } + else + RunLogicBlock(true, m_generalExpertLB, 0, 100); + } + + protected override void RunMinibossLogic() + { + if (Chasing == false) + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + Chasing = true; + break; + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalMiniBossLB, 100, 0); + break; + case (STATE_WANDER): + break; + default: + break; + } + } + else + RunLogicBlock(true, m_generalMiniBossLB, 0, 100); + } + + public override void Update(GameTime gameTime) + { + float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds; + + if (Chasing == false) + { + if (this.Difficulty != GameTypes.EnemyDifficulty.MINIBOSS) + { + if (Shake == true) + this.Rotation = (float)Math.Sin(Game.TotalGameTime * 15) * 2; + else + this.Rotation = 0; + } + } + else + { + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + this.Rotation += (420 * elapsedSeconds); + //this.Rotation += 7; + else + this.Rotation += (600 * elapsedSeconds); + //this.Rotation += 10; + + SpriteObj portrait = this.GetChildAt(0) as SpriteObj; + if (portrait.SpriteName != "EnemyPortrait" + (int)this.Difficulty + "_Sprite") + ChangePortrait(); + } + + base.Update(gameTime); + } + + public override void HitEnemy(int damage, Vector2 collisionPt, bool isPlayer) + { + ChasePlayer(); + base.HitEnemy(damage, collisionPt, isPlayer); + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + if (otherBox.AbsParent is PlayerObj) + ChasePlayer(); + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + public void ChasePlayer() + { + if (Chasing == false) + { + if (m_currentActiveLB != null) + m_currentActiveLB.StopLogicBlock(); + + Chasing = true; + if (m_target.X < this.X) + this.Orientation = 0; + else + this.Orientation = MathHelper.ToRadians(180); + } + } + + public override void Reset() + { + Chasing = false; + base.Reset(); + } + + public EnemyObj_Portrait(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyPortrait_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.Portrait; + // Creating the picture frame for the enemy. + string framePicture = "FramePicture" + CDGMath.RandomInt(1,16) + "_Sprite"; + this.GetChildAt(0).ChangeSprite(framePicture); + PhysicsObj frame = this.GetChildAt(0) as PhysicsObj; + this.DisableCollisionBoxRotations = false; + } + + public void ChangePortrait() + { + SoundManager.PlaySound("FinalBoss_St2_BlockLaugh"); + SpriteObj portrait = this.GetChildAt(0) as SpriteObj; + portrait.ChangeSprite("EnemyPortrait" + (int)this.Difficulty + "_Sprite"); + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + this.GetChildAt(1).Visible = false; + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_ShieldKnight.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_ShieldKnight.cs new file mode 100644 index 0000000..2c4e027 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_ShieldKnight.cs @@ -0,0 +1,454 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class EnemyObj_ShieldKnight : EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + + private Vector2 ShieldKnockback = new Vector2(900, 1050); + private float m_blockDmgReduction = 0.6f;//0.8f;//0.9f; + private FrameSoundObj m_walkSound, m_walkSound2; + + protected override void InitializeEV() + { + LockFlip = true; + + #region Basic Variables - General + Name = EnemyEV.ShieldKnight_Basic_Name; + LocStringID = EnemyEV.ShieldKnight_Basic_Name_locID; + + MaxHealth = EnemyEV.ShieldKnight_Basic_MaxHealth; + Damage = EnemyEV.ShieldKnight_Basic_Damage; + XPValue = EnemyEV.ShieldKnight_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.ShieldKnight_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.ShieldKnight_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.ShieldKnight_Basic_DropChance; + + Speed = EnemyEV.ShieldKnight_Basic_Speed; + TurnSpeed = EnemyEV.ShieldKnight_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.ShieldKnight_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.ShieldKnight_Basic_Jump; + CooldownTime = EnemyEV.ShieldKnight_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.ShieldKnight_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.ShieldKnight_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.ShieldKnight_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.ShieldKnight_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.ShieldKnight_Basic_IsWeighted; + + Scale = EnemyEV.ShieldKnight_Basic_Scale; + ProjectileScale = EnemyEV.ShieldKnight_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.ShieldKnight_Basic_Tint; + + MeleeRadius = EnemyEV.ShieldKnight_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.ShieldKnight_Basic_ProjectileRadius; + EngageRadius = EnemyEV.ShieldKnight_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.ShieldKnight_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + ShieldKnockback = new Vector2(1200, 1350); + + #region Miniboss Variables - General + Name = EnemyEV.ShieldKnight_Miniboss_Name; + LocStringID = EnemyEV.ShieldKnight_Miniboss_Name_locID; + + MaxHealth = EnemyEV.ShieldKnight_Miniboss_MaxHealth; + Damage = EnemyEV.ShieldKnight_Miniboss_Damage; + XPValue = EnemyEV.ShieldKnight_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.ShieldKnight_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.ShieldKnight_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.ShieldKnight_Miniboss_DropChance; + + Speed = EnemyEV.ShieldKnight_Miniboss_Speed; + TurnSpeed = EnemyEV.ShieldKnight_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.ShieldKnight_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.ShieldKnight_Miniboss_Jump; + CooldownTime = EnemyEV.ShieldKnight_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.ShieldKnight_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.ShieldKnight_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.ShieldKnight_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.ShieldKnight_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.ShieldKnight_Miniboss_IsWeighted; + + Scale = EnemyEV.ShieldKnight_Miniboss_Scale; + ProjectileScale = EnemyEV.ShieldKnight_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.ShieldKnight_Miniboss_Tint; + + MeleeRadius = EnemyEV.ShieldKnight_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.ShieldKnight_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.ShieldKnight_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.ShieldKnight_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + ShieldKnockback = new Vector2(1550, 1650); + + #region Expert Variables - General + Name = EnemyEV.ShieldKnight_Expert_Name; + LocStringID = EnemyEV.ShieldKnight_Expert_Name_locID; + + MaxHealth = EnemyEV.ShieldKnight_Expert_MaxHealth; + Damage = EnemyEV.ShieldKnight_Expert_Damage; + XPValue = EnemyEV.ShieldKnight_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.ShieldKnight_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.ShieldKnight_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.ShieldKnight_Expert_DropChance; + + Speed = EnemyEV.ShieldKnight_Expert_Speed; + TurnSpeed = EnemyEV.ShieldKnight_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.ShieldKnight_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.ShieldKnight_Expert_Jump; + CooldownTime = EnemyEV.ShieldKnight_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.ShieldKnight_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.ShieldKnight_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.ShieldKnight_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.ShieldKnight_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.ShieldKnight_Expert_IsWeighted; + + Scale = EnemyEV.ShieldKnight_Expert_Scale; + ProjectileScale = EnemyEV.ShieldKnight_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.ShieldKnight_Expert_Tint; + + MeleeRadius = EnemyEV.ShieldKnight_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.ShieldKnight_Expert_ProjectileRadius; + EngageRadius = EnemyEV.ShieldKnight_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.ShieldKnight_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + ShieldKnockback = new Vector2(1050, 1150); + + #region Advanced Variables - General + Name = EnemyEV.ShieldKnight_Advanced_Name; + LocStringID = EnemyEV.ShieldKnight_Advanced_Name_locID; + + MaxHealth = EnemyEV.ShieldKnight_Advanced_MaxHealth; + Damage = EnemyEV.ShieldKnight_Advanced_Damage; + XPValue = EnemyEV.ShieldKnight_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.ShieldKnight_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.ShieldKnight_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.ShieldKnight_Advanced_DropChance; + + Speed = EnemyEV.ShieldKnight_Advanced_Speed; + TurnSpeed = EnemyEV.ShieldKnight_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.ShieldKnight_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.ShieldKnight_Advanced_Jump; + CooldownTime = EnemyEV.ShieldKnight_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.ShieldKnight_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.ShieldKnight_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.ShieldKnight_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.ShieldKnight_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.ShieldKnight_Advanced_IsWeighted; + + Scale = EnemyEV.ShieldKnight_Advanced_Scale; + ProjectileScale = EnemyEV.ShieldKnight_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.ShieldKnight_Advanced_Tint; + + MeleeRadius = EnemyEV.ShieldKnight_Advanced_MeleeRadius; + EngageRadius = EnemyEV.ShieldKnight_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.ShieldKnight_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.ShieldKnight_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + + } + + protected override void InitializeLogic() + { + LogicSet walkStopLS = new LogicSet(this); //Face direction locked, so this only makes him stop moving. + walkStopLS.AddAction(new LockFaceDirectionLogicAction(true)); + walkStopLS.AddAction(new ChangeSpriteLogicAction("EnemyShieldKnightIdle_Character", true, true)); + //walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new MoveDirectionLogicAction(0)); + walkStopLS.AddAction(new DelayLogicAction(0.5f, 2.0f)); + + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new LockFaceDirectionLogicAction(true)); + walkTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemyShieldKnightWalk_Character", true, true)); + //walkTowardsLS.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsLS.AddAction(new MoveDirectionLogicAction()); + walkTowardsLS.AddAction(new DelayLogicAction(0.5f, 2.0f)); + + LogicSet turnLS = new LogicSet(this); + turnLS.AddAction(new LockFaceDirectionLogicAction(true)); + turnLS.AddAction(new MoveDirectionLogicAction(0)); + turnLS.AddAction(new ChangeSpriteLogicAction("EnemyShieldKnightTurnIn_Character", false, false)); + turnLS.AddAction(new PlayAnimationLogicAction(1, 2)); + turnLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"ShieldKnight_Turn")); + turnLS.AddAction(new PlayAnimationLogicAction(3, this.TotalFrames)); + turnLS.AddAction(new LockFaceDirectionLogicAction(false)); + turnLS.AddAction(new MoveLogicAction(m_target, true, 0)); + turnLS.AddAction(new LockFaceDirectionLogicAction(true)); + turnLS.AddAction(new ChangeSpriteLogicAction("EnemyShieldKnightTurnOut_Character", true, false)); + turnLS.AddAction(new MoveDirectionLogicAction()); + + + LogicSet turnExpertLS = new LogicSet(this); + turnExpertLS.AddAction(new LockFaceDirectionLogicAction(true)); + turnExpertLS.AddAction(new MoveDirectionLogicAction(0)); + turnExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyShieldKnightTurnIn_Character", false, false)); + turnExpertLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 20f)); + turnExpertLS.AddAction(new PlayAnimationLogicAction(1, 2)); + turnExpertLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "ShieldKnight_Turn")); + turnExpertLS.AddAction(new PlayAnimationLogicAction(3, this.TotalFrames)); + turnExpertLS.AddAction(new LockFaceDirectionLogicAction(false)); + turnExpertLS.AddAction(new MoveLogicAction(m_target, true, 0)); + turnExpertLS.AddAction(new LockFaceDirectionLogicAction(true)); + turnExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyShieldKnightTurnOut_Character", true, false)); + turnExpertLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / EnemyEV.ShieldKnight_Expert_AnimationDelay)); + turnExpertLS.AddAction(new MoveDirectionLogicAction()); + + m_generalBasicLB.AddLogicSet(walkStopLS, walkTowardsLS, turnLS); + m_generalExpertLB.AddLogicSet(walkStopLS, walkTowardsLS, turnExpertLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalExpertLB); + + SetCooldownLogicBlock(m_generalBasicLB, 100); + + base.InitializeLogic(); + + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + if ((m_target.X > this.X && this.HeadingX < 0) || (m_target.X < this.X && this.HeadingX >= 0)) + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100); // walkStopLS, walkTowardsLS, turnLS + else + RunLogicBlock(true, m_generalBasicLB, 0, 100, 0); // walkStopLS, walkTowardsLS, turnLS + break; + case (STATE_WANDER): + if ((m_target.X > this.X && this.HeadingX < 0) || (m_target.X < this.X && this.HeadingX >= 0)) + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100); // walkStopLS, walkTowardsLS, turnLS + else + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0); // walkStopLS, walkTowardsLS, turnLS + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + if ((m_target.X > this.X && this.HeadingX < 0) || (m_target.X < this.X && this.HeadingX >= 0)) + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100); // walkStopLS, walkTowardsLS, turnLS + else + RunLogicBlock(true, m_generalBasicLB, 0, 100, 0); // walkStopLS, walkTowardsLS, turnLS + break; + case (STATE_WANDER): + if ((m_target.X > this.X && this.HeadingX < 0) || (m_target.X < this.X && this.HeadingX >= 0)) + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100); // walkStopLS, walkTowardsLS, turnLS + else + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0); // walkStopLS, walkTowardsLS, turnLS + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + if ((m_target.X > this.X && this.HeadingX < 0) || (m_target.X < this.X && this.HeadingX >= 0)) + RunLogicBlock(true, m_generalExpertLB, 0, 0, 100); // walkStopLS, walkTowardsLS, turnLS + else + RunLogicBlock(true, m_generalExpertLB, 0, 100, 0); // walkStopLS, walkTowardsLS, turnLS + break; + case (STATE_WANDER): + if ((m_target.X > this.X && this.HeadingX < 0) || (m_target.X < this.X && this.HeadingX >= 0)) + RunLogicBlock(true, m_generalExpertLB, 0, 0, 100); // walkStopLS, walkTowardsLS, turnLS + else + RunLogicBlock(true, m_generalExpertLB, 100, 0, 0); // walkStopLS, walkTowardsLS, turnLS + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + if ((m_target.X > this.X && this.HeadingX < 0) || (m_target.X < this.X && this.HeadingX >= 0)) + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0); // walkStopLS, walkTowardsLS, turnLS + else + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0); // walkStopLS, walkTowardsLS, turnLS + break; + case (STATE_WANDER): + if ((m_target.X > this.X && this.HeadingX < 0) || (m_target.X < this.X && this.HeadingX >= 0)) + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0); // walkStopLS, walkTowardsLS, turnLS + else + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0); // walkStopLS, walkTowardsLS, turnLS + break; + default: + break; + } + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + PlayerObj player = otherBox.AbsParent as PlayerObj; + ProjectileObj proj = otherBox.AbsParent as ProjectileObj; + + //if ((collisionResponseType == Consts.COLLISIONRESPONSE_FIRSTBOXHIT) && ((otherBox.AbsParent is ProjectileObj == false && m_invincibleCounter <= 0) || (otherBox.AbsParent is ProjectileObj && m_invincibleCounterProjectile <= 0) && + // ((this.Flip == SpriteEffects.None && otherBox.AbsParent.AbsPosition.X > this.X) || (this.Flip == SpriteEffects.FlipHorizontally && otherBox.AbsParent.AbsPosition.X < this.X)) && (player != null && player.IsAirAttacking == false))) + + // Enemy blocked. + if (collisionResponseType == Consts.COLLISIONRESPONSE_FIRSTBOXHIT && + ((player != null && m_invincibleCounter <= 0) || (proj != null && m_invincibleCounterProjectile <= 0)) && + ((this.Flip == SpriteEffects.None && otherBox.AbsParent.AbsPosition.X > this.X) || (this.Flip == SpriteEffects.FlipHorizontally && otherBox.AbsParent.AbsPosition.X < this.X)) && + (player != null && player.SpriteName != "PlayerAirAttack_Character") //player.IsAirAttacking == false) + ) + { + if (CanBeKnockedBack == true) + { + CurrentSpeed = 0; + m_currentActiveLB.StopLogicBlock(); + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0); + //if (otherBox.AbsParent.Bounds.Left + otherBox.AbsParent.Bounds.Width / 2 > this.X) + // AccelerationX = -KnockBack.X; + //else + // AccelerationX = KnockBack.X; + //AccelerationY = -KnockBack.Y; + } + + + if (m_target.IsAirAttacking == true) + { + m_target.IsAirAttacking = false; // Only allow one object to perform upwards air knockback on the player. + m_target.AccelerationY = -m_target.AirAttackKnockBack; + m_target.NumAirBounces++; + } + else + { + if (m_target.Bounds.Left + m_target.Bounds.Width / 2 < this.X) + m_target.AccelerationX = -ShieldKnockback.X; + else + m_target.AccelerationX = ShieldKnockback.X; + m_target.AccelerationY = -ShieldKnockback.Y; + //if (m_target.Bounds.Left + m_target.Bounds.Width / 2 < this.X) + // m_target.AccelerationX = -m_target.EnemyKnockBack.X; + //else + // m_target.AccelerationX = m_target.EnemyKnockBack.X; + //m_target.AccelerationY = -m_target.EnemyKnockBack.Y; + } + + // This must be called before the invincible counter is set. + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + + Point intersectPt = Rectangle.Intersect(thisBox.AbsRect, otherBox.AbsRect).Center; + Vector2 impactPosition = new Vector2(intersectPt.X, intersectPt.Y); + m_levelScreen.ImpactEffectPool.DisplayBlockImpactEffect(impactPosition, new Vector2(2,2)); + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"ShieldKnight_Block01", "ShieldKnight_Block02", "ShieldKnight_Block03"); + m_invincibleCounter = InvincibilityTime; + m_levelScreen.SetLastEnemyHit(this); + Blink(Color.LightBlue, 0.1f); + + ProjectileObj projectile = otherBox.AbsParent as ProjectileObj; + if (projectile != null) + { + m_invincibleCounterProjectile = InvincibilityTime; + m_levelScreen.ProjectileManager.DestroyProjectile(projectile); + } + } + else + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + public override void HitEnemy(int damage, Vector2 position, bool isPlayer) + { + if (m_target != null && m_target.CurrentHealth > 0) + { + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "Knight_Hit01", "Knight_Hit02", "Knight_Hit03"); + if ((this.Flip == SpriteEffects.None && m_target.X > this.X) || (this.Flip == SpriteEffects.FlipHorizontally && m_target.X < this.X)) + { + // Air attacks and all other damage other than sword swipes should deal their full damage. + if (m_target.SpriteName != "PlayerAirAttack_Character") + damage = (int)(damage * (1 - m_blockDmgReduction)); + } + } + base.HitEnemy(damage, position, isPlayer); + } + + public override void Update(GameTime gameTime) + { + if (this.SpriteName == "EnemyShieldKnightWalk_Character") + { + m_walkSound.Update(); + m_walkSound2.Update(); + } + base.Update(gameTime); + } + + public EnemyObj_ShieldKnight(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyShieldKnightIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.ShieldKnight; + m_walkSound = new FrameSoundObj(this, m_target, 1, "KnightWalk1", "KnightWalk2"); + m_walkSound2 = new FrameSoundObj(this, m_target, 6, "KnightWalk1", "KnightWalk2"); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + m_walkSound.Dispose(); + m_walkSound = null; + m_walkSound2.Dispose(); + m_walkSound2 = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Skeleton.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Skeleton.cs new file mode 100644 index 0000000..841cc3c --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Skeleton.cs @@ -0,0 +1,500 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_Skeleton : EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + + private float AttackDelay = 0.1f; + private float JumpDelay = 0.25f; + + protected override void InitializeEV() + { + #region Basic Variables - General + Name = EnemyEV.Skeleton_Basic_Name; + LocStringID = EnemyEV.Skeleton_Basic_Name_locID; + + MaxHealth = EnemyEV.Skeleton_Basic_MaxHealth; + Damage = EnemyEV.Skeleton_Basic_Damage; + XPValue = EnemyEV.Skeleton_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Skeleton_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Skeleton_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Skeleton_Basic_DropChance; + + Speed = EnemyEV.Skeleton_Basic_Speed; + TurnSpeed = EnemyEV.Skeleton_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Skeleton_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Skeleton_Basic_Jump; + CooldownTime = EnemyEV.Skeleton_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Skeleton_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Skeleton_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Skeleton_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Skeleton_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Skeleton_Basic_IsWeighted; + + Scale = EnemyEV.Skeleton_Basic_Scale; + ProjectileScale = EnemyEV.Skeleton_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Skeleton_Basic_Tint; + + MeleeRadius = EnemyEV.Skeleton_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Skeleton_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Skeleton_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Skeleton_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Skeleton_Miniboss_Name; + LocStringID = EnemyEV.Skeleton_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Skeleton_Miniboss_MaxHealth; + Damage = EnemyEV.Skeleton_Miniboss_Damage; + XPValue = EnemyEV.Skeleton_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Skeleton_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Skeleton_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Skeleton_Miniboss_DropChance; + + Speed = EnemyEV.Skeleton_Miniboss_Speed; + TurnSpeed = EnemyEV.Skeleton_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Skeleton_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Skeleton_Miniboss_Jump; + CooldownTime = EnemyEV.Skeleton_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Skeleton_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Skeleton_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Skeleton_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Skeleton_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Skeleton_Miniboss_IsWeighted; + + Scale = EnemyEV.Skeleton_Miniboss_Scale; + ProjectileScale = EnemyEV.Skeleton_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Skeleton_Miniboss_Tint; + + MeleeRadius = EnemyEV.Skeleton_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Skeleton_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Skeleton_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Skeleton_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.Skeleton_Expert_Name; + LocStringID = EnemyEV.Skeleton_Expert_Name_locID; + + MaxHealth = EnemyEV.Skeleton_Expert_MaxHealth; + Damage = EnemyEV.Skeleton_Expert_Damage; + XPValue = EnemyEV.Skeleton_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Skeleton_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Skeleton_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Skeleton_Expert_DropChance; + + Speed = EnemyEV.Skeleton_Expert_Speed; + TurnSpeed = EnemyEV.Skeleton_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Skeleton_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Skeleton_Expert_Jump; + CooldownTime = EnemyEV.Skeleton_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Skeleton_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Skeleton_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Skeleton_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Skeleton_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Skeleton_Expert_IsWeighted; + + Scale = EnemyEV.Skeleton_Expert_Scale; + ProjectileScale = EnemyEV.Skeleton_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Skeleton_Expert_Tint; + + MeleeRadius = EnemyEV.Skeleton_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Skeleton_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Skeleton_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Skeleton_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.Skeleton_Advanced_Name; + LocStringID = EnemyEV.Skeleton_Advanced_Name_locID; + + MaxHealth = EnemyEV.Skeleton_Advanced_MaxHealth; + Damage = EnemyEV.Skeleton_Advanced_Damage; + XPValue = EnemyEV.Skeleton_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Skeleton_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Skeleton_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Skeleton_Advanced_DropChance; + + Speed = EnemyEV.Skeleton_Advanced_Speed; + TurnSpeed = EnemyEV.Skeleton_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Skeleton_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Skeleton_Advanced_Jump; + CooldownTime = EnemyEV.Skeleton_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Skeleton_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Skeleton_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Skeleton_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Skeleton_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Skeleton_Advanced_IsWeighted; + + Scale = EnemyEV.Skeleton_Advanced_Scale; + ProjectileScale = EnemyEV.Skeleton_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Skeleton_Advanced_Tint; + + MeleeRadius = EnemyEV.Skeleton_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Skeleton_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Skeleton_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Skeleton_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + + } + + protected override void InitializeLogic() + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "BoneProjectile_Sprite", + SourceAnchor = new Vector2(20, -20), + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = true, + RotationSpeed = 10, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(-72, -72), + CollidesWithTerrain = false, + Scale = ProjectileScale, + }; + + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonWalk_Character", true, true)); + walkTowardsLS.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsLS.AddAction(new DelayLogicAction(0.2f, 0.75f)); + + LogicSet walkAwayLS = new LogicSet(this); + walkAwayLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonWalk_Character", true, true)); + walkAwayLS.AddAction(new MoveLogicAction(m_target, false)); + walkAwayLS.AddAction(new DelayLogicAction(0.2f, 0.75f)); + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonIdle_Character", true, true)); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(0.2f, 0.75f)); + + + LogicSet walkStopMiniBossLS = new LogicSet(this); + walkStopMiniBossLS.AddAction(new StopAnimationLogicAction()); + walkStopMiniBossLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopMiniBossLS.AddAction(new DelayLogicAction(0.5f, 1.0f)); + + LogicSet throwBoneFarLS = new LogicSet(this); + throwBoneFarLS.AddAction(new MoveLogicAction(m_target, true, 0)); + throwBoneFarLS.AddAction(new LockFaceDirectionLogicAction(true)); + throwBoneFarLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonAttack_Character", false, false)); + throwBoneFarLS.AddAction(new PlayAnimationLogicAction("Start", "Windup")); + throwBoneFarLS.AddAction(new DelayLogicAction(AttackDelay)); + throwBoneFarLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SkeletonHit1")); + throwBoneFarLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + throwBoneFarLS.AddAction(new PlayAnimationLogicAction("Attack", "End")); + throwBoneFarLS.AddAction(new DelayLogicAction(0.2f, 0.4f)); + throwBoneFarLS.AddAction(new LockFaceDirectionLogicAction(false)); + throwBoneFarLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet throwBoneHighLS = new LogicSet(this); + throwBoneHighLS.AddAction(new MoveLogicAction(m_target, true, 0)); + throwBoneHighLS.AddAction(new LockFaceDirectionLogicAction(true)); + throwBoneHighLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonAttack_Character", false, false)); + throwBoneHighLS.AddAction(new PlayAnimationLogicAction("Start", "Windup")); + throwBoneHighLS.AddAction(new DelayLogicAction(AttackDelay)); + throwBoneHighLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SkeletonHit1")); + projData.Angle = new Vector2(-85, -85); + throwBoneHighLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + throwBoneHighLS.AddAction(new PlayAnimationLogicAction("Attack", "End")); + throwBoneHighLS.AddAction(new DelayLogicAction(0.2f, 0.4f)); + throwBoneHighLS.AddAction(new LockFaceDirectionLogicAction(false)); + throwBoneHighLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet jumpBoneFarLS = new LogicSet(this); + jumpBoneFarLS.AddAction(new MoveLogicAction(m_target, true, 0)); + jumpBoneFarLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonJump_Character", false, false)); + jumpBoneFarLS.AddAction(new PlayAnimationLogicAction(1, 3, false)); + jumpBoneFarLS.AddAction(new DelayLogicAction(JumpDelay)); + jumpBoneFarLS.AddAction(new JumpLogicAction()); + jumpBoneFarLS.AddAction(new LockFaceDirectionLogicAction(true)); + jumpBoneFarLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonAttack_Character", false, false)); + jumpBoneFarLS.AddAction(new PlayAnimationLogicAction("Start", "Windup")); + jumpBoneFarLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SkeletonHit1")); + projData.Angle = new Vector2(-72, -72); + jumpBoneFarLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + jumpBoneFarLS.AddAction(new PlayAnimationLogicAction("Attack", "End")); + jumpBoneFarLS.AddAction(new DelayLogicAction(0.2f, 0.4f)); + jumpBoneFarLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpBoneFarLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet jumpBoneHighLS = new LogicSet(this); + jumpBoneHighLS.AddAction(new MoveLogicAction(m_target, true, 0)); + jumpBoneHighLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonJump_Character", false, false)); + jumpBoneHighLS.AddAction(new PlayAnimationLogicAction(1, 3, false)); + jumpBoneHighLS.AddAction(new DelayLogicAction(JumpDelay)); + jumpBoneHighLS.AddAction(new JumpLogicAction()); + jumpBoneHighLS.AddAction(new LockFaceDirectionLogicAction(true)); + jumpBoneHighLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonAttack_Character", false, false)); + jumpBoneHighLS.AddAction(new PlayAnimationLogicAction("Start", "Windup")); + jumpBoneHighLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SkeletonHit1")); + projData.Angle = new Vector2(-85, -85); + jumpBoneHighLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + jumpBoneHighLS.AddAction(new PlayAnimationLogicAction("Attack", "End")); + jumpBoneHighLS.AddAction(new DelayLogicAction(0.2f, 0.4f)); + jumpBoneHighLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpBoneHighLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet throwBoneExpertLS = new LogicSet(this); + throwBoneExpertLS.AddAction(new MoveLogicAction(m_target, true, 0)); + throwBoneExpertLS.AddAction(new LockFaceDirectionLogicAction(true)); + throwBoneExpertLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonAttack_Character", false, false)); + throwBoneExpertLS.AddAction(new PlayAnimationLogicAction("Start", "Windup")); + throwBoneExpertLS.AddAction(new DelayLogicAction(AttackDelay)); + throwBoneExpertLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SkeletonHit1")); + ThrowThreeProjectiles(throwBoneExpertLS); + throwBoneExpertLS.AddAction(new PlayAnimationLogicAction("Attack", "End"), Types.Sequence.Parallel); + throwBoneExpertLS.AddAction(new DelayLogicAction(0.15f)); + ThrowThreeProjectiles(throwBoneExpertLS); + throwBoneExpertLS.AddAction(new DelayLogicAction(0.15f)); + ThrowThreeProjectiles(throwBoneExpertLS); + throwBoneExpertLS.AddAction(new DelayLogicAction(0.2f, 0.4f)); + throwBoneExpertLS.AddAction(new LockFaceDirectionLogicAction(false)); + throwBoneExpertLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet jumpBoneExpertLS = new LogicSet(this); + jumpBoneExpertLS.AddAction(new MoveLogicAction(m_target, true, 0)); + jumpBoneExpertLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonJump_Character", false, false)); + jumpBoneExpertLS.AddAction(new PlayAnimationLogicAction(1, 3, false)); + jumpBoneExpertLS.AddAction(new DelayLogicAction(JumpDelay)); + jumpBoneExpertLS.AddAction(new JumpLogicAction()); + jumpBoneExpertLS.AddAction(new LockFaceDirectionLogicAction(true)); + jumpBoneExpertLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonAttack_Character", false, false)); + jumpBoneExpertLS.AddAction(new PlayAnimationLogicAction("Start", "Windup")); + jumpBoneExpertLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SkeletonHit1")); + ThrowThreeProjectiles(jumpBoneExpertLS); + jumpBoneExpertLS.AddAction(new PlayAnimationLogicAction("Attack", "End"), Types.Sequence.Parallel); + jumpBoneExpertLS.AddAction(new DelayLogicAction(0.15f)); + ThrowThreeProjectiles(jumpBoneExpertLS); + jumpBoneExpertLS.AddAction(new DelayLogicAction(0.15f)); + ThrowThreeProjectiles(jumpBoneExpertLS); + jumpBoneExpertLS.AddAction(new DelayLogicAction(0.2f, 0.4f)); + jumpBoneExpertLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpBoneExpertLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet throwBoneMiniBossLS = new LogicSet(this); + throwBoneMiniBossLS.AddAction(new MoveLogicAction(m_target, true, 0)); + throwBoneMiniBossLS.AddAction(new LockFaceDirectionLogicAction(true)); + throwBoneMiniBossLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonAttack_Character", false, false)); + throwBoneMiniBossLS.AddAction(new PlayAnimationLogicAction("Start", "Windup")); + throwBoneMiniBossLS.AddAction(new DelayLogicAction(AttackDelay)); + projData.Angle = new Vector2(-89, -35); + projData.RotationSpeed = 8; + projData.SourceAnchor = new Vector2(5, -20); + throwBoneMiniBossLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SkeletonHit1")); + throwBoneMiniBossLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + throwBoneMiniBossLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + throwBoneMiniBossLS.AddAction(new PlayAnimationLogicAction("Attack", "End")); + throwBoneMiniBossLS.AddAction(new LockFaceDirectionLogicAction(false)); + throwBoneMiniBossLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonIdle_Character", true, true)); + throwBoneMiniBossLS.AddAction(new DelayLogicAction(0.40f, 0.90f)); + + + LogicSet throwBoneMiniBossRageLS = new LogicSet(this); + throwBoneMiniBossRageLS.AddAction(new MoveLogicAction(m_target, true, 0)); + throwBoneMiniBossRageLS.AddAction(new LockFaceDirectionLogicAction(true)); + throwBoneMiniBossRageLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonAttack_Character", false, false)); + throwBoneMiniBossRageLS.AddAction(new PlayAnimationLogicAction("Start", "Windup")); + throwBoneMiniBossRageLS.AddAction(new DelayLogicAction(AttackDelay)); + throwBoneMiniBossRageLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SkeletonHit1")); + throwBoneMiniBossRageLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + throwBoneMiniBossRageLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + throwBoneMiniBossRageLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + throwBoneMiniBossRageLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + throwBoneMiniBossRageLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + throwBoneMiniBossRageLS.AddAction(new PlayAnimationLogicAction("Attack", "End")); + throwBoneMiniBossRageLS.AddAction(new LockFaceDirectionLogicAction(false)); + throwBoneMiniBossRageLS.AddAction(new DelayLogicAction(0.15f, 0.35f)); + throwBoneMiniBossRageLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonIdle_Character", true, true)); + + m_generalBasicLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, throwBoneFarLS, throwBoneHighLS); + m_generalAdvancedLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, throwBoneFarLS, throwBoneHighLS, jumpBoneFarLS, jumpBoneHighLS); + m_generalExpertLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, throwBoneExpertLS, jumpBoneExpertLS); + m_generalMiniBossLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopMiniBossLS, throwBoneMiniBossLS, throwBoneMiniBossRageLS); + m_generalCooldownLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalMiniBossLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + + SetCooldownLogicBlock(m_generalCooldownLB, 30, 30, 40); //walkTowardsLS, walkAwayLS, walkStopLS + + projData.Dispose(); + + base.InitializeLogic(); + } + + private void ThrowThreeProjectiles(LogicSet ls) + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "BoneProjectile_Sprite", + SourceAnchor = new Vector2(20, -20), + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = true, + RotationSpeed = 10, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(-72, -72), + CollidesWithTerrain = false, + Scale = ProjectileScale, + }; + + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Speed = new Vector2(ProjectileSpeed - 350, ProjectileSpeed - 350); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Speed = new Vector2(ProjectileSpeed + 350, ProjectileSpeed + 350); + ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + //ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "BoneProjectile_Sprite", new Vector2(20, -20), -72, ProjectileSpeed, true, 10, Damage)); + //ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "BoneProjectile_Sprite", new Vector2(20, -20), -72, ProjectileSpeed - 350, true, 10, Damage)); + //ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "BoneProjectile_Sprite", new Vector2(20, -20), -72, ProjectileSpeed + 350, true, 10, Damage)); + //ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "BoneProjectile_Sprite", new Vector2(20, -18), -60, 10, true, 10, Damage)); + //ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "BoneProjectile_Sprite", new Vector2(20, -18), -60, 16, true, 10, Damage)); + //ls.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "BoneProjectile_Sprite", new Vector2(20, -18), -60, 22, true, 10, Damage)); + + projData.Dispose(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 10, 10, 0, 30, 50); //walkTowardsLS, walkAwayLS, walkStopLS, throwBoneFarLS, throwBoneHighLS + break; + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 10, 10, 0, 40, 40); //walkTowardsLS, walkAwayLS, walkStopLS, throwBoneFarLS, throwBoneHighLS + break; + case (STATE_ENGAGE): + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 40, 40, 20, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, throwBoneFarLS, throwBoneHighLS + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 10, 10, 0, 15, 15, 25, 25); //walkTowardsLS, walkAwayLS, walkStopLS, throwBoneFarLS, throwBoneHighLS, jumpBoneFarLS, jumpBoneHighLS + break; + case (STATE_ENGAGE): + case (STATE_WANDER): + RunLogicBlock(true, m_generalAdvancedLB, 40, 40, 20, 0, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, throwBoneFarLS, throwBoneHighLS, jumpBoneFarLS, jumpBoneHighLS + break; + default: + RunBasicLogic(); + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 15, 15, 0, 35, 35); //walkTowardsLS, walkAwayLS, walkStopLS, throwBoneExpertLS, jumpBoneExpertLS + break; + case (STATE_ENGAGE): + case (STATE_WANDER): + RunLogicBlock(true, m_generalExpertLB, 35, 35, 0, 0, 15); //walkTowardsLS, walkAwayLS, walkStopLS, throwBoneExpertLS, jumpBoneExpertLS + break; + default: + RunBasicLogic(); + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + if (m_levelScreen.CurrentRoom.ActiveEnemies > 1) + RunLogicBlock(true, m_generalMiniBossLB, 0, 0, 10, 90, 0); //walkTowardsLS, walkAwayLS, walkStopMiniBossLS, throwBoneMiniBossLS, throwBoneMiniBossRageLS + else + { + Console.WriteLine("RAGING"); + RunLogicBlock(true, m_generalMiniBossLB, 0, 0, 10, 0, 90); //walkTowardsLS, walkAwayLS, walkStopMiniBossLS, throwBoneMiniBossLS, throwBoneMiniBossRageLS + } + break; + } + } + + public override void Update(GameTime gameTime) + { + if (this.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS && m_levelScreen.CurrentRoom.ActiveEnemies == 1) + this.TintablePart.TextureColor = new Color(185, 0, 15); + + base.Update(gameTime); + } + + public EnemyObj_Skeleton(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemySkeletonIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.Skeleton; + } + + public override void HitEnemy(int damage, Vector2 position, bool isPlayer) + { + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"SkeletonAttack1"); + base.HitEnemy(damage, position, isPlayer); + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_SkeletonArcher.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_SkeletonArcher.cs new file mode 100644 index 0000000..6b5f8a2 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_SkeletonArcher.cs @@ -0,0 +1,524 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_SkeletonArcher : EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + + private float m_fireDelay = 0.5f; + + protected override void InitializeEV() + { + LockFlip = false; // true; + this.IsWeighted = true; + IsCollidable = true; + + #region Basic Variables - General + Name = EnemyEV.SkeletonArcher_Basic_Name; + LocStringID = EnemyEV.SkeletonArcher_Basic_Name_locID; + + MaxHealth = EnemyEV.SkeletonArcher_Basic_MaxHealth; + Damage = EnemyEV.SkeletonArcher_Basic_Damage; + XPValue = EnemyEV.SkeletonArcher_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.SkeletonArcher_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.SkeletonArcher_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.SkeletonArcher_Basic_DropChance; + + Speed = EnemyEV.SkeletonArcher_Basic_Speed; + TurnSpeed = EnemyEV.SkeletonArcher_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.SkeletonArcher_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.SkeletonArcher_Basic_Jump; + CooldownTime = EnemyEV.SkeletonArcher_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.SkeletonArcher_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.SkeletonArcher_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.SkeletonArcher_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.SkeletonArcher_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.SkeletonArcher_Basic_IsWeighted; + + Scale = EnemyEV.SkeletonArcher_Basic_Scale; + ProjectileScale = EnemyEV.SkeletonArcher_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.SkeletonArcher_Basic_Tint; + + MeleeRadius = EnemyEV.SkeletonArcher_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.SkeletonArcher_Basic_ProjectileRadius; + EngageRadius = EnemyEV.SkeletonArcher_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.SkeletonArcher_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.SkeletonArcher_Miniboss_Name; + LocStringID = EnemyEV.SkeletonArcher_Miniboss_Name_locID; + + MaxHealth = EnemyEV.SkeletonArcher_Miniboss_MaxHealth; + Damage = EnemyEV.SkeletonArcher_Miniboss_Damage; + XPValue = EnemyEV.SkeletonArcher_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.SkeletonArcher_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.SkeletonArcher_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.SkeletonArcher_Miniboss_DropChance; + + Speed = EnemyEV.SkeletonArcher_Miniboss_Speed; + TurnSpeed = EnemyEV.SkeletonArcher_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.SkeletonArcher_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.SkeletonArcher_Miniboss_Jump; + CooldownTime = EnemyEV.SkeletonArcher_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.SkeletonArcher_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.SkeletonArcher_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.SkeletonArcher_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.SkeletonArcher_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.SkeletonArcher_Miniboss_IsWeighted; + + Scale = EnemyEV.SkeletonArcher_Miniboss_Scale; + ProjectileScale = EnemyEV.SkeletonArcher_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.SkeletonArcher_Miniboss_Tint; + + MeleeRadius = EnemyEV.SkeletonArcher_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.SkeletonArcher_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.SkeletonArcher_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.SkeletonArcher_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.SkeletonArcher_Expert_Name; + LocStringID = EnemyEV.SkeletonArcher_Expert_Name_locID; + + MaxHealth = EnemyEV.SkeletonArcher_Expert_MaxHealth; + Damage = EnemyEV.SkeletonArcher_Expert_Damage; + XPValue = EnemyEV.SkeletonArcher_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.SkeletonArcher_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.SkeletonArcher_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.SkeletonArcher_Expert_DropChance; + + Speed = EnemyEV.SkeletonArcher_Expert_Speed; + TurnSpeed = EnemyEV.SkeletonArcher_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.SkeletonArcher_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.SkeletonArcher_Expert_Jump; + CooldownTime = EnemyEV.SkeletonArcher_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.SkeletonArcher_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.SkeletonArcher_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.SkeletonArcher_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.SkeletonArcher_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.SkeletonArcher_Expert_IsWeighted; + + Scale = EnemyEV.SkeletonArcher_Expert_Scale; + ProjectileScale = EnemyEV.SkeletonArcher_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.SkeletonArcher_Expert_Tint; + + MeleeRadius = EnemyEV.SkeletonArcher_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.SkeletonArcher_Expert_ProjectileRadius; + EngageRadius = EnemyEV.SkeletonArcher_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.SkeletonArcher_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.SkeletonArcher_Advanced_Name; + LocStringID = EnemyEV.SkeletonArcher_Advanced_Name_locID; + + MaxHealth = EnemyEV.SkeletonArcher_Advanced_MaxHealth; + Damage = EnemyEV.SkeletonArcher_Advanced_Damage; + XPValue = EnemyEV.SkeletonArcher_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.SkeletonArcher_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.SkeletonArcher_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.SkeletonArcher_Advanced_DropChance; + + Speed = EnemyEV.SkeletonArcher_Advanced_Speed; + TurnSpeed = EnemyEV.SkeletonArcher_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.SkeletonArcher_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.SkeletonArcher_Advanced_Jump; + CooldownTime = EnemyEV.SkeletonArcher_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.SkeletonArcher_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.SkeletonArcher_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.SkeletonArcher_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.SkeletonArcher_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.SkeletonArcher_Advanced_IsWeighted; + + Scale = EnemyEV.SkeletonArcher_Advanced_Scale; + ProjectileScale = EnemyEV.SkeletonArcher_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.SkeletonArcher_Advanced_Tint; + + MeleeRadius = EnemyEV.SkeletonArcher_Advanced_MeleeRadius; + EngageRadius = EnemyEV.SkeletonArcher_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.SkeletonArcher_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.SkeletonArcher_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + } + + protected override void InitializeLogic() + { + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new ChangeSpriteLogicAction("EnemySkeletonArcherIdle_Character", true, true)); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(0.2f, 0.75f)); + + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "ArrowProjectile_Sprite", + SourceAnchor = new Vector2(10,-20), + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = true, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = true, + Scale = ProjectileScale, + FollowArc = true, + }; + + #region FireStraightProjectile + + LogicSet fireStraightProjectile = new LogicSet(this); + fireStraightProjectile.AddAction(new ChangeSpriteLogicAction("EnemySkeletonArcherAttack_Character", false, false)); + projData.Angle = new Vector2(-20, -20); + fireStraightProjectile.AddAction(new RunFunctionLogicAction(this, "AngleArcher", projData.Angle.X)); + fireStraightProjectile.AddAction(new LockFaceDirectionLogicAction(true)); + fireStraightProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Load")); + fireStraightProjectile.AddAction(new PlayAnimationLogicAction("Start", "BeginAttack")); + fireStraightProjectile.AddAction(new DelayLogicAction(m_fireDelay)); + fireStraightProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireStraightProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Attack_01", "SkeletonArcher_Attack_02", "SkeletonArcher_Attack_03")); + fireStraightProjectile.AddAction(new PlayAnimationLogicAction("Attack", "EndAttack")); + fireStraightProjectile.AddAction(new DelayLogicAction(0.5f)); + fireStraightProjectile.AddAction(new ChangePropertyLogicAction(this.GetChildAt(1), "Rotation", 0)); + fireStraightProjectile.AddAction(new DelayLogicAction(0.5f)); + fireStraightProjectile.AddAction(new LockFaceDirectionLogicAction(false)); + + LogicSet fireStraightAdvancedProjectile = new LogicSet(this); + fireStraightAdvancedProjectile.AddAction(new ChangeSpriteLogicAction("EnemySkeletonArcherAttack_Character", false, false)); + projData.Angle = new Vector2(-20, -20); + fireStraightAdvancedProjectile.AddAction(new RunFunctionLogicAction(this, "AngleArcher", projData.Angle.X)); + fireStraightAdvancedProjectile.AddAction(new LockFaceDirectionLogicAction(true)); + fireStraightAdvancedProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Load")); + fireStraightAdvancedProjectile.AddAction(new PlayAnimationLogicAction("Start", "BeginAttack")); + fireStraightAdvancedProjectile.AddAction(new DelayLogicAction(m_fireDelay)); + projData.Angle = new Vector2(-20, -20); + fireStraightAdvancedProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-50, -50); + fireStraightAdvancedProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireStraightAdvancedProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Attack_01", "SkeletonArcher_Attack_02", "SkeletonArcher_Attack_03")); + fireStraightAdvancedProjectile.AddAction(new PlayAnimationLogicAction("Attack", "EndAttack")); + fireStraightAdvancedProjectile.AddAction(new DelayLogicAction(0.5f)); + fireStraightAdvancedProjectile.AddAction(new ChangePropertyLogicAction(this.GetChildAt(1), "Rotation", 0)); + fireStraightAdvancedProjectile.AddAction(new DelayLogicAction(0.5f)); + fireStraightAdvancedProjectile.AddAction(new LockFaceDirectionLogicAction(false)); + + LogicSet fireStraightExpertProjectile = new LogicSet(this); + fireStraightExpertProjectile.AddAction(new ChangeSpriteLogicAction("EnemySkeletonArcherAttack_Character", false, false)); + projData.Angle = new Vector2(-35, -35); + fireStraightExpertProjectile.AddAction(new RunFunctionLogicAction(this, "AngleArcher", projData.Angle.X)); + fireStraightExpertProjectile.AddAction(new LockFaceDirectionLogicAction(true)); + fireStraightExpertProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Load")); + fireStraightExpertProjectile.AddAction(new PlayAnimationLogicAction("Start", "BeginAttack")); + fireStraightExpertProjectile.AddAction(new DelayLogicAction(m_fireDelay)); + projData.Angle = new Vector2(-35, -35); + fireStraightExpertProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-15, -15); + fireStraightExpertProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-55, -55); + fireStraightExpertProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireStraightExpertProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Attack_01", "SkeletonArcher_Attack_02", "SkeletonArcher_Attack_03")); + fireStraightExpertProjectile.AddAction(new PlayAnimationLogicAction("Attack", "EndAttack")); + fireStraightExpertProjectile.AddAction(new DelayLogicAction(0.5f)); + fireStraightExpertProjectile.AddAction(new ChangePropertyLogicAction(this.GetChildAt(1), "Rotation", 0)); + fireStraightExpertProjectile.AddAction(new DelayLogicAction(0.5f)); + fireStraightExpertProjectile.AddAction(new LockFaceDirectionLogicAction(false)); + #endregion + + #region FireArchProjectile + + LogicSet fireArchProjectile = new LogicSet(this); + fireArchProjectile.AddAction(new ChangeSpriteLogicAction("EnemySkeletonArcherAttack_Character", false, false)); + projData.Angle = new Vector2(-50, -50); + fireArchProjectile.AddAction(new RunFunctionLogicAction(this, "AngleArcher", projData.Angle.X)); + fireArchProjectile.AddAction(new LockFaceDirectionLogicAction(true)); + fireArchProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Load")); + fireArchProjectile.AddAction(new PlayAnimationLogicAction("Start", "BeginAttack")); + fireArchProjectile.AddAction(new DelayLogicAction(m_fireDelay)); + projData.Angle = new Vector2(-50, -50); + fireArchProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + //projData.Angle = new Vector2(-75, -75); + //fireArchProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + //projData.Angle = new Vector2(-35, -35); + //fireArchProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireArchProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Attack_01", "SkeletonArcher_Attack_02", "SkeletonArcher_Attack_03")); + fireArchProjectile.AddAction(new PlayAnimationLogicAction("Attack", "EndAttack")); + fireArchProjectile.AddAction(new DelayLogicAction(0.5f)); + fireArchProjectile.AddAction(new ChangePropertyLogicAction(this.GetChildAt(1), "Rotation", 0)); + fireArchProjectile.AddAction(new DelayLogicAction(0.5f)); + fireArchProjectile.AddAction(new LockFaceDirectionLogicAction(false)); + + LogicSet fireArchAdvancedProjectile = new LogicSet(this); + fireArchAdvancedProjectile.AddAction(new ChangeSpriteLogicAction("EnemySkeletonArcherAttack_Character", false, false)); + projData.Angle = new Vector2(-50, -50); + fireArchAdvancedProjectile.AddAction(new RunFunctionLogicAction(this, "AngleArcher", projData.Angle.X)); + fireArchAdvancedProjectile.AddAction(new LockFaceDirectionLogicAction(true)); + fireArchAdvancedProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Load")); + fireArchAdvancedProjectile.AddAction(new PlayAnimationLogicAction("Start", "BeginAttack")); + fireArchAdvancedProjectile.AddAction(new DelayLogicAction(m_fireDelay)); + projData.Angle = new Vector2(-50, -50); + fireArchAdvancedProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-75, -75); + fireArchAdvancedProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireArchAdvancedProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Attack_01", "SkeletonArcher_Attack_02", "SkeletonArcher_Attack_03")); + fireArchAdvancedProjectile.AddAction(new PlayAnimationLogicAction("Attack", "EndAttack")); + fireArchAdvancedProjectile.AddAction(new DelayLogicAction(0.5f)); + fireArchAdvancedProjectile.AddAction(new ChangePropertyLogicAction(this.GetChildAt(1), "Rotation", 0)); + fireArchAdvancedProjectile.AddAction(new DelayLogicAction(0.5f)); + fireArchAdvancedProjectile.AddAction(new LockFaceDirectionLogicAction(false)); + + LogicSet fireArchExpertProjectile = new LogicSet(this); + fireArchExpertProjectile.AddAction(new ChangeSpriteLogicAction("EnemySkeletonArcherAttack_Character", false, false)); + projData.Angle = new Vector2(-60, -60); + fireArchExpertProjectile.AddAction(new RunFunctionLogicAction(this, "AngleArcher", projData.Angle.X)); + fireArchExpertProjectile.AddAction(new LockFaceDirectionLogicAction(true)); + fireArchExpertProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Load")); + fireArchExpertProjectile.AddAction(new PlayAnimationLogicAction("Start", "BeginAttack")); + fireArchExpertProjectile.AddAction(new DelayLogicAction(m_fireDelay)); + projData.Angle = new Vector2(-60, -60); + fireArchExpertProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-75, -75); + fireArchExpertProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-45, -45); + fireArchExpertProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireArchExpertProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Attack_01", "SkeletonArcher_Attack_02", "SkeletonArcher_Attack_03")); + fireArchExpertProjectile.AddAction(new PlayAnimationLogicAction("Attack", "EndAttack")); + fireArchExpertProjectile.AddAction(new DelayLogicAction(0.5f)); + fireArchExpertProjectile.AddAction(new ChangePropertyLogicAction(this.GetChildAt(1), "Rotation", 0)); + fireArchExpertProjectile.AddAction(new DelayLogicAction(0.5f)); + fireArchExpertProjectile.AddAction(new LockFaceDirectionLogicAction(false)); + #endregion + + #region fireHighArchProjectile + LogicSet fireHighArchProjectile = new LogicSet(this); + fireHighArchProjectile.AddAction(new ChangeSpriteLogicAction("EnemySkeletonArcherAttack_Character", false, false)); + projData.Angle = new Vector2(-70, -70); + fireHighArchProjectile.AddAction(new RunFunctionLogicAction(this, "AngleArcher", projData.Angle.X)); + fireHighArchProjectile.AddAction(new LockFaceDirectionLogicAction(true)); + fireHighArchProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Load")); + fireHighArchProjectile.AddAction(new PlayAnimationLogicAction("Start", "BeginAttack")); + fireHighArchProjectile.AddAction(new DelayLogicAction(m_fireDelay)); + projData.Angle = new Vector2(-70, -70); + fireHighArchProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireHighArchProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Attack_01", "SkeletonArcher_Attack_02", "SkeletonArcher_Attack_03")); + fireHighArchProjectile.AddAction(new PlayAnimationLogicAction("Attack", "EndAttack")); + fireHighArchProjectile.AddAction(new DelayLogicAction(0.5f)); + fireHighArchProjectile.AddAction(new ChangePropertyLogicAction(this.GetChildAt(1), "Rotation", 0)); + fireHighArchProjectile.AddAction(new DelayLogicAction(0.5f)); + fireHighArchProjectile.AddAction(new LockFaceDirectionLogicAction(false)); + + LogicSet fireHighArchAdvancedProjectile = new LogicSet(this); + fireHighArchAdvancedProjectile.AddAction(new ChangeSpriteLogicAction("EnemySkeletonArcherAttack_Character", false, false)); + projData.Angle = new Vector2(-55, -55); + fireHighArchAdvancedProjectile.AddAction(new RunFunctionLogicAction(this, "AngleArcher", projData.Angle.X)); + fireHighArchAdvancedProjectile.AddAction(new LockFaceDirectionLogicAction(true)); + fireHighArchAdvancedProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Load")); + fireHighArchAdvancedProjectile.AddAction(new PlayAnimationLogicAction("Start", "BeginAttack")); + fireHighArchAdvancedProjectile.AddAction(new DelayLogicAction(m_fireDelay)); + projData.Angle = new Vector2(-55, -55); + fireHighArchAdvancedProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-85, -85); + fireHighArchAdvancedProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireHighArchAdvancedProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Attack_01", "SkeletonArcher_Attack_02", "SkeletonArcher_Attack_03")); + fireHighArchAdvancedProjectile.AddAction(new PlayAnimationLogicAction("Attack", "EndAttack")); + fireHighArchAdvancedProjectile.AddAction(new DelayLogicAction(0.5f)); + fireHighArchAdvancedProjectile.AddAction(new ChangePropertyLogicAction(this.GetChildAt(1), "Rotation", 0)); + fireHighArchAdvancedProjectile.AddAction(new DelayLogicAction(0.5f)); + fireHighArchAdvancedProjectile.AddAction(new LockFaceDirectionLogicAction(false)); + + LogicSet fireHighArchExpertProjectile = new LogicSet(this); + fireHighArchExpertProjectile.AddAction(new ChangeSpriteLogicAction("EnemySkeletonArcherAttack_Character", false, false)); + projData.Angle = new Vector2(-90, -90); + fireHighArchExpertProjectile.AddAction(new RunFunctionLogicAction(this, "AngleArcher", projData.Angle.X)); + fireHighArchExpertProjectile.AddAction(new LockFaceDirectionLogicAction(true)); + fireHighArchExpertProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Load")); + fireHighArchExpertProjectile.AddAction(new PlayAnimationLogicAction("Start", "BeginAttack")); + fireHighArchExpertProjectile.AddAction(new DelayLogicAction(m_fireDelay)); + + projData.Angle = new Vector2(-90, -90); + fireHighArchExpertProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-85, -85); + fireHighArchExpertProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-95, -95); + fireHighArchExpertProjectile.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireHighArchExpertProjectile.AddAction(new Play3DSoundLogicAction(this, m_target,"SkeletonArcher_Attack_01", "SkeletonArcher_Attack_02", "SkeletonArcher_Attack_03")); + fireHighArchExpertProjectile.AddAction(new PlayAnimationLogicAction("Attack", "EndAttack")); + fireHighArchExpertProjectile.AddAction(new DelayLogicAction(0.5f)); + fireHighArchExpertProjectile.AddAction(new ChangePropertyLogicAction(this.GetChildAt(1), "Rotation", 0)); + fireHighArchExpertProjectile.AddAction(new DelayLogicAction(0.5f)); + fireHighArchExpertProjectile.AddAction(new LockFaceDirectionLogicAction(false)); + #endregion + + m_generalBasicLB.AddLogicSet(walkStopLS, fireStraightProjectile, fireHighArchProjectile, fireArchProjectile); + m_generalAdvancedLB.AddLogicSet(walkStopLS, fireStraightAdvancedProjectile, fireHighArchAdvancedProjectile, fireArchAdvancedProjectile); + m_generalExpertLB.AddLogicSet(walkStopLS, fireStraightExpertProjectile, fireHighArchExpertProjectile, fireArchExpertProjectile); + + //m_generalAdvancedLB.AddLogicSet(fireProjectileLS); + //m_generalExpertLB.AddLogicSet(fireProjectileLS); + //m_generalMiniBossLB.AddLogicSet(fireProjectileLS); + + projData.Dispose(); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + + _objectList[1].TextureColor = TintablePart.TextureColor; + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(false, m_generalBasicLB, 20, 50, 15,15); + break; + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(false, m_generalBasicLB, 20, 15, 50, 15); + break; + case (STATE_ENGAGE): + RunLogicBlock(false, m_generalBasicLB, 20, 15, 15, 50); + break; + case (STATE_WANDER): + RunLogicBlock(false, m_generalBasicLB, 100, 0, 0, 0); + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(false, m_generalAdvancedLB, 20, 50, 15, 15); + break; + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(false, m_generalAdvancedLB, 20, 15, 50, 15); + break; + case (STATE_ENGAGE): + RunLogicBlock(false, m_generalAdvancedLB, 20, 15, 15, 50); + break; + case (STATE_WANDER): + RunLogicBlock(false, m_generalAdvancedLB, 100, 0, 0, 0); + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(false, m_generalExpertLB, 20, 15, 50, 15); + break; + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(false, m_generalExpertLB, 20, 50, 15, 15); + break; + case (STATE_ENGAGE): + RunLogicBlock(false, m_generalExpertLB, 20, 15, 15, 50); + break; + case (STATE_WANDER): + RunLogicBlock(false, m_generalExpertLB, 100, 0, 0, 0); + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(false, m_generalBasicLB, 20, 50, 15, 15); + break; + case (STATE_PROJECTILE_ENGAGE): + RunLogicBlock(false, m_generalBasicLB, 20, 15, 50, 15); + break; + case (STATE_ENGAGE): + RunLogicBlock(false, m_generalBasicLB, 20, 15, 15, 50); + break; + case (STATE_WANDER): + RunLogicBlock(false, m_generalBasicLB, 100, 0, 0, 0); + break; + default: + break; + } + } + + public void AngleArcher(float angle) + { + if (this.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.None) + this.GetChildAt(1).Rotation = angle; + else + this.GetChildAt(1).Rotation = -angle; + } + + public override void ResetState() + { + this.GetChildAt(1).Rotation = 0; + base.ResetState(); + } + + public override void Update(GameTime gameTime) + { + base.Update(gameTime); + } + + public override void HitEnemy(int damage, Vector2 position, bool isPlayer) + { + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "SkeletonAttack1"); + base.HitEnemy(damage, position, isPlayer); + } + + public EnemyObj_SkeletonArcher(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemySkeletonArcherIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.SkeletonArcher; + TintablePart = _objectList[0]; + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Spark.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Spark.cs new file mode 100644 index 0000000..a9379f8 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Spark.cs @@ -0,0 +1,456 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_Spark : EnemyObj + { + private bool m_hookedToGround = false; + private byte m_collisionBoxSize = 10; // How large the side collision boxes should be. The faster the spark moves, the faster this should be. + + protected override void InitializeEV() + { + LockFlip = true; + this.IsWeighted = false; + + #region Basic Variables - General + Name = EnemyEV.Spark_Basic_Name; + LocStringID = EnemyEV.Spark_Basic_Name_locID; + + MaxHealth = EnemyEV.Spark_Basic_MaxHealth; + Damage = EnemyEV.Spark_Basic_Damage; + XPValue = EnemyEV.Spark_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Spark_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Spark_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Spark_Basic_DropChance; + + Speed = EnemyEV.Spark_Basic_Speed; + TurnSpeed = EnemyEV.Spark_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Spark_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Spark_Basic_Jump; + CooldownTime = EnemyEV.Spark_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Spark_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Spark_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Spark_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Spark_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Spark_Basic_IsWeighted; + + Scale = EnemyEV.Spark_Basic_Scale; + ProjectileScale = EnemyEV.Spark_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Spark_Basic_Tint; + + MeleeRadius = EnemyEV.Spark_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Spark_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Spark_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Spark_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Spark_Miniboss_Name; + LocStringID = EnemyEV.Spark_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Spark_Miniboss_MaxHealth; + Damage = EnemyEV.Spark_Miniboss_Damage; + XPValue = EnemyEV.Spark_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Spark_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Spark_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Spark_Miniboss_DropChance; + + Speed = EnemyEV.Spark_Miniboss_Speed; + TurnSpeed = EnemyEV.Spark_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Spark_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Spark_Miniboss_Jump; + CooldownTime = EnemyEV.Spark_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Spark_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Spark_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Spark_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Spark_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Spark_Miniboss_IsWeighted; + + Scale = EnemyEV.Spark_Miniboss_Scale; + ProjectileScale = EnemyEV.Spark_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Spark_Miniboss_Tint; + + MeleeRadius = EnemyEV.Spark_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Spark_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Spark_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Spark_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.Spark_Expert_Name; + LocStringID = EnemyEV.Spark_Expert_Name_locID; + + MaxHealth = EnemyEV.Spark_Expert_MaxHealth; + Damage = EnemyEV.Spark_Expert_Damage; + XPValue = EnemyEV.Spark_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Spark_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Spark_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Spark_Expert_DropChance; + + Speed = EnemyEV.Spark_Expert_Speed; + TurnSpeed = EnemyEV.Spark_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Spark_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Spark_Expert_Jump; + CooldownTime = EnemyEV.Spark_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Spark_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Spark_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Spark_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Spark_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Spark_Expert_IsWeighted; + + Scale = EnemyEV.Spark_Expert_Scale; + ProjectileScale = EnemyEV.Spark_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Spark_Expert_Tint; + + MeleeRadius = EnemyEV.Spark_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Spark_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Spark_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Spark_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.Spark_Advanced_Name; + LocStringID = EnemyEV.Spark_Advanced_Name_locID; + + MaxHealth = EnemyEV.Spark_Advanced_MaxHealth; + Damage = EnemyEV.Spark_Advanced_Damage; + XPValue = EnemyEV.Spark_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Spark_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Spark_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Spark_Advanced_DropChance; + + Speed = EnemyEV.Spark_Advanced_Speed; + TurnSpeed = EnemyEV.Spark_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Spark_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Spark_Advanced_Jump; + CooldownTime = EnemyEV.Spark_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Spark_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Spark_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Spark_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Spark_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Spark_Advanced_IsWeighted; + + Scale = EnemyEV.Spark_Advanced_Scale; + ProjectileScale = EnemyEV.Spark_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Spark_Advanced_Tint; + + MeleeRadius = EnemyEV.Spark_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Spark_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Spark_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Spark_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + } + + protected override void InitializeLogic() + { + + this.CurrentSpeed = Speed; + base.InitializeLogic(); + } + + public void HookToGround() + { + m_hookedToGround = true; + float closestGround = 1000; + TerrainObj closestTerrain = null; + foreach (TerrainObj terrainObj in m_levelScreen.CurrentRoom.TerrainObjList) + { + if (terrainObj.Y >= this.Y) + { + if (terrainObj.Y - this.Y < closestGround && CollisionMath.Intersects(terrainObj.Bounds, new Rectangle((int)this.X, (int)(this.Y + (terrainObj.Y - this.Y) + 5), this.Width, (int)(this.Height / 2)))) + { + closestGround = terrainObj.Y - this.Y; + closestTerrain = terrainObj; + } + } + } + + if (closestTerrain != null) + //this.Y = closestTerrain.Y - (this.TerrainBounds.Bottom - this.Y - 40); + this.Y = closestTerrain.Y -(this.Height / 2) + 5; + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + public override void Update(GameTime gameTime) + { + if (m_hookedToGround == false) + HookToGround(); + + CollisionCheckRight(); + if (IsPaused == false) + this.Position += this.Heading * (this.CurrentSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds); + + base.Update(gameTime); + } + + private void CollisionCheckRight() + { + bool collidesTop = false; + bool collidesBottom = false; + bool collidesLeft = false; + bool collidesRight = false; + + bool collidesTL = false; + bool collidesTR = false; + bool collidesBL = false; + bool collidesBR = false; + float rotation = 0; + + if (this.Bounds.Right >= m_levelScreen.CurrentRoom.Bounds.Right) + { + collidesTR = true; + collidesRight = true; + collidesBR = true; + } + else if (this.Bounds.Left <= m_levelScreen.CurrentRoom.Bounds.Left) + { + collidesTL = true; + collidesLeft = true; + collidesBL = true; + } + + if (this.Bounds.Top <= m_levelScreen.CurrentRoom.Bounds.Top) + { + collidesTR = true; + collidesTop = true; + collidesTL = true; + } + else if (this.Bounds.Bottom >= m_levelScreen.CurrentRoom.Bounds.Bottom) + { + collidesBL = true; + collidesBottom = true; + collidesBR = true; + } + + + foreach (TerrainObj obj in m_levelScreen.CurrentRoom.TerrainObjList) + { + Rectangle objAbsRect = new Rectangle((int)obj.X, (int)obj.Y, obj.Width, obj.Height); + + if (CollisionMath.RotatedRectIntersects(TopLeftPoint, 0, Vector2.Zero, objAbsRect, obj.Rotation, Vector2.Zero)) + collidesTL = true; + + if (CollisionMath.RotatedRectIntersects(TopRightPoint, 0, Vector2.Zero, objAbsRect, obj.Rotation, Vector2.Zero)) + collidesTR = true; + + if (CollisionMath.RotatedRectIntersects(BottomRightPoint, 0, Vector2.Zero, objAbsRect, obj.Rotation, Vector2.Zero)) + { + collidesBR = true; + if (obj.Rotation != 0) + { + Vector2 mtd = CollisionMath.RotatedRectIntersectsMTD(this.BottomRightPoint, 0, Vector2.Zero, objAbsRect, obj.Rotation, Vector2.Zero); + if (mtd.X < 0 && mtd.Y < 0) + rotation = -45; + } + } + + if (CollisionMath.RotatedRectIntersects(BottomLeftPoint, 0, Vector2.Zero, objAbsRect, obj.Rotation, Vector2.Zero)) + { + collidesBL = true; + if (obj.Rotation != 0) + { + Vector2 mtd = CollisionMath.RotatedRectIntersectsMTD(BottomLeftPoint, 0, Vector2.Zero, objAbsRect, obj.Rotation, Vector2.Zero); + if (mtd.X > 0 && mtd.Y < 0) + rotation = 45; + } + } + + if (CollisionMath.RotatedRectIntersects(TopRect, 0, Vector2.Zero, objAbsRect, obj.Rotation, Vector2.Zero)) + collidesTop = true; + + if (CollisionMath.RotatedRectIntersects(BottomRect, 0, Vector2.Zero, objAbsRect, obj.Rotation, Vector2.Zero)) + collidesBottom = true; + + if (CollisionMath.RotatedRectIntersects(LeftRect, 0, Vector2.Zero, objAbsRect, obj.Rotation, Vector2.Zero)) + collidesLeft = true; + + if (CollisionMath.RotatedRectIntersects(RightRect, 0, Vector2.Zero, objAbsRect, obj.Rotation, Vector2.Zero)) + collidesRight = true; + } + + if (collidesBR == true && collidesTR == false && collidesRight == false) + this.Orientation = 0; + + if ((collidesTR == true && collidesBR == true) && collidesTL == false) + this.Orientation = MathHelper.ToRadians(-90); + + if ((collidesTR == true && collidesTL == true) && collidesBL == false) + this.Orientation = MathHelper.ToRadians(-180); + + if (collidesTL == true && collidesLeft == true && collidesBottom == false)//collidesBL == true && collidesLeft == true && collidesBottom == false) + this.Orientation = MathHelper.ToRadians(90); + + // Special cliff cases + if (collidesTR == true && collidesTop == false && collidesRight == false) + this.Orientation = MathHelper.ToRadians(-90); + + if (collidesTL == true && collidesTop == false && collidesLeft == false) + this.Orientation = MathHelper.ToRadians(-180); + + if (collidesBL == true && collidesLeft == false && collidesRight == false && collidesBottom == false) + this.Orientation = MathHelper.ToRadians(90); + + if (collidesBR == true && collidesBottom == false && collidesRight == false) + this.Orientation = 0; + + if (rotation != 0) + { + if ((rotation < 0 && collidesBR == true && collidesRight == true) || (rotation > 0 && collidesBR == false)) + this.Orientation = MathHelper.ToRadians(rotation); + } + + this.HeadingX = (float)Math.Cos(this.Orientation); + this.HeadingY = (float)Math.Sin(this.Orientation); + } + + public EnemyObj_Spark(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemySpark_Character", target, physicsManager, levelToAttachTo, difficulty) + { + IsWeighted = false; + ForceDraw = true; + this.Type = EnemyType.Spark; + this.NonKillable = true; + } + + //public override void Draw(Camera2D camera) + //{ + // base.Draw(camera); + // camera.Draw(Game.GenericTexture, TopLeftPoint, Color.Green * 0.5f); + // camera.Draw(Game.GenericTexture, TopRightPoint, Color.Green * 0.5f); + // camera.Draw(Game.GenericTexture, BottomLeftPoint, Color.Green * 0.5f); + // camera.Draw(Game.GenericTexture, BottomRightPoint, Color.Green * 0.5f); + + // camera.Draw(Game.GenericTexture, LeftRect, Color.Red * 0.5f); + // camera.Draw(Game.GenericTexture, RightRect, Color.Red * 0.5f); + // camera.Draw(Game.GenericTexture, BottomRect, Color.Red * 0.5f); + // camera.Draw(Game.GenericTexture, TopRect, Color.Red * 0.5f); + //} + + private Rectangle TopRect + { + get { return new Rectangle(this.Bounds.Left + m_collisionBoxSize, this.Bounds.Top, this.Width - (m_collisionBoxSize * 2) , m_collisionBoxSize); } + } + + private Rectangle BottomRect + { + get { return new Rectangle(this.Bounds.Left + m_collisionBoxSize, this.Bounds.Bottom - m_collisionBoxSize, this.Width - (m_collisionBoxSize * 2), m_collisionBoxSize); } + } + + private Rectangle LeftRect + { + get { return new Rectangle(this.Bounds.Left, this.Bounds.Top + m_collisionBoxSize, m_collisionBoxSize, this.Height - (m_collisionBoxSize * 2)); } + } + + private Rectangle RightRect + { + get { return new Rectangle(this.Bounds.Right - m_collisionBoxSize, this.Bounds.Top + m_collisionBoxSize, m_collisionBoxSize, this.Height - (m_collisionBoxSize * 2)); } + } + + + private Rectangle TopLeftPoint + { + get { return new Rectangle(this.Bounds.Left, this.Bounds.Top, m_collisionBoxSize, m_collisionBoxSize); } + } + + private Rectangle TopRightPoint + { + get { return new Rectangle(this.Bounds.Right - m_collisionBoxSize, this.Bounds.Top, m_collisionBoxSize, m_collisionBoxSize); } + } + + private Rectangle BottomLeftPoint + { + get { return new Rectangle(this.Bounds.Left, this.Bounds.Bottom - m_collisionBoxSize, m_collisionBoxSize, m_collisionBoxSize); } + } + + private Rectangle BottomRightPoint + { + get { return new Rectangle(this.Bounds.Right - m_collisionBoxSize, this.Bounds.Bottom - m_collisionBoxSize, m_collisionBoxSize, m_collisionBoxSize); } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_SpikeTrap.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_SpikeTrap.cs new file mode 100644 index 0000000..afe8551 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_SpikeTrap.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_SpikeTrap : EnemyObj + { + private LogicSet m_extractLS; + private float ExtractDelay = 0.0f; //0.5f; + + private Rectangle DetectionRect; + + protected override void InitializeEV() + { + Scale = new Vector2(2.0f, 2.0f);//(1.0f, 1.0f); + AnimationDelay = 1 / 10f; + //ProjectileScale = new Vector2(3.0f, 3.0f); + Speed = 0.0f; + MaxHealth = 10; + EngageRadius = 2100; + ProjectileRadius = 2200; + MeleeRadius = 650; + CooldownTime = 2.0f; + KnockBack = new Vector2(1, 2); + Damage = 25; + JumpHeight = 20.5f; + AlwaysFaceTarget = false; + CanFallOffLedges = false; + XPValue = 2; + CanBeKnockedBack = false; + + LockFlip = true; + this.IsWeighted = false; + + ExtractDelay = 0.1f; + DetectionRect = new Rectangle(0, 0, 120, 30); //(0,0, 200,50); + Name = "Spike Trap"; + LocStringID = EnemyEV.SpikeTrap_Basic_Name_locID; + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + case (GameTypes.EnemyDifficulty.EXPERT): + case (GameTypes.EnemyDifficulty.ADVANCED): + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + this.IsCollidable = false; + } + + protected override void InitializeLogic() + { + m_extractLS = new LogicSet(this); + m_extractLS.AddAction(new PlayAnimationLogicAction(1, 2)); + m_extractLS.AddAction(new DelayLogicAction(ExtractDelay)); + m_extractLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"TrapSpike_01", "TrapSpike_02", "TrapSpike_03")); + m_extractLS.AddAction(new PlayAnimationLogicAction(2, 4)); + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + public override void Update(GameTime gameTime) + { + if (IsPaused == false) + { + if (Game.PlayerStats.Traits.X != TraitType.PAD && Game.PlayerStats.Traits.Y != TraitType.PAD) + { + if (CollisionMath.Intersects(AbsDetectionRect, m_target.Bounds) == true) + { + if (this.CurrentFrame == 1 || this.CurrentFrame == this.TotalFrames) + { + this.IsCollidable = true; + m_extractLS.Execute(); + //this.PlayAnimation("StartExtract", "ExtractComplete", false); + } + } + else + { + if (this.CurrentFrame == 5 && m_extractLS.IsActive == false) // "ExtractComplete" + { + this.IsCollidable = false; + this.PlayAnimation("StartRetract", "RetractComplete", false); + } + } + } + + if (m_extractLS.IsActive == true) + m_extractLS.Update(gameTime); + } + + base.Update(gameTime); + } + + public EnemyObj_SpikeTrap(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemySpikeTrap_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.SpikeTrap; + this.StopAnimation(); + this.PlayAnimationOnRestart = false; + NonKillable = true; + } + + public override void Reset() + { + this.PlayAnimation(1, 1); + base.Reset(); + } + + public override void ResetState() + { + this.PlayAnimation(1, 1); + base.ResetState(); + } + + private Rectangle AbsDetectionRect + { + get { return new Rectangle((int)(this.X - DetectionRect.Width / 2f), (int)(this.Y - DetectionRect.Height), DetectionRect.Width, DetectionRect.Height); } + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_extractLS.Dispose(); + m_extractLS = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Starburst.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Starburst.cs new file mode 100644 index 0000000..3a2e0be --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Starburst.cs @@ -0,0 +1,392 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; + +namespace RogueCastle +{ + public class EnemyObj_Starburst : EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + + private float FireballDelay = 0.5f; + + protected override void InitializeEV() + { + #region Basic Variables - General + Name = EnemyEV.Starburst_Basic_Name; + LocStringID = EnemyEV.Starburst_Basic_Name_locID; + + MaxHealth = EnemyEV.Starburst_Basic_MaxHealth; + Damage = EnemyEV.Starburst_Basic_Damage; + XPValue = EnemyEV.Starburst_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Starburst_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Starburst_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Starburst_Basic_DropChance; + + Speed = EnemyEV.Starburst_Basic_Speed; + TurnSpeed = EnemyEV.Starburst_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Starburst_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Starburst_Basic_Jump; + CooldownTime = EnemyEV.Starburst_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Starburst_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Starburst_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Starburst_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Starburst_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Starburst_Basic_IsWeighted; + + Scale = EnemyEV.Starburst_Basic_Scale; + ProjectileScale = EnemyEV.Starburst_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Starburst_Basic_Tint; + + MeleeRadius = EnemyEV.Starburst_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Starburst_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Starburst_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Starburst_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Starburst_Miniboss_Name; + LocStringID = EnemyEV.Starburst_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Starburst_Miniboss_MaxHealth; + Damage = EnemyEV.Starburst_Miniboss_Damage; + XPValue = EnemyEV.Starburst_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Starburst_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Starburst_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Starburst_Miniboss_DropChance; + + Speed = EnemyEV.Starburst_Miniboss_Speed; + TurnSpeed = EnemyEV.Starburst_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Starburst_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Starburst_Miniboss_Jump; + CooldownTime = EnemyEV.Starburst_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Starburst_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Starburst_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Starburst_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Starburst_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Starburst_Miniboss_IsWeighted; + + Scale = EnemyEV.Starburst_Miniboss_Scale; + ProjectileScale = EnemyEV.Starburst_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Starburst_Miniboss_Tint; + + MeleeRadius = EnemyEV.Starburst_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Starburst_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Starburst_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Starburst_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.Starburst_Expert_Name; + LocStringID = EnemyEV.Starburst_Expert_Name_locID; + + MaxHealth = EnemyEV.Starburst_Expert_MaxHealth; + Damage = EnemyEV.Starburst_Expert_Damage; + XPValue = EnemyEV.Starburst_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Starburst_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Starburst_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Starburst_Expert_DropChance; + + Speed = EnemyEV.Starburst_Expert_Speed; + TurnSpeed = EnemyEV.Starburst_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Starburst_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Starburst_Expert_Jump; + CooldownTime = EnemyEV.Starburst_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Starburst_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Starburst_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Starburst_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Starburst_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Starburst_Expert_IsWeighted; + + Scale = EnemyEV.Starburst_Expert_Scale; + ProjectileScale = EnemyEV.Starburst_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Starburst_Expert_Tint; + + MeleeRadius = EnemyEV.Starburst_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Starburst_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Starburst_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Starburst_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.Starburst_Advanced_Name; + LocStringID = EnemyEV.Starburst_Advanced_Name_locID; + + MaxHealth = EnemyEV.Starburst_Advanced_MaxHealth; + Damage = EnemyEV.Starburst_Advanced_Damage; + XPValue = EnemyEV.Starburst_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Starburst_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Starburst_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Starburst_Advanced_DropChance; + + Speed = EnemyEV.Starburst_Advanced_Speed; + TurnSpeed = EnemyEV.Starburst_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Starburst_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Starburst_Advanced_Jump; + CooldownTime = EnemyEV.Starburst_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Starburst_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Starburst_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Starburst_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Starburst_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Starburst_Advanced_IsWeighted; + + Scale = EnemyEV.Starburst_Advanced_Scale; + ProjectileScale = EnemyEV.Starburst_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Starburst_Advanced_Tint; + + MeleeRadius = EnemyEV.Starburst_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Starburst_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Starburst_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Starburst_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + } + + protected override void InitializeLogic() + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "TurretProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Speed = new Vector2(this.ProjectileSpeed, this.ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = true, //false + Scale = ProjectileScale, + }; + + LogicSet fireProjectileBasicLS = new LogicSet(this); + projData.Angle = new Vector2(0, 0); + fireProjectileBasicLS.AddAction(new RunFunctionLogicAction(this, "FireAnimation")); + fireProjectileBasicLS.AddAction(new DelayLogicAction(FireballDelay)); + fireProjectileBasicLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Eyeball_ProjectileAttack")); + fireProjectileBasicLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-90, -90); + fireProjectileBasicLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(90, 90); + fireProjectileBasicLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(180, 180); + fireProjectileBasicLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileBasicLS.AddAction(new ChangeSpriteLogicAction("EnemyStarburstIdle_Character", true, true)); + fireProjectileBasicLS.AddAction(new DelayLogicAction(1.0f, 1.0f)); + fireProjectileBasicLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet fireProjectileAdvancedLS = new LogicSet(this); + projData.Angle = new Vector2(45, 45); + fireProjectileAdvancedLS.AddAction(new ChangePropertyLogicAction(_objectList[1], "Rotation", 45)); + fireProjectileAdvancedLS.AddAction(new RunFunctionLogicAction(this, "FireAnimation")); + fireProjectileAdvancedLS.AddAction(new ChangePropertyLogicAction(_objectList[1], "Rotation", 45)); + fireProjectileAdvancedLS.AddAction(new DelayLogicAction(FireballDelay)); + fireProjectileAdvancedLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Eyeball_ProjectileAttack")); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-45, -45); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(135, 135); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-135, -135); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-90, -90); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(90, 90); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(180, 180); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(0, 0); + fireProjectileAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileAdvancedLS.AddAction(new ChangeSpriteLogicAction("EnemyStarburstIdle_Character", true, true)); + fireProjectileAdvancedLS.AddAction(new ChangePropertyLogicAction(_objectList[1], "Rotation", 45)); + fireProjectileAdvancedLS.AddAction(new DelayLogicAction(1.0f, 1.0f)); + fireProjectileAdvancedLS.Tag = GameTypes.LogicSetType_ATTACK; + + //TEDDY - Just like Advanced projetiles but made so the bullets go through terrain. + #region EXPERT + LogicSet fireProjectileExpertLS = new LogicSet(this); + projData.Angle = new Vector2(45, 45); + projData.CollidesWithTerrain = false; + projData.SpriteName = "GhostProjectile_Sprite"; + fireProjectileExpertLS.AddAction(new ChangePropertyLogicAction(_objectList[1], "Rotation", 45)); + fireProjectileExpertLS.AddAction(new RunFunctionLogicAction(this, "FireAnimation")); + fireProjectileExpertLS.AddAction(new ChangePropertyLogicAction(_objectList[1], "Rotation", 45)); + fireProjectileExpertLS.AddAction(new DelayLogicAction(FireballDelay)); + fireProjectileExpertLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Eyeball_ProjectileAttack")); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-45, -45); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(135, 135); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-135, -135); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-90, -90); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(90, 90); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(180, 180); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(0, 0); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyStarburstIdle_Character", true, true)); + fireProjectileExpertLS.AddAction(new DelayLogicAction(1.0f, 1.0f)); + + fireProjectileExpertLS.AddAction(new RunFunctionLogicAction(this, "FireAnimation")); + fireProjectileExpertLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "Eyeball_ProjectileAttack")); + projData.Angle = new Vector2(25, 25); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-25, -25); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(115, 115); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-115, -115); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-70, -70); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(70, 70); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(160, 160); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + projData.Angle = new Vector2(-160, -160); + fireProjectileExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileExpertLS.AddAction(new ChangeSpriteLogicAction("EnemyStarburstIdle_Character", true, true)); + fireProjectileExpertLS.AddAction(new ChangePropertyLogicAction(_objectList[1], "Rotation", 45)); + fireProjectileExpertLS.AddAction(new DelayLogicAction(1.25f, 1.25f)); + fireProjectileExpertLS.Tag = GameTypes.LogicSetType_ATTACK; + + #endregion + + + LogicSet doNothing = new LogicSet(this); + doNothing.AddAction(new DelayLogicAction(0.5f, 0.5f)); + + m_generalBasicLB.AddLogicSet(fireProjectileBasicLS, doNothing); + m_generalAdvancedLB.AddLogicSet(fireProjectileAdvancedLS, doNothing); + m_generalExpertLB.AddLogicSet(fireProjectileExpertLS, doNothing); + m_generalMiniBossLB.AddLogicSet(fireProjectileAdvancedLS, doNothing); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalMiniBossLB); + + projData.Dispose(); + + base.InitializeLogic(); + } + + public void FireAnimation() + { + this.ChangeSprite("EnemyStarburstAttack_Character"); + (_objectList[0] as IAnimateableObj).PlayAnimation(true); + (_objectList[1] as IAnimateableObj).PlayAnimation(false); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 100, 0); + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 100); + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 100, 0); + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalAdvancedLB, 0, 100); + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 100, 0); + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalExpertLB, 0, 100); + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + RunLogicBlock(true, m_generalMiniBossLB, 60, 40, 0); + break; + default: + break; + } + } + + public EnemyObj_Starburst(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyStarburstIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.Starburst; + } + + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_SwordKnight.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_SwordKnight.cs new file mode 100644 index 0000000..465eab7 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_SwordKnight.cs @@ -0,0 +1,460 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_SwordKnight: EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + + private float SlashDelay = 0.0f; + private float SlashTripleDelay = 1.25f; + private float TripleAttackSpeed = 500f; + private FrameSoundObj m_walkSound, m_walkSound2; + + protected override void InitializeEV() + { + SlashDelay = 0.25f; + #region Basic Variables - General + Name = EnemyEV.SwordKnight_Basic_Name; + LocStringID = EnemyEV.SwordKnight_Basic_Name_locID; + + MaxHealth = EnemyEV.SwordKnight_Basic_MaxHealth; + Damage = EnemyEV.SwordKnight_Basic_Damage; + XPValue = EnemyEV.SwordKnight_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.SwordKnight_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.SwordKnight_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.SwordKnight_Basic_DropChance; + + Speed = EnemyEV.SwordKnight_Basic_Speed; + TurnSpeed = EnemyEV.SwordKnight_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.SwordKnight_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.SwordKnight_Basic_Jump; + CooldownTime = EnemyEV.SwordKnight_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.SwordKnight_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.SwordKnight_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.SwordKnight_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.SwordKnight_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.SwordKnight_Basic_IsWeighted; + + Scale = EnemyEV.SwordKnight_Basic_Scale; + ProjectileScale = EnemyEV.SwordKnight_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.SwordKnight_Basic_Tint; + + MeleeRadius = EnemyEV.SwordKnight_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.SwordKnight_Basic_ProjectileRadius; + EngageRadius = EnemyEV.SwordKnight_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.SwordKnight_Basic_KnockBack; + #endregion + + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + ForceDraw = true; + SlashDelay = 1.05f; + #region Miniboss Variables - General + Name = EnemyEV.SwordKnight_Miniboss_Name; + LocStringID = EnemyEV.SwordKnight_Miniboss_Name_locID; + + MaxHealth = EnemyEV.SwordKnight_Miniboss_MaxHealth; + Damage = EnemyEV.SwordKnight_Miniboss_Damage; + XPValue = EnemyEV.SwordKnight_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.SwordKnight_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.SwordKnight_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.SwordKnight_Miniboss_DropChance; + + Speed = EnemyEV.SwordKnight_Miniboss_Speed; + TurnSpeed = EnemyEV.SwordKnight_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.SwordKnight_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.SwordKnight_Miniboss_Jump; + CooldownTime = EnemyEV.SwordKnight_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.SwordKnight_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.SwordKnight_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.SwordKnight_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.SwordKnight_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.SwordKnight_Miniboss_IsWeighted; + + Scale = EnemyEV.SwordKnight_Miniboss_Scale; + ProjectileScale = EnemyEV.SwordKnight_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.SwordKnight_Miniboss_Tint; + + MeleeRadius = EnemyEV.SwordKnight_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.SwordKnight_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.SwordKnight_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.SwordKnight_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + SlashDelay = 0.25f; + TripleAttackSpeed = 500f; + #region Expert Variables - General + Name = EnemyEV.SwordKnight_Expert_Name; + LocStringID = EnemyEV.SwordKnight_Expert_Name_locID; + + MaxHealth = EnemyEV.SwordKnight_Expert_MaxHealth; + Damage = EnemyEV.SwordKnight_Expert_Damage; + XPValue = EnemyEV.SwordKnight_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.SwordKnight_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.SwordKnight_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.SwordKnight_Expert_DropChance; + + Speed = EnemyEV.SwordKnight_Expert_Speed; + TurnSpeed = EnemyEV.SwordKnight_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.SwordKnight_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.SwordKnight_Expert_Jump; + CooldownTime = EnemyEV.SwordKnight_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.SwordKnight_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.SwordKnight_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.SwordKnight_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.SwordKnight_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.SwordKnight_Expert_IsWeighted; + + Scale = EnemyEV.SwordKnight_Expert_Scale; + ProjectileScale = EnemyEV.SwordKnight_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.SwordKnight_Expert_Tint; + + MeleeRadius = EnemyEV.SwordKnight_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.SwordKnight_Expert_ProjectileRadius; + EngageRadius = EnemyEV.SwordKnight_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.SwordKnight_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + SlashDelay = 0.25f; + #region Advanced Variables - General + Name = EnemyEV.SwordKnight_Advanced_Name; + LocStringID = EnemyEV.SwordKnight_Advanced_Name_locID; + + MaxHealth = EnemyEV.SwordKnight_Advanced_MaxHealth; + Damage = EnemyEV.SwordKnight_Advanced_Damage; + XPValue = EnemyEV.SwordKnight_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.SwordKnight_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.SwordKnight_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.SwordKnight_Advanced_DropChance; + + Speed = EnemyEV.SwordKnight_Advanced_Speed; + TurnSpeed = EnemyEV.SwordKnight_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.SwordKnight_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.SwordKnight_Advanced_Jump; + CooldownTime = EnemyEV.SwordKnight_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.SwordKnight_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.SwordKnight_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.SwordKnight_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.SwordKnight_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.SwordKnight_Advanced_IsWeighted; + + Scale = EnemyEV.SwordKnight_Advanced_Scale; + ProjectileScale = EnemyEV.SwordKnight_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.SwordKnight_Advanced_Tint; + + MeleeRadius = EnemyEV.SwordKnight_Advanced_MeleeRadius; + EngageRadius = EnemyEV.SwordKnight_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.SwordKnight_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.SwordKnight_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + + } + + protected override void InitializeLogic() + { + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightWalk_Character", true, true)); + walkTowardsLS.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsLS.AddAction(new DelayLogicAction(1)); + + LogicSet walkAwayLS = new LogicSet(this); + walkAwayLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightWalk_Character", true, true)); + walkAwayLS.AddAction(new MoveLogicAction(m_target, false)); + walkAwayLS.AddAction(new DelayLogicAction(1)); + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightIdle_Character", true, true)); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(0.5f)); + + LogicSet attackLS = new LogicSet(this); + attackLS.AddAction(new MoveLogicAction(m_target, true, 0)); + attackLS.AddAction(new LockFaceDirectionLogicAction(true)); + attackLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightAttack_Character", false, false)); + attackLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + attackLS.AddAction(new DelayLogicAction(SlashDelay)); + attackLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SwordKnight_Attack_v02")); + attackLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + attackLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightIdle_Character", false, false)); + attackLS.AddAction(new LockFaceDirectionLogicAction(false)); + attackLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet attackTripleLS = new LogicSet(this); + attackTripleLS.AddAction(new MoveLogicAction(m_target, true, 0)); + attackTripleLS.AddAction(new LockFaceDirectionLogicAction(true)); + attackTripleLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightAttack_Character", false, false)); + attackTripleLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + attackTripleLS.AddAction(new DelayLogicAction(SlashTripleDelay)); + attackTripleLS.AddAction(new MoveDirectionLogicAction(TripleAttackSpeed)); + attackTripleLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 60f)); + attackTripleLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SwordKnight_Attack_v02")); + attackTripleLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + + + //attackTripleLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightAttack_Character", false, false)); + attackTripleLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + attackTripleLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SwordKnight_Attack_v02")); + attackTripleLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + + //attackTripleLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightAttack_Character", false, false)); + //attackTripleLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + //attackTripleLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SwordKnight_Attack_v02")); + //attackTripleLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + + attackTripleLS.AddAction(new MoveLogicAction(null, true, 0)); + attackTripleLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / EnemyEV.SwordKnight_Advanced_AnimationDelay)); + attackTripleLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightIdle_Character", false, false)); + attackTripleLS.AddAction(new LockFaceDirectionLogicAction(false)); + attackTripleLS.Tag = GameTypes.LogicSetType_ATTACK; + + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "EnemySpearKnightWave_Sprite", + SourceAnchor = new Vector2(60, 0), + Target = null, + Speed = new Vector2(ProjectileSpeed, ProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(0, 0), + CollidesWithTerrain = true, + Scale = ProjectileScale, + }; + + LogicSet attackAdvancedLS = new LogicSet(this); + attackAdvancedLS.AddAction(new MoveLogicAction(m_target, true, 0)); + attackAdvancedLS.AddAction(new LockFaceDirectionLogicAction(true)); + attackAdvancedLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightAttack_Character", false, false)); + attackAdvancedLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + attackAdvancedLS.AddAction(new DelayLogicAction(SlashDelay)); + attackAdvancedLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnightAttack1")); + attackAdvancedLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + attackAdvancedLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + attackAdvancedLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightIdle_Character", false, false)); + attackAdvancedLS.AddAction(new LockFaceDirectionLogicAction(false)); + attackAdvancedLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet attackTripleExpertLS = new LogicSet(this); + attackTripleExpertLS.AddAction(new MoveLogicAction(m_target, true, 0)); + attackTripleExpertLS.AddAction(new LockFaceDirectionLogicAction(true)); + attackTripleExpertLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightAttack_Character", false, false)); + attackTripleExpertLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + attackTripleExpertLS.AddAction(new DelayLogicAction(SlashTripleDelay)); + attackTripleExpertLS.AddAction(new MoveDirectionLogicAction(TripleAttackSpeed)); + attackTripleExpertLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 120f)); + attackTripleExpertLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SwordKnight_Attack_v02")); + attackTripleExpertLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + + + attackTripleExpertLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightAttack_Character", false, false)); + attackTripleExpertLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + attackTripleExpertLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SwordKnight_Attack_v02")); + attackTripleExpertLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + + attackTripleExpertLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightAttack_Character", false, false)); + attackTripleExpertLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + attackTripleExpertLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SwordKnight_Attack_v02")); + attackTripleExpertLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + + attackTripleExpertLS.AddAction(new MoveLogicAction(null, true, 0)); + attackTripleExpertLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / EnemyEV.SwordKnight_Advanced_AnimationDelay)); + attackTripleExpertLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player, "SpearKnightAttack1")); + attackTripleExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + attackTripleExpertLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + attackTripleExpertLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightIdle_Character", false, false)); + attackTripleExpertLS.AddAction(new LockFaceDirectionLogicAction(false)); + attackTripleExpertLS.Tag = GameTypes.LogicSetType_ATTACK; + + LogicSet attackExpertLS = new LogicSet(this); + attackExpertLS.AddAction(new MoveLogicAction(m_target, true, 0)); + attackExpertLS.AddAction(new LockFaceDirectionLogicAction(true)); + attackExpertLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightAttack_Character", false, false)); + attackExpertLS.AddAction(new PlayAnimationLogicAction("Start", "Windup", false)); + attackExpertLS.AddAction(new DelayLogicAction(SlashDelay)); + attackExpertLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"SpearKnightAttack1")); + attackExpertLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + attackExpertLS.AddAction(new PlayAnimationLogicAction("Attack", "End", false)); + // + attackExpertLS.AddAction(new ChangeSpriteLogicAction("EnemySwordKnightIdle_Character", false, false)); + attackExpertLS.AddAction(new LockFaceDirectionLogicAction(false)); + attackExpertLS.Tag = GameTypes.LogicSetType_ATTACK; + + m_generalBasicLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, attackLS); + m_generalAdvancedLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, attackLS, attackTripleLS); + m_generalExpertLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, attackLS, attackTripleExpertLS); + m_generalCooldownLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + + //SetCooldownLogicBlock(m_generalCooldownLB, 0, 0, 100); //walkTowardsLS, walkAwayLS, walkStopLS + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.BASIC): + SetCooldownLogicBlock(m_generalCooldownLB, 14, 11, 75); //walkTowardsLS, walkAwayLS, walkStopLS + break; + case (GameTypes.EnemyDifficulty.ADVANCED): + case (GameTypes.EnemyDifficulty.EXPERT): + SetCooldownLogicBlock(m_generalCooldownLB, 40, 30, 30); //walkTowardsLS, walkAwayLS, walkStopLS + break; + case (GameTypes.EnemyDifficulty.MINIBOSS): + SetCooldownLogicBlock(m_generalCooldownLB, 100, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS + break; + default: + break; + } + + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 0, 100); //walkTowardsLS, walkAwayLS, walkStopLS, attackLS + break; + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 15, 15, 70, 0); //walkTowardsLS, walkAwayLS, walkStopLS, attackLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100, 0); //walkTowardsLS, walkAwayLS, walkStopLS, attackLS + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 0, 0, 0, 65, 35); //walkTowardsLS, walkAwayLS, walkStopLS, attackLS + break; + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalAdvancedLB, 60, 20, 20, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, attackLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalAdvancedLB, 0, 0, 100, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, attackLS + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + RunLogicBlock(true, m_generalExpertLB, 0, 0, 0, 62, 38); //walkTowardsLS, walkAwayLS, walkStopLS, attackLS + break; + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + RunLogicBlock(true, m_generalBasicLB, 60, 20, 20, 0); //walkTowardsLS, walkAwayLS, walkStopLS, attackLS + break; + case (STATE_WANDER): + RunLogicBlock(true, m_generalBasicLB, 0, 0, 100, 0); //walkTowardsLS, walkAwayLS, walkStopLS, attackLS + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + //RunLogicBlock(true, m_generalBasicLB, 0, 0, 0, 100); //walkTowardsLS, walkAwayLS, walkStopLS, attackLS + RunLogicBlock(true, m_generalBasicLB, 100, 0, 0, 0); //walkTowardsLS, walkAwayLS, walkStopLS, attackLS + break; + default: + break; + } + } + + public override void Update(GameTime gameTime) + { + if (this.SpriteName == "EnemySwordKnightWalk_Character") + { + m_walkSound.Update(); + m_walkSound2.Update(); + } + base.Update(gameTime); + } + + public EnemyObj_SwordKnight(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemySwordKnightIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.SwordKnight; + m_walkSound = new FrameSoundObj(this, m_target, 1, "KnightWalk1", "KnightWalk2"); + m_walkSound2 = new FrameSoundObj(this, m_target, 6, "KnightWalk1", "KnightWalk2"); + } + + public override void HitEnemy(int damage, Vector2 position, bool isPlayer) + { + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Knight_Hit01", "Knight_Hit02", "Knight_Hit03"); + base.HitEnemy(damage, position, isPlayer); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + m_walkSound.Dispose(); + m_walkSound = null; + m_walkSound2.Dispose(); + m_walkSound2 = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Turret.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Turret.cs new file mode 100644 index 0000000..d4e57d3 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Turret.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_Turret : EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + + protected override void InitializeEV() + { + Scale = new Vector2(2.0f, 2.0f);//(1.0f, 1.0f); + AnimationDelay = 1 / 10f; + //ProjectileScale = new Vector2(3.0f, 3.0f); + Speed = 0.0f; + MaxHealth = 10; + EngageRadius = 30; + ProjectileRadius = 20; + MeleeRadius = 10; + CooldownTime = 2.0f; + KnockBack = new Vector2(1, 2); + Damage = 25; + JumpHeight = 20.5f; + AlwaysFaceTarget = false; + CanFallOffLedges = false; + XPValue = 2; + CanBeKnockedBack = false; + + LockFlip = true; + this.IsWeighted = false; + IsCollidable = false; + this.Name = "Wall Turret"; + this.LocStringID = "LOC_ID_ENEMY_NAME_117"; + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + case (GameTypes.EnemyDifficulty.EXPERT): + case (GameTypes.EnemyDifficulty.ADVANCED): + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + } + + protected override void InitializeLogic() + { + float angle = this.Rotation; + float delay = this.ParseTagToFloat("delay"); + float speed = this.ParseTagToFloat("speed"); + if (delay == 0) + { + Console.WriteLine("ERROR: Turret set with delay of 0. Shoots too fast."); + delay = 10000; + } + + + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "TurretProjectile_Sprite", + SourceAnchor = Vector2.Zero, + Target = null, + Speed = new Vector2(speed, speed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(angle, angle), + CollidesWithTerrain = true, + Scale = ProjectileScale, + }; + + LogicSet fireProjectileLS = new LogicSet(this); + fireProjectileLS.AddAction(new PlayAnimationLogicAction(false), Types.Sequence.Parallel); + fireProjectileLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, projData)); + fireProjectileLS.AddAction(new Play3DSoundLogicAction(this, m_target, "Turret_Attack01", "Turret_Attack02", "Turret_Attack03")); + //fireProjectileLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Turret_Attack01", "Turret_Attack02", "Turret_Attack03")); + fireProjectileLS.AddAction(new DelayLogicAction(delay)); + + m_generalBasicLB.AddLogicSet(fireProjectileLS); + m_generalAdvancedLB.AddLogicSet(fireProjectileLS); + m_generalExpertLB.AddLogicSet(fireProjectileLS); + m_generalMiniBossLB.AddLogicSet(fireProjectileLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalMiniBossLB); + + projData.Dispose(); + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + RunLogicBlock(false, m_generalBasicLB, 100); + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + public EnemyObj_Turret(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyTurretFire_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.IsCollidable = false; + ForceDraw = true; + this.Type = EnemyType.Turret; + this.StopAnimation(); + this.PlayAnimationOnRestart = false; + NonKillable = true; + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Wall.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Wall.cs new file mode 100644 index 0000000..15908b3 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Wall.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_Wall : EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalAdvancedLB = new LogicBlock(); + private LogicBlock m_generalExpertLB = new LogicBlock(); + private LogicBlock m_generalMiniBossLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + + protected override void InitializeEV() + { + XPValue = 5000; + MaxHealth = 10000; + Damage = 900; + ProjectileDamage = 50; + + this.IsWeighted = false; + this.Scale = new Vector2(1f, 3.0f); + ProjectileScale = new Vector2(3.0f, 3.0f); + Speed = 1.75f; + EngageRadius = 1900; + ProjectileRadius = 1600; + MeleeRadius = 650; + CooldownTime = 2.0f; + KnockBack = new Vector2(5, 6); + JumpHeight = 20.5f; + AlwaysFaceTarget = true; + CanFallOffLedges = false; + CanBeKnockedBack = false; + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + case (GameTypes.EnemyDifficulty.EXPERT): + case (GameTypes.EnemyDifficulty.ADVANCED): + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + } + + protected override void InitializeLogic() + { + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new MoveLogicAction(m_target, true)); + //walkTowardsLS.AddAction(new DelayLogicAction(0.5f, 1.25f)); + + LogicSet walkAwayLS = new LogicSet(this); + walkAwayLS.AddAction(new MoveLogicAction(m_target, false)); + walkAwayLS.AddAction(new DelayLogicAction(0.5f, 1.25f)); + + LogicSet walkStopLS = new LogicSet(this); + walkStopLS.AddAction(new MoveLogicAction(m_target, true, 0)); + walkStopLS.AddAction(new DelayLogicAction(0.5f, 1.25f)); + + LogicSet throwBigBoneLS = new LogicSet(this); + throwBigBoneLS.AddAction(new MoveLogicAction(m_target, true)); + throwBigBoneLS.AddAction(new RunFunctionLogicAction(this, "ResizeProjectile", true)); + //throwBigBoneLS.AddAction(new FireProjectileLogicAction(m_levelScreen.ProjectileManager, "SpearProjectile", new Vector2(90, 0), 0, 6.75f, false, 1.75f, ProjectileDamage)); + throwBigBoneLS.AddAction(new RunFunctionLogicAction(this, "ResizeProjectile", false)); + throwBigBoneLS.AddAction(new DelayLogicAction(3.0f)); + + LogicSet throwRandomProjectileLS = new LogicSet(this); + throwRandomProjectileLS.AddAction(new MoveLogicAction(m_target, true)); + throwRandomProjectileLS.AddAction(new RunFunctionLogicAction(this, "FireRandomProjectile")); + throwRandomProjectileLS.AddAction(new RunFunctionLogicAction(this, "FireRandomProjectile")); + throwRandomProjectileLS.AddAction(new RunFunctionLogicAction(this, "FireRandomProjectile")); + throwRandomProjectileLS.AddAction(new DelayLogicAction(1.3f)); + + m_generalBasicLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS, throwBigBoneLS, throwRandomProjectileLS); + m_generalCooldownLB.AddLogicSet(walkTowardsLS, walkAwayLS, walkStopLS); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalAdvancedLB); + logicBlocksToDispose.Add(m_generalExpertLB); + logicBlocksToDispose.Add(m_generalMiniBossLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + + SetCooldownLogicBlock(m_generalCooldownLB, 40, 40, 20); //walkTowardsLS, walkAwayLS, walkStopLS + + base.InitializeLogic(); + } + + public void FireRandomProjectile() + { + //ProjectileObj obj = m_levelScreen.ProjectileManager.FireProjectile("BoneProjectile", this, new Vector2(-25.0f, CDGMath.RandomFloat(-300.0f, 300.0f)), 0, 5.5f, false, 5.0f, ProjectileDamage); + //obj.Scale = ProjectileScale; + } + + public void ResizeProjectile(Boolean resize) + { + if (resize == true) + ProjectileScale = new Vector2(2.5f, 2.5f); + else + ProjectileScale = new Vector2(2.5f, 2.5f); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + RunLogicBlock(false, m_generalBasicLB, 0, 0, 0, 20, 80); //walkTowardsLS, walkAwayLS, walkStopLS, throwBigBoneLS, throwRandomProjectileLS + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + public override void Update(GameTime gameTime) + { + HeadingY = 0; + if (HeadingX > 0) this.HeadingX = 1; // A hack to maintain a horizontal speed. + else if (HeadingX < 0) this.HeadingX = -1; + base.Update(gameTime); + this.Y -= this.HeadingY; // Hack to make sure the wall only goes horizontal since collisions are turned off. + } + + public EnemyObj_Wall(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyGhostIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + CollisionTypeTag = GameTypes.CollisionType_ENEMYWALL; + this.Type = EnemyType.Wall; + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Wolf.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Wolf.cs new file mode 100644 index 0000000..82bb78d --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Wolf.cs @@ -0,0 +1,394 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_Wolf: EnemyObj + { + private LogicBlock m_generalBasicLB = new LogicBlock(); + private LogicBlock m_generalCooldownLB = new LogicBlock(); + private LogicBlock m_wolfHitLB = new LogicBlock(); + + public bool Chasing { get; set; } + private float PounceDelay = 0.3f; + private float PounceLandDelay = 0.5f; // How long after a wolf lands does he start chasing again. + private Color FurColour = Color.White; + + private float m_startDelay = 1f;// A special delay for wolves since they move too quick. + private float m_startDelayCounter = 0; + + private FrameSoundObj m_runFrameSound; + + protected override void InitializeEV() + { + #region Basic Variables - General + Name = EnemyEV.Wolf_Basic_Name; + LocStringID = EnemyEV.Wolf_Basic_Name_locID; + + MaxHealth = EnemyEV.Wolf_Basic_MaxHealth; + Damage = EnemyEV.Wolf_Basic_Damage; + XPValue = EnemyEV.Wolf_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Wolf_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Wolf_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Wolf_Basic_DropChance; + + Speed = EnemyEV.Wolf_Basic_Speed; + TurnSpeed = EnemyEV.Wolf_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Wolf_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Wolf_Basic_Jump; + CooldownTime = EnemyEV.Wolf_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Wolf_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Wolf_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Wolf_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Wolf_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Wolf_Basic_IsWeighted; + + Scale = EnemyEV.Wolf_Basic_Scale; + ProjectileScale = EnemyEV.Wolf_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Wolf_Basic_Tint; + + MeleeRadius = EnemyEV.Wolf_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Wolf_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Wolf_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Wolf_Basic_KnockBack; + #endregion + + InitialLogicDelay = 1; + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + #region Miniboss Variables - General + Name = EnemyEV.Wolf_Miniboss_Name; + LocStringID = EnemyEV.Wolf_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Wolf_Miniboss_MaxHealth; + Damage = EnemyEV.Wolf_Miniboss_Damage; + XPValue = EnemyEV.Wolf_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Wolf_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Wolf_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Wolf_Miniboss_DropChance; + + Speed = EnemyEV.Wolf_Miniboss_Speed; + TurnSpeed = EnemyEV.Wolf_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Wolf_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Wolf_Miniboss_Jump; + CooldownTime = EnemyEV.Wolf_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Wolf_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Wolf_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Wolf_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Wolf_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Wolf_Miniboss_IsWeighted; + + Scale = EnemyEV.Wolf_Miniboss_Scale; + ProjectileScale = EnemyEV.Wolf_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Wolf_Miniboss_Tint; + + MeleeRadius = EnemyEV.Wolf_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Wolf_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Wolf_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Wolf_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + #region Expert Variables - General + Name = EnemyEV.Wolf_Expert_Name; + LocStringID = EnemyEV.Wolf_Expert_Name_locID; + + MaxHealth = EnemyEV.Wolf_Expert_MaxHealth; + Damage = EnemyEV.Wolf_Expert_Damage; + XPValue = EnemyEV.Wolf_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Wolf_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Wolf_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Wolf_Expert_DropChance; + + Speed = EnemyEV.Wolf_Expert_Speed; + TurnSpeed = EnemyEV.Wolf_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Wolf_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Wolf_Expert_Jump; + CooldownTime = EnemyEV.Wolf_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Wolf_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Wolf_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Wolf_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Wolf_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Wolf_Expert_IsWeighted; + + Scale = EnemyEV.Wolf_Expert_Scale; + ProjectileScale = EnemyEV.Wolf_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Wolf_Expert_Tint; + + MeleeRadius = EnemyEV.Wolf_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Wolf_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Wolf_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Wolf_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + #region Advanced Variables - General + Name = EnemyEV.Wolf_Advanced_Name; + LocStringID = EnemyEV.Wolf_Advanced_Name_locID; + + MaxHealth = EnemyEV.Wolf_Advanced_MaxHealth; + Damage = EnemyEV.Wolf_Advanced_Damage; + XPValue = EnemyEV.Wolf_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Wolf_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Wolf_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Wolf_Advanced_DropChance; + + Speed = EnemyEV.Wolf_Advanced_Speed; + TurnSpeed = EnemyEV.Wolf_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Wolf_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Wolf_Advanced_Jump; + CooldownTime = EnemyEV.Wolf_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Wolf_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Wolf_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Wolf_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Wolf_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Wolf_Advanced_IsWeighted; + + Scale = EnemyEV.Wolf_Advanced_Scale; + ProjectileScale = EnemyEV.Wolf_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Wolf_Advanced_Tint; + + MeleeRadius = EnemyEV.Wolf_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Wolf_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Wolf_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Wolf_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + //this.MaxHealth = 999; + break; + } + } + + protected override void InitializeLogic() + { + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new LockFaceDirectionLogicAction(false)); + walkTowardsLS.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsLS.AddAction(new LockFaceDirectionLogicAction(true)); + walkTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemyWargRun_Character", true, true)); + walkTowardsLS.AddAction(new ChangePropertyLogicAction(this, "Chasing", true)); + walkTowardsLS.AddAction(new DelayLogicAction(1.0f)); + + LogicSet stopWalkLS = new LogicSet(this); + stopWalkLS.AddAction(new LockFaceDirectionLogicAction(false)); + stopWalkLS.AddAction(new MoveLogicAction(m_target, true, 0)); + stopWalkLS.AddAction(new ChangeSpriteLogicAction("EnemyWargIdle_Character", true, true)); + stopWalkLS.AddAction(new ChangePropertyLogicAction(this, "Chasing", false)); + stopWalkLS.AddAction(new DelayLogicAction(1.0f)); + + LogicSet jumpLS = new LogicSet(this); + jumpLS.AddAction(new GroundCheckLogicAction()); // Make sure it can only jump while touching ground. + jumpLS.AddAction(new LockFaceDirectionLogicAction(false)); + jumpLS.AddAction(new MoveLogicAction(m_target, true, 0)); + jumpLS.AddAction(new LockFaceDirectionLogicAction(true)); + jumpLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Wolf_Attack")); + jumpLS.AddAction(new ChangeSpriteLogicAction("EnemyWargPounce_Character", true, true)); + jumpLS.AddAction(new DelayLogicAction(PounceDelay)); + jumpLS.AddAction(new ChangeSpriteLogicAction("EnemyWargJump_Character", false, false)); + jumpLS.AddAction(new PlayAnimationLogicAction("Start", "Windup")); + jumpLS.AddAction(new MoveDirectionLogicAction()); + jumpLS.AddAction(new JumpLogicAction()); + jumpLS.AddAction(new PlayAnimationLogicAction("Attack", "End")); + jumpLS.AddAction(new GroundCheckLogicAction()); + jumpLS.AddAction(new ChangeSpriteLogicAction("EnemyWargIdle_Character", true, true)); + jumpLS.AddAction(new MoveLogicAction(m_target, true, 0)); + jumpLS.AddAction(new DelayLogicAction(PounceLandDelay)); + + + + LogicSet wolfHit = new LogicSet(this); + wolfHit.AddAction(new ChangeSpriteLogicAction("EnemyWargHit_Character", false, false)); + wolfHit.AddAction(new DelayLogicAction(0.2f)); + wolfHit.AddAction(new GroundCheckLogicAction()); + + m_generalBasicLB.AddLogicSet(walkTowardsLS, stopWalkLS, jumpLS); + m_wolfHitLB.AddLogicSet(wolfHit); + + logicBlocksToDispose.Add(m_generalBasicLB); + logicBlocksToDispose.Add(m_generalCooldownLB); + logicBlocksToDispose.Add(m_wolfHitLB); + + SetCooldownLogicBlock(m_generalCooldownLB, 40, 40, 20); //walkTowardsLS, walkAwayLS, walkStopLS + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + if (m_startDelayCounter <= 0) + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + if (m_target.Y < this.Y - m_target.Height) + RunLogicBlock(false, m_generalBasicLB, 0, 0, 100); // walkTowardsLS, stopLS, jumpLS + else + RunLogicBlock(false, m_generalBasicLB, 100, 0, 0); + break; + case (STATE_ENGAGE): + if (Chasing == false) + RunLogicBlock(false, m_generalBasicLB, 100, 0, 0); + break; + case (STATE_WANDER): + if (Chasing == true) + RunLogicBlock(false, m_generalBasicLB, 0, 100, 0); + break; + default: + break; + } + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + if (m_target.Y < this.Y - m_target.Height) + RunLogicBlock(false, m_generalBasicLB, 0, 0, 100); // walkTowardsLS, stopLS, jumpLS + else + RunLogicBlock(false, m_generalBasicLB, 100, 0, 0); + break; + case (STATE_ENGAGE): + if (Chasing == false) + RunLogicBlock(false, m_generalBasicLB, 100, 0, 0); + break; + case (STATE_WANDER): + if (Chasing == true) + RunLogicBlock(false, m_generalBasicLB, 0, 100, 0); + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + if (m_target.Y < this.Y - m_target.Height) + RunLogicBlock(false, m_generalBasicLB, 0, 0, 100); // walkTowardsLS, stopLS, jumpLS + else + RunLogicBlock(false, m_generalBasicLB, 100, 0, 0); + break; + case (STATE_ENGAGE): + if (Chasing == false) + RunLogicBlock(false, m_generalBasicLB, 100, 0, 0); + break; + case (STATE_WANDER): + if (Chasing == true) + RunLogicBlock(false, m_generalBasicLB, 0, 100, 0); + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + if (m_target.Y < this.Y - m_target.Height) + RunLogicBlock(false, m_generalBasicLB, 0, 0, 100); // walkTowardsLS, stopLS, jumpLS + else + RunLogicBlock(false, m_generalBasicLB, 100, 0, 0); + break; + case (STATE_ENGAGE): + if (Chasing == false) + RunLogicBlock(false, m_generalBasicLB, 100, 0, 0); + break; + case (STATE_WANDER): + if (Chasing == true) + RunLogicBlock(false, m_generalBasicLB, 0, 100, 0); + break; + default: + break; + } + } + + public override void Update(GameTime gameTime) + { + if (m_startDelayCounter > 0) + m_startDelayCounter -= (float)gameTime.ElapsedGameTime.TotalSeconds; + + // Maintains the enemy's speed in the air so that he can jump onto platforms. + if (m_isTouchingGround == false && IsWeighted == true && CurrentSpeed == 0 && this.SpriteName == "EnemyWargJump_Character") + this.CurrentSpeed = this.Speed; + + base.Update(gameTime); + + if (m_isTouchingGround == true && CurrentSpeed == 0 && IsAnimating == false) + { + this.ChangeSprite("EnemyWargIdle_Character"); + this.PlayAnimation(true); + } + + if (this.SpriteName == "EnemyWargRun_Character") + m_runFrameSound.Update(); + } + + public override void HitEnemy(int damage, Vector2 position, bool isPlayer) + { + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Wolf_Hit_01", "Wolf_Hit_02", "Wolf_Hit_03"); + if (m_currentActiveLB != null && m_currentActiveLB.IsActive == true) + m_currentActiveLB.StopLogicBlock(); + + m_currentActiveLB = m_wolfHitLB; + m_currentActiveLB.RunLogicBlock(100); + base.HitEnemy(damage, position, isPlayer); + } + + public override void ResetState() + { + m_startDelayCounter = m_startDelay; + base.ResetState(); + } + + public override void Reset() + { + m_startDelayCounter = m_startDelay; + base.Reset(); + } + + public EnemyObj_Wolf(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyWargIdle_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.Type = EnemyType.Wolf; + m_startDelayCounter = m_startDelay; + m_runFrameSound = new FrameSoundObj(this, 1, "Wolf_Move01", "Wolf_Move02", "Wolf_Move03"); + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Zombie.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Zombie.cs new file mode 100644 index 0000000..84f0047 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyObj_Zombie.cs @@ -0,0 +1,401 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyObj_Zombie : EnemyObj + { + private LogicBlock m_basicWalkLS = new LogicBlock(); + private LogicBlock m_basicRiseLowerLS = new LogicBlock(); + + public bool Risen { get; set; } + public bool Lowered { get; set; } + + protected override void InitializeEV() + { + #region Basic Variables - General + Name = EnemyEV.Zombie_Basic_Name; + LocStringID = EnemyEV.Zombie_Basic_Name_locID; + + MaxHealth = EnemyEV.Zombie_Basic_MaxHealth; + Damage = EnemyEV.Zombie_Basic_Damage; + XPValue = EnemyEV.Zombie_Basic_XPValue; + + MinMoneyDropAmount = EnemyEV.Zombie_Basic_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Zombie_Basic_MaxDropAmount; + MoneyDropChance = EnemyEV.Zombie_Basic_DropChance; + + Speed = EnemyEV.Zombie_Basic_Speed; + TurnSpeed = EnemyEV.Zombie_Basic_TurnSpeed; + ProjectileSpeed = EnemyEV.Zombie_Basic_ProjectileSpeed; + JumpHeight = EnemyEV.Zombie_Basic_Jump; + CooldownTime = EnemyEV.Zombie_Basic_Cooldown; + AnimationDelay = 1 / EnemyEV.Zombie_Basic_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Zombie_Basic_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Zombie_Basic_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Zombie_Basic_CanBeKnockedBack; + IsWeighted = EnemyEV.Zombie_Basic_IsWeighted; + + Scale = EnemyEV.Zombie_Basic_Scale; + ProjectileScale = EnemyEV.Zombie_Basic_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Zombie_Basic_Tint; + + MeleeRadius = EnemyEV.Zombie_Basic_MeleeRadius; + ProjectileRadius = EnemyEV.Zombie_Basic_ProjectileRadius; + EngageRadius = EnemyEV.Zombie_Basic_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Zombie_Basic_KnockBack; + #endregion + + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + + #region Miniboss Variables - General + Name = EnemyEV.Zombie_Miniboss_Name; + LocStringID = EnemyEV.Zombie_Miniboss_Name_locID; + + MaxHealth = EnemyEV.Zombie_Miniboss_MaxHealth; + Damage = EnemyEV.Zombie_Miniboss_Damage; + XPValue = EnemyEV.Zombie_Miniboss_XPValue; + + MinMoneyDropAmount = EnemyEV.Zombie_Miniboss_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Zombie_Miniboss_MaxDropAmount; + MoneyDropChance = EnemyEV.Zombie_Miniboss_DropChance; + + Speed = EnemyEV.Zombie_Miniboss_Speed; + TurnSpeed = EnemyEV.Zombie_Miniboss_TurnSpeed; + ProjectileSpeed = EnemyEV.Zombie_Miniboss_ProjectileSpeed; + JumpHeight = EnemyEV.Zombie_Miniboss_Jump; + CooldownTime = EnemyEV.Zombie_Miniboss_Cooldown; + AnimationDelay = 1 / EnemyEV.Zombie_Miniboss_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Zombie_Miniboss_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Zombie_Miniboss_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Zombie_Miniboss_CanBeKnockedBack; + IsWeighted = EnemyEV.Zombie_Miniboss_IsWeighted; + + Scale = EnemyEV.Zombie_Miniboss_Scale; + ProjectileScale = EnemyEV.Zombie_Miniboss_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Zombie_Miniboss_Tint; + + MeleeRadius = EnemyEV.Zombie_Miniboss_MeleeRadius; + ProjectileRadius = EnemyEV.Zombie_Miniboss_ProjectileRadius; + EngageRadius = EnemyEV.Zombie_Miniboss_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Zombie_Miniboss_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.EXPERT): + + #region Expert Variables - General + Name = EnemyEV.Zombie_Expert_Name; + LocStringID = EnemyEV.Zombie_Expert_Name_locID; + + MaxHealth = EnemyEV.Zombie_Expert_MaxHealth; + Damage = EnemyEV.Zombie_Expert_Damage; + XPValue = EnemyEV.Zombie_Expert_XPValue; + + MinMoneyDropAmount = EnemyEV.Zombie_Expert_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Zombie_Expert_MaxDropAmount; + MoneyDropChance = EnemyEV.Zombie_Expert_DropChance; + + Speed = EnemyEV.Zombie_Expert_Speed; + TurnSpeed = EnemyEV.Zombie_Expert_TurnSpeed; + ProjectileSpeed = EnemyEV.Zombie_Expert_ProjectileSpeed; + JumpHeight = EnemyEV.Zombie_Expert_Jump; + CooldownTime = EnemyEV.Zombie_Expert_Cooldown; + AnimationDelay = 1 / EnemyEV.Zombie_Expert_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Zombie_Expert_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Zombie_Expert_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Zombie_Expert_CanBeKnockedBack; + IsWeighted = EnemyEV.Zombie_Expert_IsWeighted; + + Scale = EnemyEV.Zombie_Expert_Scale; + ProjectileScale = EnemyEV.Zombie_Expert_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Zombie_Expert_Tint; + + MeleeRadius = EnemyEV.Zombie_Expert_MeleeRadius; + ProjectileRadius = EnemyEV.Zombie_Expert_ProjectileRadius; + EngageRadius = EnemyEV.Zombie_Expert_EngageRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Zombie_Expert_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.ADVANCED): + + #region Advanced Variables - General + Name = EnemyEV.Zombie_Advanced_Name; + LocStringID = EnemyEV.Zombie_Advanced_Name_locID; + + MaxHealth = EnemyEV.Zombie_Advanced_MaxHealth; + Damage = EnemyEV.Zombie_Advanced_Damage; + XPValue = EnemyEV.Zombie_Advanced_XPValue; + + MinMoneyDropAmount = EnemyEV.Zombie_Advanced_MinDropAmount; + MaxMoneyDropAmount = EnemyEV.Zombie_Advanced_MaxDropAmount; + MoneyDropChance = EnemyEV.Zombie_Advanced_DropChance; + + Speed = EnemyEV.Zombie_Advanced_Speed; + TurnSpeed = EnemyEV.Zombie_Advanced_TurnSpeed; + ProjectileSpeed = EnemyEV.Zombie_Advanced_ProjectileSpeed; + JumpHeight = EnemyEV.Zombie_Advanced_Jump; + CooldownTime = EnemyEV.Zombie_Advanced_Cooldown; + AnimationDelay = 1 / EnemyEV.Zombie_Advanced_AnimationDelay; + + AlwaysFaceTarget = EnemyEV.Zombie_Advanced_AlwaysFaceTarget; + CanFallOffLedges = EnemyEV.Zombie_Advanced_CanFallOffLedges; + CanBeKnockedBack = EnemyEV.Zombie_Advanced_CanBeKnockedBack; + IsWeighted = EnemyEV.Zombie_Advanced_IsWeighted; + + Scale = EnemyEV.Zombie_Advanced_Scale; + ProjectileScale = EnemyEV.Zombie_Advanced_ProjectileScale; + TintablePart.TextureColor = EnemyEV.Zombie_Advanced_Tint; + + MeleeRadius = EnemyEV.Zombie_Advanced_MeleeRadius; + EngageRadius = EnemyEV.Zombie_Advanced_EngageRadius; + ProjectileRadius = EnemyEV.Zombie_Advanced_ProjectileRadius; + + ProjectileDamage = Damage; + KnockBack = EnemyEV.Zombie_Advanced_KnockBack; + #endregion + break; + + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + } + + protected override void InitializeLogic() + { + LogicSet walkTowardsLS = new LogicSet(this); + walkTowardsLS.AddAction(new LockFaceDirectionLogicAction(false)); + walkTowardsLS.AddAction(new ChangeSpriteLogicAction("EnemyZombieWalk_Character", true, true)); + walkTowardsLS.AddAction(new MoveLogicAction(m_target, true)); + walkTowardsLS.AddAction(new LockFaceDirectionLogicAction(true)); + walkTowardsLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Zombie_Groan_01", "Zombie_Groan_02", "Zombie_Groan_03", "Blank", "Blank", "Blank", "Blank", "Blank")); + walkTowardsLS.AddAction(new DelayLogicAction(0.5f)); + + LogicSet riseLS = new LogicSet(this); + riseLS.AddAction(new LockFaceDirectionLogicAction(false)); + riseLS.AddAction(new MoveLogicAction(m_target, false, 0)); + //riseLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / m_Rise_Animation_Speed)); + riseLS.AddAction(new ChangeSpriteLogicAction("EnemyZombieRise_Character", false, false)); + riseLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Zombie_Rise")); + riseLS.AddAction(new PlayAnimationLogicAction(false)); + //riseLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", 1 / 14)); + riseLS.AddAction(new ChangePropertyLogicAction(this, "Risen", true)); + riseLS.AddAction(new ChangePropertyLogicAction(this, "Lowered", false)); + + LogicSet lowerLS = new LogicSet(this); + lowerLS.AddAction(new LockFaceDirectionLogicAction(false)); + lowerLS.AddAction(new MoveLogicAction(m_target, false, 0)); + lowerLS.AddAction(new ChangeSpriteLogicAction("EnemyZombieLower_Character", false, false)); + lowerLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Zombie_Lower")); + lowerLS.AddAction(new PlayAnimationLogicAction(false)); + lowerLS.AddAction(new ChangePropertyLogicAction(this, "Risen", false)); + lowerLS.AddAction(new ChangePropertyLogicAction(this, "Lowered", true)); + + m_basicWalkLS.AddLogicSet(walkTowardsLS); + m_basicRiseLowerLS.AddLogicSet(riseLS, lowerLS); + + logicBlocksToDispose.Add(m_basicWalkLS); + logicBlocksToDispose.Add(m_basicRiseLowerLS); + + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + if (this.Risen == false) + RunLogicBlock(false, m_basicRiseLowerLS, 100, 0); + else + RunLogicBlock(false, m_basicWalkLS, 100); // walkTowardsLS + //if (Math.Abs(this.Y - m_target.Y) < 100) // Ensures the zombie doesn't appear if the player is above or below him. + //{ + // if (this.Risen == false) + // RunLogicBlock(false, m_basicRiseLowerLS, 100, 0); + // else + // RunLogicBlock(false, m_basicWalkLS, 100); // walkTowardsLS + //} + //else if (m_target.IsTouchingGround == true) + //{ + // if (this.Lowered == false) + // RunLogicBlock(false, m_basicRiseLowerLS, 0, 100); // riseLS, lowerLS + //} + break; + case (STATE_WANDER): + if (this.Lowered == false) + RunLogicBlock(false, m_basicRiseLowerLS, 0, 100); // riseLS, lowerLS + break; + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + if (this.Risen == false) + RunLogicBlock(false, m_basicRiseLowerLS, 100, 0); + else + RunLogicBlock(false, m_basicWalkLS, 100); // walkTowardsLS + //if (Math.Abs(this.Y - m_target.Y) < 100) // Ensures the zombie doesn't appear if the player is above or below him. + //{ + // if (this.Risen == false) + // RunLogicBlock(false, m_basicRiseLowerLS, 100, 0); + // else + // RunLogicBlock(false, m_basicWalkLS, 100); // walkTowardsLS + //} + //else if (m_target.IsTouchingGround == true) + //{ + // if (this.Lowered == false) + // RunLogicBlock(false, m_basicRiseLowerLS, 0, 100); // riseLS, lowerLS + //} + break; + case (STATE_WANDER): + if (this.Lowered == false) + RunLogicBlock(false, m_basicRiseLowerLS, 0, 100); // riseLS, lowerLS + break; + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + if (this.Risen == false) + RunLogicBlock(false, m_basicRiseLowerLS, 100, 0); + else + RunLogicBlock(false, m_basicWalkLS, 100); // walkTowardsLS + //if (Math.Abs(this.Y - m_target.Y) < 100) // Ensures the zombie doesn't appear if the player is above or below him. + //{ + // if (this.Risen == false) + // RunLogicBlock(false, m_basicRiseLowerLS, 100, 0); + // else + // RunLogicBlock(false, m_basicWalkLS, 100); // walkTowardsLS + //} + //else if (m_target.IsTouchingGround == true) + //{ + // if (this.Lowered == false) + // RunLogicBlock(false, m_basicRiseLowerLS, 0, 100); // riseLS, lowerLS + //} + break; + case (STATE_WANDER): + if (this.Lowered == false) + RunLogicBlock(false, m_basicRiseLowerLS, 0, 100); // riseLS, lowerLS + break; + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + if (this.Risen == false) + RunLogicBlock(false, m_basicRiseLowerLS, 100, 0); + else + RunLogicBlock(false, m_basicWalkLS, 100); // walkTowardsLS + //if (Math.Abs(this.Y - m_target.Y) < 100) // Ensures the zombie doesn't appear if the player is above or below him. + //{ + // if (this.Risen == false) + // RunLogicBlock(false, m_basicRiseLowerLS, 100, 0); + // else + // RunLogicBlock(false, m_basicWalkLS, 100); // walkTowardsLS + //} + //else if (m_target.IsTouchingGround == true) + //{ + // if (this.Lowered == false) + // RunLogicBlock(false, m_basicRiseLowerLS, 0, 100); // riseLS, lowerLS + //} + break; + case (STATE_WANDER): + if (this.Lowered == false) + RunLogicBlock(false, m_basicRiseLowerLS, 0, 100); // riseLS, lowerLS + break; + default: + break; + } + } + + public override void HitEnemy(int damage, Vector2 position, bool isPlayer) + { + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Zombie_Hit"); + base.HitEnemy(damage, position, isPlayer); + } + + public override void Update(GameTime gameTime) + { + // Hack to stop zombies in the ground from animating. I don't know why zombies keep animating. + if ((m_currentActiveLB == null || m_currentActiveLB.IsActive == false) && this.Risen == false && this.IsAnimating == true) + { + this.ChangeSprite("EnemyZombieRise_Character"); + this.StopAnimation(); + } + + base.Update(gameTime); + } + + public override void ResetState() + { + Lowered = true; + Risen = false; + base.ResetState(); + + this.ChangeSprite("EnemyZombieLower_Character"); + this.GoToFrame(this.TotalFrames); + this.StopAnimation(); + } + + public override void Reset() + { + this.ChangeSprite("EnemyZombieRise_Character"); + this.StopAnimation(); + Lowered = true; + Risen = false; + base.Reset(); + } + + public EnemyObj_Zombie(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemyZombieLower_Character", target, physicsManager, levelToAttachTo, difficulty) + { + this.GoToFrame(this.TotalFrames); + Lowered = true; + this.ForceDraw = true; + this.StopAnimation(); + this.Type = EnemyType.Zombie; + this.PlayAnimationOnRestart = false; + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyObjs/EnemyTemplate.cs b/RogueCastle/src/Game Objects/EnemyObjs/EnemyTemplate.cs new file mode 100644 index 0000000..309e731 --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyObjs/EnemyTemplate.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnemyTemplate : EnemyObj + { + protected override void InitializeEV() + { + switch (Difficulty) + { + case (GameTypes.EnemyDifficulty.MINIBOSS): + case (GameTypes.EnemyDifficulty.EXPERT): + case (GameTypes.EnemyDifficulty.ADVANCED): + case (GameTypes.EnemyDifficulty.BASIC): + default: + break; + } + } + + protected override void InitializeLogic() + { + base.InitializeLogic(); + } + + protected override void RunBasicLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunAdvancedLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunExpertLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + protected override void RunMinibossLogic() + { + switch (State) + { + case (STATE_MELEE_ENGAGE): + case (STATE_PROJECTILE_ENGAGE): + case (STATE_ENGAGE): + case (STATE_WANDER): + default: + break; + } + } + + public EnemyTemplate(PlayerObj target, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, GameTypes.EnemyDifficulty difficulty) + : base("EnemySpriteNameGoesHere", target, physicsManager, levelToAttachTo, difficulty) + { + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyOrbObj.cs b/RogueCastle/src/Game Objects/EnemyOrbObj.cs new file mode 100644 index 0000000..244919b --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyOrbObj.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; + +namespace RogueCastle +{ + public class EnemyOrbObj : GameObj + { + public int OrbType = 0; + public bool ForceFlying { get; set; } + + protected override GameObj CreateCloneInstance() + { + return new EnemyOrbObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + EnemyOrbObj clone = obj as EnemyOrbObj; + clone.OrbType = this.OrbType; + clone.ForceFlying = this.ForceFlying; + } + } +} diff --git a/RogueCastle/src/Game Objects/EnemyTagObj.cs b/RogueCastle/src/Game Objects/EnemyTagObj.cs new file mode 100644 index 0000000..1c4b01d --- /dev/null +++ b/RogueCastle/src/Game Objects/EnemyTagObj.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; + +namespace RogueCastle +{ + // Represent a tag that tells the game where enemies should be placed once they are procedurally added to a level. + public class EnemyTagObj : GameObj + { + public string EnemyType { get; set; } + + protected override GameObj CreateCloneInstance() + { + return new EnemyTagObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + EnemyTagObj clone = obj as EnemyTagObj; + clone.EnemyType = this.EnemyType; + } + } +} diff --git a/RogueCastle/src/Game Objects/EnergonProjectileObj.cs b/RogueCastle/src/Game Objects/EnergonProjectileObj.cs new file mode 100644 index 0000000..b21ebbd --- /dev/null +++ b/RogueCastle/src/Game Objects/EnergonProjectileObj.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EnergonProjectileObj : ProjectileObj + { + private const byte TYPE_SWORD = 0; + private const byte TYPE_SHIELD = 1; + private const byte TYPE_DOWNSWORD = 2; + private byte m_currentAttackType = TYPE_SWORD; + + private bool m_canHitEnemy = false; + private EnemyObj_Energon m_parent; + + public EnergonProjectileObj(string spriteName, EnemyObj_Energon parent) + : base(spriteName) + { + this.TurnSpeed = 1; + this.IsWeighted = false; + m_parent = parent; + this.ChaseTarget = true; + } + + public void SetType(byte type) + { + m_currentAttackType = type; + switch (type) + { + case (TYPE_SWORD): + this.ChangeSprite("EnergonSwordProjectile_Sprite"); + break; + case (TYPE_SHIELD): + this.ChangeSprite("EnergonShieldProjectile_Sprite"); + break; + case (TYPE_DOWNSWORD): + this.ChangeSprite("EnergonDownSwordProjectile_Sprite"); + break; + } + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + PlayerObj player = otherBox.AbsParent as PlayerObj; + if (player != null && m_canHitEnemy == false) + { + if ((this.AttackType == TYPE_SWORD && otherBox.Type == Consts.WEAPON_HITBOX && player.IsAirAttacking == false) || + (this.AttackType == TYPE_SHIELD && otherBox.Type == Consts.BODY_HITBOX && player.State == PlayerObj.STATE_BLOCKING) || + (this.AttackType == TYPE_DOWNSWORD && otherBox.Type == Consts.WEAPON_HITBOX && player.IsAirAttacking == true)) + { + Target = m_parent; + this.CollisionTypeTag = GameTypes.CollisionType_PLAYER; + this.CurrentSpeed *= 2; + player.AttachedLevel.ImpactEffectPool.DisplayEnemyImpactEffect(this.Position); + } + else if (otherBox.Type == Consts.BODY_HITBOX) + m_parent.DestroyProjectile(this); + } + else + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_parent = null; + base.Dispose(); + } + } + + private void TurnToFace(Vector2 facePosition, float turnSpeed) + { + float x = facePosition.X - this.Position.X; + float y = facePosition.Y - this.Position.Y; + + float desiredAngle = (float)Math.Atan2(y, x); + float difference = MathHelper.WrapAngle(desiredAngle - this.Orientation); + + difference = MathHelper.Clamp(difference, -turnSpeed, turnSpeed); + this.Orientation = MathHelper.WrapAngle(this.Orientation + difference); + } + + public byte AttackType + { + get { return m_currentAttackType; } + } + } +} diff --git a/RogueCastle/src/Game Objects/FairyChestObj.cs b/RogueCastle/src/Game Objects/FairyChestObj.cs new file mode 100644 index 0000000..8daa5ee --- /dev/null +++ b/RogueCastle/src/Game Objects/FairyChestObj.cs @@ -0,0 +1,264 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class FairyChestObj : ChestObj + { + public int State { get; internal set; } + private SpriteObj m_lockSprite; + private SpriteObj m_errorSprite; + private int m_conditionType = 0; + private PlayerObj m_player; + + private const float SparkleDelay = 1; + private float m_sparkleCounter = SparkleDelay; + private TextObj m_timerText; + + public float Timer { get; set; } + + public FairyChestObj(PhysicsManager physicsManager) + : base(physicsManager) + { + m_lockSprite = new SpriteObj("Chest4Unlock_Sprite"); + m_errorSprite = new SpriteObj("CancelIcon_Sprite"); + m_errorSprite.Visible = false; + + m_timerText = new TextObj(Game.JunicodeFont); + m_timerText.FontSize = 18; + m_timerText.DropShadow = new Vector2(2, 2); + m_timerText.Align = Types.TextAlign.Centre; + + m_player = Game.ScreenManager.Player; + } + + public void SetConditionType(int conditionType = 0) + { + if (conditionType != 0) + m_conditionType = conditionType; + else + int.TryParse(Tag, out m_conditionType); + + if (m_conditionType == ChestConditionType.ReachIn5Seconds) + Timer = 5; + } + + public void SetChestUnlocked() + { + if (ConditionType != ChestConditionType.InvisibleChest && ConditionType != ChestConditionType.None) + m_player.AttachedLevel.ObjectiveComplete(); + + State = ChestConditionChecker.STATE_FREE; + m_lockSprite.PlayAnimation(false); + Tweener.Tween.By(m_lockSprite, 0.2f, Tweener.Ease.Linear.EaseNone, "Y", "40"); + Tweener.Tween.To(m_lockSprite, 0.2f, Tweener.Ease.Linear.EaseNone,"delay", "0.1", "Opacity", "0"); + } + + public void SetChestFailed(bool skipTween = false) + { + if (skipTween == false) + m_player.AttachedLevel.ObjectiveFailed(); + State = ChestConditionChecker.STATE_FAILED; + this.m_errorSprite.Visible = true; + this.m_errorSprite.Opacity = 0f; + m_errorSprite.Scale = Vector2.One; + m_errorSprite.Position = new Vector2(this.X, this.Y - this.Height / 2); + + if (skipTween == false) + { + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"FairyChest_Fail"); + Tweener.Tween.To(m_errorSprite, 0.5f, Tweener.Ease.Quad.EaseIn, "ScaleX", "0.5", "ScaleY", "0.5", "Opacity", "1"); + } + else + { + m_errorSprite.Scale = new Vector2(0.5f, 0.5f); + m_errorSprite.Opacity = 1; + } + } + + public override void OpenChest(ItemDropManager itemDropManager, PlayerObj player) + { + if (State == ChestConditionChecker.STATE_FREE) + { + if (IsOpen == false && IsLocked == false) + { + this.GoToFrame(2); + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Chest_Open_Large"); + // Give gold if all runes have been found + if (Game.PlayerStats.TotalRunesFound >= EquipmentCategoryType.Total * EquipmentAbilityType.Total) + { + GiveStatDrop(itemDropManager, m_player, 1, 0); + player.AttachedLevel.RefreshMapChestIcons(); + } + else + { + List runeArray = Game.PlayerStats.GetRuneArray; + List possibleRunes = new List(); + + int categoryCounter = 0; + foreach (byte[] itemArray in runeArray) + { + int itemCounter = 0; + foreach (byte itemState in itemArray) + { + if (itemState == EquipmentState.NotFound) + possibleRunes.Add(new Vector2(categoryCounter, itemCounter)); + itemCounter++; + } + categoryCounter++; + } + + if (possibleRunes.Count > 0) + { + Vector2 chosenRune = possibleRunes[CDGMath.RandomInt(0, possibleRunes.Count - 1)]; + Game.PlayerStats.GetRuneArray[(int)chosenRune.X][(int)chosenRune.Y] = EquipmentState.FoundButNotSeen; + List objectList = new List(); + objectList.Add(new Vector2(this.X, this.Y - this.Height / 2f)); + objectList.Add(GetItemType.Rune); + objectList.Add(new Vector2(chosenRune.X, chosenRune.Y)); + + (player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.GetItem, true, objectList); + player.RunGetItemAnimation(); + + Console.WriteLine("Unlocked item index " + chosenRune.X + " of type " + chosenRune.Y); + } + else + GiveGold(itemDropManager); + + player.AttachedLevel.RefreshMapChestIcons(); + } + } + //base.OpenChest(itemDropManager, player); // Regular chest opening logic. + } + } + + public override void Draw(Camera2D camera) + { + if (this.State == ChestConditionChecker.STATE_LOCKED) + ChestConditionChecker.SetConditionState(this, m_player); + + if (this.IsOpen == false) + { + // Adds the chest sparkle effect. + if (Game.ScreenManager.CurrentScreen is ProceduralLevelScreen) // Only sparkle the chest if the game is playing. Otherwise it's probably paused. + { + if (m_sparkleCounter > 0) + { + m_sparkleCounter -= (float)camera.GameTime.ElapsedGameTime.TotalSeconds; + if (m_sparkleCounter <= 0) + { + m_sparkleCounter = SparkleDelay; + float delay = 0; + for (int i = 0; i < 2; i++) + { + Tweener.Tween.To(this, delay, Tweener.Ease.Linear.EaseNone); + Tweener.Tween.AddEndHandlerToLastTween(m_player.AttachedLevel.ImpactEffectPool, "DisplayChestSparkleEffect", new Vector2(this.X, this.Y - this.Height / 2)); + delay += 1 / 2f; + } + } + } + } + + if (ConditionType == ChestConditionType.ReachIn5Seconds && this.State == ChestConditionChecker.STATE_LOCKED) + { + if (m_player.AttachedLevel.IsPaused == false) + Timer -= (float)camera.GameTime.ElapsedGameTime.TotalSeconds; + m_timerText.Position = new Vector2(this.Position.X, this.Y - 50); + m_timerText.Text = ((int)Timer + 1).ToString(); + m_timerText.Draw(camera); + + // TODO: does this need to be refreshed on language change? + m_player.AttachedLevel.UpdateObjectiveProgress( + (LocaleBuilder.getResourceString(DialogueManager.GetText("Chest_Locked " + this.ConditionType).Dialogue[0]) + (int)(Timer + 1)).ToString() + ); + } + } + + if (ConditionType != ChestConditionType.InvisibleChest || IsOpen == true) + { + base.Draw(camera); + m_lockSprite.Flip = this.Flip; + if (this.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.None) + m_lockSprite.Position = new Vector2(this.X - 10, this.Y - this.Height / 2); + else + m_lockSprite.Position = new Vector2(this.X + 10, this.Y - this.Height / 2); + + m_lockSprite.Draw(camera); + + m_errorSprite.Position = new Vector2(this.X, this.Y - this.Height / 2); + m_errorSprite.Draw(camera); + } + + //base.Draw(camera); + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + if (this.State == ChestConditionChecker.STATE_FREE) + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + public override void ForceOpen() + { + this.State = ChestConditionChecker.STATE_FREE; + m_errorSprite.Visible = false; + m_lockSprite.Visible = false; + base.ForceOpen(); + } + + public override void ResetChest() + { + this.State = ChestConditionChecker.STATE_LOCKED; + m_errorSprite.Visible = false; + m_lockSprite.Visible = true; + m_lockSprite.Opacity = 1; + this.Opacity = 1; + m_lockSprite.PlayAnimation(1, 1, false); + this.TextureColor = Color.White; + + if (ConditionType == ChestConditionType.ReachIn5Seconds) + Timer = 5; + + base.ResetChest(); + } + + protected override GameObj CreateCloneInstance() + { + return new FairyChestObj(PhysicsMngr); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + FairyChestObj clone = obj as FairyChestObj; + clone.State = this.State; + SetConditionType(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_player = null; + m_lockSprite.Dispose(); + m_lockSprite = null; + m_errorSprite.Dispose(); + m_errorSprite = null; + m_timerText.Dispose(); + m_timerText = null; + base.Dispose(); + } + } + + public int ConditionType + { + get { return m_conditionType; } + } + } +} diff --git a/RogueCastle/src/Game Objects/HazardObj.cs b/RogueCastle/src/Game Objects/HazardObj.cs new file mode 100644 index 0000000..f5f2463 --- /dev/null +++ b/RogueCastle/src/Game Objects/HazardObj.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class HazardObj : PhysicsObj, IDealsDamageObj + { + //public int Damage { get; internal set; } + + private Texture2D m_texture; + + public HazardObj(int width, int height) + : base("Spikes_Sprite", null) + { + this.IsWeighted = false; + this.IsCollidable = true; + CollisionTypeTag = GameTypes.CollisionType_GLOBAL_DAMAGE_WALL; //GameTypes.CollisionType_ENEMYWALL; + //Damage = 25;//10; + this.DisableHitboxUpdating = true; + } + + public void InitializeTextures(Camera2D camera) + { + Vector2 scaleMod = new Vector2(60 / (float)_width, 60 / (float)_height); + _width = (int)(_width * scaleMod.X); + _height = (int)(_height * scaleMod.Y); + + m_texture = this.ConvertToTexture(camera); + _width = (int)Math.Ceiling(_width / scaleMod.X); + _height = (int)Math.Ceiling(_height / scaleMod.Y); + + this.Scale = new Vector2((_width / ((_width/60f) * 64)), 1); + } + + public void SetWidth(int width) + { + //m_actualWidth = width; + _width = width; + foreach (CollisionBox box in CollisionBoxes) + { + if (box.Type == Consts.TERRAIN_HITBOX) + box.Width = _width - 25; + else + box.Width = _width; + } + } + + public void SetHeight(int height) + { + //m_actualHeight = height; + _height = height; + } + + public override void Draw(Camera2D camera) + { + camera.Draw(m_texture, this.Position, new Rectangle(0, 0, (int)((Width / 60f) * 64),(int)( Height)), this.TextureColor, MathHelper.ToRadians(Rotation), Vector2.Zero, this.Scale, SpriteEffects.None, 1); + } + + protected override GameObj CreateCloneInstance() + { + return new HazardObj(_width, _height); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + HazardObj clone = obj as HazardObj; + clone.SetWidth(Width); + clone.SetHeight(Height); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_texture.Dispose(); + m_texture = null; + base.Dispose(); + } + } + + public override void PopulateFromXMLReader(System.Xml.XmlReader reader, System.Globalization.CultureInfo ci) + { + base.PopulateFromXMLReader(reader, ci); + + this.SetWidth(_width); + this.SetHeight(_height); + } + + public override int Width + { + get { return _width; } + } + + public override int Height + { + get { return _height; } + } + + public override Rectangle TerrainBounds + { + get + { + foreach (CollisionBox box in this.CollisionBoxes) + { + if (box.Type == Consts.TERRAIN_HITBOX) + return box.AbsRect; + } + return this.Bounds; + } + } + + public int Damage + { + get + { + PlayerObj player = Game.ScreenManager.Player; + //int playerHealth = (int)Math.Round(((player.BaseHealth + player.GetEquipmentHealth() + + // (Game.PlayerStats.BonusHealth * GameEV.ITEM_STAT_MAXHP_AMOUNT) + + // SkillSystem.GetSkill(SkillType.Health_Up).ModifierAmount + + // SkillSystem.GetSkill(SkillType.Health_Up_Final).ModifierAmount) * Game.PlayerStats.LichHealthMod), MidpointRounding.AwayFromZero) + Game.PlayerStats.LichHealth; + + int playerHealth = (int)Math.Round(((player.BaseHealth + player.GetEquipmentHealth() + + (Game.PlayerStats.BonusHealth * GameEV.ITEM_STAT_MAXHP_AMOUNT) + + SkillSystem.GetSkill(SkillType.Health_Up).ModifierAmount + + SkillSystem.GetSkill(SkillType.Health_Up_Final).ModifierAmount)), MidpointRounding.AwayFromZero); + + int damage = (int)(playerHealth * GameEV.HAZARD_DAMAGE_PERCENT); + + if (damage < 1) + damage = 1; + return damage; + } + } + } + +} diff --git a/RogueCastle/src/Game Objects/HoverObj.cs b/RogueCastle/src/Game Objects/HoverObj.cs new file mode 100644 index 0000000..eb21d2c --- /dev/null +++ b/RogueCastle/src/Game Objects/HoverObj.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class HoverObj : SpriteObj + { + private Vector2 m_startPos; + public float HoverSpeed = 1; + public float Amplitude = 1; + + public HoverObj(string spriteName) + : base(spriteName) + { + } + + public void SetStartingPos(Vector2 pos) + { + m_startPos = pos; + } + + public override void Draw(Camera2D camera) + { + this.Y = m_startPos.Y + (float)Math.Sin(Game.TotalGameTime * HoverSpeed) * Amplitude; + base.Draw(camera); + } + + protected override GameObj CreateCloneInstance() + { + return new HoverObj(this.SpriteName); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + HoverObj clone = obj as HoverObj; + clone.HoverSpeed = this.HoverSpeed; + clone.Amplitude = this.Amplitude; + clone.SetStartingPos(m_startPos); + } + } +} diff --git a/RogueCastle/src/Game Objects/IDealsDamageObj.cs b/RogueCastle/src/Game Objects/IDealsDamageObj.cs new file mode 100644 index 0000000..c8bdff5 --- /dev/null +++ b/RogueCastle/src/Game Objects/IDealsDamageObj.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + public interface IDealsDamageObj + { + int Damage { get; } + } +} diff --git a/RogueCastle/src/Game Objects/ItemDropObj.cs b/RogueCastle/src/Game Objects/ItemDropObj.cs new file mode 100644 index 0000000..5619064 --- /dev/null +++ b/RogueCastle/src/Game Objects/ItemDropObj.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class ItemDropObj : PhysicsObj + { + public int DropType = ItemDropType.None; + private float m_amount = 0; + public float CollectionCounter { get; set; } + + public ItemDropObj(string spriteName) + : base(spriteName) + { + this.IsCollidable = true; + this.IsWeighted = true; + this.CollisionTypeTag = GameTypes.CollisionType_ENEMY; + this.StopAnimation(); + this.OutlineWidth = 2; + } + + public void ConvertDrop(int dropType, float amount) + { + this.Scale = new Vector2(1); + this.TextureColor = Color.White; + + switch (dropType) + { + case (ItemDropType.Health): + this.ChangeSprite("ChickenLeg_Sprite"); + this.PlayAnimation(true); + break; + case (ItemDropType.Mana): + this.ChangeSprite("ManaPotion_Sprite"); + this.PlayAnimation(true); + break; + case(ItemDropType.BigDiamond): + this.Scale = new Vector2(1.5f); + this.TextureColor = Color.LightGreen; + this.ChangeSprite("Diamond_Sprite"); + this.PlayAnimation(true); + break; + case (ItemDropType.Diamond): + this.ChangeSprite("Diamond_Sprite"); + this.PlayAnimation(true); + break; + case (ItemDropType.MoneyBag): + this.ChangeSprite("MoneyBag_Sprite"); + this.PlayAnimation(1, 1, false); + break; + case (ItemDropType.Stat_Strength): + this.ChangeSprite("Sword_Sprite"); + this.PlayAnimation(true); + break; + case(ItemDropType.Stat_Defense): + this.ChangeSprite("Shield_Sprite"); + this.PlayAnimation(true); + break; + case(ItemDropType.Stat_Weight): + this.ChangeSprite("Backpack_Sprite"); + this.PlayAnimation(true); + break; + case (ItemDropType.Stat_MaxMana): + this.ChangeSprite("Heart_Sprite"); + this.PlayAnimation(true); + this.TextureColor = Color.Blue; + break; + case (ItemDropType.Stat_MaxHealth): + this.ChangeSprite("Heart_Sprite"); + this.PlayAnimation(true); + break; + case (ItemDropType.Coin): + default: + this.ChangeSprite("Coin_Sprite"); + this.PlayAnimation(true); + break; + } + + this.DropType = dropType; + m_amount = amount; + this.ClearCollisionBoxes(); + this.AddCollisionBox(0, 0, this.Width, this.Height, Consts.TERRAIN_HITBOX); + } + + public void GiveReward(PlayerObj player, TextManager textManager) + { + switch (DropType) + { + case (ItemDropType.Coin): + case (ItemDropType.Diamond): + case(ItemDropType.BigDiamond): + case (ItemDropType.MoneyBag): + player.AttachedLevel.ItemDropCollected(DropType); + + float castleLockGoldModifier = 1; + if (Game.PlayerStats.HasArchitectFee == true) + castleLockGoldModifier = GameEV.ARCHITECT_FEE; + int goldAmount = (int)Math.Round(m_amount * (1 + player.TotalGoldBonus) * castleLockGoldModifier, MidpointRounding.AwayFromZero); + Game.PlayerStats.Gold += goldAmount; + textManager.DisplayNumberStringText(goldAmount, "LOC_ID_ITEM_DROP_OBJ_1" /*"gold"*/, Color.Yellow, new Vector2(this.X, this.Bounds.Top)); + if (DropType == ItemDropType.MoneyBag) + this.PlayAnimation(1, 1, false); + break; + case (ItemDropType.Health): + int healthAmount = (int)(player.MaxHealth * (m_amount + SkillSystem.GetSkill(SkillType.Potion_Up).ModifierAmount)); + player.CurrentHealth += healthAmount; + textManager.DisplayNumberStringText(healthAmount, "LOC_ID_ITEM_DROP_OBJ_2" /*"hp recovered"*/, Color.LawnGreen, new Vector2(this.X, this.Bounds.Top)); + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Collect_Health"); + break; + case (ItemDropType.Mana): + int manaAmount = (int)(player.MaxMana * (m_amount + SkillSystem.GetSkill(SkillType.Potion_Up).ModifierAmount)); + player.CurrentMana += manaAmount; + textManager.DisplayNumberStringText(manaAmount, "LOC_ID_ITEM_DROP_OBJ_3" /*"mp recovered"*/, Color.LawnGreen, new Vector2(this.X, this.Bounds.Top)); + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Collect_Mana"); + break; + case (ItemDropType.Stat_Defense): + Game.PlayerStats.BonusDefense += 1 + Game.PlayerStats.TimesCastleBeaten; + textManager.DisplayStringNumberText("LOC_ID_ITEM_DROP_OBJ_4" /*"Armor Up"*/, GameEV.ITEM_STAT_ARMOR_AMOUNT * (1 + Game.PlayerStats.TimesCastleBeaten), Color.LightSteelBlue, new Vector2(this.X, this.Bounds.Top)); + break; + case (ItemDropType.Stat_MaxHealth): + Game.PlayerStats.BonusHealth += 1 + Game.PlayerStats.TimesCastleBeaten; + textManager.DisplayStringNumberText("LOC_ID_ITEM_DROP_OBJ_5" /*"Max Health Up"*/, GameEV.ITEM_STAT_MAXHP_AMOUNT * (1 + Game.PlayerStats.TimesCastleBeaten), Color.LightSteelBlue, new Vector2(this.X, this.Bounds.Top)); + player.CurrentHealth += GameEV.ITEM_STAT_MAXHP_AMOUNT; + break; + case (ItemDropType.Stat_MaxMana): + Game.PlayerStats.BonusMana += 1 + Game.PlayerStats.TimesCastleBeaten; + textManager.DisplayStringNumberText("LOC_ID_ITEM_DROP_OBJ_6" /*"Max Mana Up"*/, GameEV.ITEM_STAT_MAXMP_AMOUNT * (1 + Game.PlayerStats.TimesCastleBeaten), Color.LightSteelBlue, new Vector2(this.X, this.Bounds.Top)); + player.CurrentMana += GameEV.ITEM_STAT_MAXMP_AMOUNT; + break; + case (ItemDropType.Stat_Strength): + Game.PlayerStats.BonusStrength += 1 + Game.PlayerStats.TimesCastleBeaten; + textManager.DisplayStringNumberText("LOC_ID_ITEM_DROP_OBJ_7" /*"Attack Up"*/, GameEV.ITEM_STAT_STRENGTH_AMOUNT * (1 + Game.PlayerStats.TimesCastleBeaten), Color.LightSteelBlue, new Vector2(this.X, this.Bounds.Top)); + break; + case (ItemDropType.Stat_Magic): + Game.PlayerStats.BonusMagic += 1 + Game.PlayerStats.TimesCastleBeaten; + textManager.DisplayStringNumberText("LOC_ID_ITEM_DROP_OBJ_8" /*"Magic Up"*/, GameEV.ITEM_STAT_MAGIC_AMOUNT * (1 + Game.PlayerStats.TimesCastleBeaten), Color.LightSteelBlue, new Vector2(this.X, this.Bounds.Top)); + break; + case (ItemDropType.Stat_Weight): + Game.PlayerStats.BonusWeight += 1 + Game.PlayerStats.TimesCastleBeaten; + textManager.DisplayStringNumberText("LOC_ID_ITEM_DROP_OBJ_9" /*"Max Weight Up"*/, GameEV.ITEM_STAT_WEIGHT_AMOUNT * (1 + Game.PlayerStats.TimesCastleBeaten), Color.LightSteelBlue, new Vector2(this.X, this.Bounds.Top)); + break; + } + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + if (collisionResponseType == Consts.COLLISIONRESPONSE_TERRAIN && ((otherBox.AbsParent is TerrainObj) || otherBox.AbsParent is HazardObj) && (otherBox.AbsParent is DoorObj) == false) + { + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + this.AccelerationX = 0; + this.Y = (int)this.Y; + if (this.DropType == ItemDropType.MoneyBag && this.CurrentFrame == 1) + { + Vector2 mtd = CollisionMath.CalculateMTD(thisBox.AbsRect, otherBox.AbsRect); + //if (mtd == Vector2.Zero) + if (mtd.Y < 0) + this.PlayAnimation(2, this.TotalFrames); + } + } + } + + public override void Draw(Camera2D camera) + { + if (CollectionCounter > 0) + CollectionCounter -= (float)camera.GameTime.ElapsedGameTime.TotalSeconds; + base.Draw(camera); + } + + public bool IsCollectable + { + get { return CollectionCounter <= 0; } + } + } +} diff --git a/RogueCastle/src/Game Objects/KeyIconObj.cs b/RogueCastle/src/Game Objects/KeyIconObj.cs new file mode 100644 index 0000000..b899732 --- /dev/null +++ b/RogueCastle/src/Game Objects/KeyIconObj.cs @@ -0,0 +1,219 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; +using InputSystem; + +namespace RogueCastle +{ + public class KeyIconObj : ObjContainer + { + private TextObj m_buttonText; + + public bool IsGamepadButton { get; internal set; } + private Keys m_storedKey; + private Buttons m_storedButton; + + public KeyIconObj() + { + SpriteObj bg = new SpriteObj("KeyboardButton_Sprite"); + this.AddChild(bg); + m_buttonText = new TextObj(Game.PixelArtFont); + m_buttonText.FontSize = 16; + m_buttonText.DropShadow = new Vector2(1, 1); + m_buttonText.Align = Types.TextAlign.Centre; + m_buttonText.Y = -(m_buttonText.Height / 2); + this.AddChild(m_buttonText); + m_buttonText.Visible = false; + } + + public void SetKey(Keys? key, bool upperCase = true) + { + m_storedKey = key.Value; + + m_buttonText.FontSize = 20; + bool displayText = true; // Needed because some buttons don't use any text, so the text must be hidden. + + switch (key) + { + case (Keys.Down): + this.GetChildAt(0).ChangeSprite("KeyboardArrowDown_Sprite"); + displayText = false; + break; + case (Keys.Up): + this.GetChildAt(0).ChangeSprite("KeyboardArrowUp_Sprite"); + displayText = false; + break; + case (Keys.Left): + this.GetChildAt(0).ChangeSprite("KeyboardArrowLeft_Sprite"); + displayText = false; + break; + case (Keys.Right): + this.GetChildAt(0).ChangeSprite("KeyboardArrowRight_Sprite"); + displayText = false; + break; + case (Keys.Space): + this.GetChildAt(0).ChangeSprite("KeyboardSpacebar_Sprite"); + break; + case (Keys.NumPad0): + case (Keys.NumPad1): + case (Keys.NumPad2): + case (Keys.NumPad3): + case (Keys.NumPad4): + case (Keys.NumPad5): + case (Keys.NumPad6): + case (Keys.NumPad7): + case (Keys.NumPad8): + case (Keys.NumPad9): + this.GetChildAt(0).ChangeSprite("KeyboardButtonLong_Sprite"); + break; + case (Keys.LeftControl): + case (Keys.RightControl): + case (Keys.LeftShift): + case (Keys.RightShift): + case (Keys.Tab): + case (Keys.Enter): + case (Keys.LeftAlt): + case (Keys.RightAlt): + case (Keys.Back): + case (Keys.Escape): + this.GetChildAt(0).ChangeSprite("KeyboardButtonLong_Sprite"); + m_buttonText.FontSize = 16; + break; + case(Keys.F13): + this.GetChildAt(0).ChangeSprite("MouseLeftButton_Sprite"); + break; + case(Keys.F14): + this.GetChildAt(0).ChangeSprite("MouseRightButton_Sprite"); + break; + case(Keys.F15): + this.GetChildAt(0).ChangeSprite("MouseMiddleButton_Sprite"); + break; + default: + this.GetChildAt(0).ChangeSprite("KeyboardButton_Sprite"); + m_buttonText.FontSize = 24; + break; + } + + if (key.HasValue == false) + this.GetChildAt(0).ChangeSprite("KeyboardButtonLong_Sprite"); + + if (displayText == true) + { + if (upperCase == true) + m_buttonText.Text = InputReader.GetInputString(key, false, false, false).ToUpper(); + else + m_buttonText.Text = InputReader.GetInputString(key, false, false, false); + } + else + m_buttonText.Text = ""; + + m_buttonText.Y = -(m_buttonText.Height / 2); + m_buttonText.Visible = true; + IsGamepadButton = false; + + this.CalculateBounds(); + } + + public void SetButton(Buttons button) + { + m_storedButton = button; + + IsGamepadButton = true; + m_buttonText.Visible = false; + + switch (button) + { + case (Buttons.A): + this.GetChildAt(0).ChangeSprite("GamepadAButton_Sprite"); + break; + case (Buttons.B): + this.GetChildAt(0).ChangeSprite("GamepadBButton_Sprite"); + break; + case (Buttons.X): + this.GetChildAt(0).ChangeSprite("GamepadXButton_Sprite"); + break; + case (Buttons.Y): + this.GetChildAt(0).ChangeSprite("GamepadYButton_Sprite"); + break; + case (Buttons.Start): + this.GetChildAt(0).ChangeSprite("GamepadStartButton_Sprite"); + break; + case (Buttons.Back): + this.GetChildAt(0).ChangeSprite("GamepadBackButton_Sprite"); + break; + case (Buttons.DPadDown): + this.GetChildAt(0).ChangeSprite("GamepadDownArrow_Sprite"); + break; + case (Buttons.DPadLeft): + this.GetChildAt(0).ChangeSprite("GamepadLeftArrow_Sprite"); + break; + case (Buttons.DPadRight): + this.GetChildAt(0).ChangeSprite("GamepadRightArrow_Sprite"); + break; + case (Buttons.DPadUp): + this.GetChildAt(0).ChangeSprite("GamepadUpArrow_Sprite"); + break; + case (Buttons.LeftShoulder): + this.GetChildAt(0).ChangeSprite("GamepadLeftButton_Sprite"); + break; + case (Buttons.LeftTrigger): + this.GetChildAt(0).ChangeSprite("GamepadLeftTrigger_Sprite"); + break; + case (Buttons.RightShoulder): + this.GetChildAt(0).ChangeSprite("GamepadRightButton_Sprite"); + break; + case (Buttons.RightTrigger): + this.GetChildAt(0).ChangeSprite("GamepadRightTrigger_Sprite"); + break; + case (Buttons.RightStick): + this.GetChildAt(0).ChangeSprite("GamepadRightStick_Sprite"); + break; + case (Buttons.LeftStick): + this.GetChildAt(0).ChangeSprite("GamepadLeftStick_Sprite"); + break; + } + + this.CalculateBounds(); + } + + protected override GameObj CreateCloneInstance() + { + return new KeyIconObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + KeyIconObj icon = obj as KeyIconObj; + if (IsGamepadButton == true) + icon.SetButton(this.Button); + else + icon.SetKey(this.Key); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_buttonText = null; + base.Dispose(); + } + } + + public Keys Key + { + get { return m_storedKey; } + } + + public Buttons Button + { + get { return m_storedButton; } + } + } +} diff --git a/RogueCastle/src/Game Objects/KeyIconTextObj.cs b/RogueCastle/src/Game Objects/KeyIconTextObj.cs new file mode 100644 index 0000000..e6a6aaf --- /dev/null +++ b/RogueCastle/src/Game Objects/KeyIconTextObj.cs @@ -0,0 +1,250 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class KeyIconTextObj : TextObj + { + private List m_iconList; + private List m_iconOffset; + private float m_yOffset = 0; + private string m_storedTextString; + + public Vector2 ForcedScale { get; set; } // Allows you to force the scale of the icon, but keep the text size the same. + + public override float FontSize + { + get { return base.FontSize; } + set + { + base.FontSize = value; + if (m_storedTextString != null) + this.Text = m_storedTextString; + } + } + + public override string Text + { + get + { + return base.Text; + } + set + { + m_storedTextString = value; + foreach (KeyIconObj keyIcon in m_iconList) + keyIcon.Dispose(); + m_iconList.Clear(); + m_iconOffset.Clear(); + + string newText = value; + int iconIndex = newText.IndexOf("["); + while (iconIndex != -1) + { + int iconEndex = newText.IndexOf("]"); + if (iconEndex == -1) + throw new Exception("ERROR in KeyIconTextObj: Found starting index for icon but could not find ending index. Make sure every '[' ends with a ']'."); + newText = AddKeyIcon(newText, iconIndex, iconEndex); + + iconIndex = newText.IndexOf("["); + } + + base.Text = newText; + } + } + + public KeyIconTextObj(SpriteFont font = null) + :base (font) + { + ForcedScale = Vector2.One; + m_iconList = new List(); + m_iconOffset = new List(); + } + + public string AddKeyIcon(string text, int startIndex, int endIndex) + { + KeyIconObj icon = new KeyIconObj(); + Vector2 iconOffset = Vector2.Zero; + + string keyIconName = text.Substring(startIndex, endIndex - startIndex + 1); // Should return "[]" + string originalKeyIconName = keyIconName; + if (keyIconName.Contains("Input")) + { + string keyName = keyIconName.Replace("[Input:", ""); + keyName = keyName.Replace("]", ""); // Converting "[]" into just and storing into var keyName. + byte inputID = 0; + + try + { + inputID = byte.Parse(keyName); + } + catch + { + try + { + inputID = (byte)typeof(InputMapType).GetField(keyName).GetValue(null); + } + catch + { + throw new Exception("Invalid InputMapType"); + } + } + + if (InputSystem.InputManager.GamePadIsConnected(PlayerIndex.One) == true) + { + // Tells the icon to use the Dpad icon. + //switch (inputID) + //{ + // case (InputMapType.MENU_DOWN1): + // case (InputMapType.PLAYER_DOWN1): + // inputID = InputMapType.MENU_DOWN2; + // break; + // case (InputMapType.MENU_UP1): + // case (InputMapType.PLAYER_UP1): + // inputID = InputMapType.MENU_UP2; + // break; + // case (InputMapType.MENU_LEFT1): + // case (InputMapType.PLAYER_LEFT1): + // inputID = InputMapType.MENU_LEFT2; + // break; + // case (InputMapType.MENU_RIGHT1): + // case (InputMapType.PLAYER_RIGHT1): + // inputID = InputMapType.MENU_RIGHT2; + // break; + //} + Buttons inputButton = Game.GlobalInput.ButtonList[inputID]; + keyIconName = keyIconName.Replace(keyName, inputButton.ToString()); + keyIconName = keyIconName.Replace("Input", "Button"); + } + else + { + Keys inputKey = Game.GlobalInput.KeyList[inputID]; + keyIconName = keyIconName.Replace(keyName, inputKey.ToString()); + keyIconName = keyIconName.Replace("Input", "Key"); + } + } + + Vector2 storedScale = this.Scale; + this.Scale = Vector2.One; + if (keyIconName.Contains("Key")) // Checks to see if we're dealing with a key or a button. + { + string keyName = keyIconName.Replace("[Key:", ""); + keyName = keyName.Replace("]", ""); // Converting "[]" into just and storing into var keyName. + bool upperCase = true; + if (keyName == "Enter" || keyName == "Space") + upperCase = false; + icon.SetKey((Keys)Enum.Parse(typeof(Keys), keyName), upperCase); // Actually setting the KeyIcon to the specified key. + Vector2 fontSize = Font.MeasureString("0") * m_internalFontSizeScale * this.Scale; + float iconHeight = fontSize.Y; + icon.Scale = new Vector2(iconHeight / (float)icon.Height, iconHeight / (float)icon.Height) * ForcedScale; // Modifying the size of the icon to better match the size of the text. + m_yOffset = iconHeight / 2f; + + string blankSpace = " "; + while (Font.MeasureString(blankSpace).X * m_internalFontSizeScale.X * this.Scale.X < icon.Width) + blankSpace += " "; + + string startingText = text.Substring(0, text.IndexOf("[")); + text = text.Replace(originalKeyIconName, blankSpace); // Replaces "[]" into just and storing into var keyName. + icon.SetButton((Buttons)Enum.Parse(typeof(Buttons), keyName)); // Actually setting the KeyIcon to the specified key. + Vector2 fontSize = Font.MeasureString("0") * m_internalFontSizeScale * this.Scale; + float iconHeight = fontSize.Y; + icon.Scale = new Vector2(iconHeight / (float)icon.Height, iconHeight / (float)icon.Height) *ForcedScale; // Modifying the size of the icon to better match the size of the text. + m_yOffset = iconHeight / 2f; + + string blankSpace = " "; + while (Font.MeasureString(blankSpace).X * m_internalFontSizeScale.X * this.Scale.X < icon.Width) + blankSpace += " "; + + string startingText = text.Substring(0, text.IndexOf("[")); + text = text.Replace(originalKeyIconName, blankSpace); // Replaces "[ keyList = new List(); + foreach (KeyIconObj keyIcon in m_iconList) + keyList.Add(keyIcon.Clone() as KeyIconObj); + List iconOffsets = new List(); + iconOffsets.AddRange(m_iconOffset); + + base.WordWrap(width); + + m_iconList = keyList; + m_iconOffset = iconOffsets; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + foreach (KeyIconObj icon in m_iconList) + icon.Dispose(); + + m_iconList.Clear(); + m_iconList = null; + + m_iconOffset.Clear(); + m_iconOffset = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/KingObj.cs b/RogueCastle/src/Game Objects/KingObj.cs new file mode 100644 index 0000000..5361b84 --- /dev/null +++ b/RogueCastle/src/Game Objects/KingObj.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class KingObj : PhysicsObj//PhysicsObjContainer + { + private bool m_wasHit = false; + + public KingObj(string spriteName) + : base(spriteName) + { + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + IPhysicsObj otherBoxParent = otherBox.AbsParent as IPhysicsObj; + + if (collisionResponseType == Consts.COLLISIONRESPONSE_FIRSTBOXHIT && otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_PLAYER && m_wasHit == false) + { + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"EnemyHit1", "EnemyHit2", "EnemyHit3", "EnemyHit4", "EnemyHit5", "EnemyHit6"); + //SoundManager.PlaySound("Player_Male_Injury_01", "Player_Male_Injury_02", "Player_Male_Injury_03", "Player_Male_Injury_04", "Player_Male_Injury_05", + // "Player_Male_Injury_06", "Player_Male_Injury_07", "Player_Male_Injury_08", "Player_Male_Injury_09", "Player_Male_Injury_10"); + SoundManager.PlaySound("Boss_Title_Exit"); + SoundManager.PlaySound("Player_Death_Grunt"); + Point intersectPt = Rectangle.Intersect(thisBox.AbsRect, otherBox.AbsRect).Center; + if (thisBox.AbsRotation != 0 || otherBox.AbsRotation != 0) + intersectPt = Rectangle.Intersect(thisBox.AbsParent.Bounds, otherBox.AbsParent.Bounds).Center; + Vector2 impactPosition = new Vector2(intersectPt.X, intersectPt.Y); + (otherBox.AbsParent as PlayerObj).AttachedLevel.ImpactEffectPool.DisplayEnemyImpactEffect(impactPosition); + + m_wasHit = true; + } + + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + protected override GameObj CreateCloneInstance() + { + return new KingObj(this.SpriteName); + } + + public bool WasHit + { + get { return m_wasHit; } + } + } +} diff --git a/RogueCastle/src/Game Objects/LightSourceObj.cs b/RogueCastle/src/Game Objects/LightSourceObj.cs new file mode 100644 index 0000000..2356ec0 --- /dev/null +++ b/RogueCastle/src/Game Objects/LightSourceObj.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class LightSourceObj : SpriteObj + { + private float m_growthRate = 0; + private float m_growthDifference = 0f; + + public LightSourceObj() + : base("LightSource_Sprite") + { + m_growthRate = 0.7f + CDGMath.RandomFloat(-0.1f, 0.1f); + m_growthDifference = 0.05f + CDGMath.RandomFloat(0, 0.05f); ; + this.Opacity = 1;// 0.35f; + //this.TextureColor = new Color(187, 159, 91, 255); + } + + public override void Draw(Camera2D camera) + { + //if (m_storedScale == Vector2.Zero) + //{ + // m_storedScale = this.Scale; + // m_scaleCounter = m_storedScale.X; + //} + + //float elapsedGameTime = (float)camera.GameTime.ElapsedGameTime.TotalSeconds; + //if (m_growing == true) + //{ + // m_scaleCounter += m_growthRate * elapsedGameTime; + // if (m_scaleCounter >= m_storedScale.X + m_growthDifference) + // m_growing = false; + //} + //else + //{ + // m_scaleCounter -= m_growthRate * elapsedGameTime; + // if (m_scaleCounter <= m_storedScale.X - m_growthDifference) + // m_growing = true; + //} + + //if (m_dimming == true) + //{ + // m_dimCounter -= m_dimRate * elapsedGameTime; + // if (m_dimCounter <= 0.5f - m_dimDifference) + // m_dimming = false; + //} + //else + //{ + // m_dimCounter += m_dimRate * elapsedGameTime; + // if (m_dimCounter >= 0.5f) + // m_dimming = true; + //} + + //this.Scale = new Vector2(m_scaleCounter, m_scaleCounter); + //this.Opacity = m_dimCounter; + base.Draw(camera); + } + + protected override GameObj CreateCloneInstance() + { + return new LightSourceObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + } +} diff --git a/RogueCastle/src/Game Objects/LineageObj.cs b/RogueCastle/src/Game Objects/LineageObj.cs new file mode 100644 index 0000000..0a32614 --- /dev/null +++ b/RogueCastle/src/Game Objects/LineageObj.cs @@ -0,0 +1,787 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Tweener; +using System.Text.RegularExpressions; + +namespace RogueCastle +{ + public class LineageObj : ObjContainer // An object specific to the lineage screen, represents a single individual in a line of lineage. + { + private ObjContainer m_playerSprite; + private TextObj m_playerName; + private TextObj m_trait1Title; + private TextObj m_trait2Title; + private TextObj m_ageText; + private TextObj m_classTextObj; + + private SpriteObj m_frameSprite; + private SpriteObj m_plaqueSprite; + + private SpriteObj m_spellIcon; + private SpriteObj m_spellIconHolder; + + private bool m_isDead = false; + + public bool BeatenABoss = false; + public int NumEnemiesKilled = 0; + + public byte Age = 30; + public byte ChildAge = 4; + public byte Class = 0; + public byte Spell = 0; + public bool IsFemale = false; + public bool FlipPortrait = false; + public string RomanNumeral = ""; + private string m_playerNameString = ""; + + public string PlayerName + { + get { return m_playerNameString; } + set + { + try + { + m_playerName.ChangeFontNoDefault(m_playerName.defaultFont); + m_playerNameString = value; + m_playerName.Text = Game.NameHelper(m_playerNameString, RomanNumeral, IsFemale); + if (LocaleBuilder.languageType != LanguageType.Chinese_Simp && Regex.IsMatch(m_playerName.Text, @"\p{IsCyrillic}")) + m_playerName.ChangeFontNoDefault(Game.RobotoSlabFont); + } + catch + { + m_playerName.ChangeFontNoDefault(Game.NotoSansSCFont); + m_playerNameString = value; + m_playerName.Text = Game.NameHelper(m_playerNameString, RomanNumeral, IsFemale); + } + } + } + + public byte ChestPiece { get; set; } + public byte HeadPiece { get; set; } + public byte ShoulderPiece { get; set; } + + public bool DisablePlaque { get; set; } + + public Vector2 Traits { get; internal set; } + + private int m_textYPos = 140; + + private Color m_skinColour1 = new Color(231, 175, 131, 255); + private Color m_skinColour2 = new Color(199, 109, 112, 255); + private Color m_lichColour1 = new Color(255, 255, 255, 255); + private Color m_lichColour2 = new Color(198, 198, 198, 255); + + public LineageObj(LineageScreen screen, bool createEmpty = false) + { + this.Name = ""; + + m_frameSprite = new SpriteObj("LineageScreenFrame_Sprite"); + //m_frameSprite.ForceDraw = true; + m_frameSprite.Scale = new Vector2(2.8f, 2.8f); + m_frameSprite.DropShadow = new Vector2(4, 6); + + m_plaqueSprite = new SpriteObj("LineageScreenPlaque1Long_Sprite"); + //m_plaqueSprite.ForceDraw = true; + m_plaqueSprite.Scale = new Vector2(1.8f, 2); + + m_playerSprite = new ObjContainer("PlayerIdle_Character"); + //m_playerSprite.ForceDraw = true; + //m_playerSprite.PlayAnimation(true); + m_playerSprite.AnimationDelay = 1 / 10f; + m_playerSprite.Scale = new Vector2(2, 2); + m_playerSprite.OutlineWidth = 2; + m_playerSprite.GetChildAt(PlayerPart.Sword1).Visible = false; + m_playerSprite.GetChildAt(PlayerPart.Sword2).Visible = false; + + m_playerSprite.GetChildAt(PlayerPart.Cape).TextureColor = Color.Red; + m_playerSprite.GetChildAt(PlayerPart.Hair).TextureColor = Color.Red; + m_playerSprite.GetChildAt(PlayerPart.Glasses).Visible = false; + m_playerSprite.GetChildAt(PlayerPart.Light).Visible = false; + + Color darkPink = new Color(251, 156, 172); + m_playerSprite.GetChildAt(PlayerPart.Bowtie).TextureColor = darkPink; + + m_playerName = new TextObj(Game.JunicodeFont); + m_playerName.FontSize = 10; + m_playerName.Text = "Sir Skunky IV"; + m_playerName.Align = Types.TextAlign.Centre; + m_playerName.OutlineColour = new Color(181, 142, 39); + m_playerName.OutlineWidth = 2; + m_playerName.Y = m_textYPos; + m_playerName.LimitCorners = true; + m_playerName.X = 5; + this.AddChild(m_playerName); + + m_classTextObj = new TextObj(Game.JunicodeFont); + m_classTextObj.FontSize = 8; + m_classTextObj.Align = Types.TextAlign.Centre; + m_classTextObj.OutlineColour = new Color(181, 142, 39); + m_classTextObj.OutlineWidth = 2; + m_classTextObj.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_classTextObj); // dummy locID to add TextObj to language refresh list + m_classTextObj.Y = m_playerName.Y + m_playerName.Height - 8; + m_classTextObj.LimitCorners = true; + m_classTextObj.X = 5; + this.AddChild(m_classTextObj); + + m_trait1Title = new TextObj(Game.JunicodeFont); + m_trait1Title.FontSize = 8; + m_trait1Title.Align = Types.TextAlign.Centre; + m_trait1Title.OutlineColour = new Color(181, 142, 39); + m_trait1Title.OutlineWidth = 2; + m_trait1Title.X = 5; + m_trait1Title.Y = m_classTextObj.Y + m_classTextObj.Height + 2; + m_trait1Title.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_trait1Title); // dummy locID to add TextObj to language refresh list + m_trait1Title.LimitCorners = true; + this.AddChild(m_trait1Title); + + m_trait2Title = m_trait1Title.Clone() as TextObj; + m_trait2Title.Y += 20; + m_trait2Title.Text = ""; + m_trait2Title.LimitCorners = true; + this.AddChild(m_trait2Title); + + m_ageText = m_trait1Title.Clone() as TextObj; + m_ageText.Text = "xxx - xxx"; + m_ageText.Visible = false; + m_ageText.LimitCorners = true; + this.AddChild(m_ageText); + + m_spellIcon = new SpriteObj("Blank_Sprite"); + m_spellIcon.OutlineWidth = 1; + + m_spellIconHolder = new SpriteObj("BlacksmithUI_IconBG_Sprite"); + + if (createEmpty == false) + { + // Setting gender. + IsFemale = false; + if (CDGMath.RandomInt(0, 1) > 0) + IsFemale = true; + + // Creating random name. + if (IsFemale == true) + RomanNumeral = CreateFemaleName(screen); + else + RomanNumeral = CreateMaleName(screen); + + // Selecting random traits. + this.Traits = TraitType.CreateRandomTraits(); + + // Selecting random class. + this.Class = ClassType.GetRandomClass(); + + string classText = ""; + if (LocaleBuilder.languageType == LanguageType.English) + { + classText += LocaleBuilder.getResourceString("LOC_ID_LINEAGE_OBJ_2_MALE", true); + classText += " "; + //m_classTextObj.Text = LocaleBuilder.getResourceString(this.IsFemale ? "LOC_ID_LINEAGE_OBJ_2_FEMALE" : "LOC_ID_LINEAGE_OBJ_2_MALE") + + // " " + LocaleBuilder.getResourceString(ClassType.ToStringID(this.Class, this.IsFemale)); + } + m_classTextObj.Text = classText + LocaleBuilder.getResourceString(ClassType.ToStringID(this.Class, this.IsFemale)); + + // Special check to make sure lich doesn't get dextrocardia. + while ((this.Class == ClassType.Lich || this.Class == ClassType.Lich2) && (this.Traits.X == TraitType.Dextrocardia || this.Traits.Y == TraitType.Dextrocardia)) + this.Traits = TraitType.CreateRandomTraits(); + + // Special check to make sure wizard don't get savantism. + while ((this.Class == ClassType.Wizard || this.Class == ClassType.Wizard2 || this.Class == ClassType.Dragon) && (this.Traits.X == TraitType.Savant || this.Traits.Y == TraitType.Savant)) + this.Traits = TraitType.CreateRandomTraits(); + + // Selecting random spell. There's a check to make sure savants don't get particular spells. + byte[] spellList = ClassType.GetSpellList(this.Class); + do + { + this.Spell = spellList[CDGMath.RandomInt(0, spellList.Length - 1)]; + } while ((this.Spell == SpellType.DamageShield || this.Spell == SpellType.TimeStop || this.Spell == SpellType.Translocator) && (this.Traits.X == TraitType.Savant || this.Traits.Y == TraitType.Savant)); + Array.Clear(spellList, 0, spellList.Length); + + // Setting age. + Age = (byte)CDGMath.RandomInt(18, 30); + ChildAge = (byte)CDGMath.RandomInt(2, 5); + + // This call updates the player's graphics. + UpdateData(); + } + } + + private string CreateMaleName(LineageScreen screen) + { + string name = Game.NameArray[CDGMath.RandomInt(0, Game.NameArray.Count - 1)]; + if (screen != null) // Make sure the current branch never has matching names. + { + int countBreaker = 0; + while (screen.CurrentBranchNameCopyFound(name) == true) + { + name = Game.NameArray[CDGMath.RandomInt(0, Game.NameArray.Count - 1)]; + countBreaker++; + if (countBreaker > 20) + break; + } + } + + if (name != null) + { + if (name.Length > 10) + name = name.Substring(0, 9) + "."; + + int nameNumber = 0; + string romanNumerals = ""; + + if (screen != null) + nameNumber = screen.NameCopies(name); + if (nameNumber > 0) + romanNumerals = CDGMath.ToRoman(nameNumber + 1); + + RomanNumeral = romanNumerals; + PlayerName = name; + return romanNumerals; + } + else + PlayerName = "Hero"; + + return ""; + } + + private string CreateFemaleName(LineageScreen screen) + { + string name = Game.FemaleNameArray[CDGMath.RandomInt(0, Game.FemaleNameArray.Count - 1)]; + if (screen != null) // Make sure the current branch never has matching names. + { + int countBreaker = 0; + while (screen.CurrentBranchNameCopyFound(name) == true) + { + name = Game.FemaleNameArray[CDGMath.RandomInt(0, Game.FemaleNameArray.Count - 1)]; + countBreaker++; + if (countBreaker > 20) + break; + } + } + + if (name != null) + { + if (name.Length > 10) + name = name.Substring(0, 9) + "."; + + int nameNumber = 0; + string romanNumerals = ""; + + if (screen != null) + nameNumber = screen.NameCopies(name); + if (nameNumber > 0) + romanNumerals = CDGMath.ToRoman(nameNumber + 1); + + RomanNumeral = romanNumerals; + PlayerName = name; + return romanNumerals; + } + else + PlayerName = "Heroine"; + + return ""; + } + + public void RandomizePortrait() + { + int randHeadPiece = CDGMath.RandomInt(1, PlayerPart.NumHeadPieces); + int randShoulderPiece = CDGMath.RandomInt(1, PlayerPart.NumShoulderPieces); + int randChestPiece = CDGMath.RandomInt(1, PlayerPart.NumChestPieces); + + if (this.Class == ClassType.Traitor) + randHeadPiece = PlayerPart.IntroHelm; // Force the head piece to be Johanne's headpiece if you are playing as the fountain. + else if (this.Class == ClassType.Dragon) + randHeadPiece = PlayerPart.DragonHelm; + + SetPortrait((byte)randHeadPiece, (byte)randShoulderPiece, (byte)randChestPiece); + } + + public void SetPortrait(byte headPiece, byte shoulderPiece, byte chestPiece) + { + HeadPiece = headPiece; + ShoulderPiece = shoulderPiece; + ChestPiece = chestPiece; + + string headPart = (m_playerSprite.GetChildAt(PlayerPart.Head) as IAnimateableObj).SpriteName; + int numberIndex = headPart.IndexOf("_") - 1; + headPart = headPart.Remove(numberIndex, 1); + headPart = headPart.Replace("_", HeadPiece + "_"); + m_playerSprite.GetChildAt(PlayerPart.Head).ChangeSprite(headPart); + + string chestPart = (m_playerSprite.GetChildAt(PlayerPart.Chest) as IAnimateableObj).SpriteName; + numberIndex = chestPart.IndexOf("_") - 1; + chestPart = chestPart.Remove(numberIndex, 1); + chestPart = chestPart.Replace("_", ChestPiece + "_"); + m_playerSprite.GetChildAt(PlayerPart.Chest).ChangeSprite(chestPart); + + string shoulderAPart = (m_playerSprite.GetChildAt(PlayerPart.ShoulderA) as IAnimateableObj).SpriteName; + numberIndex = shoulderAPart.IndexOf("_") - 1; + shoulderAPart = shoulderAPart.Remove(numberIndex, 1); + shoulderAPart = shoulderAPart.Replace("_", ShoulderPiece + "_"); + m_playerSprite.GetChildAt(PlayerPart.ShoulderA).ChangeSprite(shoulderAPart); + + string shoulderBPart = (m_playerSprite.GetChildAt(PlayerPart.ShoulderB) as IAnimateableObj).SpriteName; + numberIndex = shoulderBPart.IndexOf("_") - 1; + shoulderBPart = shoulderBPart.Remove(numberIndex, 1); + shoulderBPart = shoulderBPart.Replace("_", ShoulderPiece + "_"); + m_playerSprite.GetChildAt(PlayerPart.ShoulderB).ChangeSprite(shoulderBPart); + } + + public void UpdateAge(int currentEra) + { + int startingEra = currentEra - ChildAge; + int endingEra = currentEra + Age; + m_ageText.Text = startingEra + " - " + endingEra; + } + + public void UpdateData() + { + SetTraits(Traits); + + m_playerSprite.GetChildAt(PlayerPart.Hair).Visible = true; + if (this.Traits.X == TraitType.Baldness || this.Traits.Y == TraitType.Baldness) + m_playerSprite.GetChildAt(PlayerPart.Hair).Visible = false; + + // flibit added this. + FlipPortrait = false; + m_playerSprite.Rotation = 0; + if (this.Traits.X == TraitType.Vertigo || this.Traits.Y == TraitType.Vertigo) + FlipPortrait = true; + + string classText = ""; + if (LocaleBuilder.languageType == LanguageType.English) + { + classText += LocaleBuilder.getResourceString("LOC_ID_LINEAGE_OBJ_2_MALE", true); + classText += " "; + //m_classTextObj.Text = LocaleBuilder.getResourceString(this.IsFemale ? "LOC_ID_LINEAGE_OBJ_2_FEMALE" : "LOC_ID_LINEAGE_OBJ_2_MALE") + + // " " + LocaleBuilder.getResourceString(ClassType.ToStringID(this.Class, this.IsFemale)); + } + m_classTextObj.Text = classText + LocaleBuilder.getResourceString(ClassType.ToStringID(this.Class, this.IsFemale)); + + m_spellIcon.ChangeSprite(SpellType.Icon(this.Spell)); + + if (this.Class == ClassType.Knight || this.Class == ClassType.Knight2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("PlayerIdleShield_Sprite"); + } + else if (this.Class == ClassType.Banker || this.Class == ClassType.Banker2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("PlayerIdleLamp_Sprite"); + } + else if (this.Class == ClassType.Wizard || this.Class == ClassType.Wizard2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("PlayerIdleBeard_Sprite"); + } + else if (this.Class == ClassType.Ninja || this.Class == ClassType.Ninja2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("PlayerIdleHeadband_Sprite"); + } + else if (this.Class == ClassType.Barbarian || this.Class == ClassType.Barbarian2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("PlayerIdleHorns_Sprite"); + } + else + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = false; + + // Special code for dragon. + m_playerSprite.GetChildAt(PlayerPart.Wings).Visible = false; + if (this.Class == ClassType.Dragon) + { + m_playerSprite.GetChildAt(PlayerPart.Wings).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Head).ChangeSprite("PlayerIdleHead" + PlayerPart.DragonHelm + "_Sprite"); + } + + //Special code for traitor. + if (this.Class == ClassType.Traitor) + m_playerSprite.GetChildAt(PlayerPart.Head).ChangeSprite("PlayerIdleHead" + PlayerPart.IntroHelm + "_Sprite"); + + // This is for male/female counterparts + if (IsFemale == false) + { + m_playerSprite.GetChildAt(PlayerPart.Boobs).Visible = false; + m_playerSprite.GetChildAt(PlayerPart.Bowtie).Visible = false; + } + else + { + m_playerSprite.GetChildAt(PlayerPart.Boobs).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Bowtie).Visible = true; + } + + m_playerSprite.Scale = new Vector2(2); + if (Traits.X == TraitType.Gigantism || Traits.Y == TraitType.Gigantism) + m_playerSprite.Scale = new Vector2(GameEV.TRAIT_GIGANTISM, GameEV.TRAIT_GIGANTISM); + if (Traits.X == TraitType.Dwarfism|| Traits.Y == TraitType.Dwarfism) + m_playerSprite.Scale = new Vector2(GameEV.TRAIT_DWARFISM, GameEV.TRAIT_DWARFISM); + + if (Traits.X == TraitType.Ectomorph || Traits.Y == TraitType.Ectomorph) + { + m_playerSprite.ScaleX *= 0.825f; + m_playerSprite.ScaleY *= 1.25f; + } + + if (Traits.X == TraitType.Endomorph || Traits.Y == TraitType.Endomorph) + { + m_playerSprite.ScaleX *= 1.25f; + m_playerSprite.ScaleY *= 1.175f; + } + + if (this.Class == ClassType.SpellSword || this.Class == ClassType.SpellSword2) + m_playerSprite.OutlineColour = Color.White; + else + m_playerSprite.OutlineColour = Color.Black; + } + + bool m_frameDropping = false; + public void DropFrame() + { + m_frameDropping = true; + Tween.By(m_frameSprite, 0.7f, Tweener.Ease.Back.EaseOut, "X", (-m_frameSprite.Width/2f - 2).ToString(), "Y", "30", "Rotation", "45"); + Tween.By(m_playerSprite, 0.7f, Tweener.Ease.Back.EaseOut, "X", (-m_frameSprite.Width / 2f - 2).ToString(), "Y", "30", "Rotation", "45"); + Tween.RunFunction(1.5f, this, "DropFrame2"); + } + + public void DropFrame2() + { + SoundManager.PlaySound("Cutsc_Picture_Fall"); + Tween.By(m_frameSprite, 0.5f, Tweener.Ease.Quad.EaseIn, "Y", "1000"); + Tween.By(m_playerSprite, 0.5f, Tweener.Ease.Quad.EaseIn, "Y", "1000"); + } + + public override void Draw(Camera2D camera) + { + //m_playerSprite.Rotation = 0; + if (FlipPortrait == true) + m_playerSprite.Rotation = 180; + + if (m_frameDropping == false) + { + m_frameSprite.Position = this.Position; + m_frameSprite.Y -= 12; + m_frameSprite.X += 5; + } + m_frameSprite.Opacity = this.Opacity; + m_frameSprite.Draw(camera); + + if (this.IsDead == false && this.Spell != SpellType.None) + { + m_spellIconHolder.Position = new Vector2(m_frameSprite.X, m_frameSprite.Bounds.Bottom - 20); + m_spellIcon.Position = m_spellIconHolder.Position; + m_spellIconHolder.Draw(camera); + m_spellIcon.Draw(camera); + } + + m_playerSprite.OutlineColour = this.OutlineColour; + m_playerSprite.OutlineWidth = this.OutlineWidth; + if (m_frameDropping == false) + { + m_playerSprite.Position = this.Position; + m_playerSprite.X += 10; + if (FlipPortrait == true) + { + m_playerSprite.X -= 10; + m_playerSprite.Y -= 30; + } + } + m_playerSprite.Opacity = this.Opacity; + m_playerSprite.Draw(camera); + + // only apply the lich effect if the lineageObj is being drawn. + if (CollisionMath.Intersects(this.Bounds, camera.Bounds)) + { + if (this.Class == ClassType.Lich || this.Class == ClassType.Lich2) + { + // This is the Tint Removal effect, that removes the tint from his face. + Game.ColourSwapShader.Parameters["desiredTint"].SetValue(Color.White.ToVector4()); + Game.ColourSwapShader.Parameters["Opacity"].SetValue(m_playerSprite.Opacity); + + Game.ColourSwapShader.Parameters["ColourSwappedOut1"].SetValue(m_skinColour1.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn1"].SetValue(m_lichColour1.ToVector4()); + + Game.ColourSwapShader.Parameters["ColourSwappedOut2"].SetValue(m_skinColour2.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn2"].SetValue(m_lichColour2.ToVector4()); + + camera.End(); + camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, Game.ColourSwapShader, camera.GetTransformation()); + m_playerSprite.GetChildAt(PlayerPart.Head).Draw(camera); + camera.End(); + camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, camera.GetTransformation()); + if (IsFemale == true) + m_playerSprite.GetChildAt(PlayerPart.Bowtie).Draw(camera); + m_playerSprite.GetChildAt(PlayerPart.Extra).Draw(camera); + } + else if (this.Class == ClassType.Assassin || this.Class == ClassType.Assassin2) + { + // This is the Tint Removal effect, that removes the tint from his face. + Game.ColourSwapShader.Parameters["desiredTint"].SetValue(Color.White.ToVector4()); + Game.ColourSwapShader.Parameters["Opacity"].SetValue(m_playerSprite.Opacity); + + Game.ColourSwapShader.Parameters["ColourSwappedOut1"].SetValue(m_skinColour1.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn1"].SetValue(Color.Black.ToVector4()); + + Game.ColourSwapShader.Parameters["ColourSwappedOut2"].SetValue(m_skinColour2.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn2"].SetValue(Color.Black.ToVector4()); + + camera.End(); + camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, Game.ColourSwapShader, camera.GetTransformation()); + m_playerSprite.GetChildAt(PlayerPart.Head).Draw(camera); + camera.End(); + camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, camera.GetTransformation()); + if (IsFemale == true) + m_playerSprite.GetChildAt(PlayerPart.Bowtie).Draw(camera); + m_playerSprite.GetChildAt(PlayerPart.Extra).Draw(camera); + } + } + + if (DisablePlaque == false) + { + if (m_frameDropping == false) + { + m_plaqueSprite.Position = this.Position; + m_plaqueSprite.X += 5; + m_plaqueSprite.Y = m_frameSprite.Y + m_frameSprite.Height - 30; + } + m_plaqueSprite.Draw(camera); + camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + base.Draw(camera); // Base draws the text. + camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + } + + // Makes sure the frame is drawn in front of the plaque when it's doing its fall animation. + if (m_frameDropping == true) + { + m_frameSprite.Draw(camera); + m_playerSprite.Draw(camera); + } + } + + public void SetTraits(Vector2 traits) + { + this.Traits = traits; + string traitString = ""; + if (Traits.X != 0) + traitString += LocaleBuilder.getResourceString(TraitType.ToStringID((byte)Traits.X)); + //m_trait1Title.Text = TraitType.ToString((byte)Traits.X); + else + m_trait1Title.Text = ""; + if (Traits.Y != 0) + { + if (traits.X != 0) + traitString += ", " + LocaleBuilder.getResourceString(TraitType.ToStringID((byte)Traits.Y)); + else + traitString += LocaleBuilder.getResourceString(TraitType.ToStringID((byte)Traits.Y)); + } + //m_trait2Title.Text = TraitType.ToString((byte)Traits.Y); + + m_trait1Title.Text = traitString; + + if (IsDead == false) + { + m_plaqueSprite.ScaleX = 1.8f; + // Auto-scale the plaque if the trait text is too large. + if (traits.X != TraitType.None) + { + float maxWidth = m_plaqueSprite.Width; + float traitWidth = m_trait1Title.Width + 50; + if (traitWidth > maxWidth) + m_plaqueSprite.ScaleX *= traitWidth / maxWidth; + } + //m_trait1Title.WordWrap(200); + } + } + + public void ClearTraits() + { + Traits = Vector2.Zero; + m_trait1Title.Text = LocaleBuilder.getString("LOC_ID_LINEAGE_OBJ_1", m_trait1Title); + m_trait2Title.Text = ""; + } + + public void OutlineLineageObj(Color color, int width) + { + m_plaqueSprite.OutlineColour = color; + m_plaqueSprite.OutlineWidth = width; + + m_frameSprite.OutlineColour = color; + m_frameSprite.OutlineWidth = width; + } + + public void UpdateClassRank() + { + string className = ""; + string locIDToUse = "LOC_ID_LINEAGE_OBJ_4_NEW"; + + if (LocaleBuilder.languageType == LanguageType.English) + { + //!this.IsFemale ? LocaleBuilder.getResourceString("LOC_ID_LINEAGE_OBJ_2_MALE") : LocaleBuilder.getResourceString("LOC_ID_LINEAGE_OBJ_2_FEMALE"); + + className += LocaleBuilder.getResourceString("LOC_ID_LINEAGE_OBJ_2_MALE", true); + className += " "; + } + + if (BeatenABoss == true) + locIDToUse = "LOC_ID_LINEAGE_OBJ_3_NEW"; + else + { + if (NumEnemiesKilled < 5) + locIDToUse = "LOC_ID_LINEAGE_OBJ_4_NEW"; + else if (NumEnemiesKilled >= 5 && NumEnemiesKilled < 10) + locIDToUse = "LOC_ID_LINEAGE_OBJ_5_NEW"; + else if (NumEnemiesKilled >= 10 && NumEnemiesKilled < 15) + locIDToUse = "LOC_ID_LINEAGE_OBJ_6_NEW"; + else if (NumEnemiesKilled >= 15 && NumEnemiesKilled < 20) + locIDToUse = "LOC_ID_LINEAGE_OBJ_7_NEW"; + else if (NumEnemiesKilled >= 20 && NumEnemiesKilled < 25) + locIDToUse = "LOC_ID_LINEAGE_OBJ_8_NEW"; + else if (NumEnemiesKilled >= 25 && NumEnemiesKilled < 30) + locIDToUse = "LOC_ID_LINEAGE_OBJ_9_NEW"; + else if (NumEnemiesKilled >= 30 && NumEnemiesKilled < 35) + locIDToUse = "LOC_ID_LINEAGE_OBJ_10_NEW"; + else + locIDToUse = "LOC_ID_LINEAGE_OBJ_11_NEW"; + } + + className += string.Format(LocaleBuilder.getResourceStringCustomFemale(locIDToUse, this.IsFemale), LocaleBuilder.getResourceString(ClassType.ToStringID(this.Class, this.IsFemale))); + m_classTextObj.Text = className; + + m_plaqueSprite.ScaleX = 1.8f; + // Auto-scale the plaque if the class rank text is too large. + float maxWidth = m_plaqueSprite.Width; + float classRankWidth = m_classTextObj.Width + 50; + if (classRankWidth > maxWidth) + m_plaqueSprite.ScaleX *= classRankWidth / maxWidth; + } + + public bool IsDead + { + get { return m_isDead; } + set + { + m_isDead = value; + if (value == true) + { + m_trait1Title.Visible = false; + m_trait2Title.Visible = false; + m_ageText.Visible = true; + } + else + { + if (m_hasProsopagnosia == true) + { + m_trait1Title.Visible = false; + m_trait2Title.Visible = false; + } + else + { + m_trait1Title.Visible = true; + m_trait2Title.Visible = true; + } + m_ageText.Visible = false; + } + } + } + + + private bool m_hasProsopagnosia = false; + public bool HasProsopagnosia + { + set + { + m_hasProsopagnosia = value; + if (m_isDead == false) + { + if (value == true) + { + m_trait1Title.Visible = false; + m_trait2Title.Visible = false; + } + else + { + m_trait1Title.Visible = true; + m_trait2Title.Visible = true; + } + } + } + get { return m_hasProsopagnosia; } + } + + + public override Rectangle Bounds + { + get { return m_playerSprite.Bounds; } + } + + public override Rectangle AbsBounds + { + get { return m_playerSprite.Bounds; } + } + + protected override GameObj CreateCloneInstance() + { + return new LineageObj(null); // Not used. + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_playerSprite.Dispose(); + m_playerSprite = null; + + m_trait1Title = null; + m_trait2Title = null; + m_ageText = null; + m_playerName = null; + m_classTextObj = null; + + m_frameSprite.Dispose(); + m_frameSprite = null; + m_plaqueSprite.Dispose(); + m_plaqueSprite = null; + + m_spellIcon.Dispose(); + m_spellIcon = null; + + m_spellIconHolder.Dispose(); + m_spellIconHolder = null; + + base.Dispose(); + } + } + + public void RefreshTextObjs() + { + if (this.IsDead) + UpdateClassRank(); + else + { + string classText = ""; + if (LocaleBuilder.languageType == LanguageType.English) + { + classText += LocaleBuilder.getResourceString("LOC_ID_LINEAGE_OBJ_2_MALE", true); + classText += " "; + //m_classTextObj.Text = LocaleBuilder.getResourceString(this.IsFemale ? "LOC_ID_LINEAGE_OBJ_2_FEMALE" : "LOC_ID_LINEAGE_OBJ_2_MALE") + + // " " + LocaleBuilder.getResourceString(ClassType.ToStringID(this.Class, this.IsFemale)); + } + m_classTextObj.Text = classText + LocaleBuilder.getResourceString(ClassType.ToStringID(this.Class, this.IsFemale)); + } + + PlayerName = PlayerName; // This refreshes the name. + SetTraits(this.Traits); + } + } +} diff --git a/RogueCastle/src/Game Objects/MapObj.cs b/RogueCastle/src/Game Objects/MapObj.cs new file mode 100644 index 0000000..bbe50a6 --- /dev/null +++ b/RogueCastle/src/Game Objects/MapObj.cs @@ -0,0 +1,578 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Tweener; + +namespace RogueCastle +{ + public class MapObj : GameObj + { + private PlayerObj m_player; + private ProceduralLevelScreen m_level; + + private List m_roomSpriteList; + private List m_doorSpriteList; + private List m_iconSpriteList; + private List m_roomSpritePosList; + private List m_doorSpritePosList; + private List m_iconSpritePosList; + private SpriteObj m_playerSprite; + + public Vector2 CameraOffset; + private Vector2 m_spriteScale; + private List m_addedRooms; // Necessary to keep track of the rooms added so that they don't get added multiple times. + + private RenderTarget2D m_alphaMaskRT, m_mapScreenRT; // Two render targets. The first is a black and white mask, where white represents invisible and black represents drawable area. + // The second is an RT of the actual map screen. The two are then merged and drawn to the actual screen. + private Rectangle m_alphaMaskRect; // A rectangle that stores the actual rectangle size of the current alpha mask being used (assuming it's rectangular). + + private List m_teleporterList; + private List m_teleporterPosList; + public bool DrawTeleportersOnly { get; set; } + public bool DrawNothing { get; set; } + + TweenObject m_xOffsetTween = null; + TweenObject m_yOffsetTween = null; + + public bool FollowPlayer { get; set; } + + public MapObj(bool followPlayer, ProceduralLevelScreen level) + { + m_level = level; + FollowPlayer = followPlayer; + + this.Opacity = 0.3f; + m_roomSpriteList = new List(); + m_doorSpriteList = new List(); + m_iconSpriteList = new List(); + m_roomSpritePosList = new List(); + m_doorSpritePosList = new List(); + m_iconSpritePosList = new List(); + + CameraOffset = new Vector2(20, 560); + + m_playerSprite = new SpriteObj("MapPlayerIcon_Sprite"); + m_playerSprite.AnimationDelay = 1 / 30f; + m_playerSprite.ForceDraw = true; + m_playerSprite.PlayAnimation(true); + + m_spriteScale = new Vector2(22f, 22.5f); + m_addedRooms = new List(); + m_teleporterList = new List(); + m_teleporterPosList = new List(); + } + + public void InitializeAlphaMap(Rectangle mapSize, Camera2D camera) + { + m_alphaMaskRect = mapSize; + m_mapScreenRT = new RenderTarget2D(camera.GraphicsDevice, 1320, 720, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + m_alphaMaskRT = new RenderTarget2D(camera.GraphicsDevice, 1320, 720, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + CameraOffset = new Vector2(mapSize.X, mapSize.Y); + + SpriteObj alphaMaskSprite = new SpriteObj("MapMask_Sprite"); + alphaMaskSprite.ForceDraw = true; + alphaMaskSprite.Position = new Vector2(mapSize.X, mapSize.Y); + alphaMaskSprite.Scale = new Vector2((float)mapSize.Width / alphaMaskSprite.Width, (float)mapSize.Height / alphaMaskSprite.Height); + camera.GraphicsDevice.SetRenderTarget(m_alphaMaskRT); + camera.GraphicsDevice.Clear(Color.White); + camera.Begin(); + alphaMaskSprite.Draw(camera); + camera.End(); + camera.GraphicsDevice.SetRenderTarget(Game.ScreenManager.RenderTarget); + } + + public void InitializeAlphaMap(RenderTarget2D mapScreenRT, RenderTarget2D alphaMaskRT, Rectangle mapSize) + { + m_mapScreenRT = mapScreenRT; + m_alphaMaskRT = alphaMaskRT; + m_alphaMaskRect = mapSize; + CameraOffset = new Vector2(mapSize.X, mapSize.Y); + } + + public void DisposeRTs() + { + m_mapScreenRT.Dispose(); + m_mapScreenRT = null; + m_alphaMaskRT.Dispose(); + m_alphaMaskRT = null; + } + + public void SetPlayer(PlayerObj player) + { + m_player = player; + } + + public void AddRoom(RoomObj room) + { + if (m_addedRooms.Contains(room) == false && room.Width / 1320 < 5) // A small check to make sure a too large a room is not added to the map. + { + SpriteObj roomSprite = new SpriteObj("MapRoom" + (int)(room.Width / 1320) + "x" + (int)(room.Height / 720) + "_Sprite"); + roomSprite.Position = new Vector2(room.X / m_spriteScale.X, room.Y / m_spriteScale.Y); + roomSprite.Scale = new Vector2((roomSprite.Width - 3f) / roomSprite.Width, (roomSprite.Height - 3f) / roomSprite.Height); + roomSprite.ForceDraw = true; + roomSprite.TextureColor = room.TextureColor; + m_roomSpriteList.Add(roomSprite); + m_roomSpritePosList.Add(roomSprite.Position); + foreach (DoorObj door in room.DoorList) + { + if (room.Name == "CastleEntrance" && door.DoorPosition == "Left") // Special code to hide the left door for the Castle Entrance. + continue; + + bool addDoor = false; + + SpriteObj doorSprite = new SpriteObj("MapDoor_Sprite"); + doorSprite.ForceDraw = true; + switch (door.DoorPosition) + { + case ("Left"): + doorSprite.Position = new Vector2(room.Bounds.Left / m_spriteScale.X - doorSprite.Width + 2, door.Y / m_spriteScale.Y - 2); + addDoor = true; + break; + case ("Right"): + doorSprite.Position = new Vector2(room.Bounds.Right / m_spriteScale.X - 5, door.Y / m_spriteScale.Y - 2); + addDoor = true; + break; + case ("Bottom"): + doorSprite.Rotation = -90; + doorSprite.Position = new Vector2(door.X / m_spriteScale.X, (door.Y + door.Height) / m_spriteScale.Y + 2); + addDoor = true; + break; + case ("Top"): + doorSprite.Rotation = -90; + doorSprite.Position = new Vector2(door.X / m_spriteScale.X, door.Y / m_spriteScale.Y + 2); + addDoor = true; + break; + } + + if (addDoor == true) + { + m_doorSpritePosList.Add(doorSprite.Position); + m_doorSpriteList.Add(doorSprite); + } + } + + // Don't add these if you're the spelunker (banker2) because it's already added at the start of the game. + if (room.Name != "Bonus" && Game.PlayerStats.Class != ClassType.Banker2) // Some bonus rooms have tons of chests. Don't litter it with chest icons. + { + foreach (GameObj obj in room.GameObjList) + { + ChestObj chest = obj as ChestObj; + if (chest != null) + { + SpriteObj chestSprite = null; + if (chest.IsOpen == true) + chestSprite = new SpriteObj("MapChestUnlocked_Sprite"); + else if (chest is FairyChestObj) + { + chestSprite = new SpriteObj("MapFairyChestIcon_Sprite"); + if ((chest as FairyChestObj).ConditionType == ChestConditionType.InvisibleChest) + chestSprite.Opacity = 0.2f; + } + else + chestSprite = new SpriteObj("MapLockedChestIcon_Sprite"); + m_iconSpriteList.Add(chestSprite); + chestSprite.AnimationDelay = 1 / 30f; + chestSprite.PlayAnimation(true); + chestSprite.ForceDraw = true; + chestSprite.Position = new Vector2(obj.X / m_spriteScale.X - 8, obj.Y / m_spriteScale.Y - 12); + if (room.IsReversed == true) + chestSprite.X -= (obj.Width / m_spriteScale.X); + m_iconSpritePosList.Add(chestSprite.Position); + } + } + } + + if (room.Name == "EntranceBoss") + { + SpriteObj bossSprite = new SpriteObj("MapBossIcon_Sprite"); + bossSprite.AnimationDelay = 1 / 30f; + bossSprite.ForceDraw = true; + bossSprite.PlayAnimation(true); + bossSprite.Position = new Vector2((room.X + room.Width / 2f) / m_spriteScale.X - bossSprite.Width / 2 - 1, (room.Y + room.Height / 2f) / m_spriteScale.Y - bossSprite.Height / 2 - 2); + m_iconSpriteList.Add(bossSprite); + m_iconSpritePosList.Add(bossSprite.Position); + + m_teleporterList.Add(bossSprite); + m_teleporterPosList.Add(bossSprite.Position); + } + else if (room.Name == "Linker") + { + SpriteObj teleporter = new SpriteObj("MapTeleporterIcon_Sprite"); + teleporter.AnimationDelay = 1 / 30f; + teleporter.ForceDraw = true; + teleporter.PlayAnimation(true); + teleporter.Position = new Vector2((room.X + room.Width / 2f) / m_spriteScale.X - teleporter.Width / 2 - 1, (room.Y + room.Height / 2f) / m_spriteScale.Y - teleporter.Height / 2 - 2); + m_iconSpriteList.Add(teleporter); + m_iconSpritePosList.Add(teleporter.Position); + + m_teleporterList.Add(teleporter); + m_teleporterPosList.Add(teleporter.Position); + } + else if (room.Name == "CastleEntrance") + { + SpriteObj teleporter = new SpriteObj("MapTeleporterIcon_Sprite"); + teleporter.AnimationDelay = 1 / 30f; + teleporter.ForceDraw = true; + teleporter.PlayAnimation(true); + teleporter.Position = new Vector2((room.X + room.Width / 2f) / m_spriteScale.X - teleporter.Width / 2 - 1, (room.Y + room.Height / 2f) / m_spriteScale.Y - teleporter.Height / 2 - 2); + m_iconSpriteList.Add(teleporter); + m_iconSpritePosList.Add(teleporter.Position); + + m_teleporterList.Add(teleporter); + m_teleporterPosList.Add(teleporter.Position); + } + + if (Game.PlayerStats.Class != ClassType.Banker2) // Don't add bonus room icon if you're the spelunker for the same reason you don't add chests. + { + if (room.Name == "Bonus") + { + SpriteObj bonus = new SpriteObj("MapBonusIcon_Sprite"); + bonus.PlayAnimation(true); + bonus.AnimationDelay = 1 / 30f; + bonus.ForceDraw = true; + bonus.Position = new Vector2((room.X + room.Width / 2f) / m_spriteScale.X - bonus.Width / 2 - 1, (room.Y + room.Height / 2f) / m_spriteScale.Y - bonus.Height / 2 - 2); + m_iconSpriteList.Add(bonus); + m_iconSpritePosList.Add(bonus.Position); + } + } + + m_addedRooms.Add(room); + } + } + + public void AddAllRooms(List roomList) + { + foreach (RoomObj room in roomList) + AddRoom(room); + } + + public void AddAllIcons(List roomList) + { + foreach (RoomObj room in roomList) + { + if (m_addedRooms.Contains(room) == false) + { + if (room.Name != "Bonus") // Some bonus rooms have tons of chests. Don't litter it with chest icons. + { + foreach (GameObj obj in room.GameObjList) + { + ChestObj chest = obj as ChestObj; + if (chest != null) + { + SpriteObj chestSprite = null; + if (chest.IsOpen == true) + chestSprite = new SpriteObj("MapChestUnlocked_Sprite"); + else if (chest is FairyChestObj) + { + chestSprite = new SpriteObj("MapFairyChestIcon_Sprite"); + if ((chest as FairyChestObj).ConditionType == ChestConditionType.InvisibleChest) + chestSprite.Opacity = 0.2f; + } + else + chestSprite = new SpriteObj("MapLockedChestIcon_Sprite"); + m_iconSpriteList.Add(chestSprite); + chestSprite.AnimationDelay = 1 / 30f; + chestSprite.PlayAnimation(true); + chestSprite.ForceDraw = true; + chestSprite.Position = new Vector2(obj.X / m_spriteScale.X - 8, obj.Y / m_spriteScale.Y - 12); + if (room.IsReversed == true) + chestSprite.X -= (obj.Width / m_spriteScale.X); + m_iconSpritePosList.Add(chestSprite.Position); + } + } + } + else if (room.Name == "Bonus") + { + SpriteObj bonus = new SpriteObj("MapBonusIcon_Sprite"); + bonus.PlayAnimation(true); + bonus.AnimationDelay = 1 / 30f; + bonus.ForceDraw = true; + bonus.Position = new Vector2((room.X + room.Width / 2f) / m_spriteScale.X - bonus.Width / 2 - 1, (room.Y + room.Height / 2f) / m_spriteScale.Y - bonus.Height / 2 - 2); + m_iconSpriteList.Add(bonus); + m_iconSpritePosList.Add(bonus.Position); + } + } + } + } + + public void AddLinkerRoom(GameTypes.LevelType levelType, List roomList) + { + foreach (RoomObj room in roomList) + { + if (room.Name == "Linker" && room.LevelType == levelType) + this.AddRoom(room); + } + } + + public void RefreshChestIcons(RoomObj room) + { + foreach (GameObj obj in room.GameObjList) + { + ChestObj chest = obj as ChestObj; + if (chest != null && chest.IsOpen == true) + { + Vector2 chestPosition = new Vector2(chest.X / m_spriteScale.X - 8, chest.Y / m_spriteScale.Y - 12); + for (int i = 0; i < m_iconSpritePosList.Count; i++) + { + if (CDGMath.DistanceBetweenPts(chestPosition,m_iconSpritePosList[i]) < 15) + { + m_iconSpriteList[i].ChangeSprite("MapChestUnlocked_Sprite"); + m_iconSpriteList[i].Opacity = 1; // Special code needed since Invisible chests set opacity to 0.2f + break; + } + } + } + } + } + + public void CentreAroundPos(Vector2 pos, bool tween = false) + { + if (tween == false) + { + CameraOffset.X = m_alphaMaskRect.X + m_alphaMaskRect.Width / 2f - ((pos.X / 1320f) * 60); + CameraOffset.Y = m_alphaMaskRect.Y + m_alphaMaskRect.Height / 2f - ((pos.Y / 720f) * 32); + } + else + { + if (m_xOffsetTween != null && m_xOffsetTween.TweenedObject == this) + m_xOffsetTween.StopTween(false); + if (m_yOffsetTween != null && m_yOffsetTween.TweenedObject == this) + m_yOffsetTween.StopTween(false); + + m_xOffsetTween = Tween.To(this, 0.3f, Tweener.Ease.Quad.EaseOut, "CameraOffsetX", (m_alphaMaskRect.X + m_alphaMaskRect.Width / 2f - ((pos.X / 1320f) * 60)).ToString()); + m_yOffsetTween = Tween.To(this, 0.3f, Tweener.Ease.Quad.EaseOut, "CameraOffsetY", (m_alphaMaskRect.Y + m_alphaMaskRect.Height / 2f - ((pos.Y / 720f) * 32)).ToString()); + } + } + + public void CentreAroundObj(GameObj obj) + { + CentreAroundPos(obj.Position); + } + + public void CentreAroundPlayer() + { + CentreAroundObj(m_player); + } + + public void TeleportPlayer(int index) + { + if (m_teleporterList.Count > 0) // Make sure teleporters exist before you teleport. + { + Vector2 pos = m_teleporterPosList[index]; + //Console.WriteLine(pos); + //pos.X += m_teleporterList[index].Width / 2f; + //pos.Y += m_teleporterList[index].Height / 2f; + pos.X += 10; + pos.Y += 10; + pos.X *= m_spriteScale.X; + pos.Y *= m_spriteScale.Y; + pos.X += 30; + if (index == 0) // A hack for the CastleEntranceRoom, since its teleporter is not one grid from the ground, but 5. + { + pos.X -= 610; + pos.Y += 720 / 2 - (130); + } + else + pos.Y += 720 / 2 - 70; + m_player.TeleportPlayer(pos); + } + } + + public void CentreAroundTeleporter(int index, bool tween = false) + { + Vector2 pos = m_teleporterPosList[index]; + pos.X *= m_spriteScale.X; + pos.Y *= m_spriteScale.Y; + CentreAroundPos(pos, tween); + } + + public void DrawRenderTargets(Camera2D camera) + { + if (FollowPlayer == true) + { + CameraOffset.X = (int)(m_alphaMaskRect.X + m_alphaMaskRect.Width / 2f - ((m_player.X / 1320) * 60)); + CameraOffset.Y = m_alphaMaskRect.Y + m_alphaMaskRect.Height / 2f - (((int)m_player.Y / 720f) * 32); + } + + camera.GraphicsDevice.SetRenderTarget(m_mapScreenRT); + camera.GraphicsDevice.Clear(Color.Transparent); + //camera.Begin(0, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null); + + for (int i = 0; i < m_roomSpriteList.Count; i++) + { + m_roomSpriteList[i].Position = CameraOffset + m_roomSpritePosList[i]; + m_roomSpriteList[i].Draw(camera); + } + + for (int i = 0; i < m_doorSpriteList.Count; i++) + { + m_doorSpriteList[i].Position = CameraOffset + m_doorSpritePosList[i]; + m_doorSpriteList[i].Draw(camera); + } + + if (DrawTeleportersOnly == false) + { + for (int i = 0; i < m_iconSpriteList.Count; i++) + { + m_iconSpriteList[i].Position = CameraOffset + m_iconSpritePosList[i]; + m_iconSpriteList[i].Draw(camera); + } + } + else + { + for (int i = 0; i < m_teleporterList.Count; i++) + { + m_teleporterList[i].Position = CameraOffset + m_teleporterPosList[i]; + m_teleporterList[i].Draw(camera); + } + } + + if (Game.PlayerStats.Traits.X == TraitType.EideticMemory || Game.PlayerStats.Traits.Y == TraitType.EideticMemory) + { + m_playerSprite.TextureColor = Color.Red; + foreach (RoomObj room in m_addedRooms) + { + foreach (EnemyObj enemy in room.EnemyList) + { + if (enemy.IsKilled == false && enemy.IsDemented == false && enemy.SaveToFile == true && enemy.Type != EnemyType.SpikeTrap && enemy.Type != EnemyType.Platform && enemy.Type != EnemyType.Turret) + { + m_playerSprite.Position = new Vector2(enemy.X / m_spriteScale.X - 9, enemy.Y / m_spriteScale.Y - 10) + CameraOffset; + m_playerSprite.Draw(camera); + } + } + } + } + m_playerSprite.TextureColor = Color.White; + + m_playerSprite.Position = new Vector2(m_level.Player.X / m_spriteScale.X - 9, m_level.Player.Y / m_spriteScale.Y - 10) + CameraOffset; //-10 to compensate for player width/height. + m_playerSprite.Draw(camera); + //camera.End(); + } + + public override void Draw(Camera2D camera) + { + if (this.Visible == true) + { + camera.End(); + camera.GraphicsDevice.Textures[1] = m_alphaMaskRT; + camera.GraphicsDevice.SamplerStates[1] = SamplerState.LinearClamp; + camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, Game.MaskEffect); + if (DrawNothing == false) + camera.Draw(m_mapScreenRT, Vector2.Zero, Color.White); + camera.End(); + + camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null); + if (DrawNothing == true) + m_playerSprite.Draw(camera); + } + } + + public void ClearRoomsAdded() + { + m_addedRooms.Clear(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + //Done + m_player = null; + m_level = null; + if (m_alphaMaskRT != null && m_alphaMaskRT.IsDisposed == false) + m_alphaMaskRT.Dispose(); + m_alphaMaskRT = null; + if (m_mapScreenRT != null && m_mapScreenRT.IsDisposed == false) + m_mapScreenRT.Dispose(); + m_mapScreenRT = null; + + foreach (SpriteObj sprite in m_roomSpriteList) + sprite.Dispose(); + m_roomSpriteList.Clear(); + m_roomSpriteList = null; + + foreach (SpriteObj sprite in m_doorSpriteList) + sprite.Dispose(); + m_doorSpriteList.Clear(); + m_doorSpriteList = null; + + foreach (SpriteObj sprite in m_iconSpriteList) + sprite.Dispose(); + m_iconSpriteList.Clear(); + m_iconSpriteList = null; + + m_addedRooms.Clear(); + m_addedRooms = null; + + m_roomSpritePosList.Clear(); + m_roomSpritePosList = null; + m_doorSpritePosList.Clear(); + m_doorSpritePosList = null; + m_iconSpritePosList.Clear(); + m_iconSpritePosList = null; + + m_playerSprite.Dispose(); + m_playerSprite = null; + + foreach (SpriteObj sprite in m_teleporterList) + sprite.Dispose(); + m_teleporterList.Clear(); + m_teleporterList = null; + m_teleporterPosList.Clear(); + m_teleporterPosList = null; + + m_xOffsetTween = null; + m_yOffsetTween = null; + + base.Dispose(); + } + } + + public List AddedRoomsList + { + get { return m_addedRooms; } + } + + protected override GameObj CreateCloneInstance() + { + return new MapObj(FollowPlayer, m_level); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + MapObj clone = obj as MapObj; + + clone.DrawTeleportersOnly = this.DrawTeleportersOnly; + clone.CameraOffsetX = this.CameraOffsetX; + clone.CameraOffsetY = this.CameraOffsetY; + + clone.InitializeAlphaMap(m_mapScreenRT, m_alphaMaskRT, m_alphaMaskRect); + clone.SetPlayer(m_player); + clone.AddAllRooms(m_addedRooms); + } + + public SpriteObj[] TeleporterList() + { + return m_teleporterList.ToArray(); + } + + public float CameraOffsetX + { + get { return CameraOffset.X; } + set { CameraOffset.X = value; } + } + + public float CameraOffsetY + { + get { return CameraOffset.Y; } + set { CameraOffset.Y = value; } + } + + } +} diff --git a/RogueCastle/src/Game Objects/NpcObj.cs b/RogueCastle/src/Game Objects/NpcObj.cs new file mode 100644 index 0000000..a8c9a46 --- /dev/null +++ b/RogueCastle/src/Game Objects/NpcObj.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class NpcObj : ObjContainer + { + private SpriteObj m_talkIcon; + private bool m_useArrowIcon; + public bool CanTalk { get; set; } + + public bool useArrowIcon + { + get { return m_useArrowIcon; } + set + { + if (m_useArrowIcon != value) + { + if (value == true) + { + m_talkIcon.ChangeSprite("UpArrowSquare_Sprite"); + m_talkIcon.Scale = new Vector2(1); + } + else + { + m_talkIcon.ChangeSprite("ExclamationBubble_Sprite"); + m_talkIcon.Scale = new Vector2(2); + } + } + + m_useArrowIcon = value; + } + } + + public NpcObj(string spriteName) + : base(spriteName) + { + CanTalk = true; + + m_talkIcon = new SpriteObj("ExclamationBubble_Sprite"); + m_talkIcon.Scale = new Vector2(2f, 2f); + m_talkIcon.Visible = false; + m_talkIcon.OutlineWidth = 2; + this.OutlineWidth = 2; + } + + public void Update(GameTime gameTime, PlayerObj player) + { + bool playerFacing = false; + if (this.Flip == SpriteEffects.None && player.X > this.X) + playerFacing = true; + if (this.Flip != SpriteEffects.None && player.X < this.X) + playerFacing = true; + + if (useArrowIcon == true) + playerFacing = true; + + Rectangle storedBounds = this.Bounds; + + if (player != null && CollisionMath.Intersects(player.TerrainBounds, new Rectangle(storedBounds.X - 50, storedBounds.Y, storedBounds.Width + 100, storedBounds.Height)) + && playerFacing == true && (player.Flip != this.Flip || useArrowIcon == true) && CanTalk == true && player.IsTouchingGround == true) + m_talkIcon.Visible = true; + else + m_talkIcon.Visible = false; + + if (useArrowIcon == false) + { + if (this.Flip == SpriteEffects.None) + m_talkIcon.Position = new Vector2(storedBounds.Left - m_talkIcon.AnchorX, storedBounds.Top - m_talkIcon.AnchorY + (float)Math.Sin(Game.TotalGameTime * 20) * 2); + else + m_talkIcon.Position = new Vector2(storedBounds.Right + m_talkIcon.AnchorX, storedBounds.Top - m_talkIcon.AnchorY + (float)Math.Sin(Game.TotalGameTime * 20) * 2); + } + else + { + m_talkIcon.Position = new Vector2(this.X, storedBounds.Top - 70 + (float)Math.Sin(Game.TotalGameTime * 20) * 2); + } + } + + public override void Draw(Camera2D camera) + { + if (this.Flip == SpriteEffects.None) + m_talkIcon.Flip = SpriteEffects.FlipHorizontally; + else + m_talkIcon.Flip = SpriteEffects.None; + + base.Draw(camera); + m_talkIcon.Draw(camera); + } + + public bool IsTouching + { + get { return m_talkIcon.Visible; } + } + + protected override GameObj CreateCloneInstance() + { + return new NpcObj(this.SpriteName); + } + + protected override void FillCloneInstance(object obj) + { + NpcObj clone = obj as NpcObj; + clone.useArrowIcon = this.useArrowIcon; + clone.CanTalk = this.CanTalk; + base.FillCloneInstance(obj); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_talkIcon.Dispose(); + m_talkIcon = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/BackToMenuOptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/BackToMenuOptionsObj.cs new file mode 100644 index 0000000..1b651a7 --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/BackToMenuOptionsObj.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class BackToMenuOptionsObj : OptionsObj + { + public BackToMenuOptionsObj(OptionsScreen parentScreen) + : base(parentScreen, "LOC_ID_BACK_TO_MENU_OPTIONS_1") //"Quit to Title Screen" + { + } + + public override void Initialize() + { + if (Game.PlayerStats.TutorialComplete == true) + m_nameText.Text = LocaleBuilder.getString("LOC_ID_BACK_TO_MENU_OPTIONS_1", m_nameText); //"Quit to Title Screen" + else + m_nameText.Text = LocaleBuilder.getString("LOC_ID_BACK_TO_MENU_OPTIONS_2", m_nameText); //"Quit to Title Screen (skip tutorial)" + + base.Initialize(); + } + + public void GoBackToTitle() + { + IsActive = false; + + ProceduralLevelScreen level = Game.ScreenManager.GetLevelScreen(); + //Special handling to revert your spell if you are in a carnival room. + if (level != null && (level.CurrentRoom is CarnivalShoot1BonusRoom || level.CurrentRoom is CarnivalShoot2BonusRoom)) + { + if (level.CurrentRoom is CarnivalShoot1BonusRoom) + (level.CurrentRoom as CarnivalShoot1BonusRoom).UnequipPlayer(); + if (level.CurrentRoom is CarnivalShoot2BonusRoom) + (level.CurrentRoom as CarnivalShoot2BonusRoom).UnequipPlayer(); + } + + // A check to make sure challenge rooms do not override player save data. + if (level != null) + { + ChallengeBossRoomObj challengeRoom = level.CurrentRoom as ChallengeBossRoomObj; + if (challengeRoom != null) + { + challengeRoom.LoadPlayerData(); // Make sure this is loaded before upgrade data, otherwise player equipment will be overridden. + (m_parentScreen.ScreenManager.Game as Game).SaveManager.LoadFiles(level, SaveType.UpgradeData); + level.Player.CurrentHealth = challengeRoom.StoredHP; + level.Player.CurrentMana = challengeRoom.StoredMP; + } + } + + // This code is needed otherwise the lineage data will still be on Revision 0 when the game exits, but player data is Rev1 + // which results in a mismatch. + if (Game.PlayerStats.RevisionNumber <= 0) + (m_parentScreen.ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.Lineage); + (m_parentScreen.ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData, SaveType.UpgradeData); + + if (Game.PlayerStats.TutorialComplete == true && level != null && level.CurrentRoom.Name != "Start" && level.CurrentRoom.Name != "Ending" && level.CurrentRoom.Name != "Tutorial") + (m_parentScreen.ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.MapData); + + Game.ScreenManager.DisplayScreen(ScreenType.Title, true); + } + + public void CancelCommand() + { + IsActive = false; + } + + public override bool IsActive + { + get { return base.IsActive; } + set + { + base.IsActive = value; + if (IsActive == true) + { + RCScreenManager manager = m_parentScreen.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("Back to Menu"); + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "GoBackToTitle"); + manager.DialogueScreen.SetCancelEndHandler(this, "CancelCommand"); + manager.DisplayScreen(ScreenType.Dialogue, false, null); + } + } + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/ChangeControlsOptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/ChangeControlsOptionsObj.cs new file mode 100644 index 0000000..e69de1d --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/ChangeControlsOptionsObj.cs @@ -0,0 +1,545 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Input; + +namespace RogueCastle +{ + public class ChangeControlsOptionsObj : OptionsObj + { + List m_buttonTitle; + List m_keyboardControls; + List m_gamepadControls; + + private int m_selectedEntryIndex = 0; + private TextObj m_selectedEntry; + + private KeyIconTextObj m_selectedButton; + private ObjContainer m_setKeyPlate; + + private bool m_settingKey = false; + + private int[] m_controlKeys; + private bool m_lockControls = false; + + private int m_startingY = -200; + + private SpriteObj m_selectionBar; + + public ChangeControlsOptionsObj(OptionsScreen parentScreen) + : base(parentScreen, "LOC_ID_CHANGE_CONTROLS_OPTIONS_1") //"Change Controls" + { + m_buttonTitle = new List(); + m_keyboardControls = new List(); + m_gamepadControls = new List(); + + TextObj textTemplate = new TextObj(Game.JunicodeFont); + textTemplate.FontSize = 12; + textTemplate.DropShadow = new Vector2(2, 2); + + string[] controlTitleIDs = new string[] { + "LOC_ID_CHANGE_CONTROLS_OPTIONS_2", //"Up", + "LOC_ID_CHANGE_CONTROLS_OPTIONS_3", //"Down", + "LOC_ID_CHANGE_CONTROLS_OPTIONS_4", //"Left", + "LOC_ID_CHANGE_CONTROLS_OPTIONS_5", //"Right", + "LOC_ID_CHANGE_CONTROLS_OPTIONS_6", //"Attack", + "LOC_ID_CHANGE_CONTROLS_OPTIONS_7", //"Jump", + "LOC_ID_CHANGE_CONTROLS_OPTIONS_8", //"Special", + "LOC_ID_CHANGE_CONTROLS_OPTIONS_9", //"Dash Left", + "LOC_ID_CHANGE_CONTROLS_OPTIONS_10", //"Dash Right", + "LOC_ID_CHANGE_CONTROLS_OPTIONS_11", //"Cast Spell", + "LOC_ID_CHANGE_CONTROLS_OPTIONS_12" //"Reset Controls" + }; + m_controlKeys = new int[] {InputMapType.PLAYER_UP1, InputMapType.PLAYER_DOWN1, InputMapType.PLAYER_LEFT1, InputMapType.PLAYER_RIGHT1, InputMapType.PLAYER_ATTACK, + InputMapType.PLAYER_JUMP1, InputMapType.PLAYER_BLOCK, InputMapType.PLAYER_DASHLEFT, InputMapType.PLAYER_DASHRIGHT, InputMapType.PLAYER_SPELL1, + -1}; + + for (int i = 0; i < controlTitleIDs.Length; i++) + { + TextObj textTitle = textTemplate.Clone() as TextObj; + textTitle.Text = LocaleBuilder.getString(controlTitleIDs[i], textTitle); + textTitle.X = 1320; + textTitle.Y = m_startingY + i * 30; + this.AddChild(textTitle); + m_buttonTitle.Add(textTitle); + + KeyIconTextObj keyTitle = new KeyIconTextObj(Game.JunicodeFont); + keyTitle.FontSize = 9; + keyTitle.X = textTitle.X + 200; + keyTitle.Y = textTitle.Y + 5; + this.AddChild(keyTitle); + m_keyboardControls.Add(keyTitle); + + KeyIconTextObj buttonTitle = new KeyIconTextObj(Game.JunicodeFont); + buttonTitle.FontSize = 9; + buttonTitle.X = keyTitle.X + 200; + buttonTitle.Y = keyTitle.Y; + this.AddChild(buttonTitle); + m_gamepadControls.Add(buttonTitle); + } + + UpdateKeyBindings(); + + m_setKeyPlate = new ObjContainer("GameOverStatPlate_Character"); + m_setKeyPlate.ForceDraw = true; + m_setKeyPlate.Scale = Vector2.Zero; + TextObj pressAnyKeyText = new TextObj(Game.JunicodeFont); + pressAnyKeyText.FontSize = 12; + pressAnyKeyText.Align = Types.TextAlign.Centre; + pressAnyKeyText.DropShadow = new Vector2(2, 2); + pressAnyKeyText.ForceDraw = true; + pressAnyKeyText.Text = LocaleBuilder.getString("LOC_ID_CHANGE_CONTROLS_OPTIONS_14", pressAnyKeyText); //"Press Any Key" + pressAnyKeyText.Y -= pressAnyKeyText.Height / 2f; + m_setKeyPlate.AddChild(pressAnyKeyText); + + m_selectionBar = new SpriteObj("OptionsBar_Sprite"); + } + + private void OnEnter() + { + m_selectedEntryIndex = 0; + m_selectedEntry = m_buttonTitle[m_selectedEntryIndex]; + m_selectedEntry.TextureColor = Color.Yellow; + m_selectedButton = null; + + m_settingKey = false; + m_lockControls = false; + m_setKeyPlate.Scale = Vector2.Zero; + m_setKeyPlate.Position = new Vector2(1320 / 2, 720 / 2); + } + + private void OnExit() + { + if (m_selectedEntry != null) + m_selectedEntry.TextureColor = Color.White; + if (m_selectedButton != null) + m_selectedButton.TextureColor = Color.White; + } + + public override void HandleInput() + { + if (m_lockControls == false) + { + if (m_settingKey == false) + { + int previousSelectedEntry = m_selectedEntryIndex; + + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + SoundManager.PlaySound("frame_swap"); + m_selectedEntryIndex--; + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN2)) + { + SoundManager.PlaySound("frame_swap"); + m_selectedEntryIndex++; + } + + if (m_selectedEntryIndex > m_buttonTitle.Count - 1) + m_selectedEntryIndex = 0; + if (m_selectedEntryIndex < 0) + m_selectedEntryIndex = m_buttonTitle.Count - 1; + + if (previousSelectedEntry != m_selectedEntryIndex) + { + m_selectedEntry.TextureColor = Color.White; + m_selectedEntry = m_buttonTitle[m_selectedEntryIndex]; + m_selectedEntry.TextureColor = Color.Yellow; + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + SoundManager.PlaySound("Option_Menu_Select"); + + m_lockControls = true; + if (m_selectedEntryIndex == m_controlKeys.Length - 1) + { + RCScreenManager manager = Game.ScreenManager; + manager.DialogueScreen.SetDialogue("RestoreDefaultControlsWarning"); + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "RestoreControls"); + manager.DialogueScreen.SetCancelEndHandler(this, "CancelRestoreControls"); + manager.DisplayScreen(ScreenType.Dialogue, true); + } + else + { + Tweener.Tween.To(m_setKeyPlate, 0.3f, Tweener.Ease.Back.EaseOut, "ScaleX", "1", "ScaleY", "1"); + Tweener.Tween.AddEndHandlerToLastTween(this, "SetKeyTrue"); + } + } + else if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + IsActive = false; + + base.HandleInput(); + } + else + { + if (InputManager.AnyButtonPressed(PlayerIndex.One) || InputManager.AnyKeyPressed() || InputManager.AnyMousePressed()) + ChangeKey(); + } + } + } + + public void SetKeyTrue() + { + m_settingKey = true; + m_lockControls = false; + } + + private void ChangeKey() + { + // The player has input an invalid key. + if (InputManager.AnyKeyPressed() == true) + { + Keys keyPressed = InputManager.KeysPressedArray[0]; + if (InputReader.GetInputString(keyPressed, false, false, false).ToUpper() == "") + return; + + bool unbindable = false; + Keys[] unbindableKeys = new Keys[] + { + Keys.Tab, Keys.CapsLock, Keys.LeftShift, Keys.LeftControl, Keys.LeftAlt, + Keys.RightAlt, Keys.RightControl, Keys.RightShift, Keys.Enter, Keys.Back, + Keys.Space, Keys.Left, Keys.Right, Keys.Up, Keys.Down, + }; + + foreach (Keys unbindableKey in unbindableKeys) + { + if (keyPressed == unbindableKey) + { + unbindable = true; + break; + } + } + + // Unbindable keys. + if (unbindable == true) + return; + + // Cancel changing keys. + if (keyPressed == Keys.Escape) + { + Tweener.Tween.To(m_setKeyPlate, 0.3f, Tweener.Ease.Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + m_settingKey = false; + return; + } + } + else if (InputManager.AnyButtonPressed(PlayerIndex.One) == true) + { + Buttons buttonPressed = InputManager.ButtonsPressedArray(PlayerIndex.One)[0]; + + // Unbindable buttons. + if (buttonPressed == Buttons.Start || buttonPressed == Buttons.Back) + return; + + bool unbindable = false; + Buttons[] unbindableButtons = new Buttons[] + { + Buttons.Start, Buttons.Back, + Buttons.LeftThumbstickLeft, Buttons.LeftThumbstickRight, Buttons.LeftThumbstickUp, Buttons.LeftThumbstickDown, + Buttons.RightThumbstickLeft, Buttons.RightThumbstickRight, Buttons.RightThumbstickUp, Buttons.RightThumbstickDown, + }; + + foreach (Buttons unbindableButton in unbindableButtons) + { + if (buttonPressed == unbindableButton) + { + unbindable = true; + break; + } + } + + // Unbindable buttons. + if (unbindable == true) + return; + } + + SoundManager.PlaySound("Gen_Menu_Toggle"); + Tweener.Tween.To(m_setKeyPlate, 0.3f, Tweener.Ease.Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + m_settingKey = false; + + // Register Gamepad input first. + if (InputManager.AnyButtonPressed(PlayerIndex.One) == true) + { + // a list of buttons that are exempt from being unassigned. + int[] exemptButtons = new int[] { + InputMapType.MENU_CONFIRM1, + InputMapType.MENU_CONFIRM2, + InputMapType.MENU_CONFIRM3, + InputMapType.MENU_CANCEL1, + InputMapType.MENU_CANCEL2, + InputMapType.MENU_CANCEL3, + InputMapType.MENU_CREDITS, + InputMapType.MENU_OPTIONS, + InputMapType.MENU_PAUSE, + InputMapType.MENU_PROFILECARD, + InputMapType.MENU_ROGUEMODE, + }; + + Buttons buttonPressed = InputManager.ButtonsPressedArray(PlayerIndex.One)[0]; + + // Swap the button from the buttons list. Prevents duplicate button bindings. + for (int i = 0; i < Game.GlobalInput.ButtonList.Count; i++) + { + // Make sure not to unassign "locked" buttons. + bool unassignButton = true; + foreach (int exemptButton in exemptButtons) + { + if (i == exemptButton) + { + unassignButton = false; + break; + } + } + + if (unassignButton == true) + { + if (Game.GlobalInput.ButtonList[i] == buttonPressed) + Game.GlobalInput.ButtonList[i] = Game.GlobalInput.ButtonList[m_controlKeys[m_selectedEntryIndex]]; + } + } + + Game.GlobalInput.ButtonList[m_controlKeys[m_selectedEntryIndex]] = buttonPressed; + } + else if (InputManager.AnyKeyPressed() == true || InputManager.AnyMousePressed()) + { + Keys keyPressed = Keys.None; + if (InputManager.AnyMousePressed() == true) + { + if (InputManager.MouseLeftJustPressed()) + keyPressed = Keys.F13; + else if (InputManager.MouseRightJustPressed()) + keyPressed = Keys.F14; + else if (InputManager.MouseMiddleJustPressed()) + keyPressed = Keys.F15; + } + else + keyPressed = InputManager.KeysPressedArray[0]; + + // a list of keys that are exempt from being unassigned. + int[] exemptKeys = new int[] { + InputMapType.MENU_CONFIRM1, + InputMapType.MENU_CONFIRM2, + InputMapType.MENU_CONFIRM3, + InputMapType.MENU_CANCEL1, + InputMapType.MENU_CANCEL2, + InputMapType.MENU_CONFIRM3, + InputMapType.MENU_CREDITS, + InputMapType.MENU_OPTIONS, + InputMapType.MENU_PAUSE, + InputMapType.MENU_PROFILECARD, + InputMapType.MENU_ROGUEMODE, + }; + + // Swap the button from the key list. Prevents duplicate key bindings. + for (int i = 0; i < Game.GlobalInput.KeyList.Count; i++) + { + // Make sure not to unassign "locked" keys. + bool unassignKey = true; + foreach (int exemptKey in exemptKeys) + { + if (i == exemptKey) + { + unassignKey = false; + break; + } + } + + if (unassignKey == true) + { + if (Game.GlobalInput.KeyList[i] == keyPressed) + Game.GlobalInput.KeyList[i] = Game.GlobalInput.KeyList[m_controlKeys[m_selectedEntryIndex]]; + //Game.GlobalInput.KeyList[i] = 0; + } + } + + Game.GlobalInput.KeyList[m_controlKeys[m_selectedEntryIndex]] = keyPressed; + } + + UpdateKeyBindings(); + } + + private void UpdateKeyBindings() + { + for (int i = 0; i < m_keyboardControls.Count; i++) + { + if (m_controlKeys[i] == -1) + { + m_keyboardControls[i].Text = ""; + m_gamepadControls[i].Text = ""; + } + else + { + switch (m_controlKeys[i]) + { + case (InputMapType.PLAYER_DOWN1): + m_keyboardControls[i].Text = "[Key:" + Game.GlobalInput.KeyList[m_controlKeys[i]] + "], [Key:" + Game.GlobalInput.KeyList[InputMapType.PLAYER_DOWN2] + "]"; + break; + case (InputMapType.PLAYER_UP1): + m_keyboardControls[i].Text = "[Key:" + Game.GlobalInput.KeyList[m_controlKeys[i]] + "], [Key:" + Game.GlobalInput.KeyList[InputMapType.PLAYER_UP2] + "]"; + break; + case (InputMapType.PLAYER_LEFT1): + m_keyboardControls[i].Text = "[Key:" + Game.GlobalInput.KeyList[m_controlKeys[i]] + "], [Key:" + Game.GlobalInput.KeyList[InputMapType.PLAYER_LEFT2] + "]"; + break; + case (InputMapType.PLAYER_RIGHT1): + m_keyboardControls[i].Text = "[Key:" + Game.GlobalInput.KeyList[m_controlKeys[i]] + "], [Key:" + Game.GlobalInput.KeyList[InputMapType.PLAYER_RIGHT2] + "]"; + break; + case (InputMapType.PLAYER_JUMP1): + m_keyboardControls[i].Text = "[Key:" + Game.GlobalInput.KeyList[m_controlKeys[i]] + "], [Key:" + Game.GlobalInput.KeyList[InputMapType.PLAYER_JUMP2] + "]"; + break; + default: + m_keyboardControls[i].Text = "[Key:" + Game.GlobalInput.KeyList[m_controlKeys[i]] + "]"; + break; + } + + // Just a tiny hack to better centre the mouse icons. + switch (Game.GlobalInput.KeyList[m_controlKeys[i]]) + { + case(Keys.F13): + case(Keys.F14): + case(Keys.F15): + switch (m_controlKeys[i]) + { + case (InputMapType.PLAYER_DOWN1): + m_keyboardControls[i].Text = " [Key:" + Game.GlobalInput.KeyList[m_controlKeys[i]] + "], [Key:" + Game.GlobalInput.KeyList[InputMapType.PLAYER_DOWN2] + "]"; + break; + case (InputMapType.PLAYER_UP1): + m_keyboardControls[i].Text = " [Key:" + Game.GlobalInput.KeyList[m_controlKeys[i]] + "], [Key:" + Game.GlobalInput.KeyList[InputMapType.PLAYER_UP2] + "]"; + break; + case (InputMapType.PLAYER_LEFT1): + m_keyboardControls[i].Text = " [Key:" + Game.GlobalInput.KeyList[m_controlKeys[i]] + "], [Key:" + Game.GlobalInput.KeyList[InputMapType.PLAYER_LEFT2] + "]"; + break; + case (InputMapType.PLAYER_RIGHT1): + m_keyboardControls[i].Text = " [Key:" + Game.GlobalInput.KeyList[m_controlKeys[i]] + "], [Key:" + Game.GlobalInput.KeyList[InputMapType.PLAYER_RIGHT2] + "]"; + break; + case (InputMapType.PLAYER_JUMP1): + m_keyboardControls[i].Text = " [Key:" + Game.GlobalInput.KeyList[m_controlKeys[i]] + "], [Key:" + Game.GlobalInput.KeyList[InputMapType.PLAYER_JUMP2] + "]"; + break; + default: + m_keyboardControls[i].Text = " [Key:" + Game.GlobalInput.KeyList[m_controlKeys[i]] + "]"; + break; + } + break; + } + + m_gamepadControls[i].Text = "[Button:" + Game.GlobalInput.ButtonList[m_controlKeys[i]] + "]"; + + if (Game.GlobalInput.ButtonList[m_controlKeys[i]] == 0) + m_gamepadControls[i].Text = ""; + + if (Game.GlobalInput.KeyList[m_controlKeys[i]] == 0) + m_keyboardControls[i].Text = ""; + } + } + + // Special code so that player attack acts as the second confirm and player jump acts as the second cancel. + Game.GlobalInput.KeyList[InputMapType.MENU_CONFIRM2] = Game.GlobalInput.KeyList[InputMapType.PLAYER_ATTACK]; + Game.GlobalInput.KeyList[InputMapType.MENU_CANCEL2] = Game.GlobalInput.KeyList[InputMapType.PLAYER_JUMP1]; + } + + public void RestoreControls() + { + Game.InitializeGlobalInput(); + UpdateKeyBindings(); + m_lockControls = false; + } + + public void CancelRestoreControls() + { + m_lockControls = false; + } + + public override void Draw(Camera2D camera) + { + + base.Draw(camera); + m_setKeyPlate.Draw(camera); + + if (m_selectedEntry != null) + { + m_selectionBar.Position = new Vector2(m_selectedEntry.AbsX - 15, m_selectedEntry.AbsY); + m_selectionBar.Draw(camera); + } + } + + public override void RefreshTextObjs() + { + foreach (TextObj textObj in m_buttonTitle) + { + textObj.FontSize = 12; + textObj.ScaleX = 1; + } + + switch (LocaleBuilder.languageType) + { + case (LanguageType.French): + m_buttonTitle[7].ScaleX = 0.9f; + m_buttonTitle[8].ScaleX = 0.9f; + break; + case (LanguageType.German): + m_buttonTitle[9].ScaleX = 0.8f; + break; + case (LanguageType.Portuguese_Brazil): + m_buttonTitle[7].ScaleX = 0.9f; + break; + case (LanguageType.Spanish_Spain): + m_buttonTitle[7].FontSize = 10; + m_buttonTitle[8].FontSize = 10; + m_buttonTitle[7].ScaleX = 0.8f; + m_buttonTitle[8].ScaleX = 0.8f; + break; + } + + base.RefreshTextObjs(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_buttonTitle.Clear(); + m_buttonTitle = null; + m_keyboardControls.Clear(); + m_keyboardControls = null; + m_gamepadControls.Clear(); + m_gamepadControls = null; + + m_selectedEntry = null; + m_selectedButton = null; + + m_setKeyPlate.Dispose(); + m_setKeyPlate = null; + + Array.Clear(m_controlKeys, 0, m_controlKeys.Length); + m_controlKeys = null; + + m_selectionBar.Dispose(); + m_selectionBar = null; + + base.Dispose(); + } + } + + public override bool IsActive + { + get { return base.IsActive; } + set + { + if (value == true) + OnEnter(); + else + OnExit(); + + if (value != m_isActive) + m_parentScreen.ToggleControlsConfig(); + + base.IsActive = value; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/DeadZoneOptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/DeadZoneOptionsObj.cs new file mode 100644 index 0000000..5e531f4 --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/DeadZoneOptionsObj.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; + +namespace RogueCastle +{ + public class DeadZoneOptionsObj : OptionsObj + { + private SpriteObj m_deadZoneBarBG; + private SpriteObj m_deadZoneBar; + + public DeadZoneOptionsObj(OptionsScreen parentScreen) + : base(parentScreen, "LOC_ID_DEAD_ZONE_OPTIONS_1") //"Joystick Dead Zone" + { + m_deadZoneBarBG = new SpriteObj("OptionsScreenVolumeBG_Sprite"); + m_deadZoneBarBG.X = m_optionsTextOffset; + m_deadZoneBarBG.Y = m_deadZoneBarBG.Height / 2f - 2; + this.AddChild(m_deadZoneBarBG); + + m_deadZoneBar = new SpriteObj("OptionsScreenVolumeBar_Sprite"); + m_deadZoneBar.X = m_deadZoneBarBG.X + 6; + m_deadZoneBar.Y = m_deadZoneBarBG.Y + 5; + this.AddChild(m_deadZoneBar); + } + + public override void Initialize() + { + m_deadZoneBar.ScaleX = InputManager.Deadzone / 95f; + base.Initialize(); + } + + public override void HandleInput() + { + if (Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT2)) + { + if (InputManager.Deadzone - 1 >= 0) + { + InputManager.Deadzone -= 1; + UpdateDeadZoneBar(); + } + } + else if (Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT2)) + { + if (InputManager.Deadzone + 1 <= 95) + { + InputManager.Deadzone += 1; + UpdateDeadZoneBar(); + } + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || + Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + IsActive = false; + } + + base.HandleInput(); + } + + public void UpdateDeadZoneBar() + { + m_deadZoneBar.ScaleX = InputManager.Deadzone / 95f; + } + + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_deadZoneBar = null; + m_deadZoneBarBG = null; + base.Dispose(); + } + } + + public override bool IsActive + { + get { return base.IsActive; } + set + { + base.IsActive = value; + if (value == true) + m_deadZoneBar.TextureColor = Color.Yellow; + else + m_deadZoneBar.TextureColor = Color.White; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/DeleteSaveOptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/DeleteSaveOptionsObj.cs new file mode 100644 index 0000000..eb6b507 --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/DeleteSaveOptionsObj.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class DeleteSaveOptionsObj : OptionsObj + { + public DeleteSaveOptionsObj(OptionsScreen parentScreen) + : base(parentScreen, "LOC_ID_DELETE_SAVE_OPTIONS_1") //"Delete Save" + { + } + + public override bool IsActive + { + get { return base.IsActive; } + set + { + base.IsActive = value; + if (IsActive == true) + { + RCScreenManager manager = m_parentScreen.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("Delete Save"); + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "DeleteSaveAskAgain"); + manager.DialogueScreen.SetCancelEndHandler(this, "CancelCommand"); + manager.DisplayScreen(ScreenType.Dialogue, false, null); + } + } + } + + public void CancelCommand() + { + IsActive = false; + } + + public void DeleteSaveAskAgain() + { + RCScreenManager manager = m_parentScreen.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("Delete Save2"); + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "DeleteSave"); + manager.DialogueScreen.SetCancelEndHandler(this, "CancelCommand"); + manager.DisplayScreen(ScreenType.Dialogue, false, null); + } + + public void DeleteSave() + { + IsActive = false; + Game.PlayerStats.Dispose(); + (m_parentScreen.ScreenManager.Game as Game).SaveManager.ClearAllFileTypes(false); + (m_parentScreen.ScreenManager.Game as Game).SaveManager.ClearAllFileTypes(true); + SkillSystem.ResetAllTraits(); + Game.PlayerStats = new PlayerStats(); + (m_parentScreen.ScreenManager as RCScreenManager).Player.Reset(); + SoundManager.StopMusic(1); + + (m_parentScreen.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.TutorialRoom, true); + //(m_parentScreen.ScreenManager as RCScreenManager).HideCurrentScreen(); + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/ExitProgramOptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/ExitProgramOptionsObj.cs new file mode 100644 index 0000000..eeb34d8 --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/ExitProgramOptionsObj.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class ExitProgramOptionsObj : OptionsObj + { + public ExitProgramOptionsObj(OptionsScreen parentScreen) + : base(parentScreen, "LOC_ID_EXIT_ROGUE_LEGACY_OPTIONS_1") //"Quit Rogue Legacy" + { + } + + public void QuitProgram() + { + (m_parentScreen.ScreenManager.Game as Game).SaveOnExit(); + m_parentScreen.ScreenManager.Game.Exit(); + } + + public void CancelCommand() + { + IsActive = false; + } + + public override bool IsActive + { + get { return base.IsActive; } + set + { + base.IsActive = value; + if (IsActive == true) + { + RCScreenManager manager = m_parentScreen.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("Quit Rogue Legacy"); + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "QuitProgram"); + manager.DialogueScreen.SetCancelEndHandler(this, "CancelCommand"); + manager.DisplayScreen(ScreenType.Dialogue, false, null); + } + } + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/FullScreenOptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/FullScreenOptionsObj.cs new file mode 100644 index 0000000..ee2f8db --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/FullScreenOptionsObj.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class FullScreenOptionsObj : OptionsObj + { + private TextObj m_toggleText; + + public FullScreenOptionsObj(OptionsScreen parentScreen) + : base(parentScreen, "LOC_ID_OPTIONS_SCREEN_11") + { + m_toggleText = m_nameText.Clone() as TextObj; + m_toggleText.X = m_optionsTextOffset; + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + this.AddChild(m_toggleText); + } + + public override void Initialize() + { + if ((m_parentScreen.ScreenManager.Game as Game).graphics.IsFullScreen == true) + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_3", m_toggleText); //"Yes" + else + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + base.Initialize(); + } + + public override void HandleInput() + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT2) + || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT2)) + { + SoundManager.PlaySound("frame_swap"); + if (m_toggleText.Text == LocaleBuilder.getResourceString("LOC_ID_QUICKDROP_OPTIONS_2")) // "No" + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_3", m_toggleText); //"Yes" + else + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + SoundManager.PlaySound("Option_Menu_Select"); + + GraphicsDeviceManager graphics = (m_parentScreen.ScreenManager.Game as Game).graphics; + if ((m_toggleText.Text == LocaleBuilder.getResourceString("LOC_ID_QUICKDROP_OPTIONS_2") && graphics.IsFullScreen == true) || + (m_toggleText.Text == LocaleBuilder.getResourceString("LOC_ID_QUICKDROP_OPTIONS_3") && graphics.IsFullScreen == false)) + { + ToggleFullscreen(graphics); + this.IsActive = false; + //Tweener.Tween.RunFunction(0, this, "ToggleFullscreen", graphics); + } + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + if ((m_parentScreen.ScreenManager.Game as Game).graphics.IsFullScreen == true) + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_3", m_toggleText); //"Yes" + else + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + this.IsActive = false; + } + + base.HandleInput(); + } + + public void ToggleFullscreen(GraphicsDeviceManager graphics) + { + //if (graphics.IsFullScreen == false) + // graphics.PreferMultiSampling = false; + //else + // graphics.PreferMultiSampling = true; + graphics.ToggleFullScreen(); + + Game.GameConfig.FullScreen = graphics.IsFullScreen; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_toggleText = null; + base.Dispose(); + } + } + + public override bool IsActive + { + get { return base.IsActive; } + set + { + base.IsActive = value; + if (value == true) + m_toggleText.TextureColor = Color.Yellow; + else + m_toggleText.TextureColor = Color.White; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/LanguageOptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/LanguageOptionsObj.cs new file mode 100644 index 0000000..96423d9 --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/LanguageOptionsObj.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using DS2DEngine; + +namespace RogueCastle +{ + public class LanguageOptionsObj : OptionsObj + { + private LanguageType m_languageType; + private LanguageType m_storedLanguageType; + private TextObj m_toggleText; + + public LanguageOptionsObj(OptionsScreen parentScreen) + : base(parentScreen, "LOC_ID_OPTIONS_LANGUAGE_TITLE") + { + m_toggleText = m_nameText.Clone() as TextObj; + m_toggleText.X = m_optionsTextOffset; + m_toggleText.Text = "null"; + this.AddChild(m_toggleText); + } + + public override void Initialize() + { + m_languageType = LocaleBuilder.languageType; + m_storedLanguageType = m_languageType; + UpdateText(); + } + + private void UpdateText() + { + switch (m_languageType) + { + case (LanguageType.English): + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_LANGUAGE_ENGLISH", m_toggleText); + break; + case (LanguageType.French): + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_LANGUAGE_FRENCH", m_toggleText); + break; + case (LanguageType.German): + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_LANGUAGE_GERMAN", m_toggleText); + break; + case (LanguageType.Russian): + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_LANGUAGE_RUSSIAN", m_toggleText); + break; + case (LanguageType.Portuguese_Brazil): + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_LANGUAGE_PORTUGUESE", m_toggleText); + break; + case (LanguageType.Spanish_Spain): + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_LANGUAGE_SPANISH", m_toggleText); + break; + case (LanguageType.Polish): + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_LANGUAGE_POLISH", m_toggleText); + break; + case (LanguageType.Chinese_Simp): + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_LANGUAGE_CHINESE", m_toggleText); + break; + } + } + + private void ChangeLanguageUp() + { + int languageType = (int)m_languageType; + languageType++; + if (languageType >= (int)LanguageType.MAX) + languageType = 0; + + m_languageType = (LanguageType)languageType; + UpdateText(); + } + + private void ChangeLanguageDown() + { + int languageType = (int)m_languageType; + languageType--; + if (languageType < 0) + languageType = (int)LanguageType.MAX - 1; + + m_languageType = (LanguageType)languageType; + UpdateText(); + } + + private void HandleConfirm() + { + LocaleBuilder.languageType = m_languageType; + m_storedLanguageType = m_languageType; + LocaleBuilder.RefreshAllText(); + } + + private void HandleCancel() + { + m_languageType = m_storedLanguageType; + UpdateText(); + } + + public override void HandleInput() + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT2)) + { + SoundManager.PlaySound("frame_swap"); + ChangeLanguageDown(); + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT2)) + { + SoundManager.PlaySound("frame_swap"); + ChangeLanguageUp(); + } + else if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + SoundManager.PlaySound("Option_Menu_Select"); + HandleConfirm(); + this.IsActive = false; + } + else if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + HandleCancel(); + this.IsActive = false; + } + + base.HandleInput(); + } + + public override void RefreshTextObjs() + { + m_toggleText.ScaleX = 1; + m_toggleText.FontSize = 12; + switch (LocaleBuilder.languageType) + { + case(LanguageType.German): + case(LanguageType.Portuguese_Brazil): + m_toggleText.ScaleX = 0.9f; + break; + case (LanguageType.Polish): + m_toggleText.FontSize = 11; + m_toggleText.ScaleX = 0.9f; + break; + } + + base.RefreshTextObjs(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_toggleText = null; + base.Dispose(); + } + } + + public override bool IsActive + { + get { return base.IsActive; } + set + { + base.IsActive = value; + if (value == true) + m_toggleText.TextureColor = Color.Yellow; + else + m_toggleText.TextureColor = Color.White; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/MusicVolOptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/MusicVolOptionsObj.cs new file mode 100644 index 0000000..ddf4905 --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/MusicVolOptionsObj.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class MusicVolOptionsObj : OptionsObj + { + private SpriteObj m_volumeBarBG; + private SpriteObj m_volumeBar; + + public MusicVolOptionsObj(OptionsScreen parentScreen) + : base(parentScreen, "LOC_ID_MUSICVOL_OPTIONS_1") //"Music Volume" + { + m_volumeBarBG = new SpriteObj("OptionsScreenVolumeBG_Sprite"); + m_volumeBarBG.X = m_optionsTextOffset; + m_volumeBarBG.Y = m_volumeBarBG.Height / 2f - 2; + this.AddChild(m_volumeBarBG); + + m_volumeBar = new SpriteObj("OptionsScreenVolumeBar_Sprite"); + m_volumeBar.X = m_volumeBarBG.X + 6; + m_volumeBar.Y = m_volumeBarBG.Y + 5; + this.AddChild(m_volumeBar); + } + + public override void Initialize() + { + m_volumeBar.ScaleX = SoundManager.GlobalMusicVolume; + base.Initialize(); + } + + public override void HandleInput() + { + if (Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT2)) + { + SoundManager.GlobalMusicVolume -= 0.01f; + SetVolumeLevel(); + } + else if (Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT2)) + { + SoundManager.GlobalMusicVolume += 0.01f; + SetVolumeLevel(); + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || + Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + IsActive = false; + } + + base.HandleInput(); + } + + public void SetVolumeLevel() + { + m_volumeBar.ScaleX = SoundManager.GlobalMusicVolume; + Game.GameConfig.MusicVolume = SoundManager.GlobalMusicVolume; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_volumeBar = null; + m_volumeBarBG = null; + base.Dispose(); + } + } + + public override bool IsActive + { + get { return base.IsActive; } + set + { + base.IsActive = value; + if (value == true) + m_volumeBar.TextureColor = Color.Yellow; + else + m_volumeBar.TextureColor = Color.White; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/OptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/OptionsObj.cs new file mode 100644 index 0000000..1181213 --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/OptionsObj.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public abstract class OptionsObj : ObjContainer + { + protected bool m_isSelected = false; + protected bool m_isActive = false; + + protected TextObj m_nameText; + protected OptionsScreen m_parentScreen; + protected int m_optionsTextOffset = 300; + + public OptionsObj(OptionsScreen parentScreen, string nameLocID) + { + m_parentScreen = parentScreen; + + m_nameText = new TextObj(Game.JunicodeFont); + m_nameText.FontSize = 12; + m_nameText.Text = LocaleBuilder.getString(nameLocID, m_nameText, true); + m_nameText.DropShadow = new Vector2(2, 2); + this.AddChild(m_nameText); + + this.ForceDraw = true; + } + + public virtual void Initialize() { } + + public virtual void HandleInput() + { + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + SoundManager.PlaySound("Options_Menu_Deselect"); + } + + public virtual void Update(GameTime gameTime) { } + + public virtual void RefreshTextObjs() { } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_parentScreen = null; + m_nameText = null; + base.Dispose(); + } + } + + public virtual bool IsActive + { + get { return m_isActive; } + set + { + if (value == true) + IsSelected = false; + else + IsSelected = true; + m_isActive = value; + + if (value == false) + (m_parentScreen.ScreenManager.Game as Game).SaveConfig(); + } + } + + public bool IsSelected + { + get { return m_isSelected; } + set + { + m_isSelected = value; + if (value == true) + m_nameText.TextureColor = Color.Yellow; + else + m_nameText.TextureColor = Color.White; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/QuickDropOptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/QuickDropOptionsObj.cs new file mode 100644 index 0000000..be11081 --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/QuickDropOptionsObj.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class QuickDropOptionsObj : OptionsObj + { + private TextObj m_toggleText; + + public QuickDropOptionsObj(OptionsScreen parentScreen) + : base(parentScreen, "LOC_ID_QUICKDROP_OPTIONS_1") //"Enable Quick Drop" + { + m_toggleText = m_nameText.Clone() as TextObj; + m_toggleText.X = m_optionsTextOffset; + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + this.AddChild(m_toggleText); + } + + public override void Initialize() + { + if (Game.GameConfig.QuickDrop == true) + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_3", m_toggleText); //"Yes" + else + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + base.Initialize(); + } + + public override void HandleInput() + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT2) + || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT2)) + { + SoundManager.PlaySound("frame_swap"); + if (m_toggleText.Text == LocaleBuilder.getResourceString("LOC_ID_QUICKDROP_OPTIONS_2")) // "No" + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_3", m_toggleText); //"Yes" + else + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + SoundManager.PlaySound("Option_Menu_Select"); + if (m_toggleText.Text == LocaleBuilder.getResourceString("LOC_ID_QUICKDROP_OPTIONS_3")) // "Yes" + Game.GameConfig.QuickDrop = true; + else + Game.GameConfig.QuickDrop = false; + this.IsActive = false; + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + if (Game.GameConfig.QuickDrop == true) + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_3", m_toggleText); //"Yes" + else + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + this.IsActive = false; + } + + base.HandleInput(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_toggleText = null; + base.Dispose(); + } + } + + public override bool IsActive + { + get { return base.IsActive; } + set + { + base.IsActive = value; + if (value == true) + m_toggleText.TextureColor = Color.Yellow; + else + m_toggleText.TextureColor = Color.White; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/ReduceQualityOptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/ReduceQualityOptionsObj.cs new file mode 100644 index 0000000..f94d099 --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/ReduceQualityOptionsObj.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class ReduceQualityOptionsObj : OptionsObj + { + private TextObj m_toggleText; + + public ReduceQualityOptionsObj(OptionsScreen parentScreen) + : base(parentScreen, "LOC_ID_OPTIONS_SCREEN_12") //"Reduce Shader Quality" + { + m_toggleText = m_nameText.Clone() as TextObj; + m_toggleText.X = m_optionsTextOffset; + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + this.AddChild(m_toggleText); + } + + public override void Initialize() + { + if (Game.GameConfig.ReduceQuality == true) + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_3", m_toggleText); //"Yes" + else + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + base.Initialize(); + } + + public override void HandleInput() + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT2) + || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT2)) + { + SoundManager.PlaySound("frame_swap"); + if (m_toggleText.Text == LocaleBuilder.getResourceString("LOC_ID_QUICKDROP_OPTIONS_2")) // "No" + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_3", m_toggleText); //"Yes" + else + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + SoundManager.PlaySound("Option_Menu_Select"); + if (m_toggleText.Text == LocaleBuilder.getResourceString("LOC_ID_QUICKDROP_OPTIONS_3")) // "Yes" + Game.GameConfig.ReduceQuality = true; + else + Game.GameConfig.ReduceQuality = false; + this.IsActive = false; + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + if (Game.GameConfig.ReduceQuality == true) + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_3", m_toggleText); //"Yes" + else + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + this.IsActive = false; + } + + base.HandleInput(); + } + + public override void RefreshTextObjs() + { + m_nameText.ScaleX = 1; + switch (LocaleBuilder.languageType) + { + case (LanguageType.French): + case (LanguageType.Spanish_Spain): + m_nameText.ScaleX = 0.9f; + break; + case (LanguageType.Portuguese_Brazil): + case (LanguageType.Russian): + m_nameText.ScaleX = 0.8f; + break; + } + base.RefreshTextObjs(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_toggleText = null; + base.Dispose(); + } + } + + public override bool IsActive + { + get { return base.IsActive; } + set + { + base.IsActive = value; + if (value == true) + m_toggleText.TextureColor = Color.Yellow; + else + m_toggleText.TextureColor = Color.White; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/ResolutionOptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/ResolutionOptionsObj.cs new file mode 100644 index 0000000..8a4cffc --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/ResolutionOptionsObj.cs @@ -0,0 +1,181 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using DS2DEngine; + +namespace RogueCastle +{ + public class ResolutionOptionsObj : OptionsObj + { + private const float ASPECT_RATIO = 1920f / 1080f; + List m_displayModeList; + private TextObj m_toggleText; + private Vector2 m_selectedResolution; + private int m_selectedResIndex; + + private float m_resetCounter = 0; + + public ResolutionOptionsObj(OptionsScreen parentScreen) + : base(parentScreen, "LOC_ID_OPTIONS_SCREEN_10") //"Resolution" + { + m_toggleText = m_nameText.Clone() as TextObj; + m_toggleText.X = m_optionsTextOffset; + m_toggleText.Text = "null"; + this.AddChild(m_toggleText); + } + + public override void Initialize() + { + m_resetCounter = 0; + m_selectedResolution = new Vector2(m_parentScreen.ScreenManager.Game.GraphicsDevice.Viewport.Width, m_parentScreen.ScreenManager.Game.GraphicsDevice.Viewport.Height); + //m_selectedResolution = new Vector2((m_parentScreen.ScreenManager.Game as Game).graphics.PreferredBackBufferWidth, + // (m_parentScreen.ScreenManager.Game as Game).graphics.PreferredBackBufferHeight); + + if (m_displayModeList != null) + m_displayModeList.Clear(); + m_displayModeList = (m_parentScreen.ScreenManager.Game as Game).GetSupportedResolutions(); + m_toggleText.Text = m_selectedResolution.X + "x" + m_selectedResolution.Y; + + m_selectedResIndex = 0; + for (int i = 0; i < m_displayModeList.Count; i++) + { + if (m_selectedResolution == m_displayModeList[i]) + { + m_selectedResIndex = i; + break; + } + } + } + + public override void HandleInput() + { + int previousSelectedRes = m_selectedResIndex; + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT2)) + { + m_selectedResIndex--; + SoundManager.PlaySound("frame_swap"); + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT2)) + { + m_selectedResIndex++; + SoundManager.PlaySound("frame_swap"); + } + + if (m_selectedResIndex < 0) + m_selectedResIndex = 0; + if (m_selectedResIndex > m_displayModeList.Count - 1) + m_selectedResIndex = m_displayModeList.Count - 1; + + if (m_selectedResIndex != previousSelectedRes) + { + float displayModeAspectRatio = m_displayModeList[m_selectedResIndex].X / m_displayModeList[m_selectedResIndex].Y; + if (displayModeAspectRatio == ASPECT_RATIO) + m_toggleText.TextureColor = Color.Yellow; + else + m_toggleText.TextureColor = Color.Red; + + m_toggleText.Text = m_displayModeList[m_selectedResIndex].X + "x" + m_displayModeList[m_selectedResIndex].Y; + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + SoundManager.PlaySound("Option_Menu_Select"); + Vector2 newRes = m_displayModeList[m_selectedResIndex]; + if (m_selectedResolution != newRes) + { + (m_parentScreen.ScreenManager.Game as Game).graphics.PreferredBackBufferWidth = (int)newRes.X; + (m_parentScreen.ScreenManager.Game as Game).graphics.PreferredBackBufferHeight = (int)newRes.Y; + (m_parentScreen.ScreenManager.Game as Game).graphics.ApplyChanges(); + (m_parentScreen.ScreenManager as RCScreenManager).ForceResolutionChangeCheck(); + + if ((m_parentScreen.ScreenManager.Game as Game).graphics.IsFullScreen == true) + { + RCScreenManager manager = m_parentScreen.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("Resolution Changed"); + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "SaveResolution", newRes); + manager.DialogueScreen.SetCancelEndHandler(this, "CancelResolution"); + manager.DisplayScreen(ScreenType.Dialogue, false, null); + m_resetCounter = 10; + } + else + { + m_selectedResolution = newRes; + SaveResolution(newRes); + } + } + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + this.IsActive = false; + + base.HandleInput(); + } + + public override void Update(GameTime gameTime) + { + if (m_resetCounter > 0) + { + m_resetCounter -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_resetCounter <= 0) + { + RCScreenManager manager = m_parentScreen.ScreenManager as RCScreenManager; + manager.HideCurrentScreen(); + CancelResolution(); + } + } + + base.Update(gameTime); + } + + public void SaveResolution(Vector2 resolution) + { + Game.GameConfig.ScreenWidth = (int)resolution.X; + Game.GameConfig.ScreenHeight= (int)resolution.Y; + m_resetCounter = 0; + m_selectedResolution = resolution; + this.IsActive = false; + } + + public void CancelResolution() + { + m_resetCounter = 0; + (m_parentScreen.ScreenManager.Game as Game).graphics.PreferredBackBufferWidth = (int)m_selectedResolution.X; + (m_parentScreen.ScreenManager.Game as Game).graphics.PreferredBackBufferHeight = (int)m_selectedResolution.Y; + (m_parentScreen.ScreenManager.Game as Game).graphics.ApplyChanges(); + (m_parentScreen.ScreenManager as RCScreenManager).ForceResolutionChangeCheck(); + m_toggleText.Text = m_selectedResolution.X + "x" + m_selectedResolution.Y; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_toggleText = null; + if (m_displayModeList != null) + m_displayModeList.Clear(); + m_displayModeList = null; + base.Dispose(); + } + } + + public override bool IsActive + { + get { return base.IsActive; } + set + { + base.IsActive = value; + if (value == true) + m_toggleText.TextureColor = Color.Yellow; + else + { + m_toggleText.TextureColor = Color.White; + m_toggleText.Text = m_selectedResolution.X + "x" + m_selectedResolution.Y; + } + } + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/SFXVolOptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/SFXVolOptionsObj.cs new file mode 100644 index 0000000..9fc876c --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/SFXVolOptionsObj.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class SFXVolOptionsObj : OptionsObj + { + private SpriteObj m_volumeBarBG; + private SpriteObj m_volumeBar; + + public SFXVolOptionsObj(OptionsScreen parentScreen) + : base(parentScreen, "LOC_ID_SFXVOL_OPTIONS_1") //"SFX Volume" + { + m_volumeBarBG = new SpriteObj("OptionsScreenVolumeBG_Sprite"); + m_volumeBarBG.X = m_optionsTextOffset; + m_volumeBarBG.Y = m_volumeBarBG.Height / 2f - 2; + this.AddChild(m_volumeBarBG); + + m_volumeBar = new SpriteObj("OptionsScreenVolumeBar_Sprite"); + m_volumeBar.X = m_volumeBarBG.X + 6; + m_volumeBar.Y = m_volumeBarBG.Y + 5; + this.AddChild(m_volumeBar); + } + + public override void Initialize() + { + m_volumeBar.ScaleX = SoundManager.GlobalSFXVolume; + base.Initialize(); + } + + public override void HandleInput() + { + if (Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT2)) + { + SoundManager.GlobalSFXVolume -= 0.01f; + SetVolumeLevel(); + } + else if (Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT2)) + { + SoundManager.GlobalSFXVolume += 0.01f; + SetVolumeLevel(); + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || + Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + IsActive = false; + } + + base.HandleInput(); + } + + public void SetVolumeLevel() + { + m_volumeBar.ScaleX = SoundManager.GlobalSFXVolume; + Game.GameConfig.SFXVolume = SoundManager.GlobalSFXVolume; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_volumeBar = null; + m_volumeBarBG = null; + base.Dispose(); + } + } + + public override bool IsActive + { + get { return base.IsActive; } + set + { + base.IsActive = value; + if (value == true) + m_volumeBar.TextureColor = Color.Yellow; + else + m_volumeBar.TextureColor = Color.White; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/SteamCloudOptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/SteamCloudOptionsObj.cs new file mode 100644 index 0000000..25a334e --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/SteamCloudOptionsObj.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class SteamCloudOptionsObj : OptionsObj + { + private TextObj m_toggleText; + + public SteamCloudOptionsObj(OptionsScreen parentScreen) + : base(parentScreen, "LOC_ID_OPTIONS_SCREEN_14") + { + m_toggleText = m_nameText.Clone() as TextObj; + m_toggleText.X = m_optionsTextOffset; + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + this.AddChild(m_toggleText); + } + + public override void Initialize() + { + if (Game.GameConfig.EnableSteamCloud == true) + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_3", m_toggleText); //"Yes" + else + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + base.Initialize(); + } + + public override void HandleInput() + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT2) + || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT2)) + { + SoundManager.PlaySound("frame_swap"); + if (m_toggleText.Text == LocaleBuilder.getResourceString("LOC_ID_QUICKDROP_OPTIONS_2")) // "No" + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_3", m_toggleText); //"Yes" + else + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + SoundManager.PlaySound("Option_Menu_Select"); + if (m_toggleText.Text == LocaleBuilder.getResourceString("LOC_ID_QUICKDROP_OPTIONS_3")) // "Yes" + Game.GameConfig.EnableSteamCloud = true; + else + Game.GameConfig.EnableSteamCloud = false; + this.IsActive = false; + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + if (Game.GameConfig.EnableSteamCloud == true) + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_3", m_toggleText); //"Yes" + else + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + this.IsActive = false; + } + + base.HandleInput(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_toggleText = null; + base.Dispose(); + } + } + + public override bool IsActive + { + get { return base.IsActive; } + set + { + base.IsActive = value; + if (value == true) + m_toggleText.TextureColor = Color.Yellow; + else + m_toggleText.TextureColor = Color.White; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/OptionsObjs/UnlockTraitorOptionsObj.cs b/RogueCastle/src/Game Objects/OptionsObjs/UnlockTraitorOptionsObj.cs new file mode 100644 index 0000000..d48f8d3 --- /dev/null +++ b/RogueCastle/src/Game Objects/OptionsObjs/UnlockTraitorOptionsObj.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class UnlockTraitorOptionsObj : OptionsObj + { + private TextObj m_toggleText; + private byte m_storedState; + + public UnlockTraitorOptionsObj(OptionsScreen parentScreen) + : base(parentScreen, "LOC_ID_UNLOCK_TRAITOR_OPTIONS") //"Unlock Traitor Class" + { + m_toggleText = m_nameText.Clone() as TextObj; + m_toggleText.X = m_optionsTextOffset; + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + this.AddChild(m_toggleText); + } + + public override void Initialize() + { + UpdateToggleText(); + RefreshTextObjs(); + base.Initialize(); + } + + private void UpdateToggleText() + { + if (Game.GameConfig.UnlockTraitor == 2) // 0 = invisible, 1 = no, 2 = yes + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_3", m_toggleText); //"Yes" + else + m_toggleText.Text = LocaleBuilder.getString("LOC_ID_QUICKDROP_OPTIONS_2", m_toggleText); //"No" + } + + public override void HandleInput() + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT2) + || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT2)) + { + SoundManager.PlaySound("frame_swap"); + if (Game.GameConfig.UnlockTraitor == 1) + Game.GameConfig.UnlockTraitor = 2; + else + Game.GameConfig.UnlockTraitor = 1; + UpdateToggleText(); + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + SoundManager.PlaySound("Option_Menu_Select"); + this.IsActive = false; + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + Game.GameConfig.UnlockTraitor = m_storedState; + UpdateToggleText(); + this.IsActive = false; + } + + base.HandleInput(); + } + + public override void RefreshTextObjs() + { + m_nameText.ScaleX = 1; + switch (LocaleBuilder.languageType) + { + case (LanguageType.Russian): + m_nameText.ScaleX = 0.9f; + break; + + } + base.RefreshTextObjs(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_toggleText = null; + base.Dispose(); + } + } + + public override bool IsActive + { + get { return base.IsActive; } + set + { + base.IsActive = value; + if (value == true) + { + m_storedState = Game.GameConfig.UnlockTraitor; + m_toggleText.TextureColor = Color.Yellow; + } + else + m_toggleText.TextureColor = Color.White; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/Player/PlayerHUDObj.cs b/RogueCastle/src/Game Objects/Player/PlayerHUDObj.cs new file mode 100644 index 0000000..bc2f27f --- /dev/null +++ b/RogueCastle/src/Game Objects/Player/PlayerHUDObj.cs @@ -0,0 +1,389 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class PlayerHUDObj : SpriteObj + { + private int m_maxBarLength = 360; + + private TextObj m_playerLevelText; + private SpriteObj m_coin; + private TextObj m_goldText; + + private SpriteObj m_hpBar; + private TextObj m_hpText; + + private SpriteObj m_mpBar; + private TextObj m_mpText; + + private SpriteObj[] m_abilitiesSpriteArray; + + private ObjContainer m_hpBarContainer; + private ObjContainer m_mpBarContainer; + + private SpriteObj m_specialItemIcon; + private SpriteObj m_spellIcon; + private TextObj m_spellCost; + + private SpriteObj m_iconHolder1, m_iconHolder2; + + public bool ShowBarsOnly { get; set; } + + public int forcedPlayerLevel { get; set; } + + public PlayerHUDObj() : + base("PlayerHUDLvlText_Sprite") + { + this.ForceDraw = true; + forcedPlayerLevel = -1; + + m_playerLevelText = new TextObj(); + m_playerLevelText.Text = Game.PlayerStats.CurrentLevel.ToString(); + m_playerLevelText.Font = Game.PlayerLevelFont; + + m_coin = new SpriteObj("PlayerUICoin_Sprite"); + m_coin.ForceDraw = true; + + m_goldText = new TextObj(); + m_goldText.Text = "0"; + m_goldText.Font = Game.GoldFont; + m_goldText.FontSize = 25; + + m_hpBar = new SpriteObj("HPBar_Sprite"); + m_hpBar.ForceDraw = true; + + m_mpBar = new SpriteObj("MPBar_Sprite"); + m_mpBar.ForceDraw = true; + + m_hpText = new TextObj(Game.JunicodeFont); + m_hpText.FontSize = 8; + m_hpText.DropShadow = new Vector2(1, 1); + m_hpText.ForceDraw = true; + + m_mpText = new TextObj(Game.JunicodeFont); + m_mpText.FontSize = 8; + m_mpText.DropShadow = new Vector2(1, 1); + m_mpText.ForceDraw = true; + + m_abilitiesSpriteArray = new SpriteObj[5]; // Can only have 5 abilities equipped at a time. + Vector2 startPos = new Vector2(130, 690); + int xOffset = 35; + for (int i = 0; i < m_abilitiesSpriteArray.Length; i++) + { + m_abilitiesSpriteArray[i] = new SpriteObj("Blank_Sprite"); + m_abilitiesSpriteArray[i].ForceDraw = true; + m_abilitiesSpriteArray[i].Position = startPos; + m_abilitiesSpriteArray[i].Scale = new Vector2(0.5f, 0.5f); + startPos.X += xOffset; + } + + m_hpBarContainer = new ObjContainer("PlayerHUDHPBar_Character"); + m_hpBarContainer.ForceDraw = true; + + m_mpBarContainer = new ObjContainer("PlayerHUDMPBar_Character"); + m_mpBarContainer.ForceDraw = true; + + m_specialItemIcon = new SpriteObj("Blank_Sprite"); + m_specialItemIcon.ForceDraw = true; + m_specialItemIcon.OutlineWidth = 1; + m_specialItemIcon.Scale = new Vector2(1.7f, 1.7f); + m_specialItemIcon.Visible = false; + + m_spellIcon = new SpriteObj(SpellType.Icon(SpellType.None)); + m_spellIcon.ForceDraw = true; + m_spellIcon.OutlineWidth = 1; + m_spellIcon.Visible = false; + + m_iconHolder1 = new SpriteObj("BlacksmithUI_IconBG_Sprite"); + m_iconHolder1.ForceDraw = true; + m_iconHolder1.Opacity = 0.5f; + m_iconHolder1.Scale = new Vector2(0.8f, 0.8f); + m_iconHolder2 = m_iconHolder1.Clone() as SpriteObj; + + m_spellCost = new TextObj(Game.JunicodeFont); + m_spellCost.Align = Types.TextAlign.Centre; + m_spellCost.ForceDraw = true; + m_spellCost.OutlineWidth = 2; + m_spellCost.FontSize = 8; + m_spellCost.Visible = false; + + UpdateSpecialItemIcon(); + UpdateSpellIcon(); + } + + public void SetPosition(Vector2 position) + { + SpriteObj mpBar, hpBar; + ObjContainer mpContainer, hpContainer; + + if (Game.PlayerStats.Traits.X == TraitType.Dextrocardia || Game.PlayerStats.Traits.Y == TraitType.Dextrocardia) + { + mpBar = m_hpBar; + hpBar = m_mpBar; + mpContainer = m_hpBarContainer; + hpContainer = m_mpBarContainer; + } + else + { + mpBar = m_mpBar; + hpBar = m_hpBar; + mpContainer = m_mpBarContainer; + hpContainer = m_hpBarContainer; + } + + this.Position = position; + mpBar.Position = new Vector2(this.X + 7, this.Y + 60); + hpBar.Position = new Vector2(this.X + 8, this.Y + 29); + m_playerLevelText.Position = new Vector2(this.X + 30, this.Y - 20); + + if (Game.PlayerStats.Traits.X == TraitType.Dextrocardia || Game.PlayerStats.Traits.Y == TraitType.Dextrocardia) + { + m_mpText.Position = new Vector2(this.X + 5, this.Y + 16); + m_mpText.X += 8; + + m_hpText.Position = m_mpText.Position; + m_hpText.Y += 28; + } + else + { + m_hpText.Position = new Vector2(this.X + 5, this.Y + 16); + m_hpText.X += 8; + m_hpText.Y += 5; + + m_mpText.Position = m_hpText.Position; + m_mpText.Y += 30; + } + + hpContainer.Position = new Vector2(this.X, this.Y + 17); + if (hpBar == m_hpBar) + hpBar.Position = new Vector2(hpContainer.X + 2, hpContainer.Y + 7); // Small hack to properly align dextrocardia + else + hpBar.Position = new Vector2(hpContainer.X + 2, hpContainer.Y + 6); + + mpContainer.Position = new Vector2(this.X, hpContainer.Bounds.Bottom); + if (mpBar == m_mpBar) + mpBar.Position = new Vector2(mpContainer.X + 2, mpContainer.Y + 6); + else + mpBar.Position = new Vector2(mpContainer.X + 2, mpContainer.Y + 7); // Small hack to properly align dextrocardia + + m_coin.Position = new Vector2(this.X, mpContainer.Bounds.Bottom + 2); + m_goldText.Position = new Vector2(m_coin.X + 28, m_coin.Y - 2); + + + m_iconHolder1.Position = new Vector2(m_coin.X + 25, m_coin.Y + 60); + m_iconHolder2.Position = new Vector2(m_iconHolder1.X + 55, m_iconHolder1.Y); + + m_spellIcon.Position = m_iconHolder1.Position; + m_specialItemIcon.Position = m_iconHolder2.Position; + m_spellCost.Position = new Vector2(m_spellIcon.X, m_spellIcon.Bounds.Bottom + 10); + } + + public void Update(PlayerObj player) + { + int playerLevel = Game.PlayerStats.CurrentLevel; + if (playerLevel < 0) + playerLevel = 0; + if (forcedPlayerLevel >= 0) + playerLevel = forcedPlayerLevel; + m_playerLevelText.Text = playerLevel.ToString(); + //m_playerLevelText.Text = Game.PlayerStats.CurrentLevel.ToString(); + + int playerGold = Game.PlayerStats.Gold; + if (playerGold < 0) + playerGold = 0; + m_goldText.Text = playerGold.ToString(); + //m_goldText.Text = Game.PlayerStats.Gold.ToString(); + + m_hpText.Text = (player.CurrentHealth + "/" + player.MaxHealth); + m_mpText.Text = (player.CurrentMana + "/" + player.MaxMana); + + UpdatePlayerHP(player); + UpdatePlayerMP(player); + } + + private void UpdatePlayerHP(PlayerObj player) + { + // Each piece is 32 pixels in width. + // Total bar length is 88; + int hpBarIncreaseAmount = player.MaxHealth - player.BaseHealth; // The amount of bonus HP the player has compared to his base health. + float hpPercent = player.CurrentHealth / (float)player.MaxHealth; // The current percent of health player has compared to his max health. + + int hpBarIncreaseWidth = (int)(88 + (hpBarIncreaseAmount / 5f)); + if (hpBarIncreaseWidth > m_maxBarLength) + hpBarIncreaseWidth = m_maxBarLength; + float midBarScaleX = (hpBarIncreaseWidth - 28 - 28) / 32f; + m_hpBarContainer.GetChildAt(1).ScaleX = midBarScaleX; + m_hpBarContainer.GetChildAt(2).X = m_hpBarContainer.GetChildAt(1).Bounds.Right; + m_hpBarContainer.CalculateBounds(); + + m_hpBar.ScaleX = 1; + m_hpBar.ScaleX = ((m_hpBarContainer.Width - 8) / (float)m_hpBar.Width) * hpPercent; + } + + private void UpdatePlayerMP(PlayerObj player) + { + int mpBarIncreaseAmount = (int)(player.MaxMana - player.BaseMana); + float mpPercent = player.CurrentMana / player.MaxMana; + + int mpBarIncreaseWidth = (int)(88 + (mpBarIncreaseAmount / 5f)); + if (mpBarIncreaseWidth > m_maxBarLength) + mpBarIncreaseWidth = m_maxBarLength; + float midBarScaleX = (mpBarIncreaseWidth - 28 - 28) / 32f; + m_mpBarContainer.GetChildAt(1).ScaleX = midBarScaleX; + m_mpBarContainer.GetChildAt(2).X = m_mpBarContainer.GetChildAt(1).Bounds.Right; + m_mpBarContainer.CalculateBounds(); + + m_mpBar.ScaleX = 1; + m_mpBar.ScaleX = ((m_mpBarContainer.Width - 8) / (float)m_mpBar.Width) * mpPercent; + } + + public void UpdatePlayerLevel() + { + m_playerLevelText.Text = Game.PlayerStats.CurrentLevel.ToString(); + } + + public void UpdateAbilityIcons() + { + foreach (SpriteObj sprite in m_abilitiesSpriteArray) + sprite.ChangeSprite("Blank_Sprite"); // Zeroing out each sprite. + + int spriteArrayIndex = 0; + foreach (sbyte index in Game.PlayerStats.GetEquippedRuneArray) + { + if (index != -1) + { + m_abilitiesSpriteArray[spriteArrayIndex].ChangeSprite(EquipmentAbilityType.Icon(index)); + spriteArrayIndex++; + } + } + } + + public void UpdateSpecialItemIcon() + { + m_specialItemIcon.Visible = false; + m_iconHolder2.Opacity = 0.5f; + if (Game.PlayerStats.SpecialItem != SpecialItemType.None) + { + m_specialItemIcon.Visible = true; + m_specialItemIcon.ChangeSprite(SpecialItemType.SpriteName(Game.PlayerStats.SpecialItem)); + m_iconHolder2.Opacity = 1; + } + } + + public void UpdateSpellIcon() + { + m_spellIcon.Visible = false; + m_iconHolder1.Opacity = 0.5f; + m_spellCost.Visible = false; + + if (Game.PlayerStats.Spell != SpellType.None) + { + m_spellIcon.ChangeSprite(SpellType.Icon(Game.PlayerStats.Spell)); + m_spellIcon.Visible = true; + m_iconHolder1.Opacity = 1; + m_spellCost.ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_spellCost)); + m_spellCost.Text = (int)(SpellEV.GetManaCost(Game.PlayerStats.Spell) * (1 - SkillSystem.GetSkill(SkillType.Mana_Cost_Down).ModifierAmount)) + " " + LocaleBuilder.getString("LOC_ID_SKILL_SCREEN_15", null); + m_spellCost.Visible = true; + } + } + + public override void Draw(Camera2D camera) + { + if (this.Visible == true) + { + if (ShowBarsOnly == false) + { + base.Draw(camera); + m_coin.Draw(camera); + + m_playerLevelText.Draw(camera); + m_goldText.Draw(camera); + + camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + foreach (SpriteObj sprite in m_abilitiesSpriteArray) + sprite.Draw(camera); + + m_iconHolder1.Draw(camera); + m_iconHolder2.Draw(camera); + m_spellIcon.Draw(camera); + m_specialItemIcon.Draw(camera); + + camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + m_spellCost.Draw(camera); + } + + m_mpBar.Draw(camera); + m_mpText.Draw(camera); + if (Game.PlayerStats.Traits.X != TraitType.CIP && Game.PlayerStats.Traits.Y != TraitType.CIP) + { + m_hpBar.Draw(camera); + m_hpText.Draw(camera); + } + + m_mpBarContainer.Draw(camera); + m_hpBarContainer.Draw(camera); + } + } + + public void RefreshTextObjs() + { + if (Game.PlayerStats.Spell != SpellType.None) + { + m_spellCost.ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_spellCost)); + m_spellCost.Text = (int)(SpellEV.GetManaCost(Game.PlayerStats.Spell) * (1 - SkillSystem.GetSkill(SkillType.Mana_Cost_Down).ModifierAmount)) + " " + LocaleBuilder.getString("LOC_ID_SKILL_SCREEN_15", null); + } + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + foreach (SpriteObj sprite in m_abilitiesSpriteArray) + sprite.Dispose(); + Array.Clear(m_abilitiesSpriteArray, 0, m_abilitiesSpriteArray.Length); + m_abilitiesSpriteArray = null; + + m_coin.Dispose(); + m_coin = null; + m_mpBar.Dispose(); + m_mpBar = null; + m_hpBar.Dispose(); + m_hpBar = null; + m_playerLevelText.Dispose(); + m_playerLevelText = null; + m_goldText.Dispose(); + m_goldText = null; + m_hpText.Dispose(); + m_hpText = null; + m_mpText.Dispose(); + m_mpText = null; + + m_hpBarContainer.Dispose(); + m_hpBarContainer = null; + m_mpBarContainer.Dispose(); + m_mpBarContainer = null; + + m_specialItemIcon.Dispose(); + m_specialItemIcon = null; + m_spellIcon.Dispose(); + m_spellIcon = null; + + m_spellCost.Dispose(); + m_spellCost = null; + + m_iconHolder1.Dispose(); + m_iconHolder1 = null; + m_iconHolder2.Dispose(); + m_iconHolder2 = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/Player/PlayerObj.cs b/RogueCastle/src/Game Objects/Player/PlayerObj.cs new file mode 100644 index 0000000..5c81600 --- /dev/null +++ b/RogueCastle/src/Game Objects/Player/PlayerObj.cs @@ -0,0 +1,4304 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using InputSystem; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Graphics; +using Tweener; + +namespace RogueCastle +{ + public class PlayerObj : CharacterObj, IDealsDamageObj + { + #region Variables + private Game m_game; + + #region MapInputs + private const int DEBUG_INPUT_SWAPWEAPON = 0; + private const int DEBUG_INPUT_GIVEMANA = 1; + private const int DEBUG_INPUT_GIVEHEALTH = 2; + private const int DEBUG_INPUT_LEVELUP_STRENGTH = 3; + private const int DEBUG_INPUT_LEVELUP_HEALTH = 4; + private const int DEBUG_INPUT_LEVELUP_ENDURANCE = 5; + private const int DEBUG_INPUT_LEVELUP_EQUIPLOAD = 6; + private const int DEBUG_INPUT_TRAITSCREEN = 7; + private const int DEBUG_UNLOCK_ALL_BLUEPRINTS = 8; + private const int DEBUG_PURCHASE_ALL_BLUEPRINTS = 9; + + public const int STATE_IDLE = 0; + public const int STATE_WALKING = 1; + public const int STATE_JUMPING = 2; + public const int STATE_HURT = 3; + public const int STATE_DASHING = 4; + public const int STATE_LEVELUP = 5; + public const int STATE_BLOCKING = 6; + public const int STATE_FLYING = 7; + public const int STATE_TANOOKI = 8; + public const int STATE_DRAGON = 9; + #endregion + + // EVs + private float JumpDeceleration = 0; + private int BaseDamage { get; set; } + public float BaseMana { get; internal set; } + public float CurrentMana + { + get { return m_currentMana; } + internal set + { + m_currentMana = value; + + if (m_currentMana < 0) + m_currentMana = 0; + if (m_currentMana > MaxMana) + m_currentMana = MaxMana; + } + } + private float m_currentMana = 0; + private float DashTime = 0; + private float DashSpeed = 0; + private float DashCoolDown = 0; + private float m_manaGain = 0; + public int BaseHealth { get; internal set; } + public float ProjectileLifeSpan { get; internal set; } + public float AttackDelay { get; internal set; } + public float BaseInvincibilityTime { get; internal set; } + public float BaseCriticalChance { get; internal set; } + public float BaseCriticalDamageMod { get; internal set; } + public int MaxDamage { get; internal set; } + public int MinDamage { get; internal set; } + private float ComboDelay = 1f; + public int LevelModifier { get; internal set; } + private float AttackAnimationDelay { get; set; } + private int StrongDamage { get; set; } + private Vector2 StrongEnemyKnockBack { get; set; } + private Vector2 m_enemyKnockBack = Vector2.Zero; + public float AirAttackKnockBack { get; internal set; } + public bool IsAirAttacking { get; set; } + private float AirAttackDamageMod { get; set; } + private float BaseStatDropChance = 0; + public float StatDropIncrease { get; set; } + public float FlightSpeedMod { get; internal set; } + + public int BaseWeight { get; internal set; } + public float BaseMagicDamage { get; set; } + + public float FlightTime { get; internal set; } + private float m_flightCounter = 0; + private bool m_isFlying = false; + + private int DamageGainPerLevel = 0; + private int ManaGainPerLevel = 0; + private int HealthGainPerLevel = 0; + + private float m_invincibleCounter = 0; + private float m_dropThroughGroundTimer = 0; + private float m_dropThroughGroundDuration = 0.1f; // The length of time you are unable to touch 1-ways. + + private float m_blockInvincibleCounter = 0; + private float BlockInvincibleTime { get; set; } + public bool ForceInvincible { get; set; } + public bool InvincibleToSpikes { get; set; } + public int NumAirBounces { get; set; } + + ////// + + private PlayerIndex m_playerIndex; + private float m_attackCounter; // Counter to determine how long before an attack combo ends. + private int m_attackNumber; // Keeps track of the current attack number the player is on. + + private bool m_isJumping; + //private bool m_airDashed = false; + + private byte m_doubleJumpCount = 0; + private byte m_airDashCount = 0; + + private float m_dashCounter = 0; + private float m_dashCooldownCounter = 0; + + private float m_startingAnimationDelay = 0; + + private LogicSet m_currentLogicSet; + private LogicSet m_standingAttack3LogicSet; + private LogicSet m_airAttackLS; + + private bool m_lockControls; + private InputMap m_debugInputMap; + + // The separate parts of the player. + private SpriteObj m_playerHead; + private SpriteObj m_playerLegs; + #endregion + + private FrameSoundObj m_walkUpSound, m_walkUpSoundLow, m_walkUpSoundHigh; + private FrameSoundObj m_walkDownSound, m_walkDownSoundLow, m_walkDownSoundHigh; + private TeleporterObj m_lastTouchedTeleporter; + + private LogicSet m_externalLS; + + private TextObj m_flightDurationText; + + private byte m_attacksNeededForMana = 0; + private byte m_numSequentialAttacks = 0; + private float m_blockManaDrain = 0; + private int ArmorReductionMod = 0; + private float RunSpeedMultiplier = 0; + + private ObjContainer m_translocatorSprite; + + private SpriteObj m_swearBubble; + private float m_swearBubbleCounter = 0; + + private bool m_previousIsTouchingGround = false; + + private TweenObject m_flipTween; + + // Class effect variables. + + private Color m_skinColour1 = new Color(231, 175, 131, 255); + private Color m_skinColour2 = new Color(199, 109, 112, 255); + private Color m_lichColour1 = new Color(255, 255, 255, 255); + private Color m_lichColour2 = new Color(198, 198, 198, 255); + + private float m_assassinSmokeTimer = 0.5f; + private bool m_assassinSpecialActive = false; + private float m_assassinDrainCounter = 0; + + private bool m_timeStopCast = false; + private float m_timeStopDrainCounter = 0; + + private bool m_megaDamageShieldCast = false; + private bool m_damageShieldCast = false; + private float m_damageShieldDrainCounter = 0; + + private float m_tanookiDrainCounter = 0; + + private float m_dragonManaRechargeCounter = 0; + + private bool m_lightOn = false; + private float m_lightDrainCounter = 0; + + private List m_wizardSpellList; // This is saved because it is accessed often. + private float m_wizardSparkleCounter = 0.2f; + + private float m_ninjaTeleportDelay = 0; + + private float m_spellCastDelay = 0; + private float m_rapidSpellCastDelay = 0; + + private IPhysicsObj m_closestGround; + private bool m_collidingLeft = false; // Used specifically to make sure player doesn't dig into walls. + private bool m_collidingRight = false; // Used specifically to make sure player doesn't dig into walls. + + private bool m_collidingLeftOnly = false; + private bool m_collidingRightOnly = false; + + private float m_ambilevousTimer = 0.5f; + + private Vector2 AxeSpellScale = new Vector2(3.0f, 3.0f); + private float AxeProjectileSpeed = 1100; + private Vector2 DaggerSpellScale = new Vector2(3.5f, 3.5f); + private float DaggerProjectileSpeed = 900;//875;//750; + private float m_Spell_Close_Lifespan = 6;//8; + private float m_Spell_Close_Scale = 3.5f; + private ProjectileData m_axeProjData; + private ProjectileData m_rapidDaggerProjData; + + protected override void InitializeEV() + { + //Scale = new Vector2(0.5f, 0.5f); + this.ForceDraw = true; + Speed = 500;//450;// 7.25f;//6.0f; //3.75f; + RunSpeedMultiplier = 3.0f;//1.6f; + JumpHeight = 1180;//1147;// 18.5f; //18.25f;//16.0f;//14f;//13.5fl //12.0f;//8; + DoubleJumpHeight = 845;//837;// 13.5f; //12.5f;//11.5f; //13.5f; + StepUp = 10;//21; + BaseHealth = 100;//150; //100;//75;//50;//100; + + JumpDeceleration = 5000;//2050;//1500f;//3.745f;//0.375f;//0.23f;//0.2f; + KnockBack = new Vector2(300f, 450f);//(5.0f, 7.5f); + BaseInvincibilityTime = 1.00f; //0.75f; //0.5f; + + BaseWeight = 50; + BaseMagicDamage = 25; //10; + + //BaseDamage = 25; + + + DashSpeed = 900.0f;//850.0f;//13.0f; + DashTime = 0.325f;//0.25f; + DashCoolDown = 0.25f; //0.5f; + + ProjectileLifeSpan = 10f; + AnimationDelay = 1 / 10f; // 45 fps. + AttackDelay = 0.0f; + BaseCriticalChance = 0.0f;//0.05f; + BaseCriticalDamageMod = 1.5f;//1.25f;//1.5f; + + EnemyKnockBack = new Vector2(90f, 90f);//(1.5f, 1.5f);//(3.0f, 5.5f); //(5.0f, 7.5f); + MinDamage = 25;//5; + MaxDamage = 25; //10;//25; + ComboDelay = 1.5f; + + AttackAnimationDelay = 1 / (20f + SkillSystem.GetSkill(SkillType.Attack_Speed_Up).ModifierAmount);//1 / 22f; + StrongDamage = 25; //(int)(MaxDamage * 3.0f);//1.5f); + StrongEnemyKnockBack = new Vector2(300f, 360f);//(5.0f, 6.0f);//(8.0f, 8.0f);//(10.0f, 15.5f); + + AirAttackKnockBack = 1425f;//1300f;//900f;//600f; + AirAttackDamageMod = 0.5f; + + LevelModifier = 999999999;//1000; + DamageGainPerLevel = 0; + ManaGainPerLevel = 0; + HealthGainPerLevel = 0; + + //ProjectileDamage = 10; + //ProjectileSpeed = 500; + + BlockManaDrain = GameEV.KNIGHT_BLOCK_DRAIN; //25;//10; + BaseMana = 100;//50; //30; + AttacksNeededForMana = 1;//5; + ManaGain = 0;//10; + BaseStatDropChance = 0.01f; + ArmorReductionMod = GameEV.ARMOR_DIVIDER;//250; + + BlockInvincibleTime = 1.0f; + + FlightTime = GameEV.RUNE_FLIGHT;//5; + FlightSpeedMod = GameEV.FLIGHT_SPEED_MOD; + //Scale = new Vector2(0.5f, 0.5f); + } + + protected override void InitializeLogic() + { + if (m_standingAttack3LogicSet != null) + m_standingAttack3LogicSet.Dispose(); + m_standingAttack3LogicSet = new LogicSet(this); + m_standingAttack3LogicSet.AddAction(new ChangeSpriteLogicAction("PlayerAttacking3_Character", false, false)); + m_standingAttack3LogicSet.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", AttackAnimationDelay)); + m_standingAttack3LogicSet.AddAction(new PlayAnimationLogicAction(2, 4)); + m_standingAttack3LogicSet.AddAction(new DelayLogicAction(AttackDelay)); + m_standingAttack3LogicSet.AddAction(new RunFunctionLogicAction(this, "PlayAttackSound")); + //m_standingAttack3LogicSet.AddAction(new PlaySoundLogicAction("Player_Attack01", "Player_Attack02")); + m_standingAttack3LogicSet.AddAction(new PlayAnimationLogicAction("AttackStart", "End")); + m_standingAttack3LogicSet.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", AnimationDelay)); + + if (m_airAttackLS != null) + m_airAttackLS.Dispose(); + m_airAttackLS = new LogicSet(this); + m_airAttackLS.AddAction(new ChangePropertyLogicAction(this, "IsAirAttacking", true)); + m_airAttackLS.AddAction(new ChangeSpriteLogicAction("PlayerAirAttack_Character", false, false)); + m_airAttackLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", AttackAnimationDelay)); + //m_airAttackLS.AddAction(new Play3DSoundLogicAction(this, Game.ScreenManager.Player,"Player_AttackDown01", "Player_AttackDown02")); + m_airAttackLS.AddAction(new RunFunctionLogicAction(this, "PlayAttackSound")); + + m_airAttackLS.AddAction(new PlayAnimationLogicAction("Start", "Start")); + m_airAttackLS.AddAction(new PlayAnimationLogicAction("Frame 3 Test", "Frame 3 Test")); + m_airAttackLS.AddAction(new PlayAnimationLogicAction("Attack", "Attack")); + m_airAttackLS.AddAction(new DelayLogicAction(AttackDelay)); + m_airAttackLS.AddAction(new PlayAnimationLogicAction("Attack", "End")); + m_airAttackLS.AddAction(new ChangePropertyLogicAction(this, "AnimationDelay", AnimationDelay)); + m_airAttackLS.AddAction(new ChangePropertyLogicAction(this, "IsAirAttacking", false)); + } + + public PlayerObj(string spriteName, PlayerIndex playerIndex, PhysicsManager physicsManager, ProceduralLevelScreen levelToAttachTo, Game game) + : base(spriteName, physicsManager, levelToAttachTo) // Base is called first. + { + m_game = game; + m_playerLegs = this.GetChildAt(PlayerPart.Legs) as SpriteObj; + m_playerHead = this.GetChildAt(PlayerPart.Head) as SpriteObj; + m_playerIndex = playerIndex; + + m_currentLogicSet = new LogicSet(null); + + State = STATE_IDLE; + CollisionTypeTag = GameTypes.CollisionType_PLAYER; + + m_debugInputMap = new InputMap(PlayerIndex.Two, false); + InitializeInputMap(); + + //m_walkDownSound = new FrameSoundObj(m_playerLegs, 4, "Player_Walk_01", "Player_Walk_02", "Player_Walk_03", "Player_Walk_04"); + //m_walkDownSound = new FrameSoundObj(m_playerLegs, 4, "Player_Run_01", "Player_Run_02", "Player_Run_03"); + m_walkDownSound = new FrameSoundObj(m_playerLegs, 4, "Player_WalkDown01", "Player_WalkDown02"); + //m_walkUpSound = new FrameSoundObj(m_playerLegs, 1, "Player_Walk_05", "Player_Walk_06", "Player_Walk_07"); + //m_walkUpSound = new FrameSoundObj(m_playerLegs, 1, "Player_Run_04", "Player_Run_05"); + m_walkUpSound = new FrameSoundObj(m_playerLegs, 1, "Player_WalkUp01", "Player_WalkUp02"); + + m_walkUpSoundHigh = new FrameSoundObj(m_playerLegs, 1, "Player_WalkUp01_High", "Player_WalkUp02_High"); + m_walkDownSoundHigh = new FrameSoundObj(m_playerLegs, 4, "Player_WalkDown01_High", "Player_WalkDown02_High"); + + m_walkUpSoundLow = new FrameSoundObj(m_playerLegs, 1, "Player_WalkUp01_Low", "Player_WalkUp02_Low"); + m_walkDownSoundLow = new FrameSoundObj(m_playerLegs, 4, "Player_WalkDown01_Low", "Player_WalkDown02_Low"); + + m_externalLS = new LogicSet(null); + + m_flightDurationText = new TextObj(Game.JunicodeFont); + m_flightDurationText.FontSize = 12; + m_flightDurationText.Align = Types.TextAlign.Centre; + m_flightDurationText.DropShadow = new Vector2(2, 2); + + this.OutlineWidth = 2; + + m_translocatorSprite = new ObjContainer("PlayerIdle_Character"); + m_translocatorSprite.Visible = false; + m_translocatorSprite.OutlineColour = Color.Blue; + m_translocatorSprite.OutlineWidth = 2; + + m_swearBubble = new SpriteObj("SwearBubble1_Sprite"); + m_swearBubble.Scale = new Vector2(2, 2); + m_swearBubble.Flip = SpriteEffects.FlipHorizontally; + m_swearBubble.Visible = false; + + m_axeProjData = new ProjectileData(this) + { + SpriteName = "SpellAxe_Sprite", + SourceAnchor = new Vector2(20, -20), + Target = null, + Speed = new Vector2(AxeProjectileSpeed, AxeProjectileSpeed), + IsWeighted = true, + RotationSpeed = 10, + Damage = Damage, + AngleOffset = 0, + Angle = new Vector2(-90, -90),//(-72, -72), + CollidesWithTerrain = false, + Scale = AxeSpellScale, + IgnoreInvincibleCounter= true, + }; + + m_rapidDaggerProjData = new ProjectileData(this) + { + SpriteName = "SpellDagger_Sprite", + SourceAnchor = Vector2.Zero, + Speed = new Vector2(DaggerProjectileSpeed, DaggerProjectileSpeed), + IsWeighted = false, + RotationSpeed = 0, + Damage = Damage, + AngleOffset = 0, + CollidesWithTerrain = false, + Scale = DaggerSpellScale, + FollowArc = true, + IgnoreInvincibleCounter = true, + }; + } + + public void Initialize() + { + //InitializeTraits(); + InitializeEV(); + m_startingAnimationDelay = AnimationDelay; + InitializeLogic(); + + CurrentHealth = MaxHealth; + CurrentMana = MaxMana; + + this.Scale = new Vector2(2, 2); + m_internalScale = this.Scale; + + m_wizardSpellList = new List(); + m_wizardSpellList.Add((byte)Game.PlayerStats.WizardSpellList.X); + m_wizardSpellList.Add((byte)Game.PlayerStats.WizardSpellList.Y); + m_wizardSpellList.Add((byte)Game.PlayerStats.WizardSpellList.Z); + } + + public void UpdateInternalScale() + { + m_internalScale = this.Scale; + } + + private void InitializeInputMap() + { + m_debugInputMap.AddInput(DEBUG_INPUT_SWAPWEAPON, Keys.D7); + m_debugInputMap.AddInput(DEBUG_INPUT_GIVEHEALTH, Keys.D8); + m_debugInputMap.AddInput(DEBUG_INPUT_GIVEMANA, Keys.D9); + m_debugInputMap.AddInput(DEBUG_INPUT_LEVELUP_STRENGTH, Keys.D1); + m_debugInputMap.AddInput(DEBUG_INPUT_LEVELUP_HEALTH, Keys.D2); + m_debugInputMap.AddInput(DEBUG_INPUT_LEVELUP_ENDURANCE, Keys.D3); + m_debugInputMap.AddInput(DEBUG_INPUT_LEVELUP_EQUIPLOAD, Keys.D4); + m_debugInputMap.AddInput(DEBUG_INPUT_TRAITSCREEN, Keys.X); + m_debugInputMap.AddInput(DEBUG_UNLOCK_ALL_BLUEPRINTS, Keys.H); + m_debugInputMap.AddInput(DEBUG_PURCHASE_ALL_BLUEPRINTS, Keys.J); + } + + public override void ChangeSprite(string spriteName) + { + base.ChangeSprite(spriteName); + + if (State != STATE_TANOOKI) + { + string headPart = (_objectList[PlayerPart.Head] as IAnimateableObj).SpriteName; + int numberIndex = headPart.IndexOf("_") - 1; + headPart = headPart.Remove(numberIndex, 1); + if (Game.PlayerStats.Class == ClassType.Dragon) + headPart = headPart.Replace("_", PlayerPart.DragonHelm + "_"); + else if (Game.PlayerStats.Class == ClassType.Traitor) + headPart = headPart.Replace("_", PlayerPart.IntroHelm + "_"); + else + headPart = headPart.Replace("_", Game.PlayerStats.HeadPiece + "_"); + _objectList[PlayerPart.Head].ChangeSprite(headPart); + + string chestPart = (_objectList[PlayerPart.Chest] as IAnimateableObj).SpriteName; + numberIndex = chestPart.IndexOf("_") - 1; + chestPart = chestPart.Remove(numberIndex, 1); + chestPart = chestPart.Replace("_", Game.PlayerStats.ChestPiece + "_"); + _objectList[PlayerPart.Chest].ChangeSprite(chestPart); + + string shoulderAPart = (_objectList[PlayerPart.ShoulderA] as IAnimateableObj).SpriteName; + numberIndex = shoulderAPart.IndexOf("_") - 1; + shoulderAPart = shoulderAPart.Remove(numberIndex, 1); + shoulderAPart = shoulderAPart.Replace("_", Game.PlayerStats.ShoulderPiece + "_"); + _objectList[PlayerPart.ShoulderA].ChangeSprite(shoulderAPart); + + string shoulderBPart = (_objectList[PlayerPart.ShoulderB] as IAnimateableObj).SpriteName; + numberIndex = shoulderBPart.IndexOf("_") - 1; + shoulderBPart = shoulderBPart.Remove(numberIndex, 1); + shoulderBPart = shoulderBPart.Replace("_", Game.PlayerStats.ShoulderPiece + "_"); + _objectList[PlayerPart.ShoulderB].ChangeSprite(shoulderBPart); + + // This is giving the SpellSword special arms and changing his sword opacity. + if (Game.PlayerStats.Class == ClassType.SpellSword || Game.PlayerStats.Class == ClassType.SpellSword2) + { + if (this.State == STATE_WALKING && (m_currentLogicSet != m_standingAttack3LogicSet || (m_currentLogicSet == m_standingAttack3LogicSet && m_currentLogicSet.IsActive == false))) + _objectList[PlayerPart.Arms].ChangeSprite("PlayerWalkingArmsSpellSword_Sprite"); + else if (this.State == STATE_JUMPING && (m_currentLogicSet != m_standingAttack3LogicSet || (m_currentLogicSet == m_standingAttack3LogicSet && m_currentLogicSet.IsActive == false)) && IsAirAttacking == false && IsKilled == false) + { + if (this.AccelerationY < 0) + _objectList[PlayerPart.Arms].ChangeSprite("PlayerFallingArmsSpellSword_Sprite"); + else + _objectList[PlayerPart.Arms].ChangeSprite("PlayerJumpingArmsSpellSword_Sprite"); + + } + _objectList[PlayerPart.Sword1].Opacity = 0f; + _objectList[PlayerPart.Sword2].Opacity = 0f; + } + else + { + _objectList[PlayerPart.Sword1].Opacity = 1f; + _objectList[PlayerPart.Sword2].Opacity = 1f; + } + + _objectList[PlayerPart.Light].Opacity = 0.3f; + _objectList[PlayerPart.Light].Visible = false; + + if (Game.PlayerStats.Class == ClassType.Banker2 && spriteName != "PlayerDeath_Character" && m_lightOn == true) // turn off the light if the player is dead. + _objectList[PlayerPart.Light].Visible = true; + + // This gives the player a shield in case he is the knight class. + if (Game.PlayerStats.Class == ClassType.Knight || Game.PlayerStats.Class == ClassType.Knight2) + { + string partName = spriteName.Replace("_Character", "Shield_Sprite"); + _objectList[PlayerPart.Extra].Visible = true; + _objectList[PlayerPart.Extra].ChangeSprite(partName); + } + // This gives the player a headlamp in case he is the banker (spelunker) class. + else if (Game.PlayerStats.Class == ClassType.Banker || Game.PlayerStats.Class == ClassType.Banker2) + { + string partName = spriteName.Replace("_Character", "Lamp_Sprite"); + _objectList[PlayerPart.Extra].Visible = true; + _objectList[PlayerPart.Extra].ChangeSprite(partName); + } + // This gives the player a headlamp in case he is the ninja. + else if (Game.PlayerStats.Class == ClassType.Ninja || Game.PlayerStats.Class == ClassType.Ninja2) + { + string partName = spriteName.Replace("_Character", "Headband_Sprite"); + _objectList[PlayerPart.Extra].Visible = true; + _objectList[PlayerPart.Extra].ChangeSprite(partName); + } + // This gives the player a headlamp in case he is the wizard. + else if (Game.PlayerStats.Class == ClassType.Wizard || Game.PlayerStats.Class == ClassType.Wizard2) + { + string partName = spriteName.Replace("_Character", "Beard_Sprite"); + _objectList[PlayerPart.Extra].Visible = true; + _objectList[PlayerPart.Extra].ChangeSprite(partName); + } + else if (Game.PlayerStats.Class == ClassType.Barbarian || Game.PlayerStats.Class == ClassType.Barbarian2) + { + string partName = spriteName.Replace("_Character", "Horns_Sprite"); + _objectList[PlayerPart.Extra].Visible = true; + _objectList[PlayerPart.Extra].ChangeSprite(partName); + } + else + _objectList[PlayerPart.Extra].Visible = false; + + // These are the glasses. + _objectList[PlayerPart.Glasses].Visible = false; + if (Game.PlayerStats.SpecialItem == SpecialItemType.Glasses) + _objectList[PlayerPart.Glasses].Visible = true; + + // This is for the hair. + _objectList[PlayerPart.Hair].Visible = true; + if (Game.PlayerStats.Traits.X == TraitType.Baldness || Game.PlayerStats.Traits.Y == TraitType.Baldness) + _objectList[PlayerPart.Hair].Visible = false; + + // This is for male/female counterparts + if (Game.PlayerStats.IsFemale == false) + { + _objectList[PlayerPart.Boobs].Visible = false; + _objectList[PlayerPart.Bowtie].Visible = false; + } + else + { + _objectList[PlayerPart.Boobs].Visible = true; + _objectList[PlayerPart.Bowtie].Visible = true; + } + + // Dragon wings. + _objectList[PlayerPart.Wings].Visible = false; + _objectList[PlayerPart.Wings].Opacity = 1; + if (Game.PlayerStats.Class == ClassType.Dragon) + _objectList[PlayerPart.Wings].Visible = true; + + //_objectList[PlayerPart.Sword2].Visible = false; // This is needed until the sword is properly separated. + + if (Game.PlayerStats.Class == ClassType.SpellSword || Game.PlayerStats.Class == ClassType.SpellSword2) + this.OutlineColour = Color.White; + else + this.OutlineColour = Color.Black; + } + } + + public void LockControls() + { + m_lockControls = true; + } + + public void UnlockControls() + { + m_lockControls = false; + } + + // Called in the LevelScreen. + public override void HandleInput() + { + if (m_lockControls == false && IsKilled == false) // Only check input if the controls are unlocked. + { + if (State != STATE_HURT) + InputControls(); + } + + if (Game.PlayerStats.Class == ClassType.Traitor && (AttachedLevel.CurrentRoom is CarnivalShoot1BonusRoom) == false && (AttachedLevel.CurrentRoom is CarnivalShoot2BonusRoom) == false) + { + if (IsKilled == false && State == STATE_DASHING) // Special controls only for the fountain class. + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_SPELL1) && m_spellCastDelay <= 0 && CurrentMana >= PlayerEV.TRAITOR_CLOSE_MANACOST) + { + m_spellCastDelay = 0.5f; + CurrentMana -= PlayerEV.TRAITOR_CLOSE_MANACOST; + CastCloseShield(); + } + } + } + + if (LevelEV.ENABLE_DEBUG_INPUT == true) + HandleDebugInput(); + } + + private void HandleDebugInput() + { + if (InputManager.JustPressed(Keys.T, null)) + { + Game.PlayerStats.GodMode = !Game.PlayerStats.GodMode; + SoundManager.PlaySound("Fart1", "Fart2", "Fart3"); + m_levelScreen.ImpactEffectPool.DisplayFartEffect(this); + } + + if (m_debugInputMap.JustPressed(DEBUG_INPUT_SWAPWEAPON)) + { + Game.PlayerStats.Spell++; + if (Game.PlayerStats.Spell > SpellType.Total) + Game.PlayerStats.Spell = 1; + m_levelScreen.UpdatePlayerSpellIcon(); + } + if (m_debugInputMap.JustPressed(DEBUG_INPUT_GIVEHEALTH)) + this.CurrentHealth = this.MaxHealth; + if (m_debugInputMap.JustPressed(DEBUG_INPUT_GIVEMANA)) + this.CurrentMana = this.MaxMana; + if (m_debugInputMap.JustPressed(DEBUG_INPUT_LEVELUP_STRENGTH)) + { + Game.PlayerStats.Gold += 1000; + } + if (m_debugInputMap.JustPressed(DEBUG_INPUT_LEVELUP_HEALTH)) + { + Game.PlayerStats.Gold += 10000; + + } + if (m_debugInputMap.JustPressed(DEBUG_INPUT_LEVELUP_EQUIPLOAD)) + { + Game.PlayerStats.Gold += 100000; + + } + if (m_debugInputMap.JustPressed(DEBUG_INPUT_LEVELUP_ENDURANCE)) + { + } + if (m_debugInputMap.JustPressed(DEBUG_INPUT_TRAITSCREEN)) + { + RCScreenManager screenManager = m_levelScreen.ScreenManager as RCScreenManager; + if (screenManager != null) + { + //screenManager.DisplayScreen(ScreenType.SkillUnlock, true); + //screenManager.DisplayScreen(ScreenType.Trait, true); + //screenManager.DisplayScreen(ScreenType.Ending, true); + //screenManager.DisplayScreen(ScreenType.DeathDefy, true); + + //List textscreentest = new List(); + //TextObj test = new TextObj(Game.JunicodeFont); + //test.Text = "Cellar Door Games Presents"; + //test.FontSize = 30; + //test.ForceDraw = true; + //test.Align = Types.TextAlign.Centre; + //test.Position = new Vector2(1320/2f, 720/2f); + //textscreentest.Add(1.0f); + //textscreentest.Add(0.5f); + //textscreentest.Add(3.5f); + //textscreentest.Add(true); + //textscreentest.Add(test); + //screenManager.DisplayScreen(ScreenType.Text, true, textscreentest); + //screenManager.DisplayScreen(ScreenType.DiaryFlashback, true); + //screenManager.DisplayScreen(ScreenType.Credits, true); + //screenManager.DisplayScreen(ScreenType.Ending, true); + //screenManager.DisplayScreen(ScreenType.DeathDefy, true); + + this.Kill(); + //RunGetItemAnimation(); + } + } + if (m_debugInputMap.JustPressed(DEBUG_UNLOCK_ALL_BLUEPRINTS)) + Game.EquipmentSystem.SetBlueprintState(EquipmentState.FoundButNotSeen); + if (m_debugInputMap.JustPressed(DEBUG_PURCHASE_ALL_BLUEPRINTS)) + Game.EquipmentSystem.SetBlueprintState(EquipmentState.Purchased); + + if ((InputManager.Pressed(Keys.LeftShift, PlayerIndex.One) || InputManager.Pressed(Buttons.LeftShoulder, PlayerIndex.One)) && CanRun == true && m_isTouchingGround == true) + this.CurrentSpeed *= RunSpeedMultiplier; + + if (InputManager.JustPressed(Keys.B, this.PlayerIndex)) + { + List objectList = new List(); + objectList.Add(new Vector2(this.X, this.Y - this.Height / 2f)); + objectList.Add(GetItemType.Blueprint); + objectList.Add(Vector2.Zero); + + (this.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.GetItem, true, objectList); + this.RunGetItemAnimation(); + } + else if (InputManager.JustPressed(Keys.N, this.PlayerIndex)) + { + List objectList = new List(); + objectList.Add(new Vector2(this.X, this.Y - this.Height / 2f)); + objectList.Add(GetItemType.Rune); + objectList.Add(Vector2.Zero); + + (this.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.GetItem, true, objectList); + this.RunGetItemAnimation(); + } + else if (InputManager.JustPressed(Keys.M, this.PlayerIndex)) + { + List objectList = new List(); + objectList.Add(new Vector2(this.X, this.Y - this.Height / 2f)); + objectList.Add(GetItemType.StatDrop); + objectList.Add(new Vector2(ItemDropType.Stat_Strength, ItemDropType.Stat_Strength)); + + (this.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.GetItem, true, objectList); + this.RunGetItemAnimation(); + } + else if (InputManager.JustPressed(Keys.OemComma, this.PlayerIndex)) + { + List objectList = new List(); + objectList.Add(new Vector2(this.X, this.Y - this.Height / 2f)); + objectList.Add(GetItemType.Spell); + objectList.Add(new Vector2(SpellType.Axe, 0)); + + (this.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.GetItem, true, objectList); + this.RunGetItemAnimation(); + } + else if (InputManager.JustPressed(Keys.OemPeriod, this.PlayerIndex)) + { + List objectList = new List(); + objectList.Add(new Vector2(this.X, this.Y - this.Height / 2f)); + objectList.Add(GetItemType.SpecialItem); + objectList.Add(new Vector2(SpecialItemType.FreeEntrance, 0)); + + (this.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.GetItem, true, objectList); + this.RunGetItemAnimation(); + } + else if (InputManager.JustPressed(Keys.OemQuestion, this.PlayerIndex)) + { + List objectList = new List(); + objectList.Add(new Vector2(this.X, this.Y - this.Height / 2f)); + objectList.Add(GetItemType.FountainPiece); + objectList.Add(new Vector2(ItemDropType.FountainPiece1, 0)); + + (this.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.GetItem, true, objectList); + this.RunGetItemAnimation(); + } + } + + private void InputControls() + { + //if (InputManager.JustPressed(Keys.R, null)) + //{ + // if (m_levelScreen.Camera.Zoom != 1) + // m_levelScreen.Camera.Zoom = 1; + // else + // m_levelScreen.Camera.Zoom = 2.5f; + + //} + + //if (Game.GlobalInput.JustPressed(InputMapType.MENU_PAUSE))// && Game.PlayerStats.TutorialComplete == true) + //{ + // (m_levelScreen.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Pause, true); + //} + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_MAP) && Game.PlayerStats.TutorialComplete == true && m_levelScreen.CurrentRoom.Name != "Start" && m_levelScreen.CurrentRoom.Name != "Boss" && m_levelScreen.CurrentRoom.Name != "ChallengeBoss") + m_levelScreen.DisplayMap(false); + // Code for blocking. + if (State != STATE_TANOOKI) + { + if (Game.GlobalInput.Pressed(InputMapType.PLAYER_BLOCK) && CanBlock == true && m_currentLogicSet.IsActive == false) + { + if (CurrentMana >= GameEV.KNIGHT_BLOCK_DRAIN) + { + if (m_isTouchingGround == true) + this.CurrentSpeed = 0; + + if (State == STATE_FLYING) // Stop movement if the player is flying. + { + this.CurrentSpeed = 0; + AccelerationX = 0; + AccelerationY = 0; + } + + State = STATE_BLOCKING; + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_BLOCK) == true) + SoundManager.PlaySound("Player_Block_Action"); + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_BLOCK)) + SoundManager.PlaySound("Error_Spell"); + } + else + { + if (m_isTouchingGround == false) + { + if (IsFlying == true) + { + if (State == STATE_DRAGON) + State = STATE_DRAGON; + else + State = STATE_FLYING; + } + else State = STATE_JUMPING; + } + else + State = STATE_IDLE; + } + } + + // Code for moving left and right. + if (State != STATE_BLOCKING && State != STATE_TANOOKI) + { + if (Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT2) || Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT2)) + { + if (m_isTouchingGround == true)// && State != STATE_CROUCHING) + State = STATE_WALKING; + + if ((Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT2)) && (m_collidingRight == false || m_isTouchingGround == true)) + { + this.HeadingX = 1; + this.CurrentSpeed = TotalMovementSpeed; // this.Speed; + + } + else if ((Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT2)) + && Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT1) == false && Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT2) == false && (m_collidingLeft == false || m_isTouchingGround == true)) + { + this.HeadingX = -1; + this.CurrentSpeed = TotalMovementSpeed; // this.Speed; + } + else + this.CurrentSpeed = 0; + + if (m_currentLogicSet.IsActive == false || (m_currentLogicSet.IsActive == true && (Game.PlayerStats.Traits.X == TraitType.Hypermobility || Game.PlayerStats.Traits.Y == TraitType.Hypermobility))) + { + if (Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT2)) + this.Flip = SpriteEffects.None; + else if (Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT2)) + this.Flip = SpriteEffects.FlipHorizontally; + } + + if (m_isTouchingGround == true && m_currentLogicSet == m_standingAttack3LogicSet && m_currentLogicSet.IsActive == true && m_playerLegs.SpriteName != "PlayerWalkingLegs_Sprite") + { + m_playerLegs.ChangeSprite("PlayerWalkingLegs_Sprite"); + m_playerLegs.PlayAnimation(this.CurrentFrame, this.TotalFrames); + m_playerLegs.Y += 4; + m_playerLegs.OverrideParentAnimationDelay = true; + m_playerLegs.AnimationDelay = 1 / 10f; + } + } + else + { + if (m_isTouchingGround == true) + State = STATE_IDLE; + this.CurrentSpeed = 0; + } + } + + bool justJumped = false; // Bool for detect a jump and a flight call. + // Code for jumping and double jumping. Also, dragons cannot jump. + if (State != STATE_BLOCKING && State != STATE_FLYING && State != STATE_TANOOKI && Game.PlayerStats.Class != ClassType.Dragon) + { + if ((Game.GlobalInput.JustPressed(InputMapType.PLAYER_JUMP1)|| Game.GlobalInput.JustPressed(InputMapType.PLAYER_JUMP2)) && m_isTouchingGround == true && m_dropThroughGroundTimer <= 0) + { + State = STATE_JUMPING; + AccelerationY = -JumpHeight; + m_isJumping = true; + + if (Game.PlayerStats.Traits.X == TraitType.Gigantism|| Game.PlayerStats.Traits.Y == TraitType.Gigantism) + { + SoundManager.PlaySound("Player_Jump_04_Low"); + SoundManager.PlaySound("Player_WalkUp01_Low"); + } + if (Game.PlayerStats.Traits.X == TraitType.Dwarfism || Game.PlayerStats.Traits.Y == TraitType.Dwarfism) + { + SoundManager.PlaySound("Player_Jump_04_High"); + SoundManager.PlaySound("Player_WalkUp01_High"); + } + else + { + SoundManager.PlaySound("Player_Jump_04"); + SoundManager.PlaySound("Player_WalkUp01"); + } + + if (Game.PlayerStats.Traits.X == TraitType.IBS || Game.PlayerStats.Traits.Y == TraitType.IBS) + { + if (CDGMath.RandomInt(0, 100) >= GameEV.FART_CHANCE) //82 //70 - TEDDY LOWERING ODDS OF FARTS + { + SoundManager.PlaySound("Fart1", "Fart2", "Fart3"); + m_levelScreen.ImpactEffectPool.DisplayDustEffect(this); + } + } + justJumped = true; + } + else if ((Game.GlobalInput.JustPressed(InputMapType.PLAYER_JUMP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_JUMP2)) && m_isTouchingGround == false && m_doubleJumpCount < TotalDoubleJumps && m_dropThroughGroundTimer <= 0) + { + State = STATE_JUMPING; + AccelerationY = -DoubleJumpHeight; + m_levelScreen.ImpactEffectPool.DisplayDoubleJumpEffect(new Vector2(this.X, this.Bounds.Bottom + 10)); + m_isJumping = true; + //m_doubleJumped = true; + + m_doubleJumpCount++; + //SoundManager.PlaySound("Player_WalkUp01"); + + SoundManager.PlaySound("Player_DoubleJump"); + + if (Game.PlayerStats.Traits.X == TraitType.IBS || Game.PlayerStats.Traits.Y == TraitType.IBS) + { + if (CDGMath.RandomInt(0, 100) >= GameEV.FART_CHANCE) //82 //70 - TEDDY LOWERING ODDS OF FARTS + { + SoundManager.PlaySound("Fart1", "Fart2", "Fart3"); + m_levelScreen.ImpactEffectPool.DisplayDustEffect(this); + } + } + justJumped = true; + } + + if (m_isTouchingGround == false) + { + if (m_currentLogicSet == m_standingAttack3LogicSet && m_currentLogicSet.IsActive == true) + { + if (this.AccelerationY > 0 && m_playerLegs.SpriteName != "PlayerAttackFallingLegs_Sprite") + { + m_playerLegs.ChangeSprite("PlayerAttackFallingLegs_Sprite"); + } + else if (this.AccelerationY < 0 && m_playerLegs.SpriteName != "PlayerAttackJumpingLegs_Sprite") + { + m_playerLegs.ChangeSprite("PlayerAttackJumpingLegs_Sprite"); + } + } + + if (State != STATE_FLYING) + State = STATE_JUMPING; + } + } + + // Code for attacking. + // Dragons cannot attack. They only shoot spells. + if (m_currentLogicSet.IsActive == false && State != STATE_BLOCKING && State != STATE_TANOOKI && Game.PlayerStats.Class != ClassType.Dragon) // Only attack when you're not doing an animation. + { + if ((Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN2)) && CanAirAttackDownward == true + && Game.GameConfig.QuickDrop == true && State == STATE_JUMPING && m_dropThroughGroundTimer <= 0) + { + m_currentLogicSet = m_airAttackLS; + if (Game.PlayerStats.Class == ClassType.SpellSword || Game.PlayerStats.Class == ClassType.SpellSword2) + FadeSword(); + + if (m_assassinSpecialActive == true) + DisableAssassinAbility(); + + m_currentLogicSet.Execute(); + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_ATTACK)) + { + if (State == STATE_JUMPING) + { + //Tween.RunFunction(0f, this, "PerformDelayedAirAttack"); + if ((Game.GlobalInput.Pressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_DOWN2)) && CanAirAttackDownward == true) + m_currentLogicSet = m_airAttackLS; + else + { + m_currentLogicSet = m_standingAttack3LogicSet; // Currently uses the same attack code for when he's standing but we change his legs a bit later in the code. + //if (this.AccelerationY > 0) + // this.AccelerationY = -250; + } + if (Game.PlayerStats.Class == ClassType.SpellSword || Game.PlayerStats.Class == ClassType.SpellSword2) + FadeSword(); + + if (m_assassinSpecialActive == true) + DisableAssassinAbility(); + + m_currentLogicSet.Execute(); + } + else + { + if (m_isTouchingGround == false) + this.CurrentSpeed = 0; + + if (m_attackCounter > 0) + m_attackNumber++; + + m_attackCounter = ComboDelay; + if (m_attackNumber == 0) + m_currentLogicSet = m_standingAttack3LogicSet; + else //if (m_attackNumber == 1) + { + m_currentLogicSet = m_standingAttack3LogicSet; + m_attackNumber = 0; + m_attackCounter = 0; + } + + if (Game.PlayerStats.Class == ClassType.SpellSword || Game.PlayerStats.Class == ClassType.SpellSword2) + FadeSword(); + + if (m_assassinSpecialActive == true) + DisableAssassinAbility(); + + m_playerLegs.OverrideParentAnimationDelay = false; // Reset his leg animation. + m_currentLogicSet.Execute(); + } + } + } + + // Code for subweapons + if (Game.PlayerStats.TutorialComplete == true) + { + bool fireballCasted = false; + if (Game.PlayerStats.Spell == SpellType.DragonFireNeo && (Game.GlobalInput.Pressed(InputMapType.PLAYER_ATTACK) || Game.GlobalInput.Pressed(InputMapType.PLAYER_SPELL1)) && m_rapidSpellCastDelay <= 0) + { + m_rapidSpellCastDelay = 0.2f; + CastSpell(false); + fireballCasted = true; + } + + if (m_spellCastDelay <= 0 || Game.PlayerStats.Class == ClassType.Dragon) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_SPELL1) || (Game.PlayerStats.Class == ClassType.Dragon && Game.GlobalInput.JustPressed(InputMapType.PLAYER_ATTACK))) + { + if ((Game.PlayerStats.Class == ClassType.Dragon && fireballCasted == true) == false) // Prevents casting the spell twice. + CastSpell(false); + } + } + + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_BLOCK)) + { + RoomObj room = m_levelScreen.CurrentRoom; + if (room is CarnivalShoot1BonusRoom == false && room is CarnivalShoot2BonusRoom == false && room is ChestBonusRoomObj == false) + { + if (Game.PlayerStats.Class == ClassType.SpellSword2 && m_spellCastDelay <= 0) + CastSpell(false, true); + else if (Game.PlayerStats.Class == ClassType.Lich2) + ConvertHPtoMP(); + else if (Game.PlayerStats.Class == ClassType.Assassin2 && CurrentMana > 0) + { + if (m_assassinSpecialActive == false) + ActivateAssassinAbility(); + else + DisableAssassinAbility(); + } + else if (Game.PlayerStats.Class == ClassType.Wizard2) + SwapSpells(); + else if (Game.PlayerStats.Class == ClassType.Ninja2) + NinjaTeleport(); + else if (Game.PlayerStats.Class == ClassType.Knight2) + { + if (this.State == STATE_TANOOKI) + DeactivateTanooki(); + else if (Game.GlobalInput.Pressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_DOWN2)) + ActivateTanooki(); + } + else if (Game.PlayerStats.Class == ClassType.Barbarian2) + CastFuhRohDah(); + else if (Game.PlayerStats.Class == ClassType.Traitor) + { + if (CurrentMana >= PlayerEV.TRAITOR_AXE_MANACOST && m_spellCastDelay <= 0) + { + CurrentMana -= PlayerEV.TRAITOR_AXE_MANACOST; + m_spellCastDelay = 0.5f; + ThrowAxeProjectiles(); + } + } + } + else + { + if (this.State == STATE_TANOOKI) + DeactivateTanooki(); + } + + if (Game.PlayerStats.Class == ClassType.Dragon) + { + if (State != STATE_DRAGON) + { + State = STATE_DRAGON; + this.DisableGravity = true; + m_isFlying = true; + this.AccelerationY = 0; + } + else + { + State = STATE_JUMPING; + this.DisableGravity = false; + m_isFlying = false; + } + } + else if (Game.PlayerStats.Class == ClassType.Banker2) + { + if (m_lightOn == true) + { + SoundManager.PlaySound("HeadLampOff"); + m_lightOn = false; + _objectList[PlayerPart.Light].Visible = false; + } + else + { + SoundManager.PlaySound("HeadLampOn"); + m_lightOn = true; + _objectList[PlayerPart.Light].Visible = true; + } + } + } + + // Extra handling to link jump to dragon flight. + if (Game.PlayerStats.Class == ClassType.Dragon && (Game.GlobalInput.JustPressed(InputMapType.PLAYER_JUMP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_JUMP2))) + { + if (State != STATE_DRAGON) + { + State = STATE_DRAGON; + this.DisableGravity = true; + m_isFlying = true; + this.AccelerationY = 0; + } + else + { + State = STATE_JUMPING; + this.DisableGravity = false; + m_isFlying = false; + } + } + } + + // Code for dashing. + if (m_dashCooldownCounter <= 0 && (m_isTouchingGround == true || (m_isTouchingGround == false && m_airDashCount < TotalAirDashes)) && State != STATE_BLOCKING && State != STATE_TANOOKI) + { + if (CanAirDash == true) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_DASHLEFT)) + { + //if (m_isTouchingGround == false) // Ensures the player can only air dash once. + m_airDashCount++; + State = STATE_DASHING; + this.AccelerationYEnabled = false; + m_dashCooldownCounter = DashCoolDown; + m_dashCounter = DashTime; + this.LockControls(); + CurrentSpeed = DashSpeed; + this.HeadingX = -1; + this.AccelerationY = 0; + if (m_currentLogicSet.IsActive == true) + m_currentLogicSet.Stop(); + this.AnimationDelay = m_startingAnimationDelay; + + m_levelScreen.ImpactEffectPool.DisplayDashEffect(new Vector2(this.X, TerrainBounds.Bottom), true); + + SoundManager.PlaySound("Player_Dash"); + + if (Game.PlayerStats.Traits.X == TraitType.IBS || Game.PlayerStats.Traits.Y == TraitType.IBS) + { + if (CDGMath.RandomInt(0, 100) >= GameEV.FART_CHANCE) + { + m_levelScreen.ImpactEffectPool.DisplayDustEffect(this); + SoundManager.PlaySound("Fart1", "Fart2", "Fart3"); + } + } + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_DASHRIGHT)) + { + //if (m_isTouchingGround == false) + m_airDashCount++; + //m_airDashed = true; + this.AnimationDelay = m_startingAnimationDelay; + + State = STATE_DASHING; + this.AccelerationYEnabled = false; + m_dashCooldownCounter = DashCoolDown; + m_dashCounter = DashTime; + this.LockControls(); + CurrentSpeed = DashSpeed; + this.HeadingX = 1; + this.AccelerationY = 0; + if (m_currentLogicSet.IsActive == true) + m_currentLogicSet.Stop(); + + m_levelScreen.ImpactEffectPool.DisplayDashEffect(new Vector2(this.X, TerrainBounds.Bottom), false); + + SoundManager.PlaySound("Player_Dash"); + + if (Game.PlayerStats.Traits.X == TraitType.IBS || Game.PlayerStats.Traits.Y == TraitType.IBS) + { + if (CDGMath.RandomInt(0, 100) >= GameEV.FART_CHANCE) + { + m_levelScreen.ImpactEffectPool.DisplayDustEffect(this); + SoundManager.PlaySound("Fart1", "Fart2", "Fart3"); + } + } + } + } + } + + // Code for flying + if (State == STATE_FLYING || State == STATE_DRAGON) + { + // Controls for moving the player while flying. + if (Game.GlobalInput.Pressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_UP2) || InputManager.Pressed(Buttons.LeftThumbstickUp, PlayerIndex.One)) + this.AccelerationY = -this.TotalMovementSpeed; + else if (Game.GlobalInput.Pressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_DOWN2) || InputManager.Pressed(Buttons.LeftThumbstickDown, PlayerIndex.One)) + this.AccelerationY = this.TotalMovementSpeed; + else + this.AccelerationY = 0; + + // Fix the player's legs while attacking and flying. + if (m_isTouchingGround == false) + { + if (m_currentLogicSet == m_standingAttack3LogicSet && m_currentLogicSet.IsActive == true) + { + if (this.AccelerationY > 0 && m_playerLegs.SpriteName != "PlayerAttackFallingLegs_Sprite") + m_playerLegs.ChangeSprite("PlayerAttackFallingLegs_Sprite"); + else if (this.AccelerationY <= 0 && m_playerLegs.SpriteName != "PlayerAttackJumpingLegs_Sprite") + m_playerLegs.ChangeSprite("PlayerAttackJumpingLegs_Sprite"); + } + + //State = STATE_FLYING; + } + + // Press Jump to disable flight. + if ((Game.GlobalInput.JustPressed(InputMapType.PLAYER_JUMP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_JUMP2)) && State != STATE_DRAGON) + { + //m_flightCounter = 0; + State = STATE_JUMPING; + this.DisableGravity = false; + m_isFlying = false; + } + } + else if ((Game.GlobalInput.JustPressed(InputMapType.PLAYER_JUMP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_JUMP2)) && m_isTouchingGround == false && justJumped == false && m_doubleJumpCount >= TotalDoubleJumps && m_dropThroughGroundTimer <= 0 + && CanFly == true && m_flightCounter > 0 && State != STATE_FLYING && State != STATE_DRAGON && State != STATE_BLOCKING && State != STATE_TANOOKI) + { + this.AccelerationY = 0; + //m_flightCounter = TotalFlightTime; + State = STATE_FLYING; + this.DisableGravity = true; + m_isFlying = true; + } + + //else if (m_isTouchingGround == false && CanFly == true && m_flightCounter > 0 && + // (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) && State != STATE_FLYING && State != STATE_DRAGON && State != STATE_BLOCKING && State != STATE_TANOOKI) + //{ + // this.AccelerationY = 0; + // //m_flightCounter = TotalFlightTime; + // State = STATE_FLYING; + // this.DisableGravity = true; + // m_isFlying = true; + //} + } + + public void PerformDelayedAirAttack() + { + if ((Game.GlobalInput.Pressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_DOWN2)) && CanAirAttackDownward == true) + m_currentLogicSet = m_airAttackLS; + else + { + m_currentLogicSet = m_standingAttack3LogicSet; // Currently uses the same attack code for when he's standing but we change his legs a bit later in the code. + //if (this.AccelerationY > 0) + // this.AccelerationY = -250; + } + if (Game.PlayerStats.Class == ClassType.SpellSword || Game.PlayerStats.Class == ClassType.SpellSword2) + FadeSword(); + + //if (m_assassinSpecialActive == true) + // DisableAssassinAbility(); + + m_currentLogicSet.Execute(); + } + + public override void Update(GameTime gameTime) + { + float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds; + + if (m_dropThroughGroundTimer > 0) + m_dropThroughGroundTimer -= elapsedSeconds; + + if (m_ninjaTeleportDelay > 0) + m_ninjaTeleportDelay -= elapsedSeconds; + + if (m_rapidSpellCastDelay > 0) + m_rapidSpellCastDelay -= elapsedSeconds; + + // Spellsword and assassin effects sholud not appear in the ending room. + if (m_levelScreen.CurrentRoom is EndingRoomObj == false && this.ScaleX > 0.1f) // Scale makes sure he doesn't have this effect while teleporting. + { + if ((Game.PlayerStats.Traits.Y == TraitType.Ambilevous || Game.PlayerStats.Traits.X == TraitType.Ambilevous) && CurrentSpeed == 0) + { + if (m_ambilevousTimer > 0) + { + m_ambilevousTimer -= elapsedSeconds; + if (m_ambilevousTimer <= 0) + { + m_ambilevousTimer = 0.4f; + m_levelScreen.ImpactEffectPool.DisplayQuestionMark(new Vector2(this.X, this.Bounds.Top)); + } + } + } + + // Adds the spellsword sparkle effect. + if (Game.PlayerStats.Class == ClassType.SpellSword || Game.PlayerStats.Class == ClassType.SpellSword2) + { + if (m_wizardSparkleCounter > 0) + { + m_wizardSparkleCounter -= elapsedSeconds; + if (m_wizardSparkleCounter <= 0) + { + m_wizardSparkleCounter = 0.2f; + m_levelScreen.ImpactEffectPool.DisplayChestSparkleEffect(this.Position); + m_levelScreen.ImpactEffectPool.DisplayChestSparkleEffect(this.Position); + } + } + } + + // Adding assassin smoke effect. + if (Game.PlayerStats.Class == ClassType.Assassin || Game.PlayerStats.Class == ClassType.Assassin2) + { + if (m_assassinSmokeTimer > 0) + { + m_assassinSmokeTimer -= elapsedSeconds; + if (m_assassinSmokeTimer <= 0) + { + m_assassinSmokeTimer = 0.15f; + if (CurrentSpeed > 0) + m_assassinSmokeTimer = 0.05f; + m_levelScreen.ImpactEffectPool.BlackSmokeEffect(this); + } + } + } + } + + if (m_swearBubbleCounter > 0) + { + m_swearBubbleCounter -= elapsedSeconds; + if (m_swearBubbleCounter <= 0) + m_swearBubble.Visible = false; + } + + if (m_blockInvincibleCounter > 0) + m_blockInvincibleCounter -= elapsedSeconds; + + if (IsFlying == true) + { + if (State != STATE_DRAGON) // Dragon gets infinite flight. + m_flightCounter -= elapsedSeconds; + + if (m_flightCounter <= 0 && State != STATE_DRAGON) + { + State = STATE_JUMPING; + this.DisableGravity = false; + m_isFlying = false; + } + } + + // What the heck is this code for? + if (AccelerationX < 0) AccelerationX += 200f * elapsedSeconds; + else if (AccelerationX > 0) AccelerationX -= 200f * elapsedSeconds; + if (AccelerationX < 3.6f && AccelerationX > -3.6f) AccelerationX = 0; + + this.X += this.Heading.X * (this.CurrentSpeed * elapsedSeconds); + + if (State == STATE_WALKING) + { + if (Game.PlayerStats.Traits.X == TraitType.Gigantism || Game.PlayerStats.Traits.Y == TraitType.Gigantism) + { + m_walkDownSoundLow.Update(); + m_walkUpSoundLow.Update(); + } + else if (Game.PlayerStats.Traits.X == TraitType.Dwarfism || Game.PlayerStats.Traits.Y == TraitType.Dwarfism) + { + m_walkDownSoundHigh.Update(); + m_walkUpSoundHigh.Update(); + } + else + { + m_walkDownSound.Update(); + m_walkUpSound.Update(); + } + } + + if (m_externalLS.IsActive == false) // Only update the player if an external logic set is not being run on the player. + { + if (m_attackCounter > 0) + m_attackCounter -= elapsedSeconds; + else + m_attackNumber = 0; + + if (m_currentLogicSet.IsActive) + m_currentLogicSet.Update(gameTime); + + if (m_dashCooldownCounter > 0) + m_dashCooldownCounter -= elapsedSeconds; + + if (m_dashCounter > 0) + { + m_dashCounter -= elapsedSeconds; + if (m_dashCounter <= 0 && State != STATE_HURT) + { + this.UnlockControls(); + this.AccelerationYEnabled = true; + } + } + + if (m_invincibleCounter > 0) + { + m_invincibleCounter -= elapsedSeconds; + if (m_assassinSpecialActive == false) + if (this.Opacity != 0.6f) this.Opacity = 0.6f; + } + else + { + if (m_assassinSpecialActive == false) + if (this.Opacity == 0.6f) this.Opacity = 1; + } + + //this.X += this.Heading.X * this.CurrentSpeed; + if (IsPaused == false && (m_currentLogicSet == null || m_currentLogicSet.IsActive == false)) + UpdateAnimationState(); + + CheckGroundCollision(); + + // Jump deceleration code. + if (this.State != STATE_HURT) + { + if ((((Game.GlobalInput.Pressed(InputMapType.PLAYER_JUMP1) == false && Game.GlobalInput.Pressed(InputMapType.PLAYER_JUMP2) == false)|| (m_currentLogicSet == m_airAttackLS && m_currentLogicSet.IsActive == true && IsAirAttacking == false))) && m_isTouchingGround == false && AccelerationY < 0) + { + AccelerationY += JumpDeceleration * elapsedSeconds; + //if (AccelerationY > 0) // This code doesn't seem to do anything. + // AccelerationY = 0; + } + } + + if (Game.PlayerStats.Class == ClassType.Dragon && this.CurrentMana < MaxMana) + { + m_dragonManaRechargeCounter += elapsedSeconds; + if (m_dragonManaRechargeCounter >= GameEV.MANA_OVER_TIME_TIC_RATE) + { + m_dragonManaRechargeCounter = 0; + this.CurrentMana += GameEV.DRAGON_MANAGAIN; + } + } + + // Assassin Active code. + if (m_assassinSpecialActive == true) + { + m_assassinDrainCounter += elapsedSeconds; + if (m_assassinDrainCounter >= GameEV.MANA_OVER_TIME_TIC_RATE) + { + m_assassinDrainCounter = 0; + this.CurrentMana -= GameEV.ASSASSIN_ACTIVE_MANA_DRAIN; + if (CurrentMana <= 0) + DisableAssassinAbility(); + } + } + + if (m_timeStopCast == true) + { + m_timeStopDrainCounter += elapsedSeconds; + if (m_timeStopDrainCounter >= GameEV.MANA_OVER_TIME_TIC_RATE) + { + m_timeStopDrainCounter = 0; + this.CurrentMana -= GameEV.TIMESTOP_ACTIVE_MANA_DRAIN; + if (CurrentMana <= 0) + { + //m_levelScreen.UnpauseAllEnemies(); + AttachedLevel.StopTimeStop(); + m_timeStopCast = false; + } + } + } + + if (m_damageShieldCast == true) + { + m_damageShieldDrainCounter += elapsedSeconds; + if (m_damageShieldDrainCounter >= GameEV.MANA_OVER_TIME_TIC_RATE) + { + m_damageShieldDrainCounter = 0; + if (m_megaDamageShieldCast == true) + this.CurrentMana -= GameEV.DAMAGESHIELD_ACTIVE_MANA_DRAIN * GameEV.SPELLSWORD_MANACOST_MOD; + else + this.CurrentMana -= GameEV.DAMAGESHIELD_ACTIVE_MANA_DRAIN; + if (CurrentMana <= 0) + { + m_damageShieldCast = false; + m_megaDamageShieldCast = false; + } + } + } + + if (m_lightOn == true) + { + m_lightDrainCounter += elapsedSeconds; + if (m_lightDrainCounter >= 1) + { + m_lightDrainCounter = 0; + this.CurrentMana -= GameEV.SPELUNKER_LIGHT_DRAIN; + if (CurrentMana <= 0) + { + m_lightOn = false; + _objectList[PlayerPart.Light].Visible = false; + } + } + } + + if (State == STATE_TANOOKI) + { + m_tanookiDrainCounter += elapsedSeconds; + if (m_tanookiDrainCounter >= GameEV.MANA_OVER_TIME_TIC_RATE) + { + m_tanookiDrainCounter = 0; + this.CurrentMana -= GameEV.TANOOKI_ACTIVE_MANA_DRAIN; + if (CurrentMana <= 0) + DeactivateTanooki(); + } + } + + if (m_spellCastDelay > 0) + m_spellCastDelay -= elapsedSeconds; + + base.Update(gameTime); + } + else if (m_externalLS.IsActive == true) + m_externalLS.Update(gameTime); + } + + private void UpdateAnimationState() + { + switch (State) + { + case (STATE_TANOOKI): + if (this.SpriteName != "Tanooki_Character") + this.ChangeSprite("Tanooki_Character"); + break; + case (STATE_IDLE): + if (this.SpriteName != "PlayerIdle_Character") + this.ChangeSprite("PlayerIdle_Character"); + if (this.IsAnimating == false && m_playerHead.SpriteName != "PlayerIdleHeadUp_Sprite") + this.PlayAnimation(true); + break; + case (STATE_WALKING): + if (this.SpriteName != "PlayerWalking_Character") + this.ChangeSprite("PlayerWalking_Character"); + if (this.IsAnimating == false) + this.PlayAnimation(true); + break; + case (STATE_FLYING): + case(STATE_DRAGON): + case (STATE_JUMPING): + if (this.AccelerationY <= 0) + { + if (this.SpriteName != "PlayerJumping_Character") // Player just started jumping. + this.ChangeSprite("PlayerJumping_Character"); + } + else if (this.AccelerationY > 0) + { + if (this.SpriteName != "PlayerFalling_Character") // Player falling. + this.ChangeSprite("PlayerFalling_Character"); + } + if (this.IsAnimating == false) + this.PlayAnimation(true); + + break; + case (STATE_HURT): + if (this.SpriteName != "PlayerHurt_Character") + this.ChangeSprite("PlayerHurt_Character"); + if (this.IsAnimating == true) + this.StopAnimation(); + break; + case (STATE_DASHING): + if (this.HeadingX < 0 && this.Flip == SpriteEffects.None) + { + if (this.SpriteName != "PlayerDash_Character") + this.ChangeSprite("PlayerDash_Character"); + } + else if (this.HeadingX < 0 && this.Flip == SpriteEffects.FlipHorizontally) + { + if (this.SpriteName != "PlayerFrontDash_Character") + this.ChangeSprite("PlayerFrontDash_Character"); + } + + if (this.HeadingX > 0 && this.Flip == SpriteEffects.None) + { + if (this.SpriteName != "PlayerFrontDash_Character") + this.ChangeSprite("PlayerFrontDash_Character"); + } + else if (this.HeadingX > 0 && this.Flip == SpriteEffects.FlipHorizontally) + { + if (this.SpriteName != "PlayerDash_Character") + this.ChangeSprite("PlayerDash_Character"); + } + if (this.IsAnimating == false) + this.PlayAnimation(false); + break; + case (STATE_BLOCKING): + if (this.SpriteName != "PlayerBlock_Character") + { + this.ChangeSprite("PlayerBlock_Character"); + this.PlayAnimation(false); + } + break; + } + + } + + private void CheckGroundCollision() + { + IPhysicsObj previousClosestGround = m_closestGround; + m_previousIsTouchingGround = m_isTouchingGround; + m_isTouchingGround = false; + m_collidingLeft = m_collidingRight = false; + + m_collidingLeftOnly = m_collidingRightOnly = false; + bool foundBottomCollision = false; + + //if ((m_isJumping == false && this.AccelerationY >= 0 || (m_isJumping == true && this.AccelerationY >= 0))) // Only check ground collision if falling. Do not check if he's going up, or jumping. + //if (State != STATE_DRAGON) // Dragons cannot touch the ground. + { + IPhysicsObj closestTerrain = null; + float closestFloor = float.MaxValue; + + IPhysicsObj closestRotatedTerrain = null; + float closestRotatedFloor = float.MaxValue; + + //Rectangle elongatedPlayerBounds = this.TerrainBounds; + //elongatedPlayerBounds.Height += 10; // A rectangle slightly larger than the player's height is needed to check for collisions with. + + Rectangle elongatedPlayerBounds = new Rectangle(this.TerrainBounds.Left, this.TerrainBounds.Bottom - 78, this.TerrainBounds.Width, 78 + 10); + + // This is to fix the player hooking to walls and slipping through mouseholes. + // The consequence is that he can slip off ledges. + //elongatedPlayerBounds.X -= 10; + //elongatedPlayerBounds.Width += 20; + foreach (IPhysicsObj collisionObj in PhysicsMngr.ObjectList) + { + if (Game.PlayerStats.Traits.X == TraitType.NoFurniture || Game.PlayerStats.Traits.Y == TraitType.NoFurniture) + { + if (collisionObj is PhysicsObj && collisionObj is HazardObj == false) // Disable ground collision check for bookcases when you have this trait active. + continue; + } + + if (collisionObj != this && collisionObj.Visible == true && collisionObj.IsCollidable == true && (collisionObj.CollidesTop == true || collisionObj.CollidesLeft == true || collisionObj.CollidesRight == true) && collisionObj.HasTerrainHitBox == true && + (collisionObj.CollisionTypeTag == GameTypes.CollisionType_WALL || + collisionObj.CollisionTypeTag == GameTypes.CollisionType_GLOBAL_DAMAGE_WALL || + collisionObj.CollisionTypeTag == GameTypes.CollisionType_WALL_FOR_PLAYER || + collisionObj.CollisionTypeTag == GameTypes.CollisionType_ENEMYWALL)) + { + // This code prevents dragon or flight from landing on one ways. + if (collisionObj.CollidesTop == true && collisionObj.CollidesBottom == false && (State == STATE_FLYING || State == STATE_DRAGON)) + continue; + + // Don't register ground collision on mouse holes. + if (collisionObj.CollidesTop == true && collisionObj.CollidesBottom == true && collisionObj.CollidesLeft == false && collisionObj.CollidesRight == false) + continue; + + // Do separate checks for sloped and non-sloped terrain. + HazardObj hazard = collisionObj as HazardObj; + if (collisionObj.Rotation == 0 || hazard != null) + { + Rectangle collisionObjBounds = collisionObj.TerrainBounds; + if (hazard != null) + collisionObjBounds = collisionObj.Bounds; + Vector2 mtd = CollisionMath.CalculateMTD(elongatedPlayerBounds, collisionObjBounds); + + Rectangle intersectionBounds = new Rectangle(this.TerrainBounds.X, this.TerrainBounds.Y, this.TerrainBounds.Width, this.TerrainBounds.Height); + Vector2 intersectionDepth = CollisionMath.GetIntersectionDepth(intersectionBounds, collisionObjBounds); + + //// VERY SPECIAL CODE TO PREVENT THE PLAYER FROM HOOKING TO WALLS //////////////// + Rectangle wallBounds = new Rectangle(elongatedPlayerBounds.X - 10, elongatedPlayerBounds.Y, elongatedPlayerBounds.Width + 20, elongatedPlayerBounds.Height); + Vector2 wallMTD = CollisionMath.CalculateMTD(wallBounds, collisionObjBounds); + + // These flags make sure that pressing left or right no longer moves the player in those directions. + if (wallMTD.X > 0 && collisionObj.CollidesRight == true) + m_collidingLeft = true; + if (wallMTD.X < 0 && collisionObj.CollidesLeft == true) + m_collidingRight = true; + ////////////////////////////////////////////////////////////////////////////////// + + + Vector2 testMTD = CollisionMath.CalculateMTD(this.TerrainBounds, collisionObjBounds); + if (testMTD.X > 0) + m_collidingLeftOnly = true; + else if (testMTD.X < 0) + m_collidingRightOnly = true; + else if (testMTD.Y != 0) + foundBottomCollision = true; + + if (foundBottomCollision == true) + m_collidingRightOnly = m_collidingLeftOnly = false; + + // Don't include drop through ledges otherwise things screw up. + // This is dangerous code because it is a huge cause of 1-way false positives. + // This prevents the player from locking to one ways if they're just above him. + if (collisionObj.CollidesBottom == false && Math.Abs(collisionObjBounds.Top - this.TerrainBounds.Bottom) > 20 && this.AccelerationY < 1100) + { + //if ((collisionObj as GameObj).Name == "drop" && CollisionMath.Intersects(this.TerrainBounds, collisionObj.TerrainBounds)) + // Console.WriteLine("BREAK! " + Math.Abs(collisionObjBounds.Top - this.TerrainBounds.Bottom) + " Acceleration: " + this.AccelerationY); + + //if ((collisionObj as GameObj).Name == "test" && CollisionMath.Intersects(collisionObjBounds, this.TerrainBounds)) + // Console.WriteLine("BREAK! " + Math.Abs(collisionObjBounds.Top - this.TerrainBounds.Bottom) + " Acceleration: " + this.AccelerationY); + continue; + } + + // This check is to see if you are falling and hitting the platform from above, or from the side. If falling from the side, don't include this as a ground obj. + //if (Math.Abs(intersectionDepth.X) > 2) + int intersectionX = (int)Math.Abs(intersectionDepth.X); + int intersectionY = (int)Math.Abs(intersectionDepth.Y); + if (intersectionX > 1 && intersectionX < intersectionY) + continue; + + if ((m_isJumping == false && this.AccelerationY >= 0 || (m_isJumping == true && this.AccelerationY >= 0))) // Only check ground collision if falling. Do not check if he's going up, or jumping. + { + //if (State != STATE_DRAGON) // Dragons cannot touch the ground. + + if ((mtd.Y < 0 || (mtd.Y == 0 && mtd.X != 0 && collisionObjBounds.Top > this.TerrainBounds.Top && collisionObj.Y > this.Y))) + { + int distance = Math.Abs(collisionObjBounds.Top - this.TerrainBounds.Bottom); + + if (distance < closestFloor) + { + closestTerrain = collisionObj; + closestFloor = distance; + m_closestGround = closestTerrain; + } + } + } + } + else + { + if ((m_isJumping == false && this.AccelerationY >= 0 || (m_isJumping == true && this.AccelerationY >= 0))) // Only check ground collision if falling. Do not check if he's going up, or jumping. + { + if (collisionObj is HazardObj == false) + { + Vector2 rotatedMTD = CollisionMath.RotatedRectIntersectsMTD(elongatedPlayerBounds, this.Rotation, Vector2.Zero, collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + //if ((collisionObj as GameObj).Name == "rotat") + //{ + // Console.WriteLine(this.SpriteName + " " + elongatedPlayerBounds); + //} + if (rotatedMTD.Y < 0) + { + float distance = rotatedMTD.Y; + if (distance < closestRotatedFloor) + { + closestRotatedTerrain = collisionObj; + closestRotatedFloor = distance; + } + } + + } + } + } + } + } + + if (closestTerrain != null && State != STATE_DRAGON) + { + //if (closestTerrain == m_lastPlatform && m_droppingThroughGround == true) + // m_isTouchingGround = false; + //else + // m_isTouchingGround = true; + + // New logic for determining whether you should fall through a one-way. + if (m_dropThroughGroundTimer > 0 && closestTerrain.CollidesBottom == false && closestTerrain.CollidesTop == true) + m_isTouchingGround = false; + else + m_isTouchingGround = true; + } + + if (closestRotatedTerrain != null && State != STATE_DRAGON) + { + HookToSlope(closestRotatedTerrain); + m_isTouchingGround = true; + } + + if (m_isTouchingGround == true) + { + if (State == STATE_JUMPING || State == STATE_FLYING || State == STATE_HURT) // Player just landed. + { + if (Game.PlayerStats.Traits.X == TraitType.Gigantism || Game.PlayerStats.Traits.Y == TraitType.Gigantism) + { + SoundManager.PlaySound("Player_Land_Low"); + if (this.AccelerationY > 1400) + { + SoundManager.PlaySound("TowerLand"); + AttachedLevel.ImpactEffectPool.DisplayDustEffect(new Vector2(this.TerrainBounds.Left, this.Bounds.Bottom)); + AttachedLevel.ImpactEffectPool.DisplayDustEffect(new Vector2(this.TerrainBounds.X, this.Bounds.Bottom)); + AttachedLevel.ImpactEffectPool.DisplayDustEffect(new Vector2(this.TerrainBounds.Right, this.Bounds.Bottom)); + } + } + if (Game.PlayerStats.Traits.X == TraitType.Dwarfism || Game.PlayerStats.Traits.Y == TraitType.Dwarfism) + SoundManager.PlaySound("Player_Land_High"); + else + SoundManager.PlaySound("Player_Land"); + } + + if (State == STATE_HURT) + m_invincibleCounter = InvincibilityTime; + + if (IsAirAttacking == true) + { + IsAirAttacking = false; + CancelAttack(); + } + + this.AccelerationX = 0; + + // Code to make sure to disable flying when the player touches the ground. + m_flightCounter = TotalFlightTime; + if (State != STATE_DASHING) + { + m_airDashCount = 0; + this.AccelerationYEnabled = true; + } + + NumAirBounces = 0; + m_isFlying = false; + DisableGravity = false; + + if (State == STATE_TANOOKI) + this.CurrentSpeed = 0; + + // Reset any jumping states. I.e. air jump, air dash, etc. + m_isJumping = false; + m_doubleJumpCount = 0; + + if (State != STATE_BLOCKING && State != STATE_TANOOKI && State != STATE_DASHING) // This line also breaks the player out of his hurt state. + State = STATE_IDLE; + + if (State != STATE_BLOCKING && State != STATE_TANOOKI && State != STATE_DASHING) + { + if (closestTerrain != null && this.ControlsLocked == false) + { + if ((((Game.GlobalInput.Pressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_DOWN2)) && (Game.GlobalInput.JustPressed(InputMapType.PLAYER_JUMP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_JUMP2))) + || (Game.GameConfig.QuickDrop == true && (Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN2)))) && closestTerrain.CollidesBottom == false && State != STATE_TANOOKI) // Code for dropping through ground. + { + this.AccelerationY = 0; + this.Y += 15; // This number must be 1 unit larger than the margin of error in CheckGroundCollision(). Or not? Added a different check using m_droppingThroughGround that should be more reliable. + m_isTouchingGround = false; + m_isJumping = true; + m_dropThroughGroundTimer = m_dropThroughGroundDuration; + } + } + } + } + } + } + + private void HookToSlope(IPhysicsObj collisionObj) + { + if (State != STATE_DASHING) + { + this.UpdateCollisionBoxes(); + + // Code for hooking the player to a slope + Rectangle elongatedRect = this.TerrainBounds; + elongatedRect.Height += 20; + //int checkAmount = 15; + float x1 = this.X; + + Vector2 elongatedMTD = CollisionMath.RotatedRectIntersectsMTD(elongatedRect, this.Rotation, Vector2.Zero, collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + if (elongatedMTD.Y < 0) // Player is standing on a slope because the mtd is telling you to push him up. + { + bool checkCollision = false; + float y1 = float.MaxValue; + Vector2 pt1, pt2; + if (collisionObj.Width > collisionObj.Height) // If rotated objects are done correctly. + { + pt1 = CollisionMath.UpperLeftCorner(collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + pt2 = CollisionMath.UpperRightCorner(collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + + if (Math.Abs(collisionObj.Rotation - 45.0f) <= 1.0f) // Due to floating point imprecision, don't test against 45, but test within a threshold + x1 = this.TerrainBounds.Left; + else + x1 = this.TerrainBounds.Right; + + if (x1 > pt1.X && x1 < pt2.X) + checkCollision = true; + } + else // If rotated objects are done Teddy's incorrect way. + { + if (Math.Abs(collisionObj.Rotation - 45.0f) <= 1.0f) // Due to floating point imprecision, don't test against 45, but test within a threshold + { + pt1 = CollisionMath.LowerLeftCorner(collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + pt2 = CollisionMath.UpperLeftCorner(collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + x1 = this.TerrainBounds.Right; + if (x1 > pt1.X && x1 < pt2.X) + checkCollision = true; + } + else + { + pt1 = CollisionMath.UpperRightCorner(collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + pt2 = CollisionMath.LowerRightCorner(collisionObj.TerrainBounds, collisionObj.Rotation, Vector2.Zero); + x1 = this.TerrainBounds.Left; + if (x1 > pt1.X && x1 < pt2.X) + checkCollision = true; + } + } + + if (checkCollision == true) + { + float u = pt2.X - pt1.X; + float v = pt2.Y - pt1.Y; + float x = pt1.X; + float y = pt1.Y; + + y1 = y + (x1 - x) * (v / u); + y1 -= this.TerrainBounds.Bottom - this.Y - 2; // Up by 2 to ensure collision response doesn't kick in. + this.Y = (int)y1; + } + } + } + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + IPhysicsObj otherBoxParent = otherBox.AbsParent as IPhysicsObj; + TeleporterObj teleporter = otherBox.Parent as TeleporterObj; + + if (teleporter != null && ControlsLocked == false && IsTouchingGround == true) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + StopAllSpells(); + this.LockControls(); + m_lastTouchedTeleporter = teleporter; + Tween.RunFunction(0, this.AttachedLevel, "DisplayMap", true); + //Tween.AddEndHandlerToLastTween(AttachedLevel.ScreenManager, "DisplayScreen", ScreenType.Map, true, this); + } + } + + // Logic for moving the player from a boss entrance to a boss room, and vice versa. + DoorObj door = otherBox.Parent as DoorObj; + if (door != null && ControlsLocked == false && IsTouchingGround == true) + { + if (door.IsBossDoor == true && door.Locked == false && (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2))) + { + // This line ensures you don't access the donation box at the same time as entering a boss room. + if (door.Room.DonationBox == null || (door.Room.DonationBox != null && (door.Room.DonationBox.IsTouching == false || door.Room.DonationBox.Visible == false))) + { + if (door.Name == "FinalBossDoor") + Game.ScreenManager.DisplayScreen(ScreenType.Ending, true, null); + else + { + RoomObj linkedRoom = door.Room.LinkedRoom; + if (linkedRoom != null) + { + foreach (DoorObj possibleEntrance in linkedRoom.DoorList) + { + if (possibleEntrance.IsBossDoor == true) + { + // Linking the LastBossChallengeRoom to the Boss Entrance you entered from. + if (linkedRoom is LastBossChallengeRoom) + linkedRoom.LinkedRoom = AttachedLevel.CurrentRoom; + + StopAllSpells(); + this.CurrentSpeed = 0; + this.LockControls(); + (m_levelScreen.ScreenManager as RCScreenManager).StartWipeTransition(); + Vector2 roomPos = new Vector2(possibleEntrance.X + possibleEntrance.Width / 2f, possibleEntrance.Bounds.Bottom - (this.Bounds.Bottom - this.Y)); + Tween.RunFunction(0.2f, this, "EnterBossRoom", roomPos); + Tween.RunFunction(0.2f, m_levelScreen.ScreenManager, "EndWipeTransition"); + break; + } + } + } + } + } + } + } + + BreakableObj breakableObj = otherBoxParent as BreakableObj; + if (breakableObj != null) + { + if (IsAirAttacking == true && thisBox.Type == Consts.WEAPON_HITBOX) + { + this.IsAirAttacking = false; // Only allow one object to perform upwards air knockback on the player. + this.AccelerationY = -this.AirAttackKnockBack; + this.NumAirBounces++; + } + } + + + if (Game.PlayerStats.Traits.X == TraitType.NoFurniture || Game.PlayerStats.Traits.Y == TraitType.NoFurniture) + { + if (breakableObj != null) + { + if (breakableObj.Broken == false) + breakableObj.Break(); + } + + if (otherBoxParent.GetType() == typeof(PhysicsObj) && (otherBoxParent as PhysicsObj).SpriteName != "CastleEntranceGate_Sprite") // Disables collision for things like book cases. + return; + } + + // Check to see if the terrain collision is with a wall, not with another enemy's terrain hitbox. + if (collisionResponseType == Consts.COLLISIONRESPONSE_TERRAIN && + (otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_WALL || otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_WALL_FOR_PLAYER || otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_ENEMYWALL + || otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_GLOBAL_DAMAGE_WALL)) + { + //if (otherBoxParent.CollidesBottom == false) + // m_lastPlatform = otherBoxParent; + + Vector2 mtdPos = CollisionMath.CalculateMTD(thisBox.AbsRect, otherBox.AbsRect); + + float accelerationYHolder = AccelerationY; + Vector2 rotatedMTDPos = CollisionMath.RotatedRectIntersectsMTD(thisBox.AbsRect, thisBox.AbsRotation, Vector2.Zero, otherBox.AbsRect, otherBox.AbsRotation, Vector2.Zero); + + bool checkCollision = true; + + if (m_dropThroughGroundTimer > 0 && otherBoxParent.CollidesBottom == false && otherBoxParent.CollidesTop == true) + checkCollision = false; + + // Used to make sure he doesn't hook to 1-way ground above him if he's already standing on flooring. + if (m_isTouchingGround == true && otherBoxParent.CollidesBottom == false && otherBoxParent.CollidesTop == true && otherBoxParent.TerrainBounds.Top < this.TerrainBounds.Bottom - 10) + checkCollision = false; + + // This line is for one ways. If he drops down and is going slow enough, disable collision. This is dangerous as it could result in you + // dropping through platforms. Also, doesn't work with really large platforms. + if (otherBoxParent.CollidesBottom == false && this.Bounds.Bottom > otherBoxParent.TerrainBounds.Top + 10 && m_isTouchingGround == false)//this.AccelerationY < 600) + checkCollision = false; + + if (otherBoxParent.CollidesBottom == false && otherBoxParent.CollidesTop == true && (State == STATE_FLYING || State == STATE_DRAGON)) + checkCollision = false; + + // Used to make sure he doesn't hook to two tiered walls. + if ((m_collidingLeftOnly == true || m_collidingRightOnly == true) && Math.Abs(mtdPos.X) < 10 && m_isTouchingGround == false && otherBoxParent is HazardObj == false) + checkCollision = false; + + // Super hack to prevent player from moving through mouseholes regardless of his speed. + if (otherBoxParent.CollidesLeft == false && otherBoxParent.CollidesRight == false && otherBoxParent.CollidesTop == true && otherBoxParent.CollidesBottom == true && otherBoxParent is HazardObj == false) + { + if (Game.PlayerStats.Traits.X != TraitType.Dwarfism && Game.PlayerStats.Traits.Y != TraitType.Dwarfism) + { + if (this.X < otherBoxParent.TerrainBounds.Center.X) + this.X -= this.TerrainBounds.Right - otherBoxParent.TerrainBounds.Left; + else + this.X += otherBoxParent.TerrainBounds.Right - this.TerrainBounds.Left; + } + else + checkCollision = false; + } + + // This is the step up code. + //if (Math.Abs(mtdPos.X) < 10 && mtdPos.X != 0 && Math.Abs(mtdPos.Y) < 10 && mtdPos.Y != 0) + // checkCollision = false; + + // This code was for handling corners. Without it, if you were falling on a corner, your X translation would be smaller than the Y translation, causing your + // player to be pushed out sideways when landing on a corner of an object, instead of upward ontop of the object. + // But now it causes problems when standing on one ledge, and walking into another ledge if the differences are short enough. Instead of pushing you sideways, it pushes you upwards. + if (m_isTouchingGround == true && m_closestGround == otherBoxParent)// && m_previousIsTouchingGround != m_isTouchingGround) + { + checkCollision = false; + if (otherBoxParent is HazardObj && otherBoxParent.Rotation == -90) // I'm so tired. Super hack to make these effing hazard blocks work at this rotation. + this.Y += m_closestGround.Bounds.Top - this.TerrainBounds.Bottom + 15; + else + this.Y += m_closestGround.TerrainBounds.Top - this.TerrainBounds.Bottom; + this.AccelerationY = 0; + } + + if (checkCollision == true) + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + if (rotatedMTDPos.Y != 0 && otherBox.AbsRotation != 0)// && otherBox.AbsRotation >= -SlopeClimbRotation && otherBox.AbsRotation <= SlopeClimbRotation) // Code to prevent player from sliding down rotated objects. + { + //this.CurrentSpeed = 0; // Prevents player from dashing through angled blocks. + this.X -= rotatedMTDPos.X; // Prevents player from sliding down + } + // Disabled for now because it screws up when standing on turrets that are rotated more than SlopeClimbRotation. + //else if (otherBox.AbsRotation < -SlopeClimbRotation || otherBox.AbsRotation > SlopeClimbRotation) // Prevents player from climbing slopes that are too steep. + // AccelerationY = accelerationYHolder; + } + + if (thisBox.Type == Consts.BODY_HITBOX && otherBox.Type == Consts.WEAPON_HITBOX && + (otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_ENEMY || otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_ENEMYWALL || otherBoxParent.CollisionTypeTag == GameTypes.CollisionType_GLOBAL_DAMAGE_WALL) && State != STATE_HURT && m_invincibleCounter <= 0) + { + EnemyObj enemy = otherBoxParent as EnemyObj; + if (enemy != null && enemy.IsDemented == true) + return; + ProjectileObj proj = otherBoxParent as ProjectileObj; + if (proj != null && proj.IsDemented == true) + return; + + //if (proj != null && (proj.Spell == SpellType.Boomerang || proj.Spell == SpellType.Bounce)) + // return; + + // Enemy hit player. Response goes here. + // Player blocked + if (State == STATE_BLOCKING && (CurrentMana > 0 || m_blockInvincibleCounter > 0) && (proj == null || (proj != null && proj.Spell != SpellType.Boomerang && proj.Spell != SpellType.Bounce)))//CurrentMana >= BlockManaDrain) + { + if (CanBeKnockedBack == true) + { + Point intersectPt = Rectangle.Intersect(thisBox.AbsRect, otherBox.AbsRect).Center; + Vector2 impactPosition = new Vector2(intersectPt.X, intersectPt.Y); + if (impactPosition == Vector2.Zero) + impactPosition = this.Position; + m_levelScreen.ImpactEffectPool.DisplayBlockImpactEffect(impactPosition, Vector2.One); + + CurrentSpeed = 0; + + if (otherBox.AbsParent.Bounds.Left + otherBox.AbsParent.Bounds.Width / 2 > this.X) + AccelerationX = -KnockBack.X; + else + AccelerationX = KnockBack.X; + AccelerationY = -KnockBack.Y; + + Blink(Color.LightBlue, 0.1f); + } + + if (m_blockInvincibleCounter <= 0) + { + CurrentMana -= BlockManaDrain; + m_blockInvincibleCounter = BlockInvincibleTime; + m_levelScreen.TextManager.DisplayNumberStringText(-GameEV.KNIGHT_BLOCK_DRAIN, "LOC_ID_SKILL_SCREEN_15" /*"mp"*/, Color.SkyBlue, new Vector2(this.X, this.Bounds.Top)); + } + + SoundManager.PlaySound("Player_Block"); + //SoundManager.PlaySound("Block1", "Block2", "Block3"); + } + else // Player got hit. + { + if (m_invincibleCounter <= 0) + HitPlayer(otherBox.AbsParent); // Not using otherBoxParent because that has been cast as an IPhysicsObj. + } + + ProjectileObj projectile = otherBox.AbsParent as ProjectileObj; + if (projectile != null && projectile.DestroysWithEnemy == true && m_assassinSpecialActive == false) + projectile.RunDestroyAnimation(true); + //m_levelScreen.ProjectileManager.DestroyProjectile(projectile); + } + + // Maybe this should go into the itemdropobj. + ItemDropObj itemDrop = otherBoxParent as ItemDropObj; + if (itemDrop != null && itemDrop.IsCollectable) + { + itemDrop.GiveReward(this, m_levelScreen.TextManager); + itemDrop.IsCollidable = false; + itemDrop.IsWeighted = false; + itemDrop.AnimationDelay = 1 / 60f; + itemDrop.AccelerationY = 0; + itemDrop.AccelerationX = 0; + Tweener.Tween.By(itemDrop, 0.4f, Tweener.Ease.Quad.EaseOut, "Y", "-120"); + Tweener.Tween.To(itemDrop, 0.1f, Tweener.Ease.Linear.EaseNone, "delay", "0.6", "Opacity", "0"); + Tweener.Tween.AddEndHandlerToLastTween(m_levelScreen.ItemDropManager, "DestroyItemDrop", itemDrop); + //SoundManager.PlaySound("CoinCollect1", "CoinCollect2", "CoinCollect3"); + SoundManager.PlaySound("CoinDrop1", "CoinDrop2", "CoinDrop3", "CoinDrop4", "CoinDrop5"); + + //m_levelScreen.ItemDropManager.DestroyItemDrop(itemDrop); + //SoundManager.PlaySound("CoinPickup"); + } + + ChestObj chest = otherBoxParent as ChestObj; + if (chest != null && ControlsLocked == false && m_isTouchingGround == true) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + if (chest.IsOpen == false) + chest.OpenChest(m_levelScreen.ItemDropManager, this); + } + } + } + + public void PlayAttackSound() + { + if (Game.PlayerStats.IsFemale == true) + SoundManager.PlaySound("Player_Female_Effort_03", "Player_Female_Effort_04", "Player_Female_Effort_05", "Player_Female_Effort_06", "Player_Female_Effort_07", + "Blank", "Blank", "Blank"); + else + SoundManager.PlaySound("Player_Male_Effort_01", "Player_Male_Effort_02", "Player_Male_Effort_04", "Player_Male_Effort_05", "Player_Male_Effort_07", + "Blank", "Blank", "Blank"); + + if (Game.PlayerStats.Class == ClassType.SpellSword || Game.PlayerStats.Class == ClassType.SpellSword2) + SoundManager.PlaySound("Player_Attack_Sword_Spell_01", "Player_Attack_Sword_Spell_02", "Player_Attack_Sword_Spell_03"); + else + { + if (IsAirAttacking == false) + { + if (Game.PlayerStats.Traits.X == TraitType.Hypergonadism || Game.PlayerStats.Traits.Y == TraitType.Hypergonadism) + SoundManager.PlaySound("Player_Attack01_Low", "Player_Attack02_Low"); + else if (Game.PlayerStats.Traits.X == TraitType.Hypogonadism || Game.PlayerStats.Traits.Y == TraitType.Hypogonadism) + SoundManager.PlaySound("Player_Attack01_High", "Player_Attack02_High"); + else + SoundManager.PlaySound("Player_Attack01", "Player_Attack02"); + } + else + { + if (Game.PlayerStats.Traits.X == TraitType.Hypergonadism || Game.PlayerStats.Traits.Y == TraitType.Hypergonadism) + SoundManager.PlaySound("Player_AttackDown01_Low", "Player_AttackDown02_Low"); + else if (Game.PlayerStats.Traits.X == TraitType.Hypogonadism || Game.PlayerStats.Traits.Y == TraitType.Hypogonadism) + SoundManager.PlaySound("Player_AttackDown01_High", "Player_AttackDown02_High"); + else + SoundManager.PlaySound("Player_AttackDown01", "Player_AttackDown02"); + } + } + } + + public void EnterBossRoom(Vector2 position) + { + this.Position = position; + } + + public void TeleportPlayer(Vector2 position, TeleporterObj teleporter = null) + { + this.CurrentSpeed = 0; + this.Scale = m_internalScale; + + if (teleporter == null) + teleporter = m_lastTouchedTeleporter; + Console.WriteLine("Player pos: " + this.Position + " teleporter: " + teleporter.Position); + + Tween.To(this, 0.4f, Tweener.Ease.Linear.EaseNone, "X", teleporter.X.ToString()); + Tween.To(this, 0.05f, Tweener.Ease.Linear.EaseNone, "delay", "1.5", "ScaleX", "0"); + Vector2 storedScale = this.Scale; + this.ScaleX = 0; + Tween.To(this, 0.05f, Tweener.Ease.Linear.EaseNone, "delay", "3.3", "ScaleX", storedScale.X.ToString()); + this.ScaleX = storedScale.X; + Vector2 playerTeleportPos = new Vector2(position.X, position.Y - (this.TerrainBounds.Bottom - this.Y)); + + LogicSet teleportLS = new LogicSet(this); + teleportLS.AddAction(new RunFunctionLogicAction(this, "LockControls")); + teleportLS.AddAction(new ChangeSpriteLogicAction("PlayerJumping_Character")); + teleportLS.AddAction(new JumpLogicAction(500)); + teleportLS.AddAction(new PlaySoundLogicAction("Player_Jump_04")); + teleportLS.AddAction(new RunFunctionLogicAction(teleporter, "SetCollision", true)); + teleportLS.AddAction(new DelayLogicAction(0.4f)); + teleportLS.AddAction(new GroundCheckLogicAction()); + teleportLS.AddAction(new ChangeSpriteLogicAction("PlayerLevelUp_Character", true, false), Types.Sequence.Parallel); + teleportLS.AddAction(new DelayLogicAction(0.1f)); + teleportLS.AddAction(new RunFunctionLogicAction(this.AttachedLevel.ImpactEffectPool, "DisplayTeleportEffect", new Vector2(teleporter.X, teleporter.Bounds.Top))); + teleportLS.AddAction(new DelayLogicAction(1f)); + teleportLS.AddAction(new PlaySoundLogicAction("Teleport_Disappear")); + teleportLS.AddAction(new RunFunctionLogicAction(this.AttachedLevel.ImpactEffectPool, "MegaTeleport", new Vector2(teleporter.X, teleporter.Bounds.Top), this.Scale)); + teleportLS.AddAction(new DelayLogicAction(0.8f)); + teleportLS.AddAction(new RunFunctionLogicAction(m_levelScreen.ScreenManager, "StartWipeTransition")); + teleportLS.AddAction(new DelayLogicAction(0.2f)); + teleportLS.AddAction(new RunFunctionLogicAction(teleporter, "SetCollision", false)); + teleportLS.AddAction(new TeleportLogicAction(null, playerTeleportPos)); + teleportLS.AddAction(new DelayLogicAction(0.05f)); + teleportLS.AddAction(new RunFunctionLogicAction(m_levelScreen.ScreenManager, "EndWipeTransition")); + teleportLS.AddAction(new DelayLogicAction(0.5f)); + teleportLS.AddAction(new RunFunctionLogicAction(this.AttachedLevel.ImpactEffectPool, "MegaTeleportReverse", new Vector2(position.X - 5, position.Y + 57), storedScale)); + teleportLS.AddAction(new PlaySoundLogicAction("Teleport_Reappear")); + teleportLS.AddAction(new DelayLogicAction(0.2f)); + teleportLS.AddAction(new RunFunctionLogicAction(this, "LastBossDoorHack")); + //teleportLS.AddAction(new RunFunctionLogicAction(this, "UnlockControls")); + this.RunExternalLogicSet(teleportLS); + } + + public void LastBossDoorHack() + { + if (m_levelScreen.CurrentRoom is CastleEntranceRoomObj && Game.PlayerStats.EyeballBossBeaten == true && Game.PlayerStats.FairyBossBeaten == true && Game.PlayerStats.BlobBossBeaten == true && Game.PlayerStats.FireballBossBeaten == true + && Game.PlayerStats.FinalDoorOpened == false) + { + (m_levelScreen.CurrentRoom as CastleEntranceRoomObj).PlayBossDoorAnimation(); + Game.PlayerStats.FinalDoorOpened = true; + m_levelScreen.RunCinematicBorders(6); // Hack to prevent cinematic border conflict. + } + else + UnlockControls(); + } + + public void RunExternalLogicSet(LogicSet ls) + { + if (m_currentLogicSet != null && m_currentLogicSet.IsActive == true) + m_currentLogicSet.Stop(); + + this.AnimationDelay = 1 / 10f; + + if (m_externalLS != null) + m_externalLS.Dispose(); + + m_externalLS = ls; + m_externalLS.Execute(); + } + + public void HitPlayer(GameObj obj) + { + bool hitPlayer = true; + if (obj is HazardObj) + { + if ((Game.PlayerStats.SpecialItem == SpecialItemType.SpikeImmunity && obj.Bounds.Top > this.Y) || InvincibleToSpikes == true) + hitPlayer = false; + } + + ProjectileObj projectile = obj as ProjectileObj; + if (projectile != null) + { + if (projectile.IsDemented == true) + hitPlayer = false; + else if (projectile.Spell == SpellType.Bounce || projectile.Spell == SpellType.Boomerang) + { + hitPlayer = false; + projectile.KillProjectile(); + m_levelScreen.ImpactEffectPool.SpellCastEffect(projectile.Position, CDGMath.AngleBetweenPts(this.Position, projectile.Position), false); + } + + // Check to make sure you don't die at the same time as a boss if you are hit by the boss's projectile the moment you kill him. + EnemyObj projectileSource = projectile.Source as EnemyObj; + if (projectileSource != null && (projectileSource.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS || projectileSource is EnemyObj_LastBoss) && projectileSource.CurrentHealth <= 0) + hitPlayer = false; + } + + EnemyObj dementedEnemy = obj as EnemyObj; + if (dementedEnemy != null && dementedEnemy.IsDemented == true) + hitPlayer = false; + + // A check to make sure player's that die to enemies at the same time as hitting back, won't screw things up. + if (dementedEnemy != null && (dementedEnemy.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS || dementedEnemy is EnemyObj_LastBoss) && dementedEnemy.CurrentHealth <= 0) + hitPlayer = false; + + // Disable force invincibility on spikes + if (hitPlayer == true && (ForceInvincible == false || (ForceInvincible == true && obj is HazardObj))) + { + Blink(Color.Red, 0.1f); + this.m_levelScreen.ImpactEffectPool.DisplayPlayerImpactEffect(this.Position); + //this.TextureColor = Color.White; + this.AccelerationYEnabled = true; // In case player acceleration is disabled during a dash. + this.UnlockControls(); // Unlock player controls in case they were locked during a dash. + int damage = (obj as IDealsDamageObj).Damage; + damage = (int)((damage - (damage * TotalDamageReduc)) * ClassDamageTakenMultiplier); + if (damage < 0) damage = 0; + + // Prevent the player from taking any damage in the tutorial. + if (Game.PlayerStats.TutorialComplete == false) + damage = 0; + + if (Game.PlayerStats.GodMode == false) + this.CurrentHealth -= damage; + + EnemyObj enemyObj = obj as EnemyObj; + if (enemyObj != null && CurrentHealth > 0) + { + int damageReturn = (int)(damage * TotalDamageReturn); + if (damageReturn > 0) + enemyObj.HitEnemy(damageReturn, enemyObj.Position, true); + } + + // projectile is defined up top. + if (projectile != null && projectile.CollisionTypeTag == GameTypes.CollisionType_ENEMY) + { + EnemyObj enemy = projectile.Source as EnemyObj; + if (enemy != null && enemy.IsKilled == false && enemy.IsDemented == false && CurrentHealth > 0) + { + int damageReturn = (int)(damage * TotalDamageReturn); + if (damageReturn > 0) + enemy.HitEnemy(damageReturn, enemy.Position, true); + } + } + + // Needed for chests. + m_isJumping = false; + + // Disables flying. + m_isFlying = false; + this.DisableGravity = false; + + if (CanBeKnockedBack == true)//(CanBeKnockedBack == true && (Game.PlayerStats.Traits.X != TraitType.Endomorph && Game.PlayerStats.Traits.Y != TraitType.Endomorph))// && Game.TraitSystem.GetModifierAmount(m_traitArray, TraitType.Knockback_Immune) <= 0) // If you have knockback immune trait, don't get knocked back //TEDDY MAKING KNOCKBACK NOT 0 FOR ECTOMORPH + { + if (Game.PlayerStats.Traits.X == TraitType.Tourettes || Game.PlayerStats.Traits.Y == TraitType.Tourettes) + { + int randBubble = CDGMath.RandomInt(1, 4); + m_swearBubble.ChangeSprite("SwearBubble" + randBubble + "_Sprite"); + m_swearBubble.Visible = true; + m_swearBubbleCounter = 1f; + } + + State = STATE_HURT; + + UpdateAnimationState(); // Force his animation to a hurt state. + if (m_currentLogicSet.IsActive) + m_currentLogicSet.Stop(); + IsAirAttacking = false; + AnimationDelay = m_startingAnimationDelay; + + CurrentSpeed = 0; + + float knockbackMod = 1;// Game.TraitSystem.GetModifierAmount(m_traitArray, TraitType.Knockback_Weak); + if (Game.PlayerStats.Traits.X == TraitType.Ectomorph || Game.PlayerStats.Traits.Y == TraitType.Ectomorph) + knockbackMod = GameEV.TRAIT_ECTOMORPH; + + if (Game.PlayerStats.Traits.X == TraitType.Endomorph || Game.PlayerStats.Traits.Y == TraitType.Endomorph) + knockbackMod = GameEV.TRAIT_ENDOMORPH; + + if (obj.Bounds.Left + obj.Bounds.Width / 2 > this.X) + AccelerationX = -KnockBack.X * knockbackMod; + else + AccelerationX = KnockBack.X * knockbackMod; + AccelerationY = -KnockBack.Y * knockbackMod; + } + else + m_invincibleCounter = InvincibilityTime; // Kick in the invincible timer automatically if the player is hit and knockback_immune trait exists. + + if (CurrentHealth <= 0) + { + if (Game.PlayerStats.SpecialItem == SpecialItemType.Revive) + { + this.CurrentHealth = (int)(MaxHealth * 0.25f); + Game.PlayerStats.SpecialItem = SpecialItemType.None; + (Game.ScreenManager.CurrentScreen as ProceduralLevelScreen).UpdatePlayerHUDSpecialItem(); + m_invincibleCounter = InvincibilityTime; // Kick in the invincible timer automatically if the player is hit and knockback_immune trait exists. + (m_levelScreen.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.DeathDefy, true); + } + else + { + int chanceToSurvive = CDGMath.RandomInt(1, 100); + if (chanceToSurvive <= SkillSystem.GetSkill(SkillType.Death_Dodge).ModifierAmount * 100) + { + //this.CurrentHealth = 1; + this.CurrentHealth = (int)(MaxHealth * 0.1f); + m_invincibleCounter = InvincibilityTime; // Kick in the invincible timer automatically if the player is hit and knockback_immune trait exists. + (m_levelScreen.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.DeathDefy, true); + } + else + { + ChallengeBossRoomObj challengeRoom = AttachedLevel.CurrentRoom as ChallengeBossRoomObj; + if (challengeRoom != null) + { + challengeRoom.KickPlayerOut(); + } + else + { + this.AttachedLevel.SetObjectKilledPlayer(obj); + Kill(); + } + } + } + } + + if (m_levelScreen.IsDisposed == false) + { + if (Game.PlayerStats.Traits.X == TraitType.Hypochondriac || Game.PlayerStats.Traits.Y == TraitType.Hypochondriac) + m_levelScreen.TextManager.DisplayNumberText(damage * 100 + CDGMath.RandomInt(1,99), Color.Red, new Vector2(this.X, this.Bounds.Top)); + else + m_levelScreen.TextManager.DisplayNumberText(damage, Color.Red, new Vector2(this.X, this.Bounds.Top)); + } + + if (Game.PlayerStats.SpecialItem == SpecialItemType.LoseCoins) + { + int numCoinsLost = (int)(Game.PlayerStats.Gold * 0.25f / ItemDropType.CoinAmount); + if (numCoinsLost > 50) numCoinsLost = 50; + if (numCoinsLost > 0 && AttachedLevel.ItemDropManager.AvailableItems > numCoinsLost) + { + float castleLockGoldModifier = 1; + if (Game.PlayerStats.HasArchitectFee == true) + castleLockGoldModifier = GameEV.ARCHITECT_FEE; + //Game.PlayerStats.Gold -= numCoinsLost * ItemDropType.CoinAmount; + int goldAmount = (int)(((numCoinsLost * ItemDropType.CoinAmount) * (1 + this.TotalGoldBonus)) * castleLockGoldModifier); + Game.PlayerStats.Gold -= goldAmount; + for (int i = 0; i < numCoinsLost; i++) + m_levelScreen.ItemDropManager.DropItemWide(this.Position, ItemDropType.Coin, ItemDropType.CoinAmount); + + if (goldAmount > 0) + AttachedLevel.TextManager.DisplayNumberStringText(-(int)goldAmount, "LOC_ID_PLAYER_OBJ_1" /*"gold"*/, Color.Yellow, new Vector2(this.X, this.Bounds.Top)); + //SoundManager.PlaySound("SonicRingOut"); + } + } + + if (Game.PlayerStats.IsFemale == true) + SoundManager.PlaySound("Player_Female_Damage_03", "Player_Female_Damage_04", "Player_Female_Damage_05", "Player_Female_Damage_06", "Player_Female_Damage_07"); + else + SoundManager.PlaySound("Player_Male_Injury_01", "Player_Male_Injury_02", "Player_Male_Injury_03", "Player_Male_Injury_04", "Player_Male_Injury_05", + "Player_Male_Injury_06", "Player_Male_Injury_07", "Player_Male_Injury_08", "Player_Male_Injury_09", "Player_Male_Injury_10"); + SoundManager.PlaySound("EnemyHit1", "EnemyHit2", "EnemyHit3", "EnemyHit4", "EnemyHit5", "EnemyHit6"); + } + } + + // Really just for exiting compass rooms. Makes you invincible for a short period so that you don't die on exit. + public void KickInHitInvincibility() + { + m_invincibleCounter = InvincibilityTime; + } + + public override void Kill(bool giveXP = true) + { + ChallengeBossRoomObj challengeRoom = AttachedLevel.CurrentRoom as ChallengeBossRoomObj; + if (challengeRoom != null) + { + challengeRoom.LoadPlayerData(); + Game.SaveManager.LoadFiles(AttachedLevel, SaveType.UpgradeData); + CurrentHealth = 0; + } + + m_translocatorSprite.Visible = false; + m_swearBubble.Visible = false; + m_swearBubbleCounter = 0; + + Game.PlayerStats.IsDead = true; + + m_isKilled = true; + AttachedLevel.RunGameOver(); + base.Kill(giveXP); + } + + public void RunDeathAnimation1() + { + if (Game.PlayerStats.IsFemale == true) + SoundManager.PlaySound("Player_Female_Death_01", "Player_Female_Death_02"); + else + SoundManager.PlaySound("Player_Male_Death_01", "Player_Male_Death_02", "Player_Male_Death_03", "Player_Male_Death_04", "Player_Male_Death_05", + "Player_Male_Death_06", "Player_Male_Death_07", "Player_Male_Death_08", "Player_Male_Death_09"); + this.ChangeSprite("PlayerDeath_Character"); + this.PlayAnimation(false); + + if (_objectList[PlayerPart.Wings].Visible == true) + Tween.To(_objectList[PlayerPart.Wings], 0.5f, Tween.EaseNone, "delay", "0.5", "Opacity", "0"); + } + + public void RunGetItemAnimation() + { + //m_levelScreen.PauseScreen(); + //(m_levelScreen.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.GetItem, true); + + if (m_currentLogicSet != null && m_currentLogicSet.IsActive == true) + m_currentLogicSet.Stop(); + AnimationDelay = m_startingAnimationDelay; + this.ChangeSprite("PlayerLevelUp_Character"); + this.PlayAnimation(false); + } + + public void CancelAttack() + { + if (m_currentLogicSet == m_standingAttack3LogicSet || m_currentLogicSet == m_airAttackLS) + m_currentLogicSet.Stop(); + + AnimationDelay = m_startingAnimationDelay; + } + + public void RoomTransitionReset() + { + m_timeStopCast = false; + + m_translocatorSprite.Visible = false; + //m_assassinSpecialActive = false; + //this.Opacity = 1; + //ForceInvincible = false; + } + + public override void Reset() + { + if (m_currentLogicSet.IsActive) + m_currentLogicSet.Stop(); + + State = STATE_IDLE; + m_invincibleCounter = 0; + + // These need to be called again, because some traits modify EV and Logic sets so they need to be re-initialized. + InitializeEV(); + AnimationDelay = m_startingAnimationDelay; + InitializeLogic(); + IsAirAttacking = false; + NumSequentialAttacks = 0; + + m_flightCounter = TotalFlightTime; + m_isFlying = false; + AccelerationYEnabled = true; + this.Position = Vector2.One; + UpdateEquipmentColours(); + + m_assassinSpecialActive = false; + m_wizardSparkleCounter = 0.2f; + DisableGravity = false; + InvincibleToSpikes = false; + ForceInvincible = false; + this.DisableAllWeight = false; + base.Reset(); + } + + public void ResetLevels() + { + //Game.PlayerStats.CurrentLevel = 0; + CurrentHealth = MaxHealth; + CurrentMana = MaxMana; + //Game.PlayerStats.XP = 0; + } + + public void StopDash() + { + m_dashCounter = 0; + } + + // Helper method that will update the player's armor colours automatically based on the equipment he is wearing. + public void UpdateEquipmentColours() + { + if (this.State != STATE_TANOOKI) + { + for (int i = 0; i < Game.PlayerStats.GetEquippedArray.Length; i++) + { + int equippedItem = Game.PlayerStats.GetEquippedArray[i]; + + if (equippedItem != -1) // -1 means no item equipped. + { + EquipmentData equipmentData = Game.EquipmentSystem.GetEquipmentData(i, equippedItem); + Vector3 playerPart = PlayerPart.GetPartIndices(i); + + if (playerPart.X != -1) + this.GetChildAt((int)playerPart.X).TextureColor = equipmentData.FirstColour; + if (playerPart.Y != -1) + this.GetChildAt((int)playerPart.Y).TextureColor = equipmentData.SecondColour; + if (playerPart.Z != -1) + this.GetChildAt((int)playerPart.Z).TextureColor = equipmentData.SecondColour; + + // Special handling to tint the female's boobs. + if (i == EquipmentCategoryType.Chest && playerPart.X != PlayerPart.None) + this.GetChildAt(PlayerPart.Boobs).TextureColor = equipmentData.FirstColour; + } + else // The player is dequipping + { + Vector3 playerPart = PlayerPart.GetPartIndices(i); + + // Set all part pieces to white first. + if (playerPart.X != -1) + this.GetChildAt((int)playerPart.X).TextureColor = Color.White; + if (playerPart.Y != -1) + this.GetChildAt((int)playerPart.Y).TextureColor = Color.White; + if (playerPart.Z != -1) + this.GetChildAt((int)playerPart.Z).TextureColor = Color.White; + + // Special handling to tint the female's boobs. + if (i == EquipmentCategoryType.Chest) + this.GetChildAt(PlayerPart.Boobs).TextureColor = Color.White; + + // Special handling to make the default player's cape and helm red instead of white. + if (i == EquipmentCategoryType.Helm) + this.GetChildAt(PlayerPart.Hair).TextureColor = Color.Red; + else if (i == EquipmentCategoryType.Cape) + { + if (playerPart.X != -1) + this.GetChildAt((int)playerPart.X).TextureColor = Color.Red; + if (playerPart.Y != -1) + this.GetChildAt((int)playerPart.Y).TextureColor = Color.Red; + } + else if (i == EquipmentCategoryType.Sword) + { + if (playerPart.Y != -1) + this.GetChildAt((int)playerPart.Y).TextureColor = new Color(11, 172, 239); // Light blue + } + + Color darkPink = new Color(251, 156, 172); + this.GetChildAt(PlayerPart.Bowtie).TextureColor = darkPink; + } + } + } + } + + public void CastSpell(bool activateSecondary, bool megaSpell = false) + { + byte spellType = Game.PlayerStats.Spell; + + Color textureColor = Color.White; + ProjectileData projData = SpellEV.GetProjData(spellType, this); + + float damageMult = SpellEV.GetDamageMultiplier(spellType); + projData.Damage = (int)(TotalMagicDamage * damageMult); + + int manaCost = (int)(SpellEV.GetManaCost(spellType) * (1 - SkillSystem.GetSkill(SkillType.Mana_Cost_Down).ModifierAmount)); + if (CurrentMana >= manaCost) + { + m_spellCastDelay = 0.5f; + if (AttachedLevel.CurrentRoom is CarnivalShoot1BonusRoom == false && AttachedLevel.CurrentRoom is CarnivalShoot2BonusRoom == false) + { + if (Game.PlayerStats.Traits.X == TraitType.Savant || Game.PlayerStats.Traits.Y == TraitType.Savant) + { + if (Game.PlayerStats.Class != ClassType.Dragon && Game.PlayerStats.Class != ClassType.Traitor) + { + byte[] spellList = ClassType.GetSpellList(Game.PlayerStats.Class); + do + { + Game.PlayerStats.Spell = spellList[CDGMath.RandomInt(0, spellList.Length - 1)]; + } while (Game.PlayerStats.Spell == SpellType.Translocator || Game.PlayerStats.Spell == SpellType.TimeStop || Game.PlayerStats.Spell == SpellType.DamageShield); + AttachedLevel.UpdatePlayerSpellIcon(); + } + } + } + } + + float altX = SpellEV.GetXValue(spellType); + float altY = SpellEV.GetYValue(spellType); + + if (megaSpell == true) + { + manaCost = (int)(manaCost * GameEV.SPELLSWORD_MANACOST_MOD); + projData.Scale *= GameEV.SPELLSWORD_SPELL_SCALE;//2; + projData.Damage = (int)(projData.Damage * GameEV.SPELLSWORD_SPELLDAMAGE_MOD); + } + + if (this.CurrentMana < manaCost) + SoundManager.PlaySound("Error_Spell"); + else if (spellType != SpellType.Translocator && spellType != SpellType.Nuke && m_damageShieldCast == false && manaCost > 0) + m_levelScreen.TextManager.DisplayNumberStringText(-manaCost, "LOC_ID_SKILL_SCREEN_15" /*"mp"*/, Color.SkyBlue, new Vector2(this.X, this.Bounds.Top)); + + if (spellType != SpellType.Bounce && spellType != SpellType.DamageShield) + { + if (Game.PlayerStats.Traits.X == TraitType.Ambilevous || Game.PlayerStats.Traits.Y == TraitType.Ambilevous) + projData.SourceAnchor = new Vector2(projData.SourceAnchor.X * -1, projData.SourceAnchor.Y); + } + + switch (spellType) + { + case (SpellType.Dagger): + case (SpellType.Axe): + case (SpellType.TimeBomb): + case (SpellType.Displacer): + case (SpellType.Close): + case (SpellType.DualBlades): + case (SpellType.DragonFire): + case (SpellType.DragonFireNeo): + if (this.CurrentMana >= manaCost && activateSecondary == false) + { + if (spellType == SpellType.DragonFireNeo) + { + projData.Lifespan = SpellEV.DRAGONFIRENEO_XVal; + projData.WrapProjectile = true; + } + + if (spellType == SpellType.Dagger) + SoundManager.PlaySound("Cast_Dagger"); + else if (spellType == SpellType.Axe) + SoundManager.PlaySound("Cast_Axe"); + else if (spellType == SpellType.DualBlades) + SoundManager.PlaySound("Cast_Chakram"); + else if (spellType == SpellType.Close) + SoundManager.PlaySound("Cast_GiantSword"); + else if (spellType == SpellType.DragonFire || spellType == SpellType.DragonFireNeo) + SoundManager.PlaySound("Enemy_WallTurret_Fire_01", "Enemy_WallTurret_Fire_02", "Enemy_WallTurret_Fire_03", "Enemy_WallTurret_Fire_04"); + + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(projData); + proj.Spell = spellType; + proj.TextureColor = textureColor; + proj.AltY = altY; + proj.AltX = altX; + if (spellType == SpellType.Boomerang && this.Flip == SpriteEffects.FlipHorizontally) + proj.AltX = -altX; + if (spellType == SpellType.Close) + { + proj.LifeSpan = altX; + proj.Opacity = 0; + proj.Y -= 20; + Tween.By(proj, 0.1f, Tween.EaseNone, "Y", "20"); + Tween.To(proj, 0.1f, Tween.EaseNone, "Opacity", "1"); + } + if (spellType == SpellType.DualBlades) + { + projData.Angle = new Vector2(-10, -10); + if (Game.PlayerStats.Traits.X == TraitType.Ambilevous || Game.PlayerStats.Traits.Y == TraitType.Ambilevous) + { + projData.SourceAnchor = new Vector2(-50, -30); + m_levelScreen.ImpactEffectPool.SpellCastEffect(proj.Position, -proj.Rotation, megaSpell); + } + else + { + projData.SourceAnchor = new Vector2(50, -30); + m_levelScreen.ImpactEffectPool.SpellCastEffect(proj.Position, proj.Rotation, megaSpell); + } + + projData.RotationSpeed = -20; + proj = m_levelScreen.ProjectileManager.FireProjectile(projData); + } + if (spellType == SpellType.TimeBomb) + { + proj.ShowIcon = true; + proj.Rotation = 0; + proj.BlinkTime = altX / 1.5f; + proj.LifeSpan = 20; + } + if (spellType == SpellType.Displacer) + { + proj.Rotation = 0; + proj.RunDisplacerEffect(m_levelScreen.CurrentRoom, this); + proj.KillProjectile(); + } + + if (spellType == SpellType.Close) + m_levelScreen.ImpactEffectPool.SpellCastEffect(proj.Position, 90, megaSpell); + else if (Game.PlayerStats.Traits.X == TraitType.Ambilevous || Game.PlayerStats.Traits.Y == TraitType.Ambilevous) + m_levelScreen.ImpactEffectPool.SpellCastEffect(proj.Position, -proj.Rotation, megaSpell); + else + m_levelScreen.ImpactEffectPool.SpellCastEffect(proj.Position, proj.Rotation, megaSpell); + + this.CurrentMana -= manaCost; + } + break; + case (SpellType.Boomerang): + if (this.CurrentMana >= manaCost && activateSecondary == false) + { + SoundManager.PlaySound("Cast_Boomerang"); + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(projData); + proj.Spell = spellType; + proj.IgnoreBoundsCheck = true; + proj.TextureColor = textureColor; + proj.ShowIcon = true; + proj.AltX = altX; + if ((this.Flip == SpriteEffects.FlipHorizontally && Game.PlayerStats.Traits.X != TraitType.Ambilevous && Game.PlayerStats.Traits.Y != TraitType.Ambilevous) + || (this.Flip == SpriteEffects.None && (Game.PlayerStats.Traits.X == TraitType.Ambilevous || Game.PlayerStats.Traits.Y == TraitType.Ambilevous))) + proj.AltX = -altX; + proj.AltY = 0.5f; + + this.CurrentMana -= manaCost; + m_levelScreen.ImpactEffectPool.SpellCastEffect(proj.Position, proj.Rotation, megaSpell); + } + break; + case (SpellType.Bounce): + if (this.CurrentMana >= manaCost && activateSecondary == false) + { + SoundManager.PlaySound("Cast_Dagger"); + for (int i = 0; i < 4; i++) + { + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(projData); + proj.Orientation = MathHelper.ToRadians(projData.Angle.X); + proj.Spell = spellType; + proj.ShowIcon = true; + proj.AltX = altX; + proj.AltY = 0.5f; // 0.1 secs till it can hit you. + switch (i) + { + case (0): projData.SourceAnchor = new Vector2(10, -10); break; + case (1): projData.SourceAnchor = new Vector2(10, 10); break; + case (2): projData.SourceAnchor = new Vector2(-10, 10); break; + } + projData.Angle = new Vector2(projData.Angle.X + 90, projData.Angle.Y + 90); + m_levelScreen.ImpactEffectPool.SpellCastEffect(proj.Position, proj.Rotation, megaSpell); + } + this.CurrentMana -= manaCost; + } + break; + case (SpellType.Nuke): + int numEnemies = this.AttachedLevel.CurrentRoom.ActiveEnemies; + int spellCap = 9;//10;//15;//20; + + if (numEnemies > spellCap) + numEnemies = spellCap; + if (this.CurrentMana >= manaCost && activateSecondary == false && numEnemies > 0) + { + SoundManager.PlaySound("Cast_Crowstorm"); + int projectileDistance = 200; + float angle = (360f / numEnemies); + float startingAngle = 0; + + int spellCapCounter = 0; + foreach (EnemyObj enemy in AttachedLevel.CurrentRoom.EnemyList) + { + if (enemy.NonKillable == false && enemy.IsKilled == false) + { + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(projData); + proj.LifeSpan = 10;//99; + proj.AltX = 0.25f; // The length of time the birds shoot out before they attack. + proj.AltY = 0.05f; // The counter for the crow's smoke. + proj.Orientation = MathHelper.ToRadians(startingAngle); + proj.Spell = spellType; + proj.TurnSpeed = 0.075f;//0.065f;//0.05f; + proj.IgnoreBoundsCheck = true; + proj.Target = enemy; + proj.CollisionTypeTag = GameTypes.CollisionType_WALL; + proj.Position = CDGMath.GetCirclePosition(startingAngle, projectileDistance, this.Position); + m_levelScreen.ImpactEffectPool.SpellCastEffect(proj.Position, proj.Rotation, megaSpell); + startingAngle += angle; + spellCapCounter++; + } + + if (spellCapCounter > spellCap) + break; + } + + foreach (EnemyObj enemy in AttachedLevel.CurrentRoom.TempEnemyList) + { + if (enemy.NonKillable == false && enemy.IsKilled == false) + { + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(projData); + proj.LifeSpan = 99; + proj.AltX = 0.25f; // The length of time the birds shoot out before they attack. + proj.AltY = 0.05f; // The counter for the crow's smoke. + proj.Orientation = MathHelper.ToRadians(startingAngle); + proj.Spell = spellType; + proj.TurnSpeed = 0.05f; + proj.IgnoreBoundsCheck = true; + proj.Target = enemy; + proj.CollisionTypeTag = GameTypes.CollisionType_WALL; + proj.Position = CDGMath.GetCirclePosition(startingAngle, projectileDistance, this.Position); + m_levelScreen.ImpactEffectPool.SpellCastEffect(proj.Position, proj.Rotation, megaSpell); + startingAngle += angle; + spellCapCounter++; + } + + if (spellCapCounter > spellCap) + break; + } + + this.CurrentMana -= manaCost; + m_levelScreen.TextManager.DisplayNumberStringText(-manaCost, "LOC_ID_SKILL_SCREEN_15" /*"mp"*/, Color.SkyBlue, new Vector2(this.X, this.Bounds.Top)); + } + break; + case (SpellType.DamageShield): + if (m_damageShieldCast == true) + { + m_damageShieldCast = false; + m_megaDamageShieldCast = false; + } + else if (this.CurrentMana >= manaCost && activateSecondary == false) + { + m_damageShieldCast = true; + if (megaSpell == true) + m_megaDamageShieldCast = true; + SoundManager.PlaySound("Cast_FireShield"); + int projectileDistance = 200; + for (int i = 0; i < (int)altY; i++) + { + float angle = (360f / altY) * i; + + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(projData); + proj.LifeSpan = altX; + proj.AltX = angle; // AltX and AltY are used as holders to hold the projectiles angle and distance from player respectively. + proj.AltY = projectileDistance; + proj.Spell = spellType; + proj.AccelerationXEnabled = false; + proj.AccelerationYEnabled = false; + proj.IgnoreBoundsCheck = true; + m_levelScreen.ImpactEffectPool.SpellCastEffect(proj.Position, proj.Rotation, megaSpell); + } + this.CurrentMana -= manaCost; + } + break; + case (SpellType.Laser): + if (this.CurrentMana >= manaCost && activateSecondary == false) + { + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(projData); + proj.AltX = 1; + proj.AltY = 0.5f; + proj.Opacity = 0f; + proj.X = AttachedLevel.CurrentRoom.X; + proj.Y = this.Y; + proj.Scale = new Vector2((float)(AttachedLevel.CurrentRoom.Width / proj.Width), 0); + proj.IgnoreBoundsCheck = true; + proj.Spell = spellType; + this.CurrentMana -= manaCost; + } + break; + case (SpellType.TimeStop): + if (m_timeStopCast == true) + { + AttachedLevel.StopTimeStop(); + m_timeStopCast = false; + } + else + { + if (this.CurrentMana >= manaCost && activateSecondary == false) + { + this.CurrentMana -= manaCost; + AttachedLevel.CastTimeStop(0); + m_timeStopCast = true; + } + } + break; + case (SpellType.Translocator): + if (m_translocatorSprite.Visible == false && this.CurrentMana >= manaCost) + { + this.CurrentMana -= manaCost; + m_translocatorSprite.ChangeSprite(this.SpriteName); + m_translocatorSprite.GoToFrame(this.CurrentFrame); + m_translocatorSprite.Visible = true; + m_translocatorSprite.Position = this.Position; + m_translocatorSprite.Flip = this.Flip; + m_translocatorSprite.TextureColor = Color.Black; + m_translocatorSprite.Scale = Vector2.Zero; + + for (int i = 0; i < this.NumChildren; i++) + { + (m_translocatorSprite.GetChildAt(i) as SpriteObj).ChangeSprite((_objectList[i] as SpriteObj).SpriteName); + m_translocatorSprite.GetChildAt(i).Visible = _objectList[i].Visible; + } + + m_translocatorSprite.GetChildAt(PlayerPart.Light).Visible = false; + if (Game.PlayerStats.Class == ClassType.SpellSword || Game.PlayerStats.Class == ClassType.SpellSword2) + { + m_translocatorSprite.GetChildAt(PlayerPart.Sword1).Visible = false; + m_translocatorSprite.GetChildAt(PlayerPart.Sword2).Visible = false; + } + m_levelScreen.TextManager.DisplayNumberStringText(-manaCost, "LOC_ID_SKILL_SCREEN_15" /*"mp"*/, Color.SkyBlue, new Vector2(this.X, this.Bounds.Top)); + + AttachedLevel.ImpactEffectPool.StartInverseEmit(m_translocatorSprite.Position); + Tween.To(m_translocatorSprite, 0.4f, Tweener.Ease.Linear.EaseNone, "ScaleX", this.ScaleX.ToString(), "ScaleY", this.ScaleY.ToString()); + SoundManager.PlaySound("mfqt_teleport_out"); + } + else if (m_translocatorSprite.Visible == true && m_translocatorSprite.Scale == this.Scale) + { + SoundManager.PlaySound("mfqt_teleport_in"); + //AttachedLevel.ImpactEffectPool.StartTranslocateEmit(this.Position); + this.Translocate(m_translocatorSprite.Position); + m_translocatorSprite.Visible = false; + } + break; + case (SpellType.RapidDagger): + if (this.CurrentMana >= manaCost) + { + this.CurrentMana -= manaCost; + ThrowDaggerProjectiles(); + } + break; + } + + projData.Dispose(); + } + + public void Translocate(Vector2 position) + { + this.DisableAllWeight = true; + Tween.To(this, 0.08f, Tweener.Ease.Linear.EaseNone, "ScaleX", "3", "ScaleY", "0"); + Tween.To(this, 0, Tweener.Ease.Linear.EaseNone, "delay", "0.1", "X", position.X.ToString(), "Y", position.Y.ToString()); + Tween.AddEndHandlerToLastTween(this, "ResetTranslocution"); + //this.Position = m_translocatorSprite.Position; + this.AttachedLevel.UpdateCamera(); + } + + // A hack method specifically to make quantum translocator work for Alexander neo boss. + public void OverrideInternalScale(Vector2 internalScale) + { + m_internalScale = internalScale; + } + + public void ResetTranslocution() + { + this.DisableAllWeight = false; + this.Scale = m_internalScale; + } + + public void ConvertHPtoMP() + { + if (MaxHealth > 1) + { + int baseHealthLost = (int)((MaxHealth - Game.PlayerStats.LichHealth) * GameEV.LICH_HEALTH_CONVERSION_PERCENT); + int lichHealthLost = (int)(Game.PlayerStats.LichHealth * GameEV.LICH_HEALTH_CONVERSION_PERCENT); + + int maxMana = (int)((BaseMana + + GetEquipmentMana() + (Game.PlayerStats.BonusMana * GameEV.ITEM_STAT_MAXMP_AMOUNT) + + SkillSystem.GetSkill(SkillType.Mana_Up).ModifierAmount + + SkillSystem.GetSkill(SkillType.Mana_Up_Final).ModifierAmount) * GameEV.LICH_MAX_MP_OFF_BASE); + + if (MaxMana + baseHealthLost + lichHealthLost < maxMana) + { + SoundManager.PlaySound("Lich_Swap"); + + Game.PlayerStats.LichHealthMod *= GameEV.LICH_HEALTH_CONVERSION_PERCENT; + Game.PlayerStats.LichHealth -= lichHealthLost; + Game.PlayerStats.LichMana += baseHealthLost + lichHealthLost; + this.CurrentMana += baseHealthLost + lichHealthLost; + if (CurrentHealth > this.MaxHealth) + this.CurrentHealth = this.MaxHealth; + m_levelScreen.UpdatePlayerHUD(); + + m_levelScreen.TextManager.DisplayNumberStringText((baseHealthLost + lichHealthLost), "LOC_ID_PLAYER_OBJ_2" /*"max mp"*/, Color.RoyalBlue, new Vector2(this.X, this.Bounds.Top - 30)); + m_levelScreen.TextManager.DisplayNumberStringText(-(baseHealthLost + lichHealthLost), "LOC_ID_PLAYER_OBJ_3" /*"max hp"*/, Color.Red, new Vector2(this.X, this.Bounds.Top - 60)); + } + else + { + SoundManager.PlaySound("Error_Spell"); + m_levelScreen.TextManager.DisplayStringText("LOC_ID_PLAYER_OBJ_4" /*"Max MP Converted. Need higher level."*/, Color.RoyalBlue, new Vector2(this.X, this.Bounds.Top - 30)); + } + } + } + + public void ActivateAssassinAbility() + { + if (CurrentMana >= GameEV.ASSASSIN_ACTIVE_INITIAL_COST) + { + SoundManager.PlaySound("Assassin_Stealth_Enter"); + CurrentMana -= GameEV.ASSASSIN_ACTIVE_INITIAL_COST; + Tween.To(this, 0.2f, Tween.EaseNone, "Opacity", "0.05"); + m_assassinSpecialActive = true; + ForceInvincible = true; + m_levelScreen.ImpactEffectPool.AssassinCastEffect(this.Position); + } + } + + public void DisableAssassinAbility() + { + //this.Opacity = 1; + Tween.To(this, 0.2f, Tween.EaseNone, "Opacity", "1"); + m_assassinSpecialActive = false; + ForceInvincible = false; + } + + public void SwapSpells() + { + //if (AttachedLevel.CurrentRoom is CarnivalShoot1BonusRoom == false && AttachedLevel.CurrentRoom is CarnivalShoot2BonusRoom == false) + { + SoundManager.PlaySound("Spell_Switch"); + m_wizardSpellList[0] = (byte)Game.PlayerStats.WizardSpellList.X; + m_wizardSpellList[1] = (byte)Game.PlayerStats.WizardSpellList.Y; + m_wizardSpellList[2] = (byte)Game.PlayerStats.WizardSpellList.Z; + + int spellIndex = m_wizardSpellList.IndexOf(Game.PlayerStats.Spell); + spellIndex++; + if (spellIndex >= m_wizardSpellList.Count) + spellIndex = 0; + Game.PlayerStats.Spell = m_wizardSpellList[spellIndex]; + m_levelScreen.UpdatePlayerSpellIcon(); + + if (m_damageShieldCast == true) + { + m_damageShieldCast = false; + m_megaDamageShieldCast = false; + } + + if (m_timeStopCast == true) + { + AttachedLevel.StopTimeStop(); + m_timeStopCast = false; + } + } + } + + public void NinjaTeleport() + { + if (this.CurrentMana >= GameEV.NINJA_TELEPORT_COST && m_ninjaTeleportDelay <= 0) + { + this.CurrentMana -= GameEV.NINJA_TELEPORT_COST; + m_ninjaTeleportDelay = 0.5f; + + m_levelScreen.ImpactEffectPool.NinjaDisappearEffect(this); + + int teleportDistance = GameEV.NINJA_TELEPORT_DISTANCE; + int distance = int.MaxValue; + TerrainObj closestWall = CalculateClosestWall(out distance); + + if (closestWall != null) + { + if (distance < teleportDistance) + { + //Tween.To(closestWall, 10, Tween.EaseNone, "Y", "-1000"); + if (this.Flip == SpriteEffects.None) + { + if (closestWall.Rotation == 0) + this.X += distance - this.TerrainBounds.Width / 2f; + else + this.X += distance - this.Width / 2f; + } + else + { + if (closestWall.Rotation == 0) + this.X -= distance - this.TerrainBounds.Width / 2f; + else + this.X -= distance - this.Width / 2f; + } + } + else + { + if (this.Flip == SpriteEffects.FlipHorizontally) + this.X -= teleportDistance; + else + this.X += teleportDistance; + } + } + else + { + if (this.Flip == SpriteEffects.FlipHorizontally) + this.X -= teleportDistance; + else + this.X += teleportDistance; + + if (this.X > m_levelScreen.CurrentRoom.Bounds.Right) + this.X = m_levelScreen.CurrentRoom.Bounds.Right - 5; + else if (this.X < m_levelScreen.CurrentRoom.X) + this.X = m_levelScreen.CurrentRoom.X + 5; + } + SoundManager.PlaySound("Ninja_Teleport"); + m_levelScreen.ImpactEffectPool.NinjaAppearEffect(this); + m_levelScreen.UpdateCamera(); + } + } + + public TerrainObj CalculateClosestWall(out int dist) + { + int closestDistance = int.MaxValue; + TerrainObj closestObj = null; + + Vector2 collisionPt = Vector2.Zero; + RoomObj room = m_levelScreen.CurrentRoom; + + foreach (TerrainObj terrain in room.TerrainObjList) + { + if (terrain.CollidesBottom == true || terrain.CollidesLeft == true || terrain.CollidesRight == true) + { + collisionPt = Vector2.Zero; + // Only collide with terrain that the displacer would collide with. + float distance = float.MaxValue; + if (this.Flip == SpriteEffects.None) + { + if (terrain.X > this.X && (terrain.Bounds.Top + 5 < this.TerrainBounds.Bottom && terrain.Bounds.Bottom > this.TerrainBounds.Top)) + { + //if (terrain.Rotation == -45) + if (terrain.Rotation < 0) // ROTCHECK + collisionPt = CollisionMath.LineToLineIntersect(this.Position, new Vector2(this.X + 6600, this.Y), + CollisionMath.UpperLeftCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero), CollisionMath.UpperRightCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero)); + //else if (terrain.Rotation == 45) + else if (terrain.Rotation > 0) // ROTCHECK + collisionPt = CollisionMath.LineToLineIntersect(this.Position, new Vector2(this.X + 6600, this.Y), + CollisionMath.LowerLeftCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero), CollisionMath.UpperLeftCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero)); + + if (collisionPt != Vector2.Zero) + distance = collisionPt.X - this.X; + else + distance = terrain.Bounds.Left - this.TerrainBounds.Right; + } + } + else + { + if (terrain.X < this.X && (terrain.Bounds.Top + 5 < this.TerrainBounds.Bottom && terrain.Bounds.Bottom > this.TerrainBounds.Top)) + { + //if (terrain.Rotation == -45) + if (terrain.Rotation < 0) // ROTCHECK + collisionPt = CollisionMath.LineToLineIntersect(new Vector2(this.X - 6600, this.Y), this.Position, + CollisionMath.UpperRightCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero), CollisionMath.LowerRightCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero)); + //else if (terrain.Rotation == 45) + else if (terrain.Rotation > 0) // ROTCHECK + collisionPt = CollisionMath.LineToLineIntersect(new Vector2(this.X - 6600, this.Y), this.Position, + CollisionMath.UpperLeftCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero), CollisionMath.UpperRightCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero)); + + if (collisionPt != Vector2.Zero) + distance = this.X - collisionPt.X; + else + distance = this.TerrainBounds.Left - terrain.Bounds.Right; + } + } + + if (distance < closestDistance) + { + closestDistance = (int)distance; + closestObj = terrain; + } + } + } + + dist = closestDistance; + return closestObj; + } + + public void ActivateTanooki() + { + if (CurrentMana >= GameEV.TANOOKI_ACTIVE_INITIAL_COST) + { + CurrentMana -= GameEV.TANOOKI_ACTIVE_INITIAL_COST; + m_levelScreen.ImpactEffectPool.DisplayTanookiEffect(this); + this.TextureColor = Color.White; + _objectList[0].TextureColor = Color.White; + this.State = STATE_TANOOKI; + } + } + + public void DeactivateTanooki() + { + m_levelScreen.ImpactEffectPool.DisplayTanookiEffect(this); + this.State = STATE_IDLE; + } + + public void CastFuhRohDah() + { + if (CurrentMana >= GameEV.BARBARIAN_SHOUT_INITIAL_COST) + { + CurrentMana -= GameEV.BARBARIAN_SHOUT_INITIAL_COST; + ProjectileData spellData = new ProjectileData(this) + { + SpriteName = "SpellShout_Sprite", + IsWeighted = false, + Lifespan = 2, + CollidesWith1Ways = false, + CollidesWithTerrain = false, + DestroysWithEnemy = false, + DestroysWithTerrain = false, + Damage = 0, + Scale = Vector2.One, + }; + + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(spellData); + proj.Opacity = 0; + proj.CollisionTypeTag = GameTypes.CollisionType_PLAYER; + proj.Spell = SpellType.Shout; + proj.IgnoreBoundsCheck = true; + + Tween.To(proj, 0.2f, Tween.EaseNone, "ScaleX", "100", "ScaleY", "50"); + Tween.AddEndHandlerToLastTween(proj, "KillProjectile"); + SoundManager.PlaySound("Cast_FasRoDus"); + + m_levelScreen.ImpactEffectPool.DisplayFusRoDahText(new Vector2(this.X, this.Bounds.Top)); + m_levelScreen.ShoutMagnitude = 0; + Tween.To(m_levelScreen, 1, Tween.EaseNone, "ShoutMagnitude", "3"); + } + } + + private void CastCloseShield() + { + ProjectileData projData = new ProjectileData(this) + { + SpriteName = "SpellClose_Sprite", + //Angle = new Vector2(90, 90), + //SourceAnchor = new Vector2(120, -60),//(75,-200),//(50, 0), + Speed = new Vector2(0, 0),//(450,450),//(1000, 1000), + IsWeighted = false, + RotationSpeed = 0f, + DestroysWithEnemy = false, + DestroysWithTerrain = false, + CollidesWithTerrain = false, + Scale = new Vector2(m_Spell_Close_Scale, m_Spell_Close_Scale), + Damage = Damage, + Lifespan = m_Spell_Close_Lifespan, + LockPosition = true, + }; + + projData.Damage = (int)(TotalMagicDamage * PlayerEV.TRAITOR_CLOSE_DAMAGEMOD); + + SoundManager.PlaySound("Cast_GiantSword"); + m_levelScreen.ImpactEffectPool.LastBossSpellCastEffect(this, 90, true); + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(projData); + proj.TextureColor = Color.CadetBlue; + + projData.Dispose(); + } + + private void ThrowAxeProjectiles() + { + m_axeProjData.AngleOffset = 0; + m_axeProjData.Damage = (int)(TotalMagicDamage * PlayerEV.TRAITOR_AXE_DAMAGEMOD); + + Tween.RunFunction(0, this, "CastAxe"); + Tween.RunFunction(0.15f, this, "CastAxe"); + Tween.RunFunction(0.3f, this, "CastAxe"); + Tween.RunFunction(0.45f, this, "CastAxe"); + Tween.RunFunction(0.6f, this, "CastAxe"); + } + + public void CastAxe() + { + m_axeProjData.AngleOffset = CDGMath.RandomInt(-70, 70); + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(m_axeProjData); + proj.TextureColor = Color.CadetBlue; + SoundManager.PlaySound("Cast_Axe"); + m_levelScreen.ImpactEffectPool.LastBossSpellCastEffect(this, 45, true); + } + + private void ThrowDaggerProjectiles() + { + m_rapidDaggerProjData.AngleOffset = 0; + m_rapidDaggerProjData.Damage = (int)(TotalMagicDamage * SpellEV.GetDamageMultiplier(SpellType.RapidDagger)); + + Tween.RunFunction(0, this, "CastDaggers", false); + Tween.RunFunction(0.05f, this, "CastDaggers", true); + Tween.RunFunction(0.1f, this, "CastDaggers", true); + Tween.RunFunction(0.15f, this, "CastDaggers", true); + Tween.RunFunction(0.2f, this, "CastDaggers", true); + } + + public void CastDaggers(bool randomize) + { + if (randomize == true) + m_rapidDaggerProjData.AngleOffset = CDGMath.RandomInt(-8, 8); + ProjectileObj proj = m_levelScreen.ProjectileManager.FireProjectile(m_rapidDaggerProjData); + proj.TextureColor = Color.CadetBlue; + SoundManager.PlaySound("Cast_Dagger"); + m_levelScreen.ImpactEffectPool.LastBossSpellCastEffect(this, 0, true); + } + + public void StopAllSpells() + { + if (State == STATE_TANOOKI) + DeactivateTanooki(); + + if (m_damageShieldCast == true) + { + m_damageShieldCast = false; + m_megaDamageShieldCast = false; + } + + if (m_timeStopCast == true) + { + AttachedLevel.StopTimeStop(); + m_timeStopCast = false; + } + + if (m_assassinSpecialActive == true) + DisableAssassinAbility(); + + m_lightOn = false; + m_translocatorSprite.Visible = false; + + if (State == STATE_DRAGON) + { + State = STATE_JUMPING; + this.DisableGravity = false; + m_isFlying = false; + } + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + if (m_currentLogicSet.IsActive) + m_currentLogicSet.Stop(); + m_currentLogicSet = null; + + m_standingAttack3LogicSet.Dispose(); + m_standingAttack3LogicSet = null; + m_airAttackLS.Dispose(); + m_airAttackLS = null; + + m_debugInputMap.Dispose(); + m_debugInputMap = null; + + m_playerHead = null; + m_playerLegs = null; + + m_walkDownSound.Dispose(); + m_walkDownSound = null; + m_walkUpSound.Dispose(); + m_walkUpSound = null; + + m_walkDownSoundLow.Dispose(); + m_walkDownSoundLow = null; + m_walkUpSoundLow.Dispose(); + m_walkUpSoundLow = null; + + m_walkDownSoundHigh.Dispose(); + m_walkDownSoundHigh = null; + m_walkUpSoundHigh.Dispose(); + m_walkUpSoundHigh = null; + + if (m_externalLS != null) + m_externalLS.Dispose(); + m_externalLS = null; + + m_lastTouchedTeleporter = null; + + m_flightDurationText.Dispose(); + m_flightDurationText = null; + + m_game = null; + + m_translocatorSprite.Dispose(); + m_translocatorSprite = null; + + m_swearBubble.Dispose(); + m_swearBubble = null; + + m_flipTween = null; + + m_wizardSpellList.Clear(); + m_wizardSpellList = null; + + m_closestGround = null; + + m_rapidDaggerProjData.Dispose(); + m_axeProjData.Dispose(); + + base.Dispose(); + } + } + + public override void Draw(Camera2D camera) + { + m_swearBubble.Scale = new Vector2(this.ScaleX * 1.2f, this.ScaleY * 1.2f); + m_swearBubble.Position = new Vector2(this.X - (30 * this.ScaleX), this.Y - (35 * this.ScaleX)); + m_swearBubble.Draw(camera); + + m_translocatorSprite.Draw(camera); + base.Draw(camera); + + if (IsFlying == true && State != STATE_DRAGON) + { + m_flightDurationText.Text = String.Format("{0:F1}", m_flightCounter); + m_flightDurationText.Position = new Vector2(this.X, this.TerrainBounds.Top - 70); + m_flightDurationText.Draw(camera); + } + + //if (this.Opacity == 1) + { + camera.End(); + // This is to maintain the player's helmet tint. + Game.ColourSwapShader.Parameters["desiredTint"].SetValue(m_playerHead.TextureColor.ToVector4()); + // This is the Tint Removal effect, that removes the tint from his face. + if (Game.PlayerStats.Class == ClassType.Lich || Game.PlayerStats.Class == ClassType.Lich2) + { + Game.ColourSwapShader.Parameters["Opacity"].SetValue(this.Opacity); + Game.ColourSwapShader.Parameters["ColourSwappedOut1"].SetValue(m_skinColour1.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn1"].SetValue(m_lichColour1.ToVector4()); + + Game.ColourSwapShader.Parameters["ColourSwappedOut2"].SetValue(m_skinColour2.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn2"].SetValue(m_lichColour2.ToVector4()); + } + else if (Game.PlayerStats.Class == ClassType.Assassin || Game.PlayerStats.Class == ClassType.Assassin2) + { + Game.ColourSwapShader.Parameters["Opacity"].SetValue(this.Opacity); + Game.ColourSwapShader.Parameters["ColourSwappedOut1"].SetValue(m_skinColour1.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn1"].SetValue(Color.Black.ToVector4()); + + Game.ColourSwapShader.Parameters["ColourSwappedOut2"].SetValue(m_skinColour2.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn2"].SetValue(Color.Black.ToVector4()); + } + else + { + Game.ColourSwapShader.Parameters["Opacity"].SetValue(this.Opacity); + Game.ColourSwapShader.Parameters["ColourSwappedOut1"].SetValue(m_skinColour1.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn1"].SetValue(m_skinColour1.ToVector4()); + + Game.ColourSwapShader.Parameters["ColourSwappedOut2"].SetValue(m_skinColour2.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn2"].SetValue(m_skinColour2.ToVector4()); + } + + // All camera calls changed to deferred mode. + camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, Game.ColourSwapShader, camera.GetTransformation()); + m_playerHead.Draw(camera); + camera.End(); + + camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, camera.GetTransformation()); + if (Game.PlayerStats.IsFemale == true) + _objectList[PlayerPart.Bowtie].Draw(camera); + _objectList[PlayerPart.Glasses].Draw(camera); + _objectList[PlayerPart.Extra].Draw(camera); + } + } + + public void FadeSword() + { + //SoundManager.PlaySound("Player_Attack_Sword_Spell_01", "Player_Attack_Sword_Spell_02", "Player_Attack_Sword_Spell_03"); + SpriteObj sword = _objectList[PlayerPart.Sword1] as SpriteObj; + SpriteObj sword2 = _objectList[PlayerPart.Sword2] as SpriteObj; + + Tween.StopAllContaining(sword, false); + Tween.StopAllContaining(sword2, false); + + sword.Opacity = 0f; + sword2.Opacity = 0f; + + sword.TextureColor = Color.White; + Tween.To(sword, 0.1f, Tween.EaseNone, "Opacity", "1"); + sword.Opacity = 1; + Tween.To(sword, 0.1f, Tween.EaseNone, "delay", "0.2", "Opacity", "0"); + sword.Opacity = 0f; + + sword2.TextureColor = Color.White; + Tween.To(sword2, 0.1f, Tween.EaseNone, "Opacity", "1"); + sword2.Opacity = 1; + Tween.To(sword2, 0.1f, Tween.EaseNone, "delay", "0.2", "Opacity", "0"); + sword2.Opacity = 0f; + } + + public void ChangePartColour(int playerPart, Color colour) + { + if (playerPart == PlayerPart.Cape || playerPart == PlayerPart.Neck) + { + GetPlayerPart(PlayerPart.Neck).TextureColor = colour; + GetPlayerPart(PlayerPart.Cape).TextureColor = colour; + } + else + GetPlayerPart(playerPart).TextureColor = colour; + } + + public SpriteObj GetPlayerPart(int playerPart) + { + return _objectList[playerPart] as SpriteObj; + } + + private Rectangle GroundCollisionRect + { + get { return new Rectangle((int)this.Bounds.X, (int)this.Bounds.Y, this.Bounds.Width, this.Bounds.Height + StepUp); } + } + + private Rectangle RotatedGroundCollisionRect + { + get { return new Rectangle((int)this.Bounds.X, (int)this.Bounds.Y, this.Bounds.Width, this.Bounds.Height + 40); } + } + + public void AttachLevel(ProceduralLevelScreen level) + { + m_levelScreen = level; + } + + public PlayerIndex PlayerIndex + { + get { return m_playerIndex; } + } + + public ProceduralLevelScreen AttachedLevel + { + get { return m_levelScreen; } + } + + public int Damage + { + get + { + int damageDealt = 0; + damageDealt = (int)((RandomDamage + SkillSystem.GetSkill(SkillType.Attack_Up).ModifierAmount + SkillSystem.GetSkill(SkillType.Damage_Up_Final).ModifierAmount) * ClassDamageGivenMultiplier); + //+ Game.TraitSystem.GetModifierAmount(m_traitArray, TraitType.Attack_Damage_Flat)) * ClassDamageGivenMultiplier); + if (IsAirAttacking) + damageDealt = (int)(damageDealt * TotalAirAttackDamageMod); + + if (damageDealt < 1) damageDealt = 1; + + return damageDealt; + } + } + + public float TotalAirAttackDamageMod + { + get + { + float skillModAmount = SkillSystem.GetSkill(SkillType.Down_Strike_Up).ModifierAmount * NumAirBounces; + float airAttackMod = AirAttackDamageMod + skillModAmount; + if (airAttackMod > 1) + airAttackMod = 1; + return airAttackMod; + } + } + + public int TotalMagicDamage + { + get + { + int intelligence = (int)((BaseMagicDamage + SkillSystem.GetSkill(SkillType.Magic_Damage_Up).ModifierAmount + GetEquipmentMagicDamage() + (Game.PlayerStats.BonusMagic * GameEV.ITEM_STAT_MAGIC_AMOUNT)) * ClassMagicDamageGivenMultiplier); + if (intelligence < 1) + intelligence = 1; + return intelligence; + } + } + + public int InvulnDamage + { + get + { + return (int)(RandomDamage * (1 + SkillSystem.GetSkill(SkillType.Invuln_Attack_Up).ModifierAmount) + SkillSystem.GetSkill(SkillType.Attack_Up).ModifierAmount + + SkillSystem.GetSkill(SkillType.Damage_Up_Final).ModifierAmount); + } + } + + public Vector2 EnemyKnockBack + { + get + { + if (m_currentLogicSet == m_standingAttack3LogicSet) + return StrongEnemyKnockBack; + return m_enemyKnockBack; + } + set { m_enemyKnockBack = value; } + } + + + public int RandomDamage + { + get + { + return CDGMath.RandomInt(MinDamage + GetEquipmentDamage(), MaxDamage + GetEquipmentDamage()) + + (Game.PlayerStats.BonusStrength * GameEV.ITEM_STAT_STRENGTH_AMOUNT) + + (DamageGainPerLevel * Game.PlayerStats.CurrentLevel); + } + } + + public float MaxMana + { + get + { + // if dextrocardic, return Max health instead of max mana. + if (Game.PlayerStats.Traits.X == TraitType.Dextrocardia || Game.PlayerStats.Traits.Y == TraitType.Dextrocardia) + { + int maxMana = (int)Math.Round(((BaseHealth + GetEquipmentHealth() + + (HealthGainPerLevel * Game.PlayerStats.CurrentLevel) + + (Game.PlayerStats.BonusHealth * GameEV.ITEM_STAT_MAXHP_AMOUNT) + + SkillSystem.GetSkill(SkillType.Health_Up).ModifierAmount + + SkillSystem.GetSkill(SkillType.Health_Up_Final).ModifierAmount) * ClassTotalHPMultiplier * Game.PlayerStats.LichHealthMod), MidpointRounding.AwayFromZero) + Game.PlayerStats.LichHealth; // Lich health is separate from modifiers. + + if (maxMana < 1) + maxMana = 1; + return maxMana; + } + else + { + int maxMana = (int)((BaseMana + + GetEquipmentMana() + + (ManaGainPerLevel * Game.PlayerStats.CurrentLevel) + + (Game.PlayerStats.BonusMana * GameEV.ITEM_STAT_MAXMP_AMOUNT) + + SkillSystem.GetSkill(SkillType.Mana_Up).ModifierAmount + + SkillSystem.GetSkill(SkillType.Mana_Up_Final).ModifierAmount) * ClassTotalMPMultiplier) + Game.PlayerStats.LichMana; // Lich mana is separate from modifiers. + + if (maxMana < 1) + maxMana = 1; + return maxMana; + } + } + } + + public override int MaxHealth + { + get + { + // if dextrocardic, return max mana instead of max health. + if (Game.PlayerStats.Traits.X == TraitType.Dextrocardia || Game.PlayerStats.Traits.Y == TraitType.Dextrocardia) + { + int maxHealth = (int)((BaseMana + + GetEquipmentMana() + + (ManaGainPerLevel * Game.PlayerStats.CurrentLevel) + + (Game.PlayerStats.BonusMana * GameEV.ITEM_STAT_MAXMP_AMOUNT) + + SkillSystem.GetSkill(SkillType.Mana_Up).ModifierAmount + + SkillSystem.GetSkill(SkillType.Mana_Up_Final).ModifierAmount) * ClassTotalMPMultiplier) + Game.PlayerStats.LichMana; // Lich mana is separate from modifiers. + + if (maxHealth < 1) + maxHealth = 1; + return maxHealth; + } + else + { + int maxHealth = (int)Math.Round(((BaseHealth + GetEquipmentHealth() + + (HealthGainPerLevel * Game.PlayerStats.CurrentLevel) + + (Game.PlayerStats.BonusHealth * GameEV.ITEM_STAT_MAXHP_AMOUNT) + + SkillSystem.GetSkill(SkillType.Health_Up).ModifierAmount + + SkillSystem.GetSkill(SkillType.Health_Up_Final).ModifierAmount) * ClassTotalHPMultiplier * Game.PlayerStats.LichHealthMod), MidpointRounding.AwayFromZero) + Game.PlayerStats.LichHealth; // Lich health is separate from modifiers. + + if (maxHealth < 1) + maxHealth = 1; + return maxHealth; + } + } + } + + public float InvincibilityTime + { + get + { + return BaseInvincibilityTime + SkillSystem.GetSkill(SkillType.Invuln_Time_Up).ModifierAmount; + // + Game.TraitSystem.GetModifierAmount(m_traitArray, TraitType.Invuln_Flat_Up); + } + } + + public override Rectangle Bounds + { + get + { + //return new Rectangle((int)(this.X - 37), (int)(this.Y - 56), 73, 93); + //return new Rectangle((int)((this.X - 37 * ScaleX)), (int)((this.Y - 56 * ScaleY)), (int)(73 * ScaleX),(int)(93 * ScaleY)); + return this.TerrainBounds; + } + } + + public int GetEquipmentDamage() + { + int bonusDamage = 0; + + int equipmentCategoryIndex = 0; + foreach (sbyte equippedItemIndex in Game.PlayerStats.GetEquippedArray) + { + if (equippedItemIndex > -1) + { + bonusDamage += Game.EquipmentSystem.GetEquipmentData(equipmentCategoryIndex, equippedItemIndex).BonusDamage; + } + equipmentCategoryIndex++; + } + return bonusDamage; + } + + public int GetEquipmentMana() + { + int bonusMana = 0; + + int equipmentCategoryIndex = 0; + foreach (sbyte equippedItemIndex in Game.PlayerStats.GetEquippedArray) + { + if (equippedItemIndex > -1) + { + bonusMana += Game.EquipmentSystem.GetEquipmentData(equipmentCategoryIndex, equippedItemIndex).BonusMana; + } + equipmentCategoryIndex++; + } + return bonusMana; + } + + public int GetEquipmentHealth() + { + int bonushealth = 0; + + int equipmentCategoryIndex = 0; + foreach (sbyte equippedItemIndex in Game.PlayerStats.GetEquippedArray) + { + if (equippedItemIndex > -1) + { + bonushealth += Game.EquipmentSystem.GetEquipmentData(equipmentCategoryIndex, equippedItemIndex).BonusHealth; + } + equipmentCategoryIndex++; + } + return bonushealth; + } + + public int GetEquipmentArmor() + { + int bonusArmor = 0; + + int equipmentCategoryIndex = 0; + foreach (sbyte equippedItemIndex in Game.PlayerStats.GetEquippedArray) + { + if (equippedItemIndex > -1) + { + bonusArmor += Game.EquipmentSystem.GetEquipmentData(equipmentCategoryIndex, equippedItemIndex).BonusArmor; + } + equipmentCategoryIndex++; + } + return bonusArmor; + } + + public int GetEquipmentWeight() + { + int totalWeight = 0; + + int equipmentCategoryIndex = 0; + foreach (sbyte equippedItemIndex in Game.PlayerStats.GetEquippedArray) + { + if (equippedItemIndex > -1) + { + totalWeight += Game.EquipmentSystem.GetEquipmentData(equipmentCategoryIndex, equippedItemIndex).Weight; + } + equipmentCategoryIndex++; + } + return totalWeight; + } + + public int GetEquipmentMagicDamage() + { + int totalMagic = 0; + + int equipmentCategoryIndex = 0; + foreach (sbyte equippedItemIndex in Game.PlayerStats.GetEquippedArray) + { + if (equippedItemIndex > -1) + { + totalMagic += Game.EquipmentSystem.GetEquipmentData(equipmentCategoryIndex, equippedItemIndex).BonusMagic; + } + equipmentCategoryIndex++; + } + return totalMagic; + } + + public float GetEquipmentSecondaryAttrib(int secondaryAttribType) + { + float value = 0; + int equipmentCategoryIndex = 0; + + foreach (sbyte equipmentItemIndex in Game.PlayerStats.GetEquippedArray) + { + if (equipmentItemIndex > -1) + { + EquipmentData data = Game.EquipmentSystem.GetEquipmentData(equipmentCategoryIndex, equipmentItemIndex); + foreach (Vector2 secondaryAttrib in data.SecondaryAttribute) + { + if ((int)secondaryAttrib.X == secondaryAttribType) + value += secondaryAttrib.Y; + } + } + equipmentCategoryIndex++; + } + return value; + } + + public int CurrentWeight + { + get { return GetEquipmentWeight(); } + } + + public int MaxWeight + { + get + { + return (int)(BaseWeight + SkillSystem.GetSkill(SkillType.Equip_Up).ModifierAmount + SkillSystem.GetSkill(SkillType.Equip_Up_Final).ModifierAmount) + + (Game.PlayerStats.BonusWeight * GameEV.ITEM_STAT_WEIGHT_AMOUNT); + } + } + + public bool CanFly + { + get + { + if (Game.PlayerStats.Class == ClassType.Dragon) + return true; + return TotalFlightTime > 0; + } + } + + public bool CanAirDash + { + get { return TotalAirDashes > 0; } + } + + public bool CanBlock + { + get + { + if (Game.PlayerStats.Class == ClassType.Knight2) + return true; + return false; + } + } + + public bool CanRun + { + get + { + return true; + //if (LevelEV.UNLOCK_ALL_TRAIT_ABILITIES == true) return true; + //return SkillSystem.GetSkill(SkillType.Run).ModifierAmount > 0; + } + } + + public bool CanAirAttackDownward + { + get + { + return true; + } + } + + public bool IsJumping + { + get { return m_isJumping; } + } + + public byte NumSequentialAttacks // Used to calculate the number of attacks the player has made in succession before giving him more mana. + { + get { return m_numSequentialAttacks; } + set + { + m_numSequentialAttacks = value; + // if (m_numSequentialAttacks >= AttacksNeededForMana) + // { + // m_numSequentialAttacks = 0; + // if (ManaGain > 0) + // { + // CurrentMana += ManaGain; + // //m_levelScreen.TextManager.DisplayManaText((int)ManaGain, this.Position); + // m_levelScreen.TextManager.DisplayNumberStringText((int)ManaGain, "LOC_ID_SKILL_SCREEN_15" /*"mp"*/, Color.RoyalBlue, new Vector2(this.X, this.Bounds.Top - 30)); + // } + // } + } + } + + public byte AttacksNeededForMana + { + get { return m_attacksNeededForMana; } + set { m_attacksNeededForMana = value; } + } + + public float ManaGain + { + get + { + //int classManaGain = 0; + //if (Game.PlayerStats.Class == ClassType.Wizard || Game.PlayerStats.Class == ClassType.Wizard2) + // classManaGain = GameEV.MAGE_MANA_GAIN; + //return m_manaGain + classManaGain + SkillSystem.GetSkill(SkillType.Mana_Regen_Up).ModifierAmount + ((Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.ManaGain) + (int)GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.ManaDrain)) * GameEV.RUNE_MANA_GAIN) + // + (Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.ManaHPGain) * GameEV.RUNE_MANAHPGAIN); + + int classManaGain = 0; + if (Game.PlayerStats.Class == ClassType.Wizard || Game.PlayerStats.Class == ClassType.Wizard2) + classManaGain = GameEV.MAGE_MANA_GAIN; + return (int)((m_manaGain + classManaGain + SkillSystem.GetSkill(SkillType.Mana_Regen_Up).ModifierAmount + ((Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.ManaGain) + (int)GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.ManaDrain)) * GameEV.RUNE_MANA_GAIN) + + (Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.ManaHPGain) * GameEV.RUNE_MANAHPGAIN)) * (1 + Game.PlayerStats.TimesCastleBeaten * 0.5f)); + + } //TEDDY MODDING SO MANA GAIN IS AN EV + set { m_manaGain = value; } + } + + public float BlockManaDrain + { + get { return m_blockManaDrain - (int)GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.ManaDrain) - (int)SkillSystem.GetSkill(SkillType.Block).ModifierAmount; } + set { m_blockManaDrain = value; } + } + + public float TotalStatDropChance + { + get { return StatDropIncrease + BaseStatDropChance; } + } + + public float TotalCritChance + { + get + { + float CritChanceBonus = BaseCriticalChance + SkillSystem.GetSkill(SkillType.Crit_Chance_Up).ModifierAmount + GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.CritChance); + switch (Game.PlayerStats.Class) + { + case (ClassType.Assassin): + case (ClassType.Assassin2): + return (CritChanceBonus + PlayerEV.ASSASSIN_CRITCHANCE_MOD); + case (ClassType.Ninja): + case (ClassType.Ninja2): + return 0; // Ninjas have a 0% chance of critical striking. + } + return CritChanceBonus; + } + } + + public float TotalCriticalDamage + { + get + { + //return BaseCriticalDamageMod + SkillSystem.GetSkill(SkillType.Crit_Damage_Up).ModifierAmount + GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.CritDamage); + // +Game.TraitSystem.GetModifierAmount(m_traitArray, TraitType.Crit_Damage_Flat); + float CritDamageBonus = BaseCriticalDamageMod + SkillSystem.GetSkill(SkillType.Crit_Damage_Up).ModifierAmount + GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.CritDamage); + + switch (Game.PlayerStats.Class) + { + case (ClassType.Assassin): + case (ClassType.Assassin2): + return (CritDamageBonus + PlayerEV.ASSASSIN_CRITDAMAGE_MOD); + } + return CritDamageBonus; + } + } + + public float TotalXPBonus + { + get + { + return SkillSystem.GetSkill(SkillType.XP_Gain_Up).ModifierAmount + GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.XpBonus); + //+ Game.TraitSystem.GetModifierAmount(m_traitArray, TraitType.XP_Percentage); + } + } + + public float TotalGoldBonus + { + get + { + float goldBonus = SkillSystem.GetSkill(SkillType.Gold_Gain_Up).ModifierAmount + GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.GoldBonus) + + (Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.GoldGain) * GameEV.RUNE_GOLDGAIN_MOD) + (GameEV.NEWGAMEPLUS_GOLDBOUNTY * Game.PlayerStats.TimesCastleBeaten); + // + Game.TraitSystem.GetModifierAmount(m_traitArray, TraitType.Gold_Percentage); + + switch (Game.PlayerStats.Class) + { + case (ClassType.Banker): + case (ClassType.Banker2): + return (goldBonus + PlayerEV.BANKER_GOLDGAIN_MOD); + } + return goldBonus; + } + } + + public int TotalVampBonus + { + //get { return (Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.Vampirism) * + // GameEV.RUNE_VAMPIRISM_HEALTH_GAIN) + + // ((int)GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.Vampirism) * GameEV.RUNE_VAMPIRISM_HEALTH_GAIN) + // + (Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.ManaHPGain) * GameEV.RUNE_MANAHPGAIN); } + + get + { + return (int)(((Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.Vampirism) * + GameEV.RUNE_VAMPIRISM_HEALTH_GAIN) + + ((int)GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.Vampirism) * GameEV.RUNE_VAMPIRISM_HEALTH_GAIN) + + (Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.ManaHPGain) * GameEV.RUNE_MANAHPGAIN)) * (1 + Game.PlayerStats.TimesCastleBeaten * 0.5f)); + } + } + + public int TotalAirDashes + { + get { return Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.Dash) + (int)GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.AirDash); } + } + + public int TotalDoubleJumps + { + get { return Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.DoubleJump) + (int)GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.DoubleJump); } + } + + public float TotalFlightTime + { + get { return FlightTime * (Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.Flight) + (int)GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.Flight)); } + } + + public float TotalArmor + { + get { return (SkillSystem.GetSkill(SkillType.Armor_Up).ModifierAmount + (Game.PlayerStats.BonusDefense * GameEV.ITEM_STAT_ARMOR_AMOUNT)) + GetEquipmentArmor(); } + } + + public float TotalDamageReduc + { + get { return TotalArmor / (ArmorReductionMod + TotalArmor); } + } + + public float TotalMovementSpeed + { + get + { + float flightSpeedMod = 0; + if (State == STATE_FLYING || State == STATE_DRAGON) + flightSpeedMod = FlightSpeedMod; + float moveSpeed = this.Speed * (TotalMovementSpeedPercent + flightSpeedMod); + //Console.WriteLine("This speed: " + this.Speed + " speed percent:" + TotalMovementSpeedPercent + " flightspeedMod: " + flightSpeedMod + " total speed: " + moveSpeed); + + return moveSpeed; + } + } + + public float TotalMovementSpeedPercent + { + get + { + float traitMod = 0; + if (Game.PlayerStats.Traits.X == TraitType.Hyperactive || Game.PlayerStats.Traits.Y == TraitType.Hyperactive) + traitMod = GameEV.TRAIT_MOVESPEED_AMOUNT; + + //float moveSpeed = (this.Speed * flightSpeedMod * + // (1 + (GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.MoveSpeed) + traitMod + + // (Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.MovementSpeed) * GameEV.RUNE_MOVEMENTSPEED_MOD))) * + // ClassMoveSpeedMultiplier); + float moveSpeed = (1 + GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.MoveSpeed) + traitMod + + (Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.MovementSpeed) * GameEV.RUNE_MOVEMENTSPEED_MOD) + ClassMoveSpeedMultiplier); + return moveSpeed; + } + } + + public float TotalDamageReturn + { + get + { + return (GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.DamageReturn) + + (Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.DamageReturn) * GameEV.RUNE_DAMAGERETURN_MOD)); + } + } + + public bool ControlsLocked + { + get { return m_lockControls; } + } + + public bool IsFlying + { + get { return m_isFlying; } + } + + public Game Game + { + get { return m_game; } + } + + public bool IsInvincible + { + get { return m_invincibleCounter > 0; } + } + + public float ClassDamageGivenMultiplier + { + get + { + switch (Game.PlayerStats.Class) + { + case (ClassType.Barbarian): + case (ClassType.Barbarian2): + return PlayerEV.BARBARIAN_DAMAGE_MOD; + case (ClassType.Wizard): + case (ClassType.Wizard2): + return PlayerEV.MAGE_DAMAGE_MOD; + case (ClassType.SpellSword): + case (ClassType.SpellSword2): + return PlayerEV.SPELLSWORD_DAMAGE_MOD;//0.25f;//0.2f; //0.25f; + case (ClassType.Banker): + case (ClassType.Banker2): + return PlayerEV.BANKER_DAMAGE_MOD; + case (ClassType.Ninja): + case (ClassType.Ninja2): + return PlayerEV.NINJA_DAMAGE_MOD;//1.75f; //1.5f; + case (ClassType.Assassin): + case (ClassType.Assassin2): + return PlayerEV.ASSASSIN_DAMAGE_MOD; + case (ClassType.Lich): + case (ClassType.Lich2): + return PlayerEV.LICH_DAMAGE_MOD; + + } + return 1f; + } + } + + public float ClassDamageTakenMultiplier + { + get + { + switch (Game.PlayerStats.Class) + { + case (ClassType.Assassin): + case (ClassType.Assassin2): + return 1f; + } + return 1f; + } + } + + public float ClassMagicDamageGivenMultiplier + { + get + { + switch (Game.PlayerStats.Class) + { + case (ClassType.Wizard): + case (ClassType.Wizard2): + return PlayerEV.MAGE_MAGICDAMAGE_MOD; //1.25f; + case (ClassType.Lich): + case (ClassType.Lich2): + return PlayerEV.LICH_MAGICDAMAGE_MOD; //1.25f; + } + return 1f; + } + } + + public float ClassTotalHPMultiplier + { + get + { + switch (Game.PlayerStats.Class) + { + case (ClassType.Wizard): + case (ClassType.Wizard2): + return PlayerEV.MAGE_HEALTH_MOD; //1.25f; + case (ClassType.Banker): + case (ClassType.Banker2): + return PlayerEV.BANKER_HEALTH_MOD; + case (ClassType.Barbarian): + case (ClassType.Barbarian2): + return PlayerEV.BARBARIAN_HEALTH_MOD; + case (ClassType.Ninja): + case (ClassType.Ninja2): + return PlayerEV.NINJA_HEALTH_MOD; + case (ClassType.Assassin): + case (ClassType.Assassin2): + return PlayerEV.ASSASSIN_HEALTH_MOD; + case (ClassType.Lich): + case (ClassType.Lich2): + return PlayerEV.LICH_HEALTH_MOD; + case (ClassType.SpellSword): + case (ClassType.SpellSword2): + return PlayerEV.SPELLSWORD_HEALTH_MOD;//0.5f; + case (ClassType.Dragon): + return PlayerEV.DRAGON_HEALTH_MOD;//1.5f; + case (ClassType.Traitor): + return PlayerEV.TRAITOR_HEALTH_MOD; + } + return 1f; + } + } + + public float ClassTotalMPMultiplier + { + get + { + switch (Game.PlayerStats.Class) + { + case (ClassType.Wizard): + case (ClassType.Wizard2): + return PlayerEV.MAGE_MANA_MOD; + case (ClassType.Banker): + case (ClassType.Banker2): + return PlayerEV.BANKER_MANA_MOD; + case (ClassType.Barbarian): + case (ClassType.Barbarian2): + return PlayerEV.BARBARIAN_MANA_MOD; + case (ClassType.SpellSword): + case (ClassType.SpellSword2): + return PlayerEV.SPELLSWORD_MANA_MOD;//0.5f; + case (ClassType.Ninja): + case (ClassType.Ninja2): + return PlayerEV.NINJA_MANA_MOD; + case (ClassType.Assassin): + case (ClassType.Assassin2): + return PlayerEV.ASSASSIN_MANA_MOD; + case (ClassType.Lich): + case (ClassType.Lich2): + return PlayerEV.LICH_MANA_MOD; + case (ClassType.Dragon): + return PlayerEV.DRAGON_MANA_MOD;//1.5f; + case (ClassType.Traitor): + return PlayerEV.TRAITOR_MANA_MOD; + } + return 1f; + } + } + + public float ClassMoveSpeedMultiplier + { + get + { + switch (Game.PlayerStats.Class) + { + case (ClassType.Ninja): + case (ClassType.Ninja2): + return PlayerEV.NINJA_MOVESPEED_MOD;//1.5f; + case (ClassType.Dragon): + return PlayerEV.DRAGON_MOVESPEED_MOD;//1.5f; + } + return 0f; + } + } + + public float SpellCastDelay + { + get { return m_spellCastDelay; } + } + + public bool LightOn + { + get { return m_lightOn; } + } + + public override SpriteEffects Flip + { + get { return base.Flip; } + set + { + if (Game.PlayerStats.Traits.X == TraitType.StereoBlind || Game.PlayerStats.Traits.Y == TraitType.StereoBlind) + { + if (Flip != value) + { + if (m_flipTween != null && m_flipTween.TweenedObject == this && m_flipTween.Active == true) + m_flipTween.StopTween(false); + + float storedX = m_internalScale.X; + this.ScaleX = 0; + m_flipTween = Tween.To(this, 0.15f, Tweener.Tween.EaseNone, "ScaleX", storedX.ToString()); + } + } + base.Flip = value; + } + } + + public bool CastingDamageShield + { + get { return m_damageShieldCast; } + } + } +} diff --git a/RogueCastle/src/Game Objects/Player/PlayerStats.cs b/RogueCastle/src/Game Objects/Player/PlayerStats.cs new file mode 100644 index 0000000..8e899b3 --- /dev/null +++ b/RogueCastle/src/Game Objects/Player/PlayerStats.cs @@ -0,0 +1,396 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class PlayerStats : IDisposableObj + { + public int CurrentLevel { get; set; } + private int m_gold = 0; + public int Gold + { + get { return m_gold; } + set + { + m_gold = value; + if (m_gold < 0) m_gold = 0; + } + } + public int CurrentHealth { get; set; } + public int CurrentMana { get; set; } + public byte Age { get; set; } + public byte ChildAge { get; set; } + public byte Spell { get; set; } + public byte Class { get; set; } + public byte SpecialItem { get; set; } + public Vector2 Traits { get; set; } + public string PlayerName { get; set; } + + private string m_romanNumeral = ""; + public string RomanNumeral + { + get { return m_romanNumeral; } + set { m_romanNumeral = value; } + } + + public byte HeadPiece { get; set; } + public byte ShoulderPiece { get; set; } + public byte ChestPiece { get; set; } + + public byte DiaryEntry { get; set; } + + public int BonusHealth { get; set; } + public int BonusStrength { get; set; } + public int BonusMana { get; set; } + public int BonusDefense { get; set; } + public int BonusWeight { get; set; } + public int BonusMagic { get; set; } + + public int LichHealth { get; set; } + public int LichMana { get; set; } + public float LichHealthMod { get; set; } + + public bool NewBossBeaten { get; set; } // A flag to keep track of this particular hero beat a boss. + public bool EyeballBossBeaten { get; set; } + public bool FairyBossBeaten { get; set; } + public bool FireballBossBeaten { get; set; } + public bool BlobBossBeaten { get; set; } + public bool LastbossBeaten { get; set; } + + public int TimesCastleBeaten { get; set; } // Times you've beaten the game. + public int NumEnemiesBeaten { get; set; } // Number of enemies you've beaten in a single run. + + public bool TutorialComplete { get; set; } + public bool CharacterFound { get; set; } + public bool LoadStartingRoom { get; set; } + + public bool LockCastle { get; set; } + public bool SpokeToBlacksmith { get; set; } + public bool SpokeToEnchantress{ get; set; } + public bool SpokeToArchitect { get; set; } + public bool SpokeToTollCollector { get; set; } + public bool IsDead { get; set; } + public bool FinalDoorOpened { get; set; } + public bool RerolledChildren { get; set; } + + public byte ForceLanguageGender = 0; + public bool GodMode = false; + private bool m_isFemale = false; + public bool IsFemale + { + get + { + if (ForceLanguageGender == 0) + return m_isFemale; + else if (ForceLanguageGender == 1) + return false; + else + return true; + } + set { m_isFemale = value; } + } + + public int TimesDead { get; set; } + public bool HasArchitectFee { get; set; } + public bool ReadLastDiary { get; set; } + public bool SpokenToLastBoss { get; set; } + public bool HardcoreMode { get; set; } + public float TotalHoursPlayed { get; set; } + + /// Adding Prosopagnosia trait. + public bool HasProsopagnosia { get; set; } + + // Adding Save file revision numbers. + public int RevisionNumber { get; set; } + + public Vector3 WizardSpellList { get; set; } + + // These arrays hold the blueprint unlock state of each item. + private List m_blueprintArray; + private List m_runeArray; + + // These arrays hold which item you currently have equipped. -1 means no item. + private sbyte[] m_equippedArray; + private sbyte[] m_equippedRuneArray; + + public List CurrentBranches; + public List FamilyTreeArray; + + public List EnemiesKilledList; // The total list of enemies killed. + public List EnemiesKilledInRun; // The enemies killed in a single run. + + // Adding challenge icons. + public bool ChallengeEyeballUnlocked { get; set; } + public bool ChallengeFireballUnlocked { get; set; } + public bool ChallengeBlobUnlocked { get; set; } + public bool ChallengeSkullUnlocked { get; set; } + public bool ChallengeLastBossUnlocked { get; set; } + + public bool ChallengeEyeballBeaten { get; set; } + public bool ChallengeFireballBeaten { get; set; } + public bool ChallengeBlobBeaten { get; set; } + public bool ChallengeSkullBeaten { get; set; } + public bool ChallengeLastBossBeaten { get; set; } + + public sbyte ChallengeEyeballTimesUpgraded { get; set; } + public sbyte ChallengeFireballTimesUpgraded { get; set; } + public sbyte ChallengeBlobTimesUpgraded { get; set; } + public sbyte ChallengeSkullTimesUpgraded { get; set; } + public sbyte ChallengeLastBossTimesUpgraded { get; set; } + + public bool ArchitectUsed { get; set; } + /// + + public PlayerStats() + { + if (LevelEV.RUN_TUTORIAL == false && this.TutorialComplete == false && LevelEV.RUN_TESTROOM == true) // This is debug that needs to be removed once tutorial is properly implemented. + this.TutorialComplete = true; + + PlayerName = "Lee";//"Sir Johannes"; + SpecialItem = SpecialItemType.None; + Class = ClassType.Knight; + Spell = SpellType.Dagger; + Age = 30; + ChildAge = 5; + LichHealthMod = 1; // Default is 1 + IsFemale = false; + TimesCastleBeaten = 0; + RomanNumeral = ""; + //LastbossBeaten = true; + + EnemiesKilledList = new List(); + for (int i = 0; i < EnemyType.Total; i++) + EnemiesKilledList.Add(new Vector4()); + + WizardSpellList = new Vector3(SpellType.Dagger, SpellType.Axe, SpellType.Boomerang); + + Traits = new Vector2(TraitType.None, TraitType.None); + Gold = 0; + CurrentLevel = 0; + + HeadPiece = 1; + ShoulderPiece = 1; + ChestPiece = 1; + LoadStartingRoom = true; // Default is true. + + m_blueprintArray = new List(); + m_runeArray = new List(); + m_equippedArray = new sbyte[EquipmentCategoryType.Total]; + m_equippedRuneArray = new sbyte[EquipmentCategoryType.Total]; + + FamilyTreeArray = new List(); + InitializeFirstChild(); + EnemiesKilledInRun = new List(); + CurrentBranches = null; + + for (int i = 0; i < EquipmentCategoryType.Total; i++) + { + m_blueprintArray.Add(new byte[EquipmentBaseType.Total]); + m_runeArray.Add(new byte[EquipmentAbilityType.Total]); + m_equippedArray[i] = -1; + m_equippedRuneArray[i] = -1; + } + + //TEDDY - KENNY GAVE TO RANDOMIZE THE PLAYERS EQUIPMENT AND STUFF + + HeadPiece = (byte)CDGMath.RandomInt(1, 5); + ShoulderPiece = (byte)CDGMath.RandomInt(1, 5); + ChestPiece = (byte)CDGMath.RandomInt(1, 5); + sbyte rand = (sbyte)CDGMath.RandomInt(0, 14); + /* + m_equippedArray[EquipmentCategoryType.Chest] = (sbyte)CDGMath.RandomInt(0, 14); + m_equippedArray[EquipmentCategoryType.Helm] = (sbyte)CDGMath.RandomInt(0, 14); + m_equippedArray[EquipmentCategoryType.Limbs] = (sbyte)CDGMath.RandomInt(0, 14); + m_equippedArray[EquipmentCategoryType.Cape] = (sbyte)CDGMath.RandomInt(0, 14); + m_equippedArray[EquipmentCategoryType.Sword] = rand; + */ + + // Debug stuff to test items. + m_blueprintArray[EquipmentCategoryType.Helm][EquipmentBaseType.Bronze] = EquipmentState.FoundButNotSeen; + m_blueprintArray[EquipmentCategoryType.Limbs][EquipmentBaseType.Bronze] = EquipmentState.FoundButNotSeen; + m_blueprintArray[EquipmentCategoryType.Sword][EquipmentBaseType.Bronze] = EquipmentState.FoundButNotSeen; + + m_runeArray[EquipmentCategoryType.Helm][EquipmentAbilityType.DoubleJump] = EquipmentState.FoundButNotSeen; + m_runeArray[EquipmentCategoryType.Sword][EquipmentAbilityType.Dash] = EquipmentState.FoundButNotSeen; + //m_blueprintArray[0][0] = EquipmentState.Purchased; + //m_blueprintArray[0][1] = EquipmentState.NotPurchased; + //m_blueprintArray[0][2] = EquipmentState.NotPurchased; + //m_blueprintArray[0][3] = EquipmentState.NotPurchased; + //m_blueprintArray[0][4] = EquipmentState.NotPurchased; + //m_blueprintArray[EquipmentCategoryType.Helm][4] = EquipmentState.NotPurchased; + //m_blueprintArray[EquipmentCategoryType.Cape][0] = EquipmentState.Purchased; + //m_blueprintArray[EquipmentCategoryType.Cape][7] = EquipmentState.Purchased; + //m_blueprintArray[EquipmentCategoryType.Cape][14] = EquipmentState.NotPurchased; + //m_blueprintArray[EquipmentCategoryType.Cape][5] = EquipmentState.Purchased; + + //m_runeArray[0][0] = EquipmentState.Purchased; + //m_runeArray[0][1] = EquipmentState.NotPurchased; + //m_equippedRuneArray[0] = 0; + //m_equippedRuneArray[0] = EquipmentAbilityType.Flight; + + //EyeballBossBeaten = true; + //ChallengeEyeballBeaten = true; + //ChallengeEyeballUnlocked = true; + + //FairyBossBeaten = true; + //ChallengeSkullBeaten = false; + //ChallengeSkullUnlocked = true; + + //FireballBossBeaten = true; + //ChallengeFireballBeaten = false; + //ChallengeFireballUnlocked = true; + + //BlobBossBeaten = true; + //ChallengeBlobBeaten = false; + //ChallengeBlobUnlocked = true; + + //ChallengeLastBossUnlocked = true; + //ChallengeLastBossBeaten = true; + + //HeadPiece = 7; + } + + private void InitializeFirstChild() + { + FamilyTreeNode firstNode = new FamilyTreeNode() + { + Name = "Johannes", + Age = 30, + ChildAge = 20, + Class = ClassType.Knight, + HeadPiece = 8, + ChestPiece = 1, + ShoulderPiece = 1, + NumEnemiesBeaten = 0, + BeatenABoss = true, + IsFemale = false, + Traits = Vector2.Zero, + }; + FamilyTreeArray.Add(firstNode); + } + + + private bool m_isDisposed = false; + public void Dispose() + { + if (IsDisposed == false) + { + m_blueprintArray.Clear(); + m_blueprintArray = null; + m_runeArray.Clear(); + m_runeArray = null; + m_isDisposed = true; + } + } + + public bool IsDisposed + { + get { return m_isDisposed; } + } + + public List GetBlueprintArray + { + get { return m_blueprintArray; } + } + + public sbyte[] GetEquippedArray + { + get { return m_equippedArray; } + } + + public byte TotalBlueprintsPurchased + { + get + { + byte total = 0; + foreach (byte[] categoryType in GetBlueprintArray) + { + foreach (byte purchaseState in categoryType) + { + if (purchaseState >= EquipmentState.Purchased) + total++; + } + } + return total; + } + } + + public byte TotalRunesPurchased + { + get + { + byte total = 0; + foreach (byte[] categoryType in GetRuneArray) + { + foreach (byte purchaseState in categoryType) + { + if (purchaseState >= EquipmentState.Purchased) + total++; + } + } + return total; + } + } + + public byte TotalBlueprintsFound + { + get + { + byte total = 0; + foreach (byte[] categoryType in GetBlueprintArray) + { + foreach (byte purchaseState in categoryType) + { + if (purchaseState >= EquipmentState.FoundButNotSeen) + total++; + } + } + return total; + } + } + + public byte TotalRunesFound + { + get + { + byte total = 0; + foreach (byte[] categoryType in GetRuneArray) + { + foreach (byte purchaseState in categoryType) + { + if (purchaseState >= EquipmentState.FoundButNotSeen) + total++; + } + } + return total; + } + } + + public List GetRuneArray + { + get { return m_runeArray; } + } + + public sbyte[] GetEquippedRuneArray + { + get { return m_equippedRuneArray; } + } + + public byte GetNumberOfEquippedRunes(int equipmentAbilityType) + { + byte numEquippedAbilities = 0; + if (LevelEV.UNLOCK_ALL_ABILITIES == true) + return EquipmentCategoryType.Total; + foreach (sbyte equippedAbility in m_equippedRuneArray) + { + if (equippedAbility == equipmentAbilityType) + numEquippedAbilities++; + } + return numEquippedAbilities; + } + } +} diff --git a/RogueCastle/src/Game Objects/PlayerStartObj.cs b/RogueCastle/src/Game Objects/PlayerStartObj.cs new file mode 100644 index 0000000..87b5f65 --- /dev/null +++ b/RogueCastle/src/Game Objects/PlayerStartObj.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; + +namespace RogueCastle +{ + public class PlayerStartObj : GameObj + { + protected override GameObj CreateCloneInstance() + { + return new PlayerStartObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + } +} diff --git a/RogueCastle/src/Game Objects/ProjectileIconObj.cs b/RogueCastle/src/Game Objects/ProjectileIconObj.cs new file mode 100644 index 0000000..7f0e9fd --- /dev/null +++ b/RogueCastle/src/Game Objects/ProjectileIconObj.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class ProjectileIconObj : GameObj + { + private SpriteObj m_iconBG; + private SpriteObj m_iconProjectile; + private ProjectileObj m_attachedProjectile; + + private int m_iconOffset = 60; + + public ProjectileIconObj() + { + this.ForceDraw = true; + m_iconBG = new SpriteObj("ProjectileIcon_Sprite"); + m_iconBG.ForceDraw = true; + + m_iconProjectile = new SpriteObj("Blank_Sprite"); + m_iconProjectile.ForceDraw = true; + } + + public void Update(Camera2D camera) + { + if (AttachedProjectile.X <= camera.Bounds.Left + m_iconOffset) + this.X = m_iconOffset; + else if (AttachedProjectile.X > camera.Bounds.Right - m_iconOffset) + this.X = 1320 - m_iconOffset; + else + this.X = AttachedProjectile.X - camera.TopLeftCorner.X; + + if (AttachedProjectile.Y <= camera.Bounds.Top + m_iconOffset) + this.Y = m_iconOffset; + else if (AttachedProjectile.Y > camera.Bounds.Bottom - m_iconOffset) + this.Y = 720 - m_iconOffset; + else + this.Y = AttachedProjectile.Y - camera.TopLeftCorner.Y; + + this.Rotation = CDGMath.AngleBetweenPts(camera.TopLeftCorner + this.Position, AttachedProjectile.Position); + + m_iconBG.Position = this.Position; + m_iconBG.Rotation = this.Rotation; + + m_iconProjectile.Position = this.Position; + m_iconProjectile.Rotation = AttachedProjectile.Rotation; + m_iconProjectile.GoToFrame(AttachedProjectile.CurrentFrame); + } + + public override void Draw(Camera2D camera) + { + if (this.Visible == true)// && CollisionMath.Intersects(AttachedProjectile.Bounds, camera.LogicBounds)) + { + m_iconBG.Draw(camera); + m_iconProjectile.Draw(camera); + //base.Draw(camera); + } + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_iconBG.Dispose(); + m_iconBG = null; + m_iconProjectile.Dispose(); + m_iconProjectile = null; + AttachedProjectile = null; + base.Dispose(); + } + } + + protected override GameObj CreateCloneInstance() + { + return new ProjectileIconObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + ProjectileIconObj clone = obj as ProjectileIconObj; + clone.AttachedProjectile = this.AttachedProjectile; + } + + public ProjectileObj AttachedProjectile + { + get { return m_attachedProjectile;} + set + { + m_attachedProjectile = value; + if (value != null) + { + m_iconProjectile.ChangeSprite(value.SpriteName); + m_iconProjectile.Scale = new Vector2(0.7f, 0.7f); + } + } + } + + } +} diff --git a/RogueCastle/src/Game Objects/ProjectileObj.cs b/RogueCastle/src/Game Objects/ProjectileObj.cs new file mode 100644 index 0000000..a4924cb --- /dev/null +++ b/RogueCastle/src/Game Objects/ProjectileObj.cs @@ -0,0 +1,660 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener.Ease; +using Tweener; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class ProjectileObj : PhysicsObj, IDealsDamageObj//, IPoolableObj + { + public int Damage { get; set; } + public float RotationSpeed { get; set; } + public float LifeSpan = 0; + private float m_elapsedLifeSpan = 0; + public bool IsAlive { get; internal set; } + public bool CollidesWithTerrain { get; set; } + public bool DestroysWithTerrain { get; set; } // Is destroyed upon hitting terrain. + public bool DestroysWithEnemy { get; set; } + public GameObj Target { get; set; } + public bool ChaseTarget { get; set; } + public bool FollowArc { get; set; } + public ProjectileIconObj AttachedIcon { get; set; } + public bool ShowIcon { get; set; } + public bool IgnoreBoundsCheck { get; set; } + public bool CollidesWith1Ways { get; set; } + public bool GamePaused { get; set; } + public bool DestroyOnRoomTransition { get; set; } + public bool CanBeFusRohDahed { get; set; } + public bool IgnoreInvincibleCounter { get; set; } + + public bool IsDying { get; internal set; } + + // Property used exclusively for player spells. + public int Spell { get; set; } + public float AltX { get; set; } + public float AltY { get; set; } + public float BlinkTime { get; set; } + + private Color m_blinkColour = Color.White; + private float m_blinkTimer = 0; + + public GameObj Source { get; set; } + public bool WrapProjectile { get; set; } + + public ProjectileObj(string spriteName) + : base(spriteName) + { + CollisionTypeTag = GameTypes.CollisionType_ENEMY; + CollidesWithTerrain = true; + ChaseTarget = false; + IsDying = false; + DestroysWithEnemy = true; + DestroyOnRoomTransition = true; + } + + public void Reset() + { + Source = null; + CollidesWithTerrain = true; + DestroysWithTerrain = true; + DestroysWithEnemy = true; + IsCollidable = true; + IsWeighted = true; + IsDying = false; + IsAlive = true; + m_elapsedLifeSpan = 0; + Rotation = 0; + this.TextureColor = Color.White; + Spell = 0; + AltY = 0; + AltX = 0; + BlinkTime = 0; + IgnoreBoundsCheck = false; + Scale = Vector2.One; + DisableHitboxUpdating = false; + m_blinkColour = Color.White; + m_blinkTimer = 0; + AccelerationYEnabled = true; + AccelerationXEnabled = true; + GamePaused = false; + DestroyOnRoomTransition = true; + CanBeFusRohDahed = true; + this.Flip = SpriteEffects.None; + IgnoreInvincibleCounter = false; + WrapProjectile = false; + + DisableCollisionBoxRotations = true; // Don't do rotated rect collision detection on projectiles. This is for performance purposes. + Tween.StopAllContaining(this, false); + } + + public void UpdateHeading() + { + if (ChaseTarget == true && Target != null) + { + Vector2 seekPosition = Target.Position; + TurnToFace(seekPosition, TurnSpeed, 1/60f); + + this.HeadingX = (float)Math.Cos(this.Orientation); + this.HeadingY = (float)Math.Sin(this.Orientation); + } + } + + public void Update(GameTime gameTime) + { + if (IsPaused == false) + { + float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds; + switch (Spell) + { + case (SpellType.TimeBomb): + if (BlinkTime >= AltX && AltX != 0) + { + Blink(Color.Red, 0.1f); + BlinkTime = AltX / 1.5f; + } + if (AltX > 0) + { + AltX -= elapsedTime; + if (AltX <= 0) + this.ActivateEffect(); + } + break; + case (SpellType.Nuke): + // Smoke effect + if (AltY > 0) + { + AltY -= elapsedTime; + if (AltY <= 0) + { + ProceduralLevelScreen level = Game.ScreenManager.CurrentScreen as ProceduralLevelScreen; + if (level != null) + { + level.ImpactEffectPool.CrowSmokeEffect(this.Position); + AltY = 0.05f; + } + } + } + + if (AltX <= 0) + { + Vector2 seekPosition = Target.Position; + TurnToFace(seekPosition, TurnSpeed, elapsedTime); // Turn to face already calls WrapAngle() + } + else + { + AltX -= elapsedTime; + this.Orientation = MathHelper.WrapAngle(Orientation); + } + + this.HeadingX = (float)Math.Cos(this.Orientation); + this.HeadingY = (float)Math.Sin(this.Orientation); + this.AccelerationX = 0; + this.AccelerationY = 0; + this.Position += this.Heading * (this.CurrentSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds); + + if (this.HeadingX > 0) + { + this.Flip = SpriteEffects.None; + this.Rotation = MathHelper.ToDegrees(this.Orientation); + } + else + { + this.Flip = SpriteEffects.FlipHorizontally; + float angle = MathHelper.ToDegrees(this.Orientation); + if (angle < 0) + this.Rotation = (180 + angle) * 60 * elapsedTime; + else + this.Rotation = (-180 + angle) * 60 * elapsedTime; + } + this.Rotation = MathHelper.Clamp(this.Rotation, -90, 90); + + // Destroy the spell if the enemy dies. + if (this.Target != null) + { + EnemyObj target = this.Target as EnemyObj; + if (target != null && target.IsKilled == true) + RunDestroyAnimation(false); + } + else + RunDestroyAnimation(false); + + break; + case (SpellType.DamageShield): + PlayerObj player = Game.ScreenManager.Player; + if (player.CastingDamageShield == true || Source is EnemyObj) // Special handling for the last boss since he casts this spell too. + { + AltX += (CurrentSpeed * 60 * elapsedTime); + this.Position = CDGMath.GetCirclePosition(AltX, AltY, Target.Position); + } + else + this.KillProjectile(); + break; + case (SpellType.Bounce): + this.AccelerationX = 0; + this.AccelerationY = 0; + this.HeadingX = (float)Math.Cos(this.Orientation); + this.HeadingY = (float)Math.Sin(this.Orientation); + //this.Rotation = MathHelper.ToDegrees(this.Orientation); + this.Position += this.Heading * (this.CurrentSpeed * elapsedTime); + if (this.AltY > 0) + { + this.AltY -= elapsedTime; + if (AltY <= 0) + ActivateEffect(); + } + break; + case (SpellType.Boomerang): + this.AccelerationX -= (AltX * 60 * elapsedTime); + if (this.AltY > 0) + { + this.AltY -= elapsedTime; + if (AltY <= 0) + ActivateEffect(); + } + break; + case (SpellType.Laser): + if (AltX > 0) + { + AltX -= elapsedTime; + this.Opacity = 0.9f - AltX; + this.ScaleY = 1 - AltX; + if (AltX <= 0) + ActivateEffect(); + } + break; + } + + if (ChaseTarget == true && Target != null) + { + Vector2 seekPosition = Target.Position; + TurnToFace(seekPosition, TurnSpeed, elapsedTime); + + this.HeadingX = (float)Math.Cos(this.Orientation); + this.HeadingY = (float)Math.Sin(this.Orientation); + + this.AccelerationX = 0; + this.AccelerationY = 0; + this.Position += this.Heading * (this.CurrentSpeed * elapsedTime); + this.Rotation = MathHelper.ToDegrees(this.Orientation); + } + + if (FollowArc == true && ChaseTarget == false && IsDying == false) + { + float desiredAngle = (float)Math.Atan2(AccelerationY, AccelerationX); + this.Rotation = MathHelper.ToDegrees(desiredAngle); + } + else if (ChaseTarget == false) + this.Rotation += (this.RotationSpeed * 60 * elapsedTime); + + m_elapsedLifeSpan += elapsedTime; + if (m_elapsedLifeSpan >= LifeSpan) + IsAlive = false; // Might want to change this to RunDestroyAnimation(). + + if (m_blinkTimer > 0) + { + m_blinkTimer -= elapsedTime; + this.TextureColor = m_blinkColour; + } + else if (this.TextureColor == m_blinkColour) + this.TextureColor = Color.White; + } + } + + public void Blink(Color blinkColour, float duration) + { + m_blinkColour = blinkColour; + m_blinkTimer = duration; + } + + private void TurnToFace(Vector2 facePosition, float turnSpeed, float elapsedSeconds) + { + float x = facePosition.X - this.Position.X; + float y = facePosition.Y - this.Position.Y; + + float desiredAngle = (float)Math.Atan2(y, x); + float difference = MathHelper.WrapAngle(desiredAngle - this.Orientation); + + float internalTurnSpeed = turnSpeed * 60 * elapsedSeconds; + + difference = MathHelper.Clamp(difference, -internalTurnSpeed, internalTurnSpeed); + this.Orientation = MathHelper.WrapAngle(this.Orientation + difference); + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + // Special handling for shout. + if (this.Spell == SpellType.Shout) + { + ProjectileObj proj = otherBox.AbsParent as ProjectileObj; + if (proj != null && proj.CollisionTypeTag != GameTypes.CollisionType_PLAYER && proj.CanBeFusRohDahed == true) + proj.RunDestroyAnimation(false); + } + + TerrainObj terrain = otherBox.Parent as TerrainObj; + if (CollidesWithTerrain == true && !(otherBox.Parent is DoorObj) && terrain != null && + ((terrain.CollidesTop == true && terrain.CollidesBottom == true && terrain.CollidesLeft == true && terrain.CollidesRight == true) || this.CollidesWith1Ways == true)) + { + switch (Spell) + { + case (SpellType.Displacer): + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + this.IsWeighted = false; + ActivateEffect(); + break; + case (SpellType.Bounce): + Vector2 mtd = CollisionMath.RotatedRectIntersectsMTD(thisBox.AbsRect, thisBox.AbsRotation, Vector2.Zero, otherBox.AbsRect, otherBox.AbsRotation, Vector2.Zero); + if (mtd != Vector2.Zero) + { + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Spike_Bounce_01", "Spike_Bounce_02", "Spike_Bounce_03"); + Vector2 v = Heading; + Vector2 l = new Vector2(mtd.Y, mtd.X * -1); // The angle of the side the vector hit is the normal to the MTD. + Vector2 newHeading = ((2 * (CDGMath.DotProduct(v, l) / CDGMath.DotProduct(l, l)) * l) - v); + this.X += mtd.X; + this.Y += mtd.Y; + this.Orientation = MathHelper.ToRadians(CDGMath.VectorToAngle(newHeading)); + //this.CollisionTypeTag = GameTypes.CollisionType_GLOBAL_DAMAGE_WALL; + //this.Heading = newHeading; + } + break; + case (SpellType.TimeBomb): // Proper logic for weighted objects. + if (terrain.CollidesBottom == true && terrain.CollidesTop == true && terrain.CollidesLeft == true && terrain.CollidesRight == true) + { + Vector2 mtd2 = CollisionMath.RotatedRectIntersectsMTD(thisBox.AbsRect, thisBox.AbsRotation, Vector2.Zero, otherBox.AbsRect, otherBox.AbsRotation, Vector2.Zero); + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + if ((mtd2.Y <= 0 && mtd2.X == 0) || otherBox.AbsRotation != 0) + { + this.AccelerationY = 0; + this.AccelerationX = 0; + this.IsWeighted = false; + } + } + else if (terrain.CollidesBottom == false && terrain.CollidesTop == true && terrain.CollidesLeft == false && terrain.CollidesRight == false) + { + Vector2 mtd2 = CollisionMath.RotatedRectIntersectsMTD(thisBox.AbsRect, thisBox.AbsRotation, Vector2.Zero, otherBox.AbsRect, otherBox.AbsRotation, Vector2.Zero); + if (mtd2.Y <= 0 && this.AccelerationY > 0) + { + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + if ((mtd2.Y <= 0 && mtd2.X == 0) || otherBox.AbsRotation != 0) + { + this.AccelerationY = 0; + this.AccelerationX = 0; + this.IsWeighted = false; + } + } + } + break; + default: // Default sets AccelerationX to 0, effectively sticking the projectile to walls. + if (DestroysWithTerrain == true) + RunDestroyAnimation(false); + else + { + this.AccelerationY = 0; + this.AccelerationX = 0; + this.IsWeighted = false; + } + break; + } + } + else if (otherBox.Type != Consts.TERRAIN_HITBOX) // We don't want projectile terrain boxes hitting player or enemy hitboxes. + { + switch (Spell) + { + case (SpellType.Nuke): + if (otherBox.AbsParent == this.Target) // Ensures each crow only hits its target. + this.CollisionTypeTag = GameTypes.CollisionType_PLAYER; + break; + default: + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + break; + } + } + } + + // An effect made specifically for the displacer. + public void RunDisplacerEffect(RoomObj room, PlayerObj player) + { + int closestDistance = int.MaxValue; + TerrainObj closestObj = null; + + Vector2 collisionPt = Vector2.Zero; + + foreach (TerrainObj terrain in room.TerrainObjList) + { + collisionPt = Vector2.Zero; + // Only collide with terrain that the displacer would collide with. + float distance = float.MaxValue; + if (player.Flip == SpriteEffects.None) + { + if (terrain.X > this.X && (terrain.Bounds.Top < this.Bounds.Bottom && terrain.Bounds.Bottom > this.Bounds.Top)) + { + //if (terrain.Rotation == -45) + if (terrain.Rotation < 0) // ROTCHECK + collisionPt = CollisionMath.LineToLineIntersect(this.Position, new Vector2(this.X + 6600, this.Y), + CollisionMath.UpperLeftCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero), CollisionMath.UpperRightCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero)); + //else if (terrain.Rotation == 45) + else if (terrain.Rotation > 0) // ROTCHECK + collisionPt = CollisionMath.LineToLineIntersect(this.Position, new Vector2(this.X + 6600, this.Y), + CollisionMath.LowerLeftCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero), CollisionMath.UpperLeftCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero)); + + if (collisionPt != Vector2.Zero) + distance = collisionPt.X - this.X; + else + distance = terrain.Bounds.Left - this.Bounds.Right; + } + } + else + { + if (terrain.X < this.X && (terrain.Bounds.Top < this.Bounds.Bottom && terrain.Bounds.Bottom > this.Bounds.Top)) + { + //if (terrain.Rotation == -45) + if (terrain.Rotation < 0) // ROTCHECK + collisionPt = CollisionMath.LineToLineIntersect(new Vector2(this.X - 6600, this.Y), this.Position, + CollisionMath.UpperRightCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero), CollisionMath.LowerRightCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero)); + //else if (terrain.Rotation == 45) + else if (terrain.Rotation > 0) // ROTCHECK + collisionPt = CollisionMath.LineToLineIntersect(new Vector2(this.X - 6600, this.Y), this.Position, + CollisionMath.UpperLeftCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero), CollisionMath.UpperRightCorner(terrain.NonRotatedBounds, terrain.Rotation, Vector2.Zero)); + + if (collisionPt != Vector2.Zero) + distance = this.X - collisionPt.X; + else + distance = this.Bounds.Left - terrain.Bounds.Right; + } + } + + if (distance < closestDistance) + { + closestDistance = (int)distance; + closestObj = terrain; + } + } + + if (closestObj != null) + { + if (player.Flip == SpriteEffects.None) + { + if (closestObj.Rotation == 0) + player.X += closestDistance - player.TerrainBounds.Width / 2f; + else + player.X += closestDistance - player.Width / 2f; + } + else + { + if (closestObj.Rotation == 0) + player.X -= closestDistance - player.TerrainBounds.Width / 2f; + else + player.X -= closestDistance - player.Width / 2f; + } + //Console.WriteLine(closestDistance); + //Tween.By(closestObj, 10, Tween.EaseNone, "Y", "-1000"); + } + } + + public void RunDestroyAnimation(bool hitPlayer) + { + if (IsDying == false && IsDemented == false) + { + this.CurrentSpeed = 0; + this.AccelerationX = 0; + this.AccelerationY = 0; + IsDying = true; + + switch (SpriteName) + { + case ("ArrowProjectile_Sprite"): + case ("SpellClose_Sprite"): + case ("SpellDagger_Sprite"): + if (hitPlayer == true) + { + Tween.By(this, 0.3f, Linear.EaseNone, "Rotation", "270"); + int randArrowX = CDGMath.RandomInt(-50, 50); + int randArrowY = CDGMath.RandomInt(-100, -50); + Tween.By(this, 0.3f, Linear.EaseNone, "X", randArrowX.ToString(), "Y", randArrowY.ToString()); + Tween.To(this, 0.3f, Linear.EaseNone, "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "KillProjectile"); + } + else + { + this.IsWeighted = false; + this.IsCollidable = false; + Tween.To(this, 0.3f, Linear.EaseNone, "delay", "0.3", "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "KillProjectile"); + } + break; + case ("ShurikenProjectile1_Sprite"): + case ("BoneProjectile_Sprite"): + case ("SpellBounce_Sprite"): + case ("LastBossSwordVerticalProjectile_Sprite"): + Tween.StopAllContaining(this, false); // Special handle since the last boss uses tweens to move this projectile instead of the normal way. + this.IsCollidable = false; + int randX = CDGMath.RandomInt(-50, 50); + int randY = CDGMath.RandomInt(-100, 100); + Tween.By(this, 0.3f, Linear.EaseNone, "X", randX.ToString(), "Y", randY.ToString()); + Tween.To(this, 0.3f, Linear.EaseNone, "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "KillProjectile"); + break; + case ("HomingProjectile_Sprite"): + ProceduralLevelScreen screen = Game.ScreenManager.CurrentScreen as ProceduralLevelScreen; + if (screen != null) + screen.ImpactEffectPool.DisplayExplosionEffect(this.Position); + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "MissileExplosion_01", "MissileExplosion_02"); + KillProjectile(); + break; + case ("SpellAxe_Sprite"): + case ("SpellDualBlades_Sprite"): + this.IsCollidable = false; + this.AccelerationX = 0; + this.AccelerationY = 0; + Tween.To(this, 0.3f, Tween.EaseNone, "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "KillProjectile"); + break; + case ("SpellDamageShield_Sprite"): + case ("SpellDisplacer_Sprite"): + Tween.To(this, 0.2f, Tween.EaseNone, "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "KillProjectile"); + break; + case ("LastBossSwordProjectile_Sprite"): + this.IsCollidable = false; + Tween.StopAllContaining(this, false); // Special handle since the last boss uses tweens to move this projectile instead of the normal way. + Tween.By(this, 0.3f, Linear.EaseNone, "Rotation", "270"); + int randArrow = CDGMath.RandomInt(-100, -50); + Tween.By(this, 0.3f, Linear.EaseNone, "Y", randArrow.ToString()); + Tween.To(this, 0.3f, Linear.EaseNone, "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "KillProjectile"); + break; + case("SpellNuke_Sprite"): + ProceduralLevelScreen level = Game.ScreenManager.CurrentScreen as ProceduralLevelScreen; + if (level != null) + level.ImpactEffectPool.CrowDestructionEffect(this.Position); + KillProjectile(); + break; + case ("EnemyFlailKnightBall_Sprite"): + case ("WizardIceSpell_Sprite"): + case ("WizardEarthSpell_Sprite"): + case ("SpellTimeBomb_Sprite"): + case ("SpellLaser_Sprite"): + case ("SpellBoomerang_Sprite"): + // Do nothing for projectiles that don't get destroyed on impact. + KillProjectile(); + break; + default: + if (SpriteName == "WizardIceProjectile_Sprite") + SoundManager.Play3DSound(this, Game.ScreenManager.Player,"Ice_Wizard_Break_01", "Ice_Wizard_Break_02", "Ice_Wizard_Break_03"); + string explosionName = SpriteName.Replace("_", "Explosion_"); + this.ChangeSprite(explosionName); + this.AnimationDelay = 1 / 30f; + this.PlayAnimation(false); + this.IsWeighted = false; + this.IsCollidable = false; + if (explosionName != "EnemySpearKnightWaveExplosion_Sprite" && explosionName != "WizardIceProjectileExplosion_Sprite") + this.Rotation = 0; + Tweener.Tween.RunFunction(0.5f, this, "KillProjectile"); + break; + } + } + } + + public void ActivateEffect() + { + switch (Spell) + { + case (SpellType.TimeBomb): + //this.RunDestroyAnimation(false); + this.IsWeighted = false; + this.ChangeSprite("SpellTimeBombExplosion_Sprite"); + this.PlayAnimation(false); + this.IsDying = true; + this.CollisionTypeTag = GameTypes.CollisionType_GLOBAL_DAMAGE_WALL; + this.AnimationDelay = 1 / 30f; + this.Scale = new Vector2(4, 4); + Tweener.Tween.RunFunction(0.5f, this, "KillProjectile"); + (Game.ScreenManager.CurrentScreen as ProceduralLevelScreen).ImpactEffectPool.DisplayExplosionEffect(this.Position); + break; + case (SpellType.Nuke): + this.RunDestroyAnimation(false); + (Game.ScreenManager.CurrentScreen as ProceduralLevelScreen).DamageAllEnemies((int)this.Damage); + (Game.ScreenManager.CurrentScreen as ProceduralLevelScreen).ImpactEffectPool.DisplayDeathEffect(this.Position); + break; + case (SpellType.Displacer): + this.RunDestroyAnimation(false); + PlayerObj player = (Game.ScreenManager.CurrentScreen as ProceduralLevelScreen).Player; + //(Game.ScreenManager.CurrentScreen as ProceduralLevelScreen).ImpactEffectPool.StartInverseEmit; + player.Translocate(this.Position); + break; + case (SpellType.Boomerang): + case (SpellType.Bounce): + this.CollisionTypeTag = GameTypes.CollisionType_GLOBAL_DAMAGE_WALL; + break; + case (SpellType.Laser): + this.CollisionTypeTag = GameTypes.CollisionType_GLOBAL_DAMAGE_WALL; + this.LifeSpan = AltY; + m_elapsedLifeSpan = 0; + this.IsCollidable = true; + this.Opacity = 1; + break; + } + } + + public void KillProjectile() + { + IsAlive = false; + IsDying = false; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + this.Target = null; + AttachedIcon = null; + Source = null; + base.Dispose(); + } + } + + protected override GameObj CreateCloneInstance() + { + return new ProjectileObj(_spriteName); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + ProjectileObj clone = obj as ProjectileObj; + clone.Target = this.Target; + clone.CollidesWithTerrain = this.CollidesWithTerrain; + clone.ChaseTarget = this.ChaseTarget; + clone.FollowArc = this.FollowArc; + clone.ShowIcon = this.ShowIcon; + clone.DestroysWithTerrain = this.DestroysWithTerrain; + clone.AltX = this.AltX; + clone.AltY = this.AltY; + clone.Spell = this.Spell; + clone.IgnoreBoundsCheck = this.IgnoreBoundsCheck; + clone.DestroysWithEnemy = this.DestroysWithEnemy; + clone.DestroyOnRoomTransition = this.DestroyOnRoomTransition; + clone.Source = this.Source; + clone.CanBeFusRohDahed = this.CanBeFusRohDahed; + clone.WrapProjectile = this.WrapProjectile; + clone.IgnoreInvincibleCounter = this.IgnoreInvincibleCounter; + } + + public bool IsDemented + { + get + { + EnemyObj enemy = Source as EnemyObj; + if (enemy != null && enemy.IsDemented == true) + return true; + return false; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/RaindropObj.cs b/RogueCastle/src/Game Objects/RaindropObj.cs new file mode 100644 index 0000000..0e8b4dd --- /dev/null +++ b/RogueCastle/src/Game Objects/RaindropObj.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class RaindropObj : SpriteObj + { + private float m_speedY, m_speedX; + public bool IsCollidable { get; set; } + private Vector2 m_startingPos; + public Vector2 MaxYSpeed { get; set; } + public Vector2 MaxXSpeed { get; set; } + + private bool m_splashing = false; + private bool m_isSnowflake = false; + private bool m_isParticle = false; + + public RaindropObj(Vector2 startingPos) + : base("Raindrop_Sprite") + { + ChangeToRainDrop(); + + m_speedY = CDGMath.RandomFloat(MaxYSpeed.X, MaxYSpeed.Y); + m_speedX = CDGMath.RandomFloat(MaxXSpeed.X, MaxXSpeed.Y); + IsCollidable = true; + m_startingPos = startingPos; + this.Position = m_startingPos; + AnimationDelay = 1/30f; + this.Scale = new Vector2(2, 2); + //this.TextureColor = new Color(136, 180, 182); + } + + public void ChangeToSnowflake() + { + this.ChangeSprite("Snowflake_Sprite"); + m_isSnowflake = true; + m_isParticle = false; + this.Rotation = 0; + MaxYSpeed = new Vector2(200, 400); + MaxXSpeed = new Vector2(-200, 0); + this.Position = m_startingPos; + m_speedY = CDGMath.RandomFloat(MaxYSpeed.X, MaxYSpeed.Y); + m_speedX = CDGMath.RandomFloat(MaxXSpeed.X, MaxXSpeed.Y); + } + + public void ChangeToRainDrop() + { + m_isSnowflake = false; + m_isParticle = false; + MaxYSpeed = new Vector2(800, 1200); + MaxXSpeed = new Vector2(-200, -200); + this.Rotation = 5; + m_speedY = CDGMath.RandomFloat(MaxYSpeed.X, MaxYSpeed.Y); + m_speedX = CDGMath.RandomFloat(MaxXSpeed.X, MaxXSpeed.Y); + } + + public void ChangeToParticle() + { + m_isSnowflake = false; + m_isParticle = true; + MaxYSpeed = new Vector2(0, 0); + MaxXSpeed = new Vector2(500, 1500); + this.Rotation = -90; + m_speedY = CDGMath.RandomFloat(MaxYSpeed.X, MaxYSpeed.Y); + m_speedX = CDGMath.RandomFloat(MaxXSpeed.X, MaxXSpeed.Y); + float randScale = CDGMath.RandomFloat(2, 8); + this.Scale = new Vector2(randScale, randScale); + } + + public void Update(List collisionList, GameTime gameTime) + { + if (m_splashing == false) + { + float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds; + this.Y += m_speedY * elapsedTime; + this.X += m_speedX * elapsedTime; + + if (IsCollidable == true) + { + Rectangle thisBounds = this.Bounds; // Optimization. Getting this.Bounds hits memory and it's an expensive function + + foreach (TerrainObj obj in collisionList) + { + TerrainObj copyObj = obj; // Optimization -> obj is a reference - rather than hit memory to access values, we'll cache it + Rectangle objBounds = copyObj.Bounds; // Optimization. Bounds is an expensive calc. + + if (copyObj.Visible == true && copyObj.CollidesTop == true && copyObj.Y > 120 && CollisionMath.Intersects(thisBounds, objBounds)) + { + if (copyObj.Rotation == 0) + { + if (m_isSnowflake == false) + this.Y = objBounds.Top - 10; + RunSplashAnimation(); + } + else if (copyObj.Rotation != 0) + { + if (CollisionMath.RotatedRectIntersects(thisBounds, 0, Vector2.Zero, new Rectangle((int)copyObj.X, (int)copyObj.Y, copyObj.Width, copyObj.Height), copyObj.Rotation, Vector2.Zero)) + { + if (m_isSnowflake == false) + this.Y -= 12; + RunSplashAnimation(); + } + } + break; + } + } + } + + if (this.Y > 720) + RunSplashAnimation(); // force kill the raindrop. + } + + if (this.IsAnimating == false && m_splashing == true && m_isSnowflake == false) + KillDrop(); + } + + public void UpdateNoCollision(GameTime gameTime) + { + float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds; + this.Y += m_speedY * elapsedTime; + this.X += m_speedX * elapsedTime; + + if ((this.X > m_startingPos.X + 4000) || (this.X < m_startingPos.X - 4000)) + KillDrop(); + + if ((this.Y > m_startingPos.Y + 4000) || (this.Y < m_startingPos.Y - 4000)) + KillDrop(); + } + + private void RunSplashAnimation() + { + //this.Scale = new Vector2(2, 2); + m_splashing = true; + this.Rotation = 0; + if (m_isSnowflake == false) + this.PlayAnimation(2, this.TotalFrames, false); + else + { + Tweener.Tween.To(this, 0.25f, Tweener.Tween.EaseNone, "Opacity", "0"); + Tweener.Tween.AddEndHandlerToLastTween(this, "KillDrop"); + } + } + + public void KillDrop() + { + //this.Scale = Vector2.One; + m_splashing = false; + this.GoToFrame(1); + this.Rotation = 5; + this.X = m_startingPos.X; + this.Y = CDGMath.RandomInt(-100, 0); + if (m_isParticle == true) + { + this.Y = m_startingPos.Y; + this.Rotation = -90; + } + m_speedY = CDGMath.RandomFloat(MaxYSpeed.X, MaxYSpeed.Y); + m_speedX = CDGMath.RandomFloat(MaxXSpeed.X, MaxXSpeed.Y); + this.Opacity = 1; + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/ArenaBonusRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/ArenaBonusRoomObj.cs new file mode 100644 index 0000000..ca12c61 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/ArenaBonusRoomObj.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; + +namespace RogueCastle +{ + public class ArenaBonusRoom : BonusRoomObj + { + private ChestObj m_chest; + private float m_chestStartingY; + private bool m_chestRevealed = false; + + public override void Initialize() + { + foreach (GameObj obj in GameObjList) + { + if (obj is ChestObj) + { + m_chest = obj as ChestObj; + break; + } + } + + m_chest.ChestType = ChestType.Gold; + m_chestStartingY = m_chest.Y - 200 + m_chest.Height + 6; + + base.Initialize(); + } + + public override void OnEnter() + { + UpdateEnemyNames(); + + m_chest.Y = m_chestStartingY; + m_chest.ChestType = ChestType.Gold; + + if (RoomCompleted == true) + { + m_chest.Opacity = 1; + m_chest.Y = m_chestStartingY + 200; + m_chest.IsEmpty = true; + m_chest.ForceOpen(); + m_chestRevealed = true; + + foreach (EnemyObj enemy in EnemyList) + { + if (enemy.IsKilled == false) + enemy.KillSilently(); + } + } + else + { + if (ActiveEnemies == 0) + { + m_chest.Opacity = 1; + m_chest.Y = m_chestStartingY + 200; + m_chest.IsEmpty = false; + m_chest.IsLocked = false; + m_chestRevealed = true; + } + else + { + m_chest.Opacity = 0; + m_chest.Y = m_chestStartingY; + m_chest.IsLocked = true; + m_chestRevealed = false; + } + } + + if (m_chest.PhysicsMngr == null) + Player.PhysicsMngr.AddObject(m_chest); + + base.OnEnter(); + } + + private void UpdateEnemyNames() + { + bool firstNamed = false; + foreach (EnemyObj enemy in this.EnemyList) + { + if (enemy is EnemyObj_EarthWizard) + { + if (firstNamed == false) + { + enemy.Name = "Barbatos"; + enemy.LocStringID = "LOC_ID_ENEMY_NAME_106"; + firstNamed = true; + } + else + { + enemy.Name = "Amon"; + enemy.LocStringID = "LOC_ID_ENEMY_NAME_109"; + } + } + else if (enemy is EnemyObj_Skeleton) + { + if (firstNamed == false) + { + enemy.Name = "Berith"; + enemy.LocStringID = "LOC_ID_ENEMY_NAME_108"; + firstNamed = true; + } + else + { + enemy.Name = "Halphas"; + enemy.LocStringID = "LOC_ID_ENEMY_NAME_111"; + } + } + else if (enemy is EnemyObj_Plant) + { + if (firstNamed == false) + { + enemy.Name = "Stolas"; + enemy.LocStringID = "LOC_ID_ENEMY_NAME_107"; + firstNamed = true; + } + else + { + enemy.Name = "Focalor"; + enemy.LocStringID = "LOC_ID_ENEMY_NAME_110"; + } + } + } + + } + + public override void Update(GameTime gameTime) + { + if (m_chest.IsOpen == false) + { + if (ActiveEnemies == 0 && m_chest.Opacity == 0 && m_chestRevealed == false) + { + m_chestRevealed = true; + DisplayChest(); + } + } + else + { + if (RoomCompleted == false) + RoomCompleted = true; + } + + base.Update(gameTime); + } + + public override void OnExit() + { + bool skeletonMBKilled = false; + bool plantMBKilled = false; + bool paintingMBKilled = false; + bool knightMBKilled = false; + bool wizardMBKilled = false; + if (Game.PlayerStats.EnemiesKilledList[EnemyType.Skeleton].W > 0) + skeletonMBKilled = true; + if (Game.PlayerStats.EnemiesKilledList[EnemyType.Plant].W > 0) + plantMBKilled = true; + if (Game.PlayerStats.EnemiesKilledList[EnemyType.Portrait].W > 0) + paintingMBKilled = true; + if (Game.PlayerStats.EnemiesKilledList[EnemyType.Knight].W > 0) + knightMBKilled = true; + if (Game.PlayerStats.EnemiesKilledList[EnemyType.EarthWizard].W > 0) + wizardMBKilled = true; + + if (skeletonMBKilled && plantMBKilled && paintingMBKilled && knightMBKilled && wizardMBKilled) + GameUtil.UnlockAchievement("FEAR_OF_ANIMALS"); + + base.OnExit(); + } + + private void DisplayChest() + { + m_chest.IsLocked = false; + Tween.To(m_chest, 2, Tween.EaseNone, "Opacity", "1"); + Tween.By(m_chest, 2, Tweener.Ease.Quad.EaseOut, "Y", "200"); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_chest = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/BonusRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/BonusRoomObj.cs new file mode 100644 index 0000000..4ec3165 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/BonusRoomObj.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + public class BonusRoomObj : RoomObj + { + public bool RoomCompleted { get; set; } + + public BonusRoomObj() + { + this.ID = -1; + } + + public override void Reset() + { + RoomCompleted = false; + base.Reset(); + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/CarnivalShoot1BonusRoom.cs b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/CarnivalShoot1BonusRoom.cs new file mode 100644 index 0000000..17449cc --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/CarnivalShoot1BonusRoom.cs @@ -0,0 +1,505 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Tweener; +using InputSystem; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class CarnivalShoot1BonusRoom : BonusRoomObj + { + private GameObj m_line; + private List m_targetList; + private byte m_storedPlayerSpell; + private int m_daggersThrown = 0; + private float m_storedPlayerMana; + + private int m_currentTargetIndex; + private BreakableObj m_currentTarget; + private bool m_targetMovingUp = false; + private bool m_isPlayingGame = false; + private bool m_spokeToNPC = false; + + private NpcObj m_elf; + private ObjContainer m_daggerIcons; + private ObjContainer m_targetIcons; + + private int m_numTries = 12; + private int m_numTargets = 8; + private float m_targetSpeed = 200f; + private float m_targetSpeedMod = 100f; + + private List m_balloonList; + + private ChestObj m_rewardChest; + + public CarnivalShoot1BonusRoom() + { + m_elf = new NpcObj("Clown_Character"); + m_elf.Scale = new Vector2(2, 2); + m_balloonList = new List(); + } + + public override void LoadContent(Microsoft.Xna.Framework.Graphics.GraphicsDevice graphics) + { + m_daggerIcons = new ObjContainer(); + int daggerX = 0; + int daggerY = 10; + for (int i = 0; i < m_numTries; i++) + { + SpriteObj dagger = new SpriteObj("SpellDagger_Sprite"); + dagger.Scale = new Vector2(2, 2); + dagger.X = daggerX + 10; + dagger.Y = daggerY; + + daggerX += dagger.Width; + if (i == m_numTries / 2 - 1) + { + daggerX = 0; + daggerY += 20; + } + + m_daggerIcons.AddChild(dagger); + } + m_daggerIcons.OutlineWidth = 2; + + m_targetIcons = new ObjContainer(); + for (int i = 0; i < m_numTargets; i++) + { + SpriteObj target = new SpriteObj("Target2Piece1_Sprite"); + target.Scale = new Vector2(2, 2); + target.X += i * (target.Width + 10); + m_targetIcons.AddChild(target); + } + m_targetIcons.OutlineWidth = 2; + + GameObjList.Add(m_targetIcons); + GameObjList.Add(m_daggerIcons); + + base.LoadContent(graphics); + } + + public override void Initialize() + { + Color[] randomColours = new Color[] { Color.Red, Color.Blue, Color.Green, Color.Yellow, Color.Orange, Color.Purple, Color.Pink, Color.MediumTurquoise, Color.CornflowerBlue }; + + foreach (GameObj obj in this.GameObjList) + { + if (obj is WaypointObj) + m_elf.X = obj.X; + + if (obj.Name == "Line") + m_line = obj; + + if (obj.Name == "Balloon") + { + m_balloonList.Add(obj as ObjContainer); + (obj as ObjContainer).GetChildAt(1).TextureColor = randomColours[CDGMath.RandomInt(0, randomColours.Length - 1)]; + } + } + + float floorY = 0; + + foreach (TerrainObj terrain in TerrainObjList) + { + if (terrain.Name == "Floor") + { + m_elf.Y = terrain.Y - (m_elf.Bounds.Bottom - m_elf.Y); + floorY = terrain.Y; + break; + } + } + + if (IsReversed == false) + m_elf.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + GameObjList.Add(m_elf); + m_elf.Y -= 2; + + m_targetList = new List(); + for (int i = 0; i < m_numTargets; i++) + { + BreakableObj breakableObj = new BreakableObj("Target1_Character"); + breakableObj.Scale = new Vector2(2, 2); + breakableObj.Visible = false; + breakableObj.DropItem = false; + breakableObj.HitBySpellsOnly = true; + breakableObj.Position = m_line.Position; + if (this.IsReversed == false) + breakableObj.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + else + breakableObj.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.None; + m_targetList.Add(breakableObj); + GameObjList.Add(breakableObj); + } + + m_rewardChest = new ChestObj(null); + m_rewardChest.ChestType = ChestType.Gold; + if (this.IsReversed == false) + { + m_rewardChest.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + m_rewardChest.Position = new Vector2(m_elf.X + 100, floorY - m_rewardChest.Height - 8); + } + else + m_rewardChest.Position = new Vector2(m_elf.X - 150, floorY - m_rewardChest.Height - 8); + m_rewardChest.Visible = false; + GameObjList.Add(m_rewardChest); + + base.Initialize(); + } + + public override void OnEnter() + { + // Force this chest to be gold. + m_rewardChest.ChestType = ChestType.Gold; + + // This shouldn't be needed since the chest is added to the GameObjList + if (m_rewardChest.PhysicsMngr == null) + Player.PhysicsMngr.AddObject(m_rewardChest); + + m_spokeToNPC = false; + Player.AttachedLevel.CameraLockedToPlayer = false; + if (IsReversed == false) + Player.AttachedLevel.Camera.Position = new Vector2(this.Bounds.Left + Player.AttachedLevel.Camera.Width / 2, this.Bounds.Top + Player.AttachedLevel.Camera.Height / 2); + else + Player.AttachedLevel.Camera.Position = new Vector2(this.Bounds.Right - Player.AttachedLevel.Camera.Width / 2, this.Bounds.Top + Player.AttachedLevel.Camera.Height / 2); + + m_currentTargetIndex = 0; + m_daggersThrown = 0; + m_storedPlayerMana = Player.CurrentMana; + m_storedPlayerSpell = Game.PlayerStats.Spell; + + InitializeTargetSystem(); + + if (this.IsReversed == false) + { + m_targetIcons.Position = new Vector2(this.Bounds.Right - 100 - m_targetIcons.Width, this.Bounds.Bottom - 40); + m_daggerIcons.Position = m_targetIcons.Position; + m_daggerIcons.X -= 400 + m_daggerIcons.Width; + } + else + { + m_targetIcons.Position = new Vector2(this.Bounds.Left + 150, this.Bounds.Bottom - 40); + m_daggerIcons.Position = m_targetIcons.Position; + m_daggerIcons.X += m_targetIcons.Width + 400; + } + m_daggerIcons.Y -= 30; + + ReflipPosters(); + base.OnEnter(); + } + + private void ReflipPosters() + { + foreach (GameObj obj in GameObjList) + { + SpriteObj sprite = obj as SpriteObj; + if (sprite != null && sprite.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally) + { + if (sprite.SpriteName == "CarnivalPoster1_Sprite" || sprite.SpriteName == "CarnivalPoster2_Sprite" || sprite.SpriteName == "CarnivalPoster3_Sprite" + || sprite.SpriteName == "CarnivalTent_Sprite") + sprite.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.None; + } + } + } + + public void BeginGame() + { + Player.AttachedLevel.ProjectileManager.DestroyAllProjectiles(true); + Player.StopAllSpells(); + m_isPlayingGame = true; + m_spokeToNPC = true; + + Player.AttachedLevel.CameraLockedToPlayer = false; + Player.AttachedLevel.Camera.Y = this.Bounds.Center.Y; + if (this.IsReversed == false) + Tween.To(Player.AttachedLevel.Camera, 1, Tweener.Ease.Quad.EaseInOut, "X", (m_line.X + 500).ToString()); + else + Tween.To(Player.AttachedLevel.Camera, 1, Tweener.Ease.Quad.EaseInOut, "X", (m_line.X - 500).ToString()); + EquipPlayer(); + ActivateTarget(); + } + + public void EndGame() + { + if (this.IsReversed == false) + Tween.To(Player.AttachedLevel.Camera, 1, Tweener.Ease.Quad.EaseInOut, "X", (this.X + Player.AttachedLevel.Camera.Width/2f).ToString()); + else + Tween.To(Player.AttachedLevel.Camera, 1, Tweener.Ease.Quad.EaseInOut, "X", (this.Bounds.Right - Player.AttachedLevel.Camera.Width/2f).ToString()); + + Tween.AddEndHandlerToLastTween(this, "CheckPlayerReward"); + m_isPlayingGame = false; + Game.PlayerStats.Spell = SpellType.None; + Player.AttachedLevel.UpdatePlayerSpellIcon(); + this.RoomCompleted = true; + } + + public void CheckPlayerReward() + { + if (ActiveTargets <= 0) + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("CarnivalRoom1-Reward"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true, null); + RevealChest(); + GameUtil.UnlockAchievement("LOVE_OF_CLOWNS"); + } + else + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("CarnivalRoom1-Fail"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true, null); + } + } + + public void RevealChest() + { + Player.AttachedLevel.ImpactEffectPool.DisplayDeathEffect(m_rewardChest.Position); + m_rewardChest.Visible = true; + } + + private void InitializeTargetSystem() + { + foreach (BreakableObj obj in m_targetList) + { + obj.Reset(); + obj.Visible = false; + if (this.IsReversed == false) + { + obj.Position = new Vector2(this.Bounds.Right, this.Bounds.Center.Y); + obj.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + } + else + { + obj.Position = new Vector2(this.Bounds.Left, this.Bounds.Center.Y); + obj.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.None; + } + } + } + + private void EquipPlayer() + { + Game.PlayerStats.Spell = SpellType.Dagger; + Player.AttachedLevel.UpdatePlayerSpellIcon(); + Player.CurrentMana = Player.MaxMana; + } + + public void UnequipPlayer() + { + Game.PlayerStats.Spell = m_storedPlayerSpell; + Player.AttachedLevel.UpdatePlayerSpellIcon(); + Player.CurrentMana = m_storedPlayerMana; + } + + public override void OnExit() + { + UnequipPlayer(); + Player.AttachedLevel.CameraLockedToPlayer = true; + base.OnExit(); + } + + private void HandleInput() + { + if (m_isPlayingGame == true) + { + if ((Game.GlobalInput.JustPressed(InputMapType.PLAYER_SPELL1) || (Game.GlobalInput.JustPressed(InputMapType.PLAYER_ATTACK) && Game.PlayerStats.Class== ClassType.Dragon)) + && Player.SpellCastDelay <= 0) + { + m_daggersThrown++; + Player.CurrentMana = Player.MaxMana; + if (m_daggersThrown <= m_numTries) + m_daggerIcons.GetChildAt(m_numTries - m_daggersThrown).Visible = false; + if (m_daggersThrown > m_numTries) + Game.PlayerStats.Spell = SpellType.None; + } + } + } + + public override void Update(GameTime gameTime) + { + m_elf.Update(gameTime, Player); + + // Bounds to prevent the player from moving past. + if (this.IsReversed == false) + { + if (Player.X >= m_line.X - 150) + Player.X = (int)m_line.X - 150; + } + else + { + if (Player.X < m_line.X + 150) + Player.X = m_line.X + 150; + } + + if (this.IsReversed == false) + { + if (m_isPlayingGame == true) + { + if (Player.X < Player.AttachedLevel.Camera.Bounds.Left) + Player.X = Player.AttachedLevel.Camera.Bounds.Left; + } + if (Player.X > this.Bounds.Right - 1320) + Player.X = this.Bounds.Right - 1320; + } + else + { + if (m_isPlayingGame == true) + { + if (Player.X > Player.AttachedLevel.Camera.Bounds.Right) + Player.X = Player.AttachedLevel.Camera.Bounds.Right; + } + if (Player.X < this.Bounds.Left + 1320) + Player.X = this.Bounds.Left + 1320; + } + + // Target active logic. + if (m_currentTarget != null && m_currentTarget.Broken == false) + { + float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds; + + // Moving up logic. + if (m_targetMovingUp == true && m_currentTarget.Bounds.Top > this.Bounds.Top + 80) // a little bigger than 60 so it doesn't get stuck. + m_currentTarget.Y -= elapsedTime * m_targetSpeed; + else if (m_targetMovingUp == true) + { + m_currentTarget.Y += elapsedTime * m_targetSpeed; + m_targetMovingUp = false; + } + + // Moving down logic. + if (m_targetMovingUp == false && m_currentTarget.Bounds.Bottom < this.Bounds.Bottom - 140) + m_currentTarget.Y += elapsedTime * m_targetSpeed; + else if (m_targetMovingUp == false) + { + m_currentTarget.Y -= elapsedTime * m_targetSpeed; + m_targetMovingUp = true; + } + } + + if (m_isPlayingGame == true) + { + if ((m_daggersThrown >= m_numTries && Player.AttachedLevel.ProjectileManager.ActiveProjectiles < 1 && ActiveTargets > 0) || ActiveTargets <= 0) + EndGame(); + } + + // Code that sets up the next target. + if (m_currentTarget != null && m_currentTarget.Broken == true && ActiveTargets >= 0) + { + m_currentTargetIndex++; + ActivateTarget(); + } + + // Elf code. + if (m_elf.IsTouching == true && RoomCompleted == false && m_spokeToNPC == false) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("CarnivalRoom1-Start"); + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "BeginGame"); + manager.DialogueScreen.SetCancelEndHandler(typeof(Console), "WriteLine", "Canceling Selection"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true, null); + } + } + else if (m_elf.IsTouching == true && RoomCompleted == true) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("CarnivalRoom1-End"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true, null); + } + } + + if (m_isPlayingGame == true) + m_elf.CanTalk = false; + else + m_elf.CanTalk = true; + + // Rotating the balloons. + float totalSeconds = Game.TotalGameTime; + float rotationOffset = 2f; + foreach (ObjContainer balloon in m_balloonList) + { + balloon.Rotation = (float)Math.Sin(totalSeconds * rotationOffset) * rotationOffset; + rotationOffset += 0.2f; + } + + HandleInput(); // This has to go after everything. + + base.Update(gameTime); + } + + public void ActivateTarget() + { + // Target has been destroyed + if (m_numTargets - m_currentTargetIndex < m_targetIcons.NumChildren) + { + m_targetIcons.GetChildAt(m_numTargets - m_currentTargetIndex).Visible = false; + GiveGold(); + } + + if (m_currentTargetIndex < m_numTargets) + { + if (m_currentTarget != null) + m_targetSpeed += m_targetSpeedMod; + m_currentTarget = m_targetList[m_currentTargetIndex]; + m_currentTarget.Visible = true; + + if (this.IsReversed == false) + Tween.By(m_currentTarget, 2, Tweener.Ease.Quad.EaseOut, "X", (-400 + CDGMath.RandomInt(-200, 200)).ToString()); + else + Tween.By(m_currentTarget, 2, Tweener.Ease.Quad.EaseOut, "X", (400 + CDGMath.RandomInt(-200, 200)).ToString()); + } + else + m_currentTarget = null; + } + + public void GiveGold() + { + int numCoins = m_numTargets - ActiveTargets; + if (ActiveTargets > 0) + Player.AttachedLevel.ImpactEffectPool.CarnivalGoldEffect(m_currentTarget.Position, new Vector2(Player.AttachedLevel.Camera.TopLeftCorner.X + 50, Player.AttachedLevel.Camera.TopLeftCorner.Y + 135), numCoins); + Player.AttachedLevel.TextManager.DisplayNumberStringText(numCoins * 10, "LOC_ID_CARNIVAL_BONUS_ROOM_4" /*"gold"*/, Color.Yellow, m_currentTarget.Position); + Game.PlayerStats.Gold += numCoins * 10; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_targetList.Clear(); + m_targetList = null; + m_line = null; + m_currentTarget = null; + m_elf = null; + m_daggerIcons = null; + m_targetIcons = null; + + m_balloonList.Clear(); + m_balloonList = null; + + m_rewardChest = null; + base.Dispose(); + } + } + + private int ActiveTargets + { + get + { + int activeTargets = 0; + foreach (BreakableObj obj in m_targetList) + { + if (obj.Broken == false) + activeTargets++; + } + return activeTargets; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/CarnivalShoot2BonusRoom.cs b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/CarnivalShoot2BonusRoom.cs new file mode 100644 index 0000000..2aa0cfe --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/CarnivalShoot2BonusRoom.cs @@ -0,0 +1,593 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Tweener; +using DS2DEngine; +using Tweener.Ease; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class CarnivalShoot2BonusRoom: BonusRoomObj + { + private int m_numTries = 5; + + private Rectangle m_targetBounds; + private byte m_storedPlayerSpell; + private float m_storedPlayerMana; + private bool m_isPlayingGame; + private int m_axesThrown; + + private List m_targetList; + private ObjContainer m_axeIcons; + private NpcObj m_elf; + private PhysicsObj m_gate; + private bool m_gateClosed; + + private List m_targetDataText; + private List m_targetText; + + private List m_balloonList; + + private ChestObj m_rewardChest; + + public CarnivalShoot2BonusRoom() + { + m_targetList = new List(); + m_elf = new NpcObj("Clown_Character"); + m_elf.Scale = new Vector2(2, 2); + + m_targetText = new List(); + m_targetDataText = new List(); + m_balloonList = new List(); + } + + public override void LoadContent(Microsoft.Xna.Framework.Graphics.GraphicsDevice graphics) + { + TextObj genericText = new TextObj(Game.JunicodeFont); + genericText.FontSize = 25; + genericText.Text = "test text"; // placeholder text + genericText.DropShadow = new Vector2(2, 2); + if (this.IsReversed == false) + genericText.Position = new Vector2(this.Bounds.Right - 1000, this.Bounds.Top + 200); + else + genericText.Position = new Vector2(this.Bounds.Left + 300, this.Bounds.Top + 200); + + for (int i = 0; i < 3; i++) + { + TextObj text = genericText.Clone() as TextObj; + text.Text = "";// LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", text); // dummy locID to add TextObj to language refresh list + text.Y += i * 100; + m_targetText.Add(text); + + TextObj data = genericText.Clone() as TextObj; + data.Text = "0";// LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", data); // dummy locID to add TextObj to language refresh list + data.Y += i * 100; + data.X = text.X + 500; + + m_targetDataText.Add(data); + } + + + m_axeIcons = new ObjContainer(); + int daggerX = 0; + int daggerY = 10; + for (int i = 0; i < m_numTries; i++) + { + SpriteObj dagger = new SpriteObj("SpellAxe_Sprite"); + dagger.Scale = new Vector2(2, 2); + dagger.X = daggerX + 10; + dagger.Y = daggerY; + + daggerX += dagger.Width + 5; + + m_axeIcons.AddChild(dagger); + } + m_axeIcons.OutlineWidth = 2; + this.GameObjList.Add(m_axeIcons); + base.LoadContent(graphics); + } + + public override void Initialize() + { + m_gate = new PhysicsObj("CastleEntranceGate_Sprite"); + m_gate.IsWeighted = false; + m_gate.IsCollidable = true; + m_gate.CollisionTypeTag = GameTypes.CollisionType_WALL; + m_gate.Layer = -1; + m_gate.OutlineWidth = 2; + this.GameObjList.Add(m_gate); + + Rectangle gatePosition = new Rectangle(); + + Color[] randomColours = new Color[] { Color.Red, Color.Blue, Color.Green, Color.Yellow, Color.Orange, Color.Purple, Color.Pink, Color.MediumTurquoise, Color.CornflowerBlue }; + + foreach (GameObj obj in this.GameObjList) + { + if (obj is WaypointObj) + m_elf.X = obj.X; + + if (obj.Name == "Balloon") + { + m_balloonList.Add(obj as ObjContainer); + (obj as ObjContainer).GetChildAt(1).TextureColor = randomColours[CDGMath.RandomInt(0, randomColours.Length - 1)]; + } + } + + // Positioning gate. + foreach (TerrainObj terrain in TerrainObjList) + { + if (terrain.Name == "Floor") + m_elf.Y = terrain.Y - (m_elf.Bounds.Bottom - m_elf.Y) - 2; + + if (terrain.Name == "GatePosition") + gatePosition = terrain.Bounds; + } + + m_gate.X = gatePosition.X; + m_gate.Y = gatePosition.Bottom; + + if (IsReversed == false) + m_elf.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + GameObjList.Add(m_elf); + + foreach (TerrainObj obj in TerrainObjList) + { + if (obj.Name == "Boundary") + { + obj.Visible = false; + m_targetBounds = obj.Bounds; + break; + } + } + + float arraySize = 10; + float startingX = m_targetBounds.X + 40; + float startingY = m_targetBounds.Y; + float xDiff = m_targetBounds.Width / arraySize; + float yDiff = m_targetBounds.Height / arraySize; + for (int i = 0; i < arraySize * arraySize; i++) + { + BreakableObj target = new BreakableObj("Target2_Character"); + target.X = startingX; + target.Y = startingY; + target.Scale = new Vector2(1.6f, 1.6f); + target.OutlineWidth = 2; + target.HitBySpellsOnly = true; + target.IsWeighted = false; + m_targetList.Add(target); + target.SameTypesCollide = false; + target.DropItem = false; + GameObjList.Add(target); + startingX += xDiff; + + if ((i + 1) % arraySize == 0) + { + startingX = m_targetBounds.X + 40; + startingY += yDiff; + } + } + + m_rewardChest = new ChestObj(null); + m_rewardChest.ChestType = ChestType.Gold; + if (this.IsReversed == false) + { + m_rewardChest.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + m_rewardChest.Position = new Vector2(m_elf.X + 100, m_elf.Bounds.Bottom - m_rewardChest.Height - 8); + } + else + m_rewardChest.Position = new Vector2(m_elf.X - 150, m_elf.Bounds.Bottom - m_rewardChest.Height - 8); + m_rewardChest.Visible = false; + GameObjList.Add(m_rewardChest); + + base.Initialize(); + } + + public override void OnEnter() + { + // Force this chest to be gold. + m_rewardChest.ChestType = ChestType.Gold; + + if (IsReversed == false) + m_axeIcons.Position = new Vector2(this.Bounds.Right - 200 - m_axeIcons.Width, this.Bounds.Bottom -60); + else + m_axeIcons.Position = new Vector2(this.Bounds.Left + 900, this.Bounds.Bottom - 60); + + try + { + m_targetText[0].ChangeFontNoDefault(m_targetText[0].defaultFont); + m_targetText[1].ChangeFontNoDefault(m_targetText[1].defaultFont); + m_targetText[2].ChangeFontNoDefault(m_targetText[2].defaultFont); + m_targetText[0].Text = LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_1") + ":"; //"Targets Destroyed:" + m_targetText[1].Text = LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_2") + ":"; //"Targets Remaining:" + m_targetText[2].Text = LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_3") + ":"; //"Reward:" + } + catch + { + m_targetText[0].ChangeFontNoDefault(Game.NotoSansSCFont); + m_targetText[1].ChangeFontNoDefault(Game.NotoSansSCFont); + m_targetText[2].ChangeFontNoDefault(Game.NotoSansSCFont); + m_targetText[0].Text = LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_1") + ":"; //"Targets Destroyed:" + m_targetText[1].Text = LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_2") + ":"; //"Targets Remaining:" + m_targetText[2].Text = LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_3") + ":"; //"Reward:" + } + + m_targetDataText[0].Text = "50"; // placeholder text + m_targetDataText[1].Text = "10"; // placeholder text + m_targetDataText[2].Text = "100 gold"; // placeholder text + + for (int i = 0; i < m_targetText.Count; i++) + { + m_targetText[i].Opacity = 0; + m_targetDataText[i].Opacity = 0; + } + + foreach (BreakableObj obj in m_targetList) + { + obj.Opacity = 0; + obj.Visible = false; + } + + m_gateClosed = true; + m_storedPlayerSpell = Game.PlayerStats.Spell; + m_storedPlayerMana = Player.CurrentMana; + + ReflipPosters(); + base.OnEnter(); + } + + private void ReflipPosters() + { + foreach (GameObj obj in GameObjList) + { + SpriteObj sprite = obj as SpriteObj; + if (sprite != null && sprite.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally) + { + if (sprite.SpriteName == "CarnivalPoster1_Sprite" || sprite.SpriteName == "CarnivalPoster2_Sprite" || sprite.SpriteName == "CarnivalPoster3_Sprite" + || sprite.SpriteName == "CarnivalTent_Sprite") + sprite.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.None; + } + } + } + + public override void OnExit() + { + Game.PlayerStats.Spell = m_storedPlayerSpell; + Player.AttachedLevel.UpdatePlayerSpellIcon(); + Player.CurrentMana = m_storedPlayerMana; + base.OnExit(); + } + + public void BeginGame() + { + Player.AttachedLevel.ProjectileManager.DestroyAllProjectiles(true); + Player.StopAllSpells(); + m_gateClosed = false; + Tween.By(m_gate, 0.5f, Quad.EaseInOut, "Y", (-(m_gate.Height)).ToString()); + m_isPlayingGame = true; + EquipPlayer(); + + float delay = 0; + foreach (BreakableObj obj in m_targetList) + { + obj.Visible = true; + Tween.To(obj, 0.5f, Tween.EaseNone, "delay", delay.ToString(), "Opacity", "1"); + delay += 0.01f; + } + } + + private void EndGame() + { + Player.LockControls(); + Player.CurrentSpeed = 0; + foreach (BreakableObj obj in m_targetList) + Tween.To(obj, 0.5f, Tween.EaseNone, "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "EndGame2"); + + m_isPlayingGame = false; + } + + public void EndGame2() + { + int gold = (int)(TargetsDestroyed / 2f) * 10; + + try + { + m_targetDataText[0].ChangeFontNoDefault(m_targetDataText[0].defaultFont); + m_targetDataText[1].ChangeFontNoDefault(m_targetDataText[1].defaultFont); + m_targetDataText[2].ChangeFontNoDefault(m_targetDataText[2].defaultFont); + m_targetDataText[0].Text = TargetsDestroyed.ToString(); + m_targetDataText[1].Text = TargetsRemaining.ToString(); + m_targetDataText[2].Text = gold + " " + LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_4"); //"gold" + } + catch + { + m_targetDataText[0].ChangeFontNoDefault(Game.NotoSansSCFont); + m_targetDataText[1].ChangeFontNoDefault(Game.NotoSansSCFont); + m_targetDataText[2].ChangeFontNoDefault(Game.NotoSansSCFont); + m_targetDataText[0].Text = TargetsDestroyed.ToString(); + m_targetDataText[1].Text = TargetsRemaining.ToString(); + m_targetDataText[2].Text = gold + " " + LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_4"); //"gold" + } + + float delay = 0; + for (int i = 0; i < m_targetDataText.Count; i++) + { + Tween.To(m_targetText[i], 0.5f, Tween.EaseNone, "delay", delay.ToString(), "Opacity", "1"); + Tween.To(m_targetDataText[i], 0.5f, Tween.EaseNone, "delay", delay.ToString(), "Opacity", "1"); + delay += 0.5f; + } + + Tween.AddEndHandlerToLastTween(this, "GiveReward", gold); + } + + public void GiveReward(int gold) + { + if ((this.IsReversed == false && Player.X < this.Bounds.Right - Player.AttachedLevel.Camera.Width / 2f) || (this.IsReversed == true && Player.X > this.Bounds.Left + Player.AttachedLevel.Camera.Width / 2f)) + { + Tween.To(Player.AttachedLevel.Camera, 0.5f, Quad.EaseInOut, "X", Player.X.ToString()); + Tween.AddEndHandlerToLastTween(this, "ResetCamera"); + } + else + this.ResetCamera(); + + Player.AttachedLevel.TextManager.DisplayNumberStringText(gold, "LOC_ID_CARNIVAL_BONUS_ROOM_4" /*"gold"*/, Color.Yellow, Player.Position); + Game.PlayerStats.Gold += gold; + Tween.By(m_gate, 0.5f, Quad.EaseInOut, "Y", (-(m_gate.Height)).ToString()); + m_gateClosed = false; + this.RoomCompleted = true; + + Tween.AddEndHandlerToLastTween(this, "CheckPlayerReward"); + } + + + public void CheckPlayerReward() + { + if (TargetsRemaining <= 10) + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("CarnivalRoom2-Reward"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true, null); + RevealChest(); + GameUtil.UnlockAchievement("LOVE_OF_CLOWNS"); + } + else + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("CarnivalRoom2-Fail"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true, null); + } + } + + public void RevealChest() + { + Player.AttachedLevel.ImpactEffectPool.DisplayDeathEffect(m_rewardChest.Position); + m_rewardChest.Visible = true; + } + + public void ResetCamera() + { + Player.UnlockControls(); + Player.AttachedLevel.CameraLockedToPlayer = true; + } + + + private void EquipPlayer() + { + Game.PlayerStats.Spell = SpellType.Axe; + Player.AttachedLevel.UpdatePlayerSpellIcon(); + Player.CurrentMana = Player.MaxMana; + } + + public void UnequipPlayer() + { + Game.PlayerStats.Spell = m_storedPlayerSpell; + Player.AttachedLevel.UpdatePlayerSpellIcon(); + Player.CurrentMana = m_storedPlayerMana; + } + + public override void Update(GameTime gameTime) + { + if ((m_axesThrown >= m_numTries && m_isPlayingGame == true && Player.AttachedLevel.ProjectileManager.ActiveProjectiles < 1) ||(m_isPlayingGame == true && TargetsDestroyed >= 100)) + EndGame(); + + if (m_isPlayingGame == true && m_gateClosed == false) + { + if ((this.IsReversed == false && Player.X > m_gate.Bounds.Right) || (this.IsReversed == true && Player.X < m_gate.Bounds.Left)) + { + Player.LockControls(); + Player.CurrentSpeed = 0; + Player.AccelerationX = 0; + Tween.By(m_gate, 0.5f, Quad.EaseInOut, "Y", m_gate.Height.ToString()); + Tween.AddEndHandlerToLastTween(Player, "UnlockControls"); + m_gateClosed = true; + Player.AttachedLevel.CameraLockedToPlayer = false; + if (this.IsReversed == false) + Tween.To(Player.AttachedLevel.Camera, 1f, Quad.EaseInOut, "X", (this.Bounds.Right - Player.AttachedLevel.Camera.Width / 2f).ToString()); + else + Tween.To(Player.AttachedLevel.Camera, 1f, Quad.EaseInOut, "X", (this.Bounds.Left + Player.AttachedLevel.Camera.Width / 2f).ToString()); + } + } + + // Elf code. + m_elf.Update(gameTime, Player); + + if (m_isPlayingGame == true) + m_elf.CanTalk = false; + else + m_elf.CanTalk = true; + + if (m_elf.IsTouching == true && RoomCompleted == false && m_isPlayingGame == false) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("CarnivalRoom2-Start"); + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "BeginGame"); + manager.DialogueScreen.SetCancelEndHandler(typeof(Console), "WriteLine", "Canceling Selection"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true, null); + } + } + else if (m_elf.IsTouching == true && RoomCompleted == true) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("CarnivalRoom1-End"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true, null); + } + } + + if (IsReversed == false && m_isPlayingGame == true && Player.X < this.Bounds.Left + 10) + Player.X = this.Bounds.Left + 10; + else if (IsReversed == true && m_isPlayingGame == true && Player.X > this.Bounds.Right - 10) + Player.X = this.Bounds.Right - 10; + + // Rotating the balloons. + float totalSeconds = Game.TotalGameTime; + float rotationOffset = 2f; + foreach (ObjContainer balloon in m_balloonList) + { + balloon.Rotation = (float)Math.Sin(totalSeconds * rotationOffset) * rotationOffset; + rotationOffset += 0.2f; + } + + HandleInput(); + base.Update(gameTime); + } + + private void HandleInput() + { + if (m_isPlayingGame == true) + { + if ((Game.GlobalInput.JustPressed(InputMapType.PLAYER_SPELL1) || (Game.GlobalInput.JustPressed(InputMapType.PLAYER_ATTACK) && Game.PlayerStats.Class== ClassType.Dragon)) + && Player.SpellCastDelay <= 0 && m_gateClosed == true) + { + m_axesThrown++; + Player.CurrentMana = Player.MaxMana; + if (m_axesThrown <= m_numTries) + m_axeIcons.GetChildAt(m_numTries - m_axesThrown).Visible = false; + if (m_axesThrown > m_numTries) + Game.PlayerStats.Spell = SpellType.None; + } + } + } + + public override void Draw(Camera2D camera) + { + base.Draw(camera); + camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap; + + for (int i = 0; i < m_targetText.Count; i++) + { + m_targetText[i].Draw(camera); + m_targetDataText[i].Draw(camera); + } + camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointWrap; + + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_targetList.Clear(); + m_targetList = null; + m_elf = null; + m_axeIcons = null; + m_gate = null; + + for (int i = 0; i < m_targetText.Count; i++) + { + m_targetText[i].Dispose(); + m_targetDataText[i].Dispose(); + } + m_targetText.Clear(); + m_targetText = null; + m_targetDataText.Clear(); + m_targetDataText = null; + m_balloonList.Clear(); + m_balloonList = null; + m_rewardChest = null; + base.Dispose(); + } + } + + public int TargetsDestroyed + { + get + { + int destroyed = 0; + foreach (BreakableObj obj in m_targetList) + { + if (obj.Broken == true) + destroyed++; + } + return destroyed; + } + } + + public int TargetsRemaining + { + get + { + int remaining = 0; + foreach (BreakableObj obj in m_targetList) + { + if (obj.Broken == false) + remaining++; + } + return remaining; + } + } + + public override void RefreshTextObjs() + { + m_targetText[0].ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_targetText[0])); + m_targetText[1].ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_targetText[1])); + m_targetText[2].ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_targetText[2])); + + m_targetDataText[0].ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_targetDataText[0])); + m_targetDataText[1].ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_targetDataText[1])); + m_targetDataText[2].ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_targetDataText[2])); + + + try + { + m_targetText[0].Text = LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_1") + ":"; //"Targets Destroyed:" + m_targetText[1].Text = LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_2") + ":"; //"Targets Remaining:" + m_targetText[2].Text = LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_3") + ":"; //"Reward:" + + int gold = (int)(TargetsDestroyed / 2f) * 10; + m_targetDataText[0].Text = TargetsDestroyed.ToString(); + m_targetDataText[1].Text = TargetsRemaining.ToString(); + m_targetDataText[2].Text = gold + " " + LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_4"); //"gold" + } + catch + { + m_targetText[0].ChangeFontNoDefault(Game.NotoSansSCFont); + m_targetText[1].ChangeFontNoDefault(Game.NotoSansSCFont); + m_targetText[2].ChangeFontNoDefault(Game.NotoSansSCFont); + + m_targetText[0].Text = LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_1") + ":"; //"Targets Destroyed:" + m_targetText[1].Text = LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_2") + ":"; //"Targets Remaining:" + m_targetText[2].Text = LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_3") + ":"; //"Reward:" + + m_targetDataText[0].ChangeFontNoDefault(Game.NotoSansSCFont); + m_targetDataText[1].ChangeFontNoDefault(Game.NotoSansSCFont); + m_targetDataText[2].ChangeFontNoDefault(Game.NotoSansSCFont); + + int gold = (int)(TargetsDestroyed / 2f) * 10; + m_targetDataText[0].Text = TargetsDestroyed.ToString(); + m_targetDataText[1].Text = TargetsRemaining.ToString(); + m_targetDataText[2].Text = gold + " " + LocaleBuilder.getResourceString("LOC_ID_CARNIVAL_BONUS_ROOM_4"); //"gold" + } + + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/ChestBonusRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/ChestBonusRoomObj.cs new file mode 100644 index 0000000..87c12ad --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/ChestBonusRoomObj.cs @@ -0,0 +1,274 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Tweener.Ease; +using Tweener; + +namespace RogueCastle +{ + public class ChestBonusRoomObj : BonusRoomObj + { + private const int TOTAL_UNLOCKED_CHESTS = 1; + + private bool m_paid = false; + private List m_chestList; + + private NpcObj m_elf; + private PhysicsObj m_gate; + + public ChestBonusRoomObj() + { + m_chestList = new List(); + m_elf = new NpcObj("Elf_Character"); + m_elf.Scale = new Vector2(2, 2); + + m_gate = new PhysicsObj("CastleEntranceGate_Sprite"); + m_gate.IsWeighted = false; + m_gate.IsCollidable = true; + m_gate.CollisionTypeTag = GameTypes.CollisionType_WALL; + m_gate.Layer = -1; + } + + public override void Initialize() + { + Vector2 gatePosition = Vector2.Zero; + Vector2 elfPosition = Vector2.Zero; + + foreach (GameObj obj in GameObjList) + { + if (obj is WaypointObj) + elfPosition.X = obj.X; + } + + foreach (TerrainObj terrain in TerrainObjList) + { + if (terrain.Name == "GatePosition") + gatePosition = new Vector2(terrain.X, terrain.Bounds.Bottom); + + if (terrain.Name == "Floor") + elfPosition.Y = terrain.Y; + } + + m_gate.Position = new Vector2(gatePosition.X, gatePosition.Y); + + if (IsReversed == false) + m_elf.Flip = SpriteEffects.FlipHorizontally; + m_elf.Position = new Vector2(elfPosition.X, elfPosition.Y - (m_elf.Bounds.Bottom - m_elf.AnchorY) - 2); + + GameObjList.Add(m_elf); + GameObjList.Add(m_gate); + + base.Initialize(); + } + + public override void OnEnter() + { + //if (this.ID != 1 && this.ID != 2 && this.ID != 3) + // ID = CDGMath.RandomInt(1, 3); + ID = 1; + + foreach (GameObj obj in GameObjList) + { + ChestObj chest = obj as ChestObj; + if (chest != null) + { + chest.ChestType = ChestType.Silver; + //if (ID == 1) + // chest.ChestType = ChestType.Brown; + //else if (ID == 2) + // chest.ChestType = ChestType.Silver; + //else + // chest.ChestType = ChestType.Gold; + chest.IsEmpty = true; + chest.IsLocked = true; + } + } + + (m_elf.GetChildAt(2) as SpriteObj).StopAnimation(); + base.OnEnter(); + } + + private void ShuffleChests(int goldPaid) + { + int[] chestRand = new int[] { 1, 2, 3}; + CDGMath.Shuffle(chestRand); + + int chestCounter = 0; + foreach (GameObj obj in GameObjList) + { + ChestObj chest = obj as ChestObj; + if (chest != null) + { + chest.ForcedItemType = ItemDropType.Coin; + int chestReward = chestRand[chestCounter]; + if (chestReward == 1) + chest.IsEmpty = true; + else if (chestReward == 2) + chest.IsEmpty = true; + else + { + chest.IsEmpty = false; + chest.ForcedAmount = goldPaid * 3f; + } + chestCounter++; + m_chestList.Add(chest); + chest.IsLocked = false; + + chest.TextureColor = Color.White; + if (chestReward == 3 && Game.PlayerStats.SpecialItem == SpecialItemType.Glasses) + chest.TextureColor = Color.Gold; + } + } + } + + public override void Update(GameTime gameTime) + { + m_elf.Update(gameTime, Player); + + if (RoomCompleted == false) + { + if (m_paid == true) + { + if (this.IsReversed == false && Player.X < (this.X + 50)) + Player.X = this.X + 50; + else if (this.IsReversed == true && Player.X > (this.X + this.Width - 50)) + Player.X = this.X + this.Width - 50; + } + + if (NumberOfChestsOpen >= TOTAL_UNLOCKED_CHESTS) + { + bool lostGame = false; + foreach (ChestObj chest in m_chestList) + { + if (chest.IsEmpty == true && chest.IsOpen == true) + lostGame = true; + chest.IsLocked = true; + } + + RoomCompleted = true; + + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + if (lostGame == false) + manager.DialogueScreen.SetDialogue("ChestBonusRoom1-Won"); + else + manager.DialogueScreen.SetDialogue("ChestBonusRoom1-Lost"); + Game.ScreenManager.DisplayScreen(ScreenType.Dialogue, true); + } + } + + HandleInput(); + + base.Update(gameTime); + } + + private void HandleInput() + { + if (m_elf.IsTouching == true) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + + if (RoomCompleted == false) + { + if (m_paid == false) + { + manager.DialogueScreen.SetDialogue("ChestBonusRoom" + this.ID + "-Start"); + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "PlayChestGame"); + manager.DialogueScreen.SetCancelEndHandler(typeof(Console), "WriteLine", "Canceling Selection"); + } + else + manager.DialogueScreen.SetDialogue("ChestBonusRoom1-Choose"); + } + else + manager.DialogueScreen.SetDialogue("ChestBonusRoom1-End"); + + Game.ScreenManager.DisplayScreen(ScreenType.Dialogue, true); + } + } + } + + public void PlayChestGame() + { + if (Game.PlayerStats.Gold >= 4) + { + m_paid = true; + float percent = 1; + if (ID == 1) + percent = 0.25f; + else if (ID == 2) + percent = 0.5f; + else + percent = 0.75f; + int goldPaid = (int)(Game.PlayerStats.Gold * percent); + Game.PlayerStats.Gold -= goldPaid; + ShuffleChests(goldPaid); + Player.AttachedLevel.TextManager.DisplayNumberStringText(-(int)goldPaid, "LOC_ID_CARNIVAL_BONUS_ROOM_4" /*"gold"*/, Color.Yellow, new Vector2(Player.X, Player.Bounds.Top)); + Tween.By(m_gate, 1, Quad.EaseInOut, "Y", (-m_gate.Height).ToString()); + } + else + { + (Player.AttachedLevel.ScreenManager as RCScreenManager).DialogueScreen.SetDialogue("ChestBonusRoom1-NoMoney"); + Tween.To(this, 0, Linear.EaseNone); + Tween.AddEndHandlerToLastTween(Player.AttachedLevel.ScreenManager, "DisplayScreen", ScreenType.Dialogue, true, typeof(List)); + } + } + + public override void Reset() + { + foreach (ChestObj chest in m_chestList) + chest.ResetChest(); + if (m_paid == true) + { + m_gate.Y += m_gate.Height; + m_paid = false; + } + base.Reset(); + } + + protected override GameObj CreateCloneInstance() + { + return new ChestBonusRoomObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_elf = null; + m_gate = null; + m_chestList.Clear(); + m_chestList = null; + + base.Dispose(); + } + } + + private int NumberOfChestsOpen + { + get + { + int numChestsOpen = 0; + foreach (ChestObj chest in m_chestList) + { + if (chest.IsOpen == true) + numChestsOpen++; + } + return numChestsOpen; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/DiaryRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/DiaryRoomObj.cs new file mode 100644 index 0000000..a7e6143 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/DiaryRoomObj.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; + +namespace RogueCastle +{ + public class DiaryRoomObj : BonusRoomObj + { + private SpriteObj m_speechBubble; + private SpriteObj m_diary; + private int m_diaryIndex = 0; + + public override void Initialize() + { + m_speechBubble = new SpriteObj("UpArrowSquare_Sprite"); + m_speechBubble.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + GameObjList.Add(m_speechBubble); + + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "diary") + { + m_diary = obj as SpriteObj; + break; + } + } + + m_diary.OutlineWidth = 2; + m_speechBubble.Position = new Vector2(m_diary.X, m_diary.Y - m_speechBubble.Height - 20); + + base.Initialize(); + } + + public override void OnEnter() + { + if (RoomCompleted == false) + m_speechBubble.Visible = true; + else + m_speechBubble.Visible = false; + + if (RoomCompleted == false) + m_diaryIndex = Game.PlayerStats.DiaryEntry; + + if (m_diaryIndex >= LevelEV.TOTAL_JOURNAL_ENTRIES - 1) + m_speechBubble.Visible = false; + + base.OnEnter(); + } + + public override void Update(GameTime gameTime) + { + m_speechBubble.Y = m_diary.Y - m_speechBubble.Height - 20 - 30 + (float)Math.Sin(Game.TotalGameTime * 20) * 2; + + Rectangle diaryBound = m_diary.Bounds; + diaryBound.X -= 50; + diaryBound.Width += 100; + + if (CollisionMath.Intersects(Player.Bounds, diaryBound) == false && m_speechBubble.SpriteName == "UpArrowSquare_Sprite") + m_speechBubble.ChangeSprite("ExclamationSquare_Sprite"); + + if (RoomCompleted == false || CollisionMath.Intersects(Player.Bounds, diaryBound) == true) + m_speechBubble.Visible = true; + else if (RoomCompleted == true && CollisionMath.Intersects(Player.Bounds, diaryBound) == false) + m_speechBubble.Visible = false; + + if (m_diaryIndex >= LevelEV.TOTAL_JOURNAL_ENTRIES - 1) + m_speechBubble.Visible = false; + + if (CollisionMath.Intersects(Player.Bounds, diaryBound) && Player.IsTouchingGround == true) + { + if (m_speechBubble.SpriteName == "ExclamationSquare_Sprite") + m_speechBubble.ChangeSprite("UpArrowSquare_Sprite"); + + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + if (RoomCompleted == false && Game.PlayerStats.DiaryEntry < LevelEV.TOTAL_JOURNAL_ENTRIES - 1) + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("DiaryEntry" + m_diaryIndex); + manager.DisplayScreen(ScreenType.Dialogue, true, null); + + Game.PlayerStats.DiaryEntry++; + RoomCompleted = true; + } + else + { + RoomCompleted = true; + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DisplayScreen(ScreenType.DiaryEntry, true); + } + } + } + + base.Update(gameTime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_diary = null; + m_speechBubble = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/JukeboxBonusRoom.cs b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/JukeboxBonusRoom.cs new file mode 100644 index 0000000..3538f8e --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/JukeboxBonusRoom.cs @@ -0,0 +1,204 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class JukeboxBonusRoom : BonusRoomObj + { + private GameObj m_jukeBox; + private string[] m_songList; + private string[] m_songTitleList; + private int m_songIndex; + private bool m_rotatedLeft; + private TextObj m_nowPlayingText; + private TextObj m_songTitle; + + private SpriteObj m_speechBubble; + + public JukeboxBonusRoom() + { + m_songList = new string[]{"CastleBossSong", "GardenSong", "GardenBossSong", "TowerSong", "TowerBossSong", + "DungeonSong", "DungeonBoss", "CastleSong", "PooyanSong", "LegacySong", "SkillTreeSong", "TitleScreenSong", + "CreditsSong", "LastBossSong", "EndSong", "EndSongDrums"}; + + m_songTitleList = new string[] {"Pistol Shrimp", "The Grim Outdoors", "Skin Off My Teeth", "Narwhal", "Lamprey", + "Broadside of the Broadsword", "Mincemeat", "Trilobyte", "Poot-yan", "SeaSawHorse (Legacy)", "SeaSawHorse (Manor)", "Rogue Legacy", + "The Fish and the Whale", "Rotten Legacy", "Whale. Shark.", "Whale. Shark. (Drums)"}; + } + + public override void Initialize() + { + m_speechBubble = new SpriteObj("UpArrowSquare_Sprite"); + m_speechBubble.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + m_speechBubble.Visible = false; + GameObjList.Add(m_speechBubble); + + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "Jukebox") + { + m_jukeBox = obj; + break; + } + } + + (m_jukeBox as SpriteObj).OutlineWidth = 2; + m_jukeBox.Y -= 2; + m_speechBubble.Position = new Vector2(m_jukeBox.X, m_jukeBox.Y - m_speechBubble.Height - 20); + + base.Initialize(); + } + + public override void LoadContent(Microsoft.Xna.Framework.Graphics.GraphicsDevice graphics) + { + m_songTitle = new TextObj(); + m_songTitle.Font = Game.JunicodeLargeFont; + m_songTitle.Align = Types.TextAlign.Right; + m_songTitle.Text = "Song name here"; + m_songTitle.Opacity = 0; + m_songTitle.FontSize = 40; + m_songTitle.Position = new Vector2(1320 - 50, 720 - 150); + m_songTitle.OutlineWidth = 2; + + m_nowPlayingText = m_songTitle.Clone() as TextObj; + m_nowPlayingText.Text = LocaleBuilder.getString("LOC_ID_JUKEBOX_BONUS_ROOM_1", m_nowPlayingText); // "Now Playing" + m_nowPlayingText.FontSize = 24; + m_nowPlayingText.Y -= 50; + + base.LoadContent(graphics); + } + + public override void OnEnter() + { + m_jukeBox.Scale = new Vector2(3, 3); + m_jukeBox.Rotation = 0; + base.OnEnter(); + } + + public override void Update(GameTime gameTime) + { + if (CollisionMath.Intersects(Player.Bounds, m_jukeBox.Bounds)) + { + m_speechBubble.Visible = true; + m_speechBubble.Y = m_jukeBox.Y - m_speechBubble.Height - 110 + (float)Math.Sin(Game.TotalGameTime * 20) * 2; + + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + Tween.StopAllContaining(m_jukeBox, false); + m_jukeBox.Scale = new Vector2(3, 3); + m_jukeBox.Rotation = 0; + + Tween.StopAllContaining(m_nowPlayingText, false); + Tween.StopAllContaining(m_songTitle, false); + m_songTitle.Opacity = 0; + m_nowPlayingText.Opacity = 0; + + Tween.To(m_songTitle, 0.5f, Linear.EaseNone, "delay", "0.2", "Opacity", "1"); + m_songTitle.Opacity = 1; // This is necessary because the tweener stores the initial value of the property when it is called. + Tween.To(m_songTitle, 0.5f, Linear.EaseNone, "delay", "2.2", "Opacity", "0"); + m_songTitle.Opacity = 0; + + Tween.To(m_nowPlayingText, 0.5f, Linear.EaseNone, "Opacity", "1"); + m_nowPlayingText.Opacity = 1; // This is necessary because the tweener stores the initial value of the property when it is called. + Tween.To(m_nowPlayingText, 0.5f, Linear.EaseNone, "delay", "2", "Opacity", "0"); + m_nowPlayingText.Opacity = 0; + + // Set the lineage screen song back to regular volume. If you enter this room after selecting a new lineage, its volume is set to 0. + if (m_songList[m_songIndex] == "LegacySong" && SoundManager.AudioEngine != null) + SoundManager.AudioEngine.GetCategory("Legacy").SetVolume(SoundManager.GlobalMusicVolume); + + SoundManager.PlayMusic(m_songList[m_songIndex], true, 1); + m_songTitle.Text = m_songTitleList[m_songIndex]; + m_songIndex++; + if (m_songIndex > m_songList.Length - 1) + m_songIndex = 0; + AnimateJukebox(); + + CheckForSongRepeat(); + } + } + else + m_speechBubble.Visible = false; + + base.Update(gameTime); + } + + // Checks to see if the song should keep playing or not when exiting the room. + private void CheckForSongRepeat() + { + //Console.WriteLine(this.LevelType); + //if (this.LevelType == GameTypes.LevelType.CASTLE && m_songList[m_songIndex] == "CastleSong" || + // this.LevelType == GameTypes.LevelType.DUNGEON && m_songList[m_songIndex] == "DungeonSong" || + // this.LevelType == GameTypes.LevelType.GARDEN && m_songList[m_songIndex] == "GardenSong" || + // this.LevelType == GameTypes.LevelType.TOWER && m_songList[m_songIndex] == "TowerSong") + // Game.ScreenManager.GetLevelScreen().DisableSongUpdating = false; + //else + Game.ScreenManager.GetLevelScreen().JukeboxEnabled = true; + } + + public void AnimateJukebox() + { + Tween.To(m_jukeBox, 0.2f, Tween.EaseNone, "ScaleY", "2.9", "ScaleX", "3.1", "Rotation", "0"); + Tween.AddEndHandlerToLastTween(this, "AnimateJukebox2"); + Player.AttachedLevel.ImpactEffectPool.DisplayMusicNote(new Vector2(m_jukeBox.Bounds.Center.X + CDGMath.RandomInt(-20, 20), m_jukeBox.Bounds.Top + CDGMath.RandomInt(0, 20))); + } + + public void AnimateJukebox2() + { + if (m_rotatedLeft == false) + { + Tween.To(m_jukeBox, 0.2f, Tween.EaseNone, "Rotation", "-2"); + m_rotatedLeft = true; + } + else + { + Tween.To(m_jukeBox, 0.2f, Tween.EaseNone, "Rotation", "2"); + m_rotatedLeft = false; + } + + Tween.To(m_jukeBox, 0.2f, Tween.EaseNone, "ScaleY", "3.1", "ScaleX", "2.9"); + Tween.AddEndHandlerToLastTween(this, "AnimateJukebox"); + } + + public override void Draw(Camera2D camera) + { + m_songTitle.Position = new Vector2(this.X + 1320 - 50, this.Y + 720 - 150); + m_nowPlayingText.Position = m_songTitle.Position; + m_nowPlayingText.Y -= 50; + + base.Draw(camera); + + SamplerState storedState = camera.GraphicsDevice.SamplerStates[0]; + camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + m_songTitle.Draw(camera); + m_nowPlayingText.Draw(camera); + camera.GraphicsDevice.SamplerStates[0] = storedState; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_songTitle.Dispose(); + m_songTitle = null; + m_nowPlayingText.Dispose(); + m_nowPlayingText = null; + m_jukeBox = null; + Array.Clear(m_songList, 0, m_songList.Length); + Array.Clear(m_songTitleList, 0, m_songTitleList.Length); + m_songTitleList = null; + m_songList = null; + m_speechBubble = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/PortraitRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/PortraitRoomObj.cs new file mode 100644 index 0000000..64f4b82 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/PortraitRoomObj.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class PortraitRoomObj : BonusRoomObj + { + private SpriteObj m_portraitFrame; + private int m_portraitIndex = 0; + private SpriteObj m_portrait; + + public override void Initialize() + { + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "portrait") + { + m_portraitFrame = obj as SpriteObj; + break; + } + } + + m_portraitFrame.ChangeSprite("GiantPortrait_Sprite"); + m_portraitFrame.Scale = new Vector2(2,2); + m_portrait = new SpriteObj("Blank_Sprite"); + m_portrait.Position = m_portraitFrame.Position; + m_portrait.Scale = new Vector2(0.95f, 0.95f); + GameObjList.Add(m_portrait); + + base.Initialize(); + } + + public override void OnEnter() + { + if (RoomCompleted == false && ID == -1) + { + //RoomCompleted = true; + m_portraitIndex = CDGMath.RandomInt(0, 8); // m_portraitIndex = 0; // override to test different portraits + m_portrait.ChangeSprite("Portrait" + m_portraitIndex + "_Sprite"); + ID = m_portraitIndex; + base.OnEnter(); + } + else if (ID != -1) + { + m_portraitIndex = ID; + m_portrait.ChangeSprite("Portrait" + m_portraitIndex + "_Sprite"); + } + } + + public override void Update(GameTime gameTime) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + Rectangle collideRect = new Rectangle(this.Bounds.Center.X - 100, this.Bounds.Bottom - 300, 200, 200); + if (CollisionMath.Intersects(Player.Bounds, collideRect) && Player.IsTouchingGround == true && ID > -1) + { + RCScreenManager manager = Game.ScreenManager; + manager.DialogueScreen.SetDialogue("PortraitRoomText" + ID); + manager.DisplayScreen(ScreenType.Dialogue, true); + } + } + + base.Update(gameTime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_portraitFrame = null; + m_portrait = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/RandomTeleportRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/RandomTeleportRoomObj.cs new file mode 100644 index 0000000..cb72d2d --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/RandomTeleportRoomObj.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class RandomTeleportRoomObj : BonusRoomObj + { + private TeleporterObj m_teleporter; + + public RandomTeleportRoomObj() + { + } + + public override void Initialize() + { + m_teleporter = new TeleporterObj(); + SpriteObj fauxTeleporter = null; + + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "teleporter") + { + m_teleporter.Position = obj.Position; + fauxTeleporter = obj as SpriteObj; + break; + } + } + + GameObjList.Remove(fauxTeleporter); + GameObjList.Add(m_teleporter); + + m_teleporter.OutlineWidth = 2; + m_teleporter.TextureColor = Color.PaleVioletRed; + base.Initialize(); + } + + public override void Update(GameTime gameTime) + { + if (CollisionMath.Intersects(Player.Bounds, m_teleporter.Bounds) && Player.IsTouchingGround == true) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + TeleportPlayer(); + } + } + + private void TeleportPlayer() + { + ProceduralLevelScreen level = Game.ScreenManager.GetLevelScreen(); + PlayerObj player = Game.ScreenManager.Player; + player.UpdateCollisionBoxes(); + + if (level != null) + { + Vector2 teleportPos = new Vector2(); + + int roomCount = level.RoomList.Count - 1; + if (roomCount < 1) roomCount = 1; + int randRoomIndex = CDGMath.RandomInt(0, roomCount); + + RoomObj roomToTeleportTo = level.RoomList[randRoomIndex]; + + // Ensures the room to teleport to isn't a specific type, and has at least one left/right/bottom door. + while (roomToTeleportTo.Name == "Boss" || roomToTeleportTo.Name == "Start" || roomToTeleportTo.Name == "Ending" || roomToTeleportTo.Name== "Compass" || roomToTeleportTo.Name == "ChallengeBoss" || + roomToTeleportTo.Name == "Throne" || roomToTeleportTo.Name == "Tutorial" || roomToTeleportTo.Name == "EntranceBoss" || roomToTeleportTo.Name == "Bonus" || + roomToTeleportTo.Name == "Linker" || roomToTeleportTo.Name=="Secret" || roomToTeleportTo.Name == "CastleEntrance" || roomToTeleportTo.DoorList.Count < 2) + { + randRoomIndex = CDGMath.RandomInt(0, roomCount); + roomToTeleportTo = level.RoomList[randRoomIndex]; + } + + foreach (DoorObj door in roomToTeleportTo.DoorList) + { + bool breakout = false; + teleportPos.X = door.Bounds.Center.X; + switch (door.DoorPosition) + { + case("Left"): + case ("Right"): + breakout = true; + teleportPos.Y = door.Bounds.Bottom - (player.Bounds.Bottom - player.Y); + break; + case ("Bottom"): + teleportPos.Y = door.Bounds.Top - (player.Bounds.Bottom - player.Y); + breakout = true; + break; + } + + if (breakout == true) + break; + } + + player.TeleportPlayer(teleportPos, m_teleporter); + } + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_teleporter = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/SpecialItemRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/SpecialItemRoomObj.cs new file mode 100644 index 0000000..ef17073 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/SpecialItemRoomObj.cs @@ -0,0 +1,233 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class SpecialItemRoomObj : BonusRoomObj + { + public byte ItemType { get; set; } + private SpriteObj m_pedestal; + private SpriteObj m_icon; + private float m_iconYPos; + + private SpriteObj m_speechBubble; + + public SpecialItemRoomObj() + { + } + + public override void Initialize() + { + m_speechBubble = new SpriteObj("UpArrowSquare_Sprite"); + m_speechBubble.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + + m_icon = new SpriteObj("Blank_Sprite"); + m_icon.Scale = new Vector2(2, 2); + + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "pedestal") + { + m_pedestal = obj as SpriteObj; + break; + } + } + + m_pedestal.OutlineWidth = 2; + + m_icon.X = m_pedestal.X; + m_icon.Y = m_pedestal.Y - (m_pedestal.Y - m_pedestal.Bounds.Top) - m_icon.Height / 2f - 10; + m_icon.OutlineWidth = 2; + + m_iconYPos = m_icon.Y; + GameObjList.Add(m_icon); + + m_speechBubble.Y = m_icon.Y - 30; + m_speechBubble.X = m_icon.X; + m_speechBubble.Visible = false; + GameObjList.Add(m_speechBubble); + + base.Initialize(); + } + + private void RandomizeItem() + { + if (Game.PlayerStats.Traits.X == TraitType.NearSighted || Game.PlayerStats.Traits.Y == TraitType.NearSighted || + Game.PlayerStats.Traits.X == TraitType.FarSighted || Game.PlayerStats.Traits.Y == TraitType.FarSighted || + Game.PlayerStats.Traits.X == TraitType.Vertigo || Game.PlayerStats.Traits.Y == TraitType.Vertigo || + Game.PlayerStats.Traits.X == TraitType.ColorBlind || Game.PlayerStats.Traits.Y == TraitType.ColorBlind || + Game.PlayerStats.Traits.X == TraitType.Nostalgic || Game.PlayerStats.Traits.Y == TraitType.Nostalgic) + { + if (CDGMath.RandomInt(1, 100) <= 30) // 30% chance of getting glasses. + ItemType = SpecialItemType.Glasses; + else + ItemType = GetRandomItem(); + //ItemType = (byte)(CDGMath.RandomInt(1, SpecialItemType.Total - 1)); + } + else + ItemType = GetRandomItem(); + //ItemType = (byte)(CDGMath.RandomInt(1, SpecialItemType.Total - 1)); + m_icon.ChangeSprite(SpecialItemType.SpriteName(ItemType)); + ID = ItemType; + //RoomCompleted = true; + } + + private byte GetRandomItem() + { + List possibleItems = new List(); + + for (int i = 1; i < SpecialItemType.Total; i++) + possibleItems.Add((byte)i); + + if ((Game.PlayerStats.EyeballBossBeaten == true && Game.PlayerStats.TimesCastleBeaten > 0) && Game.PlayerStats.ChallengeEyeballUnlocked == false && Game.PlayerStats.ChallengeEyeballBeaten == false) + { + possibleItems.Add(SpecialItemType.EyeballToken); + possibleItems.Add(SpecialItemType.EyeballToken); + } + if ((Game.PlayerStats.FairyBossBeaten == true && Game.PlayerStats.TimesCastleBeaten > 0) && Game.PlayerStats.ChallengeSkullUnlocked == false && Game.PlayerStats.ChallengeSkullBeaten == false) + { + possibleItems.Add(SpecialItemType.SkullToken); + possibleItems.Add(SpecialItemType.SkullToken); + } + if ((Game.PlayerStats.FireballBossBeaten == true && Game.PlayerStats.TimesCastleBeaten > 0) && Game.PlayerStats.ChallengeFireballUnlocked == false && Game.PlayerStats.ChallengeFireballBeaten == false) + { + possibleItems.Add(SpecialItemType.FireballToken); + possibleItems.Add(SpecialItemType.FireballToken); + } + if ((Game.PlayerStats.BlobBossBeaten == true && Game.PlayerStats.TimesCastleBeaten > 0) && Game.PlayerStats.ChallengeBlobUnlocked == false && Game.PlayerStats.ChallengeBlobBeaten == false) + { + possibleItems.Add(SpecialItemType.BlobToken); + possibleItems.Add(SpecialItemType.BlobToken); + possibleItems.Add(SpecialItemType.BlobToken); + } + + if (Game.PlayerStats.ChallengeLastBossUnlocked == false && Game.PlayerStats.ChallengeLastBossBeaten == false + && Game.PlayerStats.ChallengeEyeballBeaten == true + && Game.PlayerStats.ChallengeSkullBeaten == true + && Game.PlayerStats.ChallengeFireballBeaten == true + && Game.PlayerStats.ChallengeBlobBeaten == true && Game.PlayerStats.TimesCastleBeaten > 0) + { + possibleItems.Add(SpecialItemType.LastBossToken); + possibleItems.Add(SpecialItemType.LastBossToken); + possibleItems.Add(SpecialItemType.LastBossToken); + possibleItems.Add(SpecialItemType.LastBossToken); + possibleItems.Add(SpecialItemType.LastBossToken); + } + + return possibleItems[CDGMath.RandomInt(0, possibleItems.Count - 1)]; + } + + public override void OnEnter() + { + m_icon.Visible = false; + + //if (RoomCompleted == false) // Make sure not to randomize the item if it's already been randomized once. + if (ID == -1 && RoomCompleted == false) + { + do + { + RandomizeItem(); + } while (ItemType == Game.PlayerStats.SpecialItem); // Make sure the room doesn't randomize to the item the player already has. + } + else if (ID != -1) + { + ItemType = (byte)ID; + m_icon.ChangeSprite(SpecialItemType.SpriteName(ItemType)); + + if (RoomCompleted == true) + { + m_icon.Visible = false; + m_speechBubble.Visible = false; + } + } + + if (RoomCompleted == true) + m_pedestal.TextureColor = new Color(100, 100, 100); + else + m_pedestal.TextureColor = Color.White; + + base.OnEnter(); + } + + public override void Update(GameTime gameTime) + { + m_icon.Y = m_iconYPos + (float)Math.Sin(Game.TotalGameTime * 2) * 5; + m_speechBubble.Y = m_iconYPos - 30 + (float)Math.Sin(Game.TotalGameTime * 20) * 2; + + //if (ItemType != 0) + if (RoomCompleted == false) + { + //m_icon.Visible = true; + + if (CollisionMath.Intersects(Player.Bounds, m_pedestal.Bounds)) + { + m_speechBubble.Visible = true; + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("Special Item Prayer"); + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "TakeItem"); + manager.DialogueScreen.SetCancelEndHandler(typeof(Console), "WriteLine", "Canceling Selection"); + manager.DisplayScreen(ScreenType.Dialogue, true); + } + } + else + m_speechBubble.Visible = false; + } + else + m_icon.Visible = false; + + base.Update(gameTime); + } + + public void TakeItem() + { + RoomCompleted = true; + Game.PlayerStats.SpecialItem = ItemType; + m_pedestal.TextureColor = new Color(100, 100, 100); + + if (ItemType == SpecialItemType.Glasses) + { + Player.GetChildAt(10).Visible = true; + Player.PlayAnimation(true); + } + else + Player.GetChildAt(10).Visible = false; + + ItemType = 0; + m_speechBubble.Visible = false; + m_icon.Visible = false; + (Game.ScreenManager.CurrentScreen as ProceduralLevelScreen).UpdatePlayerHUDSpecialItem(); + + (Game.ScreenManager.CurrentScreen as ProceduralLevelScreen).UpdatePlayerSpellIcon(); + List objectList = new List(); + objectList.Add(new Vector2(m_pedestal.X, m_pedestal.Y - m_pedestal.Height / 2f)); + objectList.Add(GetItemType.SpecialItem); + objectList.Add(new Vector2(Game.PlayerStats.SpecialItem, 0)); + + // Saves the map and player Data the moment you take an item, to ensure you don't exploit. + (Player.AttachedLevel.ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData, SaveType.MapData); + + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.GetItem, true, objectList); + Tweener.Tween.RunFunction(0, Player, "RunGetItemAnimation"); // Necessary to delay this call by one update. + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_pedestal = null; + m_icon = null; + m_speechBubble = null; + base.Dispose(); + } + } + + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/SpellSwapRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/SpellSwapRoomObj.cs new file mode 100644 index 0000000..6c7c231 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/SpellSwapRoomObj.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class SpellSwapRoomObj : BonusRoomObj + { + public byte Spell { get; set; } + private SpriteObj m_pedestal; + private SpriteObj m_icon; + private float m_iconYPos; + + private SpriteObj m_speechBubble; + + public SpellSwapRoomObj() + { + } + + public override void Initialize() + { + m_speechBubble = new SpriteObj("UpArrowSquare_Sprite"); + m_speechBubble.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + + m_icon = new SpriteObj("Blank_Sprite"); + + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "pedestal") + { + m_pedestal = obj as SpriteObj; + break; + } + } + + m_pedestal.OutlineWidth = 2; + + m_icon.X = m_pedestal.X; + m_icon.Y = m_pedestal.Y - (m_pedestal.Y - m_pedestal.Bounds.Top) - m_icon.Height / 2f - 20; + m_icon.OutlineWidth = 2; + + m_iconYPos = m_icon.Y; + GameObjList.Add(m_icon); + + m_speechBubble.Y = m_icon.Y - 30; + m_speechBubble.X = m_icon.X; + m_speechBubble.Visible = false; + GameObjList.Add(m_speechBubble); + + base.Initialize(); + } + + private void RandomizeItem() + { + // Selecting random spell. + if (Game.PlayerStats.Class != ClassType.Dragon && Game.PlayerStats.Class != ClassType.Traitor) + { + byte[] spellList = ClassType.GetSpellList(Game.PlayerStats.Class); + + // Code to make sure spell swap doesn't interfere with savantism. + do + { + Spell = spellList[CDGMath.RandomInt(0, spellList.Length - 1)]; + } while ((Game.PlayerStats.Traits.X == TraitType.Savant || Game.PlayerStats.Traits.Y == TraitType.Savant) && + (Spell == SpellType.Translocator || Spell == SpellType.TimeStop || Spell == SpellType.DamageShield)); + + Array.Clear(spellList, 0, spellList.Length); + ID = Spell; + } + else + { + if (Game.PlayerStats.Class == ClassType.Dragon) + { + ID = SpellType.DragonFire; + Spell = SpellType.DragonFire; + } + else if (Game.PlayerStats.Class == ClassType.Traitor) + { + ID = SpellType.RapidDagger; + Spell = SpellType.RapidDagger; + } + } + + //Spell = ClassType.GetSpellList(Game.PlayerStats.Class)[0]; + + m_icon.ChangeSprite(SpellType.Icon(Spell)); + //RoomCompleted = true; + } + + public override void OnEnter() + { + if (ID == -1 && RoomCompleted == false) // Make sure not to randomize the item if it's already been randomized once. + { + do + { + RandomizeItem(); + } while ((Spell == Game.PlayerStats.Spell && Game.PlayerStats.Class != ClassType.Dragon && Game.PlayerStats.Class != ClassType.Traitor) // Make sure the room doesn't randomize to the item the player already has. + || (Spell == SpellType.DragonFire && Game.PlayerStats.Class != ClassType.Dragon) // Make sure Dragon fire is not set as the spell for a locked castle and changed class. + || (Spell == SpellType.RapidDagger && Game.PlayerStats.Class != ClassType.Traitor)); // Make sure rapid dagger is not set as the spell for a locked castle and changed class. + } + else if (ID != -1) + { + Spell = (byte)ID; + m_icon.ChangeSprite(SpellType.Icon(Spell)); + + if (RoomCompleted == true) + { + m_icon.Visible = false; + m_speechBubble.Visible = false; + } + } + + base.OnEnter(); + } + + public override void Update(GameTime gameTime) + { + m_icon.Y = m_iconYPos - 10 + (float)Math.Sin(Game.TotalGameTime * 2) * 5; + m_speechBubble.Y = m_iconYPos - 90 + (float)Math.Sin(Game.TotalGameTime * 20) * 2; + + if (RoomCompleted == false) + { + m_icon.Visible = true; + + if (CollisionMath.Intersects(Player.Bounds, m_pedestal.Bounds)) + { + m_speechBubble.Visible = true; + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + TakeItem(); + } + } + else + m_speechBubble.Visible = false; + } + else + m_icon.Visible = false; + + base.Update(gameTime); + } + + public void TakeItem() + { + RoomCompleted = true; + Game.PlayerStats.Spell = Spell; + + if (Game.PlayerStats.Class == ClassType.Wizard2) + Game.PlayerStats.WizardSpellList = SpellType.GetNext3Spells(); + + Spell = 0; + m_speechBubble.Visible = false; + m_icon.Visible = false; + (Game.ScreenManager.CurrentScreen as ProceduralLevelScreen).UpdatePlayerSpellIcon(); + List objectList = new List(); + objectList.Add(new Vector2(m_icon.X, m_icon.Y - m_icon.Height / 2f)); + objectList.Add(GetItemType.Spell); + objectList.Add(new Vector2(Game.PlayerStats.Spell, 0)); + + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.GetItem, true, objectList); + Tweener.Tween.RunFunction(0, Player, "RunGetItemAnimation"); // Necessary to delay this call by one update. + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_pedestal = null; + m_icon = null; + m_speechBubble = null; + base.Dispose(); + } + } + + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/VitaChamberRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/VitaChamberRoomObj.cs new file mode 100644 index 0000000..0e7c95c --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Bonus Rooms/VitaChamberRoomObj.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class VitaChamberRoomObj : BonusRoomObj + { + private GameObj m_fountain; + private SpriteObj m_speechBubble; + + public override void Initialize() + { + m_speechBubble = new SpriteObj("UpArrowSquare_Sprite"); + m_speechBubble.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + GameObjList.Add(m_speechBubble); + + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "fountain") + { + m_fountain = obj; + break; + } + } + + (m_fountain as SpriteObj).OutlineWidth = 2; + m_speechBubble.X = m_fountain.X; + base.Initialize(); + } + + public override void OnEnter() + { + if (RoomCompleted == true) + { + m_speechBubble.Visible = false; + m_fountain.TextureColor = new Color(100, 100, 100); + } + else + m_fountain.TextureColor = Color.White; + base.OnEnter(); + } + + public override void Update(GameTime gameTime) + { + if (RoomCompleted == false) + { + Rectangle bounds = m_fountain.Bounds; + bounds.X -= 50; + bounds.Width += 100; + if (CollisionMath.Intersects(Player.Bounds, bounds) && Player.IsTouchingGround == true) + { + m_speechBubble.Y = m_fountain.Y - 150 + (float)Math.Sin(Game.TotalGameTime * 20) * 2; + m_speechBubble.Visible = true; + } + else + m_speechBubble.Visible = false; + + if (m_speechBubble.Visible == true) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + int healthGain = (int)(Player.MaxHealth * GameEV.ROOM_VITA_CHAMBER_REGEN_AMOUNT); + int manaGain = (int)(Player.MaxMana * GameEV.ROOM_VITA_CHAMBER_REGEN_AMOUNT); + Player.CurrentHealth += healthGain; + Player.CurrentMana += manaGain; + Console.WriteLine("Healed"); + SoundManager.PlaySound("Collect_Mana"); + Player.AttachedLevel.TextManager.DisplayNumberStringText(healthGain, "LOC_ID_ITEM_DROP_OBJ_2" /*"hp recovered"*/, Color.LawnGreen, new Vector2(Player.X, Player.Bounds.Top - 30)); + Player.AttachedLevel.TextManager.DisplayNumberStringText(manaGain, "LOC_ID_ITEM_DROP_OBJ_3" /*"mp recovered"*/, Color.CornflowerBlue, new Vector2(Player.X, Player.Bounds.Top)); + //Tweener.Tween.RunFunction(0.2f, Player.AttachedLevel.TextManager, "DisplayNumberStringText", manaGain, "mp recovered", Color.LawnGreen, new Vector2(Player.X, Player.Bounds.Top - 50)); + RoomCompleted = true; + m_fountain.TextureColor = new Color(100, 100, 100); + m_speechBubble.Visible = false; + } + } + } + + base.Update(gameTime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_fountain = null; + m_speechBubble = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/BlobBossRoom.cs b/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/BlobBossRoom.cs new file mode 100644 index 0000000..4f3a447 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/BlobBossRoom.cs @@ -0,0 +1,203 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Tweener.Ease; +using Tweener; + +namespace RogueCastle +{ + public class BlobBossRoom : BossRoomObj + { + private EnemyObj_Blob m_boss1; + + private List m_blobArray; + private float m_desiredBossScale; + private int m_numIntroBlobs = 10; + + public override void Initialize() + { + m_boss1 = EnemyList[0] as EnemyObj_Blob; + //m_boss2 = EnemyList[1] as EnemyObj_Blob; + + m_boss1.PauseEnemy(true); + m_boss1.DisableAllWeight = false; + //m_boss2.PauseEnemy(true); + + m_desiredBossScale = m_boss1.Scale.X; + + m_blobArray = new List(); + for (int i = 0; i < m_numIntroBlobs; i++) + { + ObjContainer blob = new ObjContainer("EnemyBlobBossAir_Character"); + blob.Position = m_boss1.Position; + blob.Scale = new Vector2(0.4f, 0.4f); + + blob.GetChildAt(0).TextureColor = Color.White; + blob.GetChildAt(2).TextureColor = Color.LightSkyBlue; + blob.GetChildAt(2).Opacity = 0.8f; + (blob.GetChildAt(1) as SpriteObj).OutlineColour = Color.Black; + blob.Y -= 1000; + m_blobArray.Add(blob); + GameObjList.Add(blob); + } + + base.Initialize(); + } + + public override void OnEnter() + { + m_boss1.Name = "Herodotus"; + m_boss1.LocStringID = "LOC_ID_ENEMY_NAME_11"; + //m_boss1.Name = "Herod"; + //m_boss2.Name = "Otus"; + + m_boss1.GetChildAt(0).TextureColor = Color.White; + m_boss1.GetChildAt(2).TextureColor = Color.LightSkyBlue; + m_boss1.GetChildAt(2).Opacity = 0.8f; + (m_boss1.GetChildAt(1) as SpriteObj).OutlineColour = Color.Black; + m_boss1.GetChildAt(1).TextureColor = Color.Black; + + //m_boss2.GetChildAt(0).TextureColor = Color.Black; + //m_boss2.GetChildAt(2).TextureColor = Color.IndianRed; + //m_boss2.GetChildAt(2).Opacity = 0.8f; + //(m_boss2.GetChildAt(1) as SpriteObj).OutlineColour = Color.White; + //m_boss2.GetChildAt(1).TextureColor = Color.White; + SoundManager.StopMusic(0.5f); + + Player.LockControls(); + Player.AttachedLevel.UpdateCamera(); + Player.AttachedLevel.CameraLockedToPlayer = false; + Tween.To(Player.AttachedLevel.Camera, 1f, Quad.EaseInOut, "X", (this.Bounds.Left + 700).ToString(), "Y", m_boss1.Y.ToString()); + + Tween.By(m_blobArray[0], 1, Quad.EaseIn, "delay", "0.5", "Y", "1150"); + Tween.AddEndHandlerToLastTween(this, "GrowBlob", m_blobArray[0]); + Tween.By(m_blobArray[1], 1, Quad.EaseIn, "delay", "1.5", "Y", "1150"); + Tween.AddEndHandlerToLastTween(this, "GrowBlob", m_blobArray[1]); + + Tween.RunFunction(1, this, "DropBlobs"); + + m_boss1.Scale = new Vector2(0.5f, 0.5f); + + Player.AttachedLevel.RunCinematicBorders(9); + + base.OnEnter(); + } + + public void DropBlobs() + { + float delay = 1f; + for (int i = 2; i < m_blobArray.Count; i++) + { + Tween.By(m_blobArray[i], 1, Quad.EaseIn, "delay", delay.ToString(), "Y", "1150"); + Tween.AddEndHandlerToLastTween(this, "GrowBlob", m_blobArray[i]); + delay += 0.5f * (m_blobArray.Count - i) / m_blobArray.Count; + } + Tween.RunFunction(delay + 1, m_boss1, "PlayAnimation", true); + Tween.RunFunction(delay + 1, typeof(SoundManager), "PlaySound", "Boss_Blob_Idle_Loop"); + //Tween.RunFunction(delay + 1, this, "DisplayBossTitle", "The Infinite", m_boss1.Name + " & " + m_boss2.Name, "Intro2"); + Tween.RunFunction(delay + 1, this, "DisplayBossTitle", "LOC_ID_ENEMY_NAME_119", m_boss1.LocStringID, "Intro2"); + Tween.RunFunction(delay + 1, typeof(SoundManager), "PlaySound", "Boss_Blob_Spawn"); + } + + public void GrowBlob(GameObj blob) + { + float desiredBossScale = (m_desiredBossScale - 0.5f)/ m_numIntroBlobs; // Subtract 0.5f because the blob starts at 0.5. + + blob.Visible = false; + m_boss1.PlayAnimation(false); + m_boss1.ScaleX += desiredBossScale; + m_boss1.ScaleY += desiredBossScale; + + SoundManager.PlaySound("Boss_Blob_Spawn_01", "Boss_Blob_Spawn_02", "Boss_Blob_Spawn_03"); + } + + public void Intro2() + { + m_boss1.PlayAnimation(true); + Tween.To(Player.AttachedLevel.Camera, 0.5f, Quad.EaseInOut, "delay", "0.5", "X", (Player.X + GlobalEV.Camera_XOffset).ToString(), "Y", (this.Bounds.Bottom - (Player.AttachedLevel.Camera.Bounds.Bottom - Player.AttachedLevel.Camera.Y)).ToString()); + Tween.AddEndHandlerToLastTween(this, "BeginBattle"); + } + + public void BeginBattle() + { + SoundManager.PlayMusic("DungeonBoss", true, 1); + Player.AttachedLevel.CameraLockedToPlayer = true; + Player.UnlockControls(); + m_boss1.UnpauseEnemy(true); + //m_boss2.UnpauseEnemy(true); + m_boss1.PlayAnimation(true); + //m_boss2.PlayAnimation(true); + //m_boss1.Scale = m_boss2.Scale; //TEDDY - Added to make them be the correct scale. + } + + public override void Update(GameTime gameTime) + { + Rectangle bounds = this.Bounds; + + foreach (EnemyObj enemy in EnemyList) + { + if (enemy.Type == EnemyType.Blob && enemy.IsKilled == false) + { + if ((enemy.X > this.Bounds.Right - 20) || (enemy.X < this.Bounds.Left + 20) || + (enemy.Y > this.Bounds.Bottom - 20) || (enemy.Y < this.Bounds.Top + 20)) + enemy.Position = new Vector2(bounds.Center.X, bounds.Center.Y); + } + } + + foreach (EnemyObj enemy in TempEnemyList) + { + if (enemy.Type == EnemyType.Blob && enemy.IsKilled == false) + { + if ((enemy.X > this.Bounds.Right - 20) || (enemy.X < this.Bounds.Left + 20) || + (enemy.Y > this.Bounds.Bottom - 20) || (enemy.Y < this.Bounds.Top + 20)) + enemy.Position = new Vector2(bounds.Center.X, bounds.Center.Y); + } + } + base.Update(gameTime); + } + + public override bool BossKilled + { + get { return ActiveEnemies == 0; } + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_blobArray.Clear(); // Do not dispose the blobs in this array since they are added to the room and will be disposed when the room is disposed. + m_blobArray = null; + + m_boss1 = null; + base.Dispose(); + } + } + + public int NumActiveBlobs + { + get + { + int numBlobs = 0; + foreach (EnemyObj enemy in EnemyList) + { + if (enemy.Type == EnemyType.Blob && enemy.IsKilled == false) + numBlobs++; + } + + foreach (EnemyObj enemy in TempEnemyList) + { + if (enemy.Type == EnemyType.Blob && enemy.IsKilled == false) + numBlobs++; + } + return numBlobs; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/BossRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/BossRoomObj.cs new file mode 100644 index 0000000..4ffc486 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/BossRoomObj.cs @@ -0,0 +1,267 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public abstract class BossRoomObj : RoomObj + { + protected bool m_cutsceneRunning = false; + private ChestObj m_bossChest; + private float m_sparkleTimer = 0; + private bool m_teleportingOut; + private float m_roomFloor; + + private TextObj m_bossTitle1; + private TextObj m_bossTitle2; + private SpriteObj m_bossDivider; + + public override void Initialize() + { + m_bossTitle1 = new TextObj(Game.JunicodeFont); + m_bossTitle1.Text = LocaleBuilder.getString("LOC_ID_ENEMY_NAME_121", m_bossTitle1); // "The Forsaken", is this used or just overidden by DisplayBossTitle parameters + m_bossTitle1.OutlineWidth = 2; + m_bossTitle1.FontSize = 18; + + m_bossTitle2 = new TextObj(Game.JunicodeLargeFont); + m_bossTitle2.Text = LocaleBuilder.getString("LOC_ID_ENEMY_NAME_34", m_bossTitle2); // "Alexander", is this used or just overidden by DisplayBossTitle parameters + m_bossTitle2.OutlineWidth = 2; + m_bossTitle2.FontSize = 40; + + m_bossDivider = new SpriteObj("Blank_Sprite"); + m_bossDivider.OutlineWidth = 2; + + + foreach (DoorObj door in DoorList) + { + m_roomFloor = door.Bounds.Bottom; + } + + m_bossChest = new ChestObj(null); + m_bossChest.Position = new Vector2(this.Bounds.Center.X - m_bossChest.Width/2f, this.Bounds.Center.Y); + this.GameObjList.Add(m_bossChest); + + base.Initialize(); + } + + public override void OnEnter() + { + Game.ScreenManager.GetLevelScreen().JukeboxEnabled = false; // This code is to override the jukebox. + m_bossChest.ChestType = ChestType.Boss; + m_bossChest.Visible = false; + m_bossChest.IsLocked = true; + + if (m_bossChest.PhysicsMngr == null) + Player.PhysicsMngr.AddObject(m_bossChest); + m_teleportingOut = false; + + m_bossTitle1.Opacity = 0; + m_bossTitle2.Opacity = 0; + m_bossDivider.ScaleX = 0; + m_bossDivider.Opacity = 0; + + base.OnEnter(); + } + + public void DisplayBossTitle(string bossTitle1LocID, string bossTitle2LocID, string endHandler) + { + SoundManager.PlaySound("Boss_Title"); + // Setting title positions. + m_bossTitle1.Text = LocaleBuilder.getString(bossTitle1LocID, m_bossTitle1); + m_bossTitle2.Text = LocaleBuilder.getString(bossTitle2LocID, m_bossTitle2); + + Camera2D camera = Player.AttachedLevel.Camera; + if (Player.AttachedLevel.CurrentRoom is LastBossRoom) + m_bossTitle1.Position = new Vector2(camera.X - 550, camera.Y + 100); + else + m_bossTitle1.Position = new Vector2(camera.X - 550, camera.Y + 50); + m_bossTitle2.X = m_bossTitle1.X - 0; + m_bossTitle2.Y = m_bossTitle1.Y + 50; + + m_bossDivider.Position = m_bossTitle1.Position; + m_bossDivider.Y += m_bossTitle1.Height - 5; + + // Reposition the titles. + m_bossTitle1.X -= 1000; + m_bossTitle2.X += 1500; + + // Tweening the titles in. + Tween.To(m_bossDivider, 0.5f, Tween.EaseNone, "delay", "0.3", "Opacity", "1"); + Tween.To(m_bossDivider, 1, Quad.EaseInOut, "delay", "0", "ScaleX", ((float)(m_bossTitle2.Width / 5)).ToString()); + + Tween.To(m_bossTitle1, 0.5f, Tween.EaseNone, "delay", "0.3", "Opacity", "1"); + Tween.To(m_bossTitle2, 0.5f, Tween.EaseNone, "delay", "0.3", "Opacity", "1"); + Tween.By(m_bossTitle1, 1, Quad.EaseOut, "X", "1000"); + Tween.By(m_bossTitle2, 1, Quad.EaseOut, "X", "-1500"); + + // Move titles slightly after tweening. + m_bossTitle1.X += 1000; + m_bossTitle2.X -= 1500; + Tween.By(m_bossTitle1, 2f, Tween.EaseNone, "delay", "1", "X", "20"); + Tween.By(m_bossTitle2, 2f, Tween.EaseNone, "delay", "1", "X", "-20"); + m_bossTitle1.X -= 1000; + m_bossTitle2.X += 1500; + + // Add the end event handler here so that it doesn't start too late. + Tween.AddEndHandlerToLastTween(this, endHandler); + + Tween.RunFunction(3, typeof(SoundManager), "PlaySound", "Boss_Title_Exit"); + //Tweening the titles out. + m_bossTitle1.X += 1020; + m_bossTitle2.X -= 1520; + m_bossTitle1.Opacity = 1; + m_bossTitle2.Opacity = 1; + Tween.To(m_bossTitle1, 0.5f, Tween.EaseNone, "delay", "3", "Opacity", "0"); + Tween.To(m_bossTitle2, 0.5f, Tween.EaseNone, "delay", "3", "Opacity", "0"); + Tween.By(m_bossTitle1, 0.6f, Quad.EaseIn, "delay", "3", "X", "1500"); + Tween.By(m_bossTitle2, 0.6f, Quad.EaseIn, "delay", "3", "X", "-1000"); + m_bossTitle1.Opacity = 0; + m_bossTitle2.Opacity = 0; + + m_bossDivider.Opacity = 1; + Tween.To(m_bossDivider, 0.5f, Tween.EaseNone, "delay", "2.8", "Opacity", "0"); + m_bossDivider.Opacity = 0; + } + + public override void Update(GameTime gameTime) + { + if (m_cutsceneRunning == false) + base.Update(gameTime); + + if (BossKilled == true && m_bossChest.Visible == false) + { + BossCleanup(); + m_bossChest.Visible = true; + m_bossChest.Opacity = 0; + SoundManager.PlayMusic("TitleScreenSong", true, 1); // Stinger goes here. + Tween.To(m_bossChest, 4, Tween.EaseNone, "Opacity", "1"); + Tween.To(m_bossChest, 4, Quad.EaseOut, "Y", m_roomFloor.ToString()); + Tween.AddEndHandlerToLastTween(this, "UnlockChest"); + m_sparkleTimer = 0.5f; + } + + if (m_bossChest.Visible == true && m_bossChest.IsOpen == false && BossKilled == true) + { + if (m_sparkleTimer > 0) + { + m_sparkleTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_sparkleTimer <= 0) + { + m_sparkleTimer = 0.5f; + Tween.RunFunction(0, Player.AttachedLevel.ImpactEffectPool, "DisplayChestSparkleEffect", new Vector2(m_bossChest.X, m_bossChest.Y - m_bossChest.Height / 2)); + } + } + } + else if (m_bossChest.Visible == true && m_bossChest.IsOpen == true && BossKilled == true && m_teleportingOut == false) + { + m_teleportingOut = true; + if (LevelEV.RUN_DEMO_VERSION == true) + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.DemoEnd, true); + else + TeleportPlayer(); + } + } + + public virtual void BossCleanup() + { + Player.StopAllSpells(); + Game.PlayerStats.NewBossBeaten = true; + if (this.LinkedRoom != null) + Player.AttachedLevel.CloseBossDoor(this.LinkedRoom, this.LevelType); + } + + public void TeleportPlayer() + { + Player.CurrentSpeed = 0; + Vector2 storedPlayerPos = Player.Position; + + Vector2 storedScale = Player.Scale; + Tween.To(Player, 0.05f, Tweener.Ease.Linear.EaseNone, "delay", "1.2", "ScaleX", "0"); + Player.ScaleX = 0; + Tween.To(Player, 0.05f, Tweener.Ease.Linear.EaseNone, "delay", "7", "ScaleX", storedScale.X.ToString()); + Player.ScaleX = storedScale.X; + + LogicSet teleportLS = new LogicSet(Player); + teleportLS.AddAction(new ChangePropertyLogicAction(Player.AttachedLevel, "DisableSongUpdating", true)); + teleportLS.AddAction(new RunFunctionLogicAction(Player, "LockControls")); + teleportLS.AddAction(new ChangeSpriteLogicAction("PlayerLevelUp_Character", true, false)); + teleportLS.AddAction(new DelayLogicAction(0.5f)); + teleportLS.AddAction(new PlaySoundLogicAction("Teleport_Disappear")); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.ImpactEffectPool, "MegaTeleport", new Vector2(Player.X, Player.Bounds.Bottom), Player.Scale)); + teleportLS.AddAction(new DelayLogicAction(0.3f)); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.ScreenManager, "StartWipeTransition")); + teleportLS.AddAction(new DelayLogicAction(0.2f)); + if (this.LinkedRoom != null) + { + // Door symbol being revealed. + Player.Position = new Vector2(Player.AttachedLevel.RoomList[1].Bounds.Center.X, Player.AttachedLevel.RoomList[1].Bounds.Center.Y); + Player.UpdateCollisionBoxes(); + teleportLS.AddAction(new TeleportLogicAction(null, Player.Position)); + teleportLS.AddAction(new DelayLogicAction(0.05f)); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.ScreenManager, "EndWipeTransition")); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.RoomList[1], "RevealSymbol", this.LevelType, true)); + teleportLS.AddAction(new DelayLogicAction(3.5f)); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.ScreenManager, "StartWipeTransition")); + teleportLS.AddAction(new DelayLogicAction(0.2f)); + + // Teleporting player back to room entrance. + Player.Position = new Vector2(this.LinkedRoom.Bounds.Center.X, (this.LinkedRoom.Bounds.Bottom - 60 - (Player.Bounds.Bottom - Player.Y))); + Player.UpdateCollisionBoxes(); + teleportLS.AddAction(new ChangePropertyLogicAction(Player.AttachedLevel, "DisableSongUpdating", false)); + teleportLS.AddAction(new TeleportLogicAction(null, Player.Position)); + teleportLS.AddAction(new DelayLogicAction(0.05f)); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.ScreenManager, "EndWipeTransition")); + teleportLS.AddAction(new DelayLogicAction(1f)); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.ImpactEffectPool, "MegaTeleportReverse", new Vector2(Player.X, this.LinkedRoom.Bounds.Bottom - 60), storedScale)); + teleportLS.AddAction(new PlaySoundLogicAction("Teleport_Reappear")); + } + teleportLS.AddAction(new DelayLogicAction(0.2f)); + teleportLS.AddAction(new ChangePropertyLogicAction(Player, "ForceInvincible", false)); + teleportLS.AddAction(new RunFunctionLogicAction(Player, "UnlockControls")); + Player.RunExternalLogicSet(teleportLS); + Player.Position = storedPlayerPos; + Player.UpdateCollisionBoxes(); + } + + public void UnlockChest() + { + m_bossChest.IsLocked = false; + } + + public override void Draw(Camera2D camera) + { + base.Draw(camera); + + m_bossDivider.Draw(camera); + camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap; + m_bossTitle1.Draw(camera); + m_bossTitle2.Draw(camera); + camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointWrap; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_bossChest = null; + m_bossDivider.Dispose(); + m_bossDivider = null; + m_bossTitle1.Dispose(); + m_bossTitle1 = null; + m_bossTitle2.Dispose(); + m_bossTitle2 = null; + + base.Dispose(); + } + } + + public abstract bool BossKilled { get; } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/EyeballBossRoom.cs b/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/EyeballBossRoom.cs new file mode 100644 index 0000000..fd17c1e --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/EyeballBossRoom.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Tweener.Ease; +using Tweener; + +namespace RogueCastle +{ + public class EyeballBossRoom : BossRoomObj + { + private EnemyObj_Eyeball m_boss; + + public EyeballBossRoom() + { + m_roomActivityDelay = 0.5f; + } + + public override void Initialize() + { + m_boss = this.EnemyList[0] as EnemyObj_Eyeball; + base.Initialize(); + } + + public override void OnEnter() + { + m_cutsceneRunning = true; + + SoundManager.StopMusic(0.5f); + + m_boss.ChangeSprite("EnemyEyeballBossFire_Character"); + m_boss.ChangeToBossPupil(); + Vector2 storedScale = m_boss.Scale; + m_boss.Scale = new Vector2(0.3f, 0.3f); + Player.AttachedLevel.Camera.X = (int)(this.Bounds.Left + Player.AttachedLevel.Camera.Width * 0.5f); + Player.AttachedLevel.Camera.Y = Player.Y; + Vector2 storedCameraPos = Player.AttachedLevel.Camera.Position; + m_boss.AnimationDelay = 1 / 10f; + + Player.LockControls(); + Player.AttachedLevel.RunCinematicBorders(8f); + Player.AttachedLevel.CameraLockedToPlayer = false; + Player.AttachedLevel.Camera.Y = Player.Y; + Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "Y", m_boss.Y.ToString()); + //Tween.AddEndHandlerToLastTween(m_boss, "ChangeSprite", "EnemyEyeballBossFire_Character"); + Tween.RunFunction(1.1f, m_boss, "PlayAnimation", true); + Tween.To(m_boss, 0.5f, Linear.EaseNone, "delay", "2.5", "AnimationDelay", (1 / 60f).ToString()); + Tween.To(m_boss, 3f, Quad.EaseInOut, "delay", "1", "Rotation", "1800"); + Tween.AddEndHandlerToLastTween(m_boss, "ChangeSprite", "EnemyEyeballBossEye_Character"); + Tween.To(m_boss, 2, Bounce.EaseOut, "delay", "2", "ScaleX", storedScale.X.ToString(), "ScaleY", storedScale.Y.ToString()); + + Tween.RunFunction(3.2f, this, "DisplayBossTitle", "LOC_ID_ENEMY_NAME_118", m_boss.LocStringID, "Intro2"); //The Lookout + Tween.RunFunction(0.8f, typeof(SoundManager), "PlaySound", "Boss_Eyeball_Build"); + + base.OnEnter(); + } + + public void Intro2() + { + Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "delay", "0.5", "Y", ((int)(this.Bounds.Bottom - Player.AttachedLevel.Camera.Height * 0.5f)).ToString()); + Tween.AddEndHandlerToLastTween(this, "EndCutscene"); + } + + public void EndCutscene() + { + m_boss.Rotation = 0; + SoundManager.PlayMusic("CastleBossIntroSong", false, 1); + Player.AttachedLevel.CameraLockedToPlayer = true; + Player.UnlockControls(); + m_cutsceneRunning = false; + } + + public override void Update(GameTime gameTime) + { + if (m_cutsceneRunning == false && m_boss.BossVersionKilled == false) + { + if (SoundManager.IsMusicPlaying == false) + SoundManager.PlayMusic("CastleBossSong", true, 0); + } + + base.Update(gameTime); + } + + protected override GameObj CreateCloneInstance() + { + return new EyeballBossRoom(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_boss = null; + base.Dispose(); + } + } + + public override bool BossKilled + { + get { return m_boss.IsKilled == true; } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/FairyBossRoom.cs b/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/FairyBossRoom.cs new file mode 100644 index 0000000..4d0d512 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/FairyBossRoom.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Tweener.Ease; +using Tweener; + +namespace RogueCastle +{ + public class FairyBossRoom : BossRoomObj + { + private EnemyObj_Fairy m_boss; + private ObjContainer m_bossShadow; + + public override void Initialize() + { + m_boss = EnemyList[0] as EnemyObj_Fairy; + m_boss.PauseEnemy(true); + + m_bossShadow = new ObjContainer("EnemyFairyGhostBossMove_Character"); + m_boss.ChangeSprite("EnemyFairyGhostBossIdle_Character"); + m_bossShadow.TextureColor = Color.Black; + m_bossShadow.Scale = m_boss.Scale; + m_bossShadow.PlayAnimation(true); + GameObjList.Add(m_bossShadow); + + base.Initialize(); + } + + public override void OnEnter() + { + SoundManager.StopMusic(0.5f); + Player.LockControls(); + + m_boss.Opacity = 0; + + Player.AttachedLevel.UpdateCamera(); + m_bossShadow.Position = new Vector2(this.Bounds.Left + 100, this.Bounds.Top + 400); + Player.AttachedLevel.CameraLockedToPlayer = false; + + Player.AttachedLevel.RunCinematicBorders(11); + Tween.To(Player.AttachedLevel.Camera, 1f, Quad.EaseInOut, "X", (this.Bounds.Left + 900).ToString(), "Y", (this.Bounds.Top + 400).ToString()); + Tween.By(m_bossShadow, 0.5f, Tween.EaseNone, "delay", "1", "X", "3000"); + Tween.RunFunction(1.8f, this, "Intro2"); + + Tween.RunFunction(0.5f, typeof(SoundManager), "PlaySound", "Boss_Flameskull_Whoosh_01"); + base.OnEnter(); + } + + public void Intro2() + { + m_bossShadow.Position = new Vector2(this.Bounds.Right - 100, this.Bounds.Bottom - 400); + m_bossShadow.Flip = SpriteEffects.FlipHorizontally; + Tween.To(Player.AttachedLevel.Camera, 1f, Quad.EaseInOut, "X", (this.Bounds.Right - 900).ToString(), "Y", (this.Bounds.Bottom - 400).ToString()); + Tween.By(m_bossShadow, 0.5f, Tween.EaseNone, "delay", "1", "X", "-3000"); + Tween.RunFunction(1.8f, this, "Intro3"); + Tween.RunFunction(0.2f, typeof(SoundManager), "PlaySound", "Boss_Flameskull_Whoosh_02"); + } + + public void Intro3() + { + m_bossShadow.Position = m_boss.Position; + m_bossShadow.X -= 1500; + m_bossShadow.Flip = SpriteEffects.None; + Tween.To(Player.AttachedLevel.Camera, 1f, Quad.EaseInOut, "X", m_boss.X.ToString(), "Y", m_boss.Y.ToString()); + Tween.By(m_bossShadow, 1f, Quad.EaseOut, "delay", "1", "X", "1500"); + Tween.RunFunction(1.8f, this, "Intro4"); + Tween.RunFunction(0.2f, typeof(SoundManager), "PlaySound", "Boss_Flameskull_Spawn"); + } + + public void Intro4() + { + m_boss.PlayAnimation(); + m_bossShadow.ChangeSprite("EnemyFairyGhostBossIdle_Character"); + m_bossShadow.PlayAnimation(true); + Tween.To(m_boss, 0.5f, Tween.EaseNone, "delay", "0.5", "Opacity", "1"); + Tween.To(m_bossShadow, 0.5f, Tween.EaseNone, "delay", "0.5", "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "DisplayBossTitle", "LOC_ID_ENEMY_NAME_120", m_boss.LocStringID, "Intro5"); //The Forsaken + } + + public void Intro5() + { + Tween.To(Player.AttachedLevel.Camera, 0.5f, Quad.EaseInOut, "delay", "0.3", "X", (Player.X + GlobalEV.Camera_XOffset).ToString(), "Y", (this.Bounds.Bottom - (Player.AttachedLevel.Camera.Bounds.Bottom - Player.AttachedLevel.Camera.Y)).ToString()); + Tween.AddEndHandlerToLastTween(this, "BeginFight"); + } + + public void BeginFight() + { + SoundManager.PlayMusic("GardenBossSong", true, 1); + Player.AttachedLevel.CameraLockedToPlayer = true; + Player.UnlockControls(); + m_boss.UnpauseEnemy(true); + } + + public override void Draw(Camera2D camera) + { + if (m_boss.IsKilled == true && (Game.PlayerStats.Traits.X != TraitType.ColorBlind && Game.PlayerStats.Traits.Y != TraitType.ColorBlind)) + { + camera.End(); + m_boss.StopAnimation(); + + Game.HSVEffect.Parameters["Saturation"].SetValue(0); + camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, null, null, Game.HSVEffect, camera.GetTransformation()); + m_boss.Visible = true; + m_boss.Draw(camera); + m_boss.Visible = false; + camera.End(); + camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, null, null, null, camera.GetTransformation()); + } + + base.Draw(camera); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_boss = null; + m_bossShadow = null; + base.Dispose(); + } + } + + public override bool BossKilled + { + get { return m_boss.IsKilled; } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/FireballBossRoom.cs b/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/FireballBossRoom.cs new file mode 100644 index 0000000..385e0dc --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/FireballBossRoom.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Tweener.Ease; +using Tweener; + +namespace RogueCastle +{ + public class FireballBossRoom : BossRoomObj + { + private EnemyObj_Fireball m_boss; + private List m_fireList; + private float m_bossStartingScale; + + public override void Initialize() + { + foreach (EnemyObj enemy in EnemyList) + { + if (enemy is EnemyObj_Fireball) + m_boss = enemy as EnemyObj_Fireball; + + enemy.Visible = false; + enemy.PauseEnemy(true); + } + + m_boss.ChangeSprite("EnemyGhostBossIdle_Character"); + m_bossStartingScale = m_boss.ScaleX; + + m_fireList = new List(); + float angle = 0; + float angleDiff = 360 / 15f; + for (int i = 0; i < 15; i++) + { + SpriteObj fire = new SpriteObj("GhostBossProjectile_Sprite"); + fire.PlayAnimation(true); + fire.OutlineWidth = 2; + fire.Position = CDGMath.GetCirclePosition(angle, 300, m_boss.Position); + fire.Scale = new Vector2(2, 2); + angle += angleDiff; + fire.Opacity = 0; + m_fireList.Add(fire); + GameObjList.Add(fire); + } + + base.Initialize(); + } + + public override void OnEnter() + { + m_cutsceneRunning = true; + SoundManager.StopMusic(0.5f); + Player.LockControls(); + + m_boss.Scale = Vector2.Zero; + m_boss.Visible = true; + m_boss.PlayAnimation(true); + + Player.AttachedLevel.UpdateCamera(); + Player.AttachedLevel.CameraLockedToPlayer = false; + Tween.To(Player.AttachedLevel.Camera, 1f, Quad.EaseInOut, "X", m_boss.X.ToString(), "Y", m_boss.Y.ToString()); + Tween.RunFunction(1.5f, this, "Intro2"); + + Player.AttachedLevel.RunCinematicBorders(10); + + base.OnEnter(); + } + + + public void Intro2() + { + float delay = 0; + for (int i = 0; i < m_fireList.Count; i++) + { + Tween.RunFunction(delay, this, "DisplayOrb", i); + delay += 0.1f; + } + + Tween.RunFunction(delay + 0.5f, this, "Intro3"); + } + + public void DisplayOrb(int index) + { + Tween.To(m_fireList[index], 0.2f, Quad.EaseOut, "Opacity", "1"); + SoundManager.PlaySound("Boss_Fireball_Whoosh_01");//, "Boss_Fireball_Whoosh_02", "Boss_Fireball_Whoosh_03"); + } + + public void Intro3() + { + SoundManager.PlaySound("Boss_Fireball_Spawn"); + + float delay = 0; + for (int i = 0; i < m_fireList.Count; i++) + { + Tween.RunFunction(delay, this, "AbsorbOrb", i); + delay += 0.1f; + } + + //Tween.RunFunction(delay + 0.5f, this, "Intro4"); + Tween.RunFunction(delay + 0.5f, this, "DisplayBossTitle", "LOC_ID_ENEMY_NAME_122", m_boss.LocStringID, "Intro4"); + } + + public void AbsorbOrb(int index) + { + SoundManager.PlaySound("Boss_Fireball_Puff_01");//, "Boss_Fireball_Puff_02", "Boss_Fireball_Puff_03"); + Tween.To(m_fireList[index], 0.2f, Quad.EaseIn, "X", m_boss.X.ToString(), "Y", m_boss.Y.ToString()); + Tween.To(m_fireList[index], 0.1f, Tween.EaseNone, "delay", "0.1", "Opacity", "0"); + m_boss.ScaleX += m_bossStartingScale / 15f; + m_boss.ScaleY += m_bossStartingScale / 15f; + } + + public void Intro4() + { + m_boss.Visible = true; + m_boss.PlayAnimation(); + Tween.To(Player.AttachedLevel.Camera, 0.5f, Quad.EaseInOut, "delay", "0.5", "X", (Player.X + GlobalEV.Camera_XOffset).ToString(), "Y", (this.Bounds.Bottom - (Player.AttachedLevel.Camera.Bounds.Bottom - Player.AttachedLevel.Camera.Y)).ToString()); + Tween.AddEndHandlerToLastTween(this, "BeginFight"); + } + + public void BeginFight() + { + SoundManager.PlayMusic("TowerBossIntroSong", false, 1); + Player.AttachedLevel.CameraLockedToPlayer = true; + Player.UnlockControls(); + + foreach (EnemyObj enemy in EnemyList) + { + if (enemy is EnemyObj_BouncySpike) + Player.AttachedLevel.ImpactEffectPool.DisplaySpawnEffect(enemy.Position); + enemy.UnpauseEnemy(true); + enemy.Visible = true; + } + + m_cutsceneRunning = false; + } + + public override void Update(GameTime gameTime) + { + if (m_boss.CurrentHealth <= 0 && this.ActiveEnemies > 1) + { + foreach (EnemyObj enemy in EnemyList) + { + if (enemy is EnemyObj_BouncySpike) + enemy.Kill(false); + } + } + + if (m_cutsceneRunning == false) + { + if (SoundManager.IsMusicPlaying == false && m_boss.BossVersionKilled == false) + SoundManager.PlayMusic("TowerBossSong", true, 0); + } + base.Update(gameTime); + } + + public override void BossCleanup() + { + foreach (EnemyObj enemy in EnemyList) + { + if (enemy is EnemyObj_BouncySpike) + enemy.Kill(false); + } + + base.BossCleanup(); + } + + public override bool BossKilled + { + get { return m_boss.IsKilled == true; } + } + + public override void Dispose() + { + if (IsDisposed == false) + { + m_boss = null; + m_fireList.Clear(); + m_fireList = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/LastBossRoom.cs b/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/LastBossRoom.cs new file mode 100644 index 0000000..98de6c3 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Boss Rooms/LastBossRoom.cs @@ -0,0 +1,361 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Tweener.Ease; +using Tweener; + +namespace RogueCastle +{ + public class LastBossRoom : BossRoomObj + { + private EnemyObj_LastBoss m_boss; + public float BackBufferOpacity { get; set; } + + private bool m_shake = false; + private bool m_shookLeft = false; + + private float m_shakeTimer = 0.03f; + private float m_shakeDuration = 0.03f; + + private ObjContainer m_fountain; + private DoorObj m_bossDoor; + private SpriteObj m_bossDoorSprite; + + //8000 + private int m_bossCoins = 40; + private int m_bossMoneyBags = 16; + private int m_bossDiamonds = 7; + + public LastBossRoom() + { + m_roomActivityDelay = 0.5f; + } + + public override void Initialize() + { + m_boss = this.EnemyList[0] as EnemyObj_LastBoss; + + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "fountain") + m_fountain = obj as ObjContainer; + + if (obj.Name == "stainglass") + obj.Opacity = 0.5f; + + if (obj.Name == "door") + m_bossDoorSprite = obj as SpriteObj; + } + + foreach (DoorObj door in DoorList) + { + if (door.Name == "FinalBossDoor") + { + m_bossDoor = door; + m_bossDoor.Locked = true; + break; + } + } + + base.Initialize(); + } + + public override void OnEnter() + { + Player.AttachedLevel.RemoveCompassDoor(); + + m_boss.Level += LevelEV.LAST_BOSS_MODE1_LEVEL_MOD; + m_boss.CurrentHealth = m_boss.MaxHealth; + + //SoundManager.PlayMusic("CastleBossSong", true); + BackBufferOpacity = 0; + SoundManager.StopMusic(0.5f); + + StartCutscene(); + base.OnEnter(); + } + + public void StartCutscene() + { + m_cutsceneRunning = true; + + //Player.UpdateCollisionBoxes(); // Necessary check since the OnEnter() is called before player can update its collision boxes. + //Player.Y = 1440 - (60 * 5) - (Player.Bounds.Bottom - Player.Y); + Player.LockControls(); + Player.AccelerationY = 0; + Player.AttachedLevel.RunCinematicBorders(8); + Player.Flip = SpriteEffects.None; + Player.State = PlayerObj.STATE_WALKING; + + LogicSet playerMoveLS = new LogicSet(Player); + playerMoveLS.AddAction(new ChangePropertyLogicAction(Player, "IsWeighted", false)); + playerMoveLS.AddAction(new ChangePropertyLogicAction(Player, "IsCollidable", false)); + playerMoveLS.AddAction(new MoveDirectionLogicAction(new Vector2(1, 0))); + playerMoveLS.AddAction(new ChangeSpriteLogicAction("PlayerWalking_Character")); + playerMoveLS.AddAction(new PlayAnimationLogicAction(true)); + playerMoveLS.AddAction(new DelayLogicAction(1.5f)); + playerMoveLS.AddAction(new ChangePropertyLogicAction(Player, "CurrentSpeed", 0)); + playerMoveLS.AddAction(new ChangePropertyLogicAction(Player, "IsWeighted", true)); + playerMoveLS.AddAction(new ChangePropertyLogicAction(Player, "IsCollidable", true)); + Player.RunExternalLogicSet(playerMoveLS); + + Tween.RunFunction(1.6f, this, "Cutscene2"); + } + + public void Cutscene2() + { + Player.AttachedLevel.CameraLockedToPlayer = false; + Tween.By(Player.AttachedLevel.Camera, 1.5f, Quad.EaseInOut, "X", "300"); + Tween.AddEndHandlerToLastTween(this, "Cutscene3"); + } + + public void Cutscene3() + { + Tween.RunFunction(0.5f, this, "Cutscene4"); + + // Must be called first so that the tween is paused when the dialogue screen is displayed. + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + if (Game.PlayerStats.Class == ClassType.Traitor) + { + manager.DialogueScreen.SetDialogue("FinalBossTalk01_Special"); + GameUtil.UnlockAchievement("LOVE_OF_LAUGHING_AT_OTHERS"); + } + else + manager.DialogueScreen.SetDialogue("FinalBossTalk01"); + manager.DisplayScreen(ScreenType.Dialogue, true); + } + + public void Cutscene4() + { + //if (Game.PlayerStats.DiaryEntry >= LevelEV.TOTAL_JOURNAL_ENTRIES) + Tween.RunFunction(0.5f, this, "DisplayBossTitle", "LOC_ID_ENEMY_NAME_123", m_boss.LocStringID, "Cutscene5"); + //else + // Tween.RunFunction(0.5f, this, "DisplayBossTitle", "?????", "???????", "Cutscene5"); + } + + public void Cutscene5() + { + Tween.To(Player.AttachedLevel.Camera, 1f, Quad.EaseInOut, "X", Player.X.ToString()); + Tween.AddEndHandlerToLastTween(this, "BeginBattle"); + } + + public void BeginBattle() + { + //SoundManager.PlayMusic("TowerSong", true, 1); + //SoundManager.PlayMusic("CastleBossSong", true, 1); + SoundManager.PlayMusic("TitleScreenSong", true, 1); + Player.AttachedLevel.CameraLockedToPlayer = true; + Player.UnlockControls(); + m_cutsceneRunning = false; + } + + private float m_playerX = 0; + public void RunFountainCutscene() + { + Player.AttachedLevel.CameraLockedToPlayer = false; + Camera2D camera = Player.AttachedLevel.Camera; + m_playerX = camera.X; + + SoundManager.PlaySound("Cutsc_CameraMove"); + Tween.To(camera, 1f, Tweener.Ease.Quad.EaseInOut, "X", (m_fountain.Bounds.Center.X - 400).ToString()); + Tween.RunFunction(2, this, "RunFountainCutscene2"); + } + + public void RunFountainCutscene2() + { + // Animation for breaking the fountain goes here. + //SoundManager.PlayMusic("LastBossSong", true, 1); + //ProceduralLevelScreen level = Player.AttachedLevel; + //level.RunWhiteSlash2(); + //Tween.RunFunction(0, this, "DisableFountain"); + StartShake(); + SoundManager.PlaySound("Cutsc_StatueCrumble"); + m_fountain.ChangeSprite("FountainOfYouthShatter_Character"); + m_fountain.PlayAnimation(false); + Player.AttachedLevel.ImpactEffectPool.DisplayFountainShatterSmoke(m_fountain); + Tween.RunFunction(2f, this, "DisplaySecondBoss"); + Tween.RunFunction(2, this, "RunFountainCutscene3"); + } + + public void DisplaySecondBoss() + { + m_boss.SecondFormComplete(); + m_boss.UpdateCollisionBoxes(); + m_boss.Position = new Vector2(m_fountain.X, m_fountain.Y - (m_boss.Bounds.Bottom - m_boss.Y)); + } + + public void RunFountainCutscene3() + { + SoundManager.PlaySound("FinalBoss_St2_BlockLaugh"); + SoundManager.PlayMusic("LastBossSong", true, 1); + m_fountain.Visible = false; + StopShake(); + //m_boss.SecondFormComplete(); + //m_boss.UpdateCollisionBoxes(); + //m_boss.Position = new Vector2(m_fountain.X, m_fountain.Y - (m_boss.Bounds.Bottom - m_boss.Y)); + //Tween.RunFunction(2, this, "RunFountainCutscene4"); + Tween.RunFunction(2, this, "DisplayBossTitle", "LOC_ID_ENEMY_NAME_75", "LOC_ID_ENEMY_NAME_124", "RunFountainCutscene4"); + } + + public void StartShake() + { + m_shake = true; + } + + public void StopShake() + { + m_shake = false; + } + + public void DisableFountain() + { + m_fountain.Visible = false; + } + + public void RunFountainCutscene4() + { + Tween.To(Player.AttachedLevel.Camera, 1f, Tweener.Ease.Quad.EaseInOut, "X", m_playerX.ToString()); + Tween.AddEndHandlerToLastTween(m_boss, "SecondFormActive"); + } + + public override void Update(GameTime gameTime) + { + if (m_shake == true) + { + if (m_shakeTimer > 0) + { + m_shakeTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_shakeTimer <= 0) + { + Camera2D camera = Player.AttachedLevel.Camera; + + m_shakeTimer = m_shakeDuration; + if (m_shookLeft == true) + { + m_shookLeft = false; + camera.X += 5; + } + else + { + camera.X -= 5; + m_shookLeft = true; + } + } + } + } + + if (m_cutsceneRunning == false) + { + foreach (EnemyObj enemy in this.EnemyList) + { + if (enemy.IsKilled == false) + enemy.Update(gameTime); + } + + foreach (EnemyObj enemy in this.TempEnemyList) + if (enemy.IsKilled == false) + enemy.Update(gameTime); + } + } + + public override void Draw(Camera2D camera) + { + base.Draw(camera); + camera.Draw(Game.GenericTexture, new Rectangle((int)this.X, (int)this.Y, this.Width, this.Height), Color.White * BackBufferOpacity); + } + + public void ChangeWindowOpacity() + { + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "stainglass") + Tween.To(obj, 2, Tween.EaseNone, "Opacity", "0.2"); + } + } + + public override void BossCleanup() + { + Player.StopAllSpells(); + Game.PlayerStats.NewBossBeaten = true; + m_bossDoorSprite.ChangeSprite("CastleDoorOpen_Sprite"); + m_bossDoor.Locked = false; + SoundManager.PlaySound("FinalBoss_St2_WeatherChange_b"); + DropGold(); + AddEnemyKilled(); // Special handling to add the last boss to the killed list. + + //base.BossCleanup(); + } + + private void AddEnemyKilled() + { + Game.PlayerStats.NumEnemiesBeaten++; + + // Incrementing the number of times you've killed a specific type of enemy. + Vector4 enemyData = Game.PlayerStats.EnemiesKilledList[(int)m_boss.Type]; + enemyData.X += 1; + enemyData.Y += 1; + Game.PlayerStats.EnemiesKilledList[(int)m_boss.Type] = enemyData; + } + + private void DropGold() + { + int totalGold = m_bossCoins + m_bossMoneyBags + m_bossDiamonds; + List goldArray = new List(); + + for (int i = 0; i < m_bossCoins; i++) + goldArray.Add(0); + for (int i = 0; i < m_bossMoneyBags; i++) + goldArray.Add(1); + for (int i = 0; i < m_bossDiamonds; i++) + goldArray.Add(2); + + CDGMath.Shuffle(goldArray); + float coinDelay = 0;// 2.5f / goldArray.Count; // The enemy dies for 2.5 seconds. + SoundManager.PlaySound("Boss_Flash"); + + for (int i = 0; i < goldArray.Count; i++) + { + Vector2 goldPos = m_boss.Position; + if (goldArray[i] == 0) + Tween.RunFunction(i * coinDelay, Player.AttachedLevel.ItemDropManager, "DropItemWide", goldPos, ItemDropType.Coin, ItemDropType.CoinAmount); + else if (goldArray[i] == 1) + Tween.RunFunction(i * coinDelay, Player.AttachedLevel.ItemDropManager, "DropItemWide", goldPos, ItemDropType.MoneyBag, ItemDropType.MoneyBagAmount); + else + Tween.RunFunction(i * coinDelay, Player.AttachedLevel.ItemDropManager, "DropItemWide", goldPos, ItemDropType.Diamond, ItemDropType.DiamondAmount); + } + } + + protected override GameObj CreateCloneInstance() + { + return new LastBossRoom(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_fountain = null; + m_boss = null; + base.Dispose(); + } + } + + public override bool BossKilled + { + get { return m_boss.IsKilled == true && m_boss.IsSecondForm == true; } + } + + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/CastleEntranceRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/CastleEntranceRoomObj.cs new file mode 100644 index 0000000..d60cf81 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/CastleEntranceRoomObj.cs @@ -0,0 +1,393 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Tweener.Ease; +using Tweener; + +namespace RogueCastle +{ + public class CastleEntranceRoomObj : RoomObj + { + private bool m_gateClosed = false; + private PhysicsObj m_castleGate; // This doesn't need to be disposed manually because the room automatically disposes of all objects in its GameObjList. + private TeleporterObj m_teleporter; // This doesn't need to be disposed manually because the room automatically disposes of all objects in its GameObjList. + + private ObjContainer m_bossDoorSprite; + private DoorObj m_bossDoor; + + private SpriteObj m_diary; + private SpriteObj m_speechBubble; + + private TextObj m_mapText; + private KeyIconObj m_mapIcon; + + private bool m_allFilesSaved = false; + private bool m_bossDoorOpening = false; + + public CastleEntranceRoomObj() + { + m_castleGate = new PhysicsObj("CastleEntranceGate_Sprite"); + m_castleGate.IsWeighted = false; + m_castleGate.IsCollidable = true; + m_castleGate.CollisionTypeTag = GameTypes.CollisionType_WALL; + m_castleGate.Layer = -1; + m_castleGate.OutlineWidth = 2; + this.GameObjList.Add(m_castleGate); + + m_teleporter = new TeleporterObj(); + this.GameObjList.Add(m_teleporter); + } + + public override void Initialize() + { + //m_speechBubble = new SpriteObj("TalkBubbleUpArrow_Sprite"); + m_speechBubble = new SpriteObj("ExclamationSquare_Sprite"); + m_speechBubble.Flip = SpriteEffects.FlipHorizontally; + m_speechBubble.Scale = new Vector2(1.2f, 1.2f); + GameObjList.Add(m_speechBubble); + + m_mapText = new KeyIconTextObj(Game.JunicodeFont); + m_mapText.Text = LocaleBuilder.getString("LOC_ID_CASTLE_ENTRANCE_ROOM_OBJ_1", m_mapText); //"view map any time" + m_mapText.Align = Types.TextAlign.Centre; + m_mapText.FontSize = 12; + m_mapText.OutlineWidth = 2; + GameObjList.Add(m_mapText); + + m_mapIcon = new KeyIconObj(); + m_mapIcon.Scale = new Vector2(0.5f, 0.5f); + GameObjList.Add(m_mapIcon); + + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "diary") + m_diary = obj as SpriteObj; + + if (obj.Name == "map") + { + (obj as SpriteObj).OutlineWidth = 2; + m_mapText.Position = new Vector2(obj.X, obj.Bounds.Top - 50); + m_mapIcon.Position = new Vector2(m_mapText.X, m_mapText.Y - 20); + } + } + + m_diary.OutlineWidth = 2; + m_speechBubble.Position = new Vector2(m_diary.X, m_diary.Y - m_speechBubble.Height - 20); + + DoorObj leftDoor = null; + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "LastDoor") + { + m_bossDoorSprite = obj as ObjContainer; + break; + } + } + + foreach (DoorObj door in DoorList) + { + if (door.DoorPosition == "Left") + leftDoor = door; + + if (door.IsBossDoor == true) + { + m_bossDoor = door; + m_bossDoor.Locked = true; // Set to false for debugging right now. + } + } + + for (int i = 1; i < m_bossDoorSprite.NumChildren; i++) + m_bossDoorSprite.GetChildAt(i).Opacity = 0; + m_bossDoorSprite.AnimationDelay = 1 / 10f; + + m_castleGate.Position = new Vector2(leftDoor.Bounds.Right - m_castleGate.Width, leftDoor.Y - m_castleGate.Height); + m_teleporter.Position = new Vector2(this.X + this.Width / 2f - 600, this.Y + 720 - 120); + + base.Initialize(); + } + + public void RevealSymbol(GameTypes.LevelType levelType, bool tween) + { + int index = 0; + bool changeColour = false; + // index layers are completely arbitrary and determined by their layers in the spritesheet. + switch (levelType) + { + case (GameTypes.LevelType.CASTLE): + index = 1; // Eyeball symbol. + if (Game.PlayerStats.ChallengeEyeballBeaten == true) + changeColour = true; + break; + case (GameTypes.LevelType.DUNGEON): + index = 4; // Blob symbol. + if (Game.PlayerStats.ChallengeBlobBeaten == true) + changeColour = true; + break; + case (GameTypes.LevelType.GARDEN): + index = 3; // Fairy symbol. + if (Game.PlayerStats.ChallengeSkullBeaten == true) + changeColour = true; + break; + case (GameTypes.LevelType.TOWER): + index = 2; // Fireball symbol. + if (Game.PlayerStats.ChallengeFireballBeaten == true) + changeColour = true; + break; + default: + index = 5; // Last Boss Door. + if (Game.PlayerStats.ChallengeLastBossBeaten == true) + changeColour = true; + break; + } + + if (changeColour == true) + m_bossDoorSprite.GetChildAt(index).TextureColor = Color.Yellow; + else + m_bossDoorSprite.GetChildAt(index).TextureColor = Color.White; + + if (tween == true) + { + m_bossDoorSprite.GetChildAt(index).Opacity = 0; + Tween.To(m_bossDoorSprite.GetChildAt(index), 0.5f, Quad.EaseInOut, "delay", "1.5", "Opacity", "1"); + } + else + m_bossDoorSprite.GetChildAt(index).Opacity = 1; + } + + public override void OnEnter() + { + m_bossDoorOpening = false; + + if (Game.PlayerStats.ReadLastDiary == true && LinkedRoom.LinkedRoom != null) + LinkedRoom = LinkedRoom.LinkedRoom; + + Game.PlayerStats.LoadStartingRoom = false; + + if (Game.PlayerStats.DiaryEntry < 1) + m_speechBubble.Visible = true; + else + m_speechBubble.Visible = false; + + if (InputManager.GamePadIsConnected(PlayerIndex.One) == true) + { + m_mapIcon.SetButton(Game.GlobalInput.ButtonList[InputMapType.MENU_MAP]); + m_mapIcon.Scale = new Vector2(1, 1); + } + else + { + m_mapIcon.SetKey(Game.GlobalInput.KeyList[InputMapType.MENU_MAP]); + m_mapIcon.Scale = new Vector2(0.5f, 0.5f); + } + + if (m_allFilesSaved == false) + { + this.Player.Game.SaveManager.SaveAllFileTypes(false); // Save the map the moment the player enters the castle entrance. + m_allFilesSaved = true; // Prevents you from constantly saving the map over and over again. + } + + // Setting all boss states. + if (Game.PlayerStats.EyeballBossBeaten == true) + RevealSymbol(GameTypes.LevelType.CASTLE, false); + if (Game.PlayerStats.FairyBossBeaten == true) + RevealSymbol(GameTypes.LevelType.GARDEN, false); + if (Game.PlayerStats.BlobBossBeaten == true) + RevealSymbol(GameTypes.LevelType.DUNGEON, false); + if (Game.PlayerStats.FireballBossBeaten == true) + RevealSymbol(GameTypes.LevelType.TOWER, false); + + if (Game.PlayerStats.EyeballBossBeaten == true && Game.PlayerStats.FairyBossBeaten == true && Game.PlayerStats.BlobBossBeaten == true && Game.PlayerStats.FireballBossBeaten == true + && Game.PlayerStats.FinalDoorOpened == false && Player.ScaleX > 0.1f) // only run the animation if the player is actually in there. + { + //// Animation for opening the final door goes here. + PlayBossDoorAnimation(); + } + else if (Game.PlayerStats.FinalDoorOpened == true) + { + m_bossDoor.Locked = false; + m_bossDoorSprite.ChangeSprite("LastDoorOpen_Character"); + m_bossDoorSprite.GoToFrame(m_bossDoorSprite.TotalFrames); + } + + if (m_gateClosed == false) + CloseGate(true); + + if (Game.PlayerStats.EyeballBossBeaten == true && Game.PlayerStats.FairyBossBeaten == true && Game.PlayerStats.BlobBossBeaten == true && Game.PlayerStats.FireballBossBeaten == true + && Game.PlayerStats.FinalDoorOpened == false && Player.ScaleX > 0.1f) // only run the animation if the player is actually in there. + { + Game.PlayerStats.FinalDoorOpened = true; + Player.AttachedLevel.RunCinematicBorders(6); // Hack to prevent cinematic border conflict. + } + + base.OnEnter(); + } + + public void PlayBossDoorAnimation() + { + Player.StopDash(); + m_bossDoorOpening = true; + m_bossDoor.Locked = false; + Player.AttachedLevel.UpdateCamera(); + RevealSymbol(GameTypes.LevelType.NONE, true); + Player.CurrentSpeed = 0; + Player.LockControls(); + Player.AttachedLevel.CameraLockedToPlayer = false; + float storedX = Player.AttachedLevel.Camera.X; + Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "X", this.Bounds.Center.X.ToString()); + Tween.RunFunction(2.2f, this, "PlayBossDoorAnimation2", storedX); + } + + public void PlayBossDoorAnimation2(float storedX) + { + m_bossDoorSprite.ChangeSprite("LastDoorOpen_Character"); + m_bossDoorSprite.PlayAnimation(false); + SoundManager.PlaySound("LastDoor_Open"); + Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "delay", "2", "X", storedX.ToString()); + Tween.RunFunction(3.1f, this, "BossDoorAnimationComplete"); + } + + public void BossDoorAnimationComplete() + { + m_bossDoorOpening = false; + Player.UnlockControls(); + Player.AttachedLevel.CameraLockedToPlayer = true; + } + + public void ForceGateClosed() + { + m_castleGate.Y += m_castleGate.Height; + m_gateClosed = true; + } + + public override void Update(GameTime gameTime) + { + if (m_bossDoorOpening == true && Player.ControlsLocked == false) + Player.LockControls(); + + if (SoundManager.IsMusicPlaying == false) + SoundManager.PlayMusic("CastleSong", true, 0); + + // Prevents the player from going backwards. + // This is preventing the player from entering the last boss room. + if (Player.X < m_castleGate.Bounds.Right) + { + Player.X = m_castleGate.Bounds.Right + 20; + Player.AttachedLevel.UpdateCamera(); + } + + // Diary logic + Rectangle diaryBound = m_diary.Bounds; + diaryBound.X -= 50; + diaryBound.Width += 100; + m_speechBubble.Y = m_diary.Y - m_speechBubble.Height - 20 - 30 + ((float)Math.Sin(Game.TotalGameTime * 20) * 2); + if (CollisionMath.Intersects(Player.Bounds, diaryBound) && Player.IsTouchingGround == true) + { + if (m_speechBubble.SpriteName == "ExclamationSquare_Sprite") + m_speechBubble.ChangeSprite("UpArrowSquare_Sprite"); + } + else + { + if (m_speechBubble.SpriteName == "UpArrowSquare_Sprite") + m_speechBubble.ChangeSprite("ExclamationSquare_Sprite"); + } + + if (Game.PlayerStats.DiaryEntry < 1 || CollisionMath.Intersects(Player.Bounds, diaryBound) == true) + m_speechBubble.Visible = true; + else if (Game.PlayerStats.DiaryEntry >= 1 && CollisionMath.Intersects(Player.Bounds, diaryBound) == false) + m_speechBubble.Visible = false; + + + if (CollisionMath.Intersects(Player.Bounds, diaryBound) && Player.IsTouchingGround == true) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + if (Game.PlayerStats.DiaryEntry < 1) + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("DiaryEntry0"); + manager.DisplayScreen(ScreenType.Dialogue, true, null); + + Game.PlayerStats.DiaryEntry++; + } + else + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DisplayScreen(ScreenType.DiaryEntry, true); + } + } + } + + base.Update(gameTime); + } + + public void CloseGate(bool animate) + { + if (animate == true) + { + Player.Y = 381; + Player.X += 10; + Player.State = 1; // Force the player into a walking state. This state will not update until the logic set is complete. + LogicSet playerMoveLS = new LogicSet(Player); + playerMoveLS.AddAction(new RunFunctionLogicAction(Player, "LockControls")); + playerMoveLS.AddAction(new MoveDirectionLogicAction(new Vector2(1, 0))); + playerMoveLS.AddAction(new ChangeSpriteLogicAction("PlayerWalking_Character")); + playerMoveLS.AddAction(new PlayAnimationLogicAction(true)); + playerMoveLS.AddAction(new ChangePropertyLogicAction(Player, "CurrentSpeed", 200)); + playerMoveLS.AddAction(new DelayLogicAction(0.2f)); + playerMoveLS.AddAction(new ChangePropertyLogicAction(Player, "CurrentSpeed", 0)); + Player.RunExternalLogicSet(playerMoveLS); // Do not dispose this logic set. The player object will do it on its own. + + Tween.By(m_castleGate, 1.5f, Quad.EaseOut, "Y", m_castleGate.Height.ToString()); + Tween.AddEndHandlerToLastTween(Player, "UnlockControls"); + + Player.AttachedLevel.RunCinematicBorders(1.5f); + } + else + m_castleGate.Y += m_castleGate.Height; + + m_gateClosed = true; + } + + public override void Reset() + { + if (m_gateClosed == true) + { + m_castleGate.Y -= m_castleGate.Height; + m_gateClosed = false; + } + base.Reset(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_castleGate = null; + m_teleporter = null; + m_bossDoor = null; + m_bossDoorSprite = null; + + m_diary = null; + m_speechBubble = null; + m_mapText = null; + m_mapIcon = null; + base.Dispose(); + } + } + + protected override GameObj CreateCloneInstance() + { + return new CastleEntranceRoomObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/BlobChallengeRoom.cs b/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/BlobChallengeRoom.cs new file mode 100644 index 0000000..3157e03 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/BlobChallengeRoom.cs @@ -0,0 +1,418 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Tweener.Ease; +using Tweener; + +namespace RogueCastle +{ + public class BlobChallengeRoom : ChallengeBossRoomObj + { + private EnemyObj_Blob m_boss; + private EnemyObj_Blob m_boss2; + //private EnemyObj_Blob m_boss3; + private Vector2 m_startingCamPos; + + public BlobChallengeRoom() + { + m_roomActivityDelay = 0.5f; + } + + public override void Initialize() + { + m_boss = this.EnemyList[0] as EnemyObj_Blob; + m_boss.SaveToFile = false; + + + m_boss2 = this.EnemyList[1] as EnemyObj_Blob; + m_boss2.SaveToFile = false; + /* + m_boss3 = this.EnemyList[2] as EnemyObj_Blob; + m_boss3.SaveToFile = false; + */ + base.Initialize(); + } + + private void SetRoomData() + { + // Set enemy and player data here. + //Game.PlayerStats.Traits = new Vector2(TraitType.Vertigo, TraitType.None); + //Game.PlayerStats.Class = ClassType.Wizard; + m_boss.Name = "Astrodotus"; + m_boss.LocStringID = "LOC_ID_ENEMY_NAME_114"; + + m_boss.GetChildAt(0).TextureColor = Color.Green; + m_boss.GetChildAt(2).TextureColor = Color.LightGreen; + m_boss.GetChildAt(2).Opacity = 0.8f; + (m_boss.GetChildAt(1) as SpriteObj).OutlineColour = Color.Red; + m_boss.GetChildAt(1).TextureColor = Color.Red; + + m_boss2.GetChildAt(0).TextureColor = Color.Red; + m_boss2.GetChildAt(2).TextureColor = Color.LightPink; + m_boss2.GetChildAt(2).Opacity = 0.8f; + (m_boss2.GetChildAt(1) as SpriteObj).OutlineColour = Color.Black; + m_boss2.GetChildAt(1).TextureColor = Color.DarkGray; + /* + m_boss3.GetChildAt(0).TextureColor = Color.Blue; + m_boss3.GetChildAt(2).TextureColor = Color.LightBlue; + m_boss3.GetChildAt(2).Opacity = 0.8f; + (m_boss3.GetChildAt(1) as SpriteObj).OutlineColour = Color.Orange; + m_boss3.GetChildAt(1).TextureColor = Color.Orange; + */ + //Splits + m_boss.Level = 100; + m_boss.MaxHealth = 100;//15500; + m_boss.Damage = 370;//190; + m_boss.IsWeighted = false; + m_boss.TurnSpeed = 0.015f;//0.01f; + m_boss.Speed = 400;//200;//430; + m_boss.IsNeo = true; + m_boss.ChangeNeoStats(0.80f, 1.06f, 6);//(0.75f, 1.08f, 6); + m_boss.Scale = new Vector2(2, 2); + + //Fast + m_boss2.Level = m_boss.Level; + m_boss2.MaxHealth = m_boss.MaxHealth; + m_boss2.Damage = m_boss.Damage; + m_boss2.IsWeighted = m_boss.IsWeighted; + m_boss2.TurnSpeed = 0.01f;//m_boss.TurnSpeed; + m_boss2.Speed = 625;//m_boss.Speed; + m_boss2.IsNeo = m_boss.IsNeo; + m_boss2.ChangeNeoStats(0.75f, 1.160f, 5);//(0.75f, 1.175f, 5); + m_boss2.Scale = m_boss.Scale; + /* + //Slow and tanky + m_boss3.Level = m_boss.Level; + m_boss3.MaxHealth = 100;//m_boss.MaxHealth; + m_boss3.Damage = m_boss.Damage; + m_boss3.IsWeighted = m_boss.IsWeighted; + m_boss3.TurnSpeed = 0.005f;//m_boss.TurnSpeed; + m_boss3.Speed = 750f;//m_boss.Speed; + m_boss3.IsNeo = m_boss.IsNeo; + m_boss3.ChangeNeoStats(0.7f, 1.05f, 1); + m_boss3.Scale = m_boss.Scale; + */ + + //PLAYER + sbyte numEmpowered = m_storedPlayerStats.ChallengeBlobTimesUpgraded; + if (numEmpowered < 0) + numEmpowered = 0; + Player.AttachedLevel.ForcePlayerHUDLevel(numEmpowered); + + Game.PlayerStats.PlayerName = "Echidna"; + Game.PlayerStats.Class = ClassType.Dragon; + Game.PlayerStats.Spell = SpellType.DragonFireNeo; + Game.PlayerStats.IsFemale = true; + + Game.PlayerStats.BonusHealth = 450 / 5;//325/ 5; //1050//266 / 5; + Game.PlayerStats.BonusHealth += (int)(Game.PlayerStats.BonusHealth * EMPOWER_HP_AMT * numEmpowered); + + Game.PlayerStats.BonusMana = 40 / 5; + + Game.PlayerStats.BonusStrength = 50 / 1; + Game.PlayerStats.BonusStrength += (int)(Game.PlayerStats.BonusStrength * EMPOWER_PWR_AMT * numEmpowered); + + Game.PlayerStats.BonusMagic = 33 / 1; + Game.PlayerStats.BonusMagic += (int)(Game.PlayerStats.BonusMagic * EMPOWER_PWR_AMT * numEmpowered); + + Game.PlayerStats.BonusDefense = 230;//40 / 1; + Game.PlayerStats.Traits = new Vector2(TraitType.Gay, TraitType.Hypogonadism); + Player.CanBeKnockedBack = false; + //Game.PlayerStats.SpecialItem = SpecialItemType.Glasses; + //Player.Scale = new Vector2(GameEV.TRAIT_DWARFISM, GameEV.TRAIT_DWARFISM); + + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Sword] = EquipmentBaseType.Dragon; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Helm] = EquipmentBaseType.Dragon; + //Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Cape] = EquipmentBaseType.Dragon; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Limbs] = EquipmentBaseType.Dragon; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Chest] = EquipmentBaseType.Dragon; + + + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Helm] = EquipmentAbilityType.MovementSpeed; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Chest] = EquipmentAbilityType.MovementSpeed; + //Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Cape] = EquipmentAbilityType.DoubleJump; + //Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Limbs] = EquipmentAbilityType.DoubleJump; + //Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Sword] = EquipmentAbilityType.Dash; + + + // These are needed to update the player to match changes to him and the boss. + Player.IsWeighted = false; + + if (m_boss != null) + m_boss.CurrentHealth = m_boss.MaxHealth; + + if (m_boss2 != null) + m_boss2.CurrentHealth = m_boss2.MaxHealth; + /* + if (m_boss3 != null) + m_boss3.CurrentHealth = m_boss3.MaxHealth; + */ + } + + public override void OnEnter() + { + // This must go before flip to account for stereo blindness. + StorePlayerData(); + Player.Flip = SpriteEffects.FlipHorizontally; + + SetRoomData(); + + m_cutsceneRunning = true; + + SoundManager.StopMusic(0.5f); + + m_boss.AnimationDelay = 1 / 10f; + m_boss.ChangeSprite("EnemyBlobBossAir_Character"); + m_boss.PlayAnimation(); + + m_boss2.AnimationDelay = 1 / 10f; + m_boss2.ChangeSprite("EnemyBlobBossAir_Character"); + m_boss2.PlayAnimation(); + + Player.AttachedLevel.UpdateCamera(); + m_startingCamPos = Player.AttachedLevel.Camera.Position; + + Player.LockControls(); + Player.AttachedLevel.RunCinematicBorders(6f); + Player.AttachedLevel.CameraLockedToPlayer = false; + Player.AttachedLevel.Camera.Y = Player.Y; + Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "Y", m_boss.Y.ToString(), "X", m_boss.X.ToString()); + + Tween.RunFunction(1.2f, this, "DisplayBossTitle", Game.NameHelper() + " VS", m_boss.LocStringID, "Intro2"); //The Lookout + + base.OnEnter(); + + m_bossChest.ForcedItemType = ItemDropType.FountainPiece4; // Must be called after base.OnEnter() + } + + public void Intro2() + { + //Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "delay", "0.5", "Y", m_startingCamPos.Y.ToString(), "X", m_startingCamPos.X.ToString()); + Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "delay", "0.5", "X", this.Bounds.Center.X.ToString(), "Y", this.Bounds.Center.Y.ToString(), "Zoom", "0.5"); + Tween.AddEndHandlerToLastTween(this, "EndCutscene"); + } + + public void EndCutscene() + { + m_boss.Rotation = 0; + Player.IsWeighted = true; + SoundManager.PlayMusic("DungeonBoss", false, 1); + Player.AttachedLevel.CameraLockedToPlayer = false; + Player.UnlockControls(); + m_cutsceneRunning = false; + } + + public override void Update(GameTime gameTime) + { + Rectangle roomBounds = this.Bounds; + + if (Player.Y > roomBounds.Bottom) + Player.Y = roomBounds.Top + 20; + else if (Player.Y < roomBounds.Top) + Player.Y = roomBounds.Bottom - 20; + + if (Player.X > roomBounds.Right) + Player.X = roomBounds.Left + 20; + else if (Player.X < roomBounds.Left) + Player.X = roomBounds.Right - 20; + + List enemyList = Player.AttachedLevel.CurrentRoom.EnemyList; + foreach (EnemyObj enemy in enemyList) + { + if (enemy.Y > roomBounds.Bottom - 10) + enemy.Y = roomBounds.Top + 20; + else if (enemy.Y < roomBounds.Top + 10) + enemy.Y = roomBounds.Bottom - 20; + + if (enemy.X > roomBounds.Right - 10) + enemy.X = roomBounds.Left + 20; + else if (enemy.X < roomBounds.Left + 10) + enemy.X = roomBounds.Right - 20; + } + + enemyList = Player.AttachedLevel.CurrentRoom.TempEnemyList; + foreach (EnemyObj enemy in enemyList) + { + if (enemy.Y > roomBounds.Bottom - 10) + enemy.Y = roomBounds.Top + 20; + else if (enemy.Y < roomBounds.Top + 10) + enemy.Y = roomBounds.Bottom - 20; + + if (enemy.X > roomBounds.Right - 10) + enemy.X = roomBounds.Left + 20; + else if (enemy.X < roomBounds.Left + 10) + enemy.X = roomBounds.Right - 20; + } + + base.Update(gameTime); + } + + public override void Draw(Camera2D camera) + { + base.Draw(camera); + + Vector2 playerPos = Player.Position; + if (Player.X - Player.Width / 2f < this.X) + { + Player.Position = new Vector2(Player.X + this.Width, Player.Y); + Player.Draw(camera); + } + else if (Player.X + Player.Width / 2f > this.X + this.Width) + { + Player.Position = new Vector2(Player.X - this.Width, Player.Y); + Player.Draw(camera); + } + + if (Player.Y - Player.Height / 2f < this.Y) + { + Player.Position = new Vector2(Player.X, Player.Y + this.Height); + Player.Draw(camera); + } + else if (Player.Y + Player.Height / 2f > this.Y + this.Height) + { + Player.Position = new Vector2(Player.X, Player.Y - this.Height); + Player.Draw(camera); + } + Player.Position = playerPos; + + foreach (EnemyObj enemy in EnemyList) + { + Vector2 enemyPos = enemy.Position; + Rectangle enemyBounds = enemy.PureBounds; + if (enemy.X - enemy.Width / 2f < this.X) + { + enemy.Position = new Vector2(enemy.X + this.Width, enemy.Y); + enemy.Draw(camera); + } + else if (enemy.X + enemy.Width / 2f > this.X + this.Width) + { + enemy.Position = new Vector2(enemy.X - this.Width, enemy.Y); + enemy.Draw(camera); + } + + if (enemyBounds.Top < this.Y) + { + enemy.Position = new Vector2(enemy.X, enemy.Y + this.Height); + enemy.Draw(camera); + } + else if (enemyBounds.Bottom > this.Y + this.Height) + { + enemy.Position = new Vector2(enemy.X, enemy.Y - this.Height); + enemy.Draw(camera); + } + + enemy.Position = enemyPos; + } + + foreach (EnemyObj enemy in TempEnemyList) + { + enemy.ForceDraw = true; + + Vector2 enemyPos = enemy.Position; + Rectangle enemyBounds = enemy.PureBounds; + + if (enemy.X - enemy.Width / 2f < this.X) + { + enemy.Position = new Vector2(enemy.X + this.Width, enemy.Y); + enemy.Draw(camera); + } + else if (enemy.X + enemy.Width / 2f > this.X + this.Width) + { + enemy.Position = new Vector2(enemy.X - this.Width, enemy.Y); + enemy.Draw(camera); + } + + if (enemyBounds.Top < this.Y) + { + enemy.Position = new Vector2(enemy.X, enemy.Y + this.Height); + enemy.Draw(camera); + } + else if (enemyBounds.Bottom > this.Y + this.Height) + { + enemy.Position = new Vector2(enemy.X, enemy.Y - this.Height); + enemy.Draw(camera); + } + + enemy.Position = enemyPos; + } + } + + public override void OnExit() + { + if (BossKilled == false) + { + foreach (EnemyObj enemy in EnemyList) + enemy.Reset(); + } + + foreach (EnemyObj enemy in TempEnemyList) + { + enemy.KillSilently(); + enemy.Dispose(); + } + + TempEnemyList.Clear(); + Player.CanBeKnockedBack = true; + + base.OnExit(); + } + + protected override void SaveCompletionData() + { + Game.PlayerStats.ChallengeBlobBeaten = true; + GameUtil.UnlockAchievement("FEAR_OF_SPACE"); + } + + protected override GameObj CreateCloneInstance() + { + return new BlobChallengeRoom(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_boss = null; + m_boss2 = null; + base.Dispose(); + } + } + + public override bool BossKilled + { + get { return NumActiveBlobs == 0; } + } + + public int NumActiveBlobs + { + get + { + int numBlobs = 0; + foreach (EnemyObj enemy in EnemyList) + { + if (enemy.Type == EnemyType.Blob && enemy.IsKilled == false) + numBlobs++; + } + + foreach (EnemyObj enemy in TempEnemyList) + { + if (enemy.Type == EnemyType.Blob && enemy.IsKilled == false) + numBlobs++; + } + return numBlobs; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/ChallengeBossRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/ChallengeBossRoomObj.cs new file mode 100644 index 0000000..55a876d --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/ChallengeBossRoomObj.cs @@ -0,0 +1,534 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public abstract class ChallengeBossRoomObj : RoomObj + { + protected const float EMPOWER_HP_AMT = 0.20f;//0.15f; //0.125f;//EMPOWER_HP_AMT = 0.1f; + protected const float EMPOWER_PWR_AMT = 0.20f;//0.15f;//0.125f;//EMPOWER_PWR_AMT = 0.075f; + + protected bool m_cutsceneRunning = false; + protected ChestObj m_bossChest; + private float m_sparkleTimer = 0; + private bool m_teleportingOut; + private float m_roomFloor; + + private TextObj m_bossTitle1; + private TextObj m_bossTitle2; + private SpriteObj m_bossDivider; + + protected PlayerStats m_storedPlayerStats; + private int m_storedHealth; + private float m_storedMana; + private Vector2 m_storedScale; + + private List m_rainFG; + + public ChallengeBossRoomObj() + { + m_storedPlayerStats = new PlayerStats(); + } + + public override void Initialize() + { + m_bossTitle1 = new TextObj(Game.JunicodeFont); + m_bossTitle1.Text = LocaleBuilder.getString("LOC_ID_ENEMY_NAME_121", m_bossTitle1); // "The Forsaken", is this used or just overidden by DisplayBossTitle parameters + m_bossTitle1.OutlineWidth = 2; + m_bossTitle1.FontSize = 18; + + m_bossTitle2 = new TextObj(Game.JunicodeLargeFont); + m_bossTitle2.Text = LocaleBuilder.getString("LOC_ID_ENEMY_NAME_34", m_bossTitle2); // "Alexander", is this used or just overidden by DisplayBossTitle parameters + m_bossTitle2.OutlineWidth = 2; + m_bossTitle2.FontSize = 40; + + m_bossDivider = new SpriteObj("Blank_Sprite"); + m_bossDivider.OutlineWidth = 2; + + foreach (DoorObj door in DoorList) + { + m_roomFloor = door.Bounds.Bottom; + } + + m_bossChest = new ChestObj(null); + m_bossChest.Position = new Vector2(this.Bounds.Center.X - m_bossChest.Width/2f, this.Bounds.Center.Y); + this.GameObjList.Add(m_bossChest); + + m_rainFG = new List(); + for (int i = 0; i < 50; i++) + { + RaindropObj rain = new RaindropObj(new Vector2(CDGMath.RandomFloat(this.X - this.Width, this.X), CDGMath.RandomFloat(this.Y, this.Y + this.Height))); + m_rainFG.Add(rain); + rain.ChangeToParticle(); + } + + base.Initialize(); + } + + public void StorePlayerData() + { + m_storedPlayerStats = Game.PlayerStats; + Game.PlayerStats = new PlayerStats(); + Game.PlayerStats.TutorialComplete = true; // Necessary to disable nostalgia. + m_storedScale = Player.Scale; + Player.Scale = new Vector2(2, 2); + SkillSystem.ResetAllTraits(); + Player.OverrideInternalScale(Player.Scale); + + m_storedHealth = Player.CurrentHealth; + m_storedMana = Player.CurrentMana; + //m_storedPlayerStats.Spell = Game.PlayerStats.Spell; + //m_storedPlayerStats.Class = Game.PlayerStats.Class; + //m_storedPlayerStats.Traits = Game.PlayerStats.Traits; + + //m_storedPlayerStats.HeadPiece = Game.PlayerStats.HeadPiece; + //m_storedPlayerStats.ShoulderPiece = Game.PlayerStats.ShoulderPiece; + //m_storedPlayerStats.ChestPiece = Game.PlayerStats.ChestPiece; + + //m_storedPlayerStats.BonusHealth = Game.PlayerStats.BonusHealth; + //m_storedPlayerStats.BonusStrength = Game.PlayerStats.BonusStrength; + //m_storedPlayerStats.BonusMana = Game.PlayerStats.BonusMana; + //m_storedPlayerStats.BonusDefense = Game.PlayerStats.BonusDefense; + //m_storedPlayerStats.BonusWeight = Game.PlayerStats.BonusWeight; + //m_storedPlayerStats.BonusMagic = Game.PlayerStats.BonusMagic; + + //m_storedPlayerStats.LichHealth = Game.PlayerStats.LichHealth; + //m_storedPlayerStats.LichMana = Game.PlayerStats.LichMana; + //m_storedPlayerStats.LichHealthMod = Game.PlayerStats.LichHealthMod; + + //m_storedPlayerStats.WizardSpellList = Game.PlayerStats.WizardSpellList; + + //int arraySize = m_storedPlayerStats.GetEquippedArray.Length; + //for (int i = 0; i < arraySize; i++) + // m_storedPlayerStats.GetEquippedArray[i] = Game.PlayerStats.GetEquippedArray[i]; + + //arraySize = m_storedPlayerStats.GetEquippedRuneArray.Length; + //for (int i = 0; i < arraySize; i++) + // m_storedPlayerStats.GetEquippedRuneArray[i] = Game.PlayerStats.GetEquippedRuneArray[i]; + } + + public void LoadPlayerData() + { + Game.PlayerStats = m_storedPlayerStats; + + //Game.PlayerStats.Spell = m_storedPlayerStats.Spell; + //Game.PlayerStats.Class = m_storedPlayerStats.Class; + //Game.PlayerStats.Traits = m_storedPlayerStats.Traits; + + //Game.PlayerStats.HeadPiece = m_storedPlayerStats.HeadPiece; + //Game.PlayerStats.ShoulderPiece = m_storedPlayerStats.ShoulderPiece; + //Game.PlayerStats.ChestPiece = m_storedPlayerStats.ChestPiece; + + //Game.PlayerStats.BonusHealth = m_storedPlayerStats.BonusHealth; + //Game.PlayerStats.BonusStrength = m_storedPlayerStats.BonusStrength; + //Game.PlayerStats.BonusMana = m_storedPlayerStats.BonusMana; + //Game.PlayerStats.BonusDefense = m_storedPlayerStats.BonusDefense; + //Game.PlayerStats.BonusWeight = m_storedPlayerStats.BonusWeight; + //Game.PlayerStats.BonusMagic = m_storedPlayerStats.BonusMagic; + + //Game.PlayerStats.LichHealth = m_storedPlayerStats.LichHealth; + //Game.PlayerStats.LichMana = m_storedPlayerStats.LichMana; + //Game.PlayerStats.LichHealthMod = m_storedPlayerStats.LichHealthMod; + + //Game.PlayerStats.WizardSpellList = m_storedPlayerStats.WizardSpellList; + + //int arraySize = m_storedPlayerStats.GetEquippedArray.Length; + //for (int i = 0; i < arraySize; i++) + // Game.PlayerStats.GetEquippedArray[i] = m_storedPlayerStats.GetEquippedRuneArray[i]; + + //arraySize = m_storedPlayerStats.GetEquippedRuneArray.Length; + //for (int i = 0; i < arraySize; i++) + // Game.PlayerStats.GetEquippedRuneArray[i] = m_storedPlayerStats.GetEquippedRuneArray[i]; + } + + public override void OnEnter() + { + // These are needed to update the player to match changes to him and the boss. + Player.CurrentHealth = Player.MaxHealth; + Player.CurrentMana = Player.MaxMana; + Player.ChangeSprite("PlayerIdle_Character"); + Player.AttachedLevel.UpdatePlayerHUD(); + Player.AttachedLevel.UpdatePlayerHUDAbilities(); + Player.AttachedLevel.UpdatePlayerHUDSpecialItem(); + Player.AttachedLevel.UpdatePlayerSpellIcon(); + Player.UpdateEquipmentColours(); + Player.AttachedLevel.RefreshPlayerHUDPos(); + + Game.ScreenManager.GetLevelScreen().JukeboxEnabled = false; // This code is to override the jukebox. + m_bossChest.ChestType = ChestType.Boss; + m_bossChest.Visible = false; + m_bossChest.IsLocked = true; + m_bossChest.X = Player.X; + + if (m_bossChest.PhysicsMngr == null) + Player.PhysicsMngr.AddObject(m_bossChest); + m_teleportingOut = false; + + m_bossTitle1.Opacity = 0; + m_bossTitle2.Opacity = 0; + m_bossDivider.ScaleX = 0; + m_bossDivider.Opacity = 0; + + if (LevelEV.WEAKEN_BOSSES == true) + { + foreach (EnemyObj enemy in this.EnemyList) + enemy.CurrentHealth = 1; + } + base.OnEnter(); + } + + public override void OnExit() + { + // Resets the player HUD level. + Player.AttachedLevel.ForcePlayerHUDLevel(-1); + + LoadPlayerData(); + (Game.ScreenManager.Game as RogueCastle.Game).SaveManager.LoadFiles(Player.AttachedLevel, SaveType.UpgradeData); + Player.AttachedLevel.UpdatePlayerHUD(); + Player.AttachedLevel.UpdatePlayerHUDAbilities(); + Player.AttachedLevel.UpdatePlayerHUDSpecialItem(); + Player.AttachedLevel.UpdatePlayerSpellIcon(); + Player.UpdateEquipmentColours(); + Player.AttachedLevel.RefreshPlayerHUDPos(); + + // This must be called after upgrade data is loaded. + Player.CurrentHealth = m_storedHealth; + Player.CurrentMana = m_storedMana; + + if (BossKilled == true) + SaveCompletionData(); // Must be called here to make sure things that need to be saved are saved. + + Game.PlayerStats.NewBossBeaten = true; + if (this.LinkedRoom != null) + Player.AttachedLevel.CloseBossDoor(this.LinkedRoom, this.LevelType); + + (Game.ScreenManager.Game as RogueCastle.Game).SaveManager.SaveFiles(SaveType.PlayerData); + base.OnExit(); + } + + // TODO: localize bossTitle1 (player's name) + public void DisplayBossTitle(string bossTitle1, string bossTitle2LocID, string endHandler) + { + SoundManager.PlaySound("Boss_Title"); + // Setting title positions. + m_bossTitle1.Text = bossTitle1; // LocaleBuilder.getString(bossTitle1LocID, m_bossTitle1); + m_bossTitle2.Text = LocaleBuilder.getString(bossTitle2LocID, m_bossTitle2); + + Camera2D camera = Player.AttachedLevel.Camera; + if (Player.AttachedLevel.CurrentRoom is LastBossRoom) + m_bossTitle1.Position = new Vector2(camera.X - 550, camera.Y + 100); + else + m_bossTitle1.Position = new Vector2(camera.X - 550, camera.Y + 50); + m_bossTitle2.X = m_bossTitle1.X - 0; + m_bossTitle2.Y = m_bossTitle1.Y + 50; + + m_bossDivider.Position = m_bossTitle1.Position; + m_bossDivider.Y += m_bossTitle1.Height - 5; + + // Reposition the titles. + m_bossTitle1.X -= 1000; + m_bossTitle2.X += 1500; + + // Tweening the titles in. + Tween.To(m_bossDivider, 0.5f, Tween.EaseNone, "delay", "0.3", "Opacity", "1"); + Tween.To(m_bossDivider, 1, Quad.EaseInOut, "delay", "0", "ScaleX", ((float)(m_bossTitle2.Width / 5)).ToString()); + + Tween.To(m_bossTitle1, 0.5f, Tween.EaseNone, "delay", "0.3", "Opacity", "1"); + Tween.To(m_bossTitle2, 0.5f, Tween.EaseNone, "delay", "0.3", "Opacity", "1"); + Tween.By(m_bossTitle1, 1, Quad.EaseOut, "X", "1000"); + Tween.By(m_bossTitle2, 1, Quad.EaseOut, "X", "-1500"); + + // Move titles slightly after tweening. + m_bossTitle1.X += 1000; + m_bossTitle2.X -= 1500; + Tween.By(m_bossTitle1, 2f, Tween.EaseNone, "delay", "1", "X", "20"); + Tween.By(m_bossTitle2, 2f, Tween.EaseNone, "delay", "1", "X", "-20"); + m_bossTitle1.X -= 1000; + m_bossTitle2.X += 1500; + + // Add the end event handler here so that it doesn't start too late. + Tween.AddEndHandlerToLastTween(this, endHandler); + + Tween.RunFunction(3, typeof(SoundManager), "PlaySound", "Boss_Title_Exit"); + //Tweening the titles out. + m_bossTitle1.X += 1020; + m_bossTitle2.X -= 1520; + m_bossTitle1.Opacity = 1; + m_bossTitle2.Opacity = 1; + Tween.To(m_bossTitle1, 0.5f, Tween.EaseNone, "delay", "3", "Opacity", "0"); + Tween.To(m_bossTitle2, 0.5f, Tween.EaseNone, "delay", "3", "Opacity", "0"); + Tween.By(m_bossTitle1, 0.6f, Quad.EaseIn, "delay", "3", "X", "1500"); + Tween.By(m_bossTitle2, 0.6f, Quad.EaseIn, "delay", "3", "X", "-1000"); + m_bossTitle1.Opacity = 0; + m_bossTitle2.Opacity = 0; + + m_bossDivider.Opacity = 1; + Tween.To(m_bossDivider, 0.5f, Tween.EaseNone, "delay", "2.8", "Opacity", "0"); + m_bossDivider.Opacity = 0; + } + + public override void Update(GameTime gameTime) + { + foreach (RaindropObj raindrop in m_rainFG) + raindrop.UpdateNoCollision(gameTime); + + if (m_cutsceneRunning == false) + base.Update(gameTime); + + if (BossKilled == true && m_bossChest.Visible == false) + { + BossCleanup(); + m_bossChest.Visible = true; + m_bossChest.Opacity = 0; + SoundManager.PlayMusic("TitleScreenSong", true, 1); // Stinger goes here. + Tween.To(m_bossChest, 4, Tween.EaseNone, "Opacity", "1"); + Tween.To(m_bossChest, 4, Quad.EaseOut, "Y", m_roomFloor.ToString()); + Tween.AddEndHandlerToLastTween(this, "UnlockChest"); + m_sparkleTimer = 0.5f; + } + + if (m_bossChest.Visible == true && m_bossChest.IsOpen == false && BossKilled == true) + { + if (m_sparkleTimer > 0) + { + m_sparkleTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_sparkleTimer <= 0) + { + m_sparkleTimer = 0.5f; + Tween.RunFunction(0, Player.AttachedLevel.ImpactEffectPool, "DisplayChestSparkleEffect", new Vector2(m_bossChest.X, m_bossChest.Y - m_bossChest.Height / 2)); + } + } + } + else if (m_bossChest.Visible == true && m_bossChest.IsOpen == true && BossKilled == true && m_teleportingOut == false) + { + m_teleportingOut = true; + if (LevelEV.RUN_DEMO_VERSION == true) + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.DemoEnd, true); + else + TeleportPlayer(); + } + } + + protected abstract void SaveCompletionData(); + + public virtual void BossCleanup() + { + Player.StopAllSpells(); + } + + public void TeleportPlayer() + { + Player.CurrentSpeed = 0; + Vector2 storedPlayerPos = Player.Position; + Vector2 storedPlayerScale = Player.Scale; + + //Player.Scale = m_storedSize; + //Vector2 storedScale = Player.Scale; + //Tween.To(Player, 0.05f, Tweener.Ease.Linear.EaseNone, "delay", "1.3", "ScaleX", "0"); + //Player.ScaleX = 0; + //Tween.To(Player, 0.05f, Tweener.Ease.Linear.EaseNone, "delay", "3.2", "ScaleX", storedScale.X.ToString()); + //Player.ScaleX = storedScale.X; + + LogicSet teleportLS = new LogicSet(Player); + teleportLS.AddAction(new ChangePropertyLogicAction(Player.AttachedLevel, "DisableSongUpdating", true)); + teleportLS.AddAction(new RunFunctionLogicAction(Player, "LockControls")); + teleportLS.AddAction(new ChangeSpriteLogicAction("PlayerLevelUp_Character", true, false)); + teleportLS.AddAction(new DelayLogicAction(0.5f)); + teleportLS.AddAction(new PlaySoundLogicAction("Teleport_Disappear")); + teleportLS.AddAction(new RunFunctionLogicAction(this, "TeleportScaleOut")); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.ImpactEffectPool, "MegaTeleport", new Vector2(Player.X, Player.Bounds.Bottom), Player.Scale)); + teleportLS.AddAction(new DelayLogicAction(0.3f)); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.ScreenManager, "StartWipeTransition")); + teleportLS.AddAction(new DelayLogicAction(0.2f)); + teleportLS.AddAction(new RunFunctionLogicAction(this, "LoadPlayerData")); // Necessary to make sure traits that affects rooms is properly loaded when leaving. + if (this.LinkedRoom != null) + { + // Teleporting player back to room entrance. + Player.Scale = m_storedScale; + Player.OverrideInternalScale(m_storedScale); + Player.UpdateCollisionBoxes(); + Player.Position = new Vector2(this.LinkedRoom.Bounds.Center.X, (this.LinkedRoom.Bounds.Bottom - 60 - (Player.TerrainBounds.Bottom - Player.Y))); + teleportLS.AddAction(new ChangePropertyLogicAction(Player.AttachedLevel, "DisableSongUpdating", false)); + teleportLS.AddAction(new ChangePropertyLogicAction(Player, "ScaleY", m_storedScale.Y)); + teleportLS.AddAction(new TeleportLogicAction(null, Player.Position)); + teleportLS.AddAction(new DelayLogicAction(0.05f)); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.ScreenManager, "EndWipeTransition")); + teleportLS.AddAction(new DelayLogicAction(1f)); + teleportLS.AddAction(new RunFunctionLogicAction(this, "TeleportScaleIn")); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.ImpactEffectPool, "MegaTeleportReverse", new Vector2(Player.X, this.LinkedRoom.Bounds.Bottom - 60), m_storedScale)); + teleportLS.AddAction(new PlaySoundLogicAction("Teleport_Reappear")); + } + teleportLS.AddAction(new DelayLogicAction(0.2f)); + teleportLS.AddAction(new ChangePropertyLogicAction(Player, "ForceInvincible", false)); + teleportLS.AddAction(new RunFunctionLogicAction(Player, "UnlockControls")); + Player.RunExternalLogicSet(teleportLS); + Player.Position = storedPlayerPos; + Player.Scale = storedPlayerScale; + Player.UpdateCollisionBoxes(); + } + + public void TeleportScaleOut() + { + Tween.To(Player, 0.05f, Tween.EaseNone, "ScaleX", "0"); + } + + public void TeleportScaleIn() + { + Tween.To(Player, 0.05f, Tween.EaseNone, "delay", "0.15", "ScaleX", m_storedScale.X.ToString()); + } + + public void KickPlayerOut() + { + Player.AttachedLevel.PauseScreen(); + SoundManager.StopMusic(0); + Player.LockControls(); + Player.AttachedLevel.RunWhiteSlashEffect(); + SoundManager.Play3DSound(this, Game.ScreenManager.Player, "Boss_Flash"); + Player.IsWeighted = false; + Player.IsCollidable = false; + + Player.CurrentSpeed = 0; + Player.AccelerationX = 0; + Player.AccelerationY = 0; + + if (this is BlobChallengeRoom) + { + Tween.To(Player.AttachedLevel.Camera, 0.5f, Tweener.Ease.Quad.EaseInOut, "Zoom", "1", "X", Player.X.ToString(), "Y", Player.Y.ToString()); + Tween.AddEndHandlerToLastTween(this, "LockCamera"); + } + + Tween.RunFunction(1, this, "KickPlayerOut2"); + } + + public void KickPlayerOut2() + { + Player.AttachedLevel.UnpauseScreen(); + + Player.CurrentSpeed = 0; + Vector2 storedPlayerPos = Player.Position; + Vector2 storedPlayerScale = Player.Scale; + + LogicSet teleportLS = new LogicSet(Player); + teleportLS.AddAction(new ChangePropertyLogicAction(Player.AttachedLevel, "DisableSongUpdating", true)); + teleportLS.AddAction(new RunFunctionLogicAction(Player, "LockControls")); + teleportLS.AddAction(new DelayLogicAction(1.3f)); + teleportLS.AddAction(new PlaySoundLogicAction("Teleport_Disappear")); + teleportLS.AddAction(new RunFunctionLogicAction(this, "TeleportScaleOut")); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.ImpactEffectPool, "MegaTeleport", new Vector2(Player.X, Player.Bounds.Bottom), Player.Scale)); + teleportLS.AddAction(new DelayLogicAction(0.3f)); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.ScreenManager, "StartWipeTransition")); + teleportLS.AddAction(new DelayLogicAction(0.2f)); + teleportLS.AddAction(new RunFunctionLogicAction(this, "LoadPlayerData")); // Necessary to make sure traits that affects rooms is properly loaded when leaving. + if (this.LinkedRoom != null) + { + // Teleporting player back to room entrance. + Player.Scale = m_storedScale; + Player.OverrideInternalScale(m_storedScale); + Player.UpdateCollisionBoxes(); + Player.Position = new Vector2(this.LinkedRoom.Bounds.Center.X, (this.LinkedRoom.Bounds.Bottom - 60 - (Player.TerrainBounds.Bottom - Player.Y))); + teleportLS.AddAction(new ChangePropertyLogicAction(Player.AttachedLevel, "DisableSongUpdating", false)); + teleportLS.AddAction(new ChangePropertyLogicAction(Player, "ScaleY", m_storedScale.Y)); + teleportLS.AddAction(new TeleportLogicAction(null, Player.Position)); + teleportLS.AddAction(new DelayLogicAction(0.05f)); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.ScreenManager, "EndWipeTransition")); + teleportLS.AddAction(new DelayLogicAction(1f)); + teleportLS.AddAction(new RunFunctionLogicAction(this, "TeleportScaleIn")); + teleportLS.AddAction(new RunFunctionLogicAction(Player.AttachedLevel.ImpactEffectPool, "MegaTeleportReverse", new Vector2(Player.X, this.LinkedRoom.Bounds.Bottom - 60), m_storedScale)); + teleportLS.AddAction(new PlaySoundLogicAction("Teleport_Reappear")); + } + teleportLS.AddAction(new DelayLogicAction(0.2f)); + teleportLS.AddAction(new ChangePropertyLogicAction(Player, "IsWeighted", true)); + teleportLS.AddAction(new ChangePropertyLogicAction(Player, "IsCollidable", true)); + teleportLS.AddAction(new ChangePropertyLogicAction(Player, "ForceInvincible", false)); + teleportLS.AddAction(new RunFunctionLogicAction(Player, "UnlockControls")); + Player.RunExternalLogicSet(teleportLS); + Player.Position = storedPlayerPos; + Player.Scale = storedPlayerScale; + Player.UpdateCollisionBoxes(); + } + + public void LockCamera() + { + Player.AttachedLevel.CameraLockedToPlayer = true; + } + + public void UnlockChest() + { + m_bossChest.IsLocked = false; + } + + public override void Draw(Camera2D camera) + { + foreach (RaindropObj raindrop in m_rainFG) + raindrop.Draw(camera); + + base.Draw(camera); + + m_bossDivider.Draw(camera); + camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap; + m_bossTitle1.Draw(camera); + m_bossTitle2.Draw(camera); + camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointWrap; + } + + //public override void PauseRoom() + //{ + // foreach (RaindropObj rainDrop in m_rainFG) + // rainDrop.PauseAnimation(); + //} + + + //public override void UnpauseRoom() + //{ + // foreach (RaindropObj rainDrop in m_rainFG) + // rainDrop.ResumeAnimation(); + //} + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done NOT + m_bossChest = null; + m_bossDivider.Dispose(); + m_bossDivider = null; + m_bossTitle1.Dispose(); + m_bossTitle1 = null; + m_bossTitle2.Dispose(); + m_bossTitle2 = null; + + foreach (RaindropObj raindrop in m_rainFG) + raindrop.Dispose(); + m_rainFG.Clear(); + m_rainFG = null; + + base.Dispose(); + } + } + + public abstract bool BossKilled { get; } + + public int StoredHP + { + get { return m_storedHealth; } + } + + public float StoredMP + { + get { return m_storedMana; } + } + + public override void RefreshTextObjs() + { + // Can't really update boss title positioning here because could be in the middle of tween + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/EyeballChallengeRoom.cs b/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/EyeballChallengeRoom.cs new file mode 100644 index 0000000..fb30e83 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/EyeballChallengeRoom.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Tweener.Ease; +using Tweener; + +namespace RogueCastle +{ + public class EyeballChallengeRoom : ChallengeBossRoomObj + { + private EnemyObj_Eyeball m_boss; + + public EyeballChallengeRoom() + { + m_roomActivityDelay = 0.5f; + } + + public override void Initialize() + { + m_boss = this.EnemyList[0] as EnemyObj_Eyeball; + m_boss.SaveToFile = false; // Do not save Neo versions. + base.Initialize(); + } + + private void SetRoomData() + { + // Set enemy and player data here. + //Game.PlayerStats.Traits = new Vector2(TraitType.Vertigo, TraitType.None); + //Game.PlayerStats.Class = ClassType.Wizard; + + //BOSS + m_boss.GetChildAt(0).TextureColor = Color.HotPink; + m_boss.Level = 100; + m_boss.MaxHealth = 17000;//15500; + m_boss.Damage = 57; + m_boss.IsNeo = true; + + m_boss.Name = "Neo Khidr"; + m_boss.LocStringID = "LOC_ID_ENEMY_NAME_112"; + //Alexsunder + //Ponce de Freon the IcyHot + //Brohannes + + //PLAYER + + sbyte numEmpowered = m_storedPlayerStats.ChallengeEyeballTimesUpgraded; + if (numEmpowered < 0) + numEmpowered = 0; + Player.AttachedLevel.ForcePlayerHUDLevel(numEmpowered); + + //Game.PlayerStats.PlayerName = "Lady Sol the Sword"; + Game.PlayerStats.PlayerName = "McSwordy"; + Game.PlayerStats.Class = ClassType.SpellSword2; + Game.PlayerStats.Spell = SpellType.Close; + Game.PlayerStats.IsFemale = true; + + Game.PlayerStats.BonusHealth = 195 / 5;//266 / 5; + Game.PlayerStats.BonusHealth += (int)(Game.PlayerStats.BonusHealth * EMPOWER_HP_AMT * numEmpowered); + + Game.PlayerStats.BonusMana = 0 / 5; + + Game.PlayerStats.BonusStrength = 5 / 1; + Game.PlayerStats.BonusStrength += (int)(Game.PlayerStats.BonusStrength * EMPOWER_PWR_AMT * numEmpowered); + + Game.PlayerStats.BonusMagic = 190 / 1; + Game.PlayerStats.BonusMagic += (int)(Game.PlayerStats.BonusMagic * EMPOWER_PWR_AMT * numEmpowered); + + Game.PlayerStats.Traits = new Vector2(TraitType.Vertigo, TraitType.Hyperactive); + Game.PlayerStats.SpecialItem = SpecialItemType.Glasses; + //Player.Scale = new Vector2(GameEV.TRAIT_DWARFISM, GameEV.TRAIT_DWARFISM); + + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Helm] = EquipmentBaseType.Silver; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Chest] = EquipmentBaseType.Silver; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Cape] = EquipmentBaseType.Silver; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Limbs] = EquipmentBaseType.Silver; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Sword] = EquipmentBaseType.Silver; + + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Helm] = EquipmentAbilityType.DoubleJump; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Chest] = EquipmentAbilityType.DoubleJump; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Cape] = EquipmentAbilityType.Dash; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Limbs] = EquipmentAbilityType.Dash; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Sword] = EquipmentAbilityType.MovementSpeed; + + if (m_boss != null) + m_boss.CurrentHealth = m_boss.MaxHealth; + } + + public override void OnEnter() + { + StorePlayerData(); + + SetRoomData(); + + m_cutsceneRunning = true; + + SoundManager.StopMusic(0.5f); + + m_boss.ChangeSprite("EnemyEyeballBossEye_Character"); + m_boss.ChangeToBossPupil(); + m_boss.PlayAnimation(); + Player.AttachedLevel.Camera.X = (int)(this.Bounds.Left + Player.AttachedLevel.Camera.Width * 0.5f); + Player.AttachedLevel.Camera.Y = Player.Y; + Vector2 storedCameraPos = Player.AttachedLevel.Camera.Position; + + Player.LockControls(); + Player.AttachedLevel.RunCinematicBorders(6f); + Player.AttachedLevel.CameraLockedToPlayer = false; + Player.AttachedLevel.Camera.Y = Player.Y; + Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "Y", m_boss.Y.ToString()); + + Tween.RunFunction(1.2f, this, "DisplayBossTitle", Game.NameHelper() + " VS", m_boss.LocStringID, "Intro2"); + + base.OnEnter(); + + m_bossChest.ForcedItemType = ItemDropType.FountainPiece1; // Must be called after base.OnEnter() + } + + public void Intro2() + { + Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "delay", "0.5", "Y", ((int)(this.Bounds.Bottom - Player.AttachedLevel.Camera.Height * 0.5f)).ToString()); + Tween.AddEndHandlerToLastTween(this, "EndCutscene"); + } + + public void EndCutscene() + { + m_boss.Rotation = 0; + SoundManager.PlayMusic("CastleBossIntroSong", false, 1); + Player.AttachedLevel.CameraLockedToPlayer = true; + Player.UnlockControls(); + m_cutsceneRunning = false; + } + + public override void Update(GameTime gameTime) + { + if (m_cutsceneRunning == false && m_boss.BossVersionKilled == false && Player.CurrentHealth > 0) + { + if (SoundManager.IsMusicPlaying == false) + SoundManager.PlayMusic("CastleBossSong", true, 0); + } + + base.Update(gameTime); + } + + protected override void SaveCompletionData() + { + Game.PlayerStats.ChallengeEyeballBeaten = true; + GameUtil.UnlockAchievement("FEAR_OF_BLINDNESS"); + } + + public override void OnExit() + { + Player.InvincibleToSpikes = false; + base.OnExit(); + } + + protected override GameObj CreateCloneInstance() + { + return new EyeballChallengeRoom(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_boss = null; + base.Dispose(); + } + } + + public override bool BossKilled + { + get { return m_boss.IsKilled == true; } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/FairyChallengeRoom.cs b/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/FairyChallengeRoom.cs new file mode 100644 index 0000000..c586202 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/FairyChallengeRoom.cs @@ -0,0 +1,231 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Tweener.Ease; +using Tweener; + +namespace RogueCastle +{ + public class FairyChallengeRoom : ChallengeBossRoomObj + { + private EnemyObj_Fairy m_boss; + private Vector2 m_startingCamPos; + private bool m_teleportingOut = false; + + public FairyChallengeRoom() + { + m_roomActivityDelay = 0.5f; + } + + public override void Initialize() + { + m_boss = this.EnemyList[0] as EnemyObj_Fairy; + m_boss.SaveToFile = false; + m_boss.Flip = SpriteEffects.FlipHorizontally; + //m_boss2 = this.EnemyList[1] as EnemyObj_Fairy; + //m_boss2.SaveToFile = false; + base.Initialize(); + } + + private void SetRoomData() + { + // Set enemy and player data here. + //Game.PlayerStats.Traits = new Vector2(TraitType.Vertigo, TraitType.None); + //Game.PlayerStats.Class = ClassType.Wizard; + m_boss.GetChildAt(0).TextureColor = Color.Yellow; + + m_boss.Name = "Alexander the IV"; + m_boss.LocStringID = "LOC_ID_ENEMY_NAME_113"; + m_boss.Level = 100; + m_boss.MaxHealth = 15000;//15500; + m_boss.Damage = 200; + m_boss.Speed = 400; + m_boss.IsNeo = true; + + /* + m_boss.Name = "Aliceunder the Lost"; + m_boss2.TextureColor = Color.Yellow; + m_boss2.Level = 100; + m_boss2.MaxHealth = 17000;//15500; + m_boss2.Damage = 175; + m_boss2.Speed = 400; + m_boss2.IsNeo = true; + */ + + //Alexsunder + //Ponce de Freon the IcyHot + //Brohannes + + //PLAYER + sbyte numEmpowered = m_storedPlayerStats.ChallengeSkullTimesUpgraded; + if (numEmpowered < 0) + numEmpowered = 0; + Player.AttachedLevel.ForcePlayerHUDLevel(numEmpowered); + + Game.PlayerStats.PlayerName = "Wagner"; + Game.PlayerStats.Class = ClassType.Ninja2; + Game.PlayerStats.Spell = SpellType.Translocator; + Game.PlayerStats.IsFemale = false; + + Game.PlayerStats.BonusHealth = 150 / 5;//266 / 5; + Game.PlayerStats.BonusHealth += (int)(Game.PlayerStats.BonusHealth * EMPOWER_HP_AMT * numEmpowered); + + Game.PlayerStats.BonusMana = 50 / 5; + + Game.PlayerStats.BonusStrength = 150 / 1; + Game.PlayerStats.BonusStrength += (int)(Game.PlayerStats.BonusStrength * EMPOWER_PWR_AMT * numEmpowered); + + Game.PlayerStats.BonusMagic = 40 / 1; + Game.PlayerStats.BonusMagic += (int)(Game.PlayerStats.BonusMagic * EMPOWER_PWR_AMT * numEmpowered); + + Game.PlayerStats.BonusDefense = 230;//40 / 1; + Game.PlayerStats.Traits = new Vector2(TraitType.Tourettes, TraitType.OCD); + //Game.PlayerStats.SpecialItem = SpecialItemType.Glasses; + //Player.Scale = new Vector2(GameEV.TRAIT_DWARFISM, GameEV.TRAIT_DWARFISM); + + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Helm] = EquipmentBaseType.Dark; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Chest] = EquipmentBaseType.Spike; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Cape] = EquipmentBaseType.Sky; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Limbs] = EquipmentBaseType.Spike; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Sword] = EquipmentBaseType.Dark; + + //Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Helm] = EquipmentAbilityType.ManaHPGain; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Chest] = EquipmentAbilityType.DoubleJump; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Cape] = EquipmentAbilityType.DoubleJump; + //Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Limbs] = EquipmentAbilityType.ManaHPGain; + //Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Sword] = EquipmentAbilityType.ManaHPGain; + + if (m_boss != null) + m_boss.CurrentHealth = m_boss.MaxHealth; + + //if (m_boss2 != null) + // m_boss2.CurrentHealth = m_boss2.MaxHealth; + } + + public override void OnEnter() + { + m_teleportingOut = false; + + // This must go before flip to account for stereo blindness. + StorePlayerData(); + Player.Flip = SpriteEffects.None; + + SetRoomData(); + + m_cutsceneRunning = true; + + SoundManager.StopMusic(0.5f); + + m_boss.ChangeSprite("EnemyFairyGhostBossIdle_Character"); + m_boss.PlayAnimation(); + Player.AttachedLevel.UpdateCamera(); + + m_startingCamPos = Player.AttachedLevel.Camera.Position; + Player.LockControls(); + Player.AttachedLevel.RunCinematicBorders(6f); + Player.AttachedLevel.CameraLockedToPlayer = false; + Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "Y", m_boss.Y.ToString(), "X", m_boss.X.ToString()); + + Tween.RunFunction(1.2f, this, "DisplayBossTitle", Game.NameHelper() + " VS", m_boss.LocStringID, "Intro2"); //The Lookout + + base.OnEnter(); + Player.GetChildAt(PlayerPart.Sword1).TextureColor = Color.White; // Hack to change player sword since black on black looks awful. + m_bossChest.ForcedItemType = ItemDropType.FountainPiece2; // Must be called after base.OnEnter() + } + + public void Intro2() + { + Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "delay", "0.5", "Y", m_startingCamPos.Y.ToString(), "X", m_startingCamPos.X.ToString()); + Tween.AddEndHandlerToLastTween(this, "EndCutscene"); + } + + public void EndCutscene() + { + m_boss.Rotation = 0; + SoundManager.PlayMusic("GardenBossSong", false, 1); + Player.AttachedLevel.CameraLockedToPlayer = true; + Player.UnlockControls(); + m_cutsceneRunning = false; + } + + public override void Update(GameTime gameTime) + { + if (m_boss.IsKilled == true && m_teleportingOut == false) + { + Player.CurrentMana = Player.MaxMana; + } + base.Update(gameTime); + } + + public override void Draw(Camera2D camera) + { + if (m_boss.IsKilled == true && (Game.PlayerStats.Traits.X != TraitType.ColorBlind && Game.PlayerStats.Traits.Y != TraitType.ColorBlind)) + { + camera.End(); + m_boss.StopAnimation(); + + Game.HSVEffect.Parameters["Saturation"].SetValue(0); + camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, null, null, Game.HSVEffect, camera.GetTransformation()); + m_boss.Visible = true; + m_boss.Draw(camera); + m_boss.Visible = false; + camera.End(); + camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, null, null, null, camera.GetTransformation()); + } + + base.Draw(camera); + } + + public override void OnExit() + { + foreach (EnemyObj enemy in TempEnemyList) + { + enemy.KillSilently(); + enemy.Dispose(); + } + + TempEnemyList.Clear(); + + Player.InvincibleToSpikes = false; + m_teleportingOut = true; + base.OnExit(); + } + + protected override void SaveCompletionData() + { + Game.PlayerStats.ChallengeSkullBeaten = true; + GameUtil.UnlockAchievement("FEAR_OF_BONES"); + } + + protected override GameObj CreateCloneInstance() + { + return new FairyChallengeRoom(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_boss = null; + base.Dispose(); + } + } + + public override bool BossKilled + { + get { return m_boss.IsKilled == true; } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/FireballChallengeRoom.cs b/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/FireballChallengeRoom.cs new file mode 100644 index 0000000..9f23dbb --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/FireballChallengeRoom.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Tweener.Ease; +using Tweener; + +namespace RogueCastle +{ + public class FireballChallengeRoom : ChallengeBossRoomObj + { + private EnemyObj_Fireball m_boss; + + public FireballChallengeRoom() + { + m_roomActivityDelay = 0.5f; + } + + public override void Initialize() + { + m_boss = this.EnemyList[0] as EnemyObj_Fireball; + m_boss.SaveToFile = false; + m_boss.IsNeo = true; + base.Initialize(); + } + + private void SetRoomData() + { + // Set enemy and player data here. + //Game.PlayerStats.Traits = new Vector2(TraitType.Vertigo, TraitType.None); + //Game.PlayerStats.Class = ClassType.Wizard; + m_boss.GetChildAt(0).TextureColor = Color.MediumSpringGreen; + //m_boss.GetChildAt(1).TextureColor = Color.Blue; + m_boss.Name = "Ponce de Freon"; + m_boss.LocStringID = "LOC_ID_ENEMY_NAME_115"; + m_boss.Level = 100; + m_boss.MaxHealth = 12000;//15500; + m_boss.Damage = 380;//190; + m_boss.Speed = 430; + m_boss.IsNeo = true; + + //Alexsunder + //Ponce de Freon the IcyHot + //Brohannes + + //PLAYER + sbyte numEmpowered = m_storedPlayerStats.ChallengeFireballTimesUpgraded; + if (numEmpowered < 0) + numEmpowered = 0; + Player.AttachedLevel.ForcePlayerHUDLevel(numEmpowered); + + Game.PlayerStats.PlayerName = "Dovahkiin"; + Game.PlayerStats.Class = ClassType.Barbarian2; + Game.PlayerStats.Spell = SpellType.None; + Game.PlayerStats.IsFemale = false; + + Game.PlayerStats.BonusHealth = 140 / 5;//266 / 5; + Game.PlayerStats.BonusHealth += (int)(Game.PlayerStats.BonusHealth * EMPOWER_HP_AMT * numEmpowered); + + Game.PlayerStats.BonusMana = -70 / 5; + + Game.PlayerStats.BonusStrength = 150 / 1; + Game.PlayerStats.BonusStrength += (int)(Game.PlayerStats.BonusStrength * EMPOWER_PWR_AMT * numEmpowered); + + Game.PlayerStats.BonusMagic = -10 / 1; + Game.PlayerStats.BonusMagic += (int)(Game.PlayerStats.BonusMagic * EMPOWER_PWR_AMT * numEmpowered); + + Game.PlayerStats.BonusDefense = 230;//40 / 1; + Game.PlayerStats.Traits = new Vector2(TraitType.Dementia, TraitType.OCD); + //Game.PlayerStats.SpecialItem = SpecialItemType.Glasses; + //Player.Scale = new Vector2(GameEV.TRAIT_DWARFISM, GameEV.TRAIT_DWARFISM); + + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Sword] = EquipmentBaseType.Royal; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Helm] = EquipmentBaseType.Royal; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Cape] = EquipmentBaseType.Sky; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Limbs] = EquipmentBaseType.Royal; + Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Chest] = EquipmentBaseType.Royal; + + + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Helm] = EquipmentAbilityType.DoubleJump; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Chest] = EquipmentAbilityType.DoubleJump; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Cape] = EquipmentAbilityType.DoubleJump; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Limbs] = EquipmentAbilityType.DoubleJump; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Sword] = EquipmentAbilityType.Dash; + + if (m_boss != null) + m_boss.CurrentHealth = m_boss.MaxHealth; + } + + public override void OnEnter() + { + StorePlayerData(); + + SetRoomData(); + + m_cutsceneRunning = true; + + SoundManager.StopMusic(0.5f); + + m_boss.ChangeSprite("EnemyGhostBossIdle_Character"); + m_boss.PlayAnimation(); + Player.AttachedLevel.Camera.X = Player.X;// (int)(this.Bounds.Left + Player.AttachedLevel.Camera.Width * 0.5f); + Player.AttachedLevel.Camera.Y = Player.Y; + Vector2 storedCameraPos = Player.AttachedLevel.Camera.Position; + + Player.LockControls(); + Player.AttachedLevel.RunCinematicBorders(6f); + Player.AttachedLevel.CameraLockedToPlayer = false; + Player.AttachedLevel.Camera.Y = Player.Y; + Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "Y", m_boss.Y.ToString()); + + Tween.RunFunction(1.2f, this, "DisplayBossTitle", Game.NameHelper() + " VS", m_boss.LocStringID, "Intro2"); //The Lookout + + base.OnEnter(); + + m_bossChest.ForcedItemType = ItemDropType.FountainPiece3; // Must be called after base.OnEnter() + } + + public void Intro2() + { + Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "delay", "0.5", "Y", ((int)(this.Bounds.Bottom - Player.AttachedLevel.Camera.Height * 0.5f)).ToString()); + Tween.AddEndHandlerToLastTween(this, "EndCutscene"); + } + + public void EndCutscene() + { + m_boss.Rotation = 0; + SoundManager.PlayMusic("TowerBossIntroSong", false, 1); + Player.AttachedLevel.CameraLockedToPlayer = true; + Player.UnlockControls(); + m_cutsceneRunning = false; + } + + public override void Update(GameTime gameTime) + { + if (m_boss.CurrentHealth <= 0 && this.ActiveEnemies > 1) + { + foreach (EnemyObj enemy in EnemyList) + { + if (enemy is EnemyObj_BouncySpike) + enemy.Kill(false); + } + } + + if (m_cutsceneRunning == false) + { + if (SoundManager.IsMusicPlaying == false && m_boss.BossVersionKilled == false && Player.CurrentHealth > 0) + SoundManager.PlayMusic("TowerBossSong", true, 0); + } + base.Update(gameTime); + } + + protected override void SaveCompletionData() + { + Game.PlayerStats.ChallengeFireballBeaten = true; + GameUtil.UnlockAchievement("FEAR_OF_CHEMICALS"); + } + + protected override GameObj CreateCloneInstance() + { + return new FireballChallengeRoom(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_boss = null; + base.Dispose(); + } + } + + public override bool BossKilled + { + get { return m_boss.IsKilled == true; } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/LastBossChallengeRoom.cs b/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/LastBossChallengeRoom.cs new file mode 100644 index 0000000..af2f2b5 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/Challenge Boss Rooms/LastBossChallengeRoom.cs @@ -0,0 +1,237 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Tweener.Ease; +using Tweener; + +namespace RogueCastle +{ + public class LastBossChallengeRoom : ChallengeBossRoomObj + { + private EnemyObj_LastBoss m_boss; + private EnemyObj_LastBoss m_boss2; + + public LastBossChallengeRoom() + { + m_roomActivityDelay = 0.5f; + } + + public override void Initialize() + { + m_boss = this.EnemyList[0] as EnemyObj_LastBoss; + m_boss.SaveToFile = false; + + m_boss2 = this.EnemyList[1] as EnemyObj_LastBoss; + m_boss2.SaveToFile = false; + + base.Initialize(); + } + + private void SetRoomData() + { + // Set enemy and player data here. + m_boss.GetChildAt(PlayerPart.Cape).TextureColor = Color.DarkRed; + m_boss2.GetChildAt(PlayerPart.Cape).TextureColor = Color.MediumPurple; + + m_boss.GetChildAt(PlayerPart.Chest).TextureColor = Color.DarkRed; + m_boss2.GetChildAt(PlayerPart.Chest).TextureColor = Color.MediumPurple; + + m_boss.GetChildAt(PlayerPart.Head).TextureColor = Color.MediumPurple; + m_boss2.GetChildAt(PlayerPart.Head).TextureColor = Color.DarkRed; + + m_boss.GetChildAt(PlayerPart.Hair).TextureColor = Color.DarkRed; + m_boss2.GetChildAt(PlayerPart.Hair).TextureColor = Color.MediumPurple; + + m_boss.GetChildAt(PlayerPart.Legs).TextureColor = Color.MediumPurple; + m_boss2.GetChildAt(PlayerPart.Legs).TextureColor = Color.DarkRed; + + m_boss.GetChildAt(PlayerPart.Arms).TextureColor = Color.MediumPurple; + m_boss2.GetChildAt(PlayerPart.Arms).TextureColor = Color.DarkRed; + + m_boss.GetChildAt(PlayerPart.ShoulderA).TextureColor = Color.MediumPurple; + m_boss.GetChildAt(PlayerPart.ShoulderB).TextureColor = Color.MediumPurple; + m_boss2.GetChildAt(PlayerPart.ShoulderA).TextureColor = Color.DarkRed; + m_boss2.GetChildAt(PlayerPart.ShoulderB).TextureColor = Color.DarkRed; + + m_boss.GetChildAt(PlayerPart.Sword1).TextureColor = Color.White; + m_boss.GetChildAt(PlayerPart.Sword2).TextureColor = Color.DarkRed; + m_boss2.GetChildAt(PlayerPart.Sword1).TextureColor = Color.White; + m_boss2.GetChildAt(PlayerPart.Sword2).TextureColor = Color.DarkRed; + + m_boss.IsNeo = true; + m_boss2.IsNeo = true; + m_boss2.Flip = SpriteEffects.FlipHorizontally; + m_boss.Flip = SpriteEffects.None; + + m_boss.Name = "The Brohannes"; + m_boss.LocStringID = "LOC_ID_ENEMY_NAME_116"; + m_boss2.Name = m_boss.Name; + m_boss2.LocStringID = m_boss.LocStringID; + + m_boss.Level = 100; + m_boss2.Level = m_boss.Level; + + m_boss.MaxHealth = 5000;//4750;//15500; + m_boss2.MaxHealth = m_boss.MaxHealth; + + m_boss.Damage = 100;//190; + m_boss2.Damage = m_boss.Damage; + + m_boss.Speed = 345; //550; + m_boss2.Speed = m_boss.Speed; + + //m_boss.CanFallOffLedges = true; + //m_boss2.CanFallOffLedges = m_boss.CanFallOffLedges; + + //m_boss.Speed = 430; + + //Player + sbyte numEmpowered = m_storedPlayerStats.ChallengeLastBossTimesUpgraded; + if (numEmpowered < 0) + numEmpowered = 0; + Player.AttachedLevel.ForcePlayerHUDLevel(numEmpowered); + + Game.PlayerStats.PlayerName = "Johannes"; + Game.PlayerStats.Class = ClassType.Traitor; + Game.PlayerStats.IsFemale = false; + + Game.PlayerStats.BonusHealth = 900 / 5;//266 / 5; + Game.PlayerStats.BonusHealth += (int)(Game.PlayerStats.BonusHealth * EMPOWER_HP_AMT * numEmpowered); + + Game.PlayerStats.BonusMana = 330 / 5; + + Game.PlayerStats.BonusStrength = 125 / 1; + Game.PlayerStats.BonusStrength += (int)(Game.PlayerStats.BonusStrength * EMPOWER_PWR_AMT * numEmpowered); + + Game.PlayerStats.BonusMagic = 150 / 1; + Game.PlayerStats.BonusMagic += (int)(Game.PlayerStats.BonusMagic * EMPOWER_PWR_AMT * numEmpowered); + + Game.PlayerStats.BonusDefense = 0;//40 / 1; + Game.PlayerStats.Traits = new Vector2(TraitType.Hypergonadism, TraitType.None); + Game.PlayerStats.Spell = SpellType.RapidDagger; + + //Player.CanBeKnockedBack = false; + //Game.PlayerStats.SpecialItem = SpecialItemType.Glasses; + //Player.Scale = new Vector2(GameEV.TRAIT_DWARFISM, GameEV.TRAIT_DWARFISM); + + //Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Sword] = EquipmentBaseType.None; + //Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Helm] = EquipmentBaseType.None; + //Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Cape] = EquipmentBaseType.None; + //Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Limbs] = EquipmentBaseType.None; + //Game.PlayerStats.GetEquippedArray[EquipmentCategoryType.Chest] = EquipmentBaseType.None; + + + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Helm] = EquipmentAbilityType.DoubleJump; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Chest] = EquipmentAbilityType.DoubleJump; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Cape] = EquipmentAbilityType.DoubleJump; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Limbs] = EquipmentAbilityType.Dash; + Game.PlayerStats.GetEquippedRuneArray[EquipmentCategoryType.Sword] = EquipmentAbilityType.Dash; + + if (m_boss != null) + { + m_boss.CurrentHealth = m_boss.MaxHealth; + m_boss2.CurrentHealth = m_boss.MaxHealth; + } + } + + public override void OnEnter() + { + StorePlayerData(); + + SetRoomData(); + + m_cutsceneRunning = true; + + SoundManager.StopMusic(0.5f); + + m_boss.PlayAnimation(); + m_boss2.PlayAnimation(); + Player.AttachedLevel.Camera.X = Player.X;// (int)(this.Bounds.Left + Player.AttachedLevel.Camera.Width * 0.5f); + Player.AttachedLevel.Camera.Y = Player.Y; + Vector2 storedCameraPos = Player.AttachedLevel.Camera.Position; + + Player.LockControls(); + Player.AttachedLevel.RunCinematicBorders(6f); + Player.AttachedLevel.CameraLockedToPlayer = false; + Player.AttachedLevel.Camera.Y = Player.Y; + Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "Y", m_boss.Y.ToString()); + + Tween.RunFunction(1.2f, this, "DisplayBossTitle", Game.NameHelper() + LocaleBuilder.getResourceString("LOC_ID_ENEMY_NAME_123") + " VS ", m_boss.LocStringID, "Intro2"); //The Lookout + + base.OnEnter(); + + m_bossChest.ForcedItemType = ItemDropType.FountainPiece5; // Must be called after base.OnEnter() + } + + public override void OnExit() + { + if (BossKilled == false) + { + foreach (EnemyObj enemy in EnemyList) + enemy.Reset(); + } + + base.OnExit(); + } + + public void Intro2() + { + Tween.To(Player.AttachedLevel.Camera, 1, Quad.EaseInOut, "delay", "0.5", "Y", ((int)(this.Bounds.Bottom - Player.AttachedLevel.Camera.Height * 0.5f)).ToString()); + Tween.AddEndHandlerToLastTween(this, "EndCutscene"); + } + + public void EndCutscene() + { + m_boss.Rotation = 0; + SoundManager.PlayMusic("LastBossSong", false, 1); + Player.AttachedLevel.CameraLockedToPlayer = true; + Player.UnlockControls(); + m_cutsceneRunning = false; + } + + protected override void SaveCompletionData() + { + Game.PlayerStats.ChallengeLastBossBeaten = true; + + if (Game.GameConfig.UnlockTraitor <= 0 && Player != null) + { + Game.GameConfig.UnlockTraitor = 1; + Player.Game.SaveConfig(); + } + + GameUtil.UnlockAchievement("FEAR_OF_RELATIVES"); + } + + protected override GameObj CreateCloneInstance() + { + return new LastBossChallengeRoom(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_boss = null; + m_boss2 = null; + base.Dispose(); + } + } + + public override bool BossKilled + { + get { return m_boss.IsKilled == true && m_boss2.IsKilled == true; } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/CompassRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/CompassRoomObj.cs new file mode 100644 index 0000000..adacbd0 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/CompassRoomObj.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Tweener.Ease; +using Tweener; +using InputSystem; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class CompassRoomObj : RoomObj + { + public CompassRoomObj() + { + } + + public override void OnEnter() + { + if (Game.PlayerStats.SpecialItem == SpecialItemType.Compass) + { + Game.PlayerStats.SpecialItem = SpecialItemType.None; + Player.AttachedLevel.UpdatePlayerHUDSpecialItem(); + } + + SoundManager.StopMusic(2); + Player.UnlockControls(); + foreach (GameObj obj in GameObjList) + { + ChestObj chest = obj as ChestObj; + if (chest != null) + { + chest.ResetChest(); + chest.ChestType = ChestType.Gold; + } + } + base.OnEnter(); + } + + public override void OnExit() + { + Player.AttachedLevel.RemoveCompassDoor(); + Player.UnlockControls(); + Player.KickInHitInvincibility(); + base.OnExit(); + } + + protected override GameObj CreateCloneInstance() + { + return new CompassRoomObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/EndingRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/EndingRoomObj.cs new file mode 100644 index 0000000..567666a --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/EndingRoomObj.cs @@ -0,0 +1,475 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using InputSystem; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using Microsoft.Xna.Framework.Graphics; +using System.Globalization; + +namespace RogueCastle +{ + class EndingRoomObj : RoomObj + { + private SpriteObj m_endingMask; + private List m_cameraPosList; + private int m_waypointIndex; + + private List m_frameList; + private List m_nameList; + private List m_slainCountText; + private List m_plaqueList; + + private BackgroundObj m_background; + private KeyIconTextObj m_continueText; + private bool m_displayingContinueText; + private float m_waypointSpeed = 5; + + private EnemyObj_Blob m_blobBoss; + + public EndingRoomObj() + { + m_plaqueList = new List(); + } + + public override void InitializeRenderTarget(RenderTarget2D bgRenderTarget) + { + if (m_background != null) + m_background.Dispose(); + m_background = new BackgroundObj("LineageScreenBG_Sprite"); + m_background.SetRepeated(true, true, Game.ScreenManager.Camera); + m_background.X -= 1320 * 5; + m_background.Opacity = 0.7f; + + base.InitializeRenderTarget(bgRenderTarget); + } + + public override void LoadContent(Microsoft.Xna.Framework.Graphics.GraphicsDevice graphics) + { + m_continueText = new KeyIconTextObj(Game.JunicodeFont); + m_continueText.FontSize = 14; + m_continueText.Align = Types.TextAlign.Right; + m_continueText.Position = new Vector2(1320 - 50, 650); + m_continueText.ForceDraw = true; + m_continueText.Opacity = 0; + m_continueText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_continueText); // dummy locID to add TextObj to language refresh list + + m_background = new BackgroundObj("LineageScreenBG_Sprite"); + m_background.SetRepeated(true, true, Game.ScreenManager.Camera); + m_background.X -= 1320 * 5; + m_background.Opacity = 0.7f; + + m_endingMask = new SpriteObj("Blank_Sprite"); + m_endingMask.ForceDraw = true; + m_endingMask.TextureColor = Color.Black; + m_endingMask.Scale = new Vector2(1330f/m_endingMask.Width, 730f/m_endingMask.Height); + + m_cameraPosList = new List(); + m_frameList = new List(); + m_nameList = new List(); + m_slainCountText = new List(); + + foreach (GameObj obj in GameObjList) + { + if (obj is WaypointObj) + m_cameraPosList.Add(new Vector2()); + } + + // flibit didn't like this + // CultureInfo ci = (CultureInfo)CultureInfo.CurrentCulture.Clone(); + // ci.NumberFormat.CurrencyDecimalSeparator = "."; + CultureInfo ci = CultureInfo.InvariantCulture; + + foreach (GameObj obj in GameObjList) + { + if (obj is WaypointObj) + { + int index = int.Parse(obj.Name, NumberStyles.Any, ci); + m_cameraPosList[index] = obj.Position; + } + } + + float frameOffset = 150; + + foreach (EnemyObj enemy in EnemyList) + { + enemy.Initialize(); + enemy.PauseEnemy(true); + enemy.IsWeighted = false; + enemy.PlayAnimation(true); + enemy.UpdateCollisionBoxes(); + + SpriteObj frame = new SpriteObj("LineageScreenFrame_Sprite"); + frame.DropShadow = new Vector2(4, 6); + //if (enemy.Width > 150 || enemy.Height > 150) + if (enemy.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + { + frame.ChangeSprite("GiantPortrait_Sprite"); + FixMiniboss(enemy); + } + + frame.Scale = new Vector2((enemy.Width + frameOffset) / frame.Width, (enemy.Height + frameOffset) / frame.Height); + if (frame.ScaleX < 1) frame.ScaleX = 1; + if (frame.ScaleY < 1) frame.ScaleY = 1; + + frame.Position = new Vector2(enemy.X, enemy.Bounds.Top + (enemy.Height / 2f)); + m_frameList.Add(frame); + + TextObj name = new TextObj(Game.JunicodeFont); + name.FontSize = 12; + name.Align = Types.TextAlign.Centre; + name.Text = LocaleBuilder.getString(enemy.LocStringID, name); + name.OutlineColour = new Color(181, 142, 39); + name.OutlineWidth = 2; + name.Position = new Vector2(frame.X, frame.Bounds.Bottom + 40); + m_nameList.Add(name); + + TextObj numSlain = new TextObj(Game.JunicodeFont); + numSlain.FontSize = 10; + numSlain.Align = Types.TextAlign.Centre; + numSlain.OutlineColour = new Color(181, 142, 39); + numSlain.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", numSlain); // dummy locID to add TextObj to language refresh list + numSlain.OutlineWidth = 2; + numSlain.HeadingX = enemy.Type; + numSlain.HeadingY = (int)enemy.Difficulty; + numSlain.Position = new Vector2(frame.X, frame.Bounds.Bottom + 80); + m_slainCountText.Add(numSlain); + + // Some enemy fixes needed here. + switch (enemy.Type) + { + case (EnemyType.Skeleton): + if (enemy.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + { + if (enemy.Flip == SpriteEffects.None) + enemy.X -= 25; + else + enemy.X += 25; + } + break; + case (EnemyType.Fairy): + if (enemy.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + { + enemy.X += 30; + enemy.Y -= 20; + } + break; + case (EnemyType.Zombie): + enemy.ChangeSprite("EnemyZombieWalk_Character"); + enemy.PlayAnimation(true); + break; + case (EnemyType.BallAndChain): + (enemy as EnemyObj_BallAndChain).BallAndChain.Visible = false; + (enemy as EnemyObj_BallAndChain).BallAndChain2.Visible = false; + break; + case (EnemyType.Portrait): + if (enemy.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + frame.Visible = false; + break; + case (EnemyType.LastBoss): + if (enemy.Difficulty == GameTypes.EnemyDifficulty.ADVANCED) + { + (enemy as EnemyObj_LastBoss).ForceSecondForm(true); + enemy.ChangeSprite("EnemyLastBossIdle_Character"); + enemy.PlayAnimation(true); + } + + frame.ChangeSprite("GiantPortrait_Sprite"); + frame.Scale = Vector2.One; + frame.Scale = new Vector2((enemy.Width + frameOffset) / frame.Width, (enemy.Height + frameOffset) / frame.Height); + name.Position = new Vector2(frame.X, frame.Bounds.Bottom + 40); + numSlain.Position = new Vector2(frame.X, frame.Bounds.Bottom + 80); + break; + } + + SpriteObj plaque = new SpriteObj("LineageScreenPlaque1Long_Sprite"); + plaque.Scale = new Vector2(1.8f, 1.8f); + plaque.Position = new Vector2(frame.X, frame.Bounds.Bottom + 80); + m_plaqueList.Add(plaque); + } + + base.LoadContent(graphics); + } + + // Bosses aren't displayed properly, so they need to be manually fixed. + private void FixMiniboss(EnemyObj enemy) + { + switch (enemy.Type) + { + case (EnemyType.Eyeball): + enemy.ChangeSprite("EnemyEyeballBossEye_Character"); + (enemy as EnemyObj_Eyeball).ChangeToBossPupil(); + break; + case (EnemyType.Blob): + m_blobBoss = enemy as EnemyObj_Blob; + enemy.ChangeSprite("EnemyBlobBossIdle_Character"); + enemy.GetChildAt(0).TextureColor = Color.White; + enemy.GetChildAt(2).TextureColor = Color.LightSkyBlue; + enemy.GetChildAt(2).Opacity = 0.8f; + (enemy.GetChildAt(1) as SpriteObj).OutlineColour = Color.Black; + enemy.GetChildAt(1).TextureColor = Color.Black; + break; + case (EnemyType.Fireball): + enemy.ChangeSprite("EnemyGhostBossIdle_Character"); + break; + case (EnemyType.Fairy): + enemy.ChangeSprite("EnemyFairyGhostBossIdle_Character"); + break; + case (EnemyType.Skeleton): + if (enemy.Flip == SpriteEffects.None) + { + enemy.Name = "Berith"; + enemy.LocStringID = "LOC_ID_ENEMY_NAME_108"; + } + else + { + enemy.Name = "Halphas"; + enemy.LocStringID = "LOC_ID_ENEMY_NAME_111"; + } + break; + case (EnemyType.EarthWizard): + if (enemy.Flip == SpriteEffects.None) + { + enemy.Name = "Amon"; + enemy.LocStringID = "LOC_ID_ENEMY_NAME_109"; + } + else + { + enemy.Name = "Barbatos"; + enemy.LocStringID = "LOC_ID_ENEMY_NAME_106"; + } + break; + case (EnemyType.Plant): + if (enemy.Flip == SpriteEffects.None) + { + enemy.Name = "Stolas"; + enemy.LocStringID = "LOC_ID_ENEMY_NAME_107"; + } + else + { + enemy.Name = "Focalor"; + enemy.LocStringID = "LOC_ID_ENEMY_NAME_110"; + } + break; + } + + enemy.PlayAnimation(true); + } + + public override void OnEnter() + { + // Special handling for some enemies since InitializeEV overrides anything I set in LoadContent(). + m_blobBoss.PlayAnimation(true); + + foreach (EnemyObj enemy in EnemyList) + { + if (enemy.Type == EnemyType.EarthWizard) + (enemy as EnemyObj_EarthWizard).EarthProjectile.Visible = false; + } + + m_displayingContinueText = false; + UpdateEnemiesSlainText(); + m_continueText.Text = LocaleBuilder.getString("LOC_ID_ENDING_ROOM_OBJ_2_NEW", m_continueText); + m_continueText.Opacity = 0; + //Tween.To(m_continueText, 1, Tween.EaseNone, "delay", "2", "Opacity", "1"); + + Player.AttachedLevel.Camera.Position = new Vector2(0, 720 / 2f); + Player.Position = new Vector2(100, 100); + m_waypointIndex = 1; + Player.ForceInvincible = true; + Player.AttachedLevel.SetMapDisplayVisibility(false); + Player.AttachedLevel.SetPlayerHUDVisibility(false); + + SoundManager.PlayMusic("EndSongDrums", true, 1); + Game.PlayerStats.TutorialComplete = true; + Player.LockControls(); + Player.Visible = false; + Player.Opacity = 0; + Player.AttachedLevel.CameraLockedToPlayer = false; + base.OnEnter(); + ChangeWaypoints(); + } + + private void UpdateEnemiesSlainText() + { + // for simplicity, HeadingX and HeadingY in the m_numSlainTextObjs are the enemy type and difficulty respectively. + foreach (TextObj slainText in m_slainCountText) + { + int enemyType = (byte)slainText.HeadingX; + int enemyDifficulty = (int)slainText.HeadingY; + int numEnemiesSlain = 0; + + switch (enemyDifficulty) + { + case (0): + numEnemiesSlain = (int)Game.PlayerStats.EnemiesKilledList[enemyType].X; + break; + case (1): + numEnemiesSlain = (int)Game.PlayerStats.EnemiesKilledList[enemyType].Y; + break; + case (2): + numEnemiesSlain = (int)Game.PlayerStats.EnemiesKilledList[enemyType].Z; + break; + case (3): + numEnemiesSlain = (int)Game.PlayerStats.EnemiesKilledList[enemyType].W; + break; + } + + slainText.Text = LocaleBuilder.getResourceString("LOC_ID_ENDING_ROOM_OBJ_1") + ": " + numEnemiesSlain; + } + } + + public void ChangeWaypoints() + { + if (m_waypointIndex < m_cameraPosList.Count) + { + Tween.To(Player.AttachedLevel.Camera, 1.5f, Quad.EaseInOut, "X", m_cameraPosList[m_waypointIndex].X.ToString(), "Y", m_cameraPosList[m_waypointIndex].Y.ToString()); + Tween.To(Player, 1.5f, Quad.EaseInOut, "X", m_cameraPosList[m_waypointIndex].X.ToString(), "Y", m_cameraPosList[m_waypointIndex].Y.ToString()); // Player needs to follow camera otherwise barbarian shout effect will appear. + + m_waypointIndex++; + if (m_waypointIndex > m_cameraPosList.Count - 1) + { + m_waypointIndex = 0; + Tween.RunFunction(0, Player.AttachedLevel.ScreenManager, "DisplayScreen", ScreenType.Credits, true, typeof(List)); + } + else + Tween.RunFunction(m_waypointSpeed, this, "ChangeWaypoints"); + } + } + + public void ChangeLevelType() + { + this.LevelType = GameTypes.LevelType.DUNGEON; + Player.AttachedLevel.UpdateLevel(this.LevelType); + } + + public override void Update(GameTime gameTime) + { + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + if (m_displayingContinueText == true) + { + Tween.StopAll(false); + Game.ScreenManager.DisplayScreen(ScreenType.Credits, true); + } + else + { + m_displayingContinueText = true; + Tween.StopAllContaining(m_continueText, false); + Tween.To(m_continueText, 0.5f, Tween.EaseNone, "Opacity", "1"); + Tween.RunFunction(4, this, "HideContinueText"); + } + } + + base.Update(gameTime); + } + + public void HideContinueText() + { + m_displayingContinueText = false; + Tween.To(m_continueText, 0.5f, Tween.EaseNone, "delay", "0", "Opacity", "0"); + } + + + public override void Draw(Camera2D camera) + { + m_continueText.Position = new Vector2(camera.Bounds.Right - 50, camera.Bounds.Bottom - 70); + + m_endingMask.Position = camera.Position - new Vector2(660, 360); + m_endingMask.Draw(camera); + + // Hack to make an infinite scroll. + if (camera.X > m_background.X + 1320 * 5) + m_background.X = camera.X; + if (camera.X < m_background.X) + m_background.X = camera.X - 1320; + m_background.Draw(camera); + + foreach (SpriteObj frame in m_frameList) + frame.Draw(camera); + + foreach (SpriteObj plaque in m_plaqueList) + plaque.Draw(camera); + + base.Draw(camera); + camera.End(); + if (LevelEV.SHOW_ENEMY_RADII == false) + camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null, camera.GetTransformation()); // Set SpriteSortMode to immediate to allow instant changes to samplerstates. + else + camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null, camera.GetTransformation()); + + foreach (TextObj name in m_nameList) + name.Draw(camera); + + foreach (TextObj numSlain in m_slainCountText) + numSlain.Draw(camera); + + m_continueText.Draw(camera); + + camera.End(); + + if (LevelEV.SHOW_ENEMY_RADII == false) + camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, null, null, null, camera.GetTransformation()); // Set SpriteSortMode to immediate to allow instant changes to samplerstates. + else + camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, null, null, null, camera.GetTransformation()); + } + + protected override GameObj CreateCloneInstance() + { + return new EndingRoomObj(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + foreach (SpriteObj frame in m_frameList) + frame.Dispose(); + m_frameList.Clear(); + m_frameList = null; + + foreach (SpriteObj plaque in m_plaqueList) + plaque.Dispose(); + m_plaqueList.Clear(); + m_plaqueList = null; + + m_cameraPosList.Clear(); + m_cameraPosList = null; + + foreach (TextObj name in m_nameList) + name.Dispose(); + m_nameList.Clear(); + m_nameList = null; + + foreach (TextObj numSlain in m_slainCountText) + numSlain.Dispose(); + m_slainCountText.Clear(); + m_slainCountText = null; + + m_endingMask.Dispose(); + m_endingMask = null; + + m_continueText.Dispose(); + m_continueText = null; + + m_background.Dispose(); + m_background = null; + + base.Dispose(); + } + } + + public override void RefreshTextObjs() + { + UpdateEnemiesSlainText(); + //m_continueText.Text = LocaleBuilder.getResourceString("LOC_ID_ENDING_ROOM_OBJ_2") + " [Input:" + InputMapType.MENU_CONFIRM1 + "] " + LocaleBuilder.getResourceString("LOC_ID_ENDING_ROOM_OBJ_3"); + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/IntroRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/IntroRoomObj.cs new file mode 100644 index 0000000..cdda254 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/IntroRoomObj.cs @@ -0,0 +1,316 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Tweener.Ease; +using Tweener; +using InputSystem; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Audio; + +namespace RogueCastle +{ + public class IntroRoomObj : RoomObj + { + private List m_rainFG; + private Cue m_rainSFX; + private TextObj m_introText; + + private SpriteObj m_mountain1, m_mountain2; + private GameObj m_tree1, m_tree2, m_tree3; + private GameObj m_fern1, m_fern2, m_fern3; + + private float m_smokeCounter = 0; + private bool m_inSecondPart = false; + + public IntroRoomObj() + { + m_rainFG = new List(); + for (int i = 0; i < 500; i++) + { + RaindropObj rain = new RaindropObj(new Vector2(CDGMath.RandomInt(-100, 1320 * 2), CDGMath.RandomInt(-400, 720))); + m_rainFG.Add(rain); + } + } + + public override void Initialize() + { + TerrainObj blacksmithTerrain = null; + TerrainObj enchantressTerrain = null; + TerrainObj architectTerrain = null; + TerrainObj signTerrain = null; + + foreach (TerrainObj obj in TerrainObjList) + { + if (obj.Name == "BlacksmithBlock") + blacksmithTerrain = obj; + if (obj.Name == "EnchantressBlock") + enchantressTerrain = obj; + if (obj.Name == "ArchitectBlock") + architectTerrain = obj; + if (obj.Name == "SignBlock") + signTerrain = obj; + } + + if (blacksmithTerrain != null) + TerrainObjList.Remove(blacksmithTerrain); + if (enchantressTerrain != null) + TerrainObjList.Remove(enchantressTerrain); + if (architectTerrain != null) + TerrainObjList.Remove(architectTerrain); + if (signTerrain != null) + TerrainObjList.Remove(signTerrain); + + if (m_tree1 == null) + { + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "Mountains 1") + m_mountain1 = obj as SpriteObj; + else if (obj.Name == "Mountains 2") + m_mountain2 = obj as SpriteObj; + else if (obj.Name == "Sign") + obj.Visible = false; + + if (obj.Name == "Tree1") + m_tree1 = obj; + else if (obj.Name == "Tree2") + m_tree2 = obj; + else if (obj.Name == "Tree3") + m_tree3 = obj; + else if (obj.Name == "Fern1") + m_fern1 = obj; + else if (obj.Name == "Fern2") + m_fern2 = obj; + else if (obj.Name == "Fern3") + m_fern3 = obj; + } + } + + EnemyList.Clear(); + + base.Initialize(); + } + + public override void LoadContent(GraphicsDevice graphics) + { + m_introText = new TextObj(Game.JunicodeLargeFont); + m_introText.Text = LocaleBuilder.getString("LOC_ID_INTRO_ROOM_OBJ_1", m_introText); // "My duties are to my family...";//"I did everything they asked..."; + m_introText.FontSize = 25; + m_introText.ForceDraw = true; + m_introText.Align = Types.TextAlign.Centre; + m_introText.Position = new Vector2(1320 / 2f, 720 / 2f - 100); + m_introText.OutlineWidth = 2; + + base.LoadContent(graphics); + } + + public override void OnEnter() + { + SoundManager.StopMusic(); + Player.CurrentHealth = Player.MaxHealth; + Player.CurrentMana = Player.MaxMana; + + Game.PlayerStats.HeadPiece = 7; + Player.AttachedLevel.SetMapDisplayVisibility(false); + Player.AttachedLevel.SetPlayerHUDVisibility(false); + + if (m_rainSFX != null) + m_rainSFX.Dispose(); + m_rainSFX = SoundManager.PlaySound("Rain1"); + + //Player.AttachedLevel.LightningEffectTwice(); + + Player.UpdateCollisionBoxes(); // Necessary check since the OnEnter() is called before player can update its collision boxes. + Player.Position = new Vector2(10, 720 - 60 - (Player.Bounds.Bottom - Player.Y)); + Player.State = 1; // Force the player into a walking state. This state will not update until the logic set is complete. + LogicSet playerMoveLS = new LogicSet(Player); + playerMoveLS.AddAction(new RunFunctionLogicAction(Player, "LockControls")); + playerMoveLS.AddAction(new MoveDirectionLogicAction(new Vector2(1, 0))); + playerMoveLS.AddAction(new ChangeSpriteLogicAction("PlayerWalking_Character")); + playerMoveLS.AddAction(new PlayAnimationLogicAction(true)); + playerMoveLS.AddAction(new DelayLogicAction(2.5f)); + playerMoveLS.AddAction(new ChangePropertyLogicAction(Player, "CurrentSpeed", 0)); + Player.RunExternalLogicSet(playerMoveLS); // Do not dispose this logic set. The player object will do it on its own. + + Tween.RunFunction(2, this, "Intro1"); + base.OnEnter(); + } + + public void Intro1() + { + List introTextObj = new List(); + introTextObj.Add(1.0f); + introTextObj.Add(0.2f); + introTextObj.Add(4f); + introTextObj.Add(true); + introTextObj.Add(m_introText); + introTextObj.Add(false); + Game.ScreenManager.DisplayScreen(ScreenType.Text, false, introTextObj); + Tween.RunFunction(3, this, "Intro2"); + } + + public void Intro2() + { + m_inSecondPart = true; + //Player.AttachedLevel.RunCinematicBorders(10.5f); + //Player.Position = new Vector2(this.Bounds.Right - 450, this.Bounds.Bottom - 300); + Tween.RunFunction(3, Player.AttachedLevel, "LightningEffectTwice"); + //Player.State = 1; // Force the player into a walking state. This state will not update until the logic set is complete. + LogicSet playerMoveLS = new LogicSet(Player); + playerMoveLS.AddAction(new DelayLogicAction(5f)); + playerMoveLS.AddAction(new MoveDirectionLogicAction(new Vector2(1, 0))); + playerMoveLS.AddAction(new ChangeSpriteLogicAction("PlayerWalking_Character")); + playerMoveLS.AddAction(new PlayAnimationLogicAction(true)); + playerMoveLS.AddAction(new DelayLogicAction(0.7f)); + playerMoveLS.AddAction(new ChangePropertyLogicAction(Player, "CurrentSpeed", 0)); + Player.RunExternalLogicSet(playerMoveLS); + Tween.RunFunction(5.3f, this, "Intro3"); + } + + public void Intro3() + { + List introTextObj = new List(); + m_introText.Text = LocaleBuilder.getString("LOC_ID_INTRO_ROOM_OBJ_2", m_introText); //"But I am loyal only to myself.";//"And I received nothing in return..."; + introTextObj.Add(1.0f); + introTextObj.Add(0.2f); + introTextObj.Add(4f); + introTextObj.Add(true); + introTextObj.Add(m_introText); + introTextObj.Add(false); + Game.ScreenManager.DisplayScreen(ScreenType.Text, false, introTextObj); + Tween.RunFunction(4, this, "Intro4"); + } + + public void Intro4() + { + Player.Position = new Vector2(this.Bounds.Right - 450, this.Bounds.Bottom - 300); + Player.X += 700; + Player.Y = 600; + m_inSecondPart = false; + } + + public override void OnExit() + { + if (m_rainSFX != null && m_rainSFX.IsDisposed == false) + m_rainSFX.Stop(AudioStopOptions.Immediate); + } + + public override void Update(GameTime gameTime) + { + float totalGameTime = Game.TotalGameTime; + + m_tree1.Rotation = -(float)Math.Sin(totalGameTime) * 2; + m_tree2.Rotation = (float)Math.Sin(totalGameTime * 2); + m_tree3.Rotation = (float)Math.Sin(totalGameTime * 2) * 2; + m_fern1.Rotation = (float)Math.Sin(totalGameTime * 3f) / 2; + m_fern2.Rotation = -(float)Math.Sin(totalGameTime * 4f); + m_fern3.Rotation = (float)Math.Sin(totalGameTime * 4f) / 2f; + + foreach (RaindropObj raindrop in m_rainFG) + raindrop.Update(this.TerrainObjList, gameTime); + + if (m_inSecondPart == true) + { + if (m_smokeCounter < 0.2f) + { + m_smokeCounter += (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_smokeCounter >= 0.2f) + { + m_smokeCounter = 0; + Player.AttachedLevel.ImpactEffectPool.DisplayMassiveSmoke(new Vector2(Player.AttachedLevel.Camera.X + 300, Player.AttachedLevel.Camera.Bounds.Top)); + Player.AttachedLevel.ImpactEffectPool.DisplayMassiveSmoke(new Vector2(Player.AttachedLevel.Camera.X + 380, Player.AttachedLevel.Camera.Bounds.Top)); + //Player.AttachedLevel.ImpactEffectPool.DisplayMassiveSmoke(new Vector2(Player.AttachedLevel.Camera.X + 460, Player.AttachedLevel.Camera.Bounds.Top)); + //Player.AttachedLevel.ImpactEffectPool.DisplayMassiveSmoke(new Vector2(Player.AttachedLevel.Camera.X + 540, Player.AttachedLevel.Camera.Bounds.Top)); + //Player.AttachedLevel.ImpactEffectPool.DisplayMassiveSmoke(new Vector2(Player.AttachedLevel.Camera.X + 620, Player.AttachedLevel.Camera.Bounds.Top)); + //Player.AttachedLevel.ImpactEffectPool.DisplayMassiveSmoke(new Vector2(Player.AttachedLevel.Camera.X + 700, Player.AttachedLevel.Camera.Bounds.Top)); + //Player.AttachedLevel.ImpactEffectPool.DisplayMassiveSmoke(new Vector2(Player.AttachedLevel.Camera.X + 780, Player.AttachedLevel.Camera.Bounds.Top)); + } + } + + } + + base.Update(gameTime); + } + + public override void Draw(Camera2D camera) + { + m_mountain1.X = camera.TopLeftCorner.X * 0.5f; + m_mountain2.X = m_mountain1.X + 2640; // 2640 not 1320 because it is mountain1 flipped. + + base.Draw(camera); + camera.Draw(Game.GenericTexture, new Rectangle(0, 0, 1320 * 2, 720), Color.Black * 0.6f); + foreach (RaindropObj raindrop in m_rainFG) + raindrop.Draw(camera); + + if (m_inSecondPart == true) + camera.Draw(Game.GenericTexture, new Rectangle(1650, 0, 3000, 720), Color.Black); + } + + + public override void PauseRoom() + { + foreach (RaindropObj rainDrop in m_rainFG) + rainDrop.PauseAnimation(); + + if (m_rainSFX != null) + m_rainSFX.Pause(); + + //base.PauseRoom(); + } + + public override void UnpauseRoom() + { + foreach (RaindropObj rainDrop in m_rainFG) + rainDrop.ResumeAnimation(); + + if (m_rainSFX != null && m_rainSFX.IsPaused) + m_rainSFX.Resume(); + + //base.UnpauseRoom(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + foreach (RaindropObj raindrop in m_rainFG) + raindrop.Dispose(); + m_rainFG.Clear(); + m_rainFG = null; + + m_mountain1 = null; + m_mountain2 = null; + + if (m_rainSFX != null) + m_rainSFX.Dispose(); + m_rainSFX = null; + + m_tree1 = null; + m_tree2 = null; + m_tree3 = null; + m_fern1 = null; + m_fern2 = null; + m_fern3 = null; + + m_introText.Dispose(); + m_introText = null; + + base.Dispose(); + } + } + + protected override GameObj CreateCloneInstance() + { + return new IntroRoomObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/RoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/RoomObj.cs new file mode 100644 index 0000000..fc81ae6 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/RoomObj.cs @@ -0,0 +1,1048 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System.Globalization; +using Tweener; + +namespace RogueCastle +{ + public class RoomObj : GameObj + { + public bool AddToCastlePool { get; set; } + public bool AddToGardenPool { get; set; } + public bool AddToTowerPool { get; set; } + public bool AddToDungeonPool { get; set; } + public bool IsDLCMap { get; set; } + + public GameTypes.LevelType LevelType { get; set; } + public int Level { get; set; } + public List DoorList { get; internal set; } + public List EnemyList { get; internal set; } + public List TerrainObjList { get; internal set; } + public List GameObjList { get; internal set; } + public List BorderList { get; internal set; } + public List TempEnemyList { get; internal set; } // A list used for enemies that are created temporarily, like split blobs. + + public int PoolIndex = -1; // The index number of the room from the pool in LevelBuilder. + public bool IsReversed { get; internal set; } + private int m_roomNumber = -1; // The order number of when this room was built. Used for debugging. + + protected float m_roomActivityDelay = 0.2f;//0.5f;m_empower + private float m_roomActivityCounter = 0; + + protected float m_doorSparkleDelay = 0.2f; + + public RoomObj LinkedRoom { get; set; } // Linked room. Primarily used for linking boss rooms to boss entrances. + + public string RedEnemyType; + public string BlueEnemyType; + public string GreenEnemyType; + + private TextObj m_fairyChestText; + + private TextObj m_indexText; // purely for debug. Remove later. + private TextObj m_roomInfoText; // more debug. + private Vector2 m_debugRoomPosition; + + private RenderTarget2D m_bwRender; + + public PlayerObj Player; + private SpriteObj m_pauseBG; + + public NpcObj DonationBox { get; set; } + + private int[] m_empowerCostArray = {7500, 15000, 30000, 45000, 67500, 90000, 120000, 150000, 187500, 225000}; //Super cheap, 17.5% increase Max at 175% + //{10000, 25000, 47500, 77500, 115000, 160000, 212500, 272500, 340000, 415000}; //50% of costs, and 15%stats and hp. Might be good. Max at 150% everything. + //{ 7500, 15000, 30000, 52500, 82500, 120000, 165000, 217500, 277500, 345000}; 12.5%stats, 12.5% hp. 25% of cost. Not tested + //{ 5000, 10000, 20000, 40000, 80000, 160000, 320000, 640000, 1280000, 2560000 }; //7.5% stats, 1%hp. Too expensive, too little buffs + + public RoomObj() + { + GameObjList = new List(); + TerrainObjList = new List(); + DoorList = new List(); + EnemyList = new List(); + BorderList = new List(); + TempEnemyList = new List(); + + LevelType = GameTypes.LevelType.NONE; + + m_indexText = new TextObj(Game.PixelArtFontBold); + m_indexText.FontSize = 150; + m_indexText.Align = Types.TextAlign.Centre; + + m_roomInfoText = new TextObj(Game.PixelArtFontBold); + m_roomInfoText.FontSize = 30; + m_roomInfoText.Align = Types.TextAlign.Centre; + + m_fairyChestText = new TextObj(Game.JunicodeFont); + m_fairyChestText.FontSize = 26; + m_fairyChestText.Position = new Vector2(300, 20); + m_fairyChestText.DropShadow = new Vector2(2, 2); + m_fairyChestText.Text = ""; + //m_fairyChestText.Align = Types.TextAlign.Centre; + + m_pauseBG = new SpriteObj("Blank_Sprite"); + m_pauseBG.TextureColor = Color.Black; + m_pauseBG.Opacity = 0; + + IsReversed = false; + } + + public virtual void Initialize() { } + + public virtual void LoadContent(GraphicsDevice graphics) { } + + public virtual void OnEnter() + { + m_roomActivityCounter = m_roomActivityDelay; + foreach (GameObj obj in GameObjList) + { + FairyChestObj fairyChest = obj as FairyChestObj; + if (fairyChest != null && fairyChest.State == ChestConditionChecker.STATE_FAILED && fairyChest.ConditionType != ChestConditionType.InvisibleChest && fairyChest.ConditionType != ChestConditionType.None) + Player.AttachedLevel.ObjectiveFailed(); + } + + bool doorClosed = false; + if (DonationBox != null) + { + DonationBox.CanTalk = true; + DonationBox.Visible = true; + + foreach (DoorObj door in DoorList) + { + if (door.Name == "BossDoor" && door.Locked == true) + { + doorClosed = true; + break; + } + } + + if (doorClosed == true || (this.LinkedRoom is ChallengeBossRoomObj == false)) + { + DonationBox.CanTalk = false; + DonationBox.Visible = false; + } + } + } + + public virtual void OnExit() + { + Player.AttachedLevel.ResetObjectivePlate(false); + + for (int i = 0; i < this.TempEnemyList.Count; i++) + { + if (TempEnemyList[i].IsDemented == true) + { + Player.AttachedLevel.RemoveEnemyFromRoom(TempEnemyList[i], this); + i--; + } + } + } + + public virtual void InitializeRenderTarget(RenderTarget2D bgRenderTarget) + { + //m_bwRender = new RenderTarget2D(device, GlobalEV.ScreenWidth, GlobalEV.ScreenHeight); + //m_bwRender = new RenderTarget2D(device, GlobalEV.ScreenWidth, GlobalEV.ScreenHeight, false, SurfaceFormat., null); + m_bwRender = bgRenderTarget; + } + + public void SetWidth(int width) + { + _width = width; + m_pauseBG.Scale = Vector2.One; + m_pauseBG.Scale = new Vector2((this.Width + 20) / m_pauseBG.Width, (this.Height + 20) / m_pauseBG.Height); + } + + public void SetHeight(int height) + { + _height = height; + m_pauseBG.Scale = Vector2.One; + m_pauseBG.Scale = new Vector2((this.Width + 20) / m_pauseBG.Width, (this.Height + 20) / m_pauseBG.Height); + } + + public void BuffPlayer() + { + int cost = GetChallengeRoomCost(); + if (Game.PlayerStats.Gold >= cost && cost > 0) + { + Game.PlayerStats.Gold -= cost; + switch (GetChallengeRoomType()) + { + case (0): + Game.PlayerStats.ChallengeEyeballTimesUpgraded++; + break; + case (1): + Game.PlayerStats.ChallengeSkullTimesUpgraded++; + break; + case (2): + Game.PlayerStats.ChallengeFireballTimesUpgraded++; + break; + case (3): + Game.PlayerStats.ChallengeBlobTimesUpgraded++; + break; + case (4): + Game.PlayerStats.ChallengeLastBossTimesUpgraded++; + break; + } + + (Game.ScreenManager.Game as RogueCastle.Game).SaveManager.SaveFiles(SaveType.PlayerData); + + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("DonationBoxTalkUpgraded"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true, null); + + // Text effect of the gold cost. + Player.AttachedLevel.TextManager.DisplayNumberStringText(-(int)cost, "LOC_ID_CARNIVAL_BONUS_ROOM_4" /*"gold"*/, Color.Yellow, new Vector2(Player.X, Player.Bounds.Top)); + } + else if (cost < 0) + { + // Already maxxed empowered + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("DonationBoxTalkMaxxed"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true, null); + } + else + { + // Can't afford it. + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("DonationBoxTalkPoor"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true, null); + } + } + + private sbyte GetChallengeRoomTimesUpgraded() + { + sbyte timesUpgraded = 0; + + switch (GetChallengeRoomType()) + { + case (0): + timesUpgraded = Game.PlayerStats.ChallengeEyeballTimesUpgraded; + break; + case (1): + timesUpgraded = Game.PlayerStats.ChallengeSkullTimesUpgraded; + break; + case (2): + timesUpgraded = Game.PlayerStats.ChallengeFireballTimesUpgraded; + break; + case (3): + timesUpgraded = Game.PlayerStats.ChallengeBlobTimesUpgraded; + break; + case (4): + timesUpgraded = Game.PlayerStats.ChallengeLastBossTimesUpgraded; + break; + } + return timesUpgraded; + } + + private int GetChallengeRoomCost() + { + int cost = int.MaxValue; + sbyte timesUpgraded = GetChallengeRoomTimesUpgraded(); + if (timesUpgraded < m_empowerCostArray.Length - 1) + cost = m_empowerCostArray[timesUpgraded]; + else + cost = -1; + + return cost; + } + + private int GetChallengeRoomType() // -1 is not challenge room + { + if (LinkedRoom is EyeballChallengeRoom) + return 0; + if (LinkedRoom is FairyChallengeRoom) + return 1; + if (LinkedRoom is FireballChallengeRoom) + return 2; + if (LinkedRoom is BlobChallengeRoom) + return 3; + if (LinkedRoom is LastBossChallengeRoom) + return 4; + + return -1; + } + + public virtual void Update(GameTime gameTime) + { + if (this.Name == "EntranceBoss" && this.LinkedRoom is ChallengeBossRoomObj) + { + if (DonationBox != null) + { + DonationBox.Update(gameTime, Player); + + if (DonationBox.IsTouching == true) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + sbyte timesUpgraded = GetChallengeRoomTimesUpgraded(); + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + if (timesUpgraded < m_empowerCostArray.Length - 1) + { + manager.DialogueScreen.SetDialogue("DonationBoxTalk01", GetChallengeRoomCost(), timesUpgraded); + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "BuffPlayer"); + manager.DialogueScreen.SetCancelEndHandler(typeof(Console), "WriteLine", "Canceling Selection"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true, null); + } + else + { + // Already maxxed empowered + manager.DialogueScreen.SetDialogue("DonationBoxTalkMaxxed"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true, null); + } + } + } + } + + if (m_doorSparkleDelay <= 0) + { + m_doorSparkleDelay = 0.1f; + Player.AttachedLevel.ImpactEffectPool.DoorSparkleEffect(new Rectangle((int)this.X + 590, (int)this.Y + 140, 190, 150)); + } + else + m_doorSparkleDelay -= (float)gameTime.ElapsedGameTime.TotalSeconds; + } + + if (m_roomActivityCounter <= 0) + { + foreach (EnemyObj enemy in this.EnemyList) + { + if (enemy.IsKilled == false) + enemy.Update(gameTime); + } + + foreach (EnemyObj enemy in this.TempEnemyList) + if (enemy.IsKilled == false) + enemy.Update(gameTime); + } + else + m_roomActivityCounter -= (float)gameTime.ElapsedGameTime.TotalSeconds; + } + + // This method creates a Black/White Render target of the room's collision hulls. The render target will be used as a mask for applying a foreground texture to these collision hulls. + public void DrawRenderTargets(Camera2D camera) + { + camera.GraphicsDevice.SetRenderTarget(m_bwRender); + camera.GraphicsDevice.Clear(Color.White); + + foreach (TerrainObj obj in TerrainObjList) + { + if (obj.Visible == true && obj.Height > 40 && obj.ShowTerrain == true) + { + obj.ForceDraw = true; + obj.TextureColor = Color.Black; + obj.Draw(camera); + obj.ForceDraw = false; + obj.TextureColor = Color.White; + } + } + } + + public void DrawBGObjs(Camera2D camera) + { + foreach (GameObj obj in GameObjList) + { + if (obj.Layer == -1) + obj.Draw(camera); + } + } + + public override void Draw(Camera2D camera) + { + if (camera.Zoom != 1) + { + foreach (TerrainObj obj in TerrainObjList) + { + obj.Draw(camera); // Keep this so you can see levels when zoomed out. + //(obj as TerrainObj).DrawBorders(camera); + } + } + + foreach (BorderObj border in BorderList) + border.Draw(camera); + + //SamplerState storedState = camera.GraphicsDevice.SamplerStates[0]; + + //camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + foreach (BorderObj border in BorderList) + { + if (border.Rotation == 0) + border.DrawCorners(camera); + } + + //camera.GraphicsDevice.SamplerStates[0] = storedState; + + foreach (GameObj obj in GameObjList) + { + if (obj.Layer == 0) + obj.Draw(camera); + } + + // Temporary fix for chests. Not very performance efficient though. + foreach (GameObj obj in GameObjList) + { + if (obj.Layer == 1) + obj.Draw(camera); // For chests + } + + m_pauseBG.Position = this.Position; + m_pauseBG.Draw(camera); + + foreach (EnemyObj enemy in EnemyList) + enemy.Draw(camera); + + foreach (EnemyObj enemy in TempEnemyList) + enemy.Draw(camera); + + // These need to be drawn to display door arrows. + foreach (DoorObj door in DoorList) + door.Draw(camera); + + if (LevelEV.SHOW_DEBUG_TEXT == true) + { + m_indexText.Position = new Vector2(this.Position.X + this.Width / 2, this.Position.Y + this.Height / 2 - m_indexText.Height / 2); + m_indexText.Draw(camera); + m_roomInfoText.Position = new Vector2(this.Position.X + this.Width / 2, this.Position.Y); + m_roomInfoText.Draw(camera); + } + + m_fairyChestText.Draw(camera); + } + + public virtual void Reset() + { + int enemyNum = EnemyList.Count; + //foreach (EnemyObj enemy in EnemyList) + for (int i = 0; i < enemyNum; i++) + { + EnemyList[i].Reset(); + // Needed in case something like a generated blob needs to be removed from the room. + if (enemyNum != EnemyList.Count) + { + i--; + enemyNum = EnemyList.Count; + } + } + + for (int i = 0; i < TempEnemyList.Count; i++) + { + TempEnemyList[i].Reset(); + i--; // Enemies are removed from the templist on reset. + } + } + + // Flips all objects in the room along the horizontal axis, including doors. + public void Reverse() + { + IsReversed = true; + float centrePtX = this.X + this.Width / 2; + + foreach (TerrainObj obj in TerrainObjList) + { + if (obj.Name == "Left") obj.Name = "Right"; + else if (obj.Name == "Right") obj.Name = "Left"; + else if (obj.Name == "!Left") obj.Name = "!Right"; + else if (obj.Name == "!Right") obj.Name = "!Left"; + else if (obj.Name == "!RightTop") obj.Name = "!LeftTop"; + else if (obj.Name == "!RightBottom") obj.Name = "!LeftBottom"; + else if (obj.Name == "!LeftTop") obj.Name = "!RightTop"; + else if (obj.Name == "!LeftBottom") obj.Name = "!RightBottom"; + else if (obj.Name == "RightTop") obj.Name = "LeftTop"; + else if (obj.Name == "RightBottom") obj.Name = "LeftBottom"; + else if (obj.Name == "LeftTop") obj.Name = "RightTop"; + else if (obj.Name == "LeftBottom") obj.Name = "RightBottom"; + else if (obj.Name == "!BottomLeft") obj.Name = "!BottomRight"; + else if (obj.Name == "!BottomRight") obj.Name = "!BottomLeft"; + else if (obj.Name == "!TopLeft") obj.Name = "!TopRight"; + else if (obj.Name == "!TopRight") obj.Name = "!TopLeft"; + else if (obj.Name == "BottomLeft") obj.Name = "BottomRight"; + else if (obj.Name == "BottomRight") obj.Name = "BottomLeft"; + else if (obj.Name == "TopLeft") obj.Name = "TopRight"; + else if (obj.Name == "TopRight") obj.Name = "TopLeft"; + + float distFromCentreX = obj.X - centrePtX; + if (distFromCentreX >= 0) + { + if (obj.Rotation == 0) + obj.X -= (distFromCentreX * 2 + obj.Width); + else + { + Vector2 topRight = CollisionMath.UpperRightCorner(new Rectangle((int)obj.X, (int)obj.Y, obj.Width, obj.Height), obj.Rotation, Vector2.Zero); + topRight.X -= (topRight.X - centrePtX) * 2; + obj.Position = topRight; + obj.Rotation = -obj.Rotation; + } + } + else + { + if (obj.Rotation == 0) + obj.X = (centrePtX - distFromCentreX) - obj.Width; + else + { + Vector2 topRight = CollisionMath.UpperRightCorner(new Rectangle((int)obj.X, (int)obj.Y, obj.Width, obj.Height), obj.Rotation, Vector2.Zero); + topRight.X += (centrePtX - topRight.X) * 2; + obj.Position = topRight; + obj.Rotation = -obj.Rotation; + + } + } + } + + foreach (GameObj obj in GameObjList) + { + ReverseObjNames(obj); + + if ((obj is HazardObj) == false && (obj is ChestObj == false)) + { + if (obj.Flip == SpriteEffects.None) + obj.Flip = SpriteEffects.FlipHorizontally; + else + obj.Flip = SpriteEffects.None; + + float distanceFromLeftWall = obj.X - this.X; + obj.X = this.Bounds.Right - distanceFromLeftWall; + if (obj.Rotation != 0) + obj.Rotation = -obj.Rotation; + } + else + { + if (obj is ChestObj) + { + if (obj.Flip == SpriteEffects.None) + obj.Flip = SpriteEffects.FlipHorizontally; + else + obj.Flip = SpriteEffects.None; + } + + float distFromCentreX = obj.X - centrePtX; + if (distFromCentreX >= 0) + { + if (obj.Rotation == 0) + obj.X -= (distFromCentreX * 2 + obj.Width); + else + { + Vector2 topRight = CollisionMath.UpperRightCorner(new Rectangle((int)obj.X, (int)obj.Y, obj.Width, obj.Height), obj.Rotation, Vector2.Zero); + topRight.X -= (topRight.X - centrePtX) * 2; + obj.Position = topRight; + obj.Rotation = -obj.Rotation; + } + } + else + { + if (obj.Rotation == 0) + obj.X = (centrePtX - distFromCentreX) - obj.Width; + else + { + Vector2 topRight = CollisionMath.UpperRightCorner(new Rectangle((int)obj.X, (int)obj.Y, obj.Width, obj.Height), obj.Rotation, Vector2.Zero); + topRight.X += (centrePtX - topRight.X) * 2; + obj.Position = topRight; + obj.Rotation = -obj.Rotation; + + } + } + } + } + + foreach (EnemyObj obj in EnemyList) + { + if (obj.Flip == SpriteEffects.None) + { + obj.Flip = SpriteEffects.FlipHorizontally; + obj.InternalFlip = SpriteEffects.FlipHorizontally; + } + else + { + obj.Flip = SpriteEffects.None; + obj.InternalFlip = SpriteEffects.None; + } + + ReverseObjNames(obj); + + float distFromCentreX = obj.X - centrePtX; + if (distFromCentreX >= 0) + { + //if (obj.Rotation == 0) + obj.X -= (distFromCentreX * 2); + obj.Rotation = -obj.Rotation; + //else + //{ + // Vector2 topRight = CollisionMath.UpperRightCorner(new Rectangle((int)obj.X, (int)obj.Y, obj.Width, obj.Height), obj.Rotation, Vector2.Zero); + // topRight.X -= (topRight.X - centrePtX) * 2; + // obj.Position = topRight; + // obj.Rotation = -obj.Rotation; + //} + } + else + { + //if (obj.Rotation == 0) + obj.X = (centrePtX - distFromCentreX); + obj.Rotation = -obj.Rotation; + //else + //{ + // Vector2 topRight = CollisionMath.UpperRightCorner(new Rectangle((int)obj.X, (int)obj.Y, obj.Width, obj.Height), obj.Rotation, Vector2.Zero); + // topRight.X += (centrePtX - topRight.X) * 2; + // obj.Position = topRight; + // obj.Rotation = -obj.Rotation; + + //} + } + } + + // Each spriteobj may need to be drawn flipped. + foreach (BorderObj obj in BorderList) + { + ReverseObjNames(obj); + + float distFromCentreX = obj.X - centrePtX; + if (distFromCentreX >= 0) + { + if (obj.Rotation == 0) + obj.X -= (distFromCentreX * 2 + obj.Width); + else + { + Vector2 topRight = CollisionMath.UpperRightCorner(new Rectangle((int)obj.X, (int)obj.Y, obj.Width, obj.Height), obj.Rotation, Vector2.Zero); + topRight.X -= (topRight.X - centrePtX) * 2; + obj.Position = topRight; + obj.Rotation = -obj.Rotation; + } + } + else + { + if (obj.Rotation == 0) + obj.X = (centrePtX - distFromCentreX) - obj.Width; + else + { + Vector2 topRight = CollisionMath.UpperRightCorner(new Rectangle((int)obj.X, (int)obj.Y, obj.Width, obj.Height), obj.Rotation, Vector2.Zero); + topRight.X += (centrePtX - topRight.X) * 2; + obj.Position = topRight; + obj.Rotation = -obj.Rotation; + + } + } + + if (obj.BorderRight == true) + { + if (obj.BorderLeft == false) + obj.BorderRight = false; + obj.BorderLeft = true; + } + else if (obj.BorderLeft == true) + { + if (obj.BorderRight == false) + obj.BorderLeft = false; + obj.BorderRight = true; + } + } + + foreach (DoorObj door in DoorList) + { + if (door.DoorPosition == "Left") + { + door.X = this.X + this.Width - door.Width; + door.DoorPosition = "Right"; + } + else if (door.DoorPosition == "Right") + { + door.X = this.X; + door.DoorPosition = "Left"; + } + else if (door.DoorPosition == "Top") + { + float distFromCentreX = door.X - centrePtX; + if (distFromCentreX >= 0) + door.X -= (distFromCentreX * 2 + door.Width); + else + door.X = (centrePtX - distFromCentreX) - door.Width; + } + else if (door.DoorPosition == "Bottom") + { + float distFromCentreX = door.X - centrePtX; + if (distFromCentreX >= 0) + door.X -= (distFromCentreX * 2 + door.Width); + else + door.X = (centrePtX - distFromCentreX) - door.Width; + } + } + } + + private void ReverseObjNames(GameObj obj) + { + if (obj.Name == "Left") obj.Name = "Right"; + else if (obj.Name == "Right") obj.Name = "Left"; + else if (obj.Name == "!Left") obj.Name = "!Right"; + else if (obj.Name == "!Right") obj.Name = "!Left"; + else if (obj.Name == "!RightTop") obj.Name = "!LeftTop"; + else if (obj.Name == "!RightBottom") obj.Name = "!LeftBottom"; + else if (obj.Name == "!LeftTop") obj.Name = "!RightTop"; + else if (obj.Name == "!LeftBottom") obj.Name = "!RightBottom"; + else if (obj.Name == "RightTop") obj.Name = "LeftTop"; + else if (obj.Name == "RightBottom") obj.Name = "LeftBottom"; + else if (obj.Name == "LeftTop") obj.Name = "RightTop"; + else if (obj.Name == "LeftBottom") obj.Name = "RightBottom"; + else if (obj.Name == "!BottomLeft") obj.Name = "!BottomRight"; + else if (obj.Name == "!BottomRight") obj.Name = "!BottomLeft"; + else if (obj.Name == "!TopLeft") obj.Name = "!TopRight"; + else if (obj.Name == "!TopRight") obj.Name = "!TopLeft"; + else if (obj.Name == "BottomLeft") obj.Name = "BottomRight"; + else if (obj.Name == "BottomRight") obj.Name = "BottomLeft"; + else if (obj.Name == "TopLeft") obj.Name = "TopRight"; + else if (obj.Name == "TopRight") obj.Name = "TopLeft"; + } + + protected override GameObj CreateCloneInstance() + { + return new RoomObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + //WARNING: ANYTHING CHANGED HERE NEEDS TO CHANGE IN STARTINGROOMOBJ.CONVERTTOSTARTINGROOM(). + RoomObj clone = obj as RoomObj; + clone.SetWidth(_width); + clone.SetHeight(_height); + + foreach (TerrainObj terrainObj in TerrainObjList) + clone.TerrainObjList.Add(terrainObj.Clone() as TerrainObj); + + foreach (GameObj gameObj in GameObjList) + { + GameObj cloneObj = gameObj.Clone() as GameObj; + if (cloneObj is NpcObj && cloneObj.Name == "donationbox") + clone.DonationBox = cloneObj as NpcObj; + clone.GameObjList.Add(cloneObj); + } + + foreach (DoorObj door in DoorList) + { + DoorObj cloneDoor = door.Clone() as DoorObj; + cloneDoor.Room = clone; // Necessary since a cloned door returns a reference to the old room, NOT the cloned room. + clone.DoorList.Add(cloneDoor); + } + + foreach (EnemyObj enemy in EnemyList) + clone.EnemyList.Add(enemy.Clone() as EnemyObj); + + foreach (BorderObj borderObj in BorderList) + clone.BorderList.Add(borderObj.Clone() as BorderObj); + + + clone.AddToCastlePool = this.AddToCastlePool; + clone.AddToGardenPool = this.AddToGardenPool; + clone.AddToDungeonPool = this.AddToDungeonPool; + clone.AddToTowerPool = this.AddToTowerPool; + clone.PoolIndex = this.PoolIndex; + + clone.RedEnemyType = this.RedEnemyType; + clone.BlueEnemyType = this.BlueEnemyType; + clone.GreenEnemyType = this.GreenEnemyType; + + clone.LinkedRoom = this.LinkedRoom; + clone.IsReversed = this.IsReversed; + clone.DebugRoomPosition = this.DebugRoomPosition; + clone.LevelType = this.LevelType; + clone.Level = this.Level; + clone.IsDLCMap = this.IsDLCMap; + } + + public void DisplayFairyChestInfo() + { + FairyChestObj fairyChest = null; + WaypointObj waypoint = null; + + foreach (GameObj obj in GameObjList) + { + if (obj is FairyChestObj) + fairyChest = obj as FairyChestObj; + + if (obj is WaypointObj) + waypoint = obj as WaypointObj; + } + + if (fairyChest != null && fairyChest.IsOpen == false && fairyChest.ConditionType != ChestConditionType.None && fairyChest.ConditionType != ChestConditionType.InvisibleChest + && fairyChest.State != ChestConditionChecker.STATE_FREE) + //if (fairyChest != null && fairyChest.IsOpen == false && waypoint != null && fairyChest.ConditionType != 0) + { + ////(Player.AttachedLevel.ScreenManager as RCScreenManager).DialogueScreen.SetDialogue("Chest_Locked " + fairyChest.ConditionType); + ////(Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true); + //m_fairyChestText.Text = DialogueManager.GetText("Chest_Locked " + fairyChest.ConditionType).Dialogue[0]; + //m_fairyChestText.X = waypoint.X - m_fairyChestText.Width / 2f; + //m_fairyChestText.Y = waypoint.Y - m_fairyChestText.Height / 2f; + //m_fairyChestText.BeginTypeWriting(1); + + Player.AttachedLevel.DisplayObjective("LOC_ID_LEVEL_SCREEN_2", //"Fairy Chest Objective" + DialogueManager.GetText("Chest_Locked " + fairyChest.ConditionType).Speakers[0], + DialogueManager.GetText("Chest_Locked " + fairyChest.ConditionType).Dialogue[0], + true); + } + else + m_fairyChestText.Text = ""; + } + + public void DarkenRoom() + { + Tweener.Tween.To(m_pauseBG, 0.1f, Tweener.Tween.EaseNone, "Opacity", "0.7"); + } + + public virtual void PauseRoom() + { + //Tweener.Tween.To(m_pauseBG, 0.1f, Tweener.Tween.EaseNone, "Opacity", "0.7"); + + foreach (GameObj obj in GameObjList) + { + IAnimateableObj sprite = obj as IAnimateableObj; + if (sprite != null) + sprite.PauseAnimation(); + + TextObj textObj = obj as TextObj; + if (textObj != null && textObj.IsTypewriting == true) + textObj.PauseTypewriting(); + } + + foreach (EnemyObj enemy in EnemyList) + enemy.PauseAnimation(); + + foreach (EnemyObj enemy in TempEnemyList) + enemy.PauseAnimation(); + } + + public virtual void UnpauseRoom() + { + //m_pauseBG.Opacity = 0; + Tweener.Tween.To(m_pauseBG, 0.1f, Tweener.Tween.EaseNone, "Opacity", "0"); + + foreach (GameObj obj in GameObjList) + { + IAnimateableObj sprite = obj as IAnimateableObj; + if (sprite != null) + sprite.ResumeAnimation(); + + TextObj textObj = obj as TextObj; + if (textObj != null && textObj.IsTypewriting == true) + textObj.ResumeTypewriting(); + } + + foreach (EnemyObj enemy in EnemyList) + enemy.ResumeAnimation(); + + foreach (EnemyObj enemy in TempEnemyList) + enemy.ResumeAnimation(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + foreach (DoorObj door in DoorList) + door.Dispose(); + DoorList.Clear(); + DoorList = null; + + foreach (TerrainObj obj in TerrainObjList) + obj.Dispose(); + TerrainObjList.Clear(); + TerrainObjList = null; + + foreach (GameObj obj in GameObjList) + obj.Dispose(); + GameObjList.Clear(); + GameObjList = null; + + foreach (EnemyObj enemy in EnemyList) + enemy.Dispose(); + EnemyList.Clear(); + EnemyList = null; + + foreach (BorderObj borderObj in BorderList) + borderObj.Dispose(); + BorderList.Clear(); + BorderList = null; + + m_bwRender = null; // The procedural level screen disposes of this render target. + + LinkedRoom = null; + + foreach (EnemyObj enemy in TempEnemyList) + enemy.Dispose(); + TempEnemyList.Clear(); + TempEnemyList = null; + + Player = null; + + m_fairyChestText.Dispose(); + m_fairyChestText = null; + + m_pauseBG.Dispose(); + m_pauseBG = null; + + m_indexText.Dispose(); + m_indexText = null; + m_roomInfoText.Dispose(); + m_roomInfoText = null; + + Array.Clear(m_empowerCostArray, 0, m_empowerCostArray.Length); + m_empowerCostArray = null; + + base.Dispose(); + } + } + + public void CopyRoomProperties(RoomObj room) + { + this.Name = room.Name; + this.SetWidth(room.Width); + this.SetHeight(room.Height); + this.Position = room.Position; + + this.AddToCastlePool = room.AddToCastlePool; + this.AddToGardenPool = room.AddToGardenPool; + this.AddToDungeonPool = room.AddToDungeonPool; + this.AddToTowerPool = room.AddToTowerPool; + this.PoolIndex = room.PoolIndex; + + this.RedEnemyType = room.RedEnemyType; + this.BlueEnemyType = room.BlueEnemyType; + this.GreenEnemyType = room.GreenEnemyType; + + this.LinkedRoom = room.LinkedRoom; + this.IsReversed = room.IsReversed; + this.DebugRoomPosition = room.DebugRoomPosition; + this.Tag = room.Tag; + this.LevelType = room.LevelType; + this.IsDLCMap = room.IsDLCMap; + + this.TextureColor = room.TextureColor; + } + + public void CopyRoomObjects(RoomObj room) + { + foreach (TerrainObj obj in room.TerrainObjList) + TerrainObjList.Add(obj.Clone() as TerrainObj); + + foreach (GameObj obj in room.GameObjList) + { + GameObj cloneObj = obj.Clone() as GameObj; + if (cloneObj is NpcObj && cloneObj.Name == "donationbox") + DonationBox = cloneObj as NpcObj; + GameObjList.Add(cloneObj); + } + + foreach (DoorObj door in room.DoorList) + { + DoorObj cloneDoor = door.Clone() as DoorObj; + cloneDoor.Room = this; // Necessary since a cloned door returns a reference to the old room, NOT the cloned room. + DoorList.Add(cloneDoor); + } + + foreach (EnemyObj enemy in room.EnemyList) + EnemyList.Add(enemy.Clone() as EnemyObj); + + foreach (BorderObj borderObj in room.BorderList) + BorderList.Add(borderObj.Clone() as BorderObj); + } + + public override void PopulateFromXMLReader(System.Xml.XmlReader reader, System.Globalization.CultureInfo ci) + { + base.PopulateFromXMLReader(reader, ci); + + SetWidth(_width); + SetHeight(_height); + //if (reader.MoveToAttribute("Width")) + // SetWidth(int.Parse(reader.Value, NumberStyles.Any, ci)); + //if (reader.MoveToAttribute("Height")) + // SetHeight(int.Parse(reader.Value, NumberStyles.Any, ci)); + + if (reader.MoveToAttribute("CastlePool")) + this.AddToCastlePool = bool.Parse(reader.Value); + if (reader.MoveToAttribute("GardenPool")) + this.AddToGardenPool = bool.Parse(reader.Value); + if (reader.MoveToAttribute("TowerPool")) + this.AddToTowerPool = bool.Parse(reader.Value); + if (reader.MoveToAttribute("DungeonPool")) + this.AddToDungeonPool = bool.Parse(reader.Value); + + this.DebugRoomPosition = this.Position; + } + + public int RoomNumber + { + get { return m_roomNumber; } + set + { + m_roomNumber = value; + if (this.Name == "Linker") + m_indexText.Text = "Linker " + m_roomNumber.ToString(); + else if (this.Name == "EntranceBoss") + m_indexText.Text = "Boss\nEnt. " + m_roomNumber.ToString(); + else if (this.Name == "Boss") + m_indexText.Text = "Boss " + m_roomNumber.ToString(); + else if (this.Name == "Secret") + m_indexText.Text = "Secret " + m_roomNumber.ToString(); + else if (this.Name == "Bonus") + m_indexText.Text = "Bonus " + m_roomNumber.ToString(); + else if (this.Name == "Start") + m_indexText.Text = "Starting Room"; + else + m_indexText.Text = m_roomNumber.ToString(); + } + } + + public Vector2 DebugRoomPosition + { + get { return m_debugRoomPosition; } + set + { + m_debugRoomPosition = value; + m_roomInfoText.Text = "Level Editor Pos: " + m_debugRoomPosition.ToString() + "\nReversed: " + IsReversed; + } + } + + public RenderTarget2D BGRender + { + get { return m_bwRender; } + } + + public bool HasFairyChest + { + get + { + foreach (GameObj obj in GameObjList) + { + if (obj is FairyChestObj) + return true; + } + return false; + } + } + + public int ActiveEnemies + { + get + { + int activeEnemies = 0; + foreach (EnemyObj enemy in EnemyList) + { + if (enemy.NonKillable == false && enemy.IsKilled == false) + activeEnemies++; + } + + foreach (EnemyObj enemy in TempEnemyList) + { + if (enemy.NonKillable == false && enemy.IsKilled == false) + activeEnemies++; + } + return activeEnemies; + } + } + + public virtual void RefreshTextObjs() { } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/StartingRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/StartingRoomObj.cs new file mode 100644 index 0000000..afe4216 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/StartingRoomObj.cs @@ -0,0 +1,1010 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Tweener.Ease; +using Tweener; +using Microsoft.Xna.Framework.Audio; + +namespace RogueCastle +{ + public class StartingRoomObj : RoomObj + { + private BlacksmithObj m_blacksmith; + private SpriteObj m_blacksmithIcon; + private Vector2 m_blacksmithIconPosition; + + private const int ENCHANTRESS_HEAD_LAYER = 4; + private ObjContainer m_enchantress; + private SpriteObj m_enchantressIcon; + private Vector2 m_enchantressIconPosition; + + private const byte ARCHITECT_HEAD_LAYER = 1; + private ObjContainer m_architect; + private SpriteObj m_architectIcon; + private Vector2 m_architectIconPosition; + private bool m_architectRenovating; + private float m_screenShakeCounter = 0; + + private FrameSoundObj m_blacksmithAnvilSound; + private GameObj m_tree1, m_tree2, m_tree3; + private GameObj m_fern1, m_fern2, m_fern3; + + private bool m_isRaining = false; + private List m_rainFG; + private Cue m_rainSFX; + + private SpriteObj m_tent; + private SpriteObj m_blacksmithBoard; + private SpriteObj m_screw; + + private PhysicsObjContainer m_tollCollector; + private SpriteObj m_tollCollectorIcon; + + private bool m_playerWalkedOut = false; + + private SpriteObj m_mountain1, m_mountain2; + private float m_lightningTimer = 0; + + private SpriteObj m_blacksmithNewIcon; + private SpriteObj m_enchantressNewIcon; + + private TerrainObj m_blacksmithBlock; + private TerrainObj m_enchantressBlock; + private TerrainObj m_architectBlock; + + private bool m_controlsLocked = false; + + private bool m_isSnowing = false; + + public StartingRoomObj() + { + //TraitSystem.LevelUpTrait(TraitSystem.GetTrait(TraitType.Smithy)); // Debug just so I can see the smithy. + //TraitSystem.LevelUpTrait(TraitSystem.GetTrait(TraitType.Enchanter)); // Debug just so I can see the enchantress. + //TraitSystem.LevelUpTrait(TraitSystem.GetTrait(TraitType.Architect)); // Debug just so I can see the architect. + + m_blacksmith = new BlacksmithObj(); + m_blacksmith.Flip = SpriteEffects.FlipHorizontally; + m_blacksmith.Scale = new Vector2(2.5f, 2.5f); + m_blacksmith.Position = new Vector2(700, 720 - 60 - (m_blacksmith.Bounds.Bottom - m_blacksmith.Y) - 1); // -60 to subtract one tile. + m_blacksmith.OutlineWidth = 2; + + m_blacksmithBoard = new SpriteObj("StartRoomBlacksmithBoard_Sprite"); + m_blacksmithBoard.Scale = new Vector2(2, 2); + m_blacksmithBoard.OutlineWidth = 2; + m_blacksmithBoard.Position = new Vector2(m_blacksmith.X - m_blacksmithBoard.Width / 2 - 35, m_blacksmith.Bounds.Bottom - m_blacksmithBoard.Height - 1); + + //m_blacksmithIcon = new SpriteObj("TalkBubbleUpArrow_Sprite"); + m_blacksmithIcon = new SpriteObj("UpArrowBubble_Sprite"); + m_blacksmithIcon.Scale = new Vector2(2, 2); + m_blacksmithIcon.Visible = false; + m_blacksmithIconPosition = new Vector2(m_blacksmith.X - 60, m_blacksmith.Y - 10); + m_blacksmithIcon.Flip = m_blacksmith.Flip; + m_blacksmithIcon.OutlineWidth = 2; + + //m_blacksmithNewIcon = new SpriteObj("TalkBubble2_Sprite"); + m_blacksmithNewIcon = new SpriteObj("ExclamationSquare_Sprite"); + m_blacksmithNewIcon.Visible = false; + m_blacksmithNewIcon.OutlineWidth = 2; + m_enchantressNewIcon = m_blacksmithNewIcon.Clone() as SpriteObj; + + m_enchantress = new ObjContainer("Enchantress_Character"); + m_enchantress.Scale = new Vector2(2f, 2f); + m_enchantress.Flip = SpriteEffects.FlipHorizontally; + m_enchantress.Position = new Vector2(1150, 720 - 60 - (m_enchantress.Bounds.Bottom - m_enchantress.AnchorY) - 2); + m_enchantress.PlayAnimation(); + m_enchantress.AnimationDelay = 1 / 10f; + (m_enchantress.GetChildAt(ENCHANTRESS_HEAD_LAYER) as IAnimateableObj).StopAnimation(); + m_enchantress.OutlineWidth = 2; + + m_tent = new SpriteObj("StartRoomGypsyTent_Sprite"); + m_tent.Scale = new Vector2(1.5f, 1.5f); + m_tent.OutlineWidth = 2; + m_tent.Position = new Vector2(m_enchantress.X - m_tent.Width / 2 + 5, m_enchantress.Bounds.Bottom - m_tent.Height); + + //m_enchantressIcon = new SpriteObj("TalkBubbleUpArrow_Sprite"); + m_enchantressIcon = new SpriteObj("UpArrowBubble_Sprite"); + m_enchantressIcon.Scale = new Vector2(2f, 2f); + m_enchantressIcon.Visible = false; + m_enchantressIconPosition = new Vector2(m_enchantress.X - 60, m_enchantress.Y - 100); + m_enchantressIcon.Flip = m_enchantress.Flip; + m_enchantressIcon.OutlineWidth = 2; + + m_architect = new ObjContainer("ArchitectIdle_Character"); + m_architect.Flip = SpriteEffects.FlipHorizontally; + m_architect.Scale = new Vector2(2, 2); + m_architect.Position = new Vector2(1550, 720 - 60 - (m_architect.Bounds.Bottom - m_architect.AnchorY) - 2); + m_architect.PlayAnimation(true); + m_architect.AnimationDelay = 1 / 10f; + m_architect.OutlineWidth = 2; + (m_architect.GetChildAt(ARCHITECT_HEAD_LAYER) as IAnimateableObj).StopAnimation(); + + //m_architectIcon = new SpriteObj("TalkBubbleUpArrow_Sprite"); + m_architectIcon = new SpriteObj("UpArrowBubble_Sprite"); + m_architectIcon.Scale = new Vector2(2, 2); + m_architectIcon.Visible = false; + m_architectIconPosition = new Vector2(m_architect.X - 60, m_architect.Y - 100); + m_architectIcon.Flip = m_architect.Flip; + m_architectIcon.OutlineWidth = 2; + m_architectRenovating = false; + + m_screw = new SpriteObj("ArchitectGear_Sprite"); + m_screw.Scale = new Vector2(2, 2); + m_screw.OutlineWidth = 2; + m_screw.Position = new Vector2(m_architect.X + 30, m_architect.Bounds.Bottom - 1); + m_screw.AnimationDelay = 1 / 10f; + + m_tollCollector = new PhysicsObjContainer("NPCTollCollectorIdle_Character"); + m_tollCollector.Flip = SpriteEffects.FlipHorizontally; + m_tollCollector.Scale = new Vector2(2.5f, 2.5f); + m_tollCollector.IsWeighted = false; + m_tollCollector.IsCollidable = true; + m_tollCollector.Position = new Vector2(2565, 720 - 60 * 5 - (m_tollCollector.Bounds.Bottom - m_tollCollector.AnchorY)); + m_tollCollector.PlayAnimation(true); + m_tollCollector.AnimationDelay = 1 / 10f; + m_tollCollector.OutlineWidth = 2; + m_tollCollector.CollisionTypeTag = GameTypes.CollisionType_WALL; + + //m_tollCollectorIcon = new SpriteObj("TalkBubbleUpArrow_Sprite"); + m_tollCollectorIcon = new SpriteObj("UpArrowBubble_Sprite"); + m_tollCollectorIcon.Scale = new Vector2(2, 2); + m_tollCollectorIcon.Visible = false; + m_tollCollectorIcon.Flip = m_tollCollector.Flip; + m_tollCollectorIcon.OutlineWidth = 2; + + m_rainFG = new List(); + int numRainDrops = 400; + if (LevelEV.SAVE_FRAMES == true) + numRainDrops /= 2; + + for (int i = 0; i < numRainDrops; i++) + { + RaindropObj rain = new RaindropObj(new Vector2(CDGMath.RandomInt(-100, 1270 * 2), CDGMath.RandomInt(-400, 720))); + m_rainFG.Add(rain); + } + } + + public override void Initialize() + { + foreach (TerrainObj obj in TerrainObjList) + { + if (obj.Name == "BlacksmithBlock") + m_blacksmithBlock = obj; + if (obj.Name == "EnchantressBlock") + m_enchantressBlock = obj; + if (obj.Name == "ArchitectBlock") + m_architectBlock = obj; + + if (obj.Name == "bridge") + obj.ShowTerrain = false; + } + + for (int i = 0; i < GameObjList.Count; i++) + { + if (GameObjList[i].Name == "Mountains 1") + m_mountain1 = GameObjList[i] as SpriteObj; + + if (GameObjList[i].Name == "Mountains 2") + m_mountain2 = GameObjList[i] as SpriteObj; + } + + base.Initialize(); + } + + public override void LoadContent(GraphicsDevice graphics) + { + if (m_tree1 == null) + { + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "Tree1") + m_tree1 = obj; + else if (obj.Name == "Tree2") + m_tree2 = obj; + else if (obj.Name == "Tree3") + m_tree3 = obj; + else if (obj.Name == "Fern1") + m_fern1 = obj; + else if (obj.Name == "Fern2") + m_fern2 = obj; + else if (obj.Name == "Fern3") + m_fern3 = obj; + } + } + + base.LoadContent(graphics); + } + + public override void OnEnter() + { + // Extra check to make sure sure you don't have a challenge token for a challenge already beaten. + if (Game.PlayerStats.SpecialItem == SpecialItemType.EyeballToken && Game.PlayerStats.ChallengeEyeballBeaten == true) + Game.PlayerStats.SpecialItem = SpecialItemType.None; + if (Game.PlayerStats.SpecialItem == SpecialItemType.SkullToken && Game.PlayerStats.ChallengeSkullBeaten == true) + Game.PlayerStats.SpecialItem = SpecialItemType.None; + if (Game.PlayerStats.SpecialItem == SpecialItemType.FireballToken && Game.PlayerStats.ChallengeFireballBeaten == true) + Game.PlayerStats.SpecialItem = SpecialItemType.None; + if (Game.PlayerStats.SpecialItem == SpecialItemType.BlobToken && Game.PlayerStats.ChallengeBlobBeaten == true) + Game.PlayerStats.SpecialItem = SpecialItemType.None; + if (Game.PlayerStats.SpecialItem == SpecialItemType.LastBossToken && Game.PlayerStats.ChallengeLastBossBeaten == true) + Game.PlayerStats.SpecialItem = SpecialItemType.None; + Player.AttachedLevel.UpdatePlayerHUDSpecialItem(); + + m_isSnowing = (DateTime.Now.Month == 12 || DateTime.Now.Month == 1); // Only snows in Dec. and Jan. + if (m_isSnowing == true) + { + foreach (RaindropObj rainDrop in m_rainFG) + { + rainDrop.ChangeToSnowflake(); + } + } + + if ((Game.ScreenManager.Game as Game).SaveManager.FileExists(SaveType.Map) == false && Game.PlayerStats.HasArchitectFee == true) + Game.PlayerStats.HasArchitectFee = false; + + Game.PlayerStats.TutorialComplete = true; // This needs to be removed later. + Game.PlayerStats.IsDead = false; + + m_lightningTimer = 5; + Player.CurrentHealth = Player.MaxHealth; + Player.CurrentMana = Player.MaxMana; + Player.ForceInvincible = false; + (Player.AttachedLevel.ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData); + + if (TollCollectorAvailable == true) + { + if (Player.AttachedLevel.PhysicsManager.ObjectList.Contains(m_tollCollector) == false) + Player.AttachedLevel.PhysicsManager.AddObject(m_tollCollector); + } + + if (m_blacksmithAnvilSound == null) + m_blacksmithAnvilSound = new FrameSoundObj(m_blacksmith.GetChildAt(5) as IAnimateableObj, Player, 7, "Anvil1", "Anvil2", "Anvil3"); + + // Special check for Glaucoma + if (Game.PlayerStats.Traits.X == TraitType.Glaucoma || Game.PlayerStats.Traits.Y == TraitType.Glaucoma) + Game.ShadowEffect.Parameters["ShadowIntensity"].SetValue(0.7f); + else + Game.ShadowEffect.Parameters["ShadowIntensity"].SetValue(0); + + m_playerWalkedOut = false; + //if (Game.PlayerSaveData.SaveLoaded == false) + { + Player.UpdateCollisionBoxes(); // Necessary check since the OnEnter() is called before player can update its collision boxes. + Player.Position = new Vector2(0, 720 - 60 - (Player.Bounds.Bottom - Player.Y)); + Player.State = 1; // Force the player into a walking state. This state will not update until the logic set is complete. + Player.IsWeighted = false; + Player.IsCollidable = false; + LogicSet playerMoveLS = new LogicSet(Player); + playerMoveLS.AddAction(new RunFunctionLogicAction(Player, "LockControls")); + playerMoveLS.AddAction(new MoveDirectionLogicAction(new Vector2(1, 0))); + playerMoveLS.AddAction(new ChangeSpriteLogicAction("PlayerWalking_Character")); + playerMoveLS.AddAction(new PlayAnimationLogicAction(true)); + playerMoveLS.AddAction(new DelayLogicAction(0.5f)); + playerMoveLS.AddAction(new ChangePropertyLogicAction(Player, "CurrentSpeed", 0)); + playerMoveLS.AddAction(new ChangePropertyLogicAction(Player, "IsWeighted", true)); + playerMoveLS.AddAction(new ChangePropertyLogicAction(Player, "IsCollidable", true)); + Player.RunExternalLogicSet(playerMoveLS); // Do not dispose this logic set. The player object will do it on its own. + Tween.By(this, 1.0f, Linear.EaseNone); + Tween.AddEndHandlerToLastTween(Player, "UnlockControls"); + } + + SoundManager.StopMusic(1); + + m_isRaining = CDGMath.RandomPlusMinus() > 0; + m_isRaining = true; + + if (m_isRaining == true) + { + if (m_rainSFX != null) + m_rainSFX.Dispose(); + + if (m_isSnowing == false) + m_rainSFX = SoundManager.PlaySound("Rain1"); + else + m_rainSFX = SoundManager.PlaySound("snowloop_filtered"); + //m_rainSFX = SoundManager.Play3DSound(m_blacksmith, Player, "Rain1"); + } + + m_tent.TextureColor = new Color(200, 200, 200); + m_blacksmithBoard.TextureColor = new Color(200, 200, 200); + m_screw.TextureColor = new Color(200, 200, 200); + + if (Game.PlayerStats.LockCastle == true) + { + m_screw.GoToFrame(m_screw.TotalFrames); + m_architectBlock.Position = new Vector2(1492, 439 + 140); + } + else + { + m_screw.GoToFrame(1); + m_architectBlock.Position = new Vector2(1492, 439); + } + + Player.UpdateEquipmentColours(); + + + base.OnEnter(); + } + + public override void OnExit() + { + if (m_rainSFX != null && m_rainSFX.IsDisposed == false) + m_rainSFX.Stop(AudioStopOptions.Immediate); + } + + public override void Update(GameTime gameTime) + { + // Player should have max hp and mp while in the starting room. + Player.CurrentMana = Player.MaxMana; + Player.CurrentHealth = Player.MaxHealth; + + m_enchantressBlock.Visible = EnchantressAvailable; + m_blacksmithBlock.Visible = SmithyAvailable; + m_architectBlock.Visible = ArchitectAvailable; + + float totalSeconds = Game.TotalGameTime; + + if (m_playerWalkedOut == false) + { + if (Player.ControlsLocked == false && Player.X < this.Bounds.Left) + { + m_playerWalkedOut = true; + (Player.AttachedLevel.ScreenManager as RCScreenManager).StartWipeTransition(); + Tween.RunFunction(0.2f, Player.AttachedLevel.ScreenManager, "DisplayScreen", ScreenType.Skill, true, typeof(List)); + } + else if (Player.ControlsLocked == false && Player.X > this.Bounds.Right && TollCollectorAvailable == false) // Make sure the player can't pass the toll collector + { + m_playerWalkedOut = true; + LoadLevel(); + } + } + + if (m_isRaining == true) + { + foreach (TerrainObj obj in TerrainObjList) // Optimization + obj.UseCachedValues = true; // No need to set it back to false. The physics manager will do that + + foreach (RaindropObj raindrop in m_rainFG) + raindrop.Update(this.TerrainObjList, gameTime); + } + + m_tree1.Rotation = -(float)Math.Sin(totalSeconds) * 2; + m_tree2.Rotation = (float)Math.Sin(totalSeconds * 2); + m_tree3.Rotation = (float)Math.Sin(totalSeconds * 2) * 2; + m_fern1.Rotation = (float)Math.Sin(totalSeconds * 3f) / 2; + m_fern2.Rotation = -(float)Math.Sin(totalSeconds * 4f); + m_fern3.Rotation = (float)Math.Sin(totalSeconds * 4f) / 2f; + + if (m_architectRenovating == false) + HandleInput(); + + if (SmithyAvailable) + { + if (m_blacksmithAnvilSound != null) + m_blacksmithAnvilSound.Update(); + m_blacksmith.Update(gameTime); + } + + m_blacksmithIcon.Visible = false; + if (Player != null && CollisionMath.Intersects(Player.TerrainBounds, m_blacksmith.Bounds) && Player.IsTouchingGround == true && SmithyAvailable == true) + m_blacksmithIcon.Visible = true; + m_blacksmithIcon.Position = new Vector2(m_blacksmithIconPosition.X, m_blacksmithIconPosition.Y - 70 + (float)Math.Sin(totalSeconds * 20) * 2); + + m_enchantressIcon.Visible = false; + Rectangle enchantressBounds = new Rectangle((int)(m_enchantress.X - 100), (int)m_enchantress.Y, m_enchantress.Bounds.Width + 100, m_enchantress.Bounds.Height); + if (Player != null && CollisionMath.Intersects(Player.TerrainBounds, enchantressBounds) && Player.IsTouchingGround == true && EnchantressAvailable == true) + m_enchantressIcon.Visible = true; + m_enchantressIcon.Position = new Vector2(m_enchantressIconPosition.X + 20, m_enchantressIconPosition.Y + (float)Math.Sin(totalSeconds * 20) * 2); + + if (Player != null && CollisionMath.Intersects(Player.TerrainBounds, new Rectangle((int)m_architect.X - 100, (int)m_architect.Y, m_architect.Width + 200, m_architect.Height)) + && Player.X < m_architect.X && Player.Flip == SpriteEffects.None && ArchitectAvailable == true) + m_architectIcon.Visible = true; + else + m_architectIcon.Visible = false; + m_architectIcon.Position = new Vector2(m_architectIconPosition.X, m_architectIconPosition.Y + (float)Math.Sin(totalSeconds * 20) * 2); + + if (Player != null && CollisionMath.Intersects(Player.TerrainBounds, new Rectangle((int)m_tollCollector.X - 100, (int)m_tollCollector.Y, m_tollCollector.Width + 200, m_tollCollector.Height)) + && Player.X < m_tollCollector.X && Player.Flip == SpriteEffects.None && TollCollectorAvailable == true && m_tollCollector.SpriteName == "NPCTollCollectorIdle_Character") + m_tollCollectorIcon.Visible = true; + else + m_tollCollectorIcon.Visible = false; + m_tollCollectorIcon.Position = new Vector2(m_tollCollector.X - m_tollCollector.Width/2 - 10, m_tollCollector.Y - m_tollCollectorIcon.Height - m_tollCollector.Height/2 + (float)Math.Sin(totalSeconds * 20) * 2); + + // Setting blacksmith new icons settings. + m_blacksmithNewIcon.Visible = false; + if (SmithyAvailable == true) + { + if (m_blacksmithIcon.Visible == true && m_blacksmithNewIcon.Visible == true) + m_blacksmithNewIcon.Visible = false; + else if (m_blacksmithIcon.Visible == false && BlacksmithNewIconVisible == true) + m_blacksmithNewIcon.Visible = true; + m_blacksmithNewIcon.Position = new Vector2(m_blacksmithIcon.X + 50, m_blacksmithIcon.Y - 30); + } + + // Setting enchantress new icons settings. + m_enchantressNewIcon.Visible = false; + if (EnchantressAvailable == true) + { + if (m_enchantressIcon.Visible == true && m_enchantressNewIcon.Visible == true) + m_enchantressNewIcon.Visible = false; + else if (m_enchantressIcon.Visible == false && EnchantressNewIconVisible == true) + m_enchantressNewIcon.Visible = true; + m_enchantressNewIcon.Position = new Vector2(m_enchantressIcon.X + 40, m_enchantressIcon.Y - 0); + } + + // lightning effect. + if (m_isRaining == true && m_isSnowing == false) + { + if (m_lightningTimer > 0) + { + m_lightningTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_lightningTimer <= 0) + { + if (CDGMath.RandomInt(0, 100) > 70) + { + if (CDGMath.RandomInt(0, 1) > 0) + Player.AttachedLevel.LightningEffectTwice(); + else + Player.AttachedLevel.LightningEffectOnce(); + } + m_lightningTimer = 5; + } + } + } + + if (m_shakeScreen == true) + UpdateShake(); + + // Prevents the player from getting passed the Toll Collector. + if (Player.Bounds.Right > m_tollCollector.Bounds.Left && TollCollectorAvailable == true)// && Game.PlayerStats.Traits.X != TraitType.Dwarfism && Game.PlayerStats.Traits.Y != TraitType.Dwarfism) + { + Player.X = m_tollCollector.Bounds.Left - (Player.Bounds.Right - Player.X); + Player.AttachedLevel.UpdateCamera(); + } + + base.Update(gameTime); + } + + private void LoadLevel() + { + Game.ScreenManager.DisplayScreen(ScreenType.Level, true, null); + } + + private void HandleInput() + { + if (m_controlsLocked == false) + { + if (Player.State != PlayerObj.STATE_DASHING) + { + if (m_blacksmithIcon.Visible == true && (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2))) + { + MovePlayerTo(m_blacksmith); + } + + if (m_enchantressIcon.Visible == true && (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2))) + { + MovePlayerTo(m_enchantress); + } + + if (m_architectIcon.Visible == true && (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2))) + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + if ((Game.ScreenManager.Game as Game).SaveManager.FileExists(SaveType.Map)) + { + if (Game.PlayerStats.LockCastle == false) + { + if (Game.PlayerStats.SpokeToArchitect == false) + { + Game.PlayerStats.SpokeToArchitect = true; + //(manager.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData); + manager.DialogueScreen.SetDialogue("Meet Architect"); + } + else + manager.DialogueScreen.SetDialogue("Meet Architect 2"); + + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "ActivateArchitect"); + manager.DialogueScreen.SetCancelEndHandler(typeof(Console), "WriteLine", "Canceling Selection"); + } + else + manager.DialogueScreen.SetDialogue("Castle Already Locked Architect"); + } + else + manager.DialogueScreen.SetDialogue("No Castle Architect"); + + manager.DisplayScreen(ScreenType.Dialogue, true); + } + } + + if (m_tollCollectorIcon.Visible == true && (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2))) + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + if (Game.PlayerStats.SpecialItem == SpecialItemType.FreeEntrance) + { + Tween.RunFunction(0.1f, this, "TollPaid", false); + manager.DialogueScreen.SetDialogue("Toll Collector Obol"); + manager.DisplayScreen(ScreenType.Dialogue, true); + } + else if (Game.PlayerStats.SpecialItem == SpecialItemType.EyeballToken) + { + manager.DialogueScreen.SetDialogue("Challenge Icon Eyeball"); + RunTollPaidSelection(manager); + } + else if (Game.PlayerStats.SpecialItem == SpecialItemType.SkullToken) + { + manager.DialogueScreen.SetDialogue("Challenge Icon Skull"); + RunTollPaidSelection(manager); + } + else if (Game.PlayerStats.SpecialItem == SpecialItemType.FireballToken) + { + manager.DialogueScreen.SetDialogue("Challenge Icon Fireball"); + RunTollPaidSelection(manager); + } + else if (Game.PlayerStats.SpecialItem == SpecialItemType.BlobToken) + { + manager.DialogueScreen.SetDialogue("Challenge Icon Blob"); + RunTollPaidSelection(manager); + } + else if (Game.PlayerStats.SpecialItem == SpecialItemType.LastBossToken) + { + manager.DialogueScreen.SetDialogue("Challenge Icon Last Boss"); + RunTollPaidSelection(manager); + } + else + { + if (Game.PlayerStats.SpokeToTollCollector == false) + manager.DialogueScreen.SetDialogue("Meet Toll Collector 1"); + else + { + float amount = SkillSystem.GetSkill(SkillType.Prices_Down).ModifierAmount * 100; + manager.DialogueScreen.SetDialogue("Meet Toll Collector Skip" + (int)Math.Round(amount, MidpointRounding.AwayFromZero)); + } + + RunTollPaidSelection(manager); + } + } + } + } + + private void RunTollPaidSelection(RCScreenManager manager) + { + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "TollPaid", true); + manager.DialogueScreen.SetCancelEndHandler(typeof(Console), "WriteLine", "Canceling Selection"); + manager.DisplayScreen(ScreenType.Dialogue, true); + } + + public void MovePlayerTo(GameObj target) + { + m_controlsLocked = true; + if (Player.X != target.X - 150) + { + if (Player.X > target.Position.X - 150) + Player.Flip = SpriteEffects.FlipHorizontally; + + float duration = CDGMath.DistanceBetweenPts(Player.Position, new Vector2(target.X - 150, target.Y)) / (float)(Player.Speed); + + Player.UpdateCollisionBoxes(); // Necessary check since the OnEnter() is called before player can update its collision boxes. + Player.State = 1; // Force the player into a walking state. This state will not update until the logic set is complete. + Player.IsWeighted = false; + Player.AccelerationY = 0; + Player.AccelerationX = 0; + Player.IsCollidable = false; + Player.CurrentSpeed = 0; + Player.LockControls(); + Player.ChangeSprite("PlayerWalking_Character"); + Player.PlayAnimation(true); + LogicSet playerMoveLS = new LogicSet(Player); + playerMoveLS.AddAction(new DelayLogicAction(duration)); + Player.RunExternalLogicSet(playerMoveLS); + Tween.To(Player, duration, Tween.EaseNone, "X", (target.Position.X - 150).ToString()); + Tween.AddEndHandlerToLastTween(this, "MovePlayerComplete", target); + } + else + MovePlayerComplete(target); + } + + public void MovePlayerComplete(GameObj target) + { + m_controlsLocked = false; + Player.IsWeighted = true; + Player.IsCollidable = true; + Player.UnlockControls(); + Player.Flip = SpriteEffects.None; + if (target == m_blacksmith) + { + if (Game.PlayerStats.SpokeToBlacksmith == false) + { + Game.PlayerStats.SpokeToBlacksmith = true; + (Player.AttachedLevel.ScreenManager as RCScreenManager).DialogueScreen.SetDialogue("Meet Blacksmith"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DialogueScreen.SetConfirmEndHandler(Player.AttachedLevel.ScreenManager, "DisplayScreen", ScreenType.Blacksmith, true, null); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true); + } + else + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Blacksmith, true); + } + else if (target == m_enchantress) + { + if (Game.PlayerStats.SpokeToEnchantress == false) + { + Game.PlayerStats.SpokeToEnchantress = true; + (Player.AttachedLevel.ScreenManager as RCScreenManager).DialogueScreen.SetDialogue("Meet Enchantress"); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DialogueScreen.SetConfirmEndHandler(Player.AttachedLevel.ScreenManager, "DisplayScreen", ScreenType.Enchantress, true, null); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true); + } + else + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Enchantress, true); + } + } + + public void TollPaid(bool chargeFee) + { + if (chargeFee == true) + { + float goldLost = Game.PlayerStats.Gold * (GameEV.GATEKEEPER_TOLL_COST - SkillSystem.GetSkill(SkillType.Prices_Down).ModifierAmount); + Game.PlayerStats.Gold -= (int)(goldLost); + if (goldLost > 0) + Player.AttachedLevel.TextManager.DisplayNumberStringText(-(int)goldLost, "LOC_ID_PLAYER_OBJ_1" /*"gold"*/, Color.Yellow, new Vector2(Player.X, Player.Bounds.Top)); + } + + if (Game.PlayerStats.SpokeToTollCollector == true && Game.PlayerStats.SpecialItem != SpecialItemType.FreeEntrance + && Game.PlayerStats.SpecialItem != SpecialItemType.BlobToken + && Game.PlayerStats.SpecialItem != SpecialItemType.LastBossToken + && Game.PlayerStats.SpecialItem != SpecialItemType.FireballToken + && Game.PlayerStats.SpecialItem != SpecialItemType.EyeballToken + && Game.PlayerStats.SpecialItem != SpecialItemType.SkullToken) + { + Player.AttachedLevel.ImpactEffectPool.DisplayDeathEffect(m_tollCollector.Position); + SoundManager.PlaySound("Charon_Laugh"); + HideTollCollector(); + } + else + { + Game.PlayerStats.SpokeToTollCollector = true; + SoundManager.PlaySound("Charon_Laugh"); + m_tollCollector.ChangeSprite("NPCTollCollectorLaugh_Character"); + m_tollCollector.AnimationDelay = 1 / 20f; + m_tollCollector.PlayAnimation(true); + Tween.RunFunction(1, Player.AttachedLevel.ImpactEffectPool, "DisplayDeathEffect", m_tollCollector.Position); + Tween.RunFunction(1, this, "HideTollCollector"); + } + + if (Game.PlayerStats.SpecialItem == SpecialItemType.FreeEntrance || + Game.PlayerStats.SpecialItem == SpecialItemType.SkullToken || + Game.PlayerStats.SpecialItem == SpecialItemType.EyeballToken || + Game.PlayerStats.SpecialItem == SpecialItemType.LastBossToken || + Game.PlayerStats.SpecialItem == SpecialItemType.FireballToken|| + Game.PlayerStats.SpecialItem == SpecialItemType.BlobToken) + { + if (Game.PlayerStats.SpecialItem == SpecialItemType.EyeballToken) + Game.PlayerStats.ChallengeEyeballUnlocked = true; + else if (Game.PlayerStats.SpecialItem == SpecialItemType.SkullToken) + Game.PlayerStats.ChallengeSkullUnlocked = true; + else if (Game.PlayerStats.SpecialItem == SpecialItemType.FireballToken) + Game.PlayerStats.ChallengeFireballUnlocked = true; + else if (Game.PlayerStats.SpecialItem == SpecialItemType.BlobToken) + Game.PlayerStats.ChallengeBlobUnlocked = true; + else if (Game.PlayerStats.SpecialItem == SpecialItemType.LastBossToken) + Game.PlayerStats.ChallengeLastBossUnlocked = true; + + Game.PlayerStats.SpecialItem = SpecialItemType.None; + Player.AttachedLevel.UpdatePlayerHUDSpecialItem(); + } + } + + public void HideTollCollector() + { + SoundManager.Play3DSound(this, Player, "Charon_Poof"); + m_tollCollector.Visible = false; + Player.AttachedLevel.PhysicsManager.RemoveObject(m_tollCollector); + } + + public void ActivateArchitect() + { + Player.LockControls(); + Player.CurrentSpeed = 0; + m_architectIcon.Visible = false; + m_architectRenovating = true; + m_architect.ChangeSprite("ArchitectPull_Character"); + (m_architect.GetChildAt(1) as SpriteObj).PlayAnimation(false); + m_screw.AnimationDelay = 1 / 30f; + + Game.PlayerStats.ArchitectUsed = true; + + Tween.RunFunction(0.5f, m_architect.GetChildAt(0), "PlayAnimation", true); + Tween.RunFunction(0.5f, typeof(SoundManager), "PlaySound", "Architect_Lever"); + Tween.RunFunction(1, typeof(SoundManager), "PlaySound", "Architect_Screw"); + Tween.RunFunction(1f, m_screw, "PlayAnimation", false); + Tween.By(m_architectBlock, 0.8f, Tween.EaseNone, "delay", "1.1", "Y", "135"); + Tween.RunFunction(1f, this, "ShakeScreen", 2, true, false); + Tween.RunFunction(1.5f, this, "StopScreenShake"); + Tween.RunFunction(1.5f, Player.AttachedLevel.ImpactEffectPool, "SkillTreeDustEffect", new Vector2(m_screw.X - m_screw.Width / 2f, m_screw.Y - 40), true, m_screw.Width); + Tween.RunFunction(3f, this, "StopArchitectActivation"); + } + + public void StopArchitectActivation() + { + m_architectRenovating = false; + m_architectIcon.Visible = true; + Player.UnlockControls(); + + Game.PlayerStats.LockCastle = true; + Game.PlayerStats.HasArchitectFee = true; + + foreach (ChestObj chest in Player.AttachedLevel.ChestList) // Resetting all fairy chests. + { + FairyChestObj fairyChest = chest as FairyChestObj; + if (fairyChest != null) + { + if (fairyChest.State == ChestConditionChecker.STATE_FAILED) + fairyChest.ResetChest(); + } + } + + foreach (RoomObj room in Player.AttachedLevel.RoomList) + { + foreach (GameObj obj in room.GameObjList) + { + BreakableObj breakableObj = obj as BreakableObj; + if (breakableObj != null) + breakableObj.Reset(); + } + } + + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("Castle Lock Complete Architect"); + manager.DisplayScreen(ScreenType.Dialogue, true); + } + + public override void Draw(Camera2D camera) + { + // Hacked parallaxing. + m_mountain1.X = camera.TopLeftCorner.X * 0.5f; + m_mountain2.X = m_mountain1.X + 2640; // 2640 not 1320 because it is mountain1 flipped. + + base.Draw(camera); + + if (m_isRaining == true) + camera.Draw(Game.GenericTexture, new Rectangle(0, 0, 1320 * 2, 720), Color.Black * 0.3f); + + if (m_screenShakeCounter > 0) + { + camera.X += CDGMath.RandomPlusMinus(); + camera.Y += CDGMath.RandomPlusMinus(); + m_screenShakeCounter -= (float)camera.GameTime.ElapsedGameTime.TotalSeconds; + } + + if (SmithyAvailable) + { + m_blacksmithBoard.Draw(camera); + m_blacksmith.Draw(camera); + m_blacksmithIcon.Draw(camera); + } + + if (EnchantressAvailable) + { + m_tent.Draw(camera); + m_enchantress.Draw(camera); + m_enchantressIcon.Draw(camera); + } + + if (ArchitectAvailable) + { + m_screw.Draw(camera); + m_architect.Draw(camera); + m_architectIcon.Draw(camera); + } + + if (TollCollectorAvailable) + { + m_tollCollector.Draw(camera); + m_tollCollectorIcon.Draw(camera); + } + + m_blacksmithNewIcon.Draw(camera); + m_enchantressNewIcon.Draw(camera); + + if (m_isRaining == true) + { + foreach (RaindropObj raindrop in m_rainFG) + raindrop.Draw(camera); + } + } + + public override void PauseRoom() + { + foreach (RaindropObj rainDrop in m_rainFG) + rainDrop.PauseAnimation(); + + if (m_rainSFX != null) + m_rainSFX.Pause(); + + m_enchantress.PauseAnimation(); + m_blacksmith.PauseAnimation(); + m_architect.PauseAnimation(); + m_tollCollector.PauseAnimation(); + + base.PauseRoom(); + } + + public override void UnpauseRoom() + { + foreach (RaindropObj rainDrop in m_rainFG) + rainDrop.ResumeAnimation(); + + if (m_rainSFX != null && m_rainSFX.IsPaused) + m_rainSFX.Resume(); + + m_enchantress.ResumeAnimation(); + m_blacksmith.ResumeAnimation(); + m_architect.ResumeAnimation(); + m_tollCollector.ResumeAnimation(); + + base.UnpauseRoom(); + } + + private bool m_horizontalShake; + private bool m_verticalShake; + private bool m_shakeScreen; + private float m_screenShakeMagnitude; + private Vector2 m_shakeStartingPos; + + public void ShakeScreen(float magnitude, bool horizontalShake = true, bool verticalShake = true) + { + m_shakeStartingPos = Player.AttachedLevel.Camera.Position; + Player.AttachedLevel.CameraLockedToPlayer = false; + m_screenShakeMagnitude = magnitude; + m_horizontalShake = horizontalShake; + m_verticalShake = verticalShake; + m_shakeScreen = true; + } + + public void UpdateShake() + { + if (m_horizontalShake == true) + Player.AttachedLevel.Camera.X = m_shakeStartingPos.X + CDGMath.RandomPlusMinus() * (CDGMath.RandomFloat(0, 1) * m_screenShakeMagnitude); + + if (m_verticalShake == true) + Player.AttachedLevel.Camera.Y = m_shakeStartingPos.Y + CDGMath.RandomPlusMinus() * (CDGMath.RandomFloat(0, 1) * m_screenShakeMagnitude); + } + + public void StopScreenShake() + { + Player.AttachedLevel.CameraLockedToPlayer = true; + m_shakeScreen = false; + } + protected override GameObj CreateCloneInstance() + { + return new StartingRoomObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_blacksmith.Dispose(); + m_blacksmith = null; + m_blacksmithIcon.Dispose(); + m_blacksmithIcon = null; + m_blacksmithNewIcon.Dispose(); + m_blacksmithNewIcon = null; + m_blacksmithBoard.Dispose(); + m_blacksmithBoard = null; + + m_enchantress.Dispose(); + m_enchantress = null; + m_enchantressIcon.Dispose(); + m_enchantressIcon = null; + m_enchantressNewIcon.Dispose(); + m_enchantressNewIcon = null; + m_tent.Dispose(); + m_tent = null; + + m_architect.Dispose(); + m_architect = null; + m_architectIcon.Dispose(); + m_architectIcon = null; + m_screw.Dispose(); + m_screw = null; + + if (m_blacksmithAnvilSound != null) // If the blacksmith is never unlocked, this stays null and cannot be disposed. + m_blacksmithAnvilSound.Dispose(); + m_blacksmithAnvilSound = null; + + m_tree1 = null; + m_tree2 = null; + m_tree3 = null; + m_fern1 = null; + m_fern2 = null; + m_fern3 = null; + + foreach (RaindropObj raindrop in m_rainFG) + raindrop.Dispose(); + m_rainFG.Clear(); + m_rainFG = null; + + m_mountain1 = null; + m_mountain2 = null; + + m_tollCollector.Dispose(); + m_tollCollector = null; + m_tollCollectorIcon.Dispose(); + m_tollCollectorIcon = null; + + m_blacksmithBlock = null; + m_enchantressBlock = null; + m_architectBlock = null; + + if (m_rainSFX != null) + m_rainSFX.Dispose(); + m_rainSFX = null; + + base.Dispose(); + } + } + + private bool BlacksmithNewIconVisible + { + get + { + foreach (byte[] category in Game.PlayerStats.GetBlueprintArray) + { + foreach (byte state in category) + { + if (state == EquipmentState.FoundButNotSeen) + return true; + } + } + return false; + } + } + + private bool EnchantressNewIconVisible + { + get + { + foreach (byte[] category in Game.PlayerStats.GetRuneArray) + { + foreach (byte state in category) + { + if (state == EquipmentState.FoundButNotSeen) + return true; + } + } + return false; + } + } + + + private bool SmithyAvailable + { + get { return SkillSystem.GetSkill(SkillType.Smithy).ModifierAmount > 0; } + } + + private bool EnchantressAvailable + { + get { return SkillSystem.GetSkill(SkillType.Enchanter).ModifierAmount > 0; } + } + + private bool ArchitectAvailable + { + get { return SkillSystem.GetSkill(SkillType.Architect).ModifierAmount > 0; } + } + + private bool TollCollectorAvailable + { + get { return (Game.PlayerStats.TimesDead > 0 && m_tollCollector.Visible == true); } + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/ThroneRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/ThroneRoomObj.cs new file mode 100644 index 0000000..d252638 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/ThroneRoomObj.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Tweener.Ease; +using Tweener; +using InputSystem; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class ThroneRoomObj : RoomObj + { + private KeyIconTextObj m_tutorialText; + private bool m_displayText = false; + + private KingObj m_king; + private bool m_kingKilled = false; + + public ThroneRoomObj() + { + } + + public override void Initialize() + { + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "fountain") + { + (obj as ObjContainer).OutlineWidth = 2; + obj.Y -= 2; + break; + } + } + + foreach (DoorObj door in DoorList) + door.Locked = true; + base.Initialize(); + } + + public override void LoadContent(GraphicsDevice graphics) + { + m_tutorialText = new KeyIconTextObj(Game.JunicodeLargeFont); + m_tutorialText.FontSize = 28; + m_tutorialText.Text = LocaleBuilder.getString("LOC_ID_THRONE_ROOM_OBJ_1_NEW", m_tutorialText); + m_tutorialText.Align = Types.TextAlign.Centre; + m_tutorialText.OutlineWidth = 2; + + m_king = new KingObj("King_Sprite"); + m_king.OutlineWidth = 2; + m_king.AnimationDelay = 1 / 10f; + m_king.PlayAnimation(true); + m_king.IsWeighted = false; + m_king.IsCollidable = true; + m_king.Scale = new Vector2(2, 2); + base.LoadContent(graphics); + } + + public override void OnEnter() + { + SoundManager.StopMusic(1); + + if (m_king.PhysicsMngr == null) + Player.PhysicsMngr.AddObject(m_king); + + m_kingKilled = false; + Player.UnlockControls(); + m_displayText = false; + m_tutorialText.Opacity = 0; + + m_king.UpdateCollisionBoxes(); + m_king.Position = new Vector2(this.Bounds.Right - 500, this.Y + 1440 - (m_king.Bounds.Bottom - m_king.Y) - 182); + } + + public override void OnExit() + { + //Game.PlayerStats.TutorialComplete = true; + //Game.PlayerStats.Gold = 0; + //Game.PlayerStats.HeadPiece = (byte)CDGMath.RandomInt(1, PlayerPart.NumHeadPieces);// Necessary to change his headpiece so he doesn't look like the first dude. + //Game.PlayerStats.EnemiesKilledInRun.Clear(); + //(Player.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData); + base.OnExit(); + } + + public override void Update(GameTime gameTime) + { + if (m_displayText == false && CDGMath.DistanceBetweenPts(Player.Position, m_king.Position) < 200) + { + m_displayText = true; + Tween.StopAllContaining(m_tutorialText, false); + Tween.To(m_tutorialText, 0.5f, Tween.EaseNone, "Opacity", "1"); + } + else if (m_displayText == true && CDGMath.DistanceBetweenPts(Player.Position, m_king.Position) > 200) + { + m_displayText = false; + Tween.StopAllContaining(m_tutorialText, false); + Tween.To(m_tutorialText, 0.5f, Tween.EaseNone, "Opacity", "0"); + } + + if (Player.X > m_king.X - 100) + Player.X = m_king.X - 100; + + if (m_kingKilled == false && m_king.WasHit == true) + { + m_kingKilled = true; + //SoundManager.PlaySound("Boss_Title_Exit"); + //SoundManager.PlaySound("Player_Death_Grunt"); + Game.ScreenManager.DisplayScreen(ScreenType.TitleWhite, false); + } + + base.Update(gameTime); + } + + public override void Draw(Camera2D camera) + { + base.Draw(camera); + m_king.Draw(camera); + + m_tutorialText.Position = Game.ScreenManager.Camera.Position; + m_tutorialText.Y -= 200; + camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + m_tutorialText.Draw(camera); + camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_tutorialText.Dispose(); + m_tutorialText = null; + m_king.Dispose(); + m_king = null; + base.Dispose(); + } + } + + protected override GameObj CreateCloneInstance() + { + return new ThroneRoomObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + + public override void RefreshTextObjs() + { + //m_tutorialText.Text = LocaleBuilder.getResourceString("LOC_ID_THRONE_ROOM_OBJ_1") /*"Press"*/ + " [Input:" + InputMapType.PLAYER_ATTACK + "] " + LocaleBuilder.getResourceString("LOC_ID_THRONE_ROOM_OBJ_2") /*"to Attack"*/; + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Game Objects/RoomObjs/TutorialRoomObj.cs b/RogueCastle/src/Game Objects/RoomObjs/TutorialRoomObj.cs new file mode 100644 index 0000000..6e928a7 --- /dev/null +++ b/RogueCastle/src/Game Objects/RoomObjs/TutorialRoomObj.cs @@ -0,0 +1,445 @@ +//#define OLD_CONSOLE_CREDITS +//#define SWITCH_CREDITS + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Tweener.Ease; +using Tweener; +using InputSystem; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class TutorialRoomObj : RoomObj + { + private KeyIconTextObj m_tutorialText; + private int m_waypointIndex = 0; + private List m_waypointList; + //private string[,] m_tutorialTextList; + //private string[,] m_tutorialControllerTextList; + private string[] m_tutorialTextList; + private string[] m_tutorialControllerTextList; + + private TextObj m_creditsText; + private TextObj m_creditsTitleText; + private string[] m_creditsTextList; + private string[] m_creditsTextTitleList; + private Vector2 m_creditsPosition; + private int m_creditsIndex = 0; + + private SpriteObj m_diary; + private SpriteObj m_doorSprite; + private DoorObj m_door; + private SpriteObj m_speechBubble; + + public TutorialRoomObj() + { + m_waypointList = new List(); + } + + public override void Initialize() + { + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "diary") + m_diary = obj as SpriteObj; + + if (obj.Name == "doorsprite") + m_doorSprite = obj as SpriteObj; + } + + m_door = DoorList[0]; + + m_speechBubble = new SpriteObj("ExclamationSquare_Sprite"); + m_speechBubble.Flip = SpriteEffects.FlipHorizontally; + m_speechBubble.Scale = new Vector2(1.2f, 1.2f); + GameObjList.Add(m_speechBubble); + + m_diary.OutlineWidth = 2; + m_speechBubble.Position = new Vector2(m_diary.X, m_diary.Y - m_speechBubble.Height - 20); + + /* + m_tutorialTextList = new string[,] + { + // { textID, action, textID, action, textID } + { "LOC_ID_TUTORIAL_ROOM_OBJ_1", " [Input:" + InputMapType.PLAYER_JUMP2 + "] " , "LOC_ID_TUTORIAL_ROOM_OBJ_2", "" , "" }, + { "LOC_ID_TUTORIAL_ROOM_OBJ_3", " [Input:" + InputMapType.PLAYER_JUMP2 + "] " , "LOC_ID_TUTORIAL_ROOM_OBJ_4", "" , "" }, + { "LOC_ID_TUTORIAL_ROOM_OBJ_1", " [Input:" + InputMapType.PLAYER_ATTACK + "] ", "LOC_ID_TUTORIAL_ROOM_OBJ_5", "" , "" }, + { "LOC_ID_TUTORIAL_ROOM_OBJ_3", " [Input:" + InputMapType.PLAYER_DOWN2 + "] " , "LOC_ID_TUTORIAL_ROOM_OBJ_6", " [Input:" + InputMapType.PLAYER_JUMP2 + "] " , "LOC_ID_TUTORIAL_ROOM_OBJ_7" }, + { "LOC_ID_TUTORIAL_ROOM_OBJ_8", " [Input:" + InputMapType.PLAYER_DOWN2 + "] " , "LOC_ID_TUTORIAL_ROOM_OBJ_6", " [Input:" + InputMapType.PLAYER_ATTACK + "] ", "LOC_ID_TUTORIAL_ROOM_OBJ_9" } + }; + + m_tutorialControllerTextList = new string[,] + { + // { textID, action, textID, action, textID } + { "LOC_ID_TUTORIAL_ROOM_OBJ_1", " [Input:" + InputMapType.PLAYER_JUMP1 + "] " , "LOC_ID_TUTORIAL_ROOM_OBJ_2", "" , "" }, + { "LOC_ID_TUTORIAL_ROOM_OBJ_3", " [Input:" + InputMapType.PLAYER_JUMP1 + "] " , "LOC_ID_TUTORIAL_ROOM_OBJ_4", "" , "" }, + { "LOC_ID_TUTORIAL_ROOM_OBJ_1", " [Input:" + InputMapType.PLAYER_ATTACK + "] ", "LOC_ID_TUTORIAL_ROOM_OBJ_5", "" , "" }, + { "LOC_ID_TUTORIAL_ROOM_OBJ_3", " [Input:" + InputMapType.PLAYER_DOWN1 + "] " , "LOC_ID_TUTORIAL_ROOM_OBJ_6", " [Input:" + InputMapType.PLAYER_JUMP1 + "] " , "LOC_ID_TUTORIAL_ROOM_OBJ_7" }, + { "LOC_ID_TUTORIAL_ROOM_OBJ_8", " [Input:" + InputMapType.PLAYER_DOWN1 + "] " , "LOC_ID_TUTORIAL_ROOM_OBJ_6", " [Input:" + InputMapType.PLAYER_ATTACK + "] ", "LOC_ID_TUTORIAL_ROOM_OBJ_9" } + }; + */ + + // NEW PLACEHOLDER TEXT + m_tutorialTextList = new string[] + { + "LOC_ID_TUTORIAL_ROOM_OBJ_11", + "LOC_ID_TUTORIAL_ROOM_OBJ_12", + "LOC_ID_TUTORIAL_ROOM_OBJ_13", + "LOC_ID_TUTORIAL_ROOM_OBJ_14", + "LOC_ID_TUTORIAL_ROOM_OBJ_15" + }; + + m_tutorialControllerTextList = new string[] + { + "LOC_ID_TUTORIAL_ROOM_OBJ_16", + "LOC_ID_TUTORIAL_ROOM_OBJ_17", + "LOC_ID_TUTORIAL_ROOM_OBJ_18", + "LOC_ID_TUTORIAL_ROOM_OBJ_19", + "LOC_ID_TUTORIAL_ROOM_OBJ_20" + }; + + m_creditsTextTitleList = new string[] + { + "LOC_ID_TUTORIAL_CREDITS_TITLE_1", + "LOC_ID_TUTORIAL_CREDITS_TITLE_2", + "LOC_ID_TUTORIAL_CREDITS_TITLE_3", + "LOC_ID_TUTORIAL_CREDITS_TITLE_4", + "LOC_ID_TUTORIAL_CREDITS_TITLE_5", + "LOC_ID_TUTORIAL_CREDITS_TITLE_6", + "LOC_ID_TUTORIAL_CREDITS_TITLE_7", +#if OLD_CONSOLE_CREDITS || SWITCH_CREDITS + "LOC_ID_CREDITS_SCREEN_26", + //"Japanese Localization & Production By", // This is not translated +#endif + "LOC_ID_TUTORIAL_CREDITS_TITLE_8" + }; + + m_creditsTextList = new string[] + { + "Cellar Door Games", + "Teddy Lee", + "Kenny Lee", +#if SWITCH_CREDITS + "Ryan Lee", +#else + "Marie-Christine Bourdua", +#endif + "Glauber Kotaki", + "Gordon McGladdery", + "Judson Cowan", +#if OLD_CONSOLE_CREDITS + "Abstraction Games", + //"8-4, Ltd.", // The Japanese Localization text above needs to be translated before this can be uncommented out. +#endif +#if SWITCH_CREDITS + "BlitWorks SL", +#endif + "Rogue Legacy", + }; + + m_creditsPosition = new Vector2(50, 580); + + foreach (GameObj obj in GameObjList) + { + if (obj.Name == "waypoint1") + m_waypointList.Add(obj); + if (obj.Name == "waypoint2") + m_waypointList.Add(obj); + if (obj.Name == "waypoint3") + m_waypointList.Add(obj); + if (obj.Name == "waypoint4") + m_waypointList.Add(obj); + if (obj.Name == "waypoint5") + m_waypointList.Add(obj); + } + + base.Initialize(); + } + + public override void LoadContent(GraphicsDevice graphics) + { + m_tutorialText = new KeyIconTextObj(Game.JunicodeLargeFont); + m_tutorialText.FontSize = 28; + m_tutorialText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_tutorialText); // dummy locID to add TextObj to language refresh list + m_tutorialText.Align = Types.TextAlign.Centre; + m_tutorialText.OutlineWidth = 2; + m_tutorialText.ForcedScale = new Vector2(0.8f, 0.8f); + + m_creditsText = new TextObj(Game.JunicodeFont); + m_creditsText.FontSize = 20; + m_creditsText.Text = "Cellar Door Games"; // placeholder text + m_creditsText.DropShadow = new Vector2(2, 2); + + m_creditsTitleText = m_creditsText.Clone() as TextObj; + m_creditsTitleText.FontSize = 14; + + TextObj attackThisText = new TextObj(Game.JunicodeFont); + attackThisText.FontSize = 12; + attackThisText.Text = LocaleBuilder.getString("LOC_ID_TUTORIAL_ROOM_OBJ_10", attackThisText); + attackThisText.OutlineWidth = 2; + attackThisText.Align = Types.TextAlign.Centre; + attackThisText.Position = m_waypointList[m_waypointList.Count - 1].Position; + attackThisText.X -= 25; + attackThisText.Y -= 70; + this.GameObjList.Add(attackThisText); + + base.LoadContent(graphics); + } + + public override void OnEnter() + { + m_speechBubble.Visible = false; + m_diary.Visible = false; + m_doorSprite.ChangeSprite("CastleDoorOpen_Sprite"); + + // All code regarding second time entering tutorial room goes here. + if (Game.PlayerStats.TutorialComplete == true) + { + if (Game.PlayerStats.ReadLastDiary == false) + { + m_door.Locked = true; + m_doorSprite.ChangeSprite("CastleDoor_Sprite"); + } + else + { + m_door.Locked = false; + } + + m_diary.Visible = true; + Player.UpdateCollisionBoxes(); + Player.Position = new Vector2(this.X + 240 + Player.Width, this.Bounds.Bottom - 120 - (Player.Bounds.Bottom - Player.Y)); + } + + m_creditsTitleText.Opacity = 0; + m_creditsText.Opacity = 0; + + foreach (EnemyObj enemy in EnemyList) + enemy.Damage = 0; + + m_tutorialText.Opacity = 0; + Player.UnlockControls(); + + if (Game.PlayerStats.TutorialComplete == false) + SoundManager.PlayMusic("EndSong", true, 4); + else + SoundManager.StopMusic(4); + + //Tween.RunFunction(2, this, "DisplayCreditsText"); + Tween.RunFunction(2, Player.AttachedLevel, "DisplayCreditsText", true); + base.OnEnter(); + } + + // Hmm...looks like this function doesn't get executed --Dave + public void DisplayCreditsText() + { + if (m_creditsIndex < m_creditsTextList.Length) + { + m_creditsTitleText.Opacity = 0; + m_creditsText.Opacity = 0; + + m_creditsTitleText.Text = LocaleBuilder.getString(m_creditsTextTitleList[m_creditsIndex], m_creditsTitleText); + m_creditsText.Text = m_creditsTextList[m_creditsIndex]; + + // Tween text in. + Tween.To(m_creditsTitleText, 0.5f, Tween.EaseNone, "Opacity", "1"); + Tween.To(m_creditsText, 0.5f, Tween.EaseNone, "delay", "0.2", "Opacity", "1"); + m_creditsTitleText.Opacity = 1; + m_creditsText.Opacity = 1; + + // Tween text out. + Tween.To(m_creditsTitleText, 0.5f, Tween.EaseNone, "delay", "4", "Opacity", "0"); + Tween.To(m_creditsText, 0.5f, Tween.EaseNone, "delay", "4.2", "Opacity", "0"); + m_creditsTitleText.Opacity = 0; + m_creditsText.Opacity = 0; + + m_creditsIndex++; + Tween.RunFunction(8, this, "DisplayCreditsText"); + } + } + + private int PlayerNearWaypoint() + { + for (int i = 0; i < m_waypointList.Count; i++) + { + if (CDGMath.DistanceBetweenPts(Player.Position, m_waypointList[i].Position) < 500) + return i; + } + + return -1; + } + + public override void Update(GameTime gameTime) + { + if (Game.PlayerStats.TutorialComplete == false) + { + int previousIndex = m_waypointIndex; + m_waypointIndex = PlayerNearWaypoint(); + + if (m_waypointIndex != previousIndex) + { + Tween.StopAllContaining(m_tutorialText, false); + if (m_waypointIndex != -1) + { + if (InputManager.GamePadIsConnected(PlayerIndex.One) == false) + m_tutorialText.Text = LocaleBuilder.getString(m_tutorialTextList[m_waypointIndex], m_tutorialText); + //m_tutorialText.Text = LocaleBuilder.getString(m_tutorialTextList[m_waypointIndex, 0], m_tutorialText) + m_tutorialTextList[m_waypointIndex, 1] + + // LocaleBuilder.getString(m_tutorialTextList[m_waypointIndex, 2], m_tutorialText) + m_tutorialTextList[m_waypointIndex, 3] + + // LocaleBuilder.getString(m_tutorialTextList[m_waypointIndex, 4], m_tutorialText); + else + m_tutorialText.Text = LocaleBuilder.getString(m_tutorialControllerTextList[m_waypointIndex], m_tutorialText); + //m_tutorialText.Text = LocaleBuilder.getString(m_tutorialControllerTextList[m_waypointIndex, 0], m_tutorialText) + m_tutorialControllerTextList[m_waypointIndex, 1] + + // LocaleBuilder.getString(m_tutorialControllerTextList[m_waypointIndex, 2], m_tutorialText) + m_tutorialControllerTextList[m_waypointIndex, 3] + + // LocaleBuilder.getString(m_tutorialControllerTextList[m_waypointIndex, 4], m_tutorialText); + Tween.To(m_tutorialText, 0.25f, Tween.EaseNone, "Opacity", "1"); + } + else + Tween.To(m_tutorialText, 0.25f, Tween.EaseNone, "Opacity", "0"); + } + } + else + { + Rectangle diaryBound = m_diary.Bounds; + diaryBound.X -= 50; + diaryBound.Width += 100; + m_speechBubble.Y = m_diary.Y - m_speechBubble.Height - 20 - 30 + ((float)Math.Sin(Game.TotalGameTime * 20) * 2); + if (CollisionMath.Intersects(Player.Bounds, diaryBound) && Player.IsTouchingGround == true) + { + if (m_speechBubble.SpriteName == "ExclamationSquare_Sprite") + m_speechBubble.ChangeSprite("UpArrowSquare_Sprite"); + + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + if (Game.PlayerStats.ReadLastDiary == false) + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("DiaryEntry" + (LevelEV.TOTAL_JOURNAL_ENTRIES - 1)); + manager.DialogueScreen.SetConfirmEndHandler(this, "RunFlashback"); + manager.DisplayScreen(ScreenType.Dialogue, true, null); + } + else + { + RCScreenManager manager = Player.AttachedLevel.ScreenManager as RCScreenManager; + manager.DisplayScreen(ScreenType.DiaryEntry, true); + } + } + } + else + { + if (m_speechBubble.SpriteName == "UpArrowSquare_Sprite") + m_speechBubble.ChangeSprite("ExclamationSquare_Sprite"); + } + + if (Game.PlayerStats.ReadLastDiary == false || CollisionMath.Intersects(Player.Bounds, diaryBound) == true) + m_speechBubble.Visible = true; + else if (Game.PlayerStats.ReadLastDiary == true && CollisionMath.Intersects(Player.Bounds, diaryBound) == false) + m_speechBubble.Visible = false; + + } + base.Update(gameTime); + } + + public void RunFlashback() + { + Player.LockControls(); + (Player.AttachedLevel.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.DiaryFlashback, true); + Tween.RunFunction(0.5f, this, "OpenDoor"); + } + + public void OpenDoor() + { + Player.UnlockControls(); + + m_doorSprite.ChangeSprite("CastleDoorOpen_Sprite"); + m_door.Locked = false; + Game.PlayerStats.ReadLastDiary = true; + Game.PlayerStats.DiaryEntry = LevelEV.TOTAL_JOURNAL_ENTRIES; + (Player.AttachedLevel.ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData); + + // Door opening smoke effect and sfx goes here. + } + + public override void Draw(Camera2D camera) + { + Vector2 cameraPos = Game.ScreenManager.Camera.TopLeftCorner; + m_creditsTitleText.Position = new Vector2(cameraPos.X + m_creditsPosition.X, cameraPos.Y + m_creditsPosition.Y); + m_creditsText.Position = m_creditsTitleText.Position; + m_creditsText.Y += 35; + m_creditsTitleText.X += 5; + + base.Draw(camera); + + m_tutorialText.Position = Game.ScreenManager.Camera.Position; + m_tutorialText.Y -= 200; + camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + m_tutorialText.Draw(camera); + m_creditsText.Draw(camera); + m_creditsTitleText.Draw(camera); + camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_tutorialText.Dispose(); + m_tutorialText = null; + m_waypointList.Clear(); + m_waypointList = null; + m_creditsText.Dispose(); + m_creditsText = null; + m_creditsTitleText.Dispose(); + m_creditsTitleText = null; + + Array.Clear(m_tutorialTextList, 0, m_tutorialTextList.Length); + Array.Clear(m_tutorialControllerTextList, 0, m_tutorialControllerTextList.Length); + Array.Clear(m_creditsTextTitleList, 0, m_creditsTextTitleList.Length); + Array.Clear(m_creditsTextList, 0, m_creditsTextList.Length); + + m_tutorialTextList = null; + m_creditsTextTitleList = null; + m_creditsTextList = null; + m_tutorialControllerTextList = null; + + m_door = null; + m_doorSprite = null; + m_diary = null; + m_speechBubble = null; + base.Dispose(); + } + } + + protected override GameObj CreateCloneInstance() + { + return new TutorialRoomObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + } + + public override void RefreshTextObjs() + { + /* + if (m_waypointIndex != -1 && m_tutorialText != null) + { + if (InputManager.GamePadIsConnected(PlayerIndex.One) == false) + m_tutorialText.Text = LocaleBuilder.getString(m_tutorialTextList[m_waypointIndex, 0], m_tutorialText) + m_tutorialTextList[m_waypointIndex, 1] + + LocaleBuilder.getString(m_tutorialTextList[m_waypointIndex, 2], m_tutorialText) + m_tutorialTextList[m_waypointIndex, 3] + + LocaleBuilder.getString(m_tutorialTextList[m_waypointIndex, 4], m_tutorialText); + else + m_tutorialText.Text = LocaleBuilder.getString(m_tutorialControllerTextList[m_waypointIndex, 0], m_tutorialText) + m_tutorialControllerTextList[m_waypointIndex, 1] + + LocaleBuilder.getString(m_tutorialControllerTextList[m_waypointIndex, 2], m_tutorialText) + m_tutorialControllerTextList[m_waypointIndex, 3] + + LocaleBuilder.getString(m_tutorialControllerTextList[m_waypointIndex, 4], m_tutorialText); + } + */ + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Game Objects/SkillObj.cs b/RogueCastle/src/Game Objects/SkillObj.cs new file mode 100644 index 0000000..f4e86dd --- /dev/null +++ b/RogueCastle/src/Game Objects/SkillObj.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using DS2DEngine; +using Microsoft.Xna.Framework.Input; + +namespace RogueCastle +{ + public class SkillObj : SpriteObj + { + public string NameLocID { get; set; } + public string DescLocID { get; set; } + public string InputDescLocID { get; set; } + //public string[] InputDescLocIDs; // locID, text, locID + public string[] UnitLocIDs; // text, locID (some measurement units require leading space, some don't) + + // Not used anymore + //public string Description { get; set; } + //public string InputDescription { get; set; } + + public float PerLevelModifier { get; set; } + public int BaseCost { get; set; } + public int Appreciation { get; set; } + public int MaxLevel { get; set; } + public SkillType TraitType { get; set; } + public string IconName { get; set; } + private TextObj LevelText; + public string UnitOfMeasurement { get; set; } + public byte StatType { get; set; } // Dummy property. No longer used. + public bool DisplayStat { get; set; } // Dummy property. No longer used. + + private SpriteObj m_coinIcon; + + public SkillObj(string spriteName) + : base(spriteName) + { + StatType = TraitStatType.PlayerMaxHealth; + DisplayStat = false; + this.Visible = false; + this.ForceDraw = true; + LevelText = new TextObj(Game.JunicodeFont); + LevelText.FontSize = 10; + LevelText.Align = Types.TextAlign.Centre; + LevelText.OutlineWidth = 2; + //InputDescription = ""; + this.OutlineWidth = 2; + //LevelText.DropShadow = new Vector2(1, 1); + + m_coinIcon = new SpriteObj("UpgradeIcon_Sprite"); + //m_coinIcon.Scale = new Vector2(0.7f, 0.7f); + } + + public override void Draw(Camera2D camera) + { + if (this.Opacity > 0) + { + float storedOpacity = this.Opacity; + this.TextureColor = Color.Black; + this.Opacity = 0.5f; + this.X += 8; + this.Y += 8; + base.Draw(camera); + + this.X -= 8; + this.Y -= 8; + this.TextureColor = Color.White; + this.Opacity = storedOpacity; + } + base.Draw(camera); + + LevelText.Position = new Vector2(this.X, this.Bounds.Bottom - LevelText.Height/2); + LevelText.Text = this.CurrentLevel + "/" + this.MaxLevel; + LevelText.Opacity = this.Opacity; + if (this.CurrentLevel >= this.MaxLevel) + { + LevelText.TextureColor = Color.Yellow; + LevelText.Text = LocaleBuilder.getString("LOC_ID_SKILL_SCREEN_19", LevelText); //"Max Level"; //Teddy Changed Max Level to Max + } + else + LevelText.TextureColor = Color.White; + + LevelText.Draw(camera); + + if (Game.PlayerStats.Gold >= this.TotalCost && this.CurrentLevel < this.MaxLevel) + { + m_coinIcon.Opacity = this.Opacity; + m_coinIcon.Position = new Vector2(this.X + 18, this.Y - 40); + m_coinIcon.Draw(camera); + } + } + + protected override GameObj CreateCloneInstance() + { + return new SkillObj(_spriteName); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + SkillObj clone = obj as SkillObj; + //clone.Description = this.Description; + clone.PerLevelModifier = this.PerLevelModifier; + clone.BaseCost = this.BaseCost; + clone.Appreciation = this.Appreciation; + clone.MaxLevel = this.MaxLevel; + clone.CurrentLevel = this.CurrentLevel; + clone.TraitType = this.TraitType; + //clone.InputDescription = this.InputDescription; + clone.UnitOfMeasurement = this.UnitOfMeasurement; + clone.StatType = this.StatType; + clone.DisplayStat = this.DisplayStat; + clone.NameLocID = this.NameLocID; + clone.DescLocID = this.DescLocID; + clone.InputDescLocID = this.InputDescLocID; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + LevelText.Dispose(); + LevelText = null; + + m_coinIcon.Dispose(); + m_coinIcon = null; + + base.Dispose(); + } + } + + private int m_currentLevel = 0; + public int CurrentLevel // Prevent the current level from going beyond the max level. + { + get { return m_currentLevel; } + set + { + if (value > MaxLevel) + m_currentLevel = MaxLevel; + else + m_currentLevel = value; + } + } + + public int TotalCost + { + get { return BaseCost + (CurrentLevel * Appreciation) + (GameEV.SKILL_LEVEL_COST_INCREASE * Game.PlayerStats.CurrentLevel); } + } + + public float ModifierAmount + { + get + { + return CurrentLevel * PerLevelModifier; + } + } + } +} diff --git a/RogueCastle/src/Game Objects/SkyObj.cs b/RogueCastle/src/Game Objects/SkyObj.cs new file mode 100644 index 0000000..78b2e99 --- /dev/null +++ b/RogueCastle/src/Game Objects/SkyObj.cs @@ -0,0 +1,240 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class SkyObj : GameObj + { + private SpriteObj m_moon; + private BackgroundObj m_differenceCloud; + private BackgroundObj m_differenceCloud2; + private BackgroundObj m_differenceCloud3; + + private Vector2 m_moonPos; + private SpriteObj m_silhouette; + private bool m_silhouetteFlying; + private float m_silhouetteTimer; + private ProceduralLevelScreen m_levelScreen; + + public float MorningOpacity { get; set; } + + public SkyObj(ProceduralLevelScreen levelScreen) + { + m_levelScreen = levelScreen; + } + + public void LoadContent(Camera2D camera) + { + Vector2 rtScale = new Vector2(2, 2); + + m_moon = new SpriteObj("ParallaxMoon_Sprite"); + m_moon.Position = new Vector2(900, 200); + if (LevelEV.SAVE_FRAMES == true) + { + m_moon.Position /= 2; + rtScale = Vector2.One; + } + m_moon.Scale = rtScale; + m_moon.ForceDraw = true; + + m_moonPos = m_moon.Position; + + m_differenceCloud = new BackgroundObj("ParallaxDifferenceClouds_Sprite"); + m_differenceCloud.SetRepeated(true, true, camera, SamplerState.LinearWrap); + m_differenceCloud.Scale = rtScale; + + m_differenceCloud.TextureColor = new Color(10, 10, 80); + m_differenceCloud.ParallaxSpeed = new Vector2(0.2f, 0); + + m_differenceCloud2 = new BackgroundObj("ParallaxDifferenceClouds_Sprite"); + m_differenceCloud2.SetRepeated(true, true, camera, SamplerState.LinearWrap); + m_differenceCloud2.Scale = rtScale; + m_differenceCloud2.Flip = SpriteEffects.FlipHorizontally; + m_differenceCloud2.TextureColor = new Color(80, 80, 160); + m_differenceCloud2.X -= 500; + m_differenceCloud2.ParallaxSpeed = new Vector2(0.4f, 0); + + m_differenceCloud3 = new BackgroundObj("ParallaxDifferenceClouds_Sprite"); + m_differenceCloud3.SetRepeated(true, true, camera, SamplerState.LinearWrap); + m_differenceCloud3.Scale = rtScale; + m_differenceCloud3.Flip = SpriteEffects.FlipHorizontally; + m_differenceCloud3.TextureColor = Color.White; + m_differenceCloud3.X -= 500; + m_differenceCloud3.ParallaxSpeed = new Vector2(0.4f, 0); + + m_silhouette = new SpriteObj("GardenBat_Sprite"); + m_silhouette.ForceDraw = true; + m_silhouette.AnimationDelay = 1 / 20f; + m_silhouette.Scale = rtScale; + } + + public void ReinitializeRT(Camera2D camera) + { + Vector2 rtScale = new Vector2(2, 2); + if (LevelEV.SAVE_FRAMES == true) + { + m_moon.Position /= 2; + rtScale = Vector2.One; + } + + if (m_differenceCloud != null) m_differenceCloud.Dispose(); + m_differenceCloud = new BackgroundObj("ParallaxDifferenceClouds_Sprite"); + m_differenceCloud.SetRepeated(true, true, camera, SamplerState.LinearWrap); + m_differenceCloud.Scale = rtScale; + m_differenceCloud.TextureColor = new Color(10, 10, 80); + m_differenceCloud.ParallaxSpeed = new Vector2(0.2f, 0); + + if (m_differenceCloud2 != null) m_differenceCloud2.Dispose(); + m_differenceCloud2 = new BackgroundObj("ParallaxDifferenceClouds_Sprite"); + m_differenceCloud2.SetRepeated(true, true, camera, SamplerState.LinearWrap); + m_differenceCloud2.Scale = rtScale; + m_differenceCloud2.Flip = SpriteEffects.FlipHorizontally; + m_differenceCloud2.TextureColor = new Color(80, 80, 160); + m_differenceCloud2.X -= 500; + m_differenceCloud2.ParallaxSpeed = new Vector2(0.4f, 0); + + if (m_differenceCloud3 != null) m_differenceCloud3.Dispose(); + m_differenceCloud3 = new BackgroundObj("ParallaxDifferenceClouds_Sprite"); + m_differenceCloud3.SetRepeated(true, true, camera, SamplerState.LinearWrap); + m_differenceCloud3.Scale = rtScale; + m_differenceCloud3.Flip = SpriteEffects.FlipHorizontally; + m_differenceCloud3.TextureColor = new Color(80, 80, 160); + m_differenceCloud3.X -= 500; + m_differenceCloud3.ParallaxSpeed = new Vector2(0.4f, 0); + } + + public void Update(GameTime gameTime) + { + float elapsedSeconds = (float) gameTime.ElapsedGameTime.TotalSeconds; + + if (m_silhouetteFlying == false) + { + if (m_silhouetteTimer > 0) + { + m_silhouetteTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_silhouetteTimer <= 0) + { + int randInt = CDGMath.RandomInt(1, 100); + if (randInt > 95) // 5% chance of showing santa. + ShowSilhouette(true); + else if (randInt > 65) // 30% chance of other silhouette happening. + ShowSilhouette(false); + else + m_silhouetteTimer = 5; + } + } + } + + if (m_silhouetteFlying == false && m_silhouetteTimer <= 0) + m_silhouetteTimer = 5; + + if (m_silhouette.SpriteName == "GardenPerson_Sprite") + m_silhouette.Rotation += (2f * 60 * elapsedSeconds); + } + + private void ShowSilhouette(bool showSanta) + { + if (m_levelScreen != null) + { + m_silhouetteFlying = true; + m_silhouette.Rotation = 0; + m_silhouette.Flip = SpriteEffects.None; + bool appearLeft = false; + if (CDGMath.RandomInt(0, 1) > 0) // 50% chance of silhouette coming from left or right. + appearLeft = true; + + string[] randImage = new string[] { "GardenBat_Sprite", "GardenCrow_Sprite", "GardenBat_Sprite", "GardenCrow_Sprite", "GardenPerson_Sprite" }; + + if (showSanta == false) + m_silhouette.ChangeSprite(randImage[CDGMath.RandomInt(0, 4)]); + else + m_silhouette.ChangeSprite("GardenSanta_Sprite"); + + m_silhouette.PlayAnimation(true); + + Vector2 spawnPt = Vector2.Zero; + if (appearLeft == true) + m_silhouette.X = -m_silhouette.Width; + else + { + m_silhouette.Flip = SpriteEffects.FlipHorizontally; + m_silhouette.X = m_levelScreen.CurrentRoom.Width + m_silhouette.Width; + } + + m_silhouette.Y = CDGMath.RandomFloat(100, 500); + + int xDistance = m_levelScreen.CurrentRoom.Bounds.Width + m_silhouette.Width * 2; + + if (appearLeft == false) + xDistance = -xDistance; + + Tweener.Tween.By(m_silhouette, CDGMath.RandomFloat(10, 15), Tweener.Tween.EaseNone, "X", xDistance.ToString(), "Y", CDGMath.RandomInt(-200, 200).ToString()); + Tweener.Tween.AddEndHandlerToLastTween(this, "SilhouetteComplete"); + } + } + + public void SilhouetteComplete() + { + m_silhouetteFlying = false; + } + + public override void Draw(Camera2D camera) + { + m_moon.X = m_moonPos.X - (camera.TopLeftCorner.X * 0.01f); + m_moon.Y = m_moonPos.Y - (camera.TopLeftCorner.Y * 0.01f); + + camera.GraphicsDevice.Clear(new Color(4, 29, 86)); + camera.Draw(Game.GenericTexture, new Rectangle(-10, -10, 1400, 800), Color.SkyBlue * MorningOpacity); + + m_moon.Opacity = (1 - MorningOpacity); + m_silhouette.Opacity = (1 - MorningOpacity); + m_differenceCloud.Opacity = (1 - MorningOpacity); + m_differenceCloud2.Opacity = (1 - MorningOpacity); + m_differenceCloud3.Opacity = MorningOpacity; + + m_moon.Draw(camera); + m_differenceCloud.Draw(camera); + m_differenceCloud2.Draw(camera); + m_differenceCloud3.Draw(camera); + m_silhouette.Draw(camera); + + //Console.WriteLine(m_silhouette.Position + " " + m_levelScreen.CurrentRoom.Position); + + base.Draw(camera); + } + + protected override GameObj CreateCloneInstance() + { + return new SkyObj(m_levelScreen); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // DONE + m_differenceCloud.Dispose(); + m_differenceCloud = null; + m_differenceCloud2.Dispose(); + m_differenceCloud2 = null; + m_differenceCloud3.Dispose(); + m_differenceCloud3 = null; + + m_moon.Dispose(); + m_moon = null; + + m_silhouette.Dispose(); + m_silhouette = null; + + m_levelScreen = null; + + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/TeleporterObj.cs b/RogueCastle/src/Game Objects/TeleporterObj.cs new file mode 100644 index 0000000..21738e7 --- /dev/null +++ b/RogueCastle/src/Game Objects/TeleporterObj.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using DS2DEngine; + +namespace RogueCastle +{ + public class TeleporterObj : PhysicsObj + { + public bool Activated { get; set; } + private SpriteObj m_arrowIcon; + + public TeleporterObj() + : base("TeleporterBase_Sprite") + { + this.CollisionTypeTag = GameTypes.CollisionType_WALL; + SetCollision(false); + this.IsWeighted = false; + Activated = false; + this.OutlineWidth = 2; + + m_arrowIcon = new SpriteObj("UpArrowSquare_Sprite"); + m_arrowIcon.OutlineWidth = 2; + m_arrowIcon.Visible = false; + } + + public void SetCollision(bool collides) + { + this.CollidesTop = collides; + this.CollidesBottom = collides; + this.CollidesLeft = collides; + this.CollidesRight = collides; + } + + public override void Draw(Camera2D camera) + { + if (m_arrowIcon.Visible == true) + { + m_arrowIcon.Position = new Vector2(this.Bounds.Center.X, this.Bounds.Top - 50 + (float)Math.Sin(Game.TotalGameTime * 20) * 2); + m_arrowIcon.Draw(camera); + m_arrowIcon.Visible = false; + } + + base.Draw(camera); + } + + public override void CollisionResponse(CollisionBox thisBox, CollisionBox otherBox, int collisionResponseType) + { + PlayerObj player = otherBox.AbsParent as PlayerObj; + if (Game.ScreenManager.Player.ControlsLocked == false && player != null && player.IsTouchingGround == true) + m_arrowIcon.Visible = true; + + base.CollisionResponse(thisBox, otherBox, collisionResponseType); + } + + protected override GameObj CreateCloneInstance() + { + return new TeleporterObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + TeleporterObj clone = obj as TeleporterObj; + clone.Activated = this.Activated; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_arrowIcon.Dispose(); + m_arrowIcon = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/TerrainObj.cs b/RogueCastle/src/Game Objects/TerrainObj.cs new file mode 100644 index 0000000..8f6df53 --- /dev/null +++ b/RogueCastle/src/Game Objects/TerrainObj.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; +using System.Globalization; + +namespace RogueCastle +{ + public class TerrainObj : BlankObj + { + public bool ShowTerrain = true; + + public TerrainObj(int width, int height) + : base(width, height) + { + this.CollisionTypeTag = GameTypes.CollisionType_WALL; + this.IsCollidable = true; + this.IsWeighted = false; + } + + public override void Draw(Camera2D camera) + { + if (ShowTerrain == true && CollisionMath.Intersects(this.Bounds, camera.Bounds) || this.ForceDraw == true) + camera.Draw(Game.GenericTexture, this.Position, new Rectangle(0, 0, this.Width, this.Height), this.TextureColor, MathHelper.ToRadians(Rotation), Vector2.Zero, 1, SpriteEffects.None, 0); + } + + protected override GameObj CreateCloneInstance() + { + return new TerrainObj(_width, _height); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + TerrainObj clone = obj as TerrainObj; + clone.ShowTerrain = this.ShowTerrain; + foreach (CollisionBox box in this.CollisionBoxes) + clone.AddCollisionBox(box.X, box.Y, box.Width, box.Height, box.Type); + } + + public override void PopulateFromXMLReader(System.Xml.XmlReader reader, System.Globalization.CultureInfo ci) + { + base.PopulateFromXMLReader(reader, ci); + + SetWidth(_width); + SetHeight(_height); + this.AddCollisionBox(0, 0, _width, _height, Consts.TERRAIN_HITBOX); // This adds the terrain collision box for terrain objects. + this.AddCollisionBox(0, 0, _width, _height, Consts.BODY_HITBOX); // This adds a body collision box to terrain objects. + + if (this.CollidesTop == true && + this.CollidesBottom == false && + this.CollidesLeft == false && + this.CollidesRight == false) // Decreases the height of a fall-through platform. + this.SetHeight(this.Height / 2); + } + + public Rectangle NonRotatedBounds + { + get + { + return new Rectangle((int)this.X, (int)this.Y, this.Width, this.Height); + } + } + + private struct CornerPoint + { + public Vector2 Position; + public float Rotation; + + public CornerPoint(Vector2 position, float rotation) + { + Position = position; + Rotation = MathHelper.ToRadians(rotation); + } + } + } +} diff --git a/RogueCastle/src/Game Objects/WaypointObj.cs b/RogueCastle/src/Game Objects/WaypointObj.cs new file mode 100644 index 0000000..11962e0 --- /dev/null +++ b/RogueCastle/src/Game Objects/WaypointObj.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; + +namespace RogueCastle +{ + public class WaypointObj : GameObj + { + public int OrbType = 0; + + protected override GameObj CreateCloneInstance() + { + return new WaypointObj(); + } + + protected override void FillCloneInstance(object obj) + { + base.FillCloneInstance(obj); + + WaypointObj clone = obj as WaypointObj; + clone.OrbType = this.OrbType; + } + } +} diff --git a/RogueCastle/src/Game.cs b/RogueCastle/src/Game.cs new file mode 100644 index 0000000..b65e4d6 --- /dev/null +++ b/RogueCastle/src/Game.cs @@ -0,0 +1,1612 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Audio; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Media; +using SpriteSystem; +using InputSystem; +using Tweener; +using Tweener.Ease; +using DS2DEngine; +using System.IO; +using System.Globalization; +using System.Threading; + +namespace RogueCastle +{ + /// + /// This is the main type for your game + /// + public class Game : Microsoft.Xna.Framework.Game + { + //Generic textures used for multiple objects. + public static Texture2D GenericTexture; + public static Effect MaskEffect; + public static Effect BWMaskEffect; + public static Effect ShadowEffect; + public static Effect ParallaxEffect; + public static Effect RippleEffect; + public static GaussianBlur GaussianBlur; + public static Effect HSVEffect; + public static Effect InvertShader; + public static Effect ColourSwapShader; + + public static AreaStruct[] Area1List; + + public GraphicsDeviceManager graphics; + public static RCScreenManager ScreenManager { get; internal set; } + SaveGameManager m_saveGameManager; + PhysicsManager m_physicsManager; + + public static EquipmentSystem EquipmentSystem; + //public static TraitSystem TraitSystem; + + public static PlayerStats PlayerStats = new PlayerStats(); + public static SpriteFont PixelArtFont; + public static SpriteFont PixelArtFontBold; + public static SpriteFont JunicodeFont; + public static SpriteFont EnemyLevelFont; + public static SpriteFont PlayerLevelFont; + public static SpriteFont GoldFont; + public static SpriteFont HerzogFont; + public static SpriteFont JunicodeLargeFont; + public static SpriteFont CinzelFont; + public static SpriteFont BitFont; + public static SpriteFont NotoSansSCFont; // Noto Sans Simplified Chinese + public static SpriteFont RobotoSlabFont; + + public static Cue LineageSongCue; + + public static InputMap GlobalInput; + public static SettingStruct GameConfig; + //Song tempSong; + + public static List NameArray; + public static List FemaleNameArray; + + private string m_commandLineFilePath = ""; + + private GameTime m_forcedGameTime1, m_forcedGameTime2; + private float m_frameLimit = 1 / 40f; + private bool m_frameLimitSwap; + public static float TotalGameTime = 0; + + public static float HoursPlayedSinceLastSave { get; set; } + + private bool m_contentLoaded = false; + private bool m_gameLoaded = false; + + public Game(string filePath = "") + { + // Make sure to remove reference from LocaleBuilder's text refresh list when a TextObj is disposed + TextObj.disposeMethod = LocaleBuilder.RemoveFromTextRefreshList; + + if (filePath.Contains("-t")) + { + LevelEV.TESTROOM_LEVELTYPE = GameTypes.LevelType.TOWER; + filePath = filePath.Replace("-t", ""); + } + else if (filePath.Contains("-d")) + { + LevelEV.TESTROOM_LEVELTYPE = GameTypes.LevelType.DUNGEON; + filePath = filePath.Replace("-d", ""); + } + else if (filePath.Contains("-g")) + { + LevelEV.TESTROOM_LEVELTYPE = GameTypes.LevelType.GARDEN; + filePath = filePath.Replace("-g", ""); + } + + /* flibit didn't like this + if (Thread.CurrentThread.CurrentCulture.Name != "en-US") + { + Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", false); + Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US", false); + } + */ + Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; + Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; + + m_commandLineFilePath = filePath; + graphics = new GraphicsDeviceManager(this); + Content.RootDirectory = "Content"; + //this.graphics.PreferredBackBufferWidth = 1360;// GlobalEV.ScreenWidth; + //this.graphics.PreferredBackBufferHeight = 768;//GlobalEV.ScreenHeight; + + EngineEV.ScreenWidth = GlobalEV.ScreenWidth; // Very important. Tells the engine if the game is running at a fixed resolution (which it is). + EngineEV.ScreenHeight = GlobalEV.ScreenHeight; + + //this.graphics.IsFullScreen = true; + this.Window.Title = "Rogue Legacy"; + ScreenManager = new RCScreenManager(this); + m_saveGameManager = new SaveGameManager(this); + + // Set first to false and last to true for targetelapsedtime to work. + this.IsFixedTimeStep = false; // Sets game to slow down instead of frame skip if set to false. + this.graphics.SynchronizeWithVerticalRetrace = !LevelEV.SHOW_FPS; // Disables setting the FPS to your screen's refresh rate. + // WARNING, if you turn off frame limiting, if the framerate goes over 1000 then the elapsed time will be too small a number for a float to carry and things will break. + //this.TargetElapsedTime = TimeSpan.FromSeconds(1.0f / 60.0f);// Sets the frame rate to 30 fps. + this.Window.AllowUserResizing = false; + + if (LevelEV.ENABLE_OFFSCREEN_CONTROL == false) + InactiveSleepTime = new TimeSpan(); // Overrides sleep time, which disables the lag when losing focus. + + m_physicsManager = new PhysicsManager(); + EquipmentSystem = new RogueCastle.EquipmentSystem(); + EquipmentSystem.InitializeEquipmentData(); + EquipmentSystem.InitializeAbilityCosts(); + + //TraitSystem = new RogueCastle.TraitSystem(); + //TraitSystem.Initialize(); + + GameConfig = new SettingStruct(); + + GraphicsDeviceManager.PreparingDeviceSettings += ChangeGraphicsSettings; + + SleepUtil.DisableScreensaver(); + } + + protected void ChangeGraphicsSettings(object sender, PreparingDeviceSettingsEventArgs e) + { + e.GraphicsDeviceInformation.PresentationParameters.DepthStencilFormat = DepthFormat.None; + e.GraphicsDeviceInformation.PresentationParameters.RenderTargetUsage = RenderTargetUsage.PreserveContents; + } + + /// + /// Allows the game to perform any initialization it needs to before starting to run. + /// This is where it can query for any required services and load any non-graphic + /// related content. Calling base.Initialize will enumerate through any components + /// and initialize them as well. + /// + protected override void Initialize() + { + // TODO: Add your initialization logic here. + Tween.Initialize(7000); + InputManager.Initialize(); + InputManager.InitializeDXManager(this.Services, this.Window); + Buttons[] buttonList = new Buttons[] + { + Buttons.X, + Buttons.A, + Buttons.B, + Buttons.Y, + Buttons.LeftShoulder, + Buttons.RightShoulder, + Buttons.LeftTrigger, + Buttons.RightTrigger, + Buttons.Back, + Buttons.Start, + Buttons.LeftStick, + Buttons.RightStick, + }; + InputManager.RemapDXPad(buttonList); + + SpriteLibrary.Init(); + DialogueManager.Initialize(); + + // Default to english language + LocaleBuilder.languageType = LanguageType.English; +#if false + // Remove the comment tags for these language documents creating a release build. + //TxtToBinConverter.Convert("Content\\Languages\\Diary_En.txt"); + //TxtToBinConverter.Convert("Content\\Languages\\Text_En.txt"); + + // Comment out these language documents when creating a release build. + // Don't forget to copy paste the created bin files to your project's language folder! + if (LevelEV.CREATE_RETAIL_VERSION == false) + { + DialogueManager.LoadLanguageDocument(Content, "Languages\\Text_En"); + DialogueManager.LoadLanguageDocument(Content, "Languages\\Diary_En"); + } + else + { + DialogueManager.LoadLanguageBinFile("Content\\Languages\\Text_En.bin"); + DialogueManager.LoadLanguageBinFile("Content\\Languages\\Diary_En.bin"); + } + DialogueManager.SetLanguage("English"); +#endif + + m_saveGameManager.Initialize(); + + m_physicsManager.Initialize(ScreenManager.Camera); + m_physicsManager.TerminalVelocity = 2000; + //this.IsMouseVisible = true; + + //Components.Add(ScreenManager); + ScreenManager.Initialize(); // Necessary to manually call screenmanager initialize otherwise its LoadContent() method will be called first. + InitializeGlobalInput(); + LoadConfig(); // Loads the config file, override language if specified in config file + InitializeScreenConfig(); // Applies the screen config data. + + // Must be called after config file is loaded so that the correct language name array is loaded. + InitializeMaleNameArray(false); + InitializeFemaleNameArray(false); + + if (LevelEV.SHOW_FPS == true) + { + FrameRateCounter fpsCounter = new FrameRateCounter(this); + Components.Add(fpsCounter); + fpsCounter.Initialize(); + } + + // Code used to handle game chop. + m_forcedGameTime1 = new GameTime(new TimeSpan(), new TimeSpan(0, 0, 0, 0, (int)(m_frameLimit * 1000))); + m_forcedGameTime2 = new GameTime(new TimeSpan(), new TimeSpan(0, 0, 0, 0, (int)(m_frameLimit * 1050))); + + // Initializes the global input map. + //InitializeGlobalInput(); + //LoadConfig(); // Loads the config file. + //InitializeScreenConfig(); // Applies the screen config data. + base.Initialize(); // Must be called before the enemylist is created so that their content is loaded. + + // Everything below this line can be disabled for release. + + if (LevelEV.CREATE_RETAIL_VERSION == false) + { + //Steps for adding enemies to editor. + //1. Add a new EnemyEditorData object to enemyList with the name of the enemy class as the constructor (right below). + //2. In the Builder class, add a case statement for the enemy string in BuildEnemy(). + //3. Press F5 to build and run, which should create the EnemyList.xml file that the map editor reads. + List enemyList = new List(); + enemyList.Add(new EnemyEditorData(EnemyType.Skeleton)); + enemyList.Add(new EnemyEditorData(EnemyType.Knight)); + enemyList.Add(new EnemyEditorData(EnemyType.Fireball)); + enemyList.Add(new EnemyEditorData(EnemyType.Fairy)); + enemyList.Add(new EnemyEditorData(EnemyType.Turret)); + enemyList.Add(new EnemyEditorData(EnemyType.Ninja)); + enemyList.Add(new EnemyEditorData(EnemyType.Horse)); + enemyList.Add(new EnemyEditorData(EnemyType.Zombie)); + enemyList.Add(new EnemyEditorData(EnemyType.Wolf)); + enemyList.Add(new EnemyEditorData(EnemyType.BallAndChain)); + enemyList.Add(new EnemyEditorData(EnemyType.Eyeball)); + enemyList.Add(new EnemyEditorData(EnemyType.Blob)); + enemyList.Add(new EnemyEditorData(EnemyType.SwordKnight)); + enemyList.Add(new EnemyEditorData(EnemyType.Eagle)); + enemyList.Add(new EnemyEditorData(EnemyType.ShieldKnight)); + enemyList.Add(new EnemyEditorData(EnemyType.FireWizard)); + enemyList.Add(new EnemyEditorData(EnemyType.IceWizard)); + enemyList.Add(new EnemyEditorData(EnemyType.EarthWizard)); + enemyList.Add(new EnemyEditorData(EnemyType.BouncySpike)); + enemyList.Add(new EnemyEditorData(EnemyType.SpikeTrap)); + enemyList.Add(new EnemyEditorData(EnemyType.Plant)); + enemyList.Add(new EnemyEditorData(EnemyType.Energon)); + enemyList.Add(new EnemyEditorData(EnemyType.Spark)); + enemyList.Add(new EnemyEditorData(EnemyType.SkeletonArcher)); + enemyList.Add(new EnemyEditorData(EnemyType.Chicken)); + enemyList.Add(new EnemyEditorData(EnemyType.Platform)); + enemyList.Add(new EnemyEditorData(EnemyType.HomingTurret)); + enemyList.Add(new EnemyEditorData(EnemyType.LastBoss)); + enemyList.Add(new EnemyEditorData(EnemyType.Dummy)); + enemyList.Add(new EnemyEditorData(EnemyType.Starburst)); + enemyList.Add(new EnemyEditorData(EnemyType.Portrait)); + enemyList.Add(new EnemyEditorData(EnemyType.Mimic)); + + // Take this out when building release version. + XMLCompiler.CompileEnemies(enemyList, Directory.GetCurrentDirectory()); + } + } + + public static void InitializeGlobalInput() + { + if (GlobalInput != null) + GlobalInput.ClearAll(); + else + GlobalInput = new InputMap(PlayerIndex.One, true); + + //////////// KEYBOARD INPUT MAP + GlobalInput.AddInput(InputMapType.MENU_CONFIRM1, Keys.Enter); + GlobalInput.AddInput(InputMapType.MENU_CANCEL1, Keys.Escape); + GlobalInput.AddInput(InputMapType.MENU_CREDITS, Keys.LeftControl); + GlobalInput.AddInput(InputMapType.MENU_OPTIONS, Keys.Tab); + GlobalInput.AddInput(InputMapType.MENU_PROFILECARD, Keys.LeftShift); + GlobalInput.AddInput(InputMapType.MENU_ROGUEMODE, Keys.Back); + GlobalInput.AddInput(InputMapType.MENU_PAUSE, Keys.Escape); + GlobalInput.AddInput(InputMapType.MENU_MAP, Keys.Tab); + + GlobalInput.AddInput(InputMapType.PLAYER_JUMP1, Keys.S); + GlobalInput.AddInput(InputMapType.PLAYER_JUMP2, Keys.Space); + GlobalInput.AddInput(InputMapType.PLAYER_SPELL1, Keys.W); + GlobalInput.AddInput(InputMapType.PLAYER_ATTACK, Keys.D); + GlobalInput.AddInput(InputMapType.PLAYER_BLOCK, Keys.A); + GlobalInput.AddInput(InputMapType.PLAYER_DASHLEFT, Keys.Q); + GlobalInput.AddInput(InputMapType.PLAYER_DASHRIGHT, Keys.E); + GlobalInput.AddInput(InputMapType.PLAYER_UP1, Keys.I); + GlobalInput.AddInput(InputMapType.PLAYER_UP2, Keys.Up); + GlobalInput.AddInput(InputMapType.PLAYER_DOWN1, Keys.K); + GlobalInput.AddInput(InputMapType.PLAYER_DOWN2, Keys.Down); + GlobalInput.AddInput(InputMapType.PLAYER_LEFT1, Keys.J); + GlobalInput.AddInput(InputMapType.PLAYER_LEFT2, Keys.Left); + GlobalInput.AddInput(InputMapType.PLAYER_RIGHT1, Keys.L); + GlobalInput.AddInput(InputMapType.PLAYER_RIGHT2, Keys.Right); + + //////////// GAMEPAD INPUT MAP + + GlobalInput.AddInput(InputMapType.MENU_CONFIRM1, Buttons.A); + GlobalInput.AddInput(InputMapType.MENU_CONFIRM2, Buttons.Start); + GlobalInput.AddInput(InputMapType.MENU_CANCEL1, Buttons.B); + GlobalInput.AddInput(InputMapType.MENU_CANCEL2, Buttons.Back); + GlobalInput.AddInput(InputMapType.MENU_CREDITS, Buttons.RightTrigger); + GlobalInput.AddInput(InputMapType.MENU_OPTIONS, Buttons.Y); + GlobalInput.AddInput(InputMapType.MENU_PROFILECARD, Buttons.X); + GlobalInput.AddInput(InputMapType.MENU_ROGUEMODE, Buttons.Back); + GlobalInput.AddInput(InputMapType.MENU_PAUSE, Buttons.Start); + GlobalInput.AddInput(InputMapType.MENU_MAP, Buttons.Back); + + GlobalInput.AddInput(InputMapType.PLAYER_JUMP1, Buttons.A); + GlobalInput.AddInput(InputMapType.PLAYER_ATTACK, Buttons.X); + GlobalInput.AddInput(InputMapType.PLAYER_BLOCK, Buttons.Y); + GlobalInput.AddInput(InputMapType.PLAYER_DASHLEFT, Buttons.LeftTrigger); + GlobalInput.AddInput(InputMapType.PLAYER_DASHRIGHT, Buttons.RightTrigger); + GlobalInput.AddInput(InputMapType.PLAYER_UP1, Buttons.DPadUp); + //GlobalInput.AddInput(InputMapType.PLAYER_UP2, Buttons.LeftThumbstickUp); + GlobalInput.AddInput(InputMapType.PLAYER_UP2, ThumbStick.LeftStick, -90, 30); + GlobalInput.AddInput(InputMapType.PLAYER_DOWN1, Buttons.DPadDown); + GlobalInput.AddInput(InputMapType.PLAYER_DOWN2, ThumbStick.LeftStick, 90, 37); + GlobalInput.AddInput(InputMapType.PLAYER_LEFT1, Buttons.DPadLeft); + GlobalInput.AddInput(InputMapType.PLAYER_LEFT2, Buttons.LeftThumbstickLeft); + GlobalInput.AddInput(InputMapType.PLAYER_RIGHT1, Buttons.DPadRight); + GlobalInput.AddInput(InputMapType.PLAYER_RIGHT2, Buttons.LeftThumbstickRight); + GlobalInput.AddInput(InputMapType.PLAYER_SPELL1, Buttons.B); + + GlobalInput.AddInput(InputMapType.MENU_PROFILESELECT, Keys.Escape); + GlobalInput.AddInput(InputMapType.MENU_PROFILESELECT, Buttons.Back); + GlobalInput.AddInput(InputMapType.MENU_DELETEPROFILE, Keys.Back); + GlobalInput.AddInput(InputMapType.MENU_DELETEPROFILE, Buttons.Y); + + // Adding mouse confirm/cancel controls + GlobalInput.AddInput(InputMapType.MENU_CONFIRM3, Keys.F13); + GlobalInput.AddInput(InputMapType.MENU_CANCEL3, Keys.F14); + + // Special code so that player attack acts as the second confirm and player jump acts as the second cancel. + GlobalInput.KeyList[InputMapType.MENU_CONFIRM2] = Game.GlobalInput.KeyList[InputMapType.PLAYER_ATTACK]; + GlobalInput.KeyList[InputMapType.MENU_CANCEL2] = Game.GlobalInput.KeyList[InputMapType.PLAYER_JUMP1]; + } + + private void InitializeDefaultConfig() + { + GameConfig.FullScreen = false; + GameConfig.ScreenWidth = 1360; + GameConfig.ScreenHeight = 768; + GameConfig.MusicVolume = 1; + GameConfig.SFXVolume = 0.8f; + GameConfig.EnableDirectInput = true; + InputManager.Deadzone = 10; + GameConfig.ProfileSlot = 1; + GameConfig.EnableSteamCloud = false; + GameConfig.ReduceQuality = false; + + InitializeGlobalInput(); + } + + /// + /// LoadContent will be called once per game and is the place to load + /// all of your content. + /// + protected override void LoadContent() + { + if (m_contentLoaded == false) + { + m_contentLoaded = true; + LoadAllSpriteFonts(); + LoadAllEffects(); + LoadAllSpritesheets(); + + // Initializing Sound Manager. + SoundManager.Initialize("Content\\Audio\\RogueCastleXACTProj.xgs"); + SoundManager.LoadWaveBank("Content\\Audio\\SFXWaveBank.xwb"); + SoundManager.LoadWaveBank("Content\\Audio\\MusicWaveBank.xwb", true); + SoundManager.LoadSoundBank("Content\\Audio\\SFXSoundBank.xsb"); + SoundManager.LoadSoundBank("Content\\Audio\\MusicSoundBank.xsb", true); + SoundManager.GlobalMusicVolume = Game.GameConfig.MusicVolume; + SoundManager.GlobalSFXVolume = Game.GameConfig.SFXVolume; + + if (InputManager.GamePadIsConnected(PlayerIndex.One)) + InputManager.SetPadType(PlayerIndex.One, PadTypes.GamePad); + + // Creating a generic texture for use. + Game.GenericTexture = new Texture2D(GraphicsDevice, 1, 1); + Game.GenericTexture.SetData(new Color[] { Color.White }); + + // This causes massive slowdown on load. + if (LevelEV.LOAD_SPLASH_SCREEN == false) + { + LevelBuilder2.Initialize(); + LevelParser.ParseRooms("Map_1x1", this.Content); + LevelParser.ParseRooms("Map_1x2", this.Content); + LevelParser.ParseRooms("Map_1x3", this.Content); + LevelParser.ParseRooms("Map_2x1", this.Content); + LevelParser.ParseRooms("Map_2x2", this.Content); + LevelParser.ParseRooms("Map_2x3", this.Content); + LevelParser.ParseRooms("Map_3x1", this.Content); + LevelParser.ParseRooms("Map_3x2", this.Content); + LevelParser.ParseRooms("Map_Special", this.Content); + LevelParser.ParseRooms("Map_DLC1", this.Content, true); + LevelBuilder2.IndexRoomList(); + } + + SkillSystem.Initialize(); // Must be initialized after the sprites are loaded because the MiscSpritesheet is needed. + + AreaStruct CastleZone = new AreaStruct() + { + Name = "The Grand Entrance", + LevelType = GameTypes.LevelType.CASTLE, + TotalRooms = new Vector2(24, 28),//(17,19),//(20, 22),//(25,35),//(20,25),//(15, 25), + BossInArea = true, + SecretRooms = new Vector2(1, 3),//(2, 3), + BonusRooms = new Vector2(2, 3), + Color = Color.White, + }; + + AreaStruct GardenZone = new AreaStruct() + { + LevelType = GameTypes.LevelType.GARDEN, + TotalRooms = new Vector2(23, 27),//(25,29),//(25, 35),//(15, 25), + BossInArea = true, + SecretRooms = new Vector2(1, 3), + BonusRooms = new Vector2(2, 3), + Color = Color.Green, + }; + + AreaStruct TowerZone = new AreaStruct() + { + LevelType = GameTypes.LevelType.TOWER, + TotalRooms = new Vector2(23, 27),//(27,31),//(25,29),//(25, 35),//(15, 25), + BossInArea = true, + SecretRooms = new Vector2(1, 3), + BonusRooms = new Vector2(2, 3), + Color = Color.DarkBlue, + }; + + AreaStruct DungeonZone = new AreaStruct() + { + LevelType = GameTypes.LevelType.DUNGEON, + TotalRooms = new Vector2(23, 27),//(29,33),//(25, 29),//(25, 35),//(15, 25), + BossInArea = true, + SecretRooms = new Vector2(1, 3), + BonusRooms = new Vector2(2, 3), + Color = Color.Red, + }; + + #region Demo Levels + + AreaStruct CastleZoneDemo = new AreaStruct() + { + Name = "The Grand Entrance", + LevelType = GameTypes.LevelType.CASTLE, + TotalRooms = new Vector2(24, 27),//(25,35),//(20,25),//(15, 25), + BossInArea = true, + SecretRooms = new Vector2(2, 3), + BonusRooms = new Vector2(2, 3), + Color = Color.White, + }; + + AreaStruct GardenZoneDemo = new AreaStruct() + { + Name = "The Grand Entrance", + LevelType = GameTypes.LevelType.GARDEN, + TotalRooms = new Vector2(12, 14),//(25, 35),//(15, 25), + BossInArea = true, + SecretRooms = new Vector2(2, 3), + BonusRooms = new Vector2(1, 2), + Color = Color.Green, + }; + + AreaStruct DungeonZoneDemo = new AreaStruct() + { + Name = "The Grand Entrance", + LevelType = GameTypes.LevelType.DUNGEON, + TotalRooms = new Vector2(12, 14),//(25, 35),//(15, 25), + BossInArea = true, + SecretRooms = new Vector2(2, 3), + BonusRooms = new Vector2(1, 2), + Color = Color.Red, + }; + + AreaStruct TowerZoneDemo = new AreaStruct() + { + Name = "The Grand Entrance", + LevelType = GameTypes.LevelType.TOWER, + TotalRooms = new Vector2(12, 14),//(25, 35),//(15, 25), + BossInArea = true, + SecretRooms = new Vector2(2, 3), + BonusRooms = new Vector2(1, 2), + Color = Color.DarkBlue, + }; + + #endregion + + Area1List = new AreaStruct[] { CastleZone, GardenZone, TowerZone, DungeonZone }; //DUNGEON IS LAST AREA + + if (LevelEV.RUN_DEMO_VERSION == true) + Area1List = new AreaStruct[] { CastleZoneDemo }; //DUNGEON IS LAST AREA + //Area1List = new AreaStruct[] { CastleZoneDemo, GardenZoneDemo, TowerZoneDemo, DungeonZoneDemo }; //DUNGEON IS LAST AREA + + } + + //ScreenManager.LoadContent(); // What is this doing here? + } + + public void LoadAllSpriteFonts() + { + SpriteFontArray.SpriteFontList.Clear(); + PixelArtFont = Content.Load("Fonts\\Arial12"); + SpriteFontArray.SpriteFontList.Add(PixelArtFont); + PixelArtFontBold = Content.Load("Fonts\\PixelArtFontBold"); + SpriteFontArray.SpriteFontList.Add(PixelArtFontBold); + EnemyLevelFont = Content.Load("Fonts\\EnemyLevelFont"); + SpriteFontArray.SpriteFontList.Add(EnemyLevelFont); + EnemyLevelFont.Spacing = -5; + PlayerLevelFont = Content.Load("Fonts\\PlayerLevelFont"); + SpriteFontArray.SpriteFontList.Add(PlayerLevelFont); + PlayerLevelFont.Spacing = -7; + GoldFont = Content.Load("Fonts\\GoldFont"); + SpriteFontArray.SpriteFontList.Add(GoldFont); + GoldFont.Spacing = -5; + JunicodeFont = Content.Load("Fonts\\Junicode"); + SpriteFontArray.SpriteFontList.Add(JunicodeFont); + //JunicodeFont.Spacing = -1; + JunicodeLargeFont = Content.Load("Fonts\\JunicodeLarge"); + SpriteFontArray.SpriteFontList.Add(JunicodeLargeFont); + JunicodeLargeFont.Spacing = -1; + HerzogFont = Content.Load("Fonts\\HerzogVonGraf24"); + SpriteFontArray.SpriteFontList.Add(HerzogFont); + CinzelFont = Content.Load("Fonts\\CinzelFont"); + SpriteFontArray.SpriteFontList.Add(CinzelFont); + BitFont = Content.Load("Fonts\\BitFont"); + SpriteFontArray.SpriteFontList.Add(BitFont); + NotoSansSCFont = Content.Load("Fonts\\NotoSansSC"); + SpriteFontArray.SpriteFontList.Add(NotoSansSCFont); + RobotoSlabFont = Content.Load("Fonts\\RobotoSlab"); + SpriteFontArray.SpriteFontList.Add(RobotoSlabFont); + } + + public void LoadAllSpritesheets() + { + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\blacksmithUISpritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\enemyFinal2Spritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\enemyFinalSpritesheetBig", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\miscSpritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\traitsCastleSpritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\castleTerrainSpritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\playerSpritesheetBig", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\titleScreen3Spritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\mapSpritesheetBig", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\startingRoomSpritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\towerTerrainSpritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\dungeonTerrainSpritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\profileCardSpritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\portraitSpritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\gardenTerrainSpritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\parallaxBGSpritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\getItemScreenSpritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\neoTerrainSpritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\languageSpritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\language2Spritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\language3Spritesheet", false); + SpriteLibrary.LoadSpritesheet(Content, "GameSpritesheets\\blitworksSpritesheet", false); + } + + public void LoadAllEffects() + { + // Necessary stuff to create a 2D shader. + MaskEffect = Content.Load("Shaders\\AlphaMaskShader"); + + ShadowEffect = Content.Load("Shaders\\ShadowFX"); + ParallaxEffect = Content.Load("Shaders\\ParallaxFX"); + HSVEffect = Content.Load("Shaders\\HSVShader"); + InvertShader = Content.Load("Shaders\\InvertShader"); + ColourSwapShader = Content.Load("Shaders\\ColourSwapShader"); + RippleEffect = Content.Load("Shaders\\Shockwave"); + + RippleEffect.Parameters["mag"].SetValue(2); + + GaussianBlur = new RogueCastle.GaussianBlur(this, 1320, 720); + GaussianBlur.Amount = 2f; + GaussianBlur.Radius = 7; + GaussianBlur.ComputeKernel(); + GaussianBlur.ComputeOffsets(); + Game.GaussianBlur.InvertMask = true; + + // Necessary stuff to create Black/White mask shader. + BWMaskEffect = Content.Load("Shaders\\BWMaskShader"); + } + + /// + /// UnloadContent will be called once per game and is the place to unload + /// all content. + /// + protected override void UnloadContent() + { + // TODO: Unload any non ContentManager content here + } + + WeakReference gcTracker = new WeakReference(new object()); + /// + /// Allows the game to run logic such as updating the world, + /// checking for collisions, gathering input, and playing audio. + /// + /// Provides a snapshot of timing values. + /// + public int graphicsToggle = 0; + + protected override void Update(GameTime gameTime) + { + //if (InputManager.JustPressed(Keys.B, null)) + //{ + // //Game.PlayerStats.TimesCastleBeaten = 0; + // //Game.PlayerStats.LastbossBeaten = false; + // //Game.PlayerStats.EyeballBossBeaten = true; + // //Game.PlayerStats.FairyBossBeaten = true; + // //Game.PlayerStats.FireballBossBeaten = true; + // //Game.PlayerStats.BlobBossBeaten = true; + + // //Game.PlayerStats.GetBlueprintArray[0][EquipmentBaseType.Bronze] = EquipmentState.Purchased; + // //Game.PlayerStats.GetBlueprintArray[1][EquipmentBaseType.Bronze] = EquipmentState.Purchased; + // //Game.PlayerStats.GetBlueprintArray[2][EquipmentBaseType.Bronze] = EquipmentState.Purchased; + // //Game.PlayerStats.GetBlueprintArray[3][EquipmentBaseType.Bronze] = EquipmentState.Purchased; + // //Game.PlayerStats.GetBlueprintArray[4][EquipmentBaseType.Bronze] = EquipmentState.Purchased; + + // //Game.PlayerStats.GetBlueprintArray[0][EquipmentBaseType.Knight] = EquipmentState.Purchased; + // //Game.PlayerStats.GetBlueprintArray[1][EquipmentBaseType.Knight] = EquipmentState.Purchased; + // //Game.PlayerStats.GetBlueprintArray[2][EquipmentBaseType.Knight] = EquipmentState.Purchased; + // //Game.PlayerStats.GetBlueprintArray[3][EquipmentBaseType.Knight] = EquipmentState.Purchased; + // //Game.PlayerStats.GetBlueprintArray[4][EquipmentBaseType.Knight] = EquipmentState.Purchased; + + // //Game.PlayerStats.GetBlueprintArray[0][EquipmentBaseType.Blood] = EquipmentState.Purchased; + // //Game.PlayerStats.GetBlueprintArray[1][EquipmentBaseType.Blood] = EquipmentState.Purchased; + // //Game.PlayerStats.GetBlueprintArray[2][EquipmentBaseType.Blood] = EquipmentState.Purchased; + // //Game.PlayerStats.GetBlueprintArray[3][EquipmentBaseType.Blood] = EquipmentState.Purchased; + // //Game.PlayerStats.GetBlueprintArray[4][EquipmentBaseType.Blood] = EquipmentState.Purchased; + + // //Game.PlayerStats.GetRuneArray[0][EquipmentAbilityType.DoubleJump] = EquipmentState.Purchased; + // //Game.PlayerStats.GetRuneArray[1][EquipmentAbilityType.DoubleJump] = EquipmentState.Purchased; + // //Game.PlayerStats.GetRuneArray[1][EquipmentAbilityType.Flight] = EquipmentState.Purchased; + // //Game.PlayerStats.GetRuneArray[0][EquipmentAbilityType.ManaHPGain] = EquipmentState.Purchased; + // //Game.PlayerStats.GetRuneArray[1][EquipmentAbilityType.ManaHPGain] = EquipmentState.Purchased; + // //Game.PlayerStats.GetRuneArray[2][EquipmentAbilityType.ManaHPGain] = EquipmentState.Purchased; + // //Game.PlayerStats.GetRuneArray[0][EquipmentAbilityType.Dash] = EquipmentState.Purchased; + // //Game.PlayerStats.GetRuneArray[0][EquipmentAbilityType.DamageReturn] = EquipmentState.Purchased; + // //Game.PlayerStats.GetRuneArray[1][EquipmentAbilityType.DamageReturn] = EquipmentState.Purchased; + // //Game.PlayerStats.GetRuneArray[3][EquipmentAbilityType.ManaGain] = EquipmentState.Purchased; + // //Game.PlayerStats.GetRuneArray[3][EquipmentAbilityType.Vampirism] = EquipmentState.Purchased; + // //Game.PlayerStats.GetRuneArray[2][EquipmentAbilityType.Vampirism] = EquipmentState.Purchased; + // //Game.PlayerStats.GetRuneArray[2][EquipmentAbilityType.ManaGain] = EquipmentState.Purchased; + // //Game.PlayerStats.GetRuneArray[3][EquipmentAbilityType.GoldGain] = EquipmentState.Purchased; + // //Game.PlayerStats.GetRuneArray[4][EquipmentAbilityType.GoldGain] = EquipmentState.Purchased; + // //ScreenManager.Player.Visible = false; + // //ScreenManager.Player.Opacity = 0; + // ScreenManager.GetLevelScreen().SetPlayerHUDVisibility(false); + // ScreenManager.GetLevelScreen().SetMapDisplayVisibility(false); + //} + + if (m_gameLoaded == false) + { + m_gameLoaded = true; + if (LevelEV.DELETE_SAVEFILE == true) + { + SaveManager.ClearAllFileTypes(true); + SaveManager.ClearAllFileTypes(false); + } + +#if false + SkillSystem.ResetAllTraits(); + Game.PlayerStats.Dispose(); + Game.PlayerStats = new PlayerStats(); + //(ScreenManager as RCScreenManager).Player.Reset(); + Game.GameConfig.ProfileSlot = (byte)1; + (ScreenManager.Game as Game).SaveManager.LoadFiles(null, SaveType.PlayerData, SaveType.Lineage, SaveType.UpgradeData); + // Special circumstance where you should override player's current HP/MP + //Game.ScreenManager.Player.CurrentHealth = Game.PlayerStats.CurrentHealth; + //Game.ScreenManager.Player.CurrentMana = Game.PlayerStats.CurrentMana; + + ScreenManager.LoadContent(); + + // Ending screen, doesn't work when loaded this way + //ScreenManager.DisplayScreen(ScreenType.Ending, true, null); + + // GetItemScreen + /* + List objectList = new List(); + objectList.Add(new Vector2(100,100)); + + objectList.Add(GetItemType.Rune); + objectList.Add(new Vector2(EquipmentCategoryType.Helm, EquipmentAbilityType.ManaHPGain)); // (EquipmentCategoryType, EquipmentAbilityType) + + //objectList.Add(GetItemType.SpecialItem); + //objectList.Add(new Vector2(SpecialItemType.BlobToken, 0)); + + //objectList.Add(GetItemType.StatDrop); + //objectList.Add(new Vector2(ItemDropType.Stat_MaxHealth, 0)); + + //objectList.Add(GetItemType.TripStatDrop); + //objectList.Add(new Vector2(ItemDropType.Stat_MaxHealth, 0)); + //objectList.Add(new Vector2(ItemDropType.Stat_MaxMana, ItemDropType.Stat_Magic)); + + ScreenManager.DisplayScreen(ScreenType.GetItem, true, objectList); + */ + + // Enchantress (equipment) + //ScreenManager.DisplayScreen(ScreenType.Enchantress, true, null); + + // Blacksmith + //ScreenManager.DisplayScreen(ScreenType.Blacksmith, true, null); + + // Skill screen, manor + //ScreenManager.DisplayScreen(ScreenType.Skill, true, null); + + // Profile select + //ScreenManager.DisplayScreen(ScreenType.ProfileSelect, true, null); + + // Profile card + //ScreenManager.DisplayScreen(ScreenType.ProfileCard, true, null); + + // Lineage screen + //ScreenManager.DisplayScreen(ScreenType.Lineage, true, null); + + // Starting room, i.e. castle entrance with training dummy + //ScreenManager.DisplayScreen(ScreenType.StartingRoom, true, null); + + // Tutorial, make sure LevelEV.RUN_TESTROOM is false + //ScreenManager.DisplayScreen(ScreenType.TutorialRoom, true, null); + + // Dialog choice + /* + ScreenManager.DialogueScreen.SetDialogue("CarnivalRoom1-Start"); //"Meet Architect", "LineageChoiceWarning" + ScreenManager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + //ScreenManager.DialogueScreen.SetConfirmEndHandler(this, "StartGame"); + //ScreenManager.DialogueScreen.SetCancelEndHandler(typeof(Console), "WriteLine", "Canceling Selection"); + ScreenManager.DisplayScreen(ScreenType.Dialogue, true); + */ + + // Dialog screen + /* + ScreenManager.DialogueScreen.SetDialogue("DiaryEntry10"); // "FinalBossTalk03" + //ScreenManager.DialogueScreen.SetConfirmEndHandler(this, "Part4"); + ScreenManager.DisplayScreen(ScreenType.Dialogue, true); + */ + + // Options screen + /* + List optionsData = new List(); + optionsData.Add(false); + ScreenManager.DisplayScreen(ScreenType.Options, false, optionsData); + */ + + // Title screen + //ScreenManager.DisplayScreen(ScreenType.Title, true, null); +#else + if (LevelEV.LOAD_SPLASH_SCREEN == true) + { + if (LevelEV.RUN_DEMO_VERSION == true) + ScreenManager.DisplayScreen(ScreenType.DemoStart, true, null); + else + ScreenManager.DisplayScreen(ScreenType.CDGSplash, true, null); + } + else + { + if (LevelEV.LOAD_TITLE_SCREEN == false) + { + if (LevelEV.RUN_TESTROOM == true) + ScreenManager.DisplayScreen(ScreenType.Level, true, null); + else + { + if (LevelEV.RUN_TUTORIAL == true) + ScreenManager.DisplayScreen(ScreenType.TutorialRoom, true, null); + else + //ScreenManager.DisplayScreen(ScreenType.Lineage, true, null); // Just for testing lineages. + ScreenManager.DisplayScreen(ScreenType.StartingRoom, true, null); + //ScreenManager.DisplayScreen(ScreenType.Ending, true, null); + //ScreenManager.DisplayScreen(ScreenType.Credits, true, null); + } + } + else + { + //if (SaveManager.FileExists(SaveType.PlayerData)) + // this.SaveManager.LoadFiles(null, SaveType.PlayerData); + + //if (Game.PlayerStats.TutorialComplete == false) + // ScreenManager.DisplayScreen(ScreenType.TutorialRoom, true, null); + //else + ScreenManager.DisplayScreen(ScreenType.Title, true, null); + } + } +#endif + } + + // This code forces the game to slow down (instead of chop) if it drops below the frame limit. + TotalGameTime = (float)gameTime.TotalGameTime.TotalSeconds; + + GameTime gameTimeToUse = gameTime; + if (gameTime.ElapsedGameTime.TotalSeconds > m_frameLimit) + { + if (m_frameLimitSwap == false) + { + m_frameLimitSwap = true; + gameTimeToUse = m_forcedGameTime1; + } + else + { + m_frameLimitSwap = false; + gameTimeToUse = m_forcedGameTime2; + } + } + + //if (!gcTracker.IsAlive) + //{ + // Console.WriteLine("A garbage collection occurred!"); + // gcTracker = new WeakReference(new object()); + //} + + // The screenmanager is updated via the Components.Add call in the game constructor. It is called after this Update() call. + SoundManager.Update(gameTimeToUse); + if ((m_previouslyActiveCounter <= 0 && IsActive == true) || LevelEV.ENABLE_OFFSCREEN_CONTROL == true) // Only accept input if you have screen focus. + InputManager.Update(gameTimeToUse); + if (LevelEV.ENABLE_DEBUG_INPUT == true) + HandleDebugInput(); + Tween.Update(gameTimeToUse); + ScreenManager.Update(gameTimeToUse); + SoundManager.Update3DSounds(); // Special method to handle 3D sound overrides. Must go after enemy update. + base.Update(gameTime); + + if (IsActive == false) + m_previouslyActiveCounter = 0.25f; + + // Prevents mouse from accidentally leaving game while active. + //if (IsActive == true) + // Mouse.SetPosition((int)(GlobalEV.ScreenWidth / 2f), (int)(GlobalEV.ScreenHeight / 2f)); + + if (m_previouslyActiveCounter > 0) + m_previouslyActiveCounter -= 0.016f; + } + + private float m_previouslyActiveCounter = 0; // This makes sure your very first inputs upon returning after leaving the screen does not register (no accidental inputs happen). + + private void HandleDebugInput() + { + int languageType = (int)LocaleBuilder.languageType; + + if (InputManager.JustPressed(Keys.OemQuotes, null)) + { + languageType++; + if (languageType >= (int)LanguageType.MAX) + languageType = 0; + + LocaleBuilder.languageType = (LanguageType)languageType; + LocaleBuilder.RefreshAllText(); + Console.WriteLine("Changing to language type: " + (LanguageType)languageType); + } + else if (InputManager.JustPressed(Keys.OemSemicolon, null)) + { + languageType--; + if (languageType < 0) + languageType = (int)LanguageType.MAX - 1; + + LocaleBuilder.languageType = (LanguageType)languageType; + LocaleBuilder.RefreshAllText(); + Console.WriteLine("Changing to language type: " + (LanguageType)languageType); + } + + if (InputManager.JustPressed(Keys.OemPipe, null)) + { + Game.PlayerStats.ForceLanguageGender++; + if (Game.PlayerStats.ForceLanguageGender > 2) + Game.PlayerStats.ForceLanguageGender = 0; + LocaleBuilder.RefreshAllText(); + } + + if (InputManager.JustPressed(Keys.Z, null)) + { + graphicsToggle++; + if (graphicsToggle > 1) graphicsToggle = 0; + + switch (graphicsToggle) + { + case (0): + ScreenManager.GetLevelScreen().SetPlayerHUDVisibility(true); + ScreenManager.GetLevelScreen().SetMapDisplayVisibility(true); + break; + case (1): + ScreenManager.GetLevelScreen().SetPlayerHUDVisibility(false); + ScreenManager.GetLevelScreen().SetMapDisplayVisibility(false); + break; + } + } + } + + /// + /// This is called when the game should draw itself. + /// + /// Provides a snapshot of timing values. + protected override void Draw(GameTime gameTime) + { + // The screenmanager is drawn via the Components.Add call in the game constructor. It is called after this Draw() call. + ScreenManager.Draw(gameTime); + base.Draw(gameTime); + } + + private bool m_maleChineseNamesLoaded = false; + public void InitializeMaleNameArray(bool forceCreate) + { + // The name list needs to be reloaded every time the language is from Chinese to another language or vice versa. + if ((m_maleChineseNamesLoaded == false && LocaleBuilder.languageType == LanguageType.Chinese_Simp) || + (m_maleChineseNamesLoaded == true && LocaleBuilder.languageType != LanguageType.Chinese_Simp)) + forceCreate = true; + + if (NameArray != null && NameArray.Count > 0 && forceCreate == false) + return; + + if (NameArray != null) + NameArray.Clear(); + else + NameArray = new List(); + + // Logographic fonts cannot make use of the name change system, otherwise the bitmap spritesheet + // generated by the system would have to include every single glyph. + if (LocaleBuilder.languageType != LanguageType.Chinese_Simp) + { + m_maleChineseNamesLoaded = false; + + using (StreamReader sr = new StreamReader(Path.Combine("Content","HeroNames.txt"))) + { + // A test to make sure no special characters are used in the game. + SpriteFont junicode = Content.Load("Fonts\\Junicode"); + SpriteFontArray.SpriteFontList.Add(junicode); + TextObj specialCharTest = new TextObj(junicode); + + while (!sr.EndOfStream) + { + string name = sr.ReadLine(); + bool hasSpecialChar = false; + + try + { + specialCharTest.Text = name; + } + catch + { + hasSpecialChar = true; + } + + if (!name.Contains("//") && hasSpecialChar == false) + NameArray.Add(name); + } + + specialCharTest.Dispose(); + SpriteFontArray.SpriteFontList.Remove(junicode); + } + } + else + { + m_maleChineseNamesLoaded = true; + + // List of male Chinese names. + NameArray.Add("马如龙"); + NameArray.Add("常遇春"); + NameArray.Add("胡不归"); + NameArray.Add("何千山"); + NameArray.Add("方日中"); + NameArray.Add("谢南山"); + NameArray.Add("慕江南"); + NameArray.Add("赵寒江"); + NameArray.Add("宋乔木"); + NameArray.Add("应楚山"); + NameArray.Add("江山月"); + NameArray.Add("赵慕寒"); + NameArray.Add("万重山"); + NameArray.Add("郭百鸣"); + NameArray.Add("谢武夫"); + NameArray.Add("关中林"); + NameArray.Add("吴深山"); + NameArray.Add("向春风"); + NameArray.Add("牛始旦"); + NameArray.Add("卫东方"); + NameArray.Add("萧北辰"); + NameArray.Add("黃鹤年"); + NameArray.Add("王石柱"); + NameArray.Add("胡江林"); + NameArray.Add("周宇浩"); + NameArray.Add("程向阳"); + NameArray.Add("魏海风"); + NameArray.Add("龚剑辉"); + NameArray.Add("周宇浩"); + NameArray.Add("何汝平"); + } + + // Ensures the name array is greater than 0. + if (NameArray.Count < 1) + { + NameArray.Add("Lee"); + NameArray.Add("Charles"); + NameArray.Add("Lancelot"); + } + } + + private bool m_femaleChineseNamesLoaded = false; + public void InitializeFemaleNameArray(bool forceCreate) + { + // The name list needs to be reloaded every time the language is from Chinese to another language or vice versa. + if ((m_femaleChineseNamesLoaded == false && LocaleBuilder.languageType == LanguageType.Chinese_Simp) || + (m_femaleChineseNamesLoaded == true && LocaleBuilder.languageType != LanguageType.Chinese_Simp)) + forceCreate = true; + + if (FemaleNameArray != null && FemaleNameArray.Count > 0 && forceCreate == false) + return; + + if (FemaleNameArray != null) + FemaleNameArray.Clear(); + else + FemaleNameArray = new List(); + + // Logographic fonts cannot make use of the name change system, otherwise the bitmap spritesheet + // generated by the system would have to include every single glyph. + if (LocaleBuilder.languageType != LanguageType.Chinese_Simp) + { + m_femaleChineseNamesLoaded = false; + + using (StreamReader sr = new StreamReader(Path.Combine("Content", "HeroineNames.txt"))) + { + // A test to make sure no special characters are used in the game. + SpriteFont junicode = Content.Load("Fonts\\Junicode"); + SpriteFontArray.SpriteFontList.Add(junicode); + TextObj specialCharTest = new TextObj(junicode); + + while (!sr.EndOfStream) + { + string name = sr.ReadLine(); + bool hasSpecialChar = false; + + try + { + specialCharTest.Text = name; + } + catch + { + hasSpecialChar = true; + } + + if (!name.Contains("//") && hasSpecialChar == false) + FemaleNameArray.Add(name); + } + + specialCharTest.Dispose(); + SpriteFontArray.SpriteFontList.Remove(junicode); + } + } + else + { + m_femaleChineseNamesLoaded = true; + + // List of female Chinese names. + FemaleNameArray.Add("水一方"); + FemaleNameArray.Add("刘妙音"); + FemaleNameArray.Add("郭釆薇"); + FemaleNameArray.Add("颜如玉"); + FemaleNameArray.Add("陈巧雅"); + FemaleNameArray.Add("萧玉旋"); + FemaleNameArray.Add("花可秀"); + FemaleNameArray.Add("董小婉"); + FemaleNameArray.Add("李诗诗"); + FemaleNameArray.Add("唐秋香"); + FemaleNameArray.Add("方美人"); + FemaleNameArray.Add("金喜儿"); + FemaleNameArray.Add("达莉萍"); + FemaleNameArray.Add("蔡靜语"); + FemaleNameArray.Add("郭玲玲"); + FemaleNameArray.Add("黃晓莺"); + FemaleNameArray.Add("杜秋娘"); + FemaleNameArray.Add("高媛媛"); + FemaleNameArray.Add("林靜妤"); + FemaleNameArray.Add("凤雨婷"); + FemaleNameArray.Add("徐瑶瑶"); + FemaleNameArray.Add("祝台英"); + FemaleNameArray.Add("郭燕秋"); + FemaleNameArray.Add("江小满"); + FemaleNameArray.Add("项月芳"); + FemaleNameArray.Add("郑云云"); + FemaleNameArray.Add("王琼琼"); + FemaleNameArray.Add("李瓶儿"); + FemaleNameArray.Add("周楚红"); + FemaleNameArray.Add("叶秋菊"); + } + + // Ensures the female name array is greater than 0. + if (FemaleNameArray.Count < 1) + { + FemaleNameArray.Add("Jenny"); + FemaleNameArray.Add("Shanoa"); + FemaleNameArray.Add("Chun Li"); + } + } + + public static void ConvertPlayerNameFormat(ref string playerName, ref string romanNumeral) + { + if (playerName.Length < 3) + return; + + // Remove the Sir or Lady title in the player name. + if (playerName.Substring(0, 3) == "Sir") + { + if (playerName.Length > 3) + playerName = playerName.Substring(4); // Removing "Sir ". + } + else if (playerName.Length > 3 && playerName.Substring(0, 4) == "Lady") + { + if (playerName.Length > 4) + playerName = playerName.Substring(5); // Removing "Lady ". + } + + // Remove the roman numerals in the player name. + int romanNumeralIndex = playerName.Trim().LastIndexOf(" "); + if (romanNumeralIndex > 0) + { + string romanNumeralString = playerName.Substring(romanNumeralIndex + 1); + // Can't check them all, so only fix the first 40 name duplicates. + string[] romanNumeralCheckArray = new string[] { + "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XVIII", "XIX", "XX", + "XXI", "XXII", "XXIII", "XXIV", "XXV", "XXVI", "XXVII", "XXVIII", "XXIX", "XXX", "XXXI", "XXXII", "XXXIII", "XXXIV", "XXXV", "XXXVI", + "XXXVII", "XXXVIII", "XXXIX", "XXXX", + }; + for (int i = 0; i < romanNumeralCheckArray.Length; i++) + { + if (romanNumeralString == romanNumeralCheckArray[i]) + { + playerName = playerName.Substring(0, playerName.Length - romanNumeralString.Length).Trim(); + romanNumeral = romanNumeralString.Trim(); + break; + } + } + } + } + + public static string NameHelper(string playerName, string romanNumerals, bool isFemale, bool forceConversionCheck = false) + { + if (Game.PlayerStats.RevisionNumber <= 0 || forceConversionCheck == true) + ConvertPlayerNameFormat(ref playerName, ref romanNumerals); + + if (isFemale == true) + { + if (LocaleBuilder.languageType == LanguageType.Chinese_Simp && (romanNumerals == "" || romanNumerals == null)) + return string.Format(LocaleBuilder.getResourceString("LOC_ID_LINEAGE_OBJ_14_NEW_SINGULAR_ZH"), playerName, "").Trim(); + else + return string.Format(LocaleBuilder.getResourceString("LOC_ID_LINEAGE_OBJ_14_NEW"), playerName, romanNumerals).Trim(); + } + else + { + if (LocaleBuilder.languageType == LanguageType.Chinese_Simp && (romanNumerals == "" || romanNumerals == null)) + return string.Format(LocaleBuilder.getResourceString("LOC_ID_LINEAGE_OBJ_12_NEW_SINGULAR_ZH"), playerName, "").Trim(); + else + return string.Format(LocaleBuilder.getResourceString("LOC_ID_LINEAGE_OBJ_12_NEW"), playerName, romanNumerals).Trim(); + } + } + + public static string NameHelper() + { + return NameHelper(Game.PlayerStats.PlayerName, Game.PlayerStats.RomanNumeral, Game.PlayerStats.IsFemale); + } + + public static bool gameIsCorrupt; + public void SaveOnExit() + { + if (gameIsCorrupt == false) + { + // Quick hack to fix bug where save file is deleted on closing during splash screen. + if (ScreenManager.CurrentScreen is CDGSplashScreen == false && ScreenManager.CurrentScreen is DemoStartScreen == false) + { + ProceduralLevelScreen level = Game.ScreenManager.GetLevelScreen(); + //Special handling to revert your spell if you are in a carnival room. + if (level != null && (level.CurrentRoom is CarnivalShoot1BonusRoom || level.CurrentRoom is CarnivalShoot2BonusRoom)) + { + if (level.CurrentRoom is CarnivalShoot1BonusRoom) + (level.CurrentRoom as CarnivalShoot1BonusRoom).UnequipPlayer(); + if (level.CurrentRoom is CarnivalShoot2BonusRoom) + (level.CurrentRoom as CarnivalShoot2BonusRoom).UnequipPlayer(); + } + + // A check to make sure challenge rooms do not override player save data. + if (level != null) + { + ChallengeBossRoomObj challengeRoom = level.CurrentRoom as ChallengeBossRoomObj; + if (challengeRoom != null) + { + challengeRoom.LoadPlayerData(); // Make sure this is loaded before upgrade data, otherwise player equipment will be overridden. + SaveManager.LoadFiles(level, SaveType.UpgradeData); + level.Player.CurrentHealth = challengeRoom.StoredHP; + level.Player.CurrentMana = challengeRoom.StoredMP; + } + } + + // Special check in case the user closes the program while in the game over screen to reset the traits. + if (ScreenManager.CurrentScreen is GameOverScreen) + Game.PlayerStats.Traits = Vector2.Zero; + + if (SaveManager.FileExists(SaveType.PlayerData)) + { + SaveManager.SaveFiles(SaveType.PlayerData, SaveType.UpgradeData); + + // This code is needed otherwise the lineage data will still be on Revision 0 when the game exits, but player data is Rev1 + // which results in a mismatch. + if (Game.PlayerStats.RevisionNumber <= 0) + SaveManager.SaveFiles(SaveType.Lineage); + + // IMPORTANT!! Only save map data if you are actually in the castle. Not at the title screen, starting room, or anywhere else. Also make sure not to save during the intro scene. + if (Game.PlayerStats.TutorialComplete == true && level != null && level.CurrentRoom.Name != "Start" && level.CurrentRoom.Name != "Ending" && level.CurrentRoom.Name != "Tutorial") + SaveManager.SaveFiles(SaveType.MapData); + } + } + } + } + + //protected override void OnExiting(object sender, EventArgs args) + //{ + // // Quick hack to fix bug where save file is deleted on closing during splash screen. + // if (ScreenManager.CurrentScreen is CDGSplashScreen == false && ScreenManager.CurrentScreen is DemoStartScreen == false) + // { + // UpdatePlaySessionLength(); + + // ProceduralLevelScreen level = Game.ScreenManager.GetLevelScreen(); + // //Special handling to revert your spell if you are in a carnival room. + // if (level != null && (level.CurrentRoom is CarnivalShoot1BonusRoom || level.CurrentRoom is CarnivalShoot2BonusRoom)) + // { + // if (level.CurrentRoom is CarnivalShoot1BonusRoom) + // (level.CurrentRoom as CarnivalShoot1BonusRoom).UnequipPlayer(); + // if (level.CurrentRoom is CarnivalShoot2BonusRoom) + // (level.CurrentRoom as CarnivalShoot2BonusRoom).UnequipPlayer(); + // } + + // // Special check in case the user closes the program while in the game over screen to reset the traits. + // if (ScreenManager.CurrentScreen is GameOverScreen) + // Game.PlayerStats.Traits = Vector2.Zero; + + // if (SaveManager.FileExists(SaveType.PlayerData)) + // { + // SaveManager.SaveFiles(SaveType.PlayerData, SaveType.UpgradeData); + + // // IMPORTANT!! Only save map data if you are actually in the castle. Not at the title screen, starting room, or anywhere else. Also make sure not to save during the intro scene. + // if (Game.PlayerStats.TutorialComplete == true && level != null && level.CurrentRoom.Name != "Start" && level.CurrentRoom.Name != "Ending" && level.CurrentRoom.Name != "Tutorial") + // SaveManager.SaveFiles(SaveType.MapData); + // } + // } + + // SWManager.instance().shutdown(); + // base.OnExiting(sender, args); + //} + + public PhysicsManager PhysicsManager + { + get { return m_physicsManager; } + } + + public ContentManager ContentManager + { + get { return Content; } + } + + public SaveGameManager SaveManager + { + get { return m_saveGameManager; } + } + + public List GetSupportedResolutions() + { + List list = new List(); + foreach (DisplayMode mode in GraphicsDevice.Adapter.SupportedDisplayModes) + { + //if (mode.AspectRatio > 1.7f) + if (mode.Width < 2000 && mode.Height < 2000) // Restricts the resolution to below 2048 (which is max supported texture size). + { + Vector2 res = new Vector2(mode.Width, mode.Height); + if (list.Contains(res) == false) + list.Add(new Vector2(mode.Width, mode.Height)); + } + } + + //list.Sort(delegate(Vector2 obj1, Vector2 obj2) { return obj1.X.CompareTo(obj2.X); }); // Why did I do this? It just screwed up the ordering. + + return list; + } + + public void SaveConfig() + { + Console.WriteLine("Saving Config file"); + + if (!Directory.Exists(Program.OSDir)) + Directory.CreateDirectory(Program.OSDir); + string configFilePath = Path.Combine(Program.OSDir, "GameConfig.ini"); + + using (StreamWriter writer = new StreamWriter(configFilePath, false)) + { + writer.WriteLine("[Screen Resolution]"); + writer.WriteLine("ScreenWidth=" + Game.GameConfig.ScreenWidth); + writer.WriteLine("ScreenHeight=" + Game.GameConfig.ScreenHeight); + writer.WriteLine(); + writer.WriteLine("[Fullscreen]"); + writer.WriteLine("Fullscreen=" + Game.GameConfig.FullScreen); + writer.WriteLine(); + writer.WriteLine("[QuickDrop]"); + writer.WriteLine("QuickDrop=" + Game.GameConfig.QuickDrop); + writer.WriteLine(); + writer.WriteLine("[Game Volume]"); + writer.WriteLine("MusicVol=" + String.Format("{0:F2}", Game.GameConfig.MusicVolume)); + writer.WriteLine("SFXVol=" + String.Format("{0:F2}", Game.GameConfig.SFXVolume)); + writer.WriteLine(); + writer.WriteLine("[Joystick Dead Zone]"); + writer.WriteLine("DeadZone=" + InputManager.Deadzone); + writer.WriteLine(); + writer.WriteLine("[Enable DirectInput Gamepads]"); + writer.WriteLine("EnableDirectInput=" + Game.GameConfig.EnableDirectInput); + writer.WriteLine(); + writer.WriteLine("[Reduce Shader Quality]"); + writer.WriteLine("ReduceQuality=" + Game.GameConfig.ReduceQuality); + writer.WriteLine(); + //writer.WriteLine("[Enable Steam Cloud]"); + //writer.WriteLine("EnableSteamCloud=" + Game.GameConfig.EnableSteamCloud); + //writer.WriteLine(); + writer.WriteLine("[Profile]"); + writer.WriteLine("Slot=" + Game.GameConfig.ProfileSlot); + writer.WriteLine(); + writer.WriteLine("[Keyboard Config]"); + writer.WriteLine("KeyUP=" + Game.GlobalInput.KeyList[InputMapType.PLAYER_UP1]); + writer.WriteLine("KeyDOWN=" + Game.GlobalInput.KeyList[InputMapType.PLAYER_DOWN1]); + writer.WriteLine("KeyLEFT=" + Game.GlobalInput.KeyList[InputMapType.PLAYER_LEFT1]); + writer.WriteLine("KeyRIGHT=" + Game.GlobalInput.KeyList[InputMapType.PLAYER_RIGHT1]); + writer.WriteLine("KeyATTACK=" + Game.GlobalInput.KeyList[InputMapType.PLAYER_ATTACK]); + writer.WriteLine("KeyJUMP=" + Game.GlobalInput.KeyList[InputMapType.PLAYER_JUMP1]); + writer.WriteLine("KeySPECIAL=" + Game.GlobalInput.KeyList[InputMapType.PLAYER_BLOCK]); + writer.WriteLine("KeyDASHLEFT=" + Game.GlobalInput.KeyList[InputMapType.PLAYER_DASHLEFT]); + writer.WriteLine("KeyDASHRIGHT=" + Game.GlobalInput.KeyList[InputMapType.PLAYER_DASHRIGHT]); + writer.WriteLine("KeySPELL1=" + Game.GlobalInput.KeyList[InputMapType.PLAYER_SPELL1]); + writer.WriteLine(); + writer.WriteLine("[Gamepad Config]"); + writer.WriteLine("ButtonUP=" + Game.GlobalInput.ButtonList[InputMapType.PLAYER_UP1]); + writer.WriteLine("ButtonDOWN=" + Game.GlobalInput.ButtonList[InputMapType.PLAYER_DOWN1]); + writer.WriteLine("ButtonLEFT=" + Game.GlobalInput.ButtonList[InputMapType.PLAYER_LEFT1]); + writer.WriteLine("ButtonRIGHT=" + Game.GlobalInput.ButtonList[InputMapType.PLAYER_RIGHT1]); + writer.WriteLine("ButtonATTACK=" + Game.GlobalInput.ButtonList[InputMapType.PLAYER_ATTACK]); + writer.WriteLine("ButtonJUMP=" + Game.GlobalInput.ButtonList[InputMapType.PLAYER_JUMP1]); + writer.WriteLine("ButtonSPECIAL=" + Game.GlobalInput.ButtonList[InputMapType.PLAYER_BLOCK]); + writer.WriteLine("ButtonDASHLEFT=" + Game.GlobalInput.ButtonList[InputMapType.PLAYER_DASHLEFT]); + writer.WriteLine("ButtonDASHRIGHT=" + Game.GlobalInput.ButtonList[InputMapType.PLAYER_DASHRIGHT]); + writer.WriteLine("ButtonSPELL1=" + Game.GlobalInput.ButtonList[InputMapType.PLAYER_SPELL1]); + writer.WriteLine(); + writer.WriteLine("[Language]"); + writer.WriteLine("Language=" + LocaleBuilder.languageType); + writer.WriteLine(); + if (Game.GameConfig.UnlockTraitor > 0) + writer.WriteLine("UnlockTraitor=" + Game.GameConfig.UnlockTraitor); + + writer.Close(); + } + } + + public void LoadConfig() + { + Console.WriteLine("Loading Config file"); + InitializeDefaultConfig(); // Initialize a default config first in case new config data is added in the future. + try + { + string configFilePath = Path.Combine(Program.OSDir, "GameConfig.ini"); + + using (StreamReader reader = new StreamReader(configFilePath)) + { + // flibit didn't like this + // CultureInfo ci = (CultureInfo)CultureInfo.CurrentCulture.Clone(); + // ci.NumberFormat.CurrencyDecimalSeparator = "."; + CultureInfo ci = CultureInfo.InvariantCulture; + + string line = null; + while ((line = reader.ReadLine()) != null) + { + int titleIndex = line.IndexOf("="); + + if (titleIndex != -1) + { + string lineTitle = line.Substring(0, titleIndex); + string lineValue = line.Substring(titleIndex + 1); + + switch (lineTitle) + { + case ("ScreenWidth"): + Game.GameConfig.ScreenWidth = int.Parse(lineValue, NumberStyles.Any, ci); + break; + case ("ScreenHeight"): + Game.GameConfig.ScreenHeight = int.Parse(lineValue, NumberStyles.Any, ci); + break; + case ("Fullscreen"): + Game.GameConfig.FullScreen = bool.Parse(lineValue); + break; + case("QuickDrop"): + Game.GameConfig.QuickDrop = bool.Parse(lineValue); + break; + case ("MusicVol"): + Game.GameConfig.MusicVolume = Single.Parse(lineValue); + break; + case ("SFXVol"): + Game.GameConfig.SFXVolume = Single.Parse(lineValue); + break; + case ("DeadZone"): + InputManager.Deadzone = int.Parse(lineValue, NumberStyles.Any, ci); + break; + case ("EnableDirectInput"): + Game.GameConfig.EnableDirectInput = bool.Parse(lineValue); + break; + case ("ReduceQuality"): + Game.GameConfig.ReduceQuality = bool.Parse(lineValue); + LevelEV.SAVE_FRAMES = Game.GameConfig.ReduceQuality; + break; + case ("EnableSteamCloud"): + Game.GameConfig.EnableSteamCloud = bool.Parse(lineValue); + break; + case ("Slot"): + Game.GameConfig.ProfileSlot = byte.Parse(lineValue, NumberStyles.Any, ci); + break; + case ("KeyUP"): + Game.GlobalInput.KeyList[InputMapType.PLAYER_UP1] = (Keys)Enum.Parse(typeof(Keys), lineValue); + break; + case ("KeyDOWN"): + Game.GlobalInput.KeyList[InputMapType.PLAYER_DOWN1] = (Keys)Enum.Parse(typeof(Keys), lineValue); + break; + case ("KeyLEFT"): + Game.GlobalInput.KeyList[InputMapType.PLAYER_LEFT1] = (Keys)Enum.Parse(typeof(Keys), lineValue); + break; + case ("KeyRIGHT"): + Game.GlobalInput.KeyList[InputMapType.PLAYER_RIGHT1] = (Keys)Enum.Parse(typeof(Keys), lineValue); + break; + case ("KeyATTACK"): + Game.GlobalInput.KeyList[InputMapType.PLAYER_ATTACK] = (Keys)Enum.Parse(typeof(Keys), lineValue); + break; + case ("KeyJUMP"): + Game.GlobalInput.KeyList[InputMapType.PLAYER_JUMP1] = (Keys)Enum.Parse(typeof(Keys), lineValue); + break; + case ("KeySPECIAL"): + Game.GlobalInput.KeyList[InputMapType.PLAYER_BLOCK] = (Keys)Enum.Parse(typeof(Keys), lineValue); + break; + case ("KeyDASHLEFT"): + Game.GlobalInput.KeyList[InputMapType.PLAYER_DASHLEFT] = (Keys)Enum.Parse(typeof(Keys), lineValue); + break; + case ("KeyDASHRIGHT"): + Game.GlobalInput.KeyList[InputMapType.PLAYER_DASHRIGHT] = (Keys)Enum.Parse(typeof(Keys), lineValue); + break; + case ("KeySPELL1"): + Game.GlobalInput.KeyList[InputMapType.PLAYER_SPELL1] = (Keys)Enum.Parse(typeof(Keys), lineValue); + break; + case ("ButtonUP"): + Game.GlobalInput.ButtonList[InputMapType.PLAYER_UP1] = (Buttons)Enum.Parse(typeof(Buttons), lineValue); + break; + case ("ButtonDOWN"): + Game.GlobalInput.ButtonList[InputMapType.PLAYER_DOWN1] = (Buttons)Enum.Parse(typeof(Buttons), lineValue); + break; + case ("ButtonLEFT"): + Game.GlobalInput.ButtonList[InputMapType.PLAYER_LEFT1] = (Buttons)Enum.Parse(typeof(Buttons), lineValue); + break; + case ("ButtonRIGHT"): + Game.GlobalInput.ButtonList[InputMapType.PLAYER_RIGHT1] = (Buttons)Enum.Parse(typeof(Buttons), lineValue); + break; + case ("ButtonATTACK"): + Game.GlobalInput.ButtonList[InputMapType.PLAYER_ATTACK] = (Buttons)Enum.Parse(typeof(Buttons), lineValue); + break; + case ("ButtonJUMP"): + Game.GlobalInput.ButtonList[InputMapType.PLAYER_JUMP1] = (Buttons)Enum.Parse(typeof(Buttons), lineValue); + break; + case ("ButtonSPECIAL"): + Game.GlobalInput.ButtonList[InputMapType.PLAYER_BLOCK] = (Buttons)Enum.Parse(typeof(Buttons), lineValue); + break; + case ("ButtonDASHLEFT"): + Game.GlobalInput.ButtonList[InputMapType.PLAYER_DASHLEFT] = (Buttons)Enum.Parse(typeof(Buttons), lineValue); + break; + case ("ButtonDASHRIGHT"): + Game.GlobalInput.ButtonList[InputMapType.PLAYER_DASHRIGHT] = (Buttons)Enum.Parse(typeof(Buttons), lineValue); + break; + case ("ButtonSPELL1"): + Game.GlobalInput.ButtonList[InputMapType.PLAYER_SPELL1] = (Buttons)Enum.Parse(typeof(Buttons), lineValue); + break; + case ("Language"): + LocaleBuilder.languageType = (LanguageType)Enum.Parse(typeof(LanguageType), lineValue); + break; + case("UnlockTraitor"): + Game.GameConfig.UnlockTraitor = byte.Parse(lineValue, NumberStyles.Any, ci); + break; + } + } + } + + // Special code so that player attack acts as the second confirm and player jump acts as the second cancel. + Game.GlobalInput.KeyList[InputMapType.MENU_CONFIRM2] = Game.GlobalInput.KeyList[InputMapType.PLAYER_ATTACK]; + Game.GlobalInput.KeyList[InputMapType.MENU_CANCEL2] = Game.GlobalInput.KeyList[InputMapType.PLAYER_JUMP1]; + + reader.Close(); + + // Game config file was not loaded properly. Throw an exception. + if (Game.GameConfig.ScreenHeight <= 0 || Game.GameConfig.ScreenWidth <= 0) + throw new Exception("Blank Config File"); + } + } + catch + { + //If exception occurred, then no file was found and default config must be created. + Console.WriteLine("Config File Not Found. Creating Default Config File."); + InitializeDefaultConfig(); + this.SaveConfig(); + } + } + + public void InitializeScreenConfig() + { + if (Environment.GetEnvironmentVariable("SteamTenfoot") == "1" || Environment.GetEnvironmentVariable("SteamDeck") == "1") + { + // We are asked to override resolution settings in Big Picture modes + DisplayMode mode = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode; + graphics.PreferredBackBufferWidth = mode.Width; + graphics.PreferredBackBufferHeight = mode.Height; + graphics.IsFullScreen = true; + graphics.ApplyChanges(); + } + else + { + graphics.PreferredBackBufferWidth = Game.GameConfig.ScreenWidth; + graphics.PreferredBackBufferHeight = Game.GameConfig.ScreenHeight; + if ((graphics.IsFullScreen == true && Game.GameConfig.FullScreen == false) || (graphics.IsFullScreen == false && Game.GameConfig.FullScreen == true)) + graphics.ToggleFullScreen(); + else + graphics.ApplyChanges(); + } + + // No need to call Graphics.ApplyChanges() since ToggleFullScreen() implicitly calls it. + Game.ScreenManager.ForceResolutionChangeCheck(); + } + + public static void ChangeBitmapLanguage(SpriteObj sprite, string spriteName) + { + switch (LocaleBuilder.languageType) + { + case (LanguageType.English): + sprite.ChangeSprite(spriteName); + break; + case (LanguageType.German): + sprite.ChangeSprite(spriteName + "_DE"); + break; + case (LanguageType.Russian): + sprite.ChangeSprite(spriteName + "_RU"); + break; + case (LanguageType.French): + sprite.ChangeSprite(spriteName + "_FR"); + break; + case (LanguageType.Polish): + sprite.ChangeSprite(spriteName + "_PO"); + break; + case (LanguageType.Portuguese_Brazil): + sprite.ChangeSprite(spriteName + "_BR"); + break; + case (LanguageType.Spanish_Spain): + sprite.ChangeSprite(spriteName + "_SP"); + break; + case (LanguageType.Chinese_Simp): + sprite.ChangeSprite(spriteName + "_ZH"); + break; + } + } + + public GraphicsDeviceManager GraphicsDeviceManager + { + get { return graphics; } + } + + public struct SettingStruct + { + public int ScreenWidth; + public int ScreenHeight; + public bool FullScreen; + public float MusicVolume; + public float SFXVolume; + public bool QuickDrop; + public bool EnableDirectInput; + public byte ProfileSlot; + public bool ReduceQuality; + public bool EnableSteamCloud; + public byte UnlockTraitor; + } + } +} diff --git a/RogueCastle/src/GameUtil.cs b/RogueCastle/src/GameUtil.cs new file mode 100644 index 0000000..6f496a0 --- /dev/null +++ b/RogueCastle/src/GameUtil.cs @@ -0,0 +1,18 @@ +using System; +using SteamWorksWrapper; + +namespace RogueCastle +{ + public static class GameUtil + { + public static void UnlockAchievement(string achievementName) + { + Steamworks.UnlockAchievement(achievementName); + } + + public static bool IsAchievementUnlocked(string achievementName) + { + return Steamworks.IsAchievementUnlocked(achievementName); + } + } +} diff --git a/RogueCastle/src/GaussianBlur.cs b/RogueCastle/src/GaussianBlur.cs new file mode 100644 index 0000000..63dc1f0 --- /dev/null +++ b/RogueCastle/src/GaussianBlur.cs @@ -0,0 +1,310 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2008-2011 dhpoware. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using DS2DEngine; + +namespace RogueCastle +{ + /// + /// The RADIUS constant in the effect file must match the radius value in + /// the GaussianBlur class. The effect file's weights global variable + /// corresponds to the GaussianBlur class' kernel field. The effect file's + /// offsets global variable corresponds to the GaussianBlur class' + /// offsetsHoriz and offsetsVert fields. + /// + /// + public class GaussianBlur + { + private Effect effect; + private int radius; + private float amount; + private float sigma; + private float[] kernel; + private Vector2[] offsetsHoriz; + private Vector2[] offsetsVert; + + private RenderTarget2D m_renderHolder, m_renderHolder2; + + private bool m_invertMask; + private EffectParameter m_offsetParameters; + + /// + /// Returns the radius of the Gaussian blur filter kernel in pixels. + /// + public int Radius + { + get { return radius; } + set + { + radius = value; + ComputeKernel(); + } + } + + /// + /// Returns the blur amount. This value is used to calculate the + /// Gaussian blur filter kernel's sigma value. Good values for this + /// property are 2 and 3. 2 will give a more blurred result whilst 3 + /// will give a less blurred result with sharper details. + /// + public float Amount + { + get { return amount; } + set + { + amount = value; + ComputeKernel(); + } + } + + /// + /// Returns the Gaussian blur filter's standard deviation. + /// + public float Sigma + { + get { return sigma; } + } + + /// + /// Returns the Gaussian blur filter kernel matrix. Note that the + /// kernel returned is for a 1D Gaussian blur filter kernel matrix + /// intended to be used in a two pass Gaussian blur operation. + /// + public float[] Kernel + { + get { return kernel; } + } + + /// + /// Returns the texture offsets used for the horizontal Gaussian blur + /// pass. + /// + public Vector2[] TextureOffsetsX + { + get { return offsetsHoriz; } + } + + /// + /// Returns the texture offsets used for the vertical Gaussian blur + /// pass. + /// + public Vector2[] TextureOffsetsY + { + get { return offsetsVert; } + } + + public bool InvertMask + { + get { return m_invertMask; } + set + { + m_invertMask = value; + effect.Parameters["invert"].SetValue(m_invertMask); + } + } + + /// + /// Default constructor for the GaussianBlur class. This constructor + /// should be called if you don't want the GaussianBlur class to use + /// its GaussianBlur.fx effect file to perform the two pass Gaussian + /// blur operation. + /// + public GaussianBlur() + { + } + + /// + /// This overloaded constructor instructs the GaussianBlur class to + /// load and use its GaussianBlur.fx effect file that implements the + /// two pass Gaussian blur operation on the GPU. The effect file must + /// be already bound to the asset name: 'Effects\GaussianBlur' or + /// 'GaussianBlur'. + /// + /// + public GaussianBlur(Game game, int screenWidth, int screenHeight) + { + if (m_renderHolder != null && m_renderHolder.IsDisposed == false) + m_renderHolder.Dispose(); + if (m_renderHolder2 != null && m_renderHolder2.IsDisposed == false) + m_renderHolder2.Dispose(); + + if (LevelEV.SAVE_FRAMES == true) + { + m_renderHolder = new RenderTarget2D(game.GraphicsDevice, screenWidth / 2, screenHeight / 2, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + m_renderHolder2 = new RenderTarget2D(game.GraphicsDevice, screenWidth / 2, screenHeight / 2, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + } + else + { + m_renderHolder = new RenderTarget2D(game.GraphicsDevice, screenWidth, screenHeight, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + m_renderHolder2 = new RenderTarget2D(game.GraphicsDevice, screenWidth, screenHeight, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + } + + effect = game.Content.Load(@"Shaders\GaussianBlurMask"); + m_offsetParameters = effect.Parameters["offsets"]; + } + + /// + /// Calculates the Gaussian blur filter kernel. This implementation is + /// ported from the original Java code appearing in chapter 16 of + /// "Filthy Rich Clients: Developing Animated and Graphical Effects for + /// Desktop Java". + /// + /// The blur radius in pixels. + /// Used to calculate sigma. + public void ComputeKernel() + { + kernel = null; + kernel = new float[radius * 2 + 1]; + sigma = radius / amount; + + // flibit added this to avoid sending NaN to the shader + if (radius == 0) + return; + + float twoSigmaSquare = 2.0f * sigma * sigma; + float sigmaRoot = (float)Math.Sqrt(twoSigmaSquare * Math.PI); + float total = 0.0f; + float distance = 0.0f; + int index = 0; + + for (int i = -radius; i <= radius; ++i) + { + distance = i * i; + index = i + radius; + kernel[index] = (float)Math.Exp(-distance / twoSigmaSquare) / sigmaRoot; + total += kernel[index]; + } + + for (int i = 0; i < kernel.Length; ++i) + kernel[i] /= total; + effect.Parameters["weights"].SetValue(kernel); + } + + /// + /// Calculates the texture coordinate offsets corresponding to the + /// calculated Gaussian blur filter kernel. Each of these offset values + /// are added to the current pixel's texture coordinates in order to + /// obtain the neighboring texture coordinates that are affected by the + /// Gaussian blur filter kernel. This implementation has been adapted + /// from chapter 17 of "Filthy Rich Clients: Developing Animated and + /// Graphical Effects for Desktop Java". + /// + /// The texture width in pixels. + /// The texture height in pixels. + public void ComputeOffsets() + { + offsetsHoriz = null; + offsetsHoriz = new Vector2[radius * 2 + 1]; + + offsetsVert = null; + offsetsVert = new Vector2[radius * 2 + 1]; + + int index = 0; + float xOffset = 1.0f / m_renderHolder.Width; + float yOffset = 1.0f / m_renderHolder.Height; + + for (int i = -radius; i <= radius; ++i) + { + index = i + radius; + offsetsHoriz[index] = new Vector2(i * xOffset, 0.0f); + offsetsVert[index] = new Vector2(0.0f, i * yOffset); + } + } + + /// + /// Performs the Gaussian blur operation on the source texture image. + /// The Gaussian blur is performed in two passes: a horizontal blur + /// pass followed by a vertical blur pass. The output from the first + /// pass is rendered to renderTarget1. The output from the second pass + /// is rendered to renderTarget2. The dimensions of the blurred texture + /// is therefore equal to the dimensions of renderTarget2. + /// + /// The source image to blur. + /// Stores the output from the horizontal blur pass. + /// Stores the output from the vertical blur pass. + /// Used to draw quads for the blur passes. + /// The resulting Gaussian blurred image. + public void Draw(RenderTarget2D srcTexture, Camera2D Camera, RenderTarget2D mask = null) + { + if (effect == null) + throw new InvalidOperationException("GaussianBlur.fx effect not loaded."); + + // Perform horizontal Gaussian blur. + + Camera.GraphicsDevice.SetRenderTarget(m_renderHolder); + + //effect.Parameters["weights"].SetValue(kernel); + //effect.Parameters["offsets"].SetValue(offsetsVert); + m_offsetParameters.SetValue(offsetsHoriz); + + if (mask != null) + { + Camera.GraphicsDevice.Textures[1] = mask; + Camera.GraphicsDevice.SamplerStates[1] = SamplerState.LinearClamp; + } + Camera.Begin(0, BlendState.Opaque, SamplerState.LinearClamp, null, null, effect); + //Camera.Draw(srcTexture, Vector2.Zero, Color.White); + if (LevelEV.SAVE_FRAMES == true) + Camera.Draw(srcTexture, Vector2.Zero, null, Color.White, 0, Vector2.Zero, new Vector2(0.5f, 0.5f), SpriteEffects.None, 1); + else + Camera.Draw(srcTexture, Vector2.Zero, Color.White); + Camera.End(); + + + if (LevelEV.SAVE_FRAMES == true) + { + // Perform vertical Gaussian blur. + Camera.GraphicsDevice.SetRenderTarget(m_renderHolder2); + + m_offsetParameters.SetValue(offsetsVert); + + if (mask != null) + Camera.GraphicsDevice.Textures[1] = mask; + Camera.Begin(0, BlendState.Opaque, null, null, null, effect); + Camera.Draw(m_renderHolder, Vector2.Zero, Color.White); + Camera.End(); + + Camera.GraphicsDevice.SetRenderTarget(srcTexture); + Camera.Begin(0, BlendState.Opaque, SamplerState.PointClamp, null, null); + Camera.Draw(m_renderHolder2, Vector2.Zero, null, Color.White, 0, Vector2.Zero, new Vector2(2, 2), SpriteEffects.None, 1); + Camera.End(); + } + else + { + // Perform vertical Gaussian blur. + Camera.GraphicsDevice.SetRenderTarget(srcTexture); + + m_offsetParameters.SetValue(offsetsVert); + + if (mask != null) + Camera.GraphicsDevice.Textures[1] = mask; + Camera.Begin(0, BlendState.Opaque, null, null, null, effect); + Camera.Draw(m_renderHolder, Vector2.Zero, Color.White); + Camera.End(); + } + } + } +} diff --git a/RogueCastle/src/ImpactEffectPool.cs b/RogueCastle/src/ImpactEffectPool.cs new file mode 100644 index 0000000..ed31998 --- /dev/null +++ b/RogueCastle/src/ImpactEffectPool.cs @@ -0,0 +1,1138 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; + +namespace RogueCastle +{ + public class ImpactEffectPool : IDisposableObj + { + private int m_poolSize = 0; + private DS2DPool m_resourcePool; + private bool m_isPaused; + + public bool IsDisposed { get { return m_isDisposed; } } + private bool m_isDisposed = false; + + public ImpactEffectPool(int poolSize) + { + m_poolSize = poolSize; + m_resourcePool = new DS2DPool(); + } + + public void Initialize() + { + for (int i = 0; i < m_poolSize; i++) + { + SpriteObj poolObj = new SpriteObj("Blank_Sprite"); + poolObj.AnimationDelay = 1 / 30f; + poolObj.Visible = false; + poolObj.TextureColor = Color.White; + m_resourcePool.AddToPool(poolObj); + } + } + + public SpriteObj DisplayEffect(Vector2 position, string spriteName) + { + SpriteObj effect = m_resourcePool.CheckOut(); + effect.ChangeSprite(spriteName); + effect.TextureColor = Color.White; + effect.Visible = true; + effect.Position = position; + effect.PlayAnimation(false); + return effect; + } + + public void DisplayEnemyImpactEffect(Vector2 position) + { + SpriteObj impactEffect = m_resourcePool.CheckOut(); + impactEffect.ChangeSprite("ImpactEnemy_Sprite"); + impactEffect.TextureColor = Color.White; + impactEffect.Rotation = CDGMath.RandomInt(0, 360); + impactEffect.Visible = true; + impactEffect.Position = position; + impactEffect.PlayAnimation(false); + } + + public void DisplayPlayerImpactEffect(Vector2 position) + { + SpriteObj impactEffect = m_resourcePool.CheckOut(); + impactEffect.ChangeSprite("ImpactEnemy_Sprite"); + impactEffect.TextureColor = Color.Orange; + impactEffect.Rotation = CDGMath.RandomInt(0, 360); + impactEffect.Visible = true; + impactEffect.Position = position; + impactEffect.PlayAnimation(false); + } + + public void DisplayBlockImpactEffect(Vector2 position, Vector2 scale) + { + SpriteObj impactEffect = m_resourcePool.CheckOut(); + impactEffect.ChangeSprite("ImpactBlock_Sprite"); + impactEffect.TextureColor = Color.White; + impactEffect.Rotation = CDGMath.RandomInt(0, 360); + impactEffect.Visible = true; + impactEffect.Position = position; + impactEffect.PlayAnimation(false); + impactEffect.Scale = scale; + + } + + public void DisplayDeathEffect(Vector2 position) + { + for (int i = 0; i < 10; i++) + { + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("ExplosionBlue_Sprite"); + smoke.Visible = true; + smoke.Position = position; + float randomScale = CDGMath.RandomFloat(0.7f, 0.8f); + int movementAmount = 50; + smoke.Scale = new Vector2(randomScale, randomScale); + smoke.Rotation = CDGMath.RandomInt(0, 90); + smoke.PlayAnimation(true); + + float duration = CDGMath.RandomFloat(0.5f, 1.0f); + float randScaleShrink = CDGMath.RandomFloat(0, 0.1f); + Tween.To(smoke, duration - 0.2f, Linear.EaseNone, "delay", "0.2", "Opacity", "0"); + Tween.To(smoke, duration, Back.EaseIn, "ScaleX", randScaleShrink.ToString(), "ScaleY", randScaleShrink.ToString()); + Tween.By(smoke, duration, Quad.EaseOut, "X", CDGMath.RandomInt(-movementAmount, movementAmount).ToString(), "Y", CDGMath.RandomInt(-movementAmount, movementAmount).ToString()); + Tween.AddEndHandlerToLastTween(smoke, "StopAnimation"); + Tween.By(smoke, duration - 0.1f, Tweener.Ease.Quad.EaseOut, "Rotation", CDGMath.RandomInt(145, 190).ToString()); + } + } + + + public void DisplaySpawnEffect(Vector2 position) + { + for (int i = 0; i < 10; i++) + { + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("ExplosionOrange_Sprite"); + smoke.Visible = true; + smoke.Position = position; + float randomScale = CDGMath.RandomFloat(0.7f, 0.8f); + int movementAmount = 50; + smoke.Scale = new Vector2(randomScale, randomScale); + smoke.Rotation = CDGMath.RandomInt(0, 90); + smoke.PlayAnimation(true); + + float duration = CDGMath.RandomFloat(0.5f, 1.0f); + float randScaleShrink = CDGMath.RandomFloat(0, 0.1f); + Tween.To(smoke, duration - 0.2f, Linear.EaseNone, "delay", "0.2", "Opacity", "0"); + Tween.To(smoke, duration, Back.EaseIn, "ScaleX", randScaleShrink.ToString(), "ScaleY", randScaleShrink.ToString()); + Tween.By(smoke, duration, Quad.EaseOut, "X", CDGMath.RandomInt(-movementAmount, movementAmount).ToString(), "Y", CDGMath.RandomInt(-movementAmount, movementAmount).ToString()); + Tween.AddEndHandlerToLastTween(smoke, "StopAnimation"); + Tween.By(smoke, duration - 0.1f, Tweener.Ease.Quad.EaseOut, "Rotation", CDGMath.RandomInt(145, 190).ToString()); + } + } + + public void DisplayChestSparkleEffect(Vector2 position) + { + SpriteObj particle = m_resourcePool.CheckOut(); + particle.ChangeSprite("LevelUpParticleFX_Sprite"); + particle.Visible = true; + float randomScale = CDGMath.RandomFloat(0.2f, 0.5f); + particle.Scale = new Vector2(randomScale, randomScale); + particle.Opacity = 0; + particle.Position = position; + particle.Rotation = CDGMath.RandomInt(0, 90); + particle.PlayAnimation(false); + particle.Position += new Vector2(CDGMath.RandomInt(-40, 40), CDGMath.RandomInt(-40, 40)); + Tween.To(particle, 0.2f, Linear.EaseNone, "Opacity", "1"); + Tween.AddEndHandlerToLastTween(particle, "StopAnimation"); + } + + public void DisplayDoubleJumpEffect(Vector2 position) + { + SpriteObj doubleJumpFX = m_resourcePool.CheckOut(); + doubleJumpFX.ChangeSprite("DoubleJumpFX_Sprite"); + doubleJumpFX.Visible = true; + doubleJumpFX.Position = position; + //doubleJumpFX.Opacity = 0.6f; + doubleJumpFX.PlayAnimation(false); + } + + public void DisplayDashEffect(Vector2 position, bool flip) + { + SpriteObj dashFX = m_resourcePool.CheckOut(); + dashFX.ChangeSprite("DashFX_Sprite"); + if (flip == true) + dashFX.Flip = SpriteEffects.FlipHorizontally; + dashFX.Position = position; + dashFX.Visible = true; + dashFX.PlayAnimation(false); + } + + public void DisplayTeleportEffect(Vector2 position) + { + // Animation for the floating rocks. + float delay = 0.1f; + for (int i = 0; i < 5; i++) + { + SpriteObj rock = m_resourcePool.CheckOut(); + rock.Visible = true; + rock.ChangeSprite("TeleportRock" + (i + 1) + "_Sprite"); + rock.PlayAnimation(true); + rock.Position = new Vector2(CDGMath.RandomFloat(position.X - 70, position.X + 70), position.Y + CDGMath.RandomInt(-50, -30)); + rock.Opacity = 0; + float duration = 1f; + + Tween.To(rock, 0.5f, Linear.EaseNone, "delay", delay.ToString(), "Opacity", "1"); + Tween.By(rock, duration, Linear.EaseNone, "delay", delay.ToString(), "Y", "-150"); + rock.Opacity = 1; + Tween.To(rock, 0.5f, Linear.EaseNone, "delay", (duration + delay - 0.5f).ToString(), "Opacity", "0"); + Tween.AddEndHandlerToLastTween(rock, "StopAnimation"); + rock.Opacity = 0; + delay += CDGMath.RandomFloat(0.1f, 0.3f); + } + + // Animation for the actual beam. + SpriteObj teleportBeam = m_resourcePool.CheckOut(); + teleportBeam.AnimationDelay = 1/20f; + teleportBeam.Opacity = 0.8f; + teleportBeam.Visible = true; + teleportBeam.ChangeSprite("TeleporterBeam_Sprite"); + teleportBeam.Position = position; + teleportBeam.ScaleY = 0; + teleportBeam.PlayAnimation(true); + Tween.To(teleportBeam, 0.05f, Linear.EaseNone, "ScaleY", "1"); + Tween.To(teleportBeam, 2, Linear.EaseNone); + Tween.AddEndHandlerToLastTween(teleportBeam, "StopAnimation"); + } + + // Needed so that the thrust dust always appears where the object is currently standing. + public void DisplayThrustDustEffect(GameObj obj, int numClouds, float duration) + { + float cloudDelay = duration / numClouds; + float initialDelay = 0; + + for (int i = 0; i < numClouds; i++) + { + Tween.RunFunction(initialDelay, this, "DisplayDustEffect", obj); + Tween.RunFunction(initialDelay, this, "DisplayDustEffect", obj); + initialDelay += cloudDelay; + } + } + + // Displays the actual smoke. + public void DisplayDustEffect(GameObj obj) + { + int randX = CDGMath.RandomInt(-30, 30); + int randY = CDGMath.RandomInt(-30, 30); + SpriteObj cloud1 = m_resourcePool.CheckOut(); + cloud1.ChangeSprite("ExplosionBrown_Sprite"); + cloud1.Opacity = 0; + cloud1.Visible = true; + cloud1.Rotation = CDGMath.RandomInt(0, 270); + cloud1.Position = new Vector2(obj.X, obj.Bounds.Bottom); + cloud1.Scale = new Vector2(0.8f, 0.8f); + cloud1.PlayAnimation(true); + Tween.To(cloud1, 0.2f, Linear.EaseNone, "Opacity", "1"); + Tween.By(cloud1, 0.7f, Linear.EaseNone, "Rotation", "180"); + Tween.By(cloud1, 0.7f, Quad.EaseOut, "X", randX.ToString(), "Y", randY.ToString()); + Tween.AddEndHandlerToLastTween(cloud1, "StopAnimation"); + cloud1.Opacity = 1; + Tween.To(cloud1, 0.5f, Linear.EaseNone, "delay", "0.2", "Opacity", "0"); + cloud1.Opacity = 0; + } + + public void DisplayDustEffect(Vector2 pos) + { + int randX = CDGMath.RandomInt(-30, 30); + int randY = CDGMath.RandomInt(-30, 30); + SpriteObj cloud1 = m_resourcePool.CheckOut(); + cloud1.ChangeSprite("ExplosionBrown_Sprite"); + cloud1.Opacity = 0; + cloud1.Visible = true; + cloud1.Rotation = CDGMath.RandomInt(0, 270); + cloud1.Position = pos; + cloud1.Scale = new Vector2(0.8f, 0.8f); + cloud1.PlayAnimation(true); + Tween.To(cloud1, 0.2f, Linear.EaseNone, "Opacity", "1"); + Tween.By(cloud1, 0.7f, Linear.EaseNone, "Rotation", "180"); + Tween.By(cloud1, 0.7f, Quad.EaseOut, "X", randX.ToString(), "Y", randY.ToString()); + Tween.AddEndHandlerToLastTween(cloud1, "StopAnimation"); + cloud1.Opacity = 1; + Tween.To(cloud1, 0.5f, Linear.EaseNone, "delay", "0.2", "Opacity", "0"); + cloud1.Opacity = 0; + } + + public void TurretFireEffect(Vector2 pos, Vector2 scale) + { + int randX = CDGMath.RandomInt(-20, 20); + int randY = CDGMath.RandomInt(-20, 20); + SpriteObj cloud1 = m_resourcePool.CheckOut(); + cloud1.ChangeSprite("ExplosionBrown_Sprite"); + cloud1.Opacity = 0; + cloud1.Visible = true; + cloud1.Rotation = CDGMath.RandomInt(0, 270); + cloud1.Position = pos; + cloud1.Scale = scale; + cloud1.PlayAnimation(true); + Tween.To(cloud1, 0.2f, Linear.EaseNone, "Opacity", "1"); + Tween.By(cloud1, 0.7f, Linear.EaseNone, "Rotation", CDGMath.RandomInt(-50,50).ToString()); + Tween.By(cloud1, 0.7f, Quad.EaseOut, "X", randX.ToString(), "Y", randY.ToString()); + Tween.AddEndHandlerToLastTween(cloud1, "StopAnimation"); + cloud1.Opacity = 1; + Tween.To(cloud1, 0.4f, Linear.EaseNone, "delay", "0.2", "Opacity", "0"); + cloud1.Opacity = 0; + } + + public void DisplayFartEffect(GameObj obj) + { + int randX = CDGMath.RandomInt(-10, 10); + if (obj.Flip == SpriteEffects.FlipHorizontally) + randX = 20; + else + randX = -20; + int randY = CDGMath.RandomInt(-10, 10); + randY = 0; + SpriteObj cloud1 = m_resourcePool.CheckOut(); + cloud1.ChangeSprite("ExplosionBrown_Sprite"); + cloud1.Opacity = 0; + cloud1.Visible = true; + cloud1.Rotation = CDGMath.RandomInt(0, 270); + cloud1.Position = new Vector2(obj.X, obj.Bounds.Bottom); + if (obj.Flip == SpriteEffects.FlipHorizontally) + cloud1.X += 30; + else + cloud1.X -= 30; + cloud1.Scale = new Vector2(0.8f, 0.8f); + cloud1.PlayAnimation(true); + Tween.To(cloud1, 0.2f, Linear.EaseNone, "Opacity", "1"); + Tween.By(cloud1, 0.7f, Linear.EaseNone, "Rotation", "180"); + Tween.By(cloud1, 0.7f, Quad.EaseOut, "X", randX.ToString(), "Y", randY.ToString()); + Tween.AddEndHandlerToLastTween(cloud1, "StopAnimation"); + cloud1.Opacity = 1; + Tween.To(cloud1, 0.5f, Linear.EaseNone, "delay", "0.2", "Opacity", "0"); + cloud1.Opacity = 0; + } + + // Displays the actual smoke. + public void DisplayExplosionEffect(Vector2 position) + { + SpriteObj deathFX1 = m_resourcePool.CheckOut(); + deathFX1.ChangeSprite("EnemyDeathFX1_Sprite"); + deathFX1.Visible = true; + deathFX1.Position = position; + deathFX1.PlayAnimation(false); + deathFX1.AnimationDelay = 1 / 30f; + //deathFX1.Scale = new Vector2(1.5f, 1.5f); + deathFX1.Scale = new Vector2(2f, 2f); + } + + public void StartInverseEmit(Vector2 pos) + { + float duration = 0.4f; + int numPixels = 30; + float delay = (float)(duration / numPixels); + float delayCounter = 0; + + for (int i = 0; i < numPixels; i++) + { + SpriteObj pixel = m_resourcePool.CheckOut(); + pixel.ChangeSprite("Blank_Sprite"); + pixel.TextureColor = Color.Black; + pixel.Visible = true; + pixel.PlayAnimation(true); + pixel.Scale = Vector2.Zero; + + pixel.X = pos.X + CDGMath.RandomInt(-100, 100); + pixel.Y = pos.Y + CDGMath.RandomInt(-100, 100); + Tween.To(pixel, delayCounter, Linear.EaseNone, "ScaleX", "2", "ScaleY", "2"); + Tween.To(pixel, duration - delayCounter, Quad.EaseInOut, "delay", delayCounter.ToString(), "X", pos.X.ToString(), "Y", pos.Y.ToString()); + Tween.AddEndHandlerToLastTween(pixel, "StopAnimation"); + delayCounter += delay; + } + } + + public void StartTranslocateEmit(Vector2 pos) + { + int numPixels = 30; + + for (int i = 0; i < numPixels; i++) + { + SpriteObj pixel = m_resourcePool.CheckOut(); + pixel.ChangeSprite("Blank_Sprite"); + pixel.TextureColor = Color.White; + pixel.Visible = true; + pixel.PlayAnimation(true); + pixel.Scale = new Vector2(2, 2); + pixel.Position = pos; + + Tween.To(pixel, 0.5f, Linear.EaseNone,"delay", "0.5", "ScaleX", "0", "ScaleY", "0"); + Tween.By(pixel, 1, Quad.EaseIn, "X", CDGMath.RandomInt(-250, 250).ToString()); + Tween.By(pixel, 1, Quad.EaseIn, "Y", CDGMath.RandomInt(500, 800).ToString()); + Tween.AddEndHandlerToLastTween(pixel, "StopAnimation"); + } + } + + public void BlackSmokeEffect(GameObj obj) + { + for (int i = 0; i < 2; i++) + { + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("BlackSmoke_Sprite"); + smoke.Visible = true; + smoke.Y = obj.Y; + smoke.Y += CDGMath.RandomInt(-40, 40); + smoke.X = obj.Bounds.Left; + + smoke.Opacity = 0; + smoke.PlayAnimation(true); + smoke.Rotation = CDGMath.RandomInt(-30, 30); + if (CDGMath.RandomPlusMinus() < 0) + smoke.Flip = SpriteEffects.FlipHorizontally; + if (CDGMath.RandomPlusMinus() < 0) + smoke.Flip = SpriteEffects.FlipVertically; + + int heading = -1; + if (obj.Flip == SpriteEffects.FlipHorizontally) + { + heading = 1; + smoke.X = obj.Bounds.Right; + } + + Tween.To(smoke, 0.4f, Tween.EaseNone, "Opacity", "1"); + Tween.By(smoke, 1.5f, Quad.EaseInOut, "X", (CDGMath.RandomInt(50, 100) * heading).ToString(), "Y", CDGMath.RandomInt(-100, 100).ToString(), "Rotation", CDGMath.RandomInt(-45, 45).ToString()); + //Tween.AddEndHandlerToLastTween(this, "DestroyEffect", smoke); + + smoke.Opacity = 1; + Tween.To(smoke, 1f, Tween.EaseNone, "delay", "0.5", "Opacity", "0"); + smoke.Opacity = 0; + Tween.RunFunction(2, smoke, "StopAnimation"); + } + } + + public void BlackSmokeEffect(Vector2 pos, Vector2 scale) + { + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("BlackSmoke_Sprite"); + smoke.Visible = true; + smoke.Y = pos.Y; + smoke.Y += CDGMath.RandomInt(-40, 40); + smoke.X = pos.X; + smoke.X += CDGMath.RandomInt(-40, 40); + smoke.Scale = scale; + + smoke.Opacity = 0; + smoke.PlayAnimation(true); + smoke.Rotation = CDGMath.RandomInt(-30, 30); + + Tween.To(smoke, 0.4f, Tween.EaseNone, "Opacity", "1"); + Tween.By(smoke, 1.5f, Quad.EaseInOut, "X", CDGMath.RandomInt(50, 100).ToString(), "Y", CDGMath.RandomInt(-100, 100).ToString(), "Rotation", CDGMath.RandomInt(-45, 45).ToString()); + //Tween.AddEndHandlerToLastTween(this, "DestroyEffect", smoke); + smoke.Opacity = 1; + Tween.To(smoke, 1f, Tween.EaseNone, "delay", "0.5", "Opacity", "0"); + smoke.Opacity = 0; + Tween.RunFunction(2, smoke, "StopAnimation"); + } + + public void CrowDestructionEffect(Vector2 pos) + { + for (int i = 0; i < 2; i++) + { + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("BlackSmoke_Sprite"); + smoke.Visible = true; + smoke.Position = pos; + smoke.Opacity = 0; + smoke.PlayAnimation(true); + smoke.Rotation = CDGMath.RandomInt(-30, 30); + Tween.To(smoke, 0.4f, Tween.EaseNone, "Opacity", "1"); + Tween.By(smoke, 1.5f, Quad.EaseInOut, "X", CDGMath.RandomInt(-50, 50).ToString(), "Y", CDGMath.RandomInt(-50, 50).ToString(), "Rotation", CDGMath.RandomInt(-45, 45).ToString()); + //Tween.AddEndHandlerToLastTween(this, "DestroyEffect", smoke); + Tween.AddEndHandlerToLastTween(smoke, "StopAnimation"); + + smoke.Opacity = 1; + Tween.To(smoke, 1f, Tween.EaseNone, "delay", "0.5", "Opacity", "0"); + smoke.Opacity = 0; + } + + for (int i = 0; i < 4; i++) + { + SpriteObj feather = m_resourcePool.CheckOut(); + feather.ChangeSprite("CrowFeather_Sprite"); + feather.Visible = true; + feather.Scale = new Vector2(2, 2); + feather.Position = pos; + feather.X += CDGMath.RandomInt(-20, 20); + feather.Y += CDGMath.RandomInt(-20, 20); + feather.Opacity = 0; + feather.PlayAnimation(true); + feather.Rotation = CDGMath.RandomInt(-30, 30); + Tween.To(feather, 0.1f, Tween.EaseNone, "Opacity", "1"); + Tween.By(feather, 1.5f, Quad.EaseInOut, "X", CDGMath.RandomInt(-50, 50).ToString(), "Y", CDGMath.RandomInt(-50, 50).ToString(), "Rotation", CDGMath.RandomInt(-180, 180).ToString()); + //Tween.AddEndHandlerToLastTween(this, "DestroyEffect", feather); + Tween.AddEndHandlerToLastTween(feather, "StopAnimation"); + + feather.Opacity = 1; + Tween.To(feather, 1f, Tween.EaseNone, "delay", "0.5", "Opacity", "0"); + feather.Opacity = 0; + } + } + + public void CrowSmokeEffect(Vector2 pos) + { + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("BlackSmoke_Sprite"); + smoke.Visible = true; + smoke.Y = pos.Y; + smoke.Y += CDGMath.RandomInt(-40, 40); + smoke.X = pos.X; + smoke.X += CDGMath.RandomInt(-40, 40); + smoke.Scale = new Vector2(0.7f, 0.7f); + + smoke.Opacity = 0; + smoke.PlayAnimation(true); + smoke.Rotation = CDGMath.RandomInt(-30, 30); + + Tween.To(smoke, 0.2f, Tween.EaseNone, "Opacity", "1"); + Tween.By(smoke, 1f, Quad.EaseInOut, "X", CDGMath.RandomInt(50, 100).ToString(), "Y", CDGMath.RandomInt(-100, 100).ToString(), "Rotation", CDGMath.RandomInt(-45, 45).ToString()); + smoke.Opacity = 1; + Tween.To(smoke, 0.5f, Tween.EaseNone, "delay", "0.5", "Opacity", "0"); + smoke.Opacity = 0; + //Tween.RunFunction(1.05f, this, "DestroyEffect", smoke); + Tween.RunFunction(1.05f, smoke, "StopAnimation"); + } + + public void WoodChipEffect(Vector2 pos) + { + for (int i = 0; i < 5; i++) + { + SpriteObj woodChip = m_resourcePool.CheckOut(); + woodChip.ChangeSprite("WoodChip_Sprite"); + woodChip.Visible = true; + woodChip.Position = pos; + woodChip.PlayAnimation(true); + woodChip.Scale = new Vector2(2, 2); + + int randRotation = CDGMath.RandomInt(-360, 360); + woodChip.Rotation = randRotation; + Vector2 newPos = new Vector2(CDGMath.RandomInt(-60, 60), CDGMath.RandomInt(-60, 60)); + + Tween.By(woodChip, 0.3f, Tween.EaseNone, "X", newPos.X.ToString(), "Y", newPos.Y.ToString()); + Tween.By(woodChip, 0.3f, Tween.EaseNone, "Rotation", CDGMath.RandomInt(-360,360).ToString()); + //Tween.AddEndHandlerToLastTween(this, "DestroyEffect", woodChip); + Tween.AddEndHandlerToLastTween(woodChip, "StopAnimation"); + Tween.To(woodChip, 0.2f, Tween.EaseNone, "delay", "0.1", "Opacity", "0"); + } + } + + public void SpellCastEffect(Vector2 pos, float angle, bool megaSpell) + { + SpriteObj portal = m_resourcePool.CheckOut(); + portal.ChangeSprite("SpellPortal_Sprite"); + if (megaSpell == true) + portal.TextureColor = Color.Red; + portal.Visible = true; + portal.Position = pos; + portal.PlayAnimation(false); + portal.Scale = new Vector2(2, 2); + portal.Rotation = angle; + portal.OutlineWidth = 2; + } + + public void LastBossSpellCastEffect(GameObj obj, float angle, bool megaSpell) + { + SpriteObj portal = m_resourcePool.CheckOut(); + portal.ChangeSprite("SpellPortal_Sprite"); + if (megaSpell == true) + portal.TextureColor = Color.Red; + portal.Visible = true; + portal.Position = obj.Position; + portal.PlayAnimation(false); + portal.Scale = new Vector2(2, 2); + if (obj.Flip == SpriteEffects.None) + portal.Rotation = -angle; + else + portal.Rotation = angle; + portal.OutlineWidth = 2; + } + + public void LoadingGateSmokeEffect(int numEntities) + { + float xOffset = 1320f / numEntities; + + for (int i = 0; i < numEntities; i++) + { + int randX = CDGMath.RandomInt(-50, 50); + int randY = CDGMath.RandomInt(-50, 0); + + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("ExplosionBrown_Sprite"); + smoke.Visible = true; + smoke.ForceDraw = true; + smoke.Position = new Vector2(xOffset * i, 720); + smoke.PlayAnimation(true); + smoke.Opacity = 0; + smoke.Scale = new Vector2(1.5f, 1.5f); + + Tween.To(smoke, 0.2f, Linear.EaseNone, "Opacity", "0.8"); + Tween.By(smoke, 0.7f, Linear.EaseNone, "Rotation", CDGMath.RandomFloat(-180,180).ToString()); + Tween.By(smoke, 0.7f, Quad.EaseOut, "X", randX.ToString(), "Y", randY.ToString()); + Tween.AddEndHandlerToLastTween(smoke, "StopAnimation"); + smoke.Opacity = 0.8f; + Tween.To(smoke, 0.5f, Linear.EaseNone, "delay", "0.2", "Opacity", "0"); + smoke.Opacity = 0; + } + } + + public void MegaTeleport(Vector2 pos, Vector2 scale) + { + SpriteObj teleport = m_resourcePool.CheckOut() as SpriteObj; + teleport.ChangeSprite("MegaTeleport_Sprite"); + teleport.TextureColor = Color.LightSkyBlue; + teleport.Scale = scale; + teleport.Visible = true; + teleport.Position = pos; + teleport.PlayAnimation(false); + teleport.AnimationDelay = 1 / 60f; + Tween.By(teleport, 0.1f, Tween.EaseNone, "delay", "0.15", "Y", "-720"); + } + + public void MegaTeleportReverse(Vector2 pos, Vector2 scale) + { + SpriteObj teleport = m_resourcePool.CheckOut() as SpriteObj; + teleport.ChangeSprite("MegaTeleportReverse_Sprite"); + teleport.TextureColor = Color.LightSkyBlue; + teleport.Scale = scale; + teleport.Visible = true; + teleport.Position = pos; + teleport.Y -= 720; + teleport.PlayAnimation(1, 1, true); + teleport.AnimationDelay = 1 / 60f; + Tween.By(teleport, 0.1f, Tween.EaseNone, "Y", "720"); + Tween.AddEndHandlerToLastTween(teleport, "PlayAnimation", false); + } + + public void DestroyFireballBoss(Vector2 pos) + { + float angle = 0; + float angleDiff = 360 / 15f; + + for (int i = 0; i < 15; i++) + { + float delay = CDGMath.RandomFloat(0.5f, 1.1f); + int distance = CDGMath.RandomInt(50, 200); + float randScale = CDGMath.RandomFloat(2, 5); + + SpriteObj fireball = m_resourcePool.CheckOut() as SpriteObj; + fireball.ChangeSprite("SpellDamageShield_Sprite"); + fireball.Visible = true; + fireball.Scale = new Vector2(randScale, randScale); + fireball.Position = pos; + fireball.PlayAnimation(true); + Vector2 tweenPos = CDGMath.AngleToVector(angle); + Tween.By(fireball, 1.5f, Quad.EaseOut, "X", (tweenPos.X * distance).ToString(), "Y", (tweenPos.Y * distance).ToString()); + Tween.To(fireball, 0.5f, Tween.EaseNone, "delay", delay.ToString(), "Opacity", "0"); + Tween.AddEndHandlerToLastTween(fireball, "StopAnimation"); + + angle += angleDiff; + } + } + + // 0 = bottom, 1 = left, 2 = right + public void SkillTreeDustEffect(Vector2 pos, bool horizontal, float length) + { + int numClouds = (int)(length / 20f); + float cloudDisplacement = length / numClouds; + Vector2 cloudDisplacementVector = Vector2.Zero; + if (horizontal == true) + cloudDisplacementVector = new Vector2(1, 0); + else + cloudDisplacementVector = new Vector2(0, -1); + + for (int i = 0; i < numClouds; i++) + { + int randX = CDGMath.RandomInt(-10, 10); + int randY = CDGMath.RandomInt(-20, 0); + SpriteObj cloud = m_resourcePool.CheckOut(); + cloud.ChangeSprite("ExplosionBrown_Sprite"); + cloud.Opacity = 0; + cloud.Visible = true; + cloud.Scale = new Vector2(0.5f, 0.5f); + cloud.Rotation = CDGMath.RandomInt(0, 270); + cloud.Position = pos + (cloudDisplacementVector * cloudDisplacement * (i + 1)); + cloud.PlayAnimation(true); + Tween.To(cloud, 0.5f, Linear.EaseNone, "Opacity", "1"); + Tween.By(cloud, 1.5f, Linear.EaseNone, "Rotation", CDGMath.RandomFloat(-30,30).ToString()); + Tween.By(cloud, 1.5f, Quad.EaseOut, "X", randX.ToString(), "Y", randY.ToString()); + float randScale = CDGMath.RandomFloat(0.5f, 0.8f); + Tween.To(cloud, 1.5f, Quad.EaseOut, "ScaleX", randScale.ToString(), "ScaleY", randScale.ToString()); + Tween.AddEndHandlerToLastTween(cloud, "StopAnimation"); + cloud.Opacity = 1; + Tween.To(cloud, 0.7f, Linear.EaseNone, "delay", "0.6", "Opacity", "0"); + cloud.Opacity = 0; + } + } + + public void SkillTreeDustDuration(Vector2 pos, bool horizontal, float length, float duration) + { + float tick = 0.25f; + int numTicks = (int)(duration / tick); + for (int i = 0; i < numTicks; i++) + Tween.RunFunction(tick * i, this, "SkillTreeDustEffect", pos, horizontal, length); + } + + public void CarnivalGoldEffect(Vector2 startPos, Vector2 endPos, int numCoins) + { + float delay = 0.32f; + for (int i = 0; i < numCoins; i++) + { + SpriteObj coin = m_resourcePool.CheckOut() as SpriteObj; + coin.ChangeSprite("Coin_Sprite"); + coin.Visible = true; + coin.Position = startPos; + coin.PlayAnimation(true); + int randX = CDGMath.RandomInt(-30, 30); + int randY = CDGMath.RandomInt(-30, 30); + Tween.By(coin, 0.3f, Quad.EaseInOut, "X", randX.ToString(), "Y", randY.ToString()); + coin.X += randX; + coin.Y += randY; + Tween.To(coin, 0.5f, Quad.EaseIn, "delay", delay.ToString(), "X", endPos.X.ToString(), "Y", endPos.Y.ToString()); + Tween.AddEndHandlerToLastTween(coin, "StopAnimation"); + coin.X -= randX; + coin.Y -= randY; + delay += 0.05f; + } + } + + public void AssassinCastEffect(Vector2 pos) + { + int numEffects = 10; + float angle = 0; + float angleMod = 360 / numEffects; + + for (int i = 0; i < numEffects; i++) + { + Vector2 direction = CDGMath.AngleToVector(angle); + + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("ExplosionBrown_Sprite"); + smoke.Visible = true; + smoke.Position = pos; + smoke.TextureColor = new Color(20, 20, 20); + + smoke.Opacity = 0; + smoke.PlayAnimation(true); + float randScale = CDGMath.RandomFloat(0.5f, 1.5f); + smoke.Scale = new Vector2(randScale, randScale); + smoke.Rotation = CDGMath.RandomInt(-30, 30); + direction.X += CDGMath.RandomInt(-5, 5); + direction.Y += CDGMath.RandomInt(-5, 5); + + Tween.To(smoke, 0.1f, Tween.EaseNone, "Opacity", "0.5"); + Tween.By(smoke, 1f, Quad.EaseOut, "X", (direction.X * CDGMath.RandomInt(20,25)).ToString(), "Y", (direction.Y * CDGMath.RandomInt(20,25)).ToString(), "Rotation", CDGMath.RandomInt(-180, 180).ToString()); + //Tween.AddEndHandlerToLastTween(this, "DestroyEffect", smoke); + Tween.AddEndHandlerToLastTween(smoke, "StopAnimation"); + smoke.Opacity = 0.5f; + Tween.To(smoke, 0.5f, Tween.EaseNone, "delay", "0.5", "Opacity", "0"); + smoke.Opacity = 0; + + angle += angleMod; + } + } + + public void NinjaDisappearEffect(GameObj obj) + { + SpriteObj log = m_resourcePool.CheckOut(); + log.ChangeSprite("Log_Sprite"); + log.AnimationDelay = 1 / 20f; + log.Position = obj.Position; + log.Visible = true; + log.Scale = obj.Scale / 2f; + log.PlayAnimation(true); + + Tween.By(log, 0.3f, Quad.EaseIn, "delay", "0.2", "Y", "50"); + Tween.To(log, 0.2f, Linear.EaseNone, "delay", "0.3", "Opacity", "0"); + Tween.AddEndHandlerToLastTween(log, "StopAnimation"); + + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("NinjaSmoke_Sprite"); + smoke.AnimationDelay = 1 / 20f; + smoke.Position = obj.Position; + smoke.Visible = true; + smoke.Scale = obj.Scale * 2; + smoke.PlayAnimation(false); + } + + public void NinjaAppearEffect(GameObj obj) + { + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("NinjaSmoke_Sprite"); + smoke.AnimationDelay = 1 / 20f; + smoke.Position = obj.Position; + smoke.Visible = true; + smoke.Scale = obj.Scale * 2; + smoke.PlayAnimation(false); + } + + public void DisplayCriticalText(Vector2 position) + { + SpriteObj critical = m_resourcePool.CheckOut(); + critical.ChangeSprite("CriticalText_Sprite"); + Game.ChangeBitmapLanguage(critical, "CriticalText_Sprite"); + critical.Visible = true; + critical.Rotation = CDGMath.RandomInt(-20, 20); + critical.Position = CDGMath.GetCirclePosition(critical.Rotation - 90, 20, position); + critical.Scale = Vector2.Zero; + critical.PlayAnimation(true); + Tween.To(critical, 0.2f, Back.EaseOutLarge, "ScaleX", "1", "ScaleY", "1"); + Tween.To(critical, 0.2f, Tween.EaseNone, "delay", "0.5", "Opacity", "0"); + Tween.AddEndHandlerToLastTween(critical, "StopAnimation"); + } + + public void DisplayFusRoDahText(Vector2 position) + { + SpriteObj critical = m_resourcePool.CheckOut(); + critical.ChangeSprite("FusRoDahText_Sprite"); + critical.Visible = true; + critical.Rotation = CDGMath.RandomInt(-20, 20); + critical.Position = CDGMath.GetCirclePosition(critical.Rotation - 90, 40, position); + critical.Scale = Vector2.Zero; + critical.PlayAnimation(true); + Tween.To(critical, 0.2f, Back.EaseOutLarge, "ScaleX", "1", "ScaleY", "1"); + Tween.To(critical, 0.2f, Tween.EaseNone, "delay", "0.5", "Opacity", "0"); + Tween.AddEndHandlerToLastTween(critical, "StopAnimation"); + } + + public void DisplayTanookiEffect(GameObj obj) + { + for (int i = 0; i < 10; i++) + { + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("ExplosionBrown_Sprite"); + smoke.Visible = true; + smoke.Position = obj.Position; + smoke.X += CDGMath.RandomInt(-30, 30); + smoke.Y += CDGMath.RandomInt(-30, 30); + float randomScale = CDGMath.RandomFloat(0.7f, 0.8f); + int movementAmount = 50; + smoke.Scale = new Vector2(randomScale, randomScale); + smoke.Rotation = CDGMath.RandomInt(0, 90); + smoke.PlayAnimation(true); + + float duration = CDGMath.RandomFloat(0.5f, 1.0f); + float randScaleShrink = CDGMath.RandomFloat(0, 0.1f); + Tween.To(smoke, duration - 0.2f, Linear.EaseNone, "delay", "0.2", "Opacity", "0"); + Tween.To(smoke, duration, Back.EaseIn, "ScaleX", randScaleShrink.ToString(), "ScaleY", randScaleShrink.ToString()); + Tween.By(smoke, duration, Quad.EaseOut, "X", CDGMath.RandomInt(-movementAmount, movementAmount).ToString(), "Y", CDGMath.RandomInt(-movementAmount, movementAmount).ToString()); + Tween.AddEndHandlerToLastTween(smoke, "StopAnimation"); + Tween.By(smoke, duration - 0.1f, Tweener.Ease.Quad.EaseOut, "Rotation", CDGMath.RandomInt(145, 190).ToString()); + } + } + + public void DisplayMusicNote(Vector2 pos) + { + SpriteObj note = m_resourcePool.CheckOut(); + note.ChangeSprite("NoteWhite_Sprite"); + note.Visible = true; + note.Position = pos; + note.Scale = new Vector2(2, 2); + note.Opacity = 0; + note.PlayAnimation(true); + + if (CDGMath.RandomPlusMinus() < 0) + note.Flip = SpriteEffects.FlipHorizontally; + + Tween.By(note, 1f, Quad.EaseOut, "Y", "-50"); + Tween.To(note, 0.5f, Tween.EaseNone, "Opacity", "1"); + note.Opacity = 1; + Tween.To(note, 0.2f, Tween.EaseNone, "delay", "0.8", "Opacity", "0"); + note.Opacity = 0; + Tween.RunFunction(1, note, "StopAnimation"); + } + + public void DisplayQuestionMark(Vector2 pos) + { + SpriteObj note = m_resourcePool.CheckOut(); + note.ChangeSprite("QuestionMark_Sprite"); + note.Visible = true; + note.Position = pos; + float randScale = CDGMath.RandomFloat(0.8f, 2f); + note.Scale = new Vector2(randScale, randScale); + note.Opacity = 0; + note.PlayAnimation(true); + + Tween.By(note, 1f, Quad.EaseOut, "Y", CDGMath.RandomInt(-70,-50).ToString()); + Tween.By(note, 1f, Quad.EaseOut, "X", CDGMath.RandomInt(-20,20).ToString()); + Tween.To(note, 0.5f, Tween.EaseNone, "Opacity", "1"); + note.Opacity = 1; + Tween.To(note, 0.2f, Tween.EaseNone, "delay", "0.8", "Opacity", "0"); + note.Opacity = 0; + Tween.RunFunction(1, note, "StopAnimation"); + } + + public void DisplayMassiveSmoke(Vector2 topLeft) + { + Vector2 pos = topLeft; + for (int i = 0; i < 20; i++) + { + this.IntroSmokeEffect(pos); + pos.Y += 40; + } + } + + public void IntroSmokeEffect(Vector2 pos) + { + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("BlackSmoke_Sprite"); + smoke.Visible = true; + smoke.Y = pos.Y; + smoke.Y += CDGMath.RandomInt(-40, 40); + smoke.X = pos.X; + smoke.X += CDGMath.RandomInt(-40, 40); + smoke.Scale = new Vector2(2.5f, 2.5f); + + smoke.Opacity = 0; + smoke.PlayAnimation(true); + smoke.Rotation = CDGMath.RandomInt(-30, 30); + + float delay = CDGMath.RandomFloat(0, 0.2f); + + Tween.To(smoke, 0.2f, Tween.EaseNone, "delay", delay.ToString(), "Opacity", "1"); + Tween.By(smoke, 1f, Quad.EaseInOut, "delay", delay.ToString(), "X", CDGMath.RandomInt(50, 100).ToString(), "Y", CDGMath.RandomInt(-100, 100).ToString(), "Rotation", CDGMath.RandomInt(-45, 45).ToString()); + smoke.Opacity = 1; + Tween.To(smoke, 0.5f, Tween.EaseNone, "delay", (delay + 0.5f).ToString(), "Opacity", "0"); + smoke.Opacity = 0; + //Tween.AddEndHandlerToLastTween(this, "DestroyEffect", smoke); + Tween.AddEndHandlerToLastTween(smoke, "StopAnimation"); + } + + public void DisplayIceParticleEffect(GameObj sprite) + { + SpriteObj particle = m_resourcePool.CheckOut(); + particle.ChangeSprite("WizardIceParticle_Sprite"); + particle.Visible = true; + particle.Scale = Vector2.Zero; + particle.Position = new Vector2(CDGMath.RandomInt((int)sprite.Bounds.Left, sprite.Bounds.Right), CDGMath.RandomInt((int)sprite.Bounds.Top, sprite.Bounds.Bottom)); + particle.Opacity = 0; + Tween.To(particle, 0.1f, Tween.EaseNone, "Opacity", "1"); + Tween.To(particle, 0.9f, Tween.EaseNone, "ScaleX", "2.5", "ScaleY", "2.5"); + Tween.By(particle, 0.9f, Tween.EaseNone, "Rotation", (CDGMath.RandomInt(90, 270) * CDGMath.RandomPlusMinus()).ToString()); + particle.Opacity = 1; + float delay = CDGMath.RandomFloat(0.4f, 0.7f); + Tween.To(particle, 0.2f, Tween.EaseNone, "delay", delay.ToString(), "Opacity", "0"); + Tween.By(particle, 0.2f + delay, Tween.EaseNone, "X", CDGMath.RandomInt(-20, 20).ToString(), "Y", CDGMath.RandomInt(-20, 20).ToString()); + particle.Opacity = 0; + particle.PlayAnimation(true); + Tween.RunFunction(1f, particle, "StopAnimation"); + } + + public void DisplayFireParticleEffect(GameObj sprite) + { + SpriteObj particle = m_resourcePool.CheckOut(); + particle.ChangeSprite("WizardFireParticle_Sprite"); + particle.Visible = true; + particle.Scale = Vector2.Zero; + particle.Position = new Vector2(CDGMath.RandomInt((int)sprite.Bounds.Left, sprite.Bounds.Right), CDGMath.RandomInt((int)sprite.Bounds.Top, sprite.Bounds.Bottom)); + particle.Opacity = 0; + Tween.To(particle, 0.1f, Tween.EaseNone, "Opacity", "1"); + Tween.To(particle, 0.9f, Tween.EaseNone, "ScaleX", "4", "ScaleY", "4"); + particle.Opacity = 1; + float delay = CDGMath.RandomFloat(0.4f, 0.7f); + Tween.To(particle, 0.2f, Tween.EaseNone, "delay", delay.ToString(), "Opacity", "0"); + Tween.By(particle, 0.2f + delay, Tween.EaseNone, "Y", CDGMath.RandomInt(-20, -5).ToString()); + particle.Opacity = 0; + particle.PlayAnimation(true); + Tween.RunFunction(1f, particle, "StopAnimation"); + } + + public void DisplayEarthParticleEffect(GameObj sprite) + { + int randBlossom = CDGMath.RandomInt(1, 4); + SpriteObj particle = m_resourcePool.CheckOut(); + particle.ChangeSprite("Blossom" + randBlossom + "_Sprite"); + particle.Visible = true; + particle.Scale = new Vector2(0.2f, 0.2f); + particle.Position = new Vector2(CDGMath.RandomInt((int)sprite.Bounds.Left, sprite.Bounds.Right), CDGMath.RandomInt((int)sprite.Bounds.Top, sprite.Bounds.Bottom)); + particle.Opacity = 0; + Tween.To(particle, 0.1f, Tween.EaseNone, "Opacity", "1"); + Tween.To(particle, 0.9f, Tween.EaseNone, "ScaleX", "0.7", "ScaleY", "0.7"); + Tween.By(particle, 0.9f, Tween.EaseNone, "Rotation", (CDGMath.RandomInt(10, 45) * CDGMath.RandomPlusMinus()).ToString()); + particle.Opacity = 1; + float delay = CDGMath.RandomFloat(0.4f, 0.7f); + Tween.To(particle, 0.2f, Tween.EaseNone, "delay", delay.ToString(), "Opacity", "0"); + Tween.By(particle, 0.2f + delay, Tween.EaseNone, "Y", CDGMath.RandomInt(5, 20).ToString()); + particle.Opacity = 0; + particle.PlayAnimation(true); + Tween.RunFunction(1f, particle, "StopAnimation"); + } + + public void DisplayFountainShatterSmoke(GameObj sprite) + { + int numParticles = 15; + float width = (float)sprite.Width / (float)numParticles; + float startingX = sprite.Bounds.Left; + for (int i = 0; i < numParticles; i++) + { + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("FountainShatterSmoke_Sprite"); + smoke.Visible = true; + smoke.PlayAnimation(true); + smoke.Opacity = 0; + smoke.Scale = Vector2.Zero; + smoke.Position = new Vector2(startingX, sprite.Y); + + float randScale = CDGMath.RandomFloat(2,4); + Tween.To(smoke, 0.5f, Tween.EaseNone, "Opacity", "1"); + Tween.By(smoke, 4, Tween.EaseNone, "Rotation", CDGMath.RandomInt(-40, 40).ToString()); + Tween.By(smoke, 3, Tween.EaseNone, "X", CDGMath.RandomInt(-20, 20).ToString(), "Y", CDGMath.RandomInt(-50, -30).ToString()); + Tween.To(smoke, 3, Tween.EaseNone, "ScaleX", randScale.ToString(), "ScaleY", randScale.ToString()); + smoke.Opacity = 1; + Tween.To(smoke, 2, Tween.EaseNone, "delay", CDGMath.RandomFloat(1f, 2f).ToString(), "Opacity", "0"); + smoke.Opacity = 0; + Tween.RunFunction(4.5f, smoke, "StopAnimation"); + startingX += width; + } + + numParticles /= 2; + startingX = sprite.Bounds.Left + 50; + width = (float)(sprite.Width - 50) / (float)numParticles; + for (int i = 0; i < numParticles; i++) + { + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("FountainShatterSmoke_Sprite"); + smoke.Visible = true; + smoke.PlayAnimation(true); + smoke.Scale = Vector2.Zero; + smoke.Opacity = 0; + smoke.Position = new Vector2(startingX, sprite.Y - 100); + + float randScale = CDGMath.RandomFloat(2, 4); + Tween.To(smoke, 0.5f, Tween.EaseNone, "Opacity", "1"); + Tween.By(smoke, 4, Tween.EaseNone, "Rotation", CDGMath.RandomInt(-180, 180).ToString()); + Tween.By(smoke, 3, Tween.EaseNone, "X", CDGMath.RandomInt(-20, 20).ToString(), "Y", CDGMath.RandomInt(-50, -30).ToString()); + Tween.To(smoke, 3, Tween.EaseNone, "ScaleX", randScale.ToString(), "ScaleY", randScale.ToString()); + smoke.Opacity = 1; + Tween.To(smoke, 2, Tween.EaseNone, "delay", CDGMath.RandomFloat(1f, 2f).ToString(), "Opacity", "0"); + smoke.Opacity = 0; + Tween.RunFunction(4.5f, smoke, "StopAnimation"); + startingX += width; + } + + numParticles /= 2; + startingX = sprite.Bounds.Left + 100; + width = (float)(sprite.Width - 100) / (float)numParticles; + for (int i = 0; i < numParticles; i++) + { + SpriteObj smoke = m_resourcePool.CheckOut(); + smoke.ChangeSprite("FountainShatterSmoke_Sprite"); + smoke.Visible = true; + smoke.PlayAnimation(true); + smoke.Scale = Vector2.Zero; + smoke.Opacity = 0; + smoke.Position = new Vector2(startingX, sprite.Y - 200); + + float randScale = CDGMath.RandomFloat(2, 4); + Tween.To(smoke, 0.5f, Tween.EaseNone, "Opacity", "1"); + Tween.By(smoke, 4, Tween.EaseNone, "Rotation", CDGMath.RandomInt(-180, 180).ToString()); + Tween.By(smoke, 3, Tween.EaseNone, "X", CDGMath.RandomInt(-20, 20).ToString(), "Y", CDGMath.RandomInt(-50, -30).ToString()); + Tween.To(smoke, 3, Tween.EaseNone, "ScaleX", randScale.ToString(), "ScaleY", randScale.ToString()); + smoke.Opacity = 1; + Tween.To(smoke, 2, Tween.EaseNone, "delay", CDGMath.RandomFloat(1f, 2f).ToString(), "Opacity", "0"); + smoke.Opacity = 0; + Tween.RunFunction(4.5f, smoke, "StopAnimation"); + startingX += width; + } + } + + public void DoorSparkleEffect(Rectangle rect) + { + SpriteObj particle = m_resourcePool.CheckOut(); + particle.ChangeSprite("LevelUpParticleFX_Sprite"); + particle.Visible = true; + float randomScale = CDGMath.RandomFloat(0.3f, 0.5f); + particle.Scale = new Vector2(randomScale, randomScale); + particle.Opacity = 0; + particle.Position = new Vector2(CDGMath.RandomInt(rect.X, rect.X + rect.Width), CDGMath.RandomInt(rect.Y, rect.Y + rect.Height)); + particle.Rotation = CDGMath.RandomInt(0, 90); + particle.PlayAnimation(false); + Tween.To(particle, 0.4f, Linear.EaseNone, "Opacity", "1");//, "ScaleX", "0", "ScaleY", "0"); + Tween.By(particle, 0.6f, Linear.EaseNone, "Rotation", CDGMath.RandomInt(-45, 45).ToString(), "Y", "-50");//, "ScaleX", "0", "ScaleY", "0"); + Tween.To(particle, 0.7f, Linear.EaseNone, "ScaleX", "0", "ScaleY", "0"); + Tween.AddEndHandlerToLastTween(particle, "StopAnimation"); + } + + public void DestroyEffect(SpriteObj obj) + { + obj.OutlineWidth = 0; + obj.Visible = false; + obj.Rotation = 0; + obj.TextureColor = Color.White; + obj.Opacity = 1; + m_resourcePool.CheckIn(obj); + obj.Flip = SpriteEffects.None; + obj.Scale = new Vector2(1, 1); + obj.AnimationDelay = 1 / 30f; + } + + public void PauseAllAnimations() + { + m_isPaused = true; + foreach (SpriteObj sprite in m_resourcePool.ActiveObjsList) + sprite.PauseAnimation(); + } + + public void ResumeAllAnimations() + { + m_isPaused = false; + foreach (SpriteObj sprite in m_resourcePool.ActiveObjsList) + sprite.ResumeAnimation(); + } + + public void DestroyAllEffects() + { + foreach (SpriteObj sprite in m_resourcePool.ActiveObjsList) + sprite.StopAnimation(); + } + + public void Draw(Camera2D camera) + { + for (int i = 0; i < m_resourcePool.ActiveObjsList.Count; i++) + { + if (m_resourcePool.ActiveObjsList[i].IsAnimating == false && m_isPaused == false) + { + DestroyEffect(m_resourcePool.ActiveObjsList[i]); + i--; + } + else + m_resourcePool.ActiveObjsList[i].Draw(camera); + } + } + + public void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Impact Effect Pool"); + + m_isDisposed = true; + m_resourcePool.Dispose(); + m_resourcePool = null; + } + } + + public int ActiveTextObjs + { + get { return m_resourcePool.NumActiveObjs; } + } + + public int TotalPoolSize + { + get { return m_resourcePool.TotalPoolSize; } + } + + public int CurrentPoolSize + { + get { return TotalPoolSize - ActiveTextObjs; } + } + } +} diff --git a/RogueCastle/src/LevelBuilder2.cs b/RogueCastle/src/LevelBuilder2.cs new file mode 100644 index 0000000..2bea6d5 --- /dev/null +++ b/RogueCastle/src/LevelBuilder2.cs @@ -0,0 +1,2476 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using DS2DEngine; +using System.Globalization; + +namespace RogueCastle +{ + class LevelBuilder2 + { + private const int MAX_ROOM_SIZE = 4; + + private static List[,] m_castleRoomArray = new List[MAX_ROOM_SIZE, MAX_ROOM_SIZE]; + private static List[,] m_dungeonRoomArray = new List[MAX_ROOM_SIZE, MAX_ROOM_SIZE]; + private static List[,] m_towerRoomArray = new List[MAX_ROOM_SIZE, MAX_ROOM_SIZE]; + private static List[,] m_gardenRoomArray = new List[MAX_ROOM_SIZE, MAX_ROOM_SIZE]; + + private static List m_bossRoomArray = null; + + private static RoomObj m_startingRoom = null; + private static RoomObj m_testRoom = null; + private static RoomObj m_castleEntranceRoom = null; + + private static RoomObj m_linkerCastleRoom = null; + private static RoomObj m_linkerDungeonRoom = null; + private static RoomObj m_linkerGardenRoom = null; + private static RoomObj m_linkerTowerRoom = null; + + private static RoomObj m_bossCastleEntranceRoom = null; + private static RoomObj m_bossDungeonEntranceRoom = null; + private static RoomObj m_bossGardenEntranceRoom = null; + private static RoomObj m_bossTowerEntranceRoom = null; + + private static List m_secretCastleRoomArray = null; + private static List m_secretGardenRoomArray = null; + private static List m_secretTowerRoomArray = null; + private static List m_secretDungeonRoomArray = null; + + private static List m_bonusCastleRoomArray = null; + private static List m_bonusGardenRoomArray = null; + private static List m_bonusTowerRoomArray = null; + private static List m_bonusDungeonRoomArray = null; + + private static List m_dlcCastleRoomArray = null; + private static List m_dlcGardenRoomArray = null; + private static List m_dlcTowerRoomArray = null; + private static List m_dlcDungeonRoomArray = null; + + private static RoomObj m_tutorialRoom = null; + private static RoomObj m_throneRoom = null; + private static RoomObj m_endingRoom = null; + private static CompassRoomObj m_compassRoom = null; + + // Challenge Room Content. + private static List m_challengeRoomArray = null; + + public static void Initialize() + { + for (int i = 0; i < MAX_ROOM_SIZE; i++) + { + for (int k = 0; k < MAX_ROOM_SIZE; k++) + { + m_castleRoomArray[i, k] = new List(); + m_dungeonRoomArray[i, k] = new List(); + m_towerRoomArray[i, k] = new List(); + m_gardenRoomArray[i, k] = new List(); + } + } + + m_secretCastleRoomArray = new List(); + m_secretGardenRoomArray = new List(); + m_secretTowerRoomArray = new List(); + m_secretDungeonRoomArray = new List(); + + m_bonusCastleRoomArray = new List(); + m_bonusGardenRoomArray = new List(); + m_bonusTowerRoomArray = new List(); + m_bonusDungeonRoomArray = new List(); + + m_bossRoomArray = new List(); + m_challengeRoomArray = new List(); + + m_dlcCastleRoomArray = new List(); + m_dlcDungeonRoomArray = new List(); + m_dlcGardenRoomArray = new List(); + m_dlcTowerRoomArray = new List(); + } + + public static void StoreRoom(RoomObj room, GameTypes.LevelType levelType) + { + if (room.Name != "Start" && room.Name != "Linker" && + room.Name != "Boss" && room.Name != "EntranceBoss" && + room.Name != "Secret" && room.Name != "Bonus" && + room.Name != "CastleEntrance" && room.Name != "Throne" && + room.Name != "Tutorial" && room.Name != "Ending" && + room.Name != "Compass" && room.Name != "DEBUG_ROOM" && room.Name != "ChallengeBoss") + { + + if (room.Width % GlobalEV.ScreenWidth != 0) + throw new Exception("Room Name: " + room.Name + " is not a width divisible by " + GlobalEV.ScreenWidth + ". Cannot parse the file."); + + if (room.Height % GlobalEV.ScreenHeight != 0) + throw new Exception("Room Name: " + room.Name + " is not a height divisible by " + GlobalEV.ScreenHeight + ". Cannot parse the file."); + + int i = (int)(room.Width / GlobalEV.ScreenWidth); + int k = (int)(room.Height / GlobalEV.ScreenHeight); + + if (room.IsDLCMap == false) + { + List[,] roomArray = null; + switch (levelType) + { + case (GameTypes.LevelType.CASTLE): + roomArray = m_castleRoomArray; + break; + case (GameTypes.LevelType.DUNGEON): + roomArray = m_dungeonRoomArray; + break; + case (GameTypes.LevelType.TOWER): + roomArray = m_towerRoomArray; + break; + case (GameTypes.LevelType.GARDEN): + roomArray = m_gardenRoomArray; + break; + } + + roomArray[i - 1, k - 1].Add(room.Clone() as RoomObj); + RoomObj roomClone = room.Clone() as RoomObj; + roomClone.Reverse(); // Do not reverse the actual room. + roomArray[i - 1, k - 1].Add(roomClone); + } + else // Storing DLC maps in a separate array. + { + List dlcRoomArray = GetSequencedDLCRoomList(levelType); + + dlcRoomArray.Add(room.Clone() as RoomObj); + RoomObj roomClone = room.Clone() as RoomObj; + roomClone.Reverse(); // Do not reverse the actual room. + dlcRoomArray.Add(roomClone); + } + } + } + + public static void StoreSpecialRoom(RoomObj room, GameTypes.LevelType levelType, bool storeDebug = false) + { + if (storeDebug == true) + { + m_testRoom = room.Clone() as RoomObj; + m_testRoom.LevelType = LevelEV.TESTROOM_LEVELTYPE; + } + //else + { + switch (room.Name) + { + case ("Start"): + //if (m_bossEntranceRoom != null) throw new Exception("More than 1 boss entrance room found"); + if (m_startingRoom == null) // Only store the first found copy of the starting room. + { + m_startingRoom = new StartingRoomObj(); + m_startingRoom.CopyRoomProperties(room); + m_startingRoom.CopyRoomObjects(room); + } + break; + case ("Linker"): + //if (m_linkerRoom != null) throw new Exception("More than 1 linker room found"); + RoomObj linkerRoom = room.Clone() as RoomObj; + + switch (levelType) + { + case (GameTypes.LevelType.CASTLE): + m_linkerCastleRoom = linkerRoom; + break; + case (GameTypes.LevelType.DUNGEON): + m_linkerDungeonRoom = linkerRoom; + break; + case (GameTypes.LevelType.TOWER): + m_linkerTowerRoom = linkerRoom; + break; + case (GameTypes.LevelType.GARDEN): + m_linkerGardenRoom = linkerRoom; + break; + } + + TeleporterObj teleporter = new TeleporterObj(); + teleporter.Position = new Vector2(linkerRoom.X + linkerRoom.Width / 2f - (teleporter.Bounds.Right - teleporter.AnchorX), linkerRoom.Y + linkerRoom.Height - 60); + linkerRoom.GameObjList.Add(teleporter); + break; + case ("Boss"): + foreach (DoorObj door in room.DoorList) // Locking the doors to boss rooms so you can't exit a boss fight. + { + if (door.IsBossDoor == true) + door.Locked = true; + } + m_bossRoomArray.Add(room.Clone() as RoomObj); + break; + case ("EntranceBoss"): + //if (m_bossEntranceRoom != null) throw new Exception("More than 1 boss entrance room found"); + RoomObj bossEntranceRoom = room.Clone() as RoomObj; + TeleporterObj bossTeleporter = new TeleporterObj(); + bossTeleporter.Position = new Vector2(bossEntranceRoom.X + bossEntranceRoom.Width / 2f - (bossTeleporter.Bounds.Right - bossTeleporter.AnchorX), bossEntranceRoom.Y + bossEntranceRoom.Height - 60); + bossEntranceRoom.GameObjList.Add(bossTeleporter); + + NpcObj donationBox = null; + foreach (GameObj obj in bossEntranceRoom.GameObjList) + { + if (obj.Name == "donationbox") + { + donationBox = new NpcObj((obj as ObjContainer).SpriteName); + donationBox.Position = obj.Position; + donationBox.Y -= 2; + donationBox.Name = obj.Name; + donationBox.Scale = obj.Scale; + donationBox.useArrowIcon = true; + obj.Visible = false; + } + } + + if (donationBox != null) + bossEntranceRoom.GameObjList.Add(donationBox); + + switch (levelType) + { + case (GameTypes.LevelType.CASTLE): + m_bossCastleEntranceRoom = bossEntranceRoom; + break; + case (GameTypes.LevelType.DUNGEON): + m_bossDungeonEntranceRoom = bossEntranceRoom; + break; + case (GameTypes.LevelType.TOWER): + m_bossTowerEntranceRoom = bossEntranceRoom; + break; + case (GameTypes.LevelType.GARDEN): + m_bossGardenEntranceRoom = bossEntranceRoom; + break; + } + + break; + case ("CastleEntrance"): + // Only store the first copy of the castle entrance room. + if (m_castleEntranceRoom == null) + { + m_castleEntranceRoom = new CastleEntranceRoomObj(); + m_castleEntranceRoom.CopyRoomProperties(room); + m_castleEntranceRoom.CopyRoomObjects(room); + m_castleEntranceRoom.LevelType = GameTypes.LevelType.CASTLE; + } + break; + case ("Compass"): + if (m_compassRoom == null) + { + m_compassRoom = new CompassRoomObj(); + m_compassRoom.CopyRoomProperties(room); + m_compassRoom.CopyRoomObjects(room); + } + break; + case ("Secret"): + List secretRoomArray = null; + + switch (levelType) + { + case (GameTypes.LevelType.CASTLE): + secretRoomArray = m_secretCastleRoomArray; + break; + case (GameTypes.LevelType.DUNGEON): + secretRoomArray = m_secretDungeonRoomArray; + break; + case (GameTypes.LevelType.TOWER): + secretRoomArray = m_secretTowerRoomArray; + break; + case (GameTypes.LevelType.GARDEN): + secretRoomArray = m_secretGardenRoomArray; + break; + } + + secretRoomArray.Add(room.Clone() as RoomObj); + RoomObj roomClone = room.Clone() as RoomObj; + roomClone.Reverse(); // Do not reverse the actual room. + secretRoomArray.Add(roomClone); + break; + case ("Bonus"): + List bonusRoomArray = null; + + switch (levelType) + { + case (GameTypes.LevelType.CASTLE): + bonusRoomArray = m_bonusCastleRoomArray; + break; + case (GameTypes.LevelType.DUNGEON): + bonusRoomArray = m_bonusDungeonRoomArray; + break; + case (GameTypes.LevelType.TOWER): + bonusRoomArray = m_bonusTowerRoomArray; + break; + case (GameTypes.LevelType.GARDEN): + bonusRoomArray = m_bonusGardenRoomArray; + break; + } + + bonusRoomArray.Add(room.Clone() as RoomObj); + RoomObj bonusRoomClone = room.Clone() as RoomObj; + bonusRoomClone.Reverse(); // Do not reverse the actual room. + bonusRoomArray.Add(bonusRoomClone); + break; + case ("Tutorial"): + if (m_tutorialRoom == null) + { + m_tutorialRoom = new TutorialRoomObj(); + m_tutorialRoom.CopyRoomProperties(room); + m_tutorialRoom.CopyRoomObjects(room); + } + break; + case("Throne"): + if (m_throneRoom == null) + { + m_throneRoom = new ThroneRoomObj(); + m_throneRoom.CopyRoomProperties(room); + m_throneRoom.CopyRoomObjects(room); + } + break; + case ("Ending"): + if (m_endingRoom == null) + { + m_endingRoom = new EndingRoomObj(); + m_endingRoom.CopyRoomProperties(room); + m_endingRoom.CopyRoomObjects(room); + } + break; + case ("ChallengeBoss"): + foreach (DoorObj door in room.DoorList) // Locking the doors to challenge rooms so you can't exit the challenge. + { + if (door.IsBossDoor == true) + door.Locked = true; + } + m_challengeRoomArray.Add(room.Clone() as RoomObj); + break; + } + } + } + + //public static List CreateArea(int roomSize, GameTypes.LevelType levelType, List roomsToCheckCollisionsList, RoomObj startingRoom, bool firstRoom) + public static List CreateArea(int areaSize, AreaStruct areaInfo, List roomsToCheckCollisionsList, RoomObj startingRoom, bool firstRoom) + { + // The way boss rooms work, is as more and more rooms get built, the chance of a boss room appearing increases, until it hits 100% for the final room. + bool bossAdded = false; + float bossRoomChance = -100; + float bossRoomChanceIncrease = (100f / areaSize); + if (areaInfo.BossInArea == true) + bossRoomChance = 0; + else + bossAdded = true; + + int secretRoomsNeeded = CDGMath.RandomInt((int)areaInfo.SecretRooms.X, (int)areaInfo.SecretRooms.Y); + int secretRoomTotal = secretRoomsNeeded; + int secretRoomIncrease = (int)(areaSize / (secretRoomsNeeded + 1)); // The number of rooms you need to increase by before adding a secret room. + int nextSecretRoomToAdd = secretRoomIncrease; // This is where the first secret room should be added. + List secretRoomArrayCopy = new List(); // Make a clone of the secret room array. + + List secretRoomArray = null; + List bonusRoomArray = null; + switch (areaInfo.LevelType) + { + case(GameTypes.LevelType.CASTLE): + secretRoomArray = m_secretCastleRoomArray; + bonusRoomArray = m_bonusCastleRoomArray; + break; + case (GameTypes.LevelType.DUNGEON): + secretRoomArray = m_secretDungeonRoomArray; + bonusRoomArray = m_bonusDungeonRoomArray; + break; + case (GameTypes.LevelType.GARDEN): + secretRoomArray = m_secretGardenRoomArray; + bonusRoomArray = m_bonusGardenRoomArray; + break; + case (GameTypes.LevelType.TOWER): + secretRoomArray = m_secretTowerRoomArray; + bonusRoomArray = m_bonusTowerRoomArray; + break; + } + + secretRoomArrayCopy.AddRange(secretRoomArray); + + int bonusRoomsNeeded = CDGMath.RandomInt((int)areaInfo.BonusRooms.X, (int)areaInfo.BonusRooms.Y); + int bonusRoomTotal = bonusRoomsNeeded; + int bonusRoomIncrease = (int)(areaSize / (bonusRoomsNeeded + 1)); + int nextBonusRoomToAdd = bonusRoomIncrease; + List bonusRoomArrayCopy = new List(); // Make a clone of the bonus room array. + bonusRoomArrayCopy.AddRange(bonusRoomArray); + + if (areaInfo.SecretRooms.Y > secretRoomArray.Count) + throw new Exception("Cannot add " + (int)areaInfo.SecretRooms.Y + " secret rooms from pool of " + secretRoomArray.Count + " secret rooms."); + + if (areaInfo.BonusRooms.Y > bonusRoomArray.Count) + throw new Exception("Cannot add " + (int)areaInfo.BonusRooms.Y + " bonus rooms from pool of " + bonusRoomArray.Count + " bonus rooms."); + + GameTypes.LevelType levelType = areaInfo.LevelType; + + //Creating a copy of all the rooms in the level so that I can manipulate this list at will without affecting the actual list. + List tempRoomsToCheckCollisionsList = new List(); + + tempRoomsToCheckCollisionsList.AddRange(roomsToCheckCollisionsList); + + List doorsToLink = new List(); // This might run better as a linked list or maybe a FIFO queue. + List roomList = new List(); + int numRoomsLeftToCreate = areaSize; + int leftDoorPercent = 0; + int rightDoorPercent = 0; + int topDoorPercent = 0; + int bottomDoorPercent = 0; + string startingDoorPosition = "NONE"; + + switch (levelType) + { + case (GameTypes.LevelType.CASTLE): + leftDoorPercent = LevelEV.LEVEL_CASTLE_LEFTDOOR; + rightDoorPercent = LevelEV.LEVEL_CASTLE_RIGHTDOOR; + topDoorPercent = LevelEV.LEVEL_CASTLE_TOPDOOR; + bottomDoorPercent = LevelEV.LEVEL_CASTLE_BOTTOMDOOR; + startingDoorPosition = "Right"; + break; + case (GameTypes.LevelType.GARDEN): + leftDoorPercent = LevelEV.LEVEL_GARDEN_LEFTDOOR; + rightDoorPercent = LevelEV.LEVEL_GARDEN_RIGHTDOOR; + topDoorPercent = LevelEV.LEVEL_GARDEN_TOPDOOR; + bottomDoorPercent = LevelEV.LEVEL_GARDEN_BOTTOMDOOR; + startingDoorPosition = "Right"; //"Right"; TEDDY - SO GARDEN CAN CONNECT TOP + break; + case (GameTypes.LevelType.TOWER): + leftDoorPercent = LevelEV.LEVEL_TOWER_LEFTDOOR; + rightDoorPercent = LevelEV.LEVEL_TOWER_RIGHTDOOR; + topDoorPercent = LevelEV.LEVEL_TOWER_TOPDOOR; + bottomDoorPercent = LevelEV.LEVEL_TOWER_BOTTOMDOOR; + startingDoorPosition = "Top"; + break; + case (GameTypes.LevelType.DUNGEON): + leftDoorPercent = LevelEV.LEVEL_DUNGEON_LEFTDOOR; + rightDoorPercent = LevelEV.LEVEL_DUNGEON_RIGHTDOOR; + topDoorPercent = LevelEV.LEVEL_DUNGEON_TOPDOOR; + bottomDoorPercent = LevelEV.LEVEL_DUNGEON_BOTTOMDOOR; + startingDoorPosition = "Bottom";//"Bottom"; TEDDY - SO GARDEN CAN CONNECT TOP + break; + } + DoorObj startingDoor = null; + + if (firstRoom == true) + { + roomList.Add(startingRoom); + tempRoomsToCheckCollisionsList.Add(startingRoom); + + startingRoom.LevelType = GameTypes.LevelType.NONE; + numRoomsLeftToCreate--; // Because the starting room is added to the list so reduce the number of rooms that need to be made by 1. + MoveRoom(startingRoom, Vector2.Zero);// Sets the starting room to position (0,0) for simplicity. + + // Adding the castle entrance room to the game after the starting room. + RoomObj castleEntrance = m_castleEntranceRoom.Clone() as RoomObj; + roomList.Add(castleEntrance); + tempRoomsToCheckCollisionsList.Add(castleEntrance); + //castleEntrance.LevelType = GameTypes.LevelType.NONE;//GameTypes.LevelType.CASTLE; // Why? + numRoomsLeftToCreate--; + MoveRoom(castleEntrance, new Vector2(startingRoom.X + startingRoom.Width, startingRoom.Bounds.Bottom - castleEntrance.Height)); + + startingRoom = castleEntrance; // This last line is extremely important. It sets this room as the new starting room to attach new rooms to. + } + + //Finding the first door to the right in the starting room + foreach (DoorObj door in startingRoom.DoorList) + { + if (door.DoorPosition == startingDoorPosition) + { + doorsToLink.Add(door); + startingDoor = door; + break; + } + } + + // Close remaining doors in the very first room of the level. + // This shouldn't be necessary since the starting room is manually created, so no extra doors should exist. + //if (firstRoom == true) + //{ + // for (int i = 0; i < startingRoom.DoorList.Count; i++) + // { + // if (startingRoom.DoorList[i] != startingDoor) + // { + // RemoveDoorFromRoom(startingRoom.DoorList[i]); + // i--; + // } + // } + //} + + if (doorsToLink.Count == 0) // Making sure the starting room has a door positioned to the right. + throw new Exception("The starting room does not have a " + startingDoorPosition + " positioned door. Cannot create level."); + + while (numRoomsLeftToCreate > 0) + { + if (doorsToLink.Count <= 0) + { + Console.WriteLine("ERROR: Ran out of available rooms to make."); + break; + } + + bool linkDoor = false; // Each door has a percentage chance of linking to another room. This bool keeps track of that. + DoorObj needsLinking = doorsToLink[0]; // Always link the first door in the list. Once that's done, remove the door from the list and go through the list again. + //if (doorsToLink.Count == 1 && numRoomsLeftToCreate > 0) // If there are still rooms to build but this is the last available door in the list, force it open. + if ((doorsToLink.Count <= 5 && needsLinking != startingDoor && numRoomsLeftToCreate > 0) || needsLinking == startingDoor) // If there are still rooms to build but this is the last available door in the list, force it open. + linkDoor = true; + else // Each door has a percentage chance of linking to another room. This code determines that chance. + { + int percentChance = 100; + switch (needsLinking.DoorPosition) + { + case ("Left"): + percentChance = leftDoorPercent; + break; + case ("Right"): + percentChance = rightDoorPercent; + break; + case ("Top"): + percentChance = topDoorPercent; + break; + case ("Bottom"): + percentChance = bottomDoorPercent; + break; + } + + if (percentChance - CDGMath.RandomInt(1, 100) >= 0) + linkDoor = true; + } + + if (linkDoor == false) + { + doorsToLink.Remove(needsLinking); + continue; // This continue forces the while loop to go through the next iteration. + } + + List suitableDoorList = null; + + bool addingBossRoom = false; + if (bossRoomChance >= CDGMath.RandomInt(50, 100) && bossAdded == false) + { + RoomObj bossEntranceRoom = null; + + switch (areaInfo.LevelType) + { + case (GameTypes.LevelType.CASTLE): + bossEntranceRoom = m_bossCastleEntranceRoom; + break; + case (GameTypes.LevelType.DUNGEON): + bossEntranceRoom = m_bossDungeonEntranceRoom; + break; + case (GameTypes.LevelType.GARDEN): + bossEntranceRoom = m_bossGardenEntranceRoom; + break; + case (GameTypes.LevelType.TOWER): + bossEntranceRoom = m_bossTowerEntranceRoom; + break; + } + + addingBossRoom = true; + string doorNeeded = GetOppositeDoorPosition(needsLinking.DoorPosition); + suitableDoorList = new List(); + foreach (DoorObj door in bossEntranceRoom.DoorList) + { + if (door.DoorPosition == doorNeeded && CheckForRoomCollision(needsLinking, tempRoomsToCheckCollisionsList, door) == false) + { + if (suitableDoorList.Contains(door) == false) + { + bossAdded = true; + suitableDoorList.Add(door); + break; + } + } + } + } + else + bossRoomChance += bossRoomChanceIncrease; + + bool addingSpecialRoom = false; + bool addingSecretRoom = false; + + if ((addingBossRoom == true && bossAdded == false) || addingBossRoom == false) // Only continue adding rooms if the boss room isn't being added at the moment or if no suitable boss room could be found. + { + if (roomList.Count >= nextSecretRoomToAdd && secretRoomsNeeded > 0) // Add a secret room instead of a normal room. + { + addingSpecialRoom = true; + addingSecretRoom = true; + suitableDoorList = FindSuitableDoors(needsLinking, secretRoomArrayCopy, tempRoomsToCheckCollisionsList); + } + else if (roomList.Count >= nextBonusRoomToAdd && bonusRoomsNeeded > 0) // Add a bonus room instead of a normal room. + { + addingSpecialRoom = true; + suitableDoorList = FindSuitableDoors(needsLinking, bonusRoomArrayCopy, tempRoomsToCheckCollisionsList); + } + + // If you are not adding a special room, or if you are adding a special room but you cannot find a suitable room, add a normal room. + if (addingSpecialRoom == false || (addingSpecialRoom == true && suitableDoorList.Count == 0)) + { + if (roomList.Count < 5) // When building a level early, make sure you don't accidentally choose rooms with no doors (or only 1 door) in them. + suitableDoorList = FindSuitableDoors(needsLinking, MAX_ROOM_SIZE, MAX_ROOM_SIZE, tempRoomsToCheckCollisionsList, levelType, true); // Searches all rooms up to the specified size and finds suitable doors to connect to the current door. + else // The list of rooms already added needs to be passed in to check for room collisions. + suitableDoorList = FindSuitableDoors(needsLinking, MAX_ROOM_SIZE, MAX_ROOM_SIZE, tempRoomsToCheckCollisionsList, levelType, false); // Searches all rooms up to the specified size and finds suitable doors to connect to the current door. + } + else // You are adding a special room and you have found a suitable list of rooms it can connect to. Yay! + { + if (addingSecretRoom == true) + { + nextSecretRoomToAdd = roomList.Count + secretRoomIncrease; + secretRoomsNeeded--; + } + else if (addingSecretRoom == false) + { + nextBonusRoomToAdd = roomList.Count + bonusRoomIncrease; + bonusRoomsNeeded--; + } + } + } + + // If for some reason not a single suitable room could be found, remove this door from the list of doors that need rooms connected to them. + if (suitableDoorList.Count == 0) + doorsToLink.Remove(needsLinking); + else + { + int randomDoorIndex = CDGMath.RandomInt(0, suitableDoorList.Count - 1); // Choose a random door index from the suitableDoorList to attach to the door. + CDGMath.Shuffle(suitableDoorList); + DoorObj doorToLinkTo = suitableDoorList[randomDoorIndex]; + + // This code prevents the same special rooms from being added to an area twice. + if (addingSpecialRoom == true) + { + if (addingSecretRoom == true) + secretRoomArrayCopy.Remove(doorToLinkTo.Room); + else if (addingSecretRoom == false) + bonusRoomArrayCopy.Remove(doorToLinkTo.Room); + } + + RoomObj roomToAdd = doorToLinkTo.Room.Clone() as RoomObj; // Make sure to get a clone of the room since suitableDoorList returns a list of suitable rooms from the actual LevelBuilder array. + //roomToAdd.LevelType = levelType; // Set the room level type. + foreach (DoorObj door in roomToAdd.DoorList) + { + if (door.Position == doorToLinkTo.Position) + { + doorToLinkTo = door; // Because roomToAdd is cloned from doorToLinkTo, doorToLinkTo needs to relink itself to the cloned room. + break; + } + } + + roomToAdd.LevelType = levelType; // Setting the room LevelType. + roomToAdd.TextureColor = areaInfo.Color; // Setting the room Color. + roomList.Add(roomToAdd); + tempRoomsToCheckCollisionsList.Add(roomToAdd); // Add the newly selected room to the list that checks for room collisions. + + // Positioning the newly linked room next to the starting room based on the door's position. + Vector2 newRoomPosition = Vector2.Zero; + switch (needsLinking.DoorPosition) + { + case ("Left"): + newRoomPosition = new Vector2(needsLinking.X - doorToLinkTo.Room.Width, needsLinking.Y - (doorToLinkTo.Y - doorToLinkTo.Room.Y)); + break; + case ("Right"): + newRoomPosition = new Vector2(needsLinking.X + needsLinking.Width, needsLinking.Y - (doorToLinkTo.Y - doorToLinkTo.Room.Y)); + break; + case ("Top"): + newRoomPosition = new Vector2(needsLinking.X - (doorToLinkTo.X - doorToLinkTo.Room.X), needsLinking.Y - doorToLinkTo.Room.Height); + break; + case ("Bottom"): + newRoomPosition = new Vector2(needsLinking.X - (doorToLinkTo.X - doorToLinkTo.Room.X), needsLinking.Y + needsLinking.Height); + break; + } + + MoveRoom(roomToAdd, newRoomPosition); + + numRoomsLeftToCreate--; // Reducing the number of rooms that need to be made. + doorsToLink.Remove(needsLinking); // Remove the door that was just linked from the list of doors that need linking. + foreach (DoorObj door in roomToAdd.DoorList) // Add all doors (except the door that is linked to) in the newly created room to the list of doors that need linking. + { + //if (door != doorToLinkTo && door.Room != startingRoom && door.X > 0) // Prevents checking for doors where xPos == 0. + if (door != doorToLinkTo && door.Room != startingRoom && door.X >= m_startingRoom.Width) // Prevents the creation of rooms above the starting room. + doorsToLink.Add(door); + // else + // Console.WriteLine("this should be called"); + } + + // And finally what is perhaps the most important part, set the Attached flag to each door to true so that there is a way to know if this door is connected to another door. + doorToLinkTo.Attached = true; + needsLinking.Attached = true; + } + } + + //CloseRemainingDoors(roomList); //This is called in the level so that other levels can be added to the room at a later date. + //Console.WriteLine("Rooms created: " + roomList.Count); + //Console.Write("{ "); + //foreach (RoomObj room in roomList) + // Console.Write(room.PoolIndex + " "); + //Console.WriteLine("}"); + + if (secretRoomsNeeded != 0) + Console.WriteLine("WARNING: Only " + (secretRoomTotal - secretRoomsNeeded) + " secret rooms of " + secretRoomTotal + " creation attempts were successful"); + if (bonusRoomsNeeded != 0) + Console.WriteLine("WARNING: Only " + (bonusRoomTotal - bonusRoomsNeeded) + " secret rooms of " + bonusRoomTotal + " creation attempts were successful"); + + return roomList; + } + + private static List FindSuitableDoors(DoorObj doorToCheck, int roomWidth, int roomHeight, List roomList, GameTypes.LevelType levelType, bool findRoomsWithMoreDoors) + { + List suitableDoorList = new List(); + string doorPositionToCheck = GetOppositeDoorPosition(doorToCheck.DoorPosition); + + for (int i = 1; i <= roomWidth; i++) + { + for (int k = 1; k <= roomHeight; k++) + { + List gameRoomList = LevelBuilder2.GetRoomList(i, k, levelType); + foreach (RoomObj room in gameRoomList) + { + bool allowRoom = false; // A check to see if this room is allowed in the pool of rooms to check. Based on level type. + if (findRoomsWithMoreDoors == false || (findRoomsWithMoreDoors == true && room.DoorList.Count > 1)) // If findRoomsWithMoreDoors == true, it will only add rooms with more than 1 door (no dead ends). + { + allowRoom = true; + } + + if (allowRoom == true) + { + foreach (DoorObj door in room.DoorList) + { + if (door.DoorPosition == doorPositionToCheck) + { + bool collisionFound = CheckForRoomCollision(doorToCheck, roomList, door); + + if (collisionFound == false && suitableDoorList.Contains(door) == false) + suitableDoorList.Add(door); + } + } + } + } + } + } + + // Appending the DLC rooms. + List dlcRoomList = GetSequencedDLCRoomList(levelType); + foreach (RoomObj room in dlcRoomList) + { + bool allowRoom = false; // A check to see if this room is allowed in the pool of rooms to check. Based on level type. + if (findRoomsWithMoreDoors == false || (findRoomsWithMoreDoors == true && room.DoorList.Count > 1)) // If findRoomsWithMoreDoors == true, it will only add rooms with more than 1 door (no dead ends). + { + allowRoom = true; + } + + if (allowRoom == true) + { + foreach (DoorObj door in room.DoorList) + { + if (door.DoorPosition == doorPositionToCheck) + { + bool collisionFound = CheckForRoomCollision(doorToCheck, roomList, door); + + if (collisionFound == false && suitableDoorList.Contains(door) == false) + suitableDoorList.Add(door); + } + } + } + } + + return suitableDoorList; + } + + // Same as method above, except simpler. Finds a suitable list of doors from the provided room list. Used for adding secret and bonus rooms. + private static List FindSuitableDoors(DoorObj doorToCheck, List roomList, List roomCollisionList) + { + List suitableDoorList = new List(); + string doorPositionToCheck = GetOppositeDoorPosition(doorToCheck.DoorPosition); + + foreach (RoomObj room in roomList) + { + // Do not add diary rooms to the procedural generation if you have unlocked all the diaries. + if ((Game.PlayerStats.DiaryEntry >= LevelEV.TOTAL_JOURNAL_ENTRIES - 1) && room.Name == "Bonus" && room.Tag == BonusRoomTypes.Diary.ToString()) + continue; + + foreach (DoorObj door in room.DoorList) + { + if (door.DoorPosition == doorPositionToCheck) + { + bool collisionFound = CheckForRoomCollision(doorToCheck, roomCollisionList, door); + + if (collisionFound == false && suitableDoorList.Contains(door) == false) + suitableDoorList.Add(door); + } + } + } + return suitableDoorList; + } + + private static void RemoveDoorFromRoom(DoorObj doorToRemove) + { + //Add a wall to the room where the door is and remove the door, effectively closing it. + RoomObj roomToCloseDoor = doorToRemove.Room; + + TerrainObj doorTerrain = new TerrainObj(doorToRemove.Width, doorToRemove.Height); + doorTerrain.AddCollisionBox(0, 0, doorTerrain.Width, doorTerrain.Height, Consts.TERRAIN_HITBOX); + doorTerrain.AddCollisionBox(0, 0, doorTerrain.Width, doorTerrain.Height, Consts.BODY_HITBOX); + doorTerrain.Position = doorToRemove.Position; + roomToCloseDoor.TerrainObjList.Add(doorTerrain); + + // Add the newly created wall's borders. + BorderObj borderObj = new BorderObj(); + borderObj.Position = doorTerrain.Position; + borderObj.SetWidth(doorTerrain.Width); + borderObj.SetHeight(doorTerrain.Height); + + switch (doorToRemove.DoorPosition) + { + case ("Left"): + borderObj.BorderRight = true; + break; + case ("Right"): + borderObj.BorderLeft = true; + break; + case ("Top"): + borderObj.BorderBottom = true; + break; + case ("Bottom"): + borderObj.BorderTop = true; + break; + } + roomToCloseDoor.BorderList.Add(borderObj); + + roomToCloseDoor.DoorList.Remove(doorToRemove); + doorToRemove.Dispose(); + } + + public static void CloseRemainingDoors(List roomList) + { + List doorList = new List(); + List allDoorList = new List(); + + foreach (RoomObj room in roomList) + { + foreach (DoorObj door in room.DoorList) + { + if (door.DoorPosition != "None") + { + allDoorList.Add(door); + if (door.Attached == false) + doorList.Add(door); + } + } + } + + foreach (DoorObj firstDoor in doorList) + { + bool removeDoor = true; + + foreach (DoorObj secondDoor in allDoorList) + { + if (firstDoor != secondDoor) + { + switch (firstDoor.DoorPosition) + { + case ("Left"): + if (secondDoor.X < firstDoor.X && CollisionMath.Intersects(new Rectangle((int)(firstDoor.X - 5), (int)(firstDoor.Y), firstDoor.Width, firstDoor.Height), secondDoor.Bounds)) + removeDoor = false; + break; + case ("Right"): + if (secondDoor.X > firstDoor.X && CollisionMath.Intersects(new Rectangle((int)(firstDoor.X + 5), (int)(firstDoor.Y), firstDoor.Width, firstDoor.Height), secondDoor.Bounds)) + removeDoor = false; + break; + case ("Top"): + if (secondDoor.Y < firstDoor.Y && CollisionMath.Intersects(new Rectangle((int)(firstDoor.X), (int)(firstDoor.Y - 5), firstDoor.Width, firstDoor.Height), secondDoor.Bounds)) + removeDoor = false; + break; + case ("Bottom"): + if (secondDoor.Y > firstDoor.Y && CollisionMath.Intersects(new Rectangle((int)(firstDoor.X - 5), (int)(firstDoor.Y + 5), firstDoor.Width, firstDoor.Height), secondDoor.Bounds)) + removeDoor = false; + break; + case ("None"): + removeDoor = false; + break; + } + } + } + + if (removeDoor == true) + RemoveDoorFromRoom(firstDoor); + else + firstDoor.Attached = true; + } + } + + public static void AddDoorBorders(List roomList) + { + foreach (RoomObj room in roomList) + { + foreach (DoorObj door in room.DoorList) + { + // Code for attaching borders to the doors. + switch (door.DoorPosition) + { + case ("Left"): + case ("Right"): + BorderObj bottomBorder = new BorderObj(); + bottomBorder.Position = new Vector2(door.Room.X + (door.X - door.Room.X), door.Room.Y + (door.Y - door.Room.Y) - 60); // -60 because a grid tile is 60 large. + bottomBorder.SetWidth(door.Width); + bottomBorder.SetHeight(60); + bottomBorder.BorderBottom = true; + door.Room.BorderList.Add(bottomBorder); + + BorderObj topBorder = new BorderObj(); + topBorder.Position = new Vector2(door.Room.X + (door.X - door.Room.X), door.Room.Y + (door.Y - door.Room.Y) + door.Height); + topBorder.SetWidth(door.Width); + topBorder.SetHeight(60); + topBorder.BorderTop = true; + door.Room.BorderList.Add(topBorder); + break; + case ("Top"): + case ("Bottom"): + int yOffset = 0; + //if (door.DoorPosition == "Bottom") + //yOffset = 30; + + BorderObj rightBorder = new BorderObj(); + rightBorder.Position = new Vector2(door.Room.X + (door.X - door.Room.X) + door.Width, door.Room.Y + (door.Y - door.Room.Y) + yOffset); + rightBorder.SetWidth(60); + rightBorder.SetHeight(door.Height); + rightBorder.BorderLeft = true; + door.Room.BorderList.Add(rightBorder); + + BorderObj leftBorder = new BorderObj(); + leftBorder.Position = new Vector2(door.Room.X + (door.X - door.Room.X) - 60, door.Room.Y + (door.Y - door.Room.Y) + yOffset); // +30 because bottom doors have top collide platforms. + leftBorder.SetWidth(60); + leftBorder.SetHeight(door.Height); + leftBorder.BorderRight = true; + door.Room.BorderList.Add(leftBorder); + break; + } + } + } + } + + //1. Search all the rooms, and find the lowest room with an available door. Available doors are all doors that are not the opposite of doorPositionWanted. + //2. Add a linker room to that door. + //3. Keep only the door that is connecting the room and the linker room and the doorPositionWanted door open. + //4. Return the doorPositionWanted door of the linker room. + //NOTE: furthestRoomDirection is the furthest room you want to find in a specific direction. + // doorPositionWanted is the door position that should be returned when the room is found and linker room is added. + public static DoorObj FindFurthestDoor(List roomList, string furthestRoomDirection, string doorPositionWanted, bool addLinkerRoom, bool castleOnly) + { + string oppositeOfDoorWanted = GetOppositeDoorPosition(doorPositionWanted); + + RoomObj startingRoom = roomList[0]; + float furthestDistance = -10; + RoomObj furthestRoom = null; + DoorObj doorToReturn = null; + DoorObj doorToLinkTo = null; // Only used if doorToReturn is null at the end. + + foreach (RoomObj room in roomList) + { + if (room != startingRoom && ((room.LevelType == GameTypes.LevelType.CASTLE && castleOnly == true) || castleOnly == false)) + { + float distance = 0; + switch (furthestRoomDirection) + { + case ("Right"): + distance = room.X - startingRoom.X; // Furthest room to the right. + break; + case ("Left"): + distance = startingRoom.X - room.X; // Leftmost room. + break; + case ("Top"): + distance = startingRoom.Y - room.Y; // Highest room. + break; + case ("Bottom"): + distance = room.Y - startingRoom.Y; // Lowest room. + break; + } + + if (distance >= furthestDistance) // Will find rooms the same distance away but will not override doorToReturn if one is found. + { + if (doorToReturn == null || distance > furthestDistance) + { + doorToReturn = null; + foreach (DoorObj door in room.DoorList) + { + if (door.DoorPosition != "None") + { + if (door.DoorPosition == doorPositionWanted) + { + bool addRoom = true; + foreach (RoomObj collidingRoom in roomList) + { + if (collidingRoom != door.Room && CollisionMath.Intersects(new Rectangle((int)collidingRoom.X - 10, (int)collidingRoom.Y - 10, collidingRoom.Width + 20, collidingRoom.Height + 20), door.Bounds)) + { + addRoom = false; + break; + } + } + + if (addRoom == true) + { + //doorToReturn = door; + doorToLinkTo = door; // Comment this and uncomment above if you don't want to force linker rooms. + furthestDistance = distance; + furthestRoom = room; + break; + } + } + else if (door.DoorPosition != oppositeOfDoorWanted) + { + bool addRoom = true; + foreach (RoomObj collidingRoom in roomList) + { + if (collidingRoom != door.Room && CollisionMath.Intersects(new Rectangle((int)collidingRoom.X - 10, (int)collidingRoom.Y - 10, collidingRoom.Width + 20, collidingRoom.Height + 20), door.Bounds)) + { + addRoom = false; + break; + } + } + + if (addRoom == true) + { + furthestDistance = distance; + furthestRoom = room; + doorToLinkTo = door; + break; + } + } + } + } + } + } + } + } + + if (doorToLinkTo == null) + { + Console.WriteLine("Could not find suitable furthest door. That's a problem"); + return null; + } + + if (addLinkerRoom == true) + return AddLinkerToRoom(roomList, doorToLinkTo, doorPositionWanted); + else + return doorToLinkTo; + } + + public static DoorObj AddLinkerToRoom(List roomList, DoorObj needsLinking, string doorPositionWanted) + { + DoorObj doorToReturn = null; + RoomObj linkerRoom = null; + switch (needsLinking.Room.LevelType) + { + case (GameTypes.LevelType.CASTLE): + linkerRoom = m_linkerCastleRoom.Clone() as RoomObj; + break; + case (GameTypes.LevelType.DUNGEON): + linkerRoom = m_linkerDungeonRoom.Clone() as RoomObj; + break; + case (GameTypes.LevelType.TOWER): + linkerRoom = m_linkerTowerRoom.Clone() as RoomObj; + break; + case (GameTypes.LevelType.GARDEN): + linkerRoom = m_linkerGardenRoom.Clone() as RoomObj; + break; + } + + linkerRoom.TextureColor = needsLinking.Room.TextureColor; + + DoorObj doorToLinkTo = null; + string doorToLinkToPosition = GetOppositeDoorPosition(needsLinking.DoorPosition); + foreach (DoorObj door in linkerRoom.DoorList) + { + if (door.DoorPosition == doorToLinkToPosition) + { + doorToLinkTo = door; + break; + } + } + + // Positioning the newly linked room next to the starting room based on the door's position. + Vector2 newRoomPosition = Vector2.Zero; + switch (needsLinking.DoorPosition) + { + case ("Left"): + newRoomPosition = new Vector2(needsLinking.X - doorToLinkTo.Room.Width, needsLinking.Y - (doorToLinkTo.Y - doorToLinkTo.Room.Y)); + break; + case ("Right"): + newRoomPosition = new Vector2(needsLinking.X + needsLinking.Width, needsLinking.Y - (doorToLinkTo.Y - doorToLinkTo.Room.Y)); + break; + case ("Top"): + newRoomPosition = new Vector2(needsLinking.X - (doorToLinkTo.X - doorToLinkTo.Room.X), needsLinking.Y - doorToLinkTo.Room.Height); + break; + case ("Bottom"): + newRoomPosition = new Vector2(needsLinking.X - (doorToLinkTo.X - doorToLinkTo.Room.X), needsLinking.Y + needsLinking.Height); + break; + } + + MoveRoom(linkerRoom, newRoomPosition); + + needsLinking.Attached = true; + doorToLinkTo.Attached = true; + + for (int i = 0; i < linkerRoom.DoorList.Count; i++) + { + DoorObj door = linkerRoom.DoorList[i]; + + if (door.DoorPosition == doorPositionWanted) + doorToReturn = door; + //else if (door.DoorPosition != doorPositionWanted && door.Attached == false) + //{ + // RemoveDoorFromRoom(door); + // i--; + //} + } + + linkerRoom.LevelType = needsLinking.Room.LevelType; + roomList.Add(linkerRoom); + return doorToReturn; + } + + private static bool hasTopDoor = false; + private static bool hasBottomDoor = false; + private static bool hasLeftDoor = false; + private static bool hasRightDoor = false; + + private static bool hasTopLeftDoor = false; + private static bool hasTopRightDoor = false; + private static bool hasBottomLeftDoor = false; + private static bool hasBottomRightDoor = false; + private static bool hasRightTopDoor = false; + private static bool hasRightBottomDoor = false; + private static bool hasLeftTopDoor = false; + private static bool hasLeftBottomDoor = false; + + public static void AddRemoveExtraObjects(List roomList) + { + foreach (RoomObj room in roomList) + { + hasTopDoor = false; + hasBottomDoor = false; + hasLeftDoor = false; + hasRightDoor = false; + + hasTopLeftDoor = false; + hasTopRightDoor = false; + hasBottomLeftDoor = false; + hasBottomRightDoor = false; + hasRightTopDoor = false; + hasRightBottomDoor = false; + hasLeftTopDoor = false; + hasLeftBottomDoor = false; + + foreach (DoorObj door in room.DoorList) + { + switch (door.DoorPosition) + { + case ("Top"): + hasTopDoor = true; + if (door.X - room.X == 540) + hasTopLeftDoor = true; + if (room.Bounds.Right - door.X == 780) + hasTopRightDoor = true; + break; + case ("Bottom"): + hasBottomDoor = true; + if (door.X - room.X == 540) + hasBottomLeftDoor = true; + if (room.Bounds.Right - door.X == 780) + hasBottomRightDoor = true; + break; + case ("Left"): + hasLeftDoor = true; + if (door.Y - room.Y == 240) + hasLeftTopDoor = true; + if (room.Bounds.Bottom - door.Y == 480) + hasLeftBottomDoor = true; + break; + case ("Right"): + hasRightDoor = true; + if (door.Y - room.Y == 240) + hasRightTopDoor = true; + if (room.Bounds.Bottom - door.Y == 480) + hasRightBottomDoor = true; + break; + } + } + RemoveFromListHelper(room.TerrainObjList); + RemoveFromListHelper(room.GameObjList); + RemoveFromListHelper(room.EnemyList); + RemoveFromListHelper(room.BorderList); + } + } + + private static void RemoveFromListHelper(List list) + { + for (int i = 0; i < list.Count; i++) + { + string name = (list[i] as GameObj).Name; + if (name != null) + { + //if ((hasTopDoor == false && name.IndexOf("Top") != -1 && name.IndexOf("!Top") == -1) || (hasTopDoor == true && name.IndexOf("!Top") != -1)) + if (((hasTopLeftDoor == false && name.IndexOf("TopLeft") != -1 && name.IndexOf("!TopLeft") == -1) || (hasTopLeftDoor == true && name.IndexOf("!TopLeft") != -1)) || + ((hasTopRightDoor == false && name.IndexOf("TopRight") != -1 && name.IndexOf("!TopRight") == -1) || (hasTopRightDoor == true && name.IndexOf("!TopRight") != -1)) || + ((hasTopDoor == false && name.IndexOf("Top") != -1 && name.IndexOf("!Top") == -1 && name.Length == 3) || (hasTopDoor == true && name.IndexOf("!Top") != -1 && name.Length == 4))) + { + list.Remove(list[i]); + i--; + } + + //if ((hasBottomDoor == false && name.IndexOf("Bottom") != -1 && name.IndexOf("!Bottom") == -1) || (hasBottomDoor == true && name.IndexOf("!Bottom") != -1)) + if (((hasBottomLeftDoor == false && name.IndexOf("BottomLeft") != -1 && name.IndexOf("!BottomLeft") == -1) || (hasBottomLeftDoor == true && name.IndexOf("!BottomLeft") != -1)) || + ((hasBottomRightDoor == false && name.IndexOf("BottomRight") != -1 && name.IndexOf("!BottomRight") == -1) || (hasBottomRightDoor == true && name.IndexOf("!BottomRight") != -1)) || + ((hasBottomDoor == false && name.IndexOf("Bottom") != -1 && name.IndexOf("!Bottom") == -1 && name.Length == 6) || (hasBottomDoor == true && name.IndexOf("!Bottom") != -1 && name.Length == 7))) + { + list.Remove(list[i]); + i--; + } + + //if ((hasLeftDoor == false && name.IndexOf("Left") != -1 && name.IndexOf("!Left") == -1) || (hasLeftDoor == true && name.IndexOf("!Left") != -1)) + if (((hasLeftTopDoor == false && name.IndexOf("LeftTop") != -1 && name.IndexOf("!LeftTop") == -1) || (hasLeftTopDoor == true && name.IndexOf("!LeftTop") != -1)) || + ((hasLeftBottomDoor == false && name.IndexOf("LeftBottom") != -1 && name.IndexOf("!LeftBottom") == -1) || (hasLeftBottomDoor == true && name.IndexOf("!LeftBottom") != -1)) || + ((hasLeftDoor == false && name.IndexOf("Left") != -1 && name.IndexOf("!Left") == -1 && name.Length == 4) || (hasLeftDoor == true && name.IndexOf("!Left") != -1 && name.Length == 5))) + { + list.Remove(list[i]); + i--; + } + + //if ((hasRightDoor == false && name.IndexOf("Right") != -1 && name.IndexOf("!Right") == -1) || (hasRightDoor == true && name.IndexOf("!Right") != -1)) + if (((hasRightTopDoor == false && name.IndexOf("RightTop") != -1 && name.IndexOf("!RightTop") == -1) || (hasRightTopDoor == true && name.IndexOf("!RightTop") != -1)) || + ((hasRightBottomDoor == false && name.IndexOf("RightBottom") != -1 && name.IndexOf("!RightBottom") == -1) || (hasRightBottomDoor == true && name.IndexOf("!RightBottom") != -1)) || + ((hasRightDoor == false && name.IndexOf("Right") != -1 && name.IndexOf("!Right") == -1 && name.Length == 5) || (hasRightDoor == true && name.IndexOf("!Right") != -1 && name.Length == 6))) + { + list.Remove(list[i]); + i--; + } + } + } + } + + + public static void AddProceduralEnemies(List roomList) + { + Vector2 startingRoomPos = roomList[0].Position; + + foreach (RoomObj room in roomList) + { + // Setting the pool of the types of the enemies the room can select from. + byte[] enemyPool = null; + byte[] enemyDifficultyPool = null; + switch (room.LevelType) + { + default: + case (GameTypes.LevelType.CASTLE): + enemyPool = LevelEV.CASTLE_ENEMY_LIST; + enemyDifficultyPool = LevelEV.CASTLE_ENEMY_DIFFICULTY_LIST; + break; + case (GameTypes.LevelType.GARDEN): + enemyPool = LevelEV.GARDEN_ENEMY_LIST; + enemyDifficultyPool = LevelEV.GARDEN_ENEMY_DIFFICULTY_LIST; + break; + case (GameTypes.LevelType.TOWER): + enemyPool = LevelEV.TOWER_ENEMY_LIST; + enemyDifficultyPool = LevelEV.TOWER_ENEMY_DIFFICULTY_LIST; + break; + case (GameTypes.LevelType.DUNGEON): + enemyPool = LevelEV.DUNGEON_ENEMY_LIST; + enemyDifficultyPool = LevelEV.DUNGEON_ENEMY_DIFFICULTY_LIST; + break; + } + + if (enemyPool.Length != enemyDifficultyPool.Length) + throw new Exception("Cannot create enemy. Enemy pool != enemy difficulty pool - LevelBuilder2.cs - AddProceduralEnemies()"); + + // Selecting the random enemy types for each specific orb colour. + int randomEnemyOrbIndex = CDGMath.RandomInt(0, enemyPool.Length - 1); + int storedEnemyIndex = randomEnemyOrbIndex; + + // Storing red enemy type. + byte redEnemyType = enemyPool[randomEnemyOrbIndex]; + byte redEnemyDifficulty = enemyDifficultyPool[randomEnemyOrbIndex]; + + //Shuffling to get a new enemy type. + while (randomEnemyOrbIndex == storedEnemyIndex) // Code to prevent two different coloured orbs from having the same enemy type. Disabled for now since the castle only has 1 enemy type. + randomEnemyOrbIndex = CDGMath.RandomInt(0, enemyPool.Length - 1); + storedEnemyIndex = randomEnemyOrbIndex; + + // Storing blue enemy type. + byte blueEnemyType = enemyPool[randomEnemyOrbIndex]; + byte blueEnemyDifficulty = enemyDifficultyPool[randomEnemyOrbIndex]; + + // Shuffling to get a new enemy type. + while (randomEnemyOrbIndex == storedEnemyIndex) + randomEnemyOrbIndex = CDGMath.RandomInt(0, enemyPool.Length - 1); + storedEnemyIndex = randomEnemyOrbIndex; + + // Storing green enemy type. + byte greenEnemyType = enemyPool[randomEnemyOrbIndex]; + byte greenEnemyDifficulty = enemyDifficultyPool[randomEnemyOrbIndex]; + + // Shuffling to get a new enemy type. + while (randomEnemyOrbIndex == storedEnemyIndex) + randomEnemyOrbIndex = CDGMath.RandomInt(0, enemyPool.Length - 1); + storedEnemyIndex = randomEnemyOrbIndex; + + // Storing white enemy type. + byte whiteEnemyType = enemyPool[randomEnemyOrbIndex]; + byte whiteEnemyDifficulty = enemyDifficultyPool[randomEnemyOrbIndex]; + + // Shuffling to get a new enemy type. + while (randomEnemyOrbIndex == storedEnemyIndex) + randomEnemyOrbIndex = CDGMath.RandomInt(0, enemyPool.Length - 1); + storedEnemyIndex = randomEnemyOrbIndex; + + // Storing black enemy type. + byte blackEnemyType = enemyPool[randomEnemyOrbIndex]; + byte blackEnemyDifficulty = enemyDifficultyPool[randomEnemyOrbIndex]; + + // Shuffling to get new boss type. No need to prevent two of the same enemy types of appearing. + randomEnemyOrbIndex = CDGMath.RandomInt(0, enemyPool.Length - 1); + // Storing yellow enemy type. + byte yellowEnemyType = enemyPool[randomEnemyOrbIndex]; + while (yellowEnemyType == EnemyType.BouncySpike) // Prevent expert enemy from being bouncy spike + { + randomEnemyOrbIndex = CDGMath.RandomInt(0, enemyPool.Length - 1); + yellowEnemyType = enemyPool[randomEnemyOrbIndex]; + } + + for (int i = 0; i < room.GameObjList.Count; i ++) + { + // Creating a random enemy from an orb in the room. + EnemyOrbObj enemyOrb = room.GameObjList[i] as EnemyOrbObj; + if (enemyOrb != null) + { + //if (CDGMath.RandomInt(1, 100) <= 100) // Currently 100% chance of spawning the enemy. + { + EnemyObj newEnemy = null; + if (enemyOrb.OrbType == 0) // Red orb. + newEnemy = EnemyBuilder.BuildEnemy(redEnemyType, null, null, null, (GameTypes.EnemyDifficulty)redEnemyDifficulty); + else if (enemyOrb.OrbType == 1) // Blue orb. + newEnemy = EnemyBuilder.BuildEnemy(blueEnemyType, null, null, null, (GameTypes.EnemyDifficulty)blueEnemyDifficulty); + else if (enemyOrb.OrbType == 2) // Green orb. + newEnemy = EnemyBuilder.BuildEnemy(greenEnemyType, null, null, null, (GameTypes.EnemyDifficulty)greenEnemyDifficulty); + else if (enemyOrb.OrbType == 3) // White orb. + newEnemy = EnemyBuilder.BuildEnemy(whiteEnemyType, null, null, null, (GameTypes.EnemyDifficulty)whiteEnemyDifficulty); + else if (enemyOrb.OrbType == 4) // Black orb. + newEnemy = EnemyBuilder.BuildEnemy(blackEnemyType, null, null, null, (GameTypes.EnemyDifficulty)blackEnemyDifficulty); + else + newEnemy = EnemyBuilder.BuildEnemy(yellowEnemyType, null, null, null, GameTypes.EnemyDifficulty.EXPERT); // In procedurallevelscreen, expert enemies will be given +10 levels. + + // A check to ensure a forceflying orb selects a flying enemy. + while (enemyOrb.ForceFlying == true && newEnemy.IsWeighted == true) + { + if (newEnemy != null) + newEnemy.Dispose(); + + if (enemyOrb.OrbType == 0) // Red + { + randomEnemyOrbIndex = CDGMath.RandomInt(0, enemyPool.Length - 1); + redEnemyType = enemyPool[randomEnemyOrbIndex]; + redEnemyDifficulty = enemyDifficultyPool[randomEnemyOrbIndex]; + newEnemy = EnemyBuilder.BuildEnemy(redEnemyType, null, null, null, (GameTypes.EnemyDifficulty)redEnemyDifficulty); + } + else if (enemyOrb.OrbType == 1) // Blue + { + randomEnemyOrbIndex = CDGMath.RandomInt(0, enemyPool.Length - 1); + blueEnemyType = enemyPool[randomEnemyOrbIndex]; + blueEnemyDifficulty = enemyDifficultyPool[randomEnemyOrbIndex]; + newEnemy = EnemyBuilder.BuildEnemy(blueEnemyType, null, null, null, (GameTypes.EnemyDifficulty)blueEnemyDifficulty); + } + else if (enemyOrb.OrbType == 2) // Green + { + randomEnemyOrbIndex = CDGMath.RandomInt(0, enemyPool.Length - 1); + greenEnemyType = enemyPool[randomEnemyOrbIndex]; + greenEnemyDifficulty = enemyDifficultyPool[randomEnemyOrbIndex]; + newEnemy = EnemyBuilder.BuildEnemy(greenEnemyType, null, null, null, (GameTypes.EnemyDifficulty)greenEnemyDifficulty); + } + else if (enemyOrb.OrbType == 3) // White + { + randomEnemyOrbIndex = CDGMath.RandomInt(0, enemyPool.Length - 1); + whiteEnemyType = enemyPool[randomEnemyOrbIndex]; + whiteEnemyDifficulty = enemyDifficultyPool[randomEnemyOrbIndex]; + newEnemy = EnemyBuilder.BuildEnemy(whiteEnemyType, null, null, null, (GameTypes.EnemyDifficulty)whiteEnemyDifficulty); + } + else if (enemyOrb.OrbType == 4) // Black + { + randomEnemyOrbIndex = CDGMath.RandomInt(0, enemyPool.Length - 1); + blackEnemyType = enemyPool[randomEnemyOrbIndex]; + blackEnemyDifficulty = enemyDifficultyPool[randomEnemyOrbIndex]; + newEnemy = EnemyBuilder.BuildEnemy(blackEnemyType, null, null, null, (GameTypes.EnemyDifficulty)blackEnemyDifficulty); + } + else // Yellow + { + randomEnemyOrbIndex = CDGMath.RandomInt(0, enemyPool.Length - 1); + yellowEnemyType = enemyPool[randomEnemyOrbIndex]; + newEnemy = EnemyBuilder.BuildEnemy(yellowEnemyType, null, null, null, GameTypes.EnemyDifficulty.EXPERT); + } + } + + newEnemy.Position = enemyOrb.Position; + newEnemy.IsProcedural = true; + room.EnemyList.Add(newEnemy); + } + + // Remove the orb from the list. + room.GameObjList.Remove(enemyOrb); + enemyOrb.Dispose(); + i--; + continue; + } + + // Creating a random enemy for the room. + EnemyTagObj tag = room.GameObjList[i] as EnemyTagObj; + if (tag != null) + { + //if (CDGMath.RandomInt(1, 100) <= 100) // Currently 100% chance of spawning the enemy. + { + int randomEnemyIndex = CDGMath.RandomInt(0, enemyPool.Length - 1); + EnemyObj newEnemy = EnemyBuilder.BuildEnemy(enemyPool[randomEnemyIndex], null, null, null, GameTypes.EnemyDifficulty.BASIC); + newEnemy.Position = tag.Position; + newEnemy.IsProcedural = true; + room.EnemyList.Add(newEnemy); + + // Changing the enemy's level based on its distance from the start of the level. + //float enemyDistanceFromStart = Math.Abs(CDGMath.DistanceBetweenPts(startingRoomPos, newEnemy.Position)); + //newEnemy.Level = (int)Math.Ceiling(enemyDistanceFromStart / 1500); + //Console.WriteLine(newEnemy.Level); + } + + // Remove the extra tag from the list. + room.GameObjList.Remove(tag); + tag.Dispose(); + i--; + continue; + } + } + } + } + + public static void OverrideProceduralEnemies(ProceduralLevelScreen level, byte[] enemyTypeData, byte[] enemyDifficultyData) + { + Console.WriteLine("////////////////// OVERRIDING CREATED ENEMIES. LOADING PRE-CONSTRUCTED ENEMY LIST ////////"); + + //foreach (RoomObj room in level.RoomList) + //{ + // int count = 0; + // foreach (EnemyObj enemy in room.EnemyList) + // { + // if (enemy.IsProcedural == true) + // count++; + // } + // Console.WriteLine(count); + //} + + int indexCounter = 0; + // Store the enemies in a separate array. + foreach (RoomObj room in level.RoomList) + { + //if (room.Name != "Bonus" && room.Name != "Boss") // This shouldn't be necessary since bonus room enemies and boss enemies are not (or should not be) saved. + //if (room.Name != "Boss" && room.Name != "Bonus" && room.Name != "Ending" && room.Name != "Tutorial" && room.Name != "Compass") + { + for (int i = 0; i < room.EnemyList.Count; i++) + { + EnemyObj enemyToOverride = room.EnemyList[i]; + if (enemyToOverride.IsProcedural == true) // Only replace procedural enemies. + { + EnemyObj newEnemy = EnemyBuilder.BuildEnemy(enemyTypeData[indexCounter], level.Player, null, level, GameTypes.EnemyDifficulty.BASIC, true); + newEnemy.IsProcedural = true; + newEnemy.Position = enemyToOverride.Position; + + newEnemy.Level = enemyToOverride.Level; + newEnemy.SetDifficulty((GameTypes.EnemyDifficulty)enemyDifficultyData[indexCounter], false); + //newEnemy.SetDifficulty(enemyToOverride.Difficulty, false); + + room.EnemyList[i].Dispose(); + room.EnemyList[i] = newEnemy; + indexCounter++; + } + } + } + } + + Console.WriteLine("//////////////// PRE-CONSTRUCTED ENEMY LIST LOADED ////////////////"); + } + + public static void AddBottomPlatforms(List roomList) + { + foreach (RoomObj room in roomList) + { + foreach (DoorObj door in room.DoorList) + { + if (door.DoorPosition == "Bottom") + { + TerrainObj bottomPlatform = new TerrainObj(door.Width, door.Height); + bottomPlatform.AddCollisionBox(0, 0, bottomPlatform.Width, bottomPlatform.Height, Consts.TERRAIN_HITBOX); + bottomPlatform.AddCollisionBox(0, 0, bottomPlatform.Width, bottomPlatform.Height, Consts.BODY_HITBOX); + bottomPlatform.Position = door.Position; + bottomPlatform.CollidesBottom = false; + bottomPlatform.CollidesLeft = false; + bottomPlatform.CollidesRight = false; + bottomPlatform.SetHeight(30); // Each grid in the game is 60 pixels. 60/2 = 30. + room.TerrainObjList.Add(bottomPlatform); + + BorderObj border = new BorderObj(); + border.Position = bottomPlatform.Position; + border.SetWidth(bottomPlatform.Width); + border.SetHeight(bottomPlatform.Height); + //border.BorderBottom = true; + border.BorderTop = true; + room.BorderList.Add(border); + } + } + } + } + + public static void AddCompassRoom(List roomList) + { + CompassRoomObj compassRoom = m_compassRoom.Clone() as CompassRoomObj; + MoveRoom(compassRoom, new Vector2(-999999, -999999)); + roomList.Add(compassRoom); + } + + public static ProceduralLevelScreen CreateEndingRoom() + { + ProceduralLevelScreen endingScreen = new ProceduralLevelScreen(); + RoomObj endingRoom = m_endingRoom.Clone() as RoomObj; + MoveRoom(endingRoom, Vector2.Zero); + endingScreen.AddRoom(endingRoom); + AddDoorBorders(endingScreen.RoomList); + AddBottomPlatforms(endingScreen.RoomList); + AddRemoveExtraObjects(endingScreen.RoomList); + AddProceduralEnemies(endingScreen.RoomList); + LinkAllBossEntrances(endingScreen.RoomList); + ConvertBonusRooms(endingScreen.RoomList); + ConvertBossRooms(endingScreen.RoomList); + ConvertChallengeBossRooms(endingScreen.RoomList); + InitializeRooms(endingScreen.RoomList); + + return endingScreen; + } + + public static ProceduralLevelScreen CreateStartingRoom() + { + ProceduralLevelScreen startingRoomScreen = new ProceduralLevelScreen(); + RoomObj startingRoom = m_startingRoom.Clone() as RoomObj; + MoveRoom(startingRoom, Vector2.Zero); + startingRoomScreen.AddRoom(startingRoom); + AddDoorBorders(startingRoomScreen.RoomList); + AddBottomPlatforms(startingRoomScreen.RoomList); + AddRemoveExtraObjects(startingRoomScreen.RoomList); + AddProceduralEnemies(startingRoomScreen.RoomList); + LinkAllBossEntrances(startingRoomScreen.RoomList); + ConvertBonusRooms(startingRoomScreen.RoomList); + ConvertBossRooms(startingRoomScreen.RoomList); + ConvertChallengeBossRooms(startingRoomScreen.RoomList); + InitializeRooms(startingRoomScreen.RoomList); + + return startingRoomScreen; + } + + public static ProceduralLevelScreen CreateTutorialRoom() + { + ProceduralLevelScreen tutorialRoomScreen = new ProceduralLevelScreen(); + + // Adding intro cutscene room. + IntroRoomObj introRoom = new IntroRoomObj(); + introRoom.CopyRoomProperties(m_startingRoom); + introRoom.CopyRoomObjects(m_startingRoom); + MoveRoom(introRoom, Vector2.Zero); + tutorialRoomScreen.AddRoom(introRoom); + Game.ScreenManager.Player.Position = new Vector2(150, 150); + + // Adding tutorial room. + TutorialRoomObj tutorialRoom = m_tutorialRoom.Clone() as TutorialRoomObj; + MoveRoom(tutorialRoom, new Vector2(introRoom.Width, -tutorialRoom.Height + introRoom.Height)); + tutorialRoomScreen.AddRoom(tutorialRoom); + + // Adding throne room. + ThroneRoomObj throneRoom = m_throneRoom.Clone() as ThroneRoomObj; + MoveRoom(throneRoom, new Vector2(-10000,-10000)); + tutorialRoomScreen.AddRoom(throneRoom); + + // Linking tutorial room to throne room. + tutorialRoom.LinkedRoom = throneRoom; + + // Initializing rooms. + AddDoorBorders(tutorialRoomScreen.RoomList); + AddBottomPlatforms(tutorialRoomScreen.RoomList); + AddRemoveExtraObjects(tutorialRoomScreen.RoomList); + AddProceduralEnemies(tutorialRoomScreen.RoomList); + LinkAllBossEntrances(tutorialRoomScreen.RoomList); + ConvertBonusRooms(tutorialRoomScreen.RoomList); + ConvertBossRooms(tutorialRoomScreen.RoomList); + ConvertChallengeBossRooms(tutorialRoomScreen.RoomList); + InitializeRooms(tutorialRoomScreen.RoomList); + + //Game.ScreenManager.Player.Position = new Vector2(2800, 150); + //Game.ScreenManager.Player.Position = new Vector2(2800 + 1500, tutorialRoom.Y + 150); + + return tutorialRoomScreen; + } + + // Creates a level based purely on knowing the room indexes used, and the type of the room. Used for loading maps. + public static ProceduralLevelScreen CreateLevel(Vector4[] roomInfoList, Vector3[] roomColorList) + { + Console.WriteLine("///////////// LOADING PRE-CONSTRUCTED LEVEL //////"); + List sequencedRoomList = SequencedRoomList; + List dlcCastleRoomList = GetSequencedDLCRoomList(GameTypes.LevelType.CASTLE); + List dlcGardenRoomList = GetSequencedDLCRoomList(GameTypes.LevelType.GARDEN); + List dlcTowerRoomList = GetSequencedDLCRoomList(GameTypes.LevelType.TOWER); + List dlcDungeonRoomList = GetSequencedDLCRoomList(GameTypes.LevelType.DUNGEON); + + ProceduralLevelScreen createdLevel = new ProceduralLevelScreen(); + List roomList = new List(); + + int counter = 0; + foreach (Vector4 roomData in roomInfoList) + { + //RoomObj room = sequencedRoomList[(int)roomData.W].Clone() as RoomObj; + + // New logic to load levels from the DLC lists. + RoomObj room = null; + int roomIndex = (int)roomData.W; + if (roomIndex < 10000) // Take a room from the original room list. + room = sequencedRoomList[roomIndex].Clone() as RoomObj; + else if (roomIndex >= 10000 && roomIndex < 20000) // Take a room from the Castle DLC list. + room = dlcCastleRoomList[roomIndex - 10000].Clone() as RoomObj; + else if (roomIndex >= 20000 && roomIndex < 30000) // Take a room from the Garden DLC list. + room = dlcGardenRoomList[roomIndex - 20000].Clone() as RoomObj; + else if (roomIndex >= 30000 && roomIndex < 40000) // Take a room from the Tower DLC list. + room = dlcTowerRoomList[roomIndex - 30000].Clone() as RoomObj; + else // Take a room from the Dungeon DLC list. + room = dlcDungeonRoomList[roomIndex - 40000].Clone() as RoomObj; + + room.LevelType = (GameTypes.LevelType)roomData.X; + MoveRoom(room, new Vector2(roomData.Y, roomData.Z)); + roomList.Add(room); + + room.TextureColor = new Color((byte)roomColorList[counter].X, (byte)roomColorList[counter].Y, (byte)roomColorList[counter].Z); + counter++; + } + createdLevel.AddRooms(roomList); + + // Linking all boss rooms. + CloseRemainingDoors(createdLevel.RoomList); + AddDoorBorders(createdLevel.RoomList); // Must be called after all doors are closed. Adds the borders that are created by doors existing/not existing. + AddBottomPlatforms(createdLevel.RoomList); // Must be called after all doors are closed. + AddRemoveExtraObjects(createdLevel.RoomList); // Adds all the Top/!Top objects. Must be called after all doors are closed, and before enemies are added. + AddProceduralEnemies(createdLevel.RoomList); + LinkAllBossEntrances(createdLevel.RoomList); + ConvertBonusRooms(createdLevel.RoomList); + ConvertBossRooms(createdLevel.RoomList); + ConvertChallengeBossRooms(createdLevel.RoomList); + AddCompassRoom(createdLevel.RoomList); // The last room always has to be the compass room. + InitializeRooms(createdLevel.RoomList); // Initializes any special things for the created rooms, like special door entrances, bosses, etc. + + Console.WriteLine("///////////// PRE-CONSTRUCTED LEVEL LOADED //////"); + + return createdLevel; + } + + public static ProceduralLevelScreen CreateLevel(RoomObj startingRoom = null, params AreaStruct[] areaStructs) + { + if (m_testRoom != null && LevelEV.RUN_TESTROOM == true) + { + Console.WriteLine("OVERRIDING ROOM CREATION. RUNNING TEST ROOM"); + ProceduralLevelScreen debugLevel = new ProceduralLevelScreen(); + RoomObj debugRoom = m_testRoom.Clone() as RoomObj; + if (LevelEV.TESTROOM_REVERSE == true) + debugRoom.Reverse(); + MoveRoom(debugRoom, Vector2.Zero); + debugLevel.AddRoom(debugRoom); + if (LevelEV.CLOSE_TESTROOM_DOORS == true) + CloseRemainingDoors(debugLevel.RoomList); + AddDoorBorders(debugLevel.RoomList); + AddBottomPlatforms(debugLevel.RoomList); + AddRemoveExtraObjects(debugLevel.RoomList); + AddProceduralEnemies(debugLevel.RoomList); + LinkAllBossEntrances(debugLevel.RoomList); + + ConvertBonusRooms(debugLevel.RoomList); + ConvertBossRooms(debugLevel.RoomList); + ConvertChallengeBossRooms(debugLevel.RoomList); + InitializeRooms(debugLevel.RoomList); + + debugLevel.RoomList[0].LevelType = LevelEV.TESTROOM_LEVELTYPE; // A hack for special rooms, since they're set to none level type. + + return debugLevel; + } + + ProceduralLevelScreen createdLevel = new ProceduralLevelScreen(); // Create a blank level. + List masterRoomList = new List(); + + List sequentialStructs= new List(); + List nonSequentialStructs= new List(); + + // Separating the level structs into sequentially attached and non-sequentially attached ones. + foreach (AreaStruct areaStruct in areaStructs) + { + if (areaStruct.LevelType == GameTypes.LevelType.CASTLE || areaStruct.LevelType == GameTypes.LevelType.GARDEN) //TEDDY COMMENT THIS OUT TO DISABLE OUT GARDEN CONNECT RIGHT + sequentialStructs.Add(areaStruct); + else + nonSequentialStructs.Add(areaStruct); + } + + int numSequentialAreas = sequentialStructs.Count; + int numNonSequentialAreas = nonSequentialStructs.Count; + List[] sequentialAreas = new List[numSequentialAreas]; + List[] nonSequentialAreas = new List[numNonSequentialAreas]; + + ///////////// ROOM CREATION STARTS/////////////// + restartAll: + masterRoomList.Clear(); + // Build all the sequentially attached rooms first. + for (int i = 0; i < sequentialStructs.Count; i++) + { + int creationCounter = 0; + restartSequential: + sequentialAreas[i] = null; + AreaStruct areaInfo = sequentialStructs[i]; + int numRooms = CDGMath.RandomInt((int)areaInfo.TotalRooms.X, (int)areaInfo.TotalRooms.Y); + + // Keep recreating the area until the requested number of rooms are built. + DoorObj linkerDoorAdded = null; + bool addedBossRoom = true; + while (sequentialAreas[i] == null || sequentialAreas[i].Count < numRooms || addedBossRoom == false) + { + addedBossRoom = true; + if (areaInfo.BossInArea == true) + addedBossRoom = false; + + if (i == 0) + { + if (startingRoom == null) + sequentialAreas[i] = LevelBuilder2.CreateArea(numRooms, areaInfo, masterRoomList, StartingRoom.Clone() as StartingRoomObj, true); + else + sequentialAreas[i] = LevelBuilder2.CreateArea(numRooms, areaInfo, masterRoomList, startingRoom.Clone() as StartingRoomObj, true); + } + else + { + List masterListCopy = new List(); // Only use a copy in case rooms couldn't be found and this keeps getting added. + masterListCopy.AddRange(masterRoomList); + + linkerDoorAdded = FindFurthestDoor(masterListCopy, "Right", "Right", true, LevelEV.LINK_TO_CASTLE_ONLY); + if (linkerDoorAdded == null) + goto restartAll; // This isn't supposed to be possible. + sequentialAreas[i] = LevelBuilder2.CreateArea(numRooms, areaInfo, masterListCopy, linkerDoorAdded.Room, false); + } + + // Checking to make sure the area has a boss entrance in it. + foreach (RoomObj room in sequentialAreas[i]) + { + if (room.Name == "EntranceBoss") + { + addedBossRoom = true; + break; + } + } + + if (addedBossRoom == false) + Console.WriteLine("Could not find suitable boss room for area. Recreating sequential area."); + else + Console.WriteLine("Created sequential area of size: " + sequentialAreas[i].Count); + + // A safety check. If the sequential rooms cannot be added after 15 attempts, recreate the entire map. + creationCounter++; + if (creationCounter > 15) + { + Console.WriteLine("Could not create non-sequential area after 15 attempts. Recreating entire level."); + goto restartAll; + } + } + if (i != 0) + masterRoomList.Add(linkerDoorAdded.Room); + + // Making sure each area has a top, bottom, and rightmost exit door. If not, recreate sequential area. + if (LevelBuilder2.FindFurthestDoor(sequentialAreas[i], "Right", "Right", false, false) == null + || LevelBuilder2.FindFurthestDoor(sequentialAreas[i], "Top", "Top", false, false) == null + || LevelBuilder2.FindFurthestDoor(sequentialAreas[i], "Bottom", "Bottom", false, false) == null) + { + bool removedLinkedRoom = false; + if (i != 0) + removedLinkedRoom = masterRoomList.Remove(linkerDoorAdded.Room); + else + removedLinkedRoom = true; + Console.WriteLine("Attempting re-creation of sequential area. Linker Room removed: " + removedLinkedRoom); + goto restartSequential; // Didn't want to use gotos, but only way I could think of restarting loop. Goes back to the start of this forloop. + } + else // A sequential area with all exits has been created. Add it to the masterRoomList; + masterRoomList.AddRange(sequentialAreas[i]); + } + + Console.WriteLine("////////// ALL SEQUENTIAL AREAS SUCCESSFULLY ADDED"); + + // Now create all non-sequential areas. + for (int i = 0; i < nonSequentialStructs.Count; i++) + { + int creationCounter = 0; + restartNonSequential: + nonSequentialAreas[i] = null; + AreaStruct areaInfo = nonSequentialStructs[i]; + int numRooms = CDGMath.RandomInt((int)areaInfo.TotalRooms.X, (int)areaInfo.TotalRooms.Y); + string furthestDoorDirection = ""; + switch (areaInfo.LevelType) + { + case (GameTypes.LevelType.TOWER): + furthestDoorDirection = "Top"; + break; + case (GameTypes.LevelType.DUNGEON): + furthestDoorDirection = "Bottom";//"Bottom"; + break; + case (GameTypes.LevelType.GARDEN): + furthestDoorDirection = "Right"; //TEDDY - COMMENTED OUT DUNGEON CONNECT TOP, AND ADDED GARDEN CONNECT TOP + break; + default: + throw new Exception("Could not create non-sequential area of type " + areaInfo.LevelType); + } + + //int creationCounter = 0; + DoorObj linkerDoorAdded = null; + bool addedBossRoom = true; + // Keep recreating the area until the requested number of rooms are built. + while (nonSequentialAreas[i] == null || nonSequentialAreas[i].Count < numRooms || addedBossRoom == false) + { + addedBossRoom = true; + if (areaInfo.BossInArea == true) + addedBossRoom = false; + + List masterListCopy = new List(); // Only use a copy in case rooms couldn't be found and this keeps getting added. + masterListCopy.AddRange(masterRoomList); + + // Finds the furthest door of the previous area, and adds a linker room to it (on a separate list so as not to modify the original room list). + // Creates a new area from the linker room. + linkerDoorAdded = FindFurthestDoor(masterListCopy, furthestDoorDirection, furthestDoorDirection, true, LevelEV.LINK_TO_CASTLE_ONLY); + if (linkerDoorAdded == null) + goto restartAll; // This isn't supposed to be possible. + nonSequentialAreas[i] = LevelBuilder2.CreateArea(numRooms, areaInfo, masterListCopy, linkerDoorAdded.Room, false); + + // A safety check. If the non-sequential rooms cannot be added after 15 attempts, recreate the entire map. + creationCounter++; + if (creationCounter > 15) + { + Console.WriteLine("Could not create non-sequential area after 15 attempts. Recreating entire level."); + goto restartAll; + } + + // Checking to make sure the area has a boss entrance in it. + foreach (RoomObj room in nonSequentialAreas[i]) + { + if (room.Name == "EntranceBoss") + { + addedBossRoom = true; + break; + } + } + + if (addedBossRoom == false) + Console.WriteLine("Could not find suitable boss room for area. Recreating non-sequential area."); + else + Console.WriteLine("Created non-sequential area of size: " + nonSequentialAreas[i].Count); + } + masterRoomList.Add(linkerDoorAdded.Room); + + // Making sure each area has a top, bottom, and rightmost exit door. If not, recreate all sequential areas. + if ((areaInfo.LevelType == GameTypes.LevelType.TOWER && (LevelBuilder2.FindFurthestDoor(nonSequentialAreas[i], "Right", "Right", false, false) == null || + LevelBuilder2.FindFurthestDoor(nonSequentialAreas[i], "Top", "Top", false, false) == null)) || + (areaInfo.LevelType == GameTypes.LevelType.DUNGEON && (LevelBuilder2.FindFurthestDoor(nonSequentialAreas[i], "Right", "Right", false, false) == null || + LevelBuilder2.FindFurthestDoor(nonSequentialAreas[i], "Bottom", "Bottom", false, false) == null))) + { + bool removedLinkedRoom = false; + removedLinkedRoom = masterRoomList.Remove(linkerDoorAdded.Room); + Console.WriteLine("Attempting re-creation of a non-sequential area. Linker Room removed: " + removedLinkedRoom); + goto restartNonSequential; + } + else // A non-sequential area with all exits has been created. Add it to the masterRoomList; + masterRoomList.AddRange(nonSequentialAreas[i]); + } + + Console.WriteLine("////////// ALL NON-SEQUENTIAL AREAS SUCCESSFULLY ADDED"); + + createdLevel.AddRooms(masterRoomList); // Add the rooms to the level. + CloseRemainingDoors(createdLevel.RoomList); + AddDoorBorders(createdLevel.RoomList); // Must be called after all doors are closed. Adds the borders that are created by doors existing/not existing. + AddBottomPlatforms(createdLevel.RoomList); // Must be called after all doors are closed. + AddRemoveExtraObjects(createdLevel.RoomList); // Adds all the Top/!Top objects. Must be called after all doors are closed, and before enemies are added. + AddProceduralEnemies(createdLevel.RoomList); + LinkAllBossEntrances(createdLevel.RoomList); // Links all boss entrances to actual boss rooms. + ConvertBonusRooms(createdLevel.RoomList); + ConvertBossRooms(createdLevel.RoomList); + ConvertChallengeBossRooms(createdLevel.RoomList); + AddCompassRoom(createdLevel.RoomList); // The last room always has to be the compass room. + InitializeRooms(createdLevel.RoomList); // Initializes any special things for the created rooms, like special door entrances, bosses, etc. + + Console.WriteLine("////////// LEVEL CREATION SUCCESSFUL"); + + return createdLevel; + } + + private static void ConvertBonusRooms(List roomList) + { + // flibit didn't like this + // CultureInfo ci = (CultureInfo)CultureInfo.CurrentCulture.Clone(); + // ci.NumberFormat.CurrencyDecimalSeparator = "."; + CultureInfo ci = CultureInfo.InvariantCulture; + + for (int i = 0; i < roomList.Count; i++) + { + RoomObj room = roomList[i]; + if (room.Name == "Bonus") + { + if (room.Tag == "") + room.Tag = "0"; + + RoomObj roomToAdd = null; + + switch (int.Parse(room.Tag, NumberStyles.Any, ci)) + { + case (BonusRoomTypes.PickChest): + roomToAdd = new ChestBonusRoomObj(); + break; + case (BonusRoomTypes.SpecialItem): + roomToAdd = new SpecialItemRoomObj(); + break; + case (BonusRoomTypes.RandomTeleport): + roomToAdd = new RandomTeleportRoomObj(); + break; + case (BonusRoomTypes.SpellSwap): + roomToAdd = new SpellSwapRoomObj(); + break; + case (BonusRoomTypes.VitaChamber): + roomToAdd = new VitaChamberRoomObj(); + break; + case (BonusRoomTypes.Diary): + roomToAdd = new DiaryRoomObj(); + break; + case (BonusRoomTypes.Portrait): + roomToAdd = new PortraitRoomObj(); + break; + case (BonusRoomTypes.CarnivalShoot1): + roomToAdd = new CarnivalShoot1BonusRoom(); + break; + case (BonusRoomTypes.CarnivalShoot2): + roomToAdd = new CarnivalShoot2BonusRoom(); + break; + case(BonusRoomTypes.Arena): + roomToAdd = new ArenaBonusRoom(); + break; + case(BonusRoomTypes.Jukebox): + roomToAdd = new JukeboxBonusRoom(); + break; + } + + if (roomToAdd != null) + { + roomToAdd.CopyRoomProperties(room); + roomToAdd.CopyRoomObjects(room); + roomList.Insert(roomList.IndexOf(room), roomToAdd); + roomList.Remove(room); + } + } + } + } + + private static void ConvertBossRooms(List roomList) + { + // flibit didn't like this + // CultureInfo ci = (CultureInfo)CultureInfo.CurrentCulture.Clone(); + // ci.NumberFormat.CurrencyDecimalSeparator = "."; + CultureInfo ci = CultureInfo.InvariantCulture; + + for (int i = 0; i < roomList.Count; i++) + { + RoomObj room = roomList[i]; + if (room.Name == "Boss") + { + if (room.Tag == "") + room.Tag = "0"; + + RoomObj bossRoom = null; + int bossRoomType = int.Parse(room.Tag, NumberStyles.Any, ci); + + switch (bossRoomType) + { + case (BossRoomType.EyeballBossRoom): + bossRoom = new EyeballBossRoom(); + break; + case (BossRoomType.LastBossRoom): + bossRoom = new LastBossRoom(); + break; + case (BossRoomType.BlobBossRoom): + bossRoom = new BlobBossRoom(); + break; + case (BossRoomType.FairyBossRoom): + bossRoom = new FairyBossRoom(); + break; + case (BossRoomType.FireballBossRoom): + bossRoom = new FireballBossRoom(); + break; + } + + if (bossRoom != null) + { + bossRoom.CopyRoomProperties(room); + bossRoom.CopyRoomObjects(room); + if (bossRoom.LinkedRoom != null) // Adding this so you can test the room without linking it. + { + bossRoom.LinkedRoom = room.LinkedRoom; + bossRoom.LinkedRoom.LinkedRoom = bossRoom; // A roundabout way of relinking the boss entrance room to the newly made eyeball boss. + } + roomList.Insert(roomList.IndexOf(room), bossRoom); + roomList.Remove(room); + } + } + } + } + + private static void ConvertChallengeBossRooms(List roomList) + { + // flibit didn't like this + // CultureInfo ci = (CultureInfo)CultureInfo.CurrentCulture.Clone(); + // ci.NumberFormat.CurrencyDecimalSeparator = "."; + CultureInfo ci = CultureInfo.InvariantCulture; + + for (int i = 0; i < roomList.Count; i++) + { + RoomObj room = roomList[i]; + if (room.Name == "ChallengeBoss") + { + if (room.Tag == "") + room.Tag = "0"; + + RoomObj challengeRoom = null; + int challengeRoomType = int.Parse(room.Tag, NumberStyles.Any, ci); + + switch (challengeRoomType) + { + case (BossRoomType.EyeballBossRoom): + challengeRoom = new EyeballChallengeRoom(); + MoveRoom(challengeRoom, new Vector2(0, 5000000)); + break; + case (BossRoomType.FairyBossRoom): + challengeRoom = new FairyChallengeRoom(); + MoveRoom(challengeRoom, new Vector2(0, -6000000)); + break; + case (BossRoomType.FireballBossRoom): + challengeRoom = new FireballChallengeRoom(); + MoveRoom(challengeRoom, new Vector2(0, -7000000)); + break; + case (BossRoomType.BlobBossRoom): + challengeRoom = new BlobChallengeRoom(); + MoveRoom(challengeRoom, new Vector2(0, -8000000)); + break; + case (BossRoomType.LastBossRoom): + challengeRoom = new LastBossChallengeRoom(); + MoveRoom(challengeRoom, new Vector2(0, -9000000)); + break; + default: + challengeRoom = new EyeballChallengeRoom(); + MoveRoom(challengeRoom, new Vector2(0, -5000000)); + break; + } + + if (challengeRoom != null) + { + Vector2 storedPos = challengeRoom.Position; + challengeRoom.CopyRoomProperties(room); + challengeRoom.CopyRoomObjects(room); + MoveRoom(challengeRoom, storedPos); + if (challengeRoom.LinkedRoom != null) // Adding this so you can test the room without linking it. + { + challengeRoom.LinkedRoom = room.LinkedRoom; + } + roomList.Insert(roomList.IndexOf(room), challengeRoom); + roomList.Remove(room); + } + } + } + } + + + private static void InitializeRooms(List roomList) + { + foreach (RoomObj room in roomList) + room.Initialize(); + } + + private static string GetOppositeDoorPosition(string doorPosition) + { + string doorPosToReturn = ""; + switch (doorPosition) + { + case ("Left"): + doorPosToReturn = "Right"; + break; + case ("Right"): + doorPosToReturn = "Left"; + break; + case ("Top"): + doorPosToReturn = "Bottom"; + break; + case ("Bottom"): + doorPosToReturn = "Top"; + break; + } + return doorPosToReturn; + } + + private static bool CheckForRoomCollision(DoorObj doorToCheck, List roomList, DoorObj otherDoorToCheck) + { + //Code to make sure the room does not collide with other rooms in the list. + Vector2 newRoomPosition = Vector2.Zero; + switch (doorToCheck.DoorPosition) + { + case ("Left"): + newRoomPosition = new Vector2(doorToCheck.Room.X - otherDoorToCheck.Room.Width, doorToCheck.Y - (otherDoorToCheck.Y - otherDoorToCheck.Room.Y)); + break; + case ("Right"): + newRoomPosition = new Vector2(doorToCheck.X + doorToCheck.Width, doorToCheck.Y - (otherDoorToCheck.Y - otherDoorToCheck.Room.Y)); + break; + case ("Top"): + newRoomPosition = new Vector2(doorToCheck.X - (otherDoorToCheck.X - otherDoorToCheck.Room.X), doorToCheck.Y - otherDoorToCheck.Room.Height); + break; + case ("Bottom"): + newRoomPosition = new Vector2(doorToCheck.X - (otherDoorToCheck.X - otherDoorToCheck.Room.X), doorToCheck.Y + doorToCheck.Height); + break; + } + + foreach (RoomObj roomObj in roomList) + { + if (CollisionMath.Intersects(new Rectangle((int)(roomObj.X), (int)(roomObj.Y), roomObj.Width, roomObj.Height), new Rectangle((int)(newRoomPosition.X), (int)(newRoomPosition.Y), otherDoorToCheck.Room.Width, otherDoorToCheck.Room.Height)) + || newRoomPosition.X < 0) // Do not allow rooms be made past xPos = 0. + return true; + } + + return false; + } + + + public static void MoveRoom(RoomObj room, Vector2 newPosition) + { + Vector2 positionShift = room.Position - newPosition; // The amount everything in the room needs to shift by in order to put them in their new position next to the room they are linking to. + //Shifting the room to link to and its contents next to the room that needs linking. + room.Position = newPosition; + foreach (TerrainObj obj in room.TerrainObjList) + obj.Position -= positionShift; + foreach (GameObj obj in room.GameObjList) + obj.Position -= positionShift; + foreach (DoorObj door in room.DoorList) + door.Position -= positionShift; + foreach (EnemyObj enemy in room.EnemyList) + enemy.Position -= positionShift; + foreach (BorderObj border in room.BorderList) + border.Position -= positionShift; + } + + public static void LinkAllBossEntrances(List roomList) + { + Vector2 newRoomPosition = new Vector2(-100000, 0); // This is where all the boss rooms will float in. It must be left of the level so that it doesn't accidentally run into any of the level's rooms. + int maxRoomIndex = m_bossRoomArray.Count - 1; + + RoomObj bossRoom = null; + List bossRoomsToAdd = new List(); + + List challengeRoomsToAdd = new List(); + RoomObj challengeRoom = null; + + foreach (RoomObj room in roomList) + { + byte bossRoomType = 0; + switch(room.LevelType) + { + case (GameTypes.LevelType.CASTLE): + bossRoomType = LevelEV.CASTLE_BOSS_ROOM; + break; + case(GameTypes.LevelType.TOWER): + bossRoomType = LevelEV.TOWER_BOSS_ROOM; + break; + case(GameTypes.LevelType.DUNGEON): + bossRoomType = LevelEV.DUNGEON_BOSS_ROOM; + break; + case(GameTypes.LevelType.GARDEN): + bossRoomType = LevelEV.GARDEN_BOSS_ROOM; + break; + } + + if (room.Name == "EntranceBoss") + { + bossRoom = GetSpecificBossRoom(bossRoomType); + if (bossRoom != null) + bossRoom = bossRoom.Clone() as RoomObj; + if (bossRoom == null) + bossRoom = GetBossRoom(CDGMath.RandomInt(0, maxRoomIndex)).Clone() as RoomObj; + bossRoom.LevelType = room.LevelType; + MoveRoom(bossRoom, newRoomPosition); + newRoomPosition.X += bossRoom.Width; + room.LinkedRoom = bossRoom; + bossRoom.LinkedRoom = room; + + if (bossRoom != null) + bossRoomsToAdd.Add(bossRoom); + else + throw new Exception("Could not find a boss room for the boss entrance. This should NOT be possible. LinkAllBossEntrances()"); + + // Now linking challenge boss rooms + challengeRoom = GetChallengeRoom(bossRoomType); + if (challengeRoom != null) + { + challengeRoom = challengeRoom.Clone() as RoomObj; + challengeRoom.LevelType = room.LevelType; + challengeRoom.LinkedRoom = room; + + challengeRoomsToAdd.Add(challengeRoom); + } + } + else if (room.Name == "CastleEntrance") // Creating the special Last boss room that links to tutorial room. + { + // Creating tutorial room and boss room. + TutorialRoomObj tutorialRoom = m_tutorialRoom.Clone() as TutorialRoomObj; + bossRoom = GetSpecificBossRoom(BossRoomType.LastBossRoom).Clone() as RoomObj; + + // Moving tutorial room and boss room to proper positions. + MoveRoom(tutorialRoom, new Vector2(100000, -100000)); // Special positioning for the last boss room. Necessary since CastleEntranceRoomObj blocks you from going past 0. + MoveRoom(bossRoom, new Vector2(150000, -100000)); + + // Linking castle entrance to tutorial room. + room.LinkedRoom = tutorialRoom; + + // Linking tutorial room to boss room. + tutorialRoom.LinkedRoom = bossRoom; + bossRoom.LinkedRoom = tutorialRoom; + + if (bossRoom != null) + { + bossRoomsToAdd.Add(bossRoom); + bossRoomsToAdd.Add(tutorialRoom); + } + else + throw new Exception("Could not find a boss room for the boss entrance. This should NOT be possible. LinkAllBossEntrances()"); + } + } + + // Adding the Last boss challenge room. + challengeRoom = GetChallengeRoom(BossRoomType.LastBossRoom); + if (challengeRoom != null) + { + challengeRoom = challengeRoom.Clone() as RoomObj; + challengeRoom.LevelType = GameTypes.LevelType.CASTLE; + challengeRoom.LinkedRoom = null; + + challengeRoomsToAdd.Add(challengeRoom); + } + + //Console.WriteLine("Adding boss rooms to level"); + roomList.AddRange(bossRoomsToAdd); + roomList.AddRange(challengeRoomsToAdd); + } + + public static List GetRoomList(int roomWidth, int roomHeight, GameTypes.LevelType levelType) + { + return GetLevelTypeRoomArray(levelType)[roomWidth - 1, roomHeight - 1]; + } + + public static RoomObj StartingRoom + { + get { return m_startingRoom; } + } + + public static RoomObj GetBossRoom(int index) + { + return m_bossRoomArray[index]; + } + + public static RoomObj GetSpecificBossRoom(byte bossRoomType) + { + foreach (RoomObj room in m_bossRoomArray) + { + if (room.Tag != "" && byte.Parse(room.Tag) == bossRoomType) + return room; + } + return null; + } + + public static RoomObj GetChallengeRoom(byte bossRoomType) + { + foreach (RoomObj room in m_challengeRoomArray) + { + if (room.Tag != "" && byte.Parse(room.Tag) == bossRoomType) + return room; + } + return null; + } + + public static RoomObj GetChallengeBossRoomFromRoomList(GameTypes.LevelType levelType, List roomList) + { + foreach (RoomObj room in roomList) + { + if (room.Name == "ChallengeBoss") + { + if (room.LevelType == levelType) + return room; + } + } + return null; + } + + public static List[,] GetLevelTypeRoomArray(GameTypes.LevelType levelType) + { + switch (levelType) + { + default: + case (GameTypes.LevelType.NONE): + throw new Exception("Cannot create level of type NONE"); + case (GameTypes.LevelType.CASTLE): + return m_castleRoomArray; + case (GameTypes.LevelType.GARDEN): + return m_gardenRoomArray; + case (GameTypes.LevelType.TOWER): + return m_towerRoomArray; + case (GameTypes.LevelType.DUNGEON): + return m_dungeonRoomArray; + } + } + + public static void IndexRoomList() + { + int index = 0; + foreach (RoomObj room in SequencedRoomList) + { + room.PoolIndex = index; + index++; + } + + // Storing DLC maps. For easy differentiating (for extensibility in the future): + // 10000 is for Castle areas. + // 20000 is for Garden areas. + // 30000 is for Tower areas. + // 40000 is for Dungeon areas. + + index = 10000; + List roomList = GetSequencedDLCRoomList(GameTypes.LevelType.CASTLE); + foreach (RoomObj room in roomList) + { + room.PoolIndex = index; + index++; + } + + index = 20000; + roomList = GetSequencedDLCRoomList(GameTypes.LevelType.GARDEN); + foreach (RoomObj room in roomList) + { + room.PoolIndex = index; + index++; + } + + index = 30000; + roomList = GetSequencedDLCRoomList(GameTypes.LevelType.TOWER); + foreach (RoomObj room in roomList) + { + room.PoolIndex = index; + index++; + } + + index = 40000; + roomList = GetSequencedDLCRoomList(GameTypes.LevelType.DUNGEON); + foreach (RoomObj room in roomList) + { + room.PoolIndex = index; + index++; + } + } + + public static List SequencedRoomList + { + get + { + List sequencedRoomList = new List(); + + // Add the special rooms first. + sequencedRoomList.Add(m_startingRoom); + + sequencedRoomList.Add(m_linkerCastleRoom); + sequencedRoomList.Add(m_linkerTowerRoom); + sequencedRoomList.Add(m_linkerDungeonRoom); + sequencedRoomList.Add(m_linkerGardenRoom); + + sequencedRoomList.Add(m_bossCastleEntranceRoom); + sequencedRoomList.Add(m_bossTowerEntranceRoom); + sequencedRoomList.Add(m_bossDungeonEntranceRoom); + sequencedRoomList.Add(m_bossGardenEntranceRoom); + + sequencedRoomList.Add(m_castleEntranceRoom); + + // Add the normal rooms. + foreach (List roomList in m_castleRoomArray) + sequencedRoomList.AddRange(roomList); + foreach (List roomList in m_dungeonRoomArray) + sequencedRoomList.AddRange(roomList); + foreach (List roomList in m_towerRoomArray) + sequencedRoomList.AddRange(roomList); + foreach (List roomList in m_gardenRoomArray) + sequencedRoomList.AddRange(roomList); + + // Add the secret rooms. + sequencedRoomList.AddRange(m_secretCastleRoomArray); + sequencedRoomList.AddRange(m_secretTowerRoomArray); + sequencedRoomList.AddRange(m_secretDungeonRoomArray); + sequencedRoomList.AddRange(m_secretGardenRoomArray); + + // Add the bonus rooms. + sequencedRoomList.AddRange(m_bonusCastleRoomArray); + sequencedRoomList.AddRange(m_bonusTowerRoomArray); + sequencedRoomList.AddRange(m_bonusDungeonRoomArray); + sequencedRoomList.AddRange(m_bonusGardenRoomArray); + + // Add the boss room array. + sequencedRoomList.AddRange(m_bossRoomArray); + + // Add the challenge room array. + sequencedRoomList.AddRange(m_challengeRoomArray); + + //Add the compass room. + sequencedRoomList.Add(m_compassRoom); + + for (int i = 0; i < sequencedRoomList.Count; i++) + { + if (sequencedRoomList[i] == null) + { + Console.WriteLine("WARNING: Null room found at index " + i + " of sequencedRoomList. Removing room..."); + sequencedRoomList.RemoveAt(i); + i--; + } + } + return sequencedRoomList; + } + } + + // Only for DLC rooms. + // The logic is different from Non-DLC rooms to allow for easily adding more rooms in the future. + public static List GetSequencedDLCRoomList(GameTypes.LevelType levelType) + { + switch (levelType) + { + case GameTypes.LevelType.CASTLE: + return m_dlcCastleRoomArray; + case GameTypes.LevelType.DUNGEON: + return m_dlcDungeonRoomArray; + case GameTypes.LevelType.GARDEN: + return m_dlcGardenRoomArray; + case GameTypes.LevelType.TOWER: + return m_dlcTowerRoomArray; + } + return null; + } + + public static void RefreshTextObjs() + { + // TODO, empty for now + //if (m_tutorialRoom != null) m_tutorialRoom.RefrestTextObjs(); + } + } + + public struct AreaStruct + { + public string Name; + public GameTypes.LevelType LevelType; + public Vector2 EnemyLevel; + public Vector2 TotalRooms; + public Vector2 BonusRooms; + public Vector2 SecretRooms; + public int BossLevel; + public int EnemyLevelScale; + public bool BossInArea; + public bool IsFinalArea; + public Color Color; + public Color MapColor; + public bool LinkToCastleOnly; + public byte BossType; + } +} diff --git a/RogueCastle/src/LevelParser.cs b/RogueCastle/src/LevelParser.cs new file mode 100644 index 0000000..5edac08 --- /dev/null +++ b/RogueCastle/src/LevelParser.cs @@ -0,0 +1,411 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework.Content; +using System.Globalization; +using System.Xml; +using DS2DEngine; + +namespace RogueCastle +{ + class LevelParser + { + private const int MAX_ROOM_SIZE = 4; + private const int ROOM_HEIGHT = 720; + private const int ROOM_WIDTH = 1320; + + public static void ParseRooms(string filePath, ContentManager contentManager = null, bool isDLCMap = false) + { + // flibit didn't like this + // CultureInfo ci = (CultureInfo)CultureInfo.CurrentCulture.Clone(); + // ci.NumberFormat.CurrencyDecimalSeparator = "."; + CultureInfo ci = CultureInfo.InvariantCulture; + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true; + settings.IgnoreWhitespace = true; + XmlReader reader = null; + + if (contentManager == null) + reader = XmlReader.Create(filePath, settings); + else + reader = XmlReader.Create(System.IO.Path.Combine(contentManager.RootDirectory, "Levels", filePath + ".xml"), settings); + + // STEPS: + // 1. Finds a room object in the XML doc and creates a new RoomObj based off that data. + // 2. Creates and stores various object data (like doors, terrain, enemies, etc.) into that RoomObj. + // 3. That newly and fully populated RoomObj is stored in LevelBuilder via LevelBuilder.StoreRoom(). + + RoomObj currentRoom = null; + RoomObj castleRoom = null; + RoomObj dungeonRoom = null; + RoomObj gardenRoom = null; + RoomObj towerRoom = null; + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + // Parsing room object. + if (reader.Name == "RoomObject") + { + currentRoom = new RoomObj(); + ParseGenericXML(reader, currentRoom); + + if (isDLCMap == true) + currentRoom.IsDLCMap = true; + + // Start with 5 copies of a room (including the generic one). + castleRoom = currentRoom.Clone() as RoomObj; + dungeonRoom = currentRoom.Clone() as RoomObj; + gardenRoom = currentRoom.Clone() as RoomObj; + towerRoom = currentRoom.Clone() as RoomObj; + } + + // Parsing game object. + if (reader.Name == "GameObject") + { + reader.MoveToAttribute("Type"); + string type = reader.Value; + GameObj obj = null; + + switch (type) + { + case ("CollHullObj"): + obj = new TerrainObj(0, 0); + break; + case ("DoorObj"): + obj = new DoorObj(currentRoom, 0, 0, GameTypes.DoorType.OPEN); // The door type needs to be saved via editor and placed here. + break; + case ("ChestObj"): + if (reader.MoveToAttribute("Fairy")) + { + if (bool.Parse(reader.Value) == true) + { + obj = new FairyChestObj(null); + (obj as ChestObj).ChestType = ChestType.Fairy; + } + else + obj = new ChestObj(null); + } + else + obj = new ChestObj(null); + break; + case ("HazardObj"): + obj = new HazardObj(0, 0); + break; + case ("BorderObj"): + obj = new BorderObj(); + break; + case ("EnemyObj"): + reader.MoveToAttribute("Procedural"); + bool isProcedural = bool.Parse(reader.Value); + if (isProcedural == false) // The enemy is not procedural so create him now and add him to the room. + { + reader.MoveToAttribute("EnemyType"); + byte enemyType = byte.Parse(reader.Value, NumberStyles.Any, ci); + + reader.MoveToAttribute("Difficulty"); + GameTypes.EnemyDifficulty difficulty = (GameTypes.EnemyDifficulty)Enum.Parse(typeof(GameTypes.EnemyDifficulty), reader.Value, true); + obj = EnemyBuilder.BuildEnemy(enemyType, null, null, null, difficulty); + if (reader.MoveToAttribute("Flip")) + { + if (bool.Parse(reader.Value) == true) + { + obj.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + // (obj as EnemyObj).InternalFlip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + } + } + if (reader.MoveToAttribute("InitialDelay")) + (obj as EnemyObj).InitialLogicDelay = float.Parse(reader.Value, NumberStyles.Any, ci); + } + else // The enemy is procedural, so leave an EnemyTagObj so that the enemy can be added later. + { + reader.MoveToAttribute("EnemyType"); + string enemyType = reader.Value; + obj = new EnemyTagObj(); + (obj as EnemyTagObj).EnemyType = enemyType; + } + break; + case ("EnemyOrbObj"): + reader.MoveToAttribute("OrbType"); + int orbType = int.Parse(reader.Value, NumberStyles.Any, ci); + bool isWaypoint = false; + if (reader.MoveToAttribute("IsWaypoint")) + isWaypoint = bool.Parse(reader.Value); + + if (isWaypoint == true) + { + obj = new WaypointObj(); + (obj as WaypointObj).OrbType = orbType; + } + else + { + obj = new EnemyOrbObj(); + (obj as EnemyOrbObj).OrbType = orbType; + if (reader.MoveToAttribute("ForceFlying")) + (obj as EnemyOrbObj).ForceFlying = bool.Parse(reader.Value); + } + break; + case ("SpriteObj"): + reader.MoveToAttribute("SpriteName"); + if (reader.Value == "LightSource_Sprite") + obj = new LightSourceObj(); + else + obj = new SpriteObj(reader.Value); + break; + case ("PhysicsObj"): + reader.MoveToAttribute("SpriteName"); + obj = new PhysicsObj(reader.Value); + PhysicsObj physObj = obj as PhysicsObj; + //physObj.CollisionTypeTag = GameTypes.CollisionType_WALL; + physObj.CollisionTypeTag = GameTypes.CollisionType_WALL_FOR_PLAYER; + physObj.CollidesBottom = false; + physObj.CollidesLeft = false; + physObj.CollidesRight = false; + break; + case ("PhysicsObjContainer"): + bool breakable = false; + if (reader.MoveToAttribute("Breakable")) + breakable = bool.Parse(reader.Value); + reader.MoveToAttribute("SpriteName"); + if (breakable == true) + obj = new BreakableObj(reader.Value); + else + obj = new PhysicsObjContainer(reader.Value); + break; + case ("ObjContainer"): + reader.MoveToAttribute("SpriteName"); + obj = new ObjContainer(reader.Value); + break; + case ("PlayerStartObj"): + obj = new PlayerStartObj(); + break; + } + + ParseGenericXML(reader, obj); + + GameTypes.LevelType levelType = GameTypes.LevelType.NONE; + if (reader.MoveToAttribute("LevelType")) + levelType = (GameTypes.LevelType)int.Parse(reader.Value, NumberStyles.Any, ci); + + if (levelType == GameTypes.LevelType.CASTLE) + { + StoreObj(obj, castleRoom); + StoreSwappedObj(obj, GameTypes.LevelType.DUNGEON, dungeonRoom); + StoreSwappedObj(obj, GameTypes.LevelType.TOWER, towerRoom); + StoreSwappedObj(obj, GameTypes.LevelType.GARDEN, gardenRoom); + + // Special code to change the pictures in the picture frames. + SpriteObj sprite = obj as SpriteObj; + if (sprite != null && sprite.SpriteName == "CastleAssetFrame_Sprite") + sprite.ChangeSprite("FramePicture" + CDGMath.RandomInt(1, 16) + "_Sprite"); + } + else if (levelType == GameTypes.LevelType.DUNGEON) + StoreObj(obj, dungeonRoom); + else if (levelType == GameTypes.LevelType.TOWER) + StoreObj(obj, towerRoom); + else if (levelType == GameTypes.LevelType.GARDEN) + StoreObj(obj, gardenRoom); + else + { + // If the object is generic, put it into all four room types. + StoreObj(obj, castleRoom); + StoreObj(obj, dungeonRoom); + StoreObj(obj, towerRoom); + StoreObj(obj, gardenRoom); + StoreObj(obj, currentRoom); + } + + // Extra debug code so that when testing a room, the correct LevelType objects will appear in that room. + // Removing this code doesn't hurt the game. It just turns Test Rooms into generic rooms. + if (LevelEV.RUN_TESTROOM == true && (levelType == LevelEV.TESTROOM_LEVELTYPE || levelType == GameTypes.LevelType.CASTLE)) + { + if (levelType == LevelEV.TESTROOM_LEVELTYPE) + StoreObj(obj, currentRoom); + else if (levelType == GameTypes.LevelType.CASTLE) + StoreSwappedObj(obj, LevelEV.TESTROOM_LEVELTYPE, currentRoom); + } + + // Special handling for test rooms. + if (obj is PlayerStartObj) + currentRoom.Name += "DEBUG_ROOM"; + } + } + else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "RoomObject") + { + if (currentRoom.X < 10000 && currentRoom.Name != "Boss" && currentRoom.Name != "ChallengeBoss") + { + if (currentRoom.Name.Contains("DEBUG_ROOM") == false) + { + if (currentRoom.AddToCastlePool == true) + { + LevelBuilder2.StoreRoom(castleRoom, GameTypes.LevelType.CASTLE); + LevelBuilder2.StoreSpecialRoom(castleRoom, GameTypes.LevelType.CASTLE); + } + if (currentRoom.AddToDungeonPool == true) + { + LevelBuilder2.StoreRoom(dungeonRoom, GameTypes.LevelType.DUNGEON); + LevelBuilder2.StoreSpecialRoom(dungeonRoom, GameTypes.LevelType.DUNGEON); + } + if (currentRoom.AddToGardenPool == true) + { + LevelBuilder2.StoreRoom(gardenRoom, GameTypes.LevelType.GARDEN); + LevelBuilder2.StoreSpecialRoom(gardenRoom, GameTypes.LevelType.GARDEN); + } + if (currentRoom.AddToTowerPool == true) + { + LevelBuilder2.StoreRoom(towerRoom, GameTypes.LevelType.TOWER); + LevelBuilder2.StoreSpecialRoom(towerRoom, GameTypes.LevelType.TOWER); + } + } + + // If the room is a debug room, store the debug room, but then store the regular version of the room in the normal list. + if (currentRoom.Name.Contains("DEBUG_ROOM")) + { + currentRoom.Name = currentRoom.Name.Replace("DEBUG_ROOM", ""); + if (LevelEV.TESTROOM_LEVELTYPE != GameTypes.LevelType.CASTLE) + LevelBuilder2.StoreSpecialRoom(currentRoom, GameTypes.LevelType.CASTLE, true); // Store a castle version because SequencedRoomList in LevelBuilder2 checks for the castle version. + LevelBuilder2.StoreSpecialRoom(currentRoom, LevelEV.TESTROOM_LEVELTYPE, true); + + //RoomObj testRoom = currentRoom.Clone() as RoomObj; + //testRoom.Name = "DEBUG_ROOM"; + //LevelBuilder2.StoreSpecialRoom(testRoom); + //currentRoom.Name = currentRoom.Name.Replace("DEBUG_ROOM", ""); + } + + // If the room is special, store it here. + // LevelBuilder2.StoreSpecialRoom(currentRoom, GameTypes.LevelType.CASTLE); + } + + if (currentRoom.X < 10000 && (currentRoom.Name == "Boss" || currentRoom.Name == "ChallengeBoss")) // Special handling for storing boss rooms. + LevelBuilder2.StoreSpecialRoom(currentRoom, GameTypes.LevelType.CASTLE); + } + } + } + + public static void ParseGenericXML(XmlReader reader, GameObj obj) + { + // flibit didn't like this + // CultureInfo ci = (CultureInfo)CultureInfo.CurrentCulture.Clone(); + // ci.NumberFormat.CurrencyDecimalSeparator = "."; + CultureInfo ci = CultureInfo.InvariantCulture; + + obj.PopulateFromXMLReader(reader, ci); // Most important line. Populates the properties for each object. + + // Special reader attribute to determine whether the object is on the front or back layer. + bool bgLayer = false; + if (reader.MoveToAttribute("BGLayer")) + bgLayer = bool.Parse(reader.Value); + if (bgLayer == true) + obj.Layer = -1; + + // Force breakable objects to always be collidable. This is needed because breakable objs are just physics obj, and their weighted settings are set to false. Hack. + BreakableObj breakableObj = obj as BreakableObj; + if (breakableObj != null) + breakableObj.IsCollidable = true; + } + + public static void StoreSwappedObj(GameObj obj, GameTypes.LevelType levelType, RoomObj currentRoom) + { + string[] swapList = null; + switch (levelType) + { + case (GameTypes.LevelType.DUNGEON): + swapList = LevelEV.DUNGEON_ASSETSWAP_LIST; + break; + case(GameTypes.LevelType.TOWER): + swapList = LevelEV.TOWER_ASSETSWAP_LIST; + break; + case (GameTypes.LevelType.GARDEN): + swapList = LevelEV.GARDEN_ASSETSWAP_LIST; + break; + default: + throw new Exception("Cannot find asset swaplist for leveltype " + levelType); + } + + // Hack to disable top collisions for Castle Urns. + BreakableObj breakableObj = obj as BreakableObj; + if (breakableObj != null && breakableObj.SpriteName.Contains("CastleAssetUrn")) + breakableObj.CollidesTop = false; + + bool storeObj = false; + IAnimateableObj clone = obj.Clone() as IAnimateableObj; + if (clone != null) + { + for (int i = 0; i < LevelEV.CASTLE_ASSETSWAP_LIST.Length; i++) + { + if (clone.SpriteName == LevelEV.CASTLE_ASSETSWAP_LIST[i]) + { + string newSprite = swapList[i]; + if (newSprite.Contains("RANDOM")) + { + int numRandoms = int.Parse(Convert.ToString(newSprite[(newSprite.IndexOf("RANDOM") + 6)])); + int randChoice = CDGMath.RandomInt(1,numRandoms); + newSprite = newSprite.Replace("RANDOM" + numRandoms.ToString(), randChoice.ToString()); + + // Special handling to reposition tower holes. + if (newSprite.Contains("TowerHole")) + { + (clone as GameObj).X += CDGMath.RandomInt(-50, 50); + (clone as GameObj).Y += CDGMath.RandomInt(-50, 50); + if (CDGMath.RandomInt(1, 100) > 70) // 70% chance of the hole being visible + (clone as GameObj).Visible = false; + } + + // Special handling for garden floating rocks. + if (newSprite.Contains("GardenFloatingRock")) + { + HoverObj hover = new HoverObj(newSprite); + hover.Position = (clone as GameObj).Position; + hover.Amplitude = CDGMath.RandomFloat(-50, 50); + hover.HoverSpeed = CDGMath.RandomFloat(-2, 2); + hover.Scale = (clone as GameObj).Scale; + hover.Layer = (clone as GameObj).Layer; + clone = hover; + } + } + + // Special code to change the pictures in the picture frames for TOWERS ONLY. Castle done somewhere else. I know, it's awful. + if (newSprite == "CastleAssetFrame_Sprite") + newSprite = "FramePicture" + CDGMath.RandomInt(1, 16) + "_Sprite"; + + if (newSprite != "") + { + clone.ChangeSprite(newSprite); + storeObj = true; + + // Hack to make garden fairy sprites translucent. + if (newSprite.Contains("GardenFairy")) + { + (clone as GameObj).X += CDGMath.RandomInt(-25, 25); + (clone as GameObj).Y += CDGMath.RandomInt(-25, 25); + (clone as GameObj).Opacity = 0.8f; + } + + } + break; + } + } + } + + if (storeObj == true) + StoreObj(clone as GameObj, currentRoom); + } + + public static void StoreObj(GameObj obj, RoomObj currentRoom) + { + if (obj is EnemyObj) + currentRoom.EnemyList.Add(obj as EnemyObj); + else if (obj is DoorObj) // Must go before TerrainObj since for reason they inherit from TerrainObj. + currentRoom.DoorList.Add(obj as DoorObj); + else if (obj is TerrainObj) + currentRoom.TerrainObjList.Add(obj as TerrainObj); + else if (obj is BorderObj) + currentRoom.BorderList.Add(obj as BorderObj); + else + currentRoom.GameObjList.Add(obj); + } + } +} diff --git a/RogueCastle/src/Lighting Effect/LightArea.cs b/RogueCastle/src/Lighting Effect/LightArea.cs new file mode 100644 index 0000000..dd6cdb9 --- /dev/null +++ b/RogueCastle/src/Lighting Effect/LightArea.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + class LightArea + { + private GraphicsDevice graphicsDevice; + + public RenderTarget2D RenderTarget { get; private set; } + public Vector2 LightPosition { get; set; } + public Vector2 LightAreaSize { get; set; } + + public LightArea(GraphicsDevice graphicsDevice, ShadowmapSize size) + { + int baseSize = 2 << (int)size; + LightAreaSize = new Vector2(baseSize); + RenderTarget = new RenderTarget2D(graphicsDevice, baseSize, baseSize, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + this.graphicsDevice = graphicsDevice; + } + + public Vector2 ToRelativePosition(Vector2 worldPosition) + { + return worldPosition - (LightPosition - LightAreaSize * 0.5f); + } + + public void BeginDrawingShadowCasters() + { + graphicsDevice.SetRenderTarget(RenderTarget); + graphicsDevice.Clear(Color.Transparent); + } + + public void EndDrawingShadowCasters() + { + graphicsDevice.SetRenderTarget(null); + } + } +} diff --git a/RogueCastle/src/Lighting Effect/QuadRenderComponent.cs b/RogueCastle/src/Lighting Effect/QuadRenderComponent.cs new file mode 100644 index 0000000..c059523 --- /dev/null +++ b/RogueCastle/src/Lighting Effect/QuadRenderComponent.cs @@ -0,0 +1,69 @@ +// Using Statements +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Content; + +namespace RogueCastle +{ + public partial class QuadRenderComponent : DrawableGameComponent + { + VertexPositionTexture[] verts = null; + short[] ib = null; + + // Constructor + public QuadRenderComponent(Game game) + : base(game) + { + + } + + protected override void LoadContent() + { + verts = new VertexPositionTexture[] + { + new VertexPositionTexture( + new Vector3(0,0,0), + new Vector2(1,1)), + new VertexPositionTexture( + new Vector3(0,0,0), + new Vector2(0,1)), + new VertexPositionTexture( + new Vector3(0,0,0), + new Vector2(0,0)), + new VertexPositionTexture( + new Vector3(0,0,0), + new Vector2(1,0)) + }; + + ib = new short[] { 0, 1, 2, 2, 3, 0 }; + + base.LoadContent(); + } + + + protected override void UnloadContent() + { + base.UnloadContent(); + } + + public void Render(Vector2 v1, Vector2 v2) + { + verts[0].Position.X = v2.X; + verts[0].Position.Y = v1.Y; + + verts[1].Position.X = v1.X; + verts[1].Position.Y = v1.Y; + + verts[2].Position.X = v1.X; + verts[2].Position.Y = v2.Y; + + verts[3].Position.X = v2.X; + verts[3].Position.Y = v2.Y; + + GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, verts, 0, 4, ib, 0, 2); + } + + } +} diff --git a/RogueCastle/src/Lighting Effect/ShadowmapResolver.cs b/RogueCastle/src/Lighting Effect/ShadowmapResolver.cs new file mode 100644 index 0000000..1ac0004 --- /dev/null +++ b/RogueCastle/src/Lighting Effect/ShadowmapResolver.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Content; + +namespace RogueCastle +{ + public enum ShadowmapSize + { + Size128 = 6, + Size256 = 7, + Size512 = 8, + Size1024 = 9, + } + public class ShadowmapResolver + { + private GraphicsDevice graphicsDevice; + + private int reductionChainCount; + private int baseSize; + private int depthBufferSize; + + Effect resolveShadowsEffect; + Effect reductionEffect; + public static Effect blender; + + RenderTarget2D distortRT; + RenderTarget2D shadowMap; + RenderTarget2D shadowsRT; + RenderTarget2D processedShadowsRT; + + QuadRenderComponent quadRender; + RenderTarget2D distancesRT; + RenderTarget2D[] reductionRT; + + + /// + /// Creates a new shadowmap resolver + /// + /// The Graphics Device used by the XNA game + /// + /// The size of the light regions + public ShadowmapResolver(GraphicsDevice graphicsDevice, QuadRenderComponent quadRender, ShadowmapSize maxShadowmapSize, ShadowmapSize maxDepthBufferSize) + { + this.graphicsDevice = graphicsDevice; + this.quadRender = quadRender; + + reductionChainCount = (int)maxShadowmapSize; + baseSize = 2 << reductionChainCount; + depthBufferSize = 2 << (int)maxDepthBufferSize; + } + + public void LoadContent(ContentManager content) + { + reductionEffect = content.Load("Shaders\\reductionEffect"); + resolveShadowsEffect = content.Load("Shaders\\resolveShadowsEffect"); + blender = content.Load("Shaders\\2xMultiBlend"); + + SurfaceFormat surfaceFormat = SurfaceFormat.Color; + + distortRT = new RenderTarget2D(graphicsDevice, baseSize, baseSize, false, surfaceFormat, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + distancesRT = new RenderTarget2D(graphicsDevice, baseSize, baseSize, false, surfaceFormat, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + shadowMap = new RenderTarget2D(graphicsDevice, 2, baseSize, false, surfaceFormat, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + reductionRT = new RenderTarget2D[reductionChainCount]; + for (int i = 0; i < reductionChainCount; i++) + { + reductionRT[i] = new RenderTarget2D(graphicsDevice, 2 << i, baseSize, false, surfaceFormat, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + } + + + shadowsRT = new RenderTarget2D(graphicsDevice, baseSize, baseSize, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + processedShadowsRT = new RenderTarget2D(graphicsDevice, baseSize, baseSize, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + } + + public void ResolveShadows(Texture2D shadowCastersTexture, RenderTarget2D result, Vector2 lightPosition) + { + graphicsDevice.BlendState = BlendState.Opaque; + + ExecuteTechnique(shadowCastersTexture, distancesRT, "ComputeDistances"); + ExecuteTechnique(distancesRT, distortRT, "Distort"); + ApplyHorizontalReduction(distortRT, shadowMap); + ExecuteTechnique(null, shadowsRT, "DrawShadows", shadowMap); + ExecuteTechnique(shadowsRT, processedShadowsRT, "BlurHorizontally"); + ExecuteTechnique(processedShadowsRT, result, "BlurVerticallyAndAttenuate"); + } + + private void ExecuteTechnique(Texture2D source, RenderTarget2D destination, string techniqueName) + { + ExecuteTechnique(source, destination, techniqueName, null); + } + + private void ExecuteTechnique(Texture2D source, RenderTarget2D destination, string techniqueName, Texture2D shadowMap) + { + Vector2 renderTargetSize; + renderTargetSize = new Vector2((float)baseSize, (float)baseSize); + graphicsDevice.SetRenderTarget(destination); + graphicsDevice.Clear(Color.White); + resolveShadowsEffect.Parameters["renderTargetSize"].SetValue(renderTargetSize); + + if (source != null) + resolveShadowsEffect.Parameters["InputTexture"].SetValue(source); + if (shadowMap != null) + resolveShadowsEffect.Parameters["ShadowMapTexture"].SetValue(shadowMap); + + resolveShadowsEffect.CurrentTechnique = resolveShadowsEffect.Techniques[techniqueName]; + + foreach (EffectPass pass in resolveShadowsEffect.CurrentTechnique.Passes) + { + pass.Apply(); + quadRender.Render(Vector2.One * -1, Vector2.One); + } + graphicsDevice.SetRenderTarget(null); + } + + + private void ApplyHorizontalReduction(RenderTarget2D source, RenderTarget2D destination) + { + int step = reductionChainCount - 1; + RenderTarget2D s = source; + RenderTarget2D d = reductionRT[step]; + reductionEffect.CurrentTechnique = reductionEffect.Techniques["HorizontalReduction"]; + + while (step >= 0) + { + d = reductionRT[step]; + + graphicsDevice.SetRenderTarget(d); + graphicsDevice.Clear(Color.White); + + reductionEffect.Parameters["SourceTexture"].SetValue(s); + Vector2 textureDim = new Vector2(1.0f / (float)s.Width, 1.0f / (float)s.Height); + reductionEffect.Parameters["TextureDimensions"].SetValue(textureDim); + + foreach (EffectPass pass in reductionEffect.CurrentTechnique.Passes) + { + pass.Apply(); + quadRender.Render(Vector2.One * -1, new Vector2(1, 1)); + } + + graphicsDevice.SetRenderTarget(null); + + s = d; + step--; + } + + //copy to destination + graphicsDevice.SetRenderTarget(destination); + reductionEffect.CurrentTechnique = reductionEffect.Techniques["Copy"]; + reductionEffect.Parameters["SourceTexture"].SetValue(d); + + foreach (EffectPass pass in reductionEffect.CurrentTechnique.Passes) + { + pass.Apply(); + quadRender.Render(Vector2.One * -1, new Vector2(1, 1)); + } + + reductionEffect.Parameters["SourceTexture"].SetValue(reductionRT[reductionChainCount - 1]); + graphicsDevice.SetRenderTarget(null); + } + + + } +} diff --git a/RogueCastle/src/LogicActions/CheckWallLogicAction.cs b/RogueCastle/src/LogicActions/CheckWallLogicAction.cs new file mode 100644 index 0000000..477b2e2 --- /dev/null +++ b/RogueCastle/src/LogicActions/CheckWallLogicAction.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; + +namespace RogueCastle +{ + public class CheckWallLogicAction : LogicAction + { + EnemyObj m_obj = null; + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + m_obj = ParentLogicSet.ParentGameObj as EnemyObj; + SequenceType = Types.Sequence.Serial; + base.Execute(); + } + } + + public override void Update(Microsoft.Xna.Framework.GameTime gameTime) + { + this.ExecuteNext(); + base.Update(gameTime); + } + + public override void ExecuteNext() + { + base.ExecuteNext(); + } + + public override object Clone() + { + return new CheckWallLogicAction(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + m_obj = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/LogicActions/DelayObjLogicAction.cs b/RogueCastle/src/LogicActions/DelayObjLogicAction.cs new file mode 100644 index 0000000..c83909d --- /dev/null +++ b/RogueCastle/src/LogicActions/DelayObjLogicAction.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Tweener; +using Tweener.Ease; +using DS2DEngine; + +namespace RogueCastle +{ + // Hack method to store floats in "pointers". + public class DelayObjLogicAction : LogicAction + { + private GameObj m_delayObj; + private float m_delayCounter; + + public DelayObjLogicAction(GameObj delayObj) + { + m_delayObj = delayObj; + m_delayCounter = 0; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + SequenceType = Types.Sequence.Serial; + m_delayCounter = m_delayObj.X; + base.Execute(); + } + } + + public override void Update(Microsoft.Xna.Framework.GameTime gameTime) + { + m_delayCounter -= (float)gameTime.ElapsedGameTime.TotalSeconds; + this.ExecuteNext(); + base.Update(gameTime); + } + + public override void ExecuteNext() + { + if (m_delayCounter <= 0) + base.ExecuteNext(); + } + + //public override void Execute() + //{ + // if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + // { + // SequenceType = Types.Sequence.Serial; + + // if (m_maxDelayDuration > m_minDelayDuration) + // m_minDelayDuration = CDGMath.RandomFloat(m_minDelayDuration, m_maxDelayDuration); + + // m_delayTween = Tween.To(m_blankObj, m_minDelayDuration, Linear.EaseNone, "X", "1"); + // m_delayTween.UseTicks = m_useTicks; + // base.Execute(); + // } + //} + + //public override void ExecuteNext() + //{ + // if (m_delayTween != null) + // { + // if (NextLogicAction != null) + // m_delayTween.EndHandler(NextLogicAction, "Execute"); + // else + // m_delayTween.EndHandler(ParentLogicSet, "ExecuteComplete"); + // } + // else + // base.ExecuteNext(); + // //base.ExecuteNext(); Must override base.ExecuteNext() entirely. + //} + + public override void Stop() + { + // Okay. Big problem with delay tweens. Because logic actions are never disposed in-level (due to garbage collection concerns) the reference to the delay tween in this logic action will exist until it is + // disposed, EVEN if the tween completes. If the tween completes, it goes back into the pool, and then something else will call it, but this logic action's delay tween reference will still be pointing to it. + // This becomes a HUGE problem if this logic action's Stop() method is called, because it will then stop the tween that this tween reference is pointing to. + // The solution is to comment out the code below. This means that this tween reference will always call it's endhandler, which in this case is either Execute() or ExecuteComplete(). This turns out + // to not be a problem, because when a logic set is called to stop, its IsActive flag is set to false, and all Execute() methods in logic actions have to have their parent logic set's IsActive flag to true + // in order to run. Therefore, when the tween calls Execute() or ExecuteComplete() nothing will happen. + // - This bug kept you confused for almost 5 hours. DO NOT FORGET IT. That is what this long explanation is for. + // TL;DR - DO NOT UNCOMMENT THE CODE BELOW OR LOGIC SETS BREAK. + + //if (m_delayTween != null) + // m_delayTween.StopTween(false); + + base.Stop(); + } + + public override object Clone() + { + return new DelayObjLogicAction(m_delayObj); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + m_delayObj = null; + base.Dispose(); + } + } + + //public override void Dispose() + //{ + // if (IsDisposed == false) + // { + // // See above for explanation. + // //if (m_delayTween != null) + // // m_delayTween.StopTween(false); + + // m_delayTween = null; + // m_blankObj.Dispose(); + // m_blankObj = null; + // base.Dispose(); + // } + //} + } +} diff --git a/RogueCastle/src/LogicActions/FireProjectileLogicAction.cs b/RogueCastle/src/LogicActions/FireProjectileLogicAction.cs new file mode 100644 index 0000000..c45b003 --- /dev/null +++ b/RogueCastle/src/LogicActions/FireProjectileLogicAction.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class FireProjectileLogicAction : LogicAction + { + ProjectileManager m_projectileManager; + ProjectileData m_data; + + public FireProjectileLogicAction(ProjectileManager projectileManager, ProjectileData data) + { + m_projectileManager = projectileManager; + m_data = data.Clone(); + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + EnemyObj enemy = ParentLogicSet.ParentGameObj as EnemyObj; + ProjectileObj obj = m_projectileManager.FireProjectile(m_data); + + base.Execute(); + } + } + + public override object Clone() + { + return new FireProjectileLogicAction(m_projectileManager, m_data); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_projectileManager = null; + m_data = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/LogicActions/GroundCheckLogicAction.cs b/RogueCastle/src/LogicActions/GroundCheckLogicAction.cs new file mode 100644 index 0000000..2f11b93 --- /dev/null +++ b/RogueCastle/src/LogicActions/GroundCheckLogicAction.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; + +namespace RogueCastle +{ + public class GroundCheckLogicAction : LogicAction + { + CharacterObj m_obj = null; + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + m_obj = ParentLogicSet.ParentGameObj as CharacterObj; + SequenceType = Types.Sequence.Serial; + base.Execute(); + } + } + + public override void Update(Microsoft.Xna.Framework.GameTime gameTime) + { + this.ExecuteNext(); + base.Update(gameTime); + } + + public override void ExecuteNext() + { + if (m_obj.IsTouchingGround == true) + base.ExecuteNext(); + } + + public override object Clone() + { + return new GroundCheckLogicAction(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_obj = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/LogicActions/JumpLogicAction.cs b/RogueCastle/src/LogicActions/JumpLogicAction.cs new file mode 100644 index 0000000..f805926 --- /dev/null +++ b/RogueCastle/src/LogicActions/JumpLogicAction.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class JumpLogicAction : LogicAction + { + private float m_overriddenHeight; + + public JumpLogicAction(float overriddenHeight = 0) + { + m_overriddenHeight = overriddenHeight; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + CharacterObj character = ParentLogicSet.ParentGameObj as CharacterObj; + if (character != null) + { + if (m_overriddenHeight > 0) + character.AccelerationY = -m_overriddenHeight; + else + character.AccelerationY = -character.JumpHeight; + } + + base.Execute(); + } + } + + public override object Clone() + { + return new JumpLogicAction(m_overriddenHeight); + } + } +} diff --git a/RogueCastle/src/LogicActions/LockFaceDirectionLogicAction.cs b/RogueCastle/src/LogicActions/LockFaceDirectionLogicAction.cs new file mode 100644 index 0000000..f548e88 --- /dev/null +++ b/RogueCastle/src/LogicActions/LockFaceDirectionLogicAction.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; + +namespace RogueCastle +{ + public class LockFaceDirectionLogicAction : LogicAction + { + private int m_forceDirection = 0; + private bool m_lockFace = false; + + public LockFaceDirectionLogicAction(bool lockFace, int forceDirection = 0) + { + m_lockFace = lockFace; + m_forceDirection = forceDirection; + } + + public override void Execute() + { + if (ParentLogicSet != null && ParentLogicSet.IsActive == true) + { + CharacterObj obj = ParentLogicSet.ParentGameObj as CharacterObj; + if (obj != null) + { + obj.LockFlip = m_lockFace; + + if (m_forceDirection > 0) + obj.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.None; + else if (m_forceDirection < 0) + obj.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + } + base.Execute(); + } + } + + public override object Clone() + { + return new LockFaceDirectionLogicAction(m_lockFace, m_forceDirection); + } + } +} diff --git a/RogueCastle/src/Managers/DialogueManager.cs b/RogueCastle/src/Managers/DialogueManager.cs new file mode 100644 index 0000000..fb182ba --- /dev/null +++ b/RogueCastle/src/Managers/DialogueManager.cs @@ -0,0 +1,820 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using Microsoft.Xna.Framework.Content; +using DS2DEngine; + +namespace RogueCastle +{ + public class DialogueManager : IDisposable + { + private static bool m_isDisposed = false; + + private static Dictionary> m_languageArray; + private static Dictionary m_dialogDict; + private static string m_currentLanguage; + + public static void Initialize() + { + m_languageArray = new Dictionary>(); + m_dialogDict = new Dictionary(); + + // Text entries + m_dialogDict.Add("Meet Blacksmith", + new DialogueObj( + new string[] { "LOC_ID_TEXT_1", "LOC_ID_TEXT_1", "LOC_ID_TEXT_1", "LOC_ID_TEXT_1", "LOC_ID_TEXT_1", }, + new string[] { "LOC_ID_TEXT_2", "LOC_ID_TEXT_3", "LOC_ID_TEXT_4", "LOC_ID_TEXT_5", "LOC_ID_TEXT_6", } + )); + m_dialogDict.Add("Meet Enchantress", + new DialogueObj( + new string[] { "LOC_ID_TEXT_7", "LOC_ID_TEXT_7", "LOC_ID_TEXT_7", "LOC_ID_TEXT_7", "LOC_ID_TEXT_7", }, + new string[] { "LOC_ID_TEXT_8", "LOC_ID_TEXT_9", "LOC_ID_TEXT_10", "LOC_ID_TEXT_11", "LOC_ID_TEXT_12", } + )); + m_dialogDict.Add("Meet Architect", + new DialogueObj( + new string[] { "LOC_ID_TEXT_13", "LOC_ID_TEXT_13", "LOC_ID_TEXT_13", "LOC_ID_TEXT_13", "LOC_ID_TEXT_13", "LOC_ID_TEXT_13", "LOC_ID_TEXT_13", "LOC_ID_TEXT_21", }, + new string[] { "LOC_ID_TEXT_14", "LOC_ID_TEXT_15", "LOC_ID_TEXT_16", "LOC_ID_TEXT_17", "LOC_ID_TEXT_18", "LOC_ID_TEXT_19", "LOC_ID_TEXT_20", "LOC_ID_TEXT_22", } + )); + m_dialogDict.Add("Meet Architect 2", + new DialogueObj( + new string[] { "LOC_ID_TEXT_23", }, + new string[] { "LOC_ID_TEXT_24", } + )); + m_dialogDict.Add("No Castle Architect", + new DialogueObj( + new string[] { "LOC_ID_TEXT_25", }, + new string[] { "LOC_ID_TEXT_26", } + )); + m_dialogDict.Add("Castle Already Locked Architect", + new DialogueObj( + new string[] { "LOC_ID_TEXT_27", }, + new string[] { "LOC_ID_TEXT_28", } + )); + m_dialogDict.Add("Castle Lock Complete Architect", + new DialogueObj( + new string[] { "LOC_ID_TEXT_29", }, + new string[] { "LOC_ID_TEXT_30", } + )); + m_dialogDict.Add("Meet Toll Collector 1", + new DialogueObj( + new string[] { "LOC_ID_TEXT_31", "LOC_ID_TEXT_33", }, + new string[] { "LOC_ID_TEXT_32", "LOC_ID_TEXT_34", } + )); + m_dialogDict.Add("Meet Toll Collector Skip0", + new DialogueObj( + new string[] { "LOC_ID_TEXT_35", }, + new string[] { "LOC_ID_TEXT_36", } + )); + m_dialogDict.Add("Meet Toll Collector Skip10", + new DialogueObj( + new string[] { "LOC_ID_TEXT_37", }, + new string[] { "LOC_ID_TEXT_38", } + )); + m_dialogDict.Add("Meet Toll Collector Skip20", + new DialogueObj( + new string[] { "LOC_ID_TEXT_39", }, + new string[] { "LOC_ID_TEXT_40", } + )); + m_dialogDict.Add("Meet Toll Collector Skip30", + new DialogueObj( + new string[] { "LOC_ID_TEXT_41", }, + new string[] { "LOC_ID_TEXT_42", } + )); + m_dialogDict.Add("Meet Toll Collector Skip40", + new DialogueObj( + new string[] { "LOC_ID_TEXT_43", }, + new string[] { "LOC_ID_TEXT_44", } + )); + m_dialogDict.Add("Meet Toll Collector Skip50", + new DialogueObj( + new string[] { "LOC_ID_TEXT_45", }, + new string[] { "LOC_ID_TEXT_46", } + )); + m_dialogDict.Add("Toll Collector Obol", + new DialogueObj( + new string[] { "LOC_ID_TEXT_47", }, + new string[] { "LOC_ID_TEXT_48", } + )); + m_dialogDict.Add("Challenge Icon Eyeball", + new DialogueObj( + new string[] { "LOC_ID_TEXT_49", "LOC_ID_TEXT_49", "LOC_ID_TEXT_49", }, + new string[] { "LOC_ID_TEXT_50", "LOC_ID_TEXT_51", "LOC_ID_TEXT_52", } + )); + m_dialogDict.Add("Challenge Icon Skull", + new DialogueObj( + new string[] { "LOC_ID_TEXT_53", "LOC_ID_TEXT_53", "LOC_ID_TEXT_53", }, + new string[] { "LOC_ID_TEXT_54", "LOC_ID_TEXT_55", "LOC_ID_TEXT_56", } + )); + m_dialogDict.Add("Challenge Icon Fireball", + new DialogueObj( + new string[] { "LOC_ID_TEXT_57", "LOC_ID_TEXT_57", "LOC_ID_TEXT_57", }, + new string[] { "LOC_ID_TEXT_58", "LOC_ID_TEXT_59", "LOC_ID_TEXT_60", } + )); + m_dialogDict.Add("Challenge Icon Blob", + new DialogueObj( + new string[] { "LOC_ID_TEXT_61", "LOC_ID_TEXT_61", "LOC_ID_TEXT_61", }, + new string[] { "LOC_ID_TEXT_62", "LOC_ID_TEXT_63", "LOC_ID_TEXT_64", } + )); + m_dialogDict.Add("Challenge Icon Last Boss", + new DialogueObj( + new string[] { "LOC_ID_TEXT_65", "LOC_ID_TEXT_65", "LOC_ID_TEXT_65", }, + new string[] { "LOC_ID_TEXT_66", "LOC_ID_TEXT_67", "LOC_ID_TEXT_68", } + )); + m_dialogDict.Add("Special Item Prayer", + new DialogueObj( + new string[] { "LOC_ID_TEXT_69", }, + new string[] { "LOC_ID_TEXT_70", } + )); + m_dialogDict.Add("Meet Last Boss", + new DialogueObj( + new string[] { "LOC_ID_TEXT_71", }, + new string[] { "LOC_ID_TEXT_72", } + )); + m_dialogDict.Add("Chest_Locked 0", + new DialogueObj( + new string[] { "LOC_ID_TEXT_73", }, + new string[] { "LOC_ID_TEXT_74", } + )); + m_dialogDict.Add("Chest_Locked 1", + new DialogueObj( + new string[] { "LOC_ID_TEXT_75", }, + new string[] { "LOC_ID_TEXT_76", } + )); + m_dialogDict.Add("Chest_Locked 2", + new DialogueObj( + new string[] { "LOC_ID_TEXT_77", }, + new string[] { "LOC_ID_TEXT_78", } + )); + m_dialogDict.Add("Chest_Locked 3", + new DialogueObj( + new string[] { "LOC_ID_TEXT_79", }, + new string[] { "LOC_ID_TEXT_80", } + )); + m_dialogDict.Add("Chest_Locked 4", + new DialogueObj( + new string[] { "LOC_ID_TEXT_81", }, + new string[] { "LOC_ID_TEXT_82", } + )); + m_dialogDict.Add("Chest_Locked 5", + new DialogueObj( + new string[] { "LOC_ID_TEXT_83", }, + new string[] { "LOC_ID_TEXT_84", } + )); + m_dialogDict.Add("Chest_Locked 6", + new DialogueObj( + new string[] { "LOC_ID_TEXT_85", }, + new string[] { "LOC_ID_TEXT_86", } + )); + m_dialogDict.Add("Chest_Locked 7", + new DialogueObj( + new string[] { "LOC_ID_TEXT_87", }, + new string[] { "LOC_ID_TEXT_88", } + )); + m_dialogDict.Add("Chest_Locked 8", + new DialogueObj( + new string[] { "LOC_ID_TEXT_89", }, + new string[] { "LOC_ID_TEXT_90", } + )); + m_dialogDict.Add("Chest_Locked 9", + new DialogueObj( + new string[] { "LOC_ID_TEXT_91", }, + new string[] { "LOC_ID_TEXT_92", } + )); + m_dialogDict.Add("Chest_Locked 10", + new DialogueObj( + new string[] { "LOC_ID_TEXT_93", }, + new string[] { "LOC_ID_TEXT_94", } + )); + m_dialogDict.Add("Chest_Failed 3", + new DialogueObj( + new string[] { "LOC_ID_TEXT_95", }, + new string[] { "LOC_ID_TEXT_96", } + )); + m_dialogDict.Add("Chest_Failed 4", + new DialogueObj( + new string[] { "LOC_ID_TEXT_97", }, + new string[] { "LOC_ID_TEXT_98", } + )); + m_dialogDict.Add("Chest_Failed 5", + new DialogueObj( + new string[] { "LOC_ID_TEXT_99", }, + new string[] { "LOC_ID_TEXT_100", } + )); + m_dialogDict.Add("Chest_Failed 6", + new DialogueObj( + new string[] { "LOC_ID_TEXT_101", }, + new string[] { "LOC_ID_TEXT_102", } + )); + m_dialogDict.Add("CarnivalRoom1-Start", + new DialogueObj( + new string[] { "LOC_ID_TEXT_103", "LOC_ID_TEXT_103", }, + new string[] { "LOC_ID_TEXT_104", "LOC_ID_TEXT_106", } + )); + m_dialogDict.Add("CarnivalRoom1-End", + new DialogueObj( + new string[] { "LOC_ID_TEXT_107", }, + new string[] { "LOC_ID_TEXT_108", } + )); + m_dialogDict.Add("CarnivalRoom1-Reward", + new DialogueObj( + new string[] { "LOC_ID_TEXT_109", }, + new string[] { "LOC_ID_TEXT_110", } + )); + m_dialogDict.Add("CarnivalRoom1-Fail", + new DialogueObj( + new string[] { "LOC_ID_TEXT_111", }, + new string[] { "LOC_ID_TEXT_112", } + )); + m_dialogDict.Add("CarnivalRoom2-Start", + new DialogueObj( + new string[] { "LOC_ID_TEXT_114", "LOC_ID_TEXT_114", }, + new string[] { "LOC_ID_TEXT_115", "LOC_ID_TEXT_117", } + )); + m_dialogDict.Add("CarnivalRoom2-Reward", + new DialogueObj( + new string[] { "LOC_ID_TEXT_118", }, + new string[] { "LOC_ID_TEXT_119", } + )); + m_dialogDict.Add("CarnivalRoom2-Fail", + new DialogueObj( + new string[] { "LOC_ID_TEXT_120", }, + new string[] { "LOC_ID_TEXT_121", } + )); + m_dialogDict.Add("ChestBonusRoom1-Start", + new DialogueObj( + new string[] { "LOC_ID_TEXT_123", "LOC_ID_TEXT_125", "LOC_ID_TEXT_125", "LOC_ID_TEXT_128", }, + new string[] { "LOC_ID_TEXT_124", "LOC_ID_TEXT_126", "LOC_ID_TEXT_127", "LOC_ID_TEXT_129", } + )); + m_dialogDict.Add("ChestBonusRoom2-Start", + new DialogueObj( + new string[] { "LOC_ID_TEXT_130", "LOC_ID_TEXT_132", "LOC_ID_TEXT_132", "LOC_ID_TEXT_135", }, + new string[] { "LOC_ID_TEXT_131", "LOC_ID_TEXT_133", "LOC_ID_TEXT_134", "LOC_ID_TEXT_136", } + )); + m_dialogDict.Add("ChestBonusRoom3-Start", + new DialogueObj( + new string[] { "LOC_ID_TEXT_137", "LOC_ID_TEXT_139", "LOC_ID_TEXT_139", "LOC_ID_TEXT_142", }, + new string[] { "LOC_ID_TEXT_138", "LOC_ID_TEXT_140", "LOC_ID_TEXT_141", "LOC_ID_TEXT_143", } + )); + m_dialogDict.Add("ChestBonusRoom1-NoMoney", + new DialogueObj( + new string[] { "LOC_ID_TEXT_144", }, + new string[] { "LOC_ID_TEXT_145", } + )); + m_dialogDict.Add("ChestBonusRoom1-Lost", + new DialogueObj( + new string[] { "LOC_ID_TEXT_146", "LOC_ID_TEXT_146", "LOC_ID_TEXT_146", }, + new string[] { "LOC_ID_TEXT_147", "LOC_ID_TEXT_148", "LOC_ID_TEXT_149", } + )); + m_dialogDict.Add("ChestBonusRoom1-Won", + new DialogueObj( + new string[] { "LOC_ID_TEXT_150", }, + new string[] { "LOC_ID_TEXT_151", } + )); + m_dialogDict.Add("ChestBonusRoom1-Choose", + new DialogueObj( + new string[] { "LOC_ID_TEXT_152", }, + new string[] { "LOC_ID_TEXT_153", } + )); + m_dialogDict.Add("ChestBonusRoom1-End", + new DialogueObj( + new string[] { "LOC_ID_TEXT_154", }, + new string[] { "LOC_ID_TEXT_155", } + )); + m_dialogDict.Add("PortraitRoomText0", + new DialogueObj( + new string[] { "LOC_ID_TEXT_156", "LOC_ID_TEXT_156", "LOC_ID_TEXT_156", "LOC_ID_TEXT_156", "LOC_ID_TEXT_156", "LOC_ID_TEXT_156", "LOC_ID_TEXT_156", }, + new string[] { "LOC_ID_TEXT_157", "LOC_ID_TEXT_160", "LOC_ID_TEXT_161", "LOC_ID_TEXT_162", "LOC_ID_TEXT_163", "LOC_ID_TEXT_164", "LOC_ID_TEXT_165", } + )); + m_dialogDict.Add("PortraitRoomText1", + new DialogueObj( + new string[] { "LOC_ID_TEXT_166", "LOC_ID_TEXT_166", "LOC_ID_TEXT_166", "LOC_ID_TEXT_166", "LOC_ID_TEXT_166", "LOC_ID_TEXT_166", "LOC_ID_TEXT_166", "LOC_ID_TEXT_166", }, + new string[] { "LOC_ID_TEXT_167", "LOC_ID_TEXT_170", "LOC_ID_TEXT_171", "LOC_ID_TEXT_172", "LOC_ID_TEXT_173", "LOC_ID_TEXT_174", "LOC_ID_TEXT_175", "LOC_ID_TEXT_176", } + )); + m_dialogDict.Add("PortraitRoomText2", + new DialogueObj( + new string[] { "LOC_ID_TEXT_177", "LOC_ID_TEXT_177", "LOC_ID_TEXT_177", "LOC_ID_TEXT_177", "LOC_ID_TEXT_177", "LOC_ID_TEXT_177", "LOC_ID_TEXT_177", }, + new string[] { "LOC_ID_TEXT_178", "LOC_ID_TEXT_181", "LOC_ID_TEXT_182", "LOC_ID_TEXT_183", "LOC_ID_TEXT_184", "LOC_ID_TEXT_185", "LOC_ID_TEXT_186", } + )); + m_dialogDict.Add("PortraitRoomText3", + new DialogueObj( + new string[] { "LOC_ID_TEXT_187", "LOC_ID_TEXT_187", "LOC_ID_TEXT_187", "LOC_ID_TEXT_187", "LOC_ID_TEXT_187", }, + new string[] { "LOC_ID_TEXT_188", "LOC_ID_TEXT_191", "LOC_ID_TEXT_192", "LOC_ID_TEXT_193", "LOC_ID_TEXT_194", } + )); + m_dialogDict.Add("PortraitRoomText4", + new DialogueObj( + new string[] { "LOC_ID_TEXT_195", "LOC_ID_TEXT_195", "LOC_ID_TEXT_195", "LOC_ID_TEXT_195", "LOC_ID_TEXT_195", "LOC_ID_TEXT_195", "LOC_ID_TEXT_195", "LOC_ID_TEXT_195", }, + new string[] { "LOC_ID_TEXT_196", "LOC_ID_TEXT_199", "LOC_ID_TEXT_200", "LOC_ID_TEXT_201", "LOC_ID_TEXT_202", "LOC_ID_TEXT_203", "LOC_ID_TEXT_204", "LOC_ID_TEXT_205", } + )); + m_dialogDict.Add("PortraitRoomText5", + new DialogueObj( + new string[] { "LOC_ID_TEXT_206", "LOC_ID_TEXT_206", "LOC_ID_TEXT_206", "LOC_ID_TEXT_206", "LOC_ID_TEXT_206", "LOC_ID_TEXT_206", }, + new string[] { "LOC_ID_TEXT_207", "LOC_ID_TEXT_210", "LOC_ID_TEXT_211", "LOC_ID_TEXT_212", "LOC_ID_TEXT_213", "LOC_ID_TEXT_214", } + )); + m_dialogDict.Add("PortraitRoomText6", + new DialogueObj( + new string[] { "LOC_ID_TEXT_215", "LOC_ID_TEXT_215", "LOC_ID_TEXT_215", "LOC_ID_TEXT_215", "LOC_ID_TEXT_215", "LOC_ID_TEXT_215", }, + new string[] { "LOC_ID_TEXT_216", "LOC_ID_TEXT_219", "LOC_ID_TEXT_220", "LOC_ID_TEXT_221", "LOC_ID_TEXT_222", "LOC_ID_TEXT_223", } + )); + m_dialogDict.Add("PortraitRoomText7", + new DialogueObj( + new string[] { "LOC_ID_TEXT_224", "LOC_ID_TEXT_224", "LOC_ID_TEXT_224", "LOC_ID_TEXT_224", "LOC_ID_TEXT_224", "LOC_ID_TEXT_224", "LOC_ID_TEXT_224", "LOC_ID_TEXT_224", "LOC_ID_TEXT_224", "LOC_ID_TEXT_224", }, + new string[] { "LOC_ID_TEXT_225", "LOC_ID_TEXT_228", "LOC_ID_TEXT_229", "LOC_ID_TEXT_230", "LOC_ID_TEXT_231", "LOC_ID_TEXT_232", "LOC_ID_TEXT_233", "LOC_ID_TEXT_234", "LOC_ID_TEXT_235", "LOC_ID_TEXT_236", } + )); + m_dialogDict.Add("PortraitRoomText8", + new DialogueObj( + new string[] { "LOC_ID_TEXT_224", "LOC_ID_TEXT_224", "LOC_ID_TEXT_224", "LOC_ID_TEXT_224", "LOC_ID_TEXT_224", "LOC_ID_TEXT_224" }, + new string[] { "LOC_ID_PORTRAIT_TEXT_NEW_1", "LOC_ID_PORTRAIT_TEXT_NEW_2", "LOC_ID_PORTRAIT_TEXT_NEW_3", "LOC_ID_PORTRAIT_TEXT_NEW_4", "LOC_ID_PORTRAIT_TEXT_NEW_5", "LOC_ID_PORTRAIT_TEXT_NEW_6"} + )); + m_dialogDict.Add("ConfirmTest1", + new DialogueObj( + new string[] { "LOC_ID_TEXT_237", }, + new string[] { "LOC_ID_TEXT_238", } + )); + m_dialogDict.Add("DeleteFileWarning", + new DialogueObj( + new string[] { "LOC_ID_TEXT_239", }, + new string[] { "LOC_ID_TEXT_240", } + )); + m_dialogDict.Add("RestoreDefaultControlsWarning", + new DialogueObj( + new string[] { "LOC_ID_TEXT_241", }, + new string[] { "LOC_ID_TEXT_242", } + )); + m_dialogDict.Add("LineageChoiceWarning", + new DialogueObj( + new string[] { "LOC_ID_TEXT_243", }, + new string[] { "LOC_ID_TEXT_244", } + )); + m_dialogDict.Add("Resolution Changed", + new DialogueObj( + new string[] { "LOC_ID_TEXT_245", }, + new string[] { "LOC_ID_TEXT_246", } + )); + m_dialogDict.Add("Delete Save", + new DialogueObj( + new string[] { "LOC_ID_TEXT_248", }, + new string[] { "LOC_ID_TEXT_249", } + )); + m_dialogDict.Add("Delete Save2", + new DialogueObj( + new string[] { "LOC_ID_TEXT_251", }, + new string[] { "LOC_ID_TEXT_252", } + )); + m_dialogDict.Add("Back to Menu", + new DialogueObj( + new string[] { "LOC_ID_TEXT_254", }, + new string[] { "LOC_ID_TEXT_255", } + )); + m_dialogDict.Add("Quit Rogue Legacy", + new DialogueObj( + new string[] { "LOC_ID_TEXT_256", }, + new string[] { "LOC_ID_TEXT_257", } + )); + m_dialogDict.Add("Save File Error", + new DialogueObj( + new string[] { "LOC_ID_TEXT_258", "LOC_ID_TEXT_258", }, + new string[] { "LOC_ID_TEXT_259", "LOC_ID_TEXT_260", } + )); + m_dialogDict.Add("Save File Error 2", + new DialogueObj( + new string[] { "LOC_ID_TEXT_261", }, + new string[] { "LOC_ID_TEXT_262", } + )); + m_dialogDict.Add("Save File Error Antivirus", + new DialogueObj( + new string[] { "LOC_ID_TEXT_263", "LOC_ID_TEXT_263", }, + new string[] { "LOC_ID_TEXT_264", "LOC_ID_TEXT_265", } + )); + + // Diary entries + m_dialogDict.Add("DiaryEntry0", + new DialogueObj( + new string[] { "LOC_ID_DIARY_1", "LOC_ID_DIARY_1", "LOC_ID_DIARY_1", "LOC_ID_DIARY_1", "LOC_ID_DIARY_1", "LOC_ID_DIARY_1", }, + new string[] { "LOC_ID_DIARY_2", "LOC_ID_DIARY_3", "LOC_ID_DIARY_4", "LOC_ID_DIARY_5", "LOC_ID_DIARY_6", "LOC_ID_DIARY_7", } + )); + m_dialogDict.Add("DiaryEntry1", + new DialogueObj( + new string[] { "LOC_ID_DIARY_8", "LOC_ID_DIARY_8", "LOC_ID_DIARY_8", "LOC_ID_DIARY_8", "LOC_ID_DIARY_8", "LOC_ID_DIARY_8", "LOC_ID_DIARY_8", }, + new string[] { "LOC_ID_DIARY_9", "LOC_ID_DIARY_10", "LOC_ID_DIARY_11", "LOC_ID_DIARY_12", "LOC_ID_DIARY_13", "LOC_ID_DIARY_14", "LOC_ID_DIARY_15", } + )); + m_dialogDict.Add("DiaryEntry2", + new DialogueObj( + new string[] { "LOC_ID_DIARY_16", "LOC_ID_DIARY_16", "LOC_ID_DIARY_16", "LOC_ID_DIARY_16", "LOC_ID_DIARY_16", "LOC_ID_DIARY_16", }, + new string[] { "LOC_ID_DIARY_17", "LOC_ID_DIARY_18", "LOC_ID_DIARY_19", "LOC_ID_DIARY_20", "LOC_ID_DIARY_21", "LOC_ID_DIARY_22", } + )); + m_dialogDict.Add("DiaryEntry3", + new DialogueObj( + new string[] { "LOC_ID_DIARY_23", "LOC_ID_DIARY_23", "LOC_ID_DIARY_23", "LOC_ID_DIARY_23", "LOC_ID_DIARY_23", "LOC_ID_DIARY_23", }, + new string[] { "LOC_ID_DIARY_24", "LOC_ID_DIARY_25", "LOC_ID_DIARY_26", "LOC_ID_DIARY_27", "LOC_ID_DIARY_28", "LOC_ID_DIARY_29", } + )); + m_dialogDict.Add("DiaryEntry4", + new DialogueObj( + new string[] { "LOC_ID_DIARY_30", "LOC_ID_DIARY_30", "LOC_ID_DIARY_30", "LOC_ID_DIARY_30", "LOC_ID_DIARY_30", }, + new string[] { "LOC_ID_DIARY_31", "LOC_ID_DIARY_32", "LOC_ID_DIARY_33", "LOC_ID_DIARY_34", "LOC_ID_DIARY_35", } + )); + m_dialogDict.Add("DiaryEntry5", + new DialogueObj( + new string[] { "LOC_ID_DIARY_36", "LOC_ID_DIARY_36", "LOC_ID_DIARY_36", "LOC_ID_DIARY_36", "LOC_ID_DIARY_36", }, + new string[] { "LOC_ID_DIARY_37", "LOC_ID_DIARY_38", "LOC_ID_DIARY_39", "LOC_ID_DIARY_40", "LOC_ID_DIARY_41", } + )); + m_dialogDict.Add("DiaryEntry6", + new DialogueObj( + new string[] { "LOC_ID_DIARY_42", "LOC_ID_DIARY_42", "LOC_ID_DIARY_42", "LOC_ID_DIARY_42", "LOC_ID_DIARY_42", "LOC_ID_DIARY_42", }, + new string[] { "LOC_ID_DIARY_43", "LOC_ID_DIARY_44", "LOC_ID_DIARY_45", "LOC_ID_DIARY_46", "LOC_ID_DIARY_47", "LOC_ID_DIARY_48", } + )); + m_dialogDict.Add("DiaryEntry7", + new DialogueObj( + new string[] { "LOC_ID_DIARY_49", "LOC_ID_DIARY_49", "LOC_ID_DIARY_49", "LOC_ID_DIARY_49", "LOC_ID_DIARY_49", }, + new string[] { "LOC_ID_DIARY_50", "LOC_ID_DIARY_51", "LOC_ID_DIARY_52", "LOC_ID_DIARY_53", "LOC_ID_DIARY_54", } + )); + m_dialogDict.Add("DiaryEntry8", + new DialogueObj( + new string[] { "LOC_ID_DIARY_55", "LOC_ID_DIARY_55", "LOC_ID_DIARY_55", "LOC_ID_DIARY_55", }, + new string[] { "LOC_ID_DIARY_56", "LOC_ID_DIARY_57", "LOC_ID_DIARY_58", "LOC_ID_DIARY_59", } + )); + m_dialogDict.Add("DiaryEntry9", + new DialogueObj( + new string[] { "LOC_ID_DIARY_60", "LOC_ID_DIARY_60", "LOC_ID_DIARY_60", "LOC_ID_DIARY_60", "LOC_ID_DIARY_60", "LOC_ID_DIARY_60", }, + new string[] { "LOC_ID_DIARY_61", "LOC_ID_DIARY_62", "LOC_ID_DIARY_63", "LOC_ID_DIARY_64", "LOC_ID_DIARY_65", "LOC_ID_DIARY_66", } + )); + m_dialogDict.Add("DiaryEntry10", + new DialogueObj( + new string[] { "LOC_ID_DIARY_67", "LOC_ID_DIARY_67", "LOC_ID_DIARY_67", "LOC_ID_DIARY_67", "LOC_ID_DIARY_67", }, + new string[] { "LOC_ID_DIARY_68", "LOC_ID_DIARY_69", "LOC_ID_DIARY_70", "LOC_ID_DIARY_71", "LOC_ID_DIARY_72", } + )); + m_dialogDict.Add("DiaryEntry11", + new DialogueObj( + new string[] { "LOC_ID_DIARY_73", "LOC_ID_DIARY_73", "LOC_ID_DIARY_73", "LOC_ID_DIARY_73", "LOC_ID_DIARY_73", }, + new string[] { "LOC_ID_DIARY_74", "LOC_ID_DIARY_75", "LOC_ID_DIARY_76", "LOC_ID_DIARY_77", "LOC_ID_DIARY_78", } + )); + m_dialogDict.Add("DiaryEntry12", + new DialogueObj( + new string[] { "LOC_ID_DIARY_79", "LOC_ID_DIARY_79", "LOC_ID_DIARY_79", "LOC_ID_DIARY_79", }, + new string[] { "LOC_ID_DIARY_80", "LOC_ID_DIARY_81", "LOC_ID_DIARY_82", "LOC_ID_DIARY_83", } + )); + m_dialogDict.Add("DiaryEntry13", + new DialogueObj( + new string[] { "LOC_ID_DIARY_84", "LOC_ID_DIARY_84", "LOC_ID_DIARY_84", "LOC_ID_DIARY_84", }, + new string[] { "LOC_ID_DIARY_85", "LOC_ID_DIARY_86", "LOC_ID_DIARY_87", "LOC_ID_DIARY_88", } + )); + m_dialogDict.Add("DiaryEntry14", + new DialogueObj( + new string[] { "LOC_ID_DIARY_89", "LOC_ID_DIARY_89", "LOC_ID_DIARY_89", "LOC_ID_DIARY_89", "LOC_ID_DIARY_89", }, + new string[] { "LOC_ID_DIARY_90", "LOC_ID_DIARY_91", "LOC_ID_DIARY_92", "LOC_ID_DIARY_93", "LOC_ID_DIARY_94", } + )); + m_dialogDict.Add("DiaryEntry15", + new DialogueObj( + new string[] { "LOC_ID_DIARY_95", "LOC_ID_DIARY_95", "LOC_ID_DIARY_95", "LOC_ID_DIARY_95", "LOC_ID_DIARY_95", }, + new string[] { "LOC_ID_DIARY_96", "LOC_ID_DIARY_97", "LOC_ID_DIARY_98", "LOC_ID_DIARY_99", "LOC_ID_DIARY_100", } + )); + m_dialogDict.Add("DiaryEntry16", + new DialogueObj( + new string[] { "LOC_ID_DIARY_101", "LOC_ID_DIARY_101", "LOC_ID_DIARY_101", "LOC_ID_DIARY_101", "LOC_ID_DIARY_101", }, + new string[] { "LOC_ID_DIARY_102", "LOC_ID_DIARY_103", "LOC_ID_DIARY_104", "LOC_ID_DIARY_105", "LOC_ID_DIARY_106", } + )); + m_dialogDict.Add("DiaryEntry17", + new DialogueObj( + new string[] { "LOC_ID_DIARY_107", "LOC_ID_DIARY_107", "LOC_ID_DIARY_107", "LOC_ID_DIARY_107", }, + new string[] { "LOC_ID_DIARY_108", "LOC_ID_DIARY_109", "LOC_ID_DIARY_110", "LOC_ID_DIARY_111", } + )); + m_dialogDict.Add("DiaryEntry18", + new DialogueObj( + new string[] { "LOC_ID_DIARY_112", "LOC_ID_DIARY_112", "LOC_ID_DIARY_112", "LOC_ID_DIARY_112", }, + new string[] { "LOC_ID_DIARY_113", "LOC_ID_DIARY_114", "LOC_ID_DIARY_115", "LOC_ID_DIARY_116", } + )); + m_dialogDict.Add("DiaryEntry19", + new DialogueObj( + new string[] { "LOC_ID_DIARY_117", "LOC_ID_DIARY_117", "LOC_ID_DIARY_117", "LOC_ID_DIARY_117", "LOC_ID_DIARY_117", }, + new string[] { "LOC_ID_DIARY_118", "LOC_ID_DIARY_119", "LOC_ID_DIARY_120", "LOC_ID_DIARY_121", "LOC_ID_DIARY_122", } + )); + m_dialogDict.Add("DiaryEntry20", + new DialogueObj( + new string[] { "LOC_ID_DIARY_123", "LOC_ID_DIARY_123", "LOC_ID_DIARY_123", "LOC_ID_DIARY_123", }, + new string[] { "LOC_ID_DIARY_124", "LOC_ID_DIARY_125", "LOC_ID_DIARY_126", "LOC_ID_DIARY_127", } + )); + m_dialogDict.Add("DiaryEntry21", + new DialogueObj( + new string[] { "LOC_ID_DIARY_128", "LOC_ID_DIARY_128", "LOC_ID_DIARY_128", "LOC_ID_DIARY_128", "LOC_ID_DIARY_128", "LOC_ID_DIARY_128", }, + new string[] { "LOC_ID_DIARY_129", "LOC_ID_DIARY_130", "LOC_ID_DIARY_131", "LOC_ID_DIARY_132", "LOC_ID_DIARY_133", "LOC_ID_DIARY_134", } + )); + m_dialogDict.Add("DiaryEntry22", + new DialogueObj( + new string[] { "LOC_ID_DIARY_135", "LOC_ID_DIARY_135", "LOC_ID_DIARY_135", "LOC_ID_DIARY_135", "LOC_ID_DIARY_135", "LOC_ID_DIARY_135", "LOC_ID_DIARY_135", "LOC_ID_DIARY_135", }, + new string[] { "LOC_ID_DIARY_136", "LOC_ID_DIARY_137", "LOC_ID_DIARY_138", "LOC_ID_DIARY_139", "LOC_ID_DIARY_140", "LOC_ID_DIARY_141", "LOC_ID_DIARY_142", "LOC_ID_DIARY_143", } + )); + m_dialogDict.Add("DiaryEntry23", + new DialogueObj( + new string[] { "LOC_ID_DIARY_144", "LOC_ID_DIARY_144", "LOC_ID_DIARY_144", }, + new string[] { "LOC_ID_DIARY_145", "LOC_ID_DIARY_146", "LOC_ID_DIARY_147", } + )); + m_dialogDict.Add("DiaryEntry24", + new DialogueObj( + new string[] { "LOC_ID_DIARY_148", "LOC_ID_DIARY_148", "LOC_ID_DIARY_148", "LOC_ID_DIARY_148", "LOC_ID_DIARY_148", "LOC_ID_DIARY_148", "LOC_ID_DIARY_148", "LOC_ID_DIARY_148", "LOC_ID_DIARY_148", "LOC_ID_DIARY_148", "LOC_ID_DIARY_148", }, + new string[] { "LOC_ID_DIARY_149", "LOC_ID_DIARY_150", "LOC_ID_DIARY_151", "LOC_ID_DIARY_152", "LOC_ID_DIARY_153", "LOC_ID_DIARY_154", "LOC_ID_DIARY_155", "LOC_ID_DIARY_156", "LOC_ID_DIARY_157", "LOC_ID_DIARY_158", "LOC_ID_DIARY_159", } + )); + m_dialogDict.Add("FinalBossTalk01_Special", + new DialogueObj( + new string[] { "LOC_ID_DIARY_160", "LOC_ID_DIARY_160", "LOC_ID_DIARY_160", }, + new string[] { "LOC_ID_DIARY_161", "LOC_ID_DIARY_162", "LOC_ID_DIARY_163", } + )); + m_dialogDict.Add("FinalBossTalk01", + new DialogueObj( + new string[] { "LOC_ID_DIARY_164", "LOC_ID_DIARY_164", "LOC_ID_DIARY_164", "LOC_ID_DIARY_164", "LOC_ID_DIARY_164", "LOC_ID_DIARY_164", }, + new string[] { "LOC_ID_DIARY_165", "LOC_ID_DIARY_166", "LOC_ID_DIARY_167", "LOC_ID_DIARY_168", "LOC_ID_DIARY_169", "LOC_ID_DIARY_170", } + )); + m_dialogDict.Add("FinalBossTalk02", + new DialogueObj( + new string[] { "LOC_ID_DIARY_171", "LOC_ID_DIARY_171", "LOC_ID_DIARY_171", "LOC_ID_DIARY_171", "LOC_ID_DIARY_171", }, + new string[] { "LOC_ID_DIARY_172", "LOC_ID_DIARY_173", "LOC_ID_DIARY_174", "LOC_ID_DIARY_175", "LOC_ID_DIARY_176", } + )); + m_dialogDict.Add("FinalBossTalk03", + new DialogueObj( + new string[] { "LOC_ID_DIARY_177", "LOC_ID_DIARY_177", "LOC_ID_DIARY_177", "LOC_ID_DIARY_177", "LOC_ID_DIARY_177", "LOC_ID_DIARY_177", "LOC_ID_DIARY_177", "LOC_ID_DIARY_177", "LOC_ID_DIARY_177", }, + new string[] { "LOC_ID_DIARY_178", "LOC_ID_DIARY_179", "LOC_ID_DIARY_180", "LOC_ID_DIARY_181", "LOC_ID_DIARY_182", "LOC_ID_DIARY_183", "LOC_ID_DIARY_184", "LOC_ID_DIARY_185", "LOC_ID_DIARY_186", } + )); + m_dialogDict.Add("DonationBoxTalk01", + new DialogueObj( + new string[] { "LOC_ID_DONATIONBOX_TITLE_1" }, + new string[] { "LOC_ID_DONATIONBOX_TEXT_1" } + )); + m_dialogDict.Add("DonationBoxTalkUpgraded", + new DialogueObj( + new string[] { "" }, + new string[] { "LOC_ID_DONATIONBOX_TEXT_4" } + )); + m_dialogDict.Add("DonationBoxTalkMaxxed", + new DialogueObj( + new string[] { "LOC_ID_DONATIONBOX_TITLE_1" }, + new string[] { "LOC_ID_DONATIONBOX_TEXT_2" } + )); + m_dialogDict.Add("DonationBoxTalkPoor", + new DialogueObj( + new string[] { "LOC_ID_DONATIONBOX_TITLE_1" }, + new string[] { "LOC_ID_DONATIONBOX_TEXT_3" } + )); + } + + public static void LoadLanguageDocument(ContentManager content, string fileName) + { + LoadLanguageDocument(Path.Combine(content.RootDirectory, fileName + ".txt")); + } + + public static void LoadLanguageDocument(string fullFilePath) + { + FileInfo fileInfo = new FileInfo(fullFilePath); + + using (StreamReader reader = fileInfo.OpenText()) + { + ParseDocument(reader); + } + } + + private static void ParseDocument(StreamReader reader) + { + string line = ""; + int lineCount = 0; + string currentLabel = ""; + string currentSpeaker = ""; + string currentDialogue = null; + List currentSpeakerArray = new List(); + List currentTextArray = new List(); + bool newTextBlock = true; + + while ((line = reader.ReadLine()) != null) + { + if (line != "" && line.IndexOf("//") != 0) // ignore blank lines. + { + string data = line.Substring(line.IndexOf(" ") + 1); + if (lineCount == 0 && !line.Contains("@language")) + throw new Exception("Cannot create text dictionary from file. Unspecified language type."); + + if (line.Contains("@language")) + SetLanguage(data); + else if (line.Contains("@label")) + { + if (newTextBlock == false) + { + if (currentDialogue != null) + { + currentTextArray.Add(currentDialogue); + currentDialogue = null; + } + AddText(currentLabel, currentSpeakerArray.ToArray(), currentTextArray.ToArray()); + newTextBlock = true; + } + + if (newTextBlock == true) + { + // Resets everything to a new text block. + newTextBlock = false; + currentLabel = data; + currentSpeakerArray.Clear(); + currentTextArray.Clear(); + currentDialogue = null; + currentSpeaker = ""; + } + } + else if (line.Contains("@title")) + currentSpeaker = data; + else if (line.Contains("@text")) + { + currentSpeakerArray.Add(currentSpeaker); + if (currentDialogue != null) + { + currentTextArray.Add(currentDialogue); + currentDialogue = null; + } + currentDialogue = data; + } + else + currentDialogue += "\n" + line; + } + lineCount++; + } + + if (currentDialogue != null) + { + currentTextArray.Add(currentDialogue); + currentDialogue = null; + } + AddText(currentLabel, currentSpeakerArray.ToArray(), currentTextArray.ToArray()); + + //Console.WriteLine("m_languageArray[\"English\"]: " + m_languageArray["English"]); + } + + public static void LoadLanguageBinFile(string filePath) + { + using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) + //using (StreamReader fileStream = new StreamReader(filePath)) + { + using (BinaryReader reader = new BinaryReader(fileStream)) + { + string line = ""; + int lineCount = 0; + string currentLabel = ""; + string currentSpeaker = ""; + string currentDialogue = null; + List currentSpeakerArray = new List(); + List currentTextArray = new List(); + bool newTextBlock = true; + + do + { + line = reader.ReadString(); + + if (line != "" && line.IndexOf("//") != 0) // ignore blank lines. + { + string data = line.Substring(line.IndexOf(" ") + 1); + if (lineCount == 0 && !line.Contains("@language")) + throw new Exception("Cannot create text dictionary from file. Unspecified language type."); + + if (line.Contains("@language")) + SetLanguage(data); + else if (line.Contains("@label")) + { + if (newTextBlock == false) + { + if (currentDialogue != null) + { + currentTextArray.Add(currentDialogue); + currentDialogue = null; + } + + AddText(currentLabel, currentSpeakerArray.ToArray(), currentTextArray.ToArray()); + newTextBlock = true; + } + + if (newTextBlock == true) + { + // Resets everything to a new text block. + newTextBlock = false; + currentLabel = data; + currentSpeakerArray.Clear(); + currentTextArray.Clear(); + currentDialogue = null; + currentSpeaker = ""; + } + } + else if (line.Contains("@title")) + currentSpeaker = data; + else if (line.Contains("@text")) + { + currentSpeakerArray.Add(currentSpeaker); + if (currentDialogue != null) + { + currentTextArray.Add(currentDialogue); + currentDialogue = null; + } + currentDialogue = data; + } + else if (line != "eof") + currentDialogue += "\n" + line; + } + lineCount++; + + } while (line != "eof"); // end of file check. + + if (newTextBlock == false) + { + if (currentDialogue != null) + { + currentTextArray.Add(currentDialogue); + currentDialogue = null; + } + + AddText(currentLabel, currentSpeakerArray.ToArray(), currentTextArray.ToArray()); + } + } + } + } + + public static void SetLanguage(string language) + { + m_currentLanguage = language; + if (m_languageArray.ContainsKey(m_currentLanguage) == false) + { + Console.WriteLine("Adding language dictionary for language: " + language); + m_languageArray.Add(language, new Dictionary()); + } + } + + public static void AddText(string key, string[] speakers, string[] text) + { + if (m_currentLanguage != null) + { + if (m_languageArray[m_currentLanguage].ContainsKey(key)) + Console.WriteLine("Cannot add text. Text with title already specified."); + else + { + DialogueObj dialogueObj = new DialogueObj(speakers, text); + m_languageArray[m_currentLanguage].Add(key, dialogueObj); + +#if false + // Generate this: + /* + m_dialogDict.Add("DiaryEntry0", + new DialogueObj( + new string[] { "LOC_ID_DIARY_1", "LOC_ID_DIARY_1", "LOC_ID_DIARY_1", "LOC_ID_DIARY_1", "LOC_ID_DIARY_1", "LOC_ID_DIARY_1" }, + new string[] { "LOC_ID_DIARY_2", "LOC_ID_DIARY_3", "LOC_ID_DIARY_4", "LOC_ID_DIARY_5", "LOC_ID_DIARY_6", "LOC_ID_DIARY_7" } + )); + */ + + Console.WriteLine("m_dialogDict.Add(\"" + key + "\","); + Console.WriteLine(" new DialogueObj("); + Console.Write(" new string[] { "); + foreach (var item in speakers) + { + Console.Write("\"" + item.ToString() + "\", "); + } + Console.WriteLine("},"); + Console.Write(" new string[] { "); + foreach (var item in text) + { + Console.Write("\"" + item.ToString() + "\", "); + } + Console.WriteLine("}"); + Console.WriteLine(" ));"); +#endif + } + } + else + Console.WriteLine("Call SetLanguage() before attempting to add text to a specified language."); + } + + public static DialogueObj GetText(string key) + { + //return m_languageArray[m_currentLanguage][key]; + return m_dialogDict[key]; + } + + public static string GetCurrentLanguage() + { + return m_currentLanguage; + } + + public void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Dialogue Manager"); + + foreach (KeyValuePair> languageDict in m_languageArray) + { + foreach (KeyValuePair text in languageDict.Value) + text.Value.Dispose(); + languageDict.Value.Clear(); + } + m_languageArray.Clear(); + m_languageArray = null; + m_isDisposed = true; + } + } + + public static bool IsDisposed + { + get { return m_isDisposed; } + } + } +} diff --git a/RogueCastle/src/Managers/ItemDropManager.cs b/RogueCastle/src/Managers/ItemDropManager.cs new file mode 100644 index 0000000..fea4f6a --- /dev/null +++ b/RogueCastle/src/Managers/ItemDropManager.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class ItemDropManager : IDisposableObj + { + private DS2DPool m_itemDropPool; + private List m_itemDropsToRemoveList; + private int m_poolSize = 0; + + private PhysicsManager m_physicsManager; + + private bool m_isDisposed = false; + + public ItemDropManager(int poolSize, PhysicsManager physicsManager) + { + m_itemDropPool = new DS2DPool(); + m_itemDropsToRemoveList = new List(); + m_poolSize = poolSize; + m_physicsManager = physicsManager; + } + + public void Initialize() + { + for (int i = 0; i < m_poolSize; i++) + { + ItemDropObj itemDrop = new ItemDropObj("Coin_Sprite"); + itemDrop.Visible = false; + m_itemDropPool.AddToPool(itemDrop); + } + } + + public void DropItem(Vector2 position, int dropType, float amount) + { + //ItemDropObj item = m_itemDropPool.CheckOut(); + ItemDropObj item = m_itemDropPool.CheckOutReturnNull(); + if (item == null) + return; + + item.ConvertDrop(dropType, amount); + m_physicsManager.AddObject(item); + + item.Position = position; + item.AccelerationY = CDGMath.RandomFloat(-720, -480); + item.AccelerationX = CDGMath.RandomFloat(-120, 120); + item.Visible = true; + item.IsWeighted = true; + item.IsCollidable = true; + item.AnimationDelay = 1 / 20f; + item.Opacity = 1; + item.CollectionCounter = 0.2f; + + //SoundManager.Play3DSound(this, Game.ScreenManager.Player,"CoinDrop1", "CoinDrop2", "CoinDrop3", "CoinDrop4", "CoinDrop5"); + SoundManager.Play3DSound(item, Game.ScreenManager.Player,"CoinCollect1", "CoinCollect2", "CoinCollect3"); + } + + // For player only. + public void DropItemWide(Vector2 position, int dropType, float amount) + { + //ItemDropObj item = m_itemDropPool.CheckOut(); + ItemDropObj item = m_itemDropPool.CheckOutReturnNull(); + if (item == null) + return; + + item.ConvertDrop(dropType, amount); + m_physicsManager.AddObject(item); + + item.Position = position; + item.AccelerationY = CDGMath.RandomFloat(-1200, -300); + item.AccelerationX = CDGMath.RandomFloat(-600, 600); + item.Visible = true; + item.IsWeighted = true; + item.IsCollidable = true; + item.AnimationDelay = 1 / 20f; + item.Opacity = 1; + item.CollectionCounter = 0.2f; + + //SoundManager.Play3DSound(this, Game.ScreenManager.Player,"CoinDrop1", "CoinDrop2", "CoinDrop3", "CoinDrop4", "CoinDrop5"); + //SoundManager.Play3DSound(this, Game.ScreenManager.Player,"CoinCollect1", "CoinCollect2", "CoinCollect3"); + } + + public void DestroyItemDrop(ItemDropObj itemDrop) + { + if (m_itemDropPool.ActiveObjsList.Contains(itemDrop)) // Only destroy items if they haven't already been destroyed. It is possible for two objects to call Destroy on the same projectile. + { + itemDrop.Visible = false; + itemDrop.TextureColor = Color.White; + m_physicsManager.RemoveObject(itemDrop); // Might be better to keep them in the physics manager and just turn off their collision detection. + m_itemDropPool.CheckIn(itemDrop); + } + } + + public void DestroyAllItemDrops() + { + ItemDropObj[] itemDropArray = m_itemDropPool.ActiveObjsList.ToArray(); + foreach (ItemDropObj item in itemDropArray) + { + DestroyItemDrop(item); + } + } + + public void PauseAllAnimations() + { + foreach (ItemDropObj item in m_itemDropPool.ActiveObjsList) + item.PauseAnimation(); + } + + public void ResumeAllAnimations() + { + foreach (ItemDropObj item in m_itemDropPool.ActiveObjsList) + item.ResumeAnimation(); + } + + public void Draw(Camera2D camera) + { + foreach (ItemDropObj item in m_itemDropPool.ActiveObjsList) + item.Draw(camera); + } + + public int AvailableItems + { + get { return m_itemDropPool.CurrentPoolSize; } + } + + public void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Item Drop Manager"); + + DestroyAllItemDrops(); + m_itemDropsToRemoveList.Clear(); + m_itemDropsToRemoveList = null; + m_itemDropPool.Dispose(); + m_itemDropPool = null; + m_physicsManager = null; // This must be set null last, since all item drops need to be removed from the physics manager first. + + m_isDisposed = true; + } + } + + public bool IsDisposed + { + get { return m_isDisposed; } + } + } +} diff --git a/RogueCastle/src/Managers/ProjectileManager.cs b/RogueCastle/src/Managers/ProjectileManager.cs new file mode 100644 index 0000000..1d846ca --- /dev/null +++ b/RogueCastle/src/Managers/ProjectileManager.cs @@ -0,0 +1,476 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class ProjectileManager: IDisposable + { + private ProceduralLevelScreen m_levelScreen; + private DS2DPool m_projectilePool; + private List m_projectilesToRemoveList; + private int m_poolSize = 0; + + private bool m_isDisposed = false; + + public ProjectileManager(ProceduralLevelScreen level, int poolSize) + { + //POOL_SIZE = poolSize; + //m_projectileStack = new Stack(); + //m_activeProjectilesList = new List(); + m_projectilesToRemoveList = new List(); + //m_numActiveProjectiles = 0; + m_levelScreen = level; + + m_projectilePool = new DS2DPool(); + m_poolSize = poolSize; + } + + public void Initialize() + { + for (int i = 0; i < m_poolSize; i++) + { + //m_projectileStack.Push(new ProjectileObj("BoneProjectile") { Visible = false }); + ProjectileObj projectile = new ProjectileObj("BoneProjectile_Sprite"); + projectile.Visible = false; + projectile.AnimationDelay = 1 / 20f; + projectile.OutlineWidth = 2; + //m_levelScreen.PhysicsManager.AddObject(projectile); // Might be better to just add the projectiles to the physics manager as opposed to constantly adding and removing via CheckIn()/CheckOut(). + m_projectilePool.AddToPool(projectile); + } + } + + public ProjectileObj FireProjectile(ProjectileData data) + { + if (data.Source == null) + throw new Exception("Cannot have a projectile with no source"); + + ProjectileObj projectile = m_projectilePool.CheckOut(); + projectile.Reset(); // Must be called to reset the life span of the projectile as well as revive them. "Dead" projectiles are ones with life spans that have run out. + + projectile.LifeSpan = data.Lifespan; + GameObj source = data.Source; + + projectile.ChaseTarget = data.ChaseTarget; + projectile.Source = source; + projectile.Target = data.Target; + projectile.UpdateHeading(); + projectile.TurnSpeed = data.TurnSpeed; + projectile.CollidesWithTerrain = data.CollidesWithTerrain; + projectile.DestroysWithTerrain = data.DestroysWithTerrain; + projectile.DestroysWithEnemy = data.DestroysWithEnemy; + projectile.FollowArc = data.FollowArc; + projectile.Orientation = MathHelper.ToRadians(data.StartingRotation); + projectile.ShowIcon = data.ShowIcon; + projectile.IsCollidable = data.IsCollidable; + projectile.CollidesWith1Ways = data.CollidesWith1Ways; + projectile.DestroyOnRoomTransition = data.DestroyOnRoomTransition; + projectile.CanBeFusRohDahed = data.CanBeFusRohDahed; + projectile.IgnoreInvincibleCounter = data.IgnoreInvincibleCounter; + projectile.WrapProjectile = data.WrapProjectile; + + float angle = 0; + if (data.Target != null) + { + float x = data.Target.X - source.X; + float y = data.Target.Y - source.Y - data.SourceAnchor.Y; + if (source.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally) + { + angle = 180 - angle; + x += data.SourceAnchor.X; + angle = MathHelper.ToDegrees((float)Math.Atan2(y, x)); + + angle -= data.AngleOffset; + } + else + { + angle = MathHelper.ToDegrees((float)Math.Atan2(y, x)); + x -= data.SourceAnchor.X; + + angle += data.AngleOffset; + } + } + else + { + angle = data.Angle.X + data.AngleOffset; + if (data.Angle.X != data.Angle.Y) + angle = CDGMath.RandomFloat(data.Angle.X, data.Angle.Y) + data.AngleOffset; + + if (source.Flip != Microsoft.Xna.Framework.Graphics.SpriteEffects.None && source.Rotation != 0) + angle -= 180; + else if (source.Flip != Microsoft.Xna.Framework.Graphics.SpriteEffects.None && source.Rotation == 0) + angle = 180 - angle; + } + + if (data.LockPosition == false) + projectile.Rotation = angle; + angle = MathHelper.ToRadians(angle); + + //projectile.Rotation = 0; + projectile.Damage = data.Damage; + m_levelScreen.PhysicsManager.AddObject(projectile); // Might be better to keep them in the physics manager and just turn off their collision detection. + projectile.ChangeSprite(data.SpriteName); + projectile.RotationSpeed = data.RotationSpeed; + projectile.Visible = true; + + //if (data.LockPosition == false) + { + if (source.Flip != Microsoft.Xna.Framework.Graphics.SpriteEffects.None) + projectile.X = source.AbsX - data.SourceAnchor.X; + else + projectile.X = source.AbsX + data.SourceAnchor.X; + } + + //projectile.Flip = source.Flip; + + //if (data.LockPosition == false) + projectile.Y = source.AbsY + data.SourceAnchor.Y; + + projectile.IsWeighted = data.IsWeighted; + Vector2 targetPoint = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)); + + float speed = data.Speed.X; + if (data.Speed.X != data.Speed.Y) + speed = CDGMath.RandomFloat(data.Speed.X, data.Speed.Y); + + projectile.AccelerationX = targetPoint.X * speed; + projectile.AccelerationY = targetPoint.Y * speed; + projectile.CurrentSpeed = speed; + + //if (source.Flip != Microsoft.Xna.Framework.Graphics.SpriteEffects.None) + // projectile.AccelerationX = -projectile.AccelerationX; + + if (source is PlayerObj) + { + if (projectile.LifeSpan == 0) + projectile.LifeSpan = (source as PlayerObj).ProjectileLifeSpan; + projectile.CollisionTypeTag = GameTypes.CollisionType_PLAYER; + projectile.Scale = data.Scale; + } + else + { + if (projectile.LifeSpan == 0) + projectile.LifeSpan = 15; // All projectiles are given an arbitrary lifespan of 15 seconds (unless they die earlier than that). + projectile.CollisionTypeTag = GameTypes.CollisionType_ENEMY; + projectile.Scale = data.Scale; + } + + if (data.Target != null && data.Source.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally && data.ChaseTarget == true) + projectile.Orientation = MathHelper.ToRadians(180); + + if (data.Source is PlayerObj && (Game.PlayerStats.Traits.X == TraitType.Ambilevous ||Game.PlayerStats.Traits.Y == TraitType.Ambilevous)) + { + projectile.AccelerationX *= -1; + if (data.LockPosition == false) + { + if (data.Source.Flip == Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally) + projectile.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.None; + else + projectile.Flip = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally; + } + } + + projectile.PlayAnimation(true); + return projectile; + } + + public void DestroyProjectile(ProjectileObj projectile) + { + if (m_projectilePool.ActiveObjsList.Contains(projectile)) // Only destroy projectiles if they haven't already been destroyed. It is possible for two objects to call Destroy on the same projectile. + { + projectile.CollidesWithTerrain = true; + projectile.DestroyOnRoomTransition = true; + projectile.ChaseTarget = false; + projectile.Target = null; + projectile.Visible = false; + projectile.Scale = new Vector2(1, 1); + + projectile.CurrentSpeed = 0; + projectile.Opacity = 1; + projectile.IsAlive = false; + + projectile.IsCollidable = true; + m_levelScreen.PhysicsManager.RemoveObject(projectile); // Might be better to keep them in the physics manager and just turn off their collision detection. + m_projectilePool.CheckIn(projectile); + } + } + + public void DestroyAllProjectiles(bool destroyRoomTransitionProjectiles) + { + ProjectileObj[] activeProjectilesArray = m_projectilePool.ActiveObjsList.ToArray(); + foreach (ProjectileObj projectile in activeProjectilesArray) + { + if (destroyRoomTransitionProjectiles == true || (destroyRoomTransitionProjectiles == false && projectile.DestroyOnRoomTransition == true)) + DestroyProjectile(projectile); + } + + PerformProjectileCleanup(); + } + + public void PauseAllProjectiles(bool pausePlayerProjectiles) + { + foreach (ProjectileObj projectile in m_projectilePool.ActiveObjsList) + { + if (projectile.CollisionTypeTag != GameTypes.CollisionType_PLAYER || pausePlayerProjectiles == true) + { + projectile.GamePaused = true; + projectile.PauseAnimation(); + if (projectile.Spell != SpellType.DamageShield || (projectile.Spell == SpellType.DamageShield && projectile.CollisionTypeTag == GameTypes.CollisionType_ENEMY)) + { + projectile.AccelerationXEnabled = false; + projectile.AccelerationYEnabled = false; + } + } + } + + Tweener.Tween.PauseAllContaining(typeof(ProjectileObj)); + } + + public void UnpauseAllProjectiles() + { + foreach (ProjectileObj projectile in m_projectilePool.ActiveObjsList) + { + if (projectile.GamePaused == true) + { + projectile.GamePaused = false; + projectile.ResumeAnimation(); + if (projectile.Spell != SpellType.DamageShield || (projectile.Spell == SpellType.DamageShield && projectile.CollisionTypeTag == GameTypes.CollisionType_ENEMY)) + { + projectile.AccelerationXEnabled = true; + projectile.AccelerationYEnabled = true; + } + } + } + Tweener.Tween.ResumeAllContaining(typeof(ProjectileObj)); + } + + public void Update(GameTime gameTime) + { + RoomObj currentRoom = m_levelScreen.CurrentRoom; + + foreach (ProjectileObj projectile in m_projectilePool.ActiveObjsList) + { + if (projectile.WrapProjectile == true) + { + if (projectile.X < currentRoom.X) + projectile.X = currentRoom.X + currentRoom.Width; + else if (projectile.X > currentRoom.X + currentRoom.Width) + projectile.X = currentRoom.X; + } + projectile.Update(gameTime); + } + + // Removes any projectiles that exit the camera logic bounds. + if (currentRoom != null) + { + if (m_projectilesToRemoveList.Count > 0) + m_projectilesToRemoveList.Clear(); + + //foreach (ProjectileObj projectileToRemove in m_activeProjectilesList) + //{ + // if (projectileToRemove.X < m_levelScreen.CurrentRoom.X || projectileToRemove.X > m_levelScreen.CurrentRoom.X + m_levelScreen.CurrentRoom.Width) + // m_projectilesToRemoveList.Add(projectileToRemove); + // else if (projectileToRemove.Y < m_levelScreen.CurrentRoom.Y || projectileToRemove.Y > m_levelScreen.CurrentRoom.Y + m_levelScreen.CurrentRoom.Height) + // m_projectilesToRemoveList.Add(projectileToRemove); + //} + + foreach (ProjectileObj projectileToRemove in m_projectilePool.ActiveObjsList) + { + if (projectileToRemove.IsAlive == true && projectileToRemove.IsDying == false && projectileToRemove.IgnoreBoundsCheck == false) + { + // Projectiles cannot exit bounds of room. + if (projectileToRemove.Bounds.Left < m_levelScreen.CurrentRoom.Bounds.Left - 200 || projectileToRemove.Bounds.Right > m_levelScreen.CurrentRoom.Bounds.Right + 200) + m_projectilesToRemoveList.Add(projectileToRemove); + else if (projectileToRemove.Bounds.Bottom > m_levelScreen.CurrentRoom.Bounds.Bottom + 200) + m_projectilesToRemoveList.Add(projectileToRemove); + + /* + // Projectiles cannot exit camera bounds. + if (projectileToRemove.Bounds.Left < m_levelScreen.Camera.LogicBounds.Left || projectileToRemove.Bounds.Right > m_levelScreen.Camera.LogicBounds.Right) + m_projectilesToRemoveList.Add(projectileToRemove); + else if (projectileToRemove.Bounds.Top < m_levelScreen.Camera.LogicBounds.Top || projectileToRemove.Bounds.Bottom > m_levelScreen.Camera.LogicBounds.Bottom) + m_projectilesToRemoveList.Add(projectileToRemove); + */ + } + else if (projectileToRemove.IsAlive == false) + m_projectilesToRemoveList.Add(projectileToRemove); + } + + foreach (ProjectileObj obj in m_projectilesToRemoveList) + DestroyProjectile(obj); + } + } + + // This function is necessary because cleanup is done during the update call. But sometimes the game chops and the update call is late, causing problems with + // the pool determining which projectiles are alive, and which ones are awaiting cleanup. This function forces a cleanup call. + public void PerformProjectileCleanup() + { + if (m_levelScreen.CurrentRoom != null) + { + if (m_projectilesToRemoveList.Count > 0) + m_projectilesToRemoveList.Clear(); + + foreach (ProjectileObj projectileToRemove in m_projectilePool.ActiveObjsList) + { + if (projectileToRemove.IsAlive == true && projectileToRemove.IsDying == false && projectileToRemove.IgnoreBoundsCheck == false) + { + // Projectiles cannot exit bounds of room. + if (projectileToRemove.Bounds.Left < m_levelScreen.CurrentRoom.Bounds.Left - 200 || projectileToRemove.Bounds.Right > m_levelScreen.CurrentRoom.Bounds.Right + 200) + m_projectilesToRemoveList.Add(projectileToRemove); + else if (projectileToRemove.Bounds.Bottom > m_levelScreen.CurrentRoom.Bounds.Bottom + 200) + m_projectilesToRemoveList.Add(projectileToRemove); + } + else if (projectileToRemove.IsAlive == false) + m_projectilesToRemoveList.Add(projectileToRemove); + } + + foreach (ProjectileObj obj in m_projectilesToRemoveList) + DestroyProjectile(obj); + } + } + + public void Draw(Camera2D camera) + { + foreach (ProjectileObj projectile in m_projectilePool.ActiveObjsList) + { + //projectile.DrawOutline(camera, 2); + projectile.Draw(camera); + } + } + + public bool IsDisposed + { + get { return m_isDisposed;} + } + + public void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Projectile Manager"); + + m_levelScreen= null; + m_projectilePool.Dispose(); + m_projectilePool = null; + + m_projectilesToRemoveList.Clear(); + m_projectilesToRemoveList = null; + + m_isDisposed = true; + } + } + + public List ActiveProjectileList + { + get { return m_projectilePool.ActiveObjsList; } + } + + public int ActiveProjectiles + { + get { return m_projectilePool.NumActiveObjs; } + } + + public int TotalPoolSize + { + get { return m_projectilePool.TotalPoolSize; } + } + + public int CurrentPoolSize + { + get { return TotalPoolSize - ActiveProjectiles; } + } + } + + public class ProjectileData : IDisposable + { + bool m_isDisposed = false; + + public bool IsWeighted; + public string SpriteName; + public GameObj Source; + public GameObj Target; + public Vector2 SourceAnchor; + public float AngleOffset; + public Vector2 Angle; + public float RotationSpeed; + public int Damage; + public Vector2 Speed; + public Vector2 Scale = new Vector2(1, 1); + public bool CollidesWithTerrain = true; + public bool DestroysWithTerrain = true; + public float Lifespan = 10; + public float TurnSpeed = 10; + public bool ChaseTarget = false; + public bool FollowArc = false; + public float StartingRotation; + public bool ShowIcon = true; + public bool IsCollidable = true; + public bool DestroysWithEnemy = true; + public bool LockPosition = false; + public bool CollidesWith1Ways = false; + public bool DestroyOnRoomTransition = true; + public bool CanBeFusRohDahed = true; + public bool IgnoreInvincibleCounter = false; + public bool WrapProjectile = false; + + public ProjectileData(GameObj source) + { + if (source == null) + throw new Exception("Cannot create a projectile without a source"); + Source = source; + } + + public void Dispose() + { + if (IsDisposed == false) + { + //Done + Source = null; + Target = null; + m_isDisposed = true; + } + } + + public bool IsDisposed + { + get { return m_isDisposed; } + } + + public ProjectileData Clone() + { + return new ProjectileData(this.Source) + { + IsWeighted = this.IsWeighted, + SpriteName = this.SpriteName, + Source = this.Source, + Target = this.Target, + SourceAnchor = this.SourceAnchor, + AngleOffset = this.AngleOffset, + Angle = this.Angle, + RotationSpeed = this.RotationSpeed, + Damage = this.Damage, + Speed = this.Speed, + Scale = this.Scale, + CollidesWithTerrain = this.CollidesWithTerrain, + Lifespan = this.Lifespan, + ChaseTarget = this.ChaseTarget, + TurnSpeed = this.TurnSpeed, + FollowArc = this.FollowArc, + StartingRotation = this.StartingRotation, + ShowIcon = this.ShowIcon, + DestroysWithTerrain = this.DestroysWithTerrain, + IsCollidable = this.IsCollidable, + DestroysWithEnemy = this.DestroysWithEnemy, + LockPosition = this.LockPosition, + CollidesWith1Ways = this.CollidesWith1Ways, + DestroyOnRoomTransition = this.DestroyOnRoomTransition, + CanBeFusRohDahed = this.CanBeFusRohDahed, + IgnoreInvincibleCounter = this.IgnoreInvincibleCounter, + WrapProjectile = this.WrapProjectile, + }; + } + } +} diff --git a/RogueCastle/src/Managers/SaveGameManager.cs b/RogueCastle/src/Managers/SaveGameManager.cs new file mode 100644 index 0000000..986aa35 --- /dev/null +++ b/RogueCastle/src/Managers/SaveGameManager.cs @@ -0,0 +1,2276 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework.Storage; +using Microsoft.Xna.Framework; +using System.IO; +using DS2DEngine; + +namespace RogueCastle +{ + public class SaveGameManager + { + private StorageContainer m_storageContainer; + private string m_fileNamePlayer = "RogueLegacyPlayer.rcdat"; + private string m_fileNameUpgrades = "RogueLegacyBP.rcdat"; + private string m_fileNameMap = "RogueLegacyMap.rcdat"; + private string m_fileNameMapData = "RogueLegacyMapDat.rcdat"; + private string m_fileNameLineage = "RogueLegacyLineage.rcdat"; + private Game m_game; + + private int m_saveFailCounter; + private bool m_autosaveLoaded; + + public SaveGameManager(Game game) + { + m_saveFailCounter = 0; + m_autosaveLoaded = false; + m_game = game; + } + + public void Initialize() + { + if (LevelEV.RUN_DEMO_VERSION == true) + { + m_fileNamePlayer = "RogueLegacyDemoPlayer.rcdat"; + m_fileNameUpgrades = "RogueLegacyDemoBP.rcdat"; + m_fileNameMap = "RogueLegacyDemoMap.rcdat"; + m_fileNameMapData = "RogueLegacyDemoMapDat.rcdat"; + m_fileNameLineage = "RogueLegacyDemoLineage.rcdat"; + } + + if (m_storageContainer != null) + { + m_storageContainer.Dispose(); + m_storageContainer = null; + } + + PerformDirectoryCheck(); + } + + private void GetStorageContainer() + { + if (m_storageContainer == null || m_storageContainer.IsDisposed) + { + IAsyncResult aSyncResult = StorageDevice.BeginShowSelector(null, null); + aSyncResult.AsyncWaitHandle.WaitOne(); + StorageDevice storageDevice = StorageDevice.EndShowSelector(aSyncResult); + aSyncResult.AsyncWaitHandle.Close(); + aSyncResult = storageDevice.BeginOpenContainer("RogueLegacyStorageContainer", null, null); + aSyncResult.AsyncWaitHandle.WaitOne(); + m_storageContainer = storageDevice.EndOpenContainer(aSyncResult); + aSyncResult.AsyncWaitHandle.Close(); + } + } + + // This code was added to create profile directories in case the computer doesn't have them. + // Older versions of this game does not use directories. + private void PerformDirectoryCheck() + { + GetStorageContainer(); + + // Creating the directories. + if (m_storageContainer.DirectoryExists("Profile1") == false) + { + m_storageContainer.CreateDirectory("Profile1"); + + // Copying all files from the base directory into Profile1. + CopyFile(m_storageContainer, m_fileNamePlayer, "Profile1"); + CopyFile(m_storageContainer, "AutoSave_" + m_fileNamePlayer, "Profile1"); + + CopyFile(m_storageContainer, m_fileNameUpgrades, "Profile1"); + CopyFile(m_storageContainer, "AutoSave_" + m_fileNameUpgrades, "Profile1"); + + CopyFile(m_storageContainer, m_fileNameMap, "Profile1"); + CopyFile(m_storageContainer, "AutoSave_" + m_fileNameMap, "Profile1"); + + CopyFile(m_storageContainer, m_fileNameMapData, "Profile1"); + CopyFile(m_storageContainer, "AutoSave_" + m_fileNameMapData, "Profile1"); + + CopyFile(m_storageContainer, m_fileNameLineage, "Profile1"); + CopyFile(m_storageContainer, "AutoSave_" + m_fileNameLineage, "Profile1"); + } + if (m_storageContainer.DirectoryExists("Profile2") == false) + m_storageContainer.CreateDirectory("Profile2"); + if (m_storageContainer.DirectoryExists("Profile3") == false) + m_storageContainer.CreateDirectory("Profile3"); + + m_storageContainer.Dispose(); + m_storageContainer = null; + } + + private void CopyFile(StorageContainer storageContainer, string fileName, string profileName) + { + if (storageContainer.FileExists(fileName) == true) + { + Stream fileToCopy = storageContainer.OpenFile(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); + Stream copiedFile = storageContainer.CreateFile(profileName + "/" + fileName); + fileToCopy.CopyTo(copiedFile); + fileToCopy.Close(); + copiedFile.Close(); + } + } + + public void SaveFiles(params SaveType[] saveList) + { + if (LevelEV.DISABLE_SAVING == false) + { + GetStorageContainer(); + try + { + foreach (SaveType saveType in saveList) + SaveData(saveType, false); + m_saveFailCounter = 0; + } + //catch (IOException e) + catch + { + if (m_saveFailCounter > 2) + { + RCScreenManager manager = Game.ScreenManager; + manager.DialogueScreen.SetDialogue("Save File Error Antivirus"); + //manager.DisplayScreen(ScreenType.Dialogue, false, null); + Tweener.Tween.RunFunction(0.25f, manager, "DisplayScreen", ScreenType.Dialogue, true, typeof(List)); + m_saveFailCounter = 0; + } + else + { + m_saveFailCounter++; + } + } + finally + { + if (m_storageContainer != null && m_storageContainer.IsDisposed == false) + m_storageContainer.Dispose(); + m_storageContainer = null; + } + } + } + + public void SaveBackupFiles(params SaveType[] saveList) + { + if (LevelEV.DISABLE_SAVING == false) + { + GetStorageContainer(); + foreach (SaveType saveType in saveList) + SaveData(saveType, true); + m_storageContainer.Dispose(); + m_storageContainer = null; + } + } + + public void SaveAllFileTypes(bool saveBackup) + { + if (saveBackup == false) + SaveFiles(SaveType.PlayerData, SaveType.UpgradeData, SaveType.Map, SaveType.MapData, SaveType.Lineage); + else + SaveBackupFiles(SaveType.PlayerData, SaveType.UpgradeData, SaveType.Map, SaveType.MapData, SaveType.Lineage); + } + + public void LoadFiles(ProceduralLevelScreen level, params SaveType[] loadList) + { + if (LevelEV.ENABLE_BACKUP_SAVING == true) + { + GetStorageContainer(); + + SaveType currentType = SaveType.None; + + try + { + if (LevelEV.DISABLE_SAVING == false) + { + foreach (SaveType loadType in loadList) + { + currentType = loadType; + LoadData(loadType, level); + } + } + } + catch (Exception e) + { + Console.WriteLine("Save File Error: " + e.Message); + // Only perform autosave loading if you're not loading the map. This is because the map is loaded on a separate thread, so it needs to + // manually call ForceBackup() once the thread has exited. + if (currentType != SaveType.Map && currentType != SaveType.MapData && currentType != SaveType.None) + { + if (m_autosaveLoaded == false) + { + RCScreenManager manager = Game.ScreenManager; + manager.DialogueScreen.SetDialogue("Save File Error"); + //manager.DialogueScreen.SetDialogue("Save File Error 2"); + Game.gameIsCorrupt = true; + manager.DialogueScreen.SetConfirmEndHandler(this, "LoadAutosave"); + //manager.DialogueScreen.SetConfirmEndHandler(m_game, "Exit"); + manager.DisplayScreen(ScreenType.Dialogue, false, null); + // Just a small trigger to make sure the game knows the file is corrupt, and to stop doing whatever it's doing. + Game.PlayerStats.HeadPiece = 0; + + } + else + { + m_autosaveLoaded = false; + RCScreenManager manager = Game.ScreenManager; + manager.DialogueScreen.SetDialogue("Save File Error 2"); + //manager.DialogueScreen.SetConfirmEndHandler(this, "StartNewGame"); + Game.gameIsCorrupt = true; + manager.DialogueScreen.SetConfirmEndHandler(m_game, "Exit"); + manager.DisplayScreen(ScreenType.Dialogue, false, null); + + // Just a small trigger to make sure the game knows the file is corrupt, and to stop doing whatever it's doing. + Game.PlayerStats.HeadPiece = 0; + } + } + else throw new Exception(); // This triggers the try/catch block in the loading screen + } + finally + { + if (m_storageContainer != null && m_storageContainer.IsDisposed == false) + m_storageContainer.Dispose(); + } + } + else + { + if (LevelEV.DISABLE_SAVING == false) + { + GetStorageContainer(); + foreach (SaveType loadType in loadList) + LoadData(loadType, level); + m_storageContainer.Dispose(); + m_storageContainer = null; + } + } + } + + public void ForceBackup() + { + if (m_storageContainer != null && m_storageContainer.IsDisposed == false) + m_storageContainer.Dispose(); + RCScreenManager manager = Game.ScreenManager; + manager.DialogueScreen.SetDialogue("Save File Error"); + manager.DialogueScreen.SetConfirmEndHandler(this, "LoadAutosave"); + manager.DisplayScreen(ScreenType.Dialogue, false, null); + } + + public void LoadAutosave() + { + Console.WriteLine("Save file corrupted"); + SkillSystem.ResetAllTraits(); + Game.PlayerStats.Dispose(); + Game.PlayerStats = new PlayerStats(); + Game.ScreenManager.Player.Reset(); + LoadBackups(); + Game.ScreenManager.DisplayScreen(ScreenType.Title, true); + } + + public void StartNewGame() + { + this.ClearAllFileTypes(false); + this.ClearAllFileTypes(true); + SkillSystem.ResetAllTraits(); + Game.PlayerStats.Dispose(); + Game.PlayerStats = new PlayerStats(); + Game.ScreenManager.Player.Reset(); + Game.ScreenManager.DisplayScreen(ScreenType.TutorialRoom, true); + } + + public void ResetAutosave() + { + m_autosaveLoaded = false; + } + + public void LoadAllFileTypes(ProceduralLevelScreen level) + { + LoadFiles(level, SaveType.PlayerData, SaveType.UpgradeData, SaveType.Map, SaveType.MapData, SaveType.Lineage); + } + + public void ClearFiles(params SaveType[] deleteList) + { + GetStorageContainer(); + foreach (SaveType deleteType in deleteList) + DeleteData(deleteType); + m_storageContainer.Dispose(); + m_storageContainer = null; + } + + public void ClearBackupFiles(params SaveType[] deleteList) + { + GetStorageContainer(); + foreach (SaveType deleteType in deleteList) + DeleteBackupData(deleteType); + m_storageContainer.Dispose(); + m_storageContainer = null; + } + + public void ClearAllFileTypes(bool deleteBackups) + { + if (deleteBackups == false) + ClearFiles(SaveType.PlayerData, SaveType.UpgradeData, SaveType.Map, SaveType.MapData, SaveType.Lineage); + else + ClearBackupFiles(SaveType.PlayerData, SaveType.UpgradeData, SaveType.Map, SaveType.MapData, SaveType.Lineage); + } + + private void DeleteData(SaveType deleteType) + { + switch (deleteType) + { + case (SaveType.PlayerData): + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNamePlayer)) + m_storageContainer.DeleteFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNamePlayer); + break; + case (SaveType.UpgradeData): + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameUpgrades)) + m_storageContainer.DeleteFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameUpgrades); + break; + case (SaveType.Map): + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameMap)) + m_storageContainer.DeleteFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameMap); + break; + case (SaveType.MapData): + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameMapData)) + m_storageContainer.DeleteFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameMapData); + break; + case (SaveType.Lineage): + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameLineage)) + m_storageContainer.DeleteFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameLineage); + break; + } + + Console.WriteLine("Save file type " + deleteType + " deleted."); + } + + private void DeleteBackupData(SaveType deleteType) + { + switch (deleteType) + { + case (SaveType.PlayerData): + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNamePlayer)) + m_storageContainer.DeleteFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNamePlayer); + break; + case (SaveType.UpgradeData): + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameUpgrades)) + m_storageContainer.DeleteFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameUpgrades); + break; + case (SaveType.Map): + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameMap)) + m_storageContainer.DeleteFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameMap); + break; + case (SaveType.MapData): + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameMapData)) + m_storageContainer.DeleteFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameMapData); + break; + case (SaveType.Lineage): + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameLineage)) + m_storageContainer.DeleteFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameLineage); + break; + } + + Console.WriteLine("Backup save file type " + deleteType + " deleted."); + } + + private void LoadBackups() + { + Console.WriteLine("Replacing save file with back up saves"); + GetStorageContainer(); + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNamePlayer) && m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNamePlayer)) + { + Stream fileToCopy = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNamePlayer, FileMode.Open, FileAccess.Read, FileShare.Read); // Open the backup + + // Copy the backup prior to corruption revert. This is in case the loading didn't work, and all data is lost (since backups get overwritten once people start playing again. + Stream backupCopy = m_storageContainer.CreateFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSaveBACKUP_" + m_fileNamePlayer); + fileToCopy.CopyTo(backupCopy); + backupCopy.Close(); + fileToCopy.Close(); + + fileToCopy = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNamePlayer, FileMode.Open, FileAccess.Read, FileShare.Read); // Open the backup + Stream fileToOverride = m_storageContainer.CreateFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNamePlayer); // Create a new file + fileToCopy.CopyTo(fileToOverride); // Copy the backup to the new file. + + fileToCopy.Close(); + fileToOverride.Close(); + } + + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameUpgrades) && m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameUpgrades)) + { + Stream fileToCopy = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameUpgrades, FileMode.Open, FileAccess.Read, FileShare.Read); // Open the backup + + // Copy the backup prior to corruption revert. This is in case the loading didn't work, and all data is lost (since backups get overwritten once people start playing again. + Stream backupCopy = m_storageContainer.CreateFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSaveBACKUP_" + m_fileNameUpgrades); + fileToCopy.CopyTo(backupCopy); + backupCopy.Close(); + fileToCopy.Close(); + + fileToCopy = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameUpgrades, FileMode.Open, FileAccess.Read, FileShare.Read); // Open the backup + Stream fileToOverride = m_storageContainer.CreateFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameUpgrades); // Create a new file + fileToCopy.CopyTo(fileToOverride); // Copy the backup to the new file. + + fileToCopy.Close(); + fileToOverride.Close(); + } + + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameMap) && m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameMap)) + { + Stream fileToCopy = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameMap, FileMode.Open, FileAccess.Read, FileShare.Read); // Open the backup + + // Copy the backup prior to corruption revert. This is in case the loading didn't work, and all data is lost (since backups get overwritten once people start playing again. + Stream backupCopy = m_storageContainer.CreateFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSaveBACKUP_" + m_fileNameMap); + fileToCopy.CopyTo(backupCopy); + backupCopy.Close(); + fileToCopy.Close(); + + fileToCopy = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameMap, FileMode.Open, FileAccess.Read, FileShare.Read); // Open the backup + Stream fileToOverride = m_storageContainer.CreateFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameMap); // Create a new file + fileToCopy.CopyTo(fileToOverride); // Copy the backup to the new file. + + fileToCopy.Close(); + fileToOverride.Close(); + } + + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameMapData) && m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameMapData)) + { + Stream fileToCopy = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameMapData, FileMode.Open, FileAccess.Read, FileShare.Read); // Open the backup + + // Copy the backup prior to corruption revert. This is in case the loading didn't work, and all data is lost (since backups get overwritten once people start playing again. + Stream backupCopy = m_storageContainer.CreateFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSaveBACKUP_" + m_fileNameMapData); + fileToCopy.CopyTo(backupCopy); + backupCopy.Close(); + fileToCopy.Close(); + + fileToCopy = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameMapData, FileMode.Open, FileAccess.Read, FileShare.Read); // Open the backup + Stream fileToOverride = m_storageContainer.CreateFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameMapData); // Create a new file + fileToCopy.CopyTo(fileToOverride); // Copy the backup to the new file. + + fileToCopy.Close(); + fileToOverride.Close(); + } + + if (m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameLineage) && m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameLineage)) + { + Stream fileToCopy = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameLineage, FileMode.Open, FileAccess.Read, FileShare.Read); // Open the backup + + // Copy the backup prior to corruption revert. This is in case the loading didn't work, and all data is lost (since backups get overwritten once people start playing again. + Stream backupCopy = m_storageContainer.CreateFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSaveBACKUP_" + m_fileNameLineage); + fileToCopy.CopyTo(backupCopy); + backupCopy.Close(); + fileToCopy.Close(); + + fileToCopy = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + "AutoSave_" + m_fileNameLineage, FileMode.Open, FileAccess.Read, FileShare.Read); // Open the backup + Stream fileToOverride = m_storageContainer.CreateFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameLineage); // Create a new file + fileToCopy.CopyTo(fileToOverride); // Copy the backup to the new file. + + fileToCopy.Close(); + fileToOverride.Close(); + } + m_autosaveLoaded = true; + m_storageContainer.Dispose(); + m_storageContainer = null; + } + + private void SaveData(SaveType saveType, bool saveBackup) + { + switch (saveType) + { + case (SaveType.PlayerData): + SavePlayerData(saveBackup); + break; + case (SaveType.UpgradeData): + SaveUpgradeData(saveBackup); + break; + case (SaveType.Map): + SaveMap(saveBackup); + break; + case (SaveType.MapData): + SaveMapData(saveBackup); + break; + case (SaveType.Lineage): + SaveLineageData(saveBackup); + break; + } + Console.WriteLine("\nData type " + saveType + " saved!"); + } + + private void SavePlayerData(bool saveBackup) + { + string fileName = m_fileNamePlayer; + if (saveBackup == true) + fileName = fileName.Insert(0, "AutoSave_"); + fileName = fileName.Insert(0, "Profile" + Game.GameConfig.ProfileSlot + "/"); + + // If you have an old version save file, update the name to match the new format before saving. + if (Game.PlayerStats.RevisionNumber <= 0) + { + string playerName = Game.PlayerStats.PlayerName; + string romanNumeral = ""; + Game.ConvertPlayerNameFormat(ref playerName, ref romanNumeral); + Game.PlayerStats.PlayerName = playerName; + Game.PlayerStats.RomanNumeral = romanNumeral; + } + + using (Stream stream = m_storageContainer.CreateFile(fileName)) + //using (Stream stream = m_storageContainer.OpenFile(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) + { + using (BinaryWriter writer = new BinaryWriter(stream)) + { + // Saving player gold. (int32) + writer.Write(Game.PlayerStats.Gold); + + // Saving player health. (int32) + Game.PlayerStats.CurrentHealth = Game.ScreenManager.Player.CurrentHealth; + writer.Write(Game.PlayerStats.CurrentHealth); + // Saving player mana. (int32) + Game.PlayerStats.CurrentMana = (int)Game.ScreenManager.Player.CurrentMana; + writer.Write(Game.PlayerStats.CurrentMana); + + // Saving player Age. (byte) + writer.Write(Game.PlayerStats.Age); + // Saving player's Child Age (byte) + writer.Write(Game.PlayerStats.ChildAge); + // Saving player spell (byte) + writer.Write(Game.PlayerStats.Spell); + // Saving player class (byte) + writer.Write(Game.PlayerStats.Class); + // Saving player special item (byte) + writer.Write(Game.PlayerStats.SpecialItem); + // Saving traits. Saved as bytes, but should be loaded into a Vector2. + writer.Write((byte)Game.PlayerStats.Traits.X); + writer.Write((byte)Game.PlayerStats.Traits.Y); + // Saving player name (string) + writer.Write(Game.PlayerStats.PlayerName); + + // Saving player parts. All bytes. + writer.Write(Game.PlayerStats.HeadPiece); + writer.Write(Game.PlayerStats.ShoulderPiece); + writer.Write(Game.PlayerStats.ChestPiece); + + // Saving diary entry (byte) + writer.Write(Game.PlayerStats.DiaryEntry); + + // Saving bonus stats. All int32s. + writer.Write(Game.PlayerStats.BonusHealth); + writer.Write(Game.PlayerStats.BonusStrength); + writer.Write(Game.PlayerStats.BonusMana); + writer.Write(Game.PlayerStats.BonusDefense); + writer.Write(Game.PlayerStats.BonusWeight); + writer.Write(Game.PlayerStats.BonusMagic); + + // Saving lich health and mana. Only needed for lich. + writer.Write(Game.PlayerStats.LichHealth); // int32 + writer.Write(Game.PlayerStats.LichMana); // int32 + writer.Write(Game.PlayerStats.LichHealthMod); // Single + + // Saving boss progress. All bools. + writer.Write(Game.PlayerStats.NewBossBeaten); + writer.Write(Game.PlayerStats.EyeballBossBeaten); + writer.Write(Game.PlayerStats.FairyBossBeaten); + writer.Write(Game.PlayerStats.FireballBossBeaten); + writer.Write(Game.PlayerStats.BlobBossBeaten); + writer.Write(Game.PlayerStats.LastbossBeaten); + + // Saving the number of times the castle was beaten (for new game plus) and number of enemies beaten (for rank). (int32) + writer.Write(Game.PlayerStats.TimesCastleBeaten); + writer.Write(Game.PlayerStats.NumEnemiesBeaten); + + // Saving misc. flags. + // Saving castle lock state. Bool. + writer.Write(Game.PlayerStats.TutorialComplete); + writer.Write(Game.PlayerStats.CharacterFound); + writer.Write(Game.PlayerStats.LoadStartingRoom); + + writer.Write(Game.PlayerStats.LockCastle); + writer.Write(Game.PlayerStats.SpokeToBlacksmith); + writer.Write(Game.PlayerStats.SpokeToEnchantress); + writer.Write(Game.PlayerStats.SpokeToArchitect); + writer.Write(Game.PlayerStats.SpokeToTollCollector); + writer.Write(Game.PlayerStats.IsDead); + writer.Write(Game.PlayerStats.FinalDoorOpened); + writer.Write(Game.PlayerStats.RerolledChildren); + writer.Write(Game.PlayerStats.IsFemale); + writer.Write(Game.PlayerStats.TimesDead); // int32; + writer.Write(Game.PlayerStats.HasArchitectFee); + writer.Write(Game.PlayerStats.ReadLastDiary); + writer.Write(Game.PlayerStats.SpokenToLastBoss); + writer.Write(Game.PlayerStats.HardcoreMode); + + Game.PlayerStats.TotalHoursPlayed += Game.HoursPlayedSinceLastSave; + Game.HoursPlayedSinceLastSave = 0; + writer.Write(Game.PlayerStats.TotalHoursPlayed); + + // Saving the wizard spell list. + writer.Write((byte)Game.PlayerStats.WizardSpellList.X); + writer.Write((byte)Game.PlayerStats.WizardSpellList.Y); + writer.Write((byte)Game.PlayerStats.WizardSpellList.Z); + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + Console.WriteLine("\nSaving Player Stats"); + Console.WriteLine("Gold: " + Game.PlayerStats.Gold); + Console.WriteLine("Current Health: " + Game.PlayerStats.CurrentHealth); + Console.WriteLine("Current Mana: " + Game.PlayerStats.CurrentMana); + Console.WriteLine("Age: " + Game.PlayerStats.Age); + Console.WriteLine("Child Age: " + Game.PlayerStats.ChildAge); + Console.WriteLine("Spell: " + Game.PlayerStats.Spell); + Console.WriteLine("Class: " + Game.PlayerStats.Class); + Console.WriteLine("Special Item: " + Game.PlayerStats.SpecialItem); + Console.WriteLine("Traits: " + Game.PlayerStats.Traits.X + ", " + Game.PlayerStats.Traits.Y); + Console.WriteLine("Name: " + Game.PlayerStats.PlayerName); + Console.WriteLine("---------------"); + Console.WriteLine("Head Piece: " + Game.PlayerStats.HeadPiece); + Console.WriteLine("Shoulder Piece: " + Game.PlayerStats.ShoulderPiece); + Console.WriteLine("Chest Piece: " + Game.PlayerStats.ChestPiece); + Console.WriteLine("---------------"); + Console.WriteLine("Diary Entry: " + Game.PlayerStats.DiaryEntry); + Console.WriteLine("---------------"); + Console.WriteLine("Bonus Health: " + Game.PlayerStats.BonusHealth); + Console.WriteLine("Bonus Strength: " + Game.PlayerStats.BonusStrength); + Console.WriteLine("Bonus Mana: " + Game.PlayerStats.BonusMana); + Console.WriteLine("Bonus Armor: " + Game.PlayerStats.BonusDefense); + Console.WriteLine("Bonus Weight: " + Game.PlayerStats.BonusWeight); + Console.WriteLine("Bonus Magic: " + Game.PlayerStats.BonusMagic); + Console.WriteLine("---------------"); + Console.WriteLine("Lich Health: " + Game.PlayerStats.LichHealth); + Console.WriteLine("Lich Mana: " + Game.PlayerStats.LichMana); + Console.WriteLine("Lich Health Mod: " + Game.PlayerStats.LichHealthMod); + Console.WriteLine("---------------"); + Console.WriteLine("New Boss Beaten: " + Game.PlayerStats.NewBossBeaten); + Console.WriteLine("Eyeball Boss Beaten: " + Game.PlayerStats.EyeballBossBeaten); + Console.WriteLine("Fairy Boss Beaten: " + Game.PlayerStats.FairyBossBeaten); + Console.WriteLine("Fireball Boss Beaten: " + Game.PlayerStats.FireballBossBeaten); + Console.WriteLine("Blob Boss Beaten: " + Game.PlayerStats.BlobBossBeaten); + Console.WriteLine("Last Boss Beaten: " + Game.PlayerStats.LastbossBeaten); + Console.WriteLine("---------------"); + Console.WriteLine("Times Castle Beaten: " + Game.PlayerStats.TimesCastleBeaten); + Console.WriteLine("Number of Enemies Beaten: " + Game.PlayerStats.NumEnemiesBeaten); + Console.WriteLine("---------------"); + Console.WriteLine("Tutorial Complete: " + Game.PlayerStats.TutorialComplete); + Console.WriteLine("Character Found: " + Game.PlayerStats.CharacterFound); + Console.WriteLine("Load Starting Room: " + Game.PlayerStats.LoadStartingRoom); + Console.WriteLine("---------------"); + Console.WriteLine("Spoke to Blacksmith: " + Game.PlayerStats.SpokeToBlacksmith); + Console.WriteLine("Spoke to Enchantress: " + Game.PlayerStats.SpokeToEnchantress); + Console.WriteLine("Spoke to Architect: " + Game.PlayerStats.SpokeToArchitect); + Console.WriteLine("Spoke to Toll Collector: " + Game.PlayerStats.SpokeToTollCollector); + Console.WriteLine("Player Is Dead: " + Game.PlayerStats.IsDead); + Console.WriteLine("Final Door Opened: " + Game.PlayerStats.FinalDoorOpened); + Console.WriteLine("Rerolled Children: " + Game.PlayerStats.RerolledChildren); + Console.WriteLine("Is Female: " + Game.PlayerStats.IsFemale); + Console.WriteLine("Times Dead: " + Game.PlayerStats.TimesDead); + Console.WriteLine("Has Architect Fee: " + Game.PlayerStats.HasArchitectFee); + Console.WriteLine("Player read last diary: " + Game.PlayerStats.ReadLastDiary); + Console.WriteLine("Player has spoken to last boss: " + Game.PlayerStats.SpokenToLastBoss); + Console.WriteLine("Is Hardcore mode: " + Game.PlayerStats.HardcoreMode); + Console.WriteLine("Total Hours Played " + Game.PlayerStats.TotalHoursPlayed); + Console.WriteLine("Wizard Spell 1: " + Game.PlayerStats.WizardSpellList.X); + Console.WriteLine("Wizard Spell 2: " + Game.PlayerStats.WizardSpellList.Y); + Console.WriteLine("Wizard Spell 3: " + Game.PlayerStats.WizardSpellList.Z); + } + + Console.WriteLine("///// ENEMY LIST DATA - BEGIN SAVING /////"); + // Saving the currently created branch. + List enemyList = Game.PlayerStats.EnemiesKilledList; + foreach (Vector4 enemy in enemyList) + { + writer.Write((byte)enemy.X); + writer.Write((byte)enemy.Y); + writer.Write((byte)enemy.Z); + writer.Write((byte)enemy.W); + } + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + Console.WriteLine("Saving Enemy List Data"); + int counter = 0; + foreach (Vector4 enemy in enemyList) + { + Console.WriteLine("Enemy Type: " + counter + ", Difficulty: Basic, Killed: " + enemy.X); + Console.WriteLine("Enemy Type: " + counter + ", Difficulty: Advanced, Killed: " + enemy.Y); + Console.WriteLine("Enemy Type: " + counter + ", Difficulty: Expert, Killed: " + enemy.Z); + Console.WriteLine("Enemy Type: " + counter + ", Difficulty: Miniboss, Killed: " + enemy.W); + counter++; + } + } + + int numKilledEnemiesInRun = Game.PlayerStats.EnemiesKilledInRun.Count; + List enemiesKilledInRun = Game.PlayerStats.EnemiesKilledInRun; + writer.Write(numKilledEnemiesInRun); + + foreach (Vector2 enemyData in enemiesKilledInRun) + { + writer.Write((int)enemyData.X); // Saving enemy's room location. + writer.Write((int)enemyData.Y); // Saving enemy's index in that specific room. + } + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + Console.WriteLine("Saving num enemies killed"); + Console.WriteLine("Number of enemies killed in run: " + numKilledEnemiesInRun); + foreach (Vector2 enemy in enemiesKilledInRun) + { + Console.WriteLine("Enemy Room Index: " + enemy.X); + Console.WriteLine("Enemy Index in EnemyList: " + enemy.Y); + } + } + + Console.WriteLine("///// ENEMY LIST DATA - SAVE COMPLETE /////"); + + Console.WriteLine("///// DLC DATA - BEGIN SAVING /////"); + // Saving Challenge Room Data. All bools. + writer.Write(Game.PlayerStats.ChallengeEyeballUnlocked); + writer.Write(Game.PlayerStats.ChallengeSkullUnlocked); + writer.Write(Game.PlayerStats.ChallengeFireballUnlocked); + writer.Write(Game.PlayerStats.ChallengeBlobUnlocked); + writer.Write(Game.PlayerStats.ChallengeLastBossUnlocked); + + writer.Write(Game.PlayerStats.ChallengeEyeballBeaten); + writer.Write(Game.PlayerStats.ChallengeSkullBeaten); + writer.Write(Game.PlayerStats.ChallengeFireballBeaten); + writer.Write(Game.PlayerStats.ChallengeBlobBeaten); + writer.Write(Game.PlayerStats.ChallengeLastBossBeaten); + + writer.Write(Game.PlayerStats.ChallengeEyeballTimesUpgraded); + writer.Write(Game.PlayerStats.ChallengeSkullTimesUpgraded); + writer.Write(Game.PlayerStats.ChallengeFireballTimesUpgraded); + writer.Write(Game.PlayerStats.ChallengeBlobTimesUpgraded); + writer.Write(Game.PlayerStats.ChallengeLastBossTimesUpgraded); + + writer.Write(Game.PlayerStats.RomanNumeral); + writer.Write(Game.PlayerStats.HasProsopagnosia); + writer.Write(LevelEV.SAVEFILE_REVISION_NUMBER); + writer.Write(Game.PlayerStats.ArchitectUsed); + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + Console.WriteLine("Eyeball Challenge Unlocked: " + Game.PlayerStats.ChallengeEyeballUnlocked); + Console.WriteLine("Skull Challenge Unlocked: " + Game.PlayerStats.ChallengeSkullUnlocked); + Console.WriteLine("Fireball Challenge Unlocked: " + Game.PlayerStats.ChallengeFireballUnlocked); + Console.WriteLine("Blob Challenge Unlocked: " + Game.PlayerStats.ChallengeBlobUnlocked); + Console.WriteLine("Last Boss Challenge Unlocked: " + Game.PlayerStats.ChallengeLastBossUnlocked); + + Console.WriteLine("Eyeball Challenge Beaten: " + Game.PlayerStats.ChallengeEyeballBeaten); + Console.WriteLine("Skull Challenge Beaten: " + Game.PlayerStats.ChallengeSkullBeaten); + Console.WriteLine("Fireball Challenge Beaten: " + Game.PlayerStats.ChallengeFireballBeaten); + Console.WriteLine("Blob Challenge Beaten: " + Game.PlayerStats.ChallengeBlobBeaten); + Console.WriteLine("Last Boss Challenge Beaten: " + Game.PlayerStats.ChallengeLastBossBeaten); + + Console.WriteLine("Eyeball Challenge Times Upgraded: " + Game.PlayerStats.ChallengeEyeballTimesUpgraded); + Console.WriteLine("Skull Challenge Times Upgraded: " + Game.PlayerStats.ChallengeSkullTimesUpgraded); + Console.WriteLine("Fireball Challenge Times Upgraded: " + Game.PlayerStats.ChallengeFireballTimesUpgraded); + Console.WriteLine("Blob Challenge Times Upgraded: " + Game.PlayerStats.ChallengeBlobTimesUpgraded); + Console.WriteLine("Last Boss Challenge Times Upgraded: " + Game.PlayerStats.ChallengeLastBossTimesUpgraded); + + Console.WriteLine("Player Name Number: " + Game.PlayerStats.RomanNumeral); + Console.WriteLine("Player HasProsopagnosia: " + Game.PlayerStats.HasProsopagnosia); + Console.WriteLine("Save File Revision Number: " + LevelEV.SAVEFILE_REVISION_NUMBER); + Console.WriteLine("Architect used: " + Game.PlayerStats.ArchitectUsed); + } + + Console.WriteLine("///// DLC DATA - SAVE COMPLETE /////"); + + if (saveBackup == true) + { + FileStream fileStream = stream as FileStream; + if (fileStream != null) + fileStream.Flush(true); + } + + writer.Close(); + } + + stream.Close(); + } + } + + private void SaveUpgradeData(bool saveBackup) + { + string fileName = m_fileNameUpgrades; + if (saveBackup == true) + fileName = fileName.Insert(0, "AutoSave_"); + fileName = fileName.Insert(0, "Profile" + Game.GameConfig.ProfileSlot + "/"); + + using (Stream stream = m_storageContainer.CreateFile(fileName)) + { + using (BinaryWriter writer = new BinaryWriter(stream)) + { + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.WriteLine("\nSaving Equipment States"); + + // Saving the base equipment states. + List blueprintArray = Game.PlayerStats.GetBlueprintArray; + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.WriteLine("Standard Blueprints"); + foreach (byte[] categoryType in blueprintArray) + { + foreach (byte equipmentState in categoryType) + { + writer.Write(equipmentState); + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write(" " + equipmentState); + } + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write("\n"); + } + + // Saving the ability equipment states. + List abilityBPArray = Game.PlayerStats.GetRuneArray; + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.WriteLine("\nRune Blueprints"); + foreach (byte[] categoryType in abilityBPArray) + { + foreach (byte equipmentState in categoryType) + { + writer.Write(equipmentState); + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write(" " + equipmentState); + } + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write("\n"); + } + + // Saving equipped items + sbyte[] equippedArray = Game.PlayerStats.GetEquippedArray; + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.WriteLine("\nEquipped Standard Item"); + foreach (sbyte equipmentState in equippedArray) + { + writer.Write(equipmentState); + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write(" " + equipmentState); + } + + // Saving equipped abilities + sbyte[] equippedAbilityArray = Game.PlayerStats.GetEquippedRuneArray; + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.WriteLine("\nEquipped Abilities"); + foreach (sbyte equipmentState in equippedAbilityArray) + { + writer.Write(equipmentState); + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write(" " + equipmentState); + } + + // Saving skills data. + SkillObj[] skillArray = SkillSystem.GetSkillArray(); + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.WriteLine("\nskills"); + foreach (SkillObj skill in skillArray) + { + writer.Write(skill.CurrentLevel); + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write(" " + skill.CurrentLevel); + } + + if (saveBackup == true) + { + FileStream fileStream = stream as FileStream; + if (fileStream != null) + fileStream.Flush(true); + } + + writer.Close(); + } + stream.Close(); + } + } + + private void SaveMap(bool saveBackup) + { + string fileName = m_fileNameMap; + if (saveBackup == true) + fileName = fileName.Insert(0, "AutoSave_"); + fileName = fileName.Insert(0, "Profile" + Game.GameConfig.ProfileSlot + "/"); + + using (Stream stream = m_storageContainer.CreateFile(fileName)) + { + using (BinaryWriter writer = new BinaryWriter(stream)) + { + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.WriteLine("\nSaving Map"); + + int newlineCounter = 0; + + ProceduralLevelScreen levelToSave = Game.ScreenManager.GetLevelScreen(); + if (levelToSave != null) + { + + //Console.WriteLine("START"); + //foreach (RoomObj room in levelToSave.RoomList) + //{ + // if (room.Name != "Boss" && room.Name != "Compass" && room.Name != "Bonus") + // { + // int count = 0; + // foreach (GameObj obj in room.GameObjList) + // { + // if (obj is ChestObj) + // count++; + // } + // Console.WriteLine(count); + // } + //} + //Console.WriteLine("END"); + + //Console.WriteLine("Enemy start"); + //foreach (RoomObj room in levelToSave.RoomList) + //{ + // int count = 0; + // foreach (EnemyObj enemy in room.EnemyList) + // { + // if (enemy.IsProcedural == true) + // count++; + // } + // Console.WriteLine(count); + //} + //Console.WriteLine("Enemy End"); + + // Store the number of rooms in the level first. + if (LevelEV.RUN_DEMO_VERSION == true) + writer.Write(levelToSave.RoomList.Count - 4); // Subtracting only 3 rooms because the demo only has 2 bosses (castle + last boss + tutorial room + compass). IF THIS EVER CHANGES, THIS NEEDS TO BE CHANGED TOO. + else + writer.Write(levelToSave.RoomList.Count - 12); // Subtracting the 5 boss rooms + the tutorial room + compass room + 5 challenge rooms. + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.WriteLine("Map size: " + (levelToSave.RoomList.Count - 12)); // Subtracting the 5 boss rooms + the tutorial room + the compass room + 5 challenge rooms. + + List enemyTypeList = new List(); + List enemyDifficultyList = new List(); + + // Storing the actual map. + foreach (RoomObj room in levelToSave.RoomList) + { + if (room.Name != "Boss" && room.Name != "Tutorial" && room.Name != "Ending" && room.Name != "Compass" && room.Name != "ChallengeBoss")// && room.Name != "Bonus") // Do not store boss rooms because they will be added when loaded. + { + // Saving the room's pool index. + writer.Write((int)room.PoolIndex); + // Saving the level type of the room. (byte) + writer.Write((byte)room.LevelType); + // Saving the level's position. (int) + writer.Write((int)room.X); + writer.Write((int)room.Y); + + // Saving the room's colour. + writer.Write((byte)room.TextureColor.R); + writer.Write((byte)room.TextureColor.G); + writer.Write((byte)room.TextureColor.B); + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write("I:" + room.PoolIndex + " T:" + (int)room.LevelType + ", "); + newlineCounter++; + if (newlineCounter > 5) + { + newlineCounter = 0; + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write("\n"); + } + + foreach (EnemyObj enemy in room.EnemyList) + { + if (enemy.IsProcedural == true) + { + enemyTypeList.Add(enemy.Type); + enemyDifficultyList.Add((byte)enemy.Difficulty); + } + } + } + } + + // Saving the enemies in the level + int numEnemies = enemyTypeList.Count; + writer.Write(numEnemies); // Saving the number of enemies in the game. (int32) + foreach (byte enemyType in enemyTypeList) + writer.Write(enemyType); //(byte) + + // Saving the difficulty of each enemy. + foreach (byte enemyDifficulty in enemyDifficultyList) + writer.Write(enemyDifficulty); + } + else + Console.WriteLine("WARNING: Attempting to save LEVEL screen but it was null. Make sure it exists in the screen manager before saving it."); + + if (saveBackup == true) + { + FileStream fileStream = stream as FileStream; + if (fileStream != null) + fileStream.Flush(true); + } + + writer.Close(); + } + stream.Close(); + } + } + + private void SaveMapData(bool saveBackup) + { + string fileName = m_fileNameMapData; + if (saveBackup == true) + fileName = fileName.Insert(0, "AutoSave_"); + fileName = fileName.Insert(0, "Profile" + Game.GameConfig.ProfileSlot + "/"); + + using (Stream stream = m_storageContainer.CreateFile(fileName)) + { + using (BinaryWriter writer = new BinaryWriter(stream)) + { + ProceduralLevelScreen levelToSave = Game.ScreenManager.GetLevelScreen(); + if (levelToSave != null) + { + List levelMapList = levelToSave.MapRoomsAdded; + + List roomVisited = new List(); + List bonusRoomCompleted = new List(); + List bonusRoomData = new List(); + List chestOpened = new List(); + List chestTypes = new List(); + List fairyChestFailed = new List(); + List enemyDead = new List(); + List breakablesOpened = new List(); + + foreach (RoomObj room in levelToSave.RoomList) + { + if (levelMapList.Contains(room)) + roomVisited.Add(true); + else + roomVisited.Add(false); + + BonusRoomObj bonusRoom = room as BonusRoomObj; + if (bonusRoom != null) + { + if (bonusRoom.RoomCompleted == true) + bonusRoomCompleted.Add(true); + else + bonusRoomCompleted.Add(false); + + bonusRoomData.Add(bonusRoom.ID); + } + + if (room.Name != "Boss" && room.Name != "ChallengeBoss")// && room.Name != "Bonus") + { + foreach (EnemyObj enemy in room.EnemyList) + { + if (enemy.IsKilled == true) + enemyDead.Add(true); + else + enemyDead.Add(false); + } + } + + if (room.Name != "Bonus" && room.Name != "Boss" && room.Name != "Compass" && room.Name != "ChallengeBoss") // Don't save bonus room or boss room chests, or bonus room breakables (it's ok if they reset). + { + foreach (GameObj obj in room.GameObjList) + { + // Saving breakables state. + BreakableObj breakable = obj as BreakableObj; + if (breakable != null) + { + if (breakable.Broken == true) + breakablesOpened.Add(true); + else + breakablesOpened.Add(false); + } + + // Saving chest states. + ChestObj chest = obj as ChestObj; + if (chest != null) + { + chestTypes.Add(chest.ChestType); + + if (chest.IsOpen == true) + chestOpened.Add(true); + else + chestOpened.Add(false); + + FairyChestObj fairyChest = chest as FairyChestObj; + if (fairyChest != null) + { + if (fairyChest.State == ChestConditionChecker.STATE_FAILED) + fairyChestFailed.Add(true); + else + fairyChestFailed.Add(false); + } + } + } + } + } + + // Saving rooms visited state. + writer.Write(roomVisited.Count); // int32 + foreach (bool state in roomVisited) + writer.Write(state); + + // Saving the state of the bonus rooms. + writer.Write(bonusRoomCompleted.Count); // int32 + foreach (bool state in bonusRoomCompleted) + writer.Write(state); + + // Saving the data of the bonus rooms. + // No need to save number of bonus rooms because that's saved above. + foreach (int data in bonusRoomData) + writer.Write(data); + + // Saving the type of chests. + writer.Write(chestTypes.Count); // int32 + foreach (byte type in chestTypes) + writer.Write(type); + + // Saving the state of chests. + writer.Write(chestOpened.Count); // int32 + foreach (bool state in chestOpened) + writer.Write(state); + + // Saving the state of fairy chests. + writer.Write(fairyChestFailed.Count); // int32 + foreach (bool state in fairyChestFailed) + writer.Write(state); + + // Saving the state of enemies + writer.Write(enemyDead.Count); // int32 + foreach (bool state in enemyDead) + writer.Write(state); + + // Saving breakable object states + writer.Write(breakablesOpened.Count); // int32 + foreach (bool state in breakablesOpened) + writer.Write(state); + } + else + Console.WriteLine("WARNING: Attempting to save level screen MAP data but level was null. Make sure it exists in the screen manager before saving it."); + + if (saveBackup == true) + { + FileStream fileStream = stream as FileStream; + if (fileStream != null) + fileStream.Flush(true); + } + + writer.Close(); + } + stream.Close(); + } + } + + private void SaveLineageData(bool saveBackup) + { + string fileName = m_fileNameLineage; + if (saveBackup == true) + fileName = fileName.Insert(0, "AutoSave_"); + fileName = fileName.Insert(0, "Profile" + Game.GameConfig.ProfileSlot + "/"); + + using (Stream stream = m_storageContainer.CreateFile(fileName)) + { + using (BinaryWriter writer = new BinaryWriter(stream)) + { + Console.WriteLine("///// PLAYER LINEAGE DATA - BEGIN SAVING /////"); + // Saving the currently created branch. + List currentBranches = Game.PlayerStats.CurrentBranches; + int numChildren = 0; + + if (currentBranches != null) + { + numChildren = currentBranches.Count; + writer.Write(numChildren); + + for (int i = 0; i < numChildren; i++) + { + // If you have an old version save file, update the name to match the new format before saving. + if (Game.PlayerStats.RevisionNumber <= 0) + { + string playerName = currentBranches[i].Name; + string romanNumeral = ""; + Game.ConvertPlayerNameFormat(ref playerName, ref romanNumeral); + PlayerLineageData data = currentBranches[i]; + data.Name = playerName; + data.RomanNumeral = romanNumeral; + currentBranches[i] = data; + } + + writer.Write(currentBranches[i].Name); // string + writer.Write(currentBranches[i].Spell); // byte + writer.Write(currentBranches[i].Class); // byte + writer.Write(currentBranches[i].HeadPiece); // byte + writer.Write(currentBranches[i].ChestPiece); // byte + writer.Write(currentBranches[i].ShoulderPiece); // byte + + writer.Write(currentBranches[i].Age); // byte + writer.Write(currentBranches[i].ChildAge); // byte + + writer.Write((byte)currentBranches[i].Traits.X); // byte + writer.Write((byte)currentBranches[i].Traits.Y); // byte + writer.Write(currentBranches[i].IsFemale); // bool + writer.Write(currentBranches[i].RomanNumeral); // string + } + } + else + writer.Write(numChildren); // Writing zero children. + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + Console.WriteLine("Saving Current Branch Lineage Data"); + for (int i = 0; i < numChildren; i++) + { + Console.WriteLine("Player Name: " + currentBranches[i].Name); + Console.WriteLine("Spell: " + currentBranches[i].Name); + Console.WriteLine("Class: " + currentBranches[i].Name); + Console.WriteLine("Head Piece: " + currentBranches[i].HeadPiece); + Console.WriteLine("Chest Piece: " + currentBranches[i].ChestPiece); + Console.WriteLine("Shoulder Piece: " + currentBranches[i].ShoulderPiece); + Console.WriteLine("Player Age: " + currentBranches[i].Age); + Console.WriteLine("Player Child Age: " + currentBranches[i].ChildAge); + Console.WriteLine("Traits: " + currentBranches[i].Traits.X + ", " + currentBranches[i].Traits.Y); + Console.WriteLine("Is Female: " + currentBranches[i].IsFemale); + Console.WriteLine("Roman Numeral: " + currentBranches[i].RomanNumeral); + } + } + + //////////////////////////////////////// + + // Saving family tree info + List familyTreeArray = Game.PlayerStats.FamilyTreeArray; + int numBranches = 0; + + if (familyTreeArray != null) + { + numBranches = familyTreeArray.Count; + writer.Write(numBranches); + + for (int i = 0; i < numBranches; i++) + { + // If you have an old version save file, update the name to match the new format before saving. + if (Game.PlayerStats.RevisionNumber <= 0) + { + string playerName = familyTreeArray[i].Name; + string romanNumeral = ""; + Game.ConvertPlayerNameFormat(ref playerName, ref romanNumeral); + FamilyTreeNode data = familyTreeArray[i]; + data.Name = playerName; + data.RomanNumeral = romanNumeral; + familyTreeArray[i] = data; + } + + writer.Write(familyTreeArray[i].Name); // string + writer.Write(familyTreeArray[i].Age); // byte + writer.Write(familyTreeArray[i].Class); // byte + writer.Write(familyTreeArray[i].HeadPiece); // byte + writer.Write(familyTreeArray[i].ChestPiece); // byte + writer.Write(familyTreeArray[i].ShoulderPiece); // byte + writer.Write(familyTreeArray[i].NumEnemiesBeaten); // int + writer.Write(familyTreeArray[i].BeatenABoss); // bool + writer.Write((byte)familyTreeArray[i].Traits.X); // byte + writer.Write((byte)familyTreeArray[i].Traits.Y); // byte + writer.Write(familyTreeArray[i].IsFemale); // bool + writer.Write(familyTreeArray[i].RomanNumeral); // string + } + } + else + writer.Write(numBranches); // Tree has no nodes. + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + Console.WriteLine("Saving Family Tree Data"); + Console.WriteLine("Number of Branches: " + numBranches); + for (int i = 0; i < numBranches; i++) + { + Console.WriteLine("/// Saving branch"); + Console.WriteLine("Name: " + familyTreeArray[i].Name); + Console.WriteLine("Age: " + familyTreeArray[i].Age); + Console.WriteLine("Class: " + familyTreeArray[i].Class); + Console.WriteLine("Head Piece: " + familyTreeArray[i].HeadPiece); + Console.WriteLine("Chest Piece: " + familyTreeArray[i].ChestPiece); + Console.WriteLine("Shoulder Piece: " + familyTreeArray[i].ShoulderPiece); + Console.WriteLine("Number of Enemies Beaten: " + familyTreeArray[i].NumEnemiesBeaten); + Console.WriteLine("Beaten a Boss: " + familyTreeArray[i].BeatenABoss); + Console.WriteLine("Traits: " + familyTreeArray[i].Traits.X + ", " + familyTreeArray[i].Traits.Y); + Console.WriteLine("Is Female: " + familyTreeArray[i].IsFemale); + Console.WriteLine("Roman Numeral: " + familyTreeArray[i].RomanNumeral); + } + } + + Console.WriteLine("///// PLAYER LINEAGE DATA - SAVE COMPLETE /////"); + if (saveBackup == true) + { + FileStream fileStream = stream as FileStream; + if (fileStream != null) + fileStream.Flush(true); + } + + writer.Close(); + } + stream.Close(); + } + } + + private void LoadData(SaveType loadType, ProceduralLevelScreen level) + { + if (FileExists(loadType)) + { + switch (loadType) + { + case (SaveType.PlayerData): + //if (Game.ScreenManager.Player != null) + LoadPlayerData(); + break; + case (SaveType.UpgradeData): + //if (Game.ScreenManager.Player != null) + LoadUpgradeData(); + break; + case (SaveType.Map): + Console.WriteLine("Cannot load Map directly from LoadData. Call LoadMap() instead."); + //if (Game.PlayerStats.IsDead == false) + //{ + // ProceduralLevelScreen createdLevel = LoadMap(); + // createdLevel.LoadGameData = true; + //} + //else + // Game.ScreenManager.DisplayScreen(ScreenType.Lineage, true, null); + break; + case (SaveType.MapData): + if (level != null) + LoadMapData(level); + else + Console.WriteLine("Could not load Map data. Level was null."); + break; + case (SaveType.Lineage): + LoadLineageData(); + break; + } + + Console.WriteLine("\nData of type " + loadType + " Loaded."); + } + else + Console.WriteLine("Could not load data of type " + loadType + " because data did not exist."); + } + + private void LoadPlayerData() + { + using (Stream stream = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNamePlayer, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + using (BinaryReader reader = new BinaryReader(stream)) + { + //Game.PlayerStats.PlayerPosition = new Vector2(reader.ReadInt32(), reader.ReadInt32()); + Game.PlayerStats.Gold = reader.ReadInt32(); + Game.PlayerStats.CurrentHealth = reader.ReadInt32(); + Game.PlayerStats.CurrentMana = reader.ReadInt32(); + Game.PlayerStats.Age = reader.ReadByte(); + Game.PlayerStats.ChildAge = reader.ReadByte(); + Game.PlayerStats.Spell = reader.ReadByte(); + Game.PlayerStats.Class = reader.ReadByte(); + Game.PlayerStats.SpecialItem = reader.ReadByte(); + Game.PlayerStats.Traits = new Vector2(reader.ReadByte(), reader.ReadByte()); + Game.PlayerStats.PlayerName = reader.ReadString(); + + // Reading player parts + Game.PlayerStats.HeadPiece = reader.ReadByte(); + Game.PlayerStats.ShoulderPiece = reader.ReadByte(); + Game.PlayerStats.ChestPiece = reader.ReadByte(); + + // Necessary to kick in the try catch block in CDGSplashScreen since reader.ReadByte() returns 0 instead of crashing when reading incorrect data. + //if (Game.PlayerStats.HeadPiece == 0 || Game.PlayerStats.ShoulderPiece == 0 || Game.PlayerStats.ChestPiece == 0) + if (Game.PlayerStats.HeadPiece == 0 && Game.PlayerStats.ShoulderPiece == 0 && Game.PlayerStats.ChestPiece == 0) + throw new Exception("Corrupted Save File: All equipment pieces are 0."); + + // Reading Diary entry position + Game.PlayerStats.DiaryEntry = reader.ReadByte(); + + // Reading bonus stats. + Game.PlayerStats.BonusHealth = reader.ReadInt32(); + Game.PlayerStats.BonusStrength = reader.ReadInt32(); + Game.PlayerStats.BonusMana = reader.ReadInt32(); + Game.PlayerStats.BonusDefense = reader.ReadInt32(); + Game.PlayerStats.BonusWeight = reader.ReadInt32(); + Game.PlayerStats.BonusMagic = reader.ReadInt32(); + + // Reading lich stats. + Game.PlayerStats.LichHealth = reader.ReadInt32(); + Game.PlayerStats.LichMana = reader.ReadInt32(); + Game.PlayerStats.LichHealthMod = reader.ReadSingle(); + + // Reading boss progress states + Game.PlayerStats.NewBossBeaten = reader.ReadBoolean(); + Game.PlayerStats.EyeballBossBeaten = reader.ReadBoolean(); + Game.PlayerStats.FairyBossBeaten = reader.ReadBoolean(); + Game.PlayerStats.FireballBossBeaten = reader.ReadBoolean(); + Game.PlayerStats.BlobBossBeaten = reader.ReadBoolean(); + Game.PlayerStats.LastbossBeaten = reader.ReadBoolean(); + + // Reading new game plus progress + Game.PlayerStats.TimesCastleBeaten = reader.ReadInt32(); + Game.PlayerStats.NumEnemiesBeaten = reader.ReadInt32(); + + // Loading misc flags + Game.PlayerStats.TutorialComplete = reader.ReadBoolean(); + Game.PlayerStats.CharacterFound = reader.ReadBoolean(); + Game.PlayerStats.LoadStartingRoom = reader.ReadBoolean(); + + Game.PlayerStats.LockCastle = reader.ReadBoolean(); + Game.PlayerStats.SpokeToBlacksmith = reader.ReadBoolean(); + Game.PlayerStats.SpokeToEnchantress = reader.ReadBoolean(); + Game.PlayerStats.SpokeToArchitect = reader.ReadBoolean(); + Game.PlayerStats.SpokeToTollCollector = reader.ReadBoolean(); + Game.PlayerStats.IsDead = reader.ReadBoolean(); + Game.PlayerStats.FinalDoorOpened = reader.ReadBoolean(); + Game.PlayerStats.RerolledChildren = reader.ReadBoolean(); + Game.PlayerStats.IsFemale = reader.ReadBoolean(); + Game.PlayerStats.TimesDead = reader.ReadInt32(); + Game.PlayerStats.HasArchitectFee = reader.ReadBoolean(); + Game.PlayerStats.ReadLastDiary = reader.ReadBoolean(); + Game.PlayerStats.SpokenToLastBoss = reader.ReadBoolean(); + Game.PlayerStats.HardcoreMode = reader.ReadBoolean(); + Game.PlayerStats.TotalHoursPlayed = reader.ReadSingle(); + + // Loading wizard spells + byte wizardSpell1 = reader.ReadByte(); + byte wizardSpell2 = reader.ReadByte(); + byte wizardSpell3 = reader.ReadByte(); + + Game.PlayerStats.WizardSpellList = new Vector3(wizardSpell1, wizardSpell2, wizardSpell3); + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + Console.WriteLine("\nLoading Player Stats"); + Console.WriteLine("Gold: " + Game.PlayerStats.Gold); + Console.WriteLine("Current Health: " + Game.PlayerStats.CurrentHealth); + Console.WriteLine("Current Mana: " + Game.PlayerStats.CurrentMana); + Console.WriteLine("Age: " + Game.PlayerStats.Age); + Console.WriteLine("Child Age: " + Game.PlayerStats.ChildAge); + Console.WriteLine("Spell: " + Game.PlayerStats.Spell); + Console.WriteLine("Class: " + Game.PlayerStats.Class); + Console.WriteLine("Special Item: " + Game.PlayerStats.SpecialItem); + Console.WriteLine("Traits: " + Game.PlayerStats.Traits.X + ", " + Game.PlayerStats.Traits.Y); + Console.WriteLine("Name: " + Game.PlayerStats.PlayerName); + Console.WriteLine("---------------"); + Console.WriteLine("Head Piece: " + Game.PlayerStats.HeadPiece); + Console.WriteLine("Shoulder Piece: " + Game.PlayerStats.ShoulderPiece); + Console.WriteLine("Chest Piece: " + Game.PlayerStats.ChestPiece); + Console.WriteLine("---------------"); + Console.WriteLine("Diary Entry: " + Game.PlayerStats.DiaryEntry); + Console.WriteLine("---------------"); + Console.WriteLine("Bonus Health: " + Game.PlayerStats.BonusHealth); + Console.WriteLine("Bonus Strength: " + Game.PlayerStats.BonusStrength); + Console.WriteLine("Bonus Mana: " + Game.PlayerStats.BonusMana); + Console.WriteLine("Bonus Armor: " + Game.PlayerStats.BonusDefense); + Console.WriteLine("Bonus Weight: " + Game.PlayerStats.BonusWeight); + Console.WriteLine("Bonus Magic: " + Game.PlayerStats.BonusMagic); + Console.WriteLine("---------------"); + Console.WriteLine("Lich Health: " + Game.PlayerStats.LichHealth); + Console.WriteLine("Lich Mana: " + Game.PlayerStats.LichMana); + Console.WriteLine("Lich Health Mod: " + Game.PlayerStats.LichHealthMod); + Console.WriteLine("---------------"); + Console.WriteLine("New Boss Beaten: " + Game.PlayerStats.NewBossBeaten); + Console.WriteLine("Eyeball Boss Beaten: " + Game.PlayerStats.EyeballBossBeaten); + Console.WriteLine("Fairy Boss Beaten: " + Game.PlayerStats.FairyBossBeaten); + Console.WriteLine("Fireball Boss Beaten: " + Game.PlayerStats.FireballBossBeaten); + Console.WriteLine("Blob Boss Beaten: " + Game.PlayerStats.BlobBossBeaten); + Console.WriteLine("Last Boss Beaten: " + Game.PlayerStats.LastbossBeaten); + Console.WriteLine("---------------"); + Console.WriteLine("Times Castle Beaten: " + Game.PlayerStats.TimesCastleBeaten); + Console.WriteLine("Number of Enemies Beaten: " + Game.PlayerStats.NumEnemiesBeaten); + Console.WriteLine("---------------"); + Console.WriteLine("Tutorial Complete: " + Game.PlayerStats.TutorialComplete); + Console.WriteLine("Character Found: " + Game.PlayerStats.CharacterFound); + Console.WriteLine("Load Starting Room: " + Game.PlayerStats.LoadStartingRoom); + Console.WriteLine("---------------"); + Console.WriteLine("Castle Locked: " + Game.PlayerStats.LockCastle); + Console.WriteLine("Spoke to Blacksmith: " + Game.PlayerStats.SpokeToBlacksmith); + Console.WriteLine("Spoke to Enchantress: " + Game.PlayerStats.SpokeToEnchantress); + Console.WriteLine("Spoke to Architect: " + Game.PlayerStats.SpokeToArchitect); + Console.WriteLine("Spoke to Toll Collector: " + Game.PlayerStats.SpokeToTollCollector); + Console.WriteLine("Player Is Dead: " + Game.PlayerStats.IsDead); + Console.WriteLine("Final Door Opened: " + Game.PlayerStats.FinalDoorOpened); + Console.WriteLine("Rerolled Children: " + Game.PlayerStats.RerolledChildren); + Console.WriteLine("Is Female: " + Game.PlayerStats.IsFemale); + Console.WriteLine("Times Dead: " + Game.PlayerStats.TimesDead); + Console.WriteLine("Has Architect Fee: " + Game.PlayerStats.HasArchitectFee); + Console.WriteLine("Player read last diary: " + Game.PlayerStats.ReadLastDiary); + Console.WriteLine("Player has spoken to last boss: " + Game.PlayerStats.SpokenToLastBoss); + Console.WriteLine("Is Hardcore mode: " + Game.PlayerStats.HardcoreMode); + Console.WriteLine("Total Hours Played " + Game.PlayerStats.TotalHoursPlayed); + Console.WriteLine("Wizard Spell 1: " + Game.PlayerStats.WizardSpellList.X); + Console.WriteLine("Wizard Spell 2: " + Game.PlayerStats.WizardSpellList.Y); + Console.WriteLine("Wizard Spell 3: " + Game.PlayerStats.WizardSpellList.Z); + } + + Console.WriteLine("///// ENEMY LIST DATA - BEGIN LOADING /////"); + + for (int i = 0; i < EnemyType.Total; i++) + { + Vector4 enemyStats = new Vector4(reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte()); + Game.PlayerStats.EnemiesKilledList[i] = enemyStats; + } + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + Console.WriteLine("Loading Enemy List Data"); + int counter = 0; + foreach (Vector4 enemy in Game.PlayerStats.EnemiesKilledList) + { + Console.WriteLine("Enemy Type: " + counter + ", Difficulty: Basic, Killed: " + enemy.X); + Console.WriteLine("Enemy Type: " + counter + ", Difficulty: Advanced, Killed: " + enemy.Y); + Console.WriteLine("Enemy Type: " + counter + ", Difficulty: Expert, Killed: " + enemy.Z); + Console.WriteLine("Enemy Type: " + counter + ", Difficulty: Miniboss, Killed: " + enemy.W); + + counter++; + } + } + + int numKilledEnemiesInRun = reader.ReadInt32(); + + for (int i = 0; i < numKilledEnemiesInRun; i++) + { + Vector2 enemyKilled = new Vector2(reader.ReadInt32(), reader.ReadInt32()); + Game.PlayerStats.EnemiesKilledInRun.Add(enemyKilled); + } + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + Console.WriteLine("Loading num enemies killed"); + Console.WriteLine("Number of enemies killed in run: " + numKilledEnemiesInRun); + foreach (Vector2 enemy in Game.PlayerStats.EnemiesKilledInRun) + { + Console.WriteLine("Enemy Room Index: " + enemy.X); + Console.WriteLine("Enemy Index in EnemyList: " + enemy.Y); + } + } + + Console.WriteLine("///// ENEMY LIST DATA - LOAD COMPLETE /////"); + + + + if (reader.PeekChar() != -1) // If a character is found, then DLC is in the file. + { + Console.WriteLine("///// DLC DATA FOUND - BEGIN LOADING /////"); + Game.PlayerStats.ChallengeEyeballUnlocked = reader.ReadBoolean(); + Game.PlayerStats.ChallengeSkullUnlocked = reader.ReadBoolean(); + Game.PlayerStats.ChallengeFireballUnlocked = reader.ReadBoolean(); + Game.PlayerStats.ChallengeBlobUnlocked = reader.ReadBoolean(); + Game.PlayerStats.ChallengeLastBossUnlocked = reader.ReadBoolean(); + + Game.PlayerStats.ChallengeEyeballBeaten = reader.ReadBoolean(); + Game.PlayerStats.ChallengeSkullBeaten = reader.ReadBoolean(); + Game.PlayerStats.ChallengeFireballBeaten = reader.ReadBoolean(); + Game.PlayerStats.ChallengeBlobBeaten = reader.ReadBoolean(); + Game.PlayerStats.ChallengeLastBossBeaten = reader.ReadBoolean(); + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + Console.WriteLine("Eyeball Challenge Unlocked: " + Game.PlayerStats.ChallengeEyeballUnlocked); + Console.WriteLine("Skull Challenge Unlocked: " + Game.PlayerStats.ChallengeSkullUnlocked); + Console.WriteLine("Fireball Challenge Unlocked: " + Game.PlayerStats.ChallengeFireballUnlocked); + Console.WriteLine("Blob Challenge Unlocked: " + Game.PlayerStats.ChallengeBlobUnlocked); + Console.WriteLine("Last Boss Challenge Unlocked: " + Game.PlayerStats.ChallengeLastBossUnlocked); + + Console.WriteLine("Eyeball Challenge Beaten: " + Game.PlayerStats.ChallengeEyeballBeaten); + Console.WriteLine("Skull Challenge Beaten: " + Game.PlayerStats.ChallengeSkullBeaten); + Console.WriteLine("Fireball Challenge Beaten: " + Game.PlayerStats.ChallengeFireballBeaten); + Console.WriteLine("Blob Challenge Beaten: " + Game.PlayerStats.ChallengeBlobBeaten); + Console.WriteLine("Last Boss Challenge Beaten: " + Game.PlayerStats.ChallengeLastBossBeaten); + } + + if (reader.PeekChar() != -1) // Even more DLC added + { + Game.PlayerStats.ChallengeEyeballTimesUpgraded = reader.ReadSByte(); + Game.PlayerStats.ChallengeSkullTimesUpgraded = reader.ReadSByte(); + Game.PlayerStats.ChallengeFireballTimesUpgraded = reader.ReadSByte(); + Game.PlayerStats.ChallengeBlobTimesUpgraded = reader.ReadSByte(); + Game.PlayerStats.ChallengeLastBossTimesUpgraded = reader.ReadSByte(); + Game.PlayerStats.RomanNumeral = reader.ReadString(); + Game.PlayerStats.HasProsopagnosia = reader.ReadBoolean(); + Game.PlayerStats.RevisionNumber = reader.ReadInt32(); + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + Console.WriteLine("Eyeball Challenge Times Upgraded: " + Game.PlayerStats.ChallengeEyeballTimesUpgraded); + Console.WriteLine("Skull Challenge Times Upgraded: " + Game.PlayerStats.ChallengeSkullTimesUpgraded); + Console.WriteLine("Fireball Challenge Times Upgraded: " + Game.PlayerStats.ChallengeFireballTimesUpgraded); + Console.WriteLine("Blob Challenge Times Upgraded: " + Game.PlayerStats.ChallengeBlobTimesUpgraded); + Console.WriteLine("Last Boss Challenge Times Upgraded: " + Game.PlayerStats.ChallengeLastBossTimesUpgraded); + Console.WriteLine("Player Name Number: " + Game.PlayerStats.RomanNumeral); + Console.WriteLine("Player has Prosopagnosia: " + Game.PlayerStats.HasProsopagnosia); + } + + if (reader.PeekChar() != -1) // Even more... + { + Game.PlayerStats.ArchitectUsed = reader.ReadBoolean(); + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + Console.WriteLine("Architect used: " + Game.PlayerStats.ArchitectUsed); + } + } + } + + Console.WriteLine("///// DLC DATA - LOADING COMPLETE /////"); + } + else + Console.WriteLine("///// NO DLC DATA FOUND - SKIPPED LOADING /////"); + + reader.Close(); + } + stream.Close(); + } + } + + private void LoadUpgradeData() + { + using (Stream stream = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameUpgrades, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + using (BinaryReader reader = new BinaryReader(stream)) + { + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + Console.WriteLine("\nLoading Equipment States"); + Console.WriteLine("\nLoading Standard Blueprints"); + } + + List blueprintArray = Game.PlayerStats.GetBlueprintArray; + for (int i = 0; i < EquipmentCategoryType.Total; i++) + { + for (int k = 0; k < EquipmentBaseType.Total; k++) + { + blueprintArray[i][k] = reader.ReadByte(); + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write(" " + blueprintArray[i][k]); + } + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write("\n"); + } + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.WriteLine("\nLoading Ability Blueprints"); + List abilityBPArray = Game.PlayerStats.GetRuneArray; + for (int i = 0; i < EquipmentCategoryType.Total; i++) + { + for (int k = 0; k < EquipmentAbilityType.Total; k++) + { + abilityBPArray[i][k] = reader.ReadByte(); + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write(" " + abilityBPArray[i][k]); + } + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write("\n"); + } + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.WriteLine("\nLoading Equipped Standard Items"); + sbyte[] equippedArray = Game.PlayerStats.GetEquippedArray; + for (int i = 0; i < EquipmentCategoryType.Total; i++) + { + equippedArray[i] = reader.ReadSByte(); + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write(" " + equippedArray[i]); + } + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.WriteLine("\nLoading Equipped Abilities"); + sbyte[] equippedAbilityArray = Game.PlayerStats.GetEquippedRuneArray; + for (int i = 0; i < EquipmentCategoryType.Total; i++) + { + equippedAbilityArray[i] = reader.ReadSByte(); + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write(" " + equippedAbilityArray[i]); + } + + SkillObj[] traitArray = SkillSystem.GetSkillArray(); + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.WriteLine("\nLoading Traits"); + + SkillSystem.ResetAllTraits(); // Reset all traits first. + Game.PlayerStats.CurrentLevel = 0; // Reset player level. + for (int i = 0; i < (int)SkillType.DIVIDER - 2; i++) //The starting 2 traits are null and filler. + { + int traitLevel = reader.ReadInt32(); + for (int k = 0; k < traitLevel; k++) + SkillSystem.LevelUpTrait(traitArray[i], false); + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + Console.Write(" " + traitArray[i].CurrentLevel); + } + reader.Close(); + + Game.ScreenManager.Player.UpdateEquipmentColours(); + } + stream.Close(); + + // These checks probably aren't necessary anymore. + // Your game was corrupted if you have double jump equipped but no enchantress unlocked. + //if (Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.DoubleJump) > 0 && SkillSystem.GetSkill(SkillType.Enchanter).CurrentLevel < 1 && LevelEV.CREATE_RETAIL_VERSION == true) + // throw new Exception("Corrupted Save file"); + + // Another check for corruption on the skill tree + //bool possibleCorruption = false; + //List familyTree = Game.PlayerStats.FamilyTreeArray; + //foreach (FamilyTreeNode node in familyTree) + //{ + // if (node.Class > ClassType.Assassin) + // { + // possibleCorruption = true; + // break; + // } + //} + + //// If you ever find a class that is normally locked in the family tree, and the smithy is not unlocked, then the file is corrupt. + //if (possibleCorruption == true && SkillSystem.GetSkill(SkillType.Smithy).CurrentLevel < 1 && LevelEV.CREATE_RETAIL_VERSION == true) + // throw new Exception("Corrupted Save file"); + } + } + + public ProceduralLevelScreen LoadMap() + { + GetStorageContainer(); + ProceduralLevelScreen loadedLevel = null; + using (Stream stream = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameMap, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + using (BinaryReader reader = new BinaryReader(stream)) + { + int roomSize = reader.ReadInt32(); + Vector4[] roomList = new Vector4[roomSize]; + Vector3[] roomColorList = new Vector3[roomSize]; + + for (int i = 0; i < roomSize; i++) + { + roomList[i].W = reader.ReadInt32(); // Reading the pool index. + roomList[i].X = reader.ReadByte(); // Reading the level type. + roomList[i].Y = reader.ReadInt32(); // Reading the level's X pos. + roomList[i].Z = reader.ReadInt32(); // Reading the level's Y pos. + + roomColorList[i].X = reader.ReadByte(); // Reading RGB + roomColorList[i].Y = reader.ReadByte(); + roomColorList[i].Z = reader.ReadByte(); + } + + loadedLevel = LevelBuilder2.CreateLevel(roomList, roomColorList); + + int numEnemies = reader.ReadInt32(); // Reading the number of enemies in the game. + List enemyList = new List(); + for (int i = 0; i < numEnemies; i++) + enemyList.Add(reader.ReadByte()); // Reading the enemy type and storing it into the array. + + List enemyDifficultyList = new List(); + for (int i = 0; i < numEnemies; i++) // Reading the enemy difficulty and storing it in an array. + enemyDifficultyList.Add(reader.ReadByte()); + + LevelBuilder2.OverrideProceduralEnemies(loadedLevel, enemyList.ToArray(), enemyDifficultyList.ToArray()); + + reader.Close(); + } + stream.Close(); + } + m_storageContainer.Dispose(); + + return loadedLevel; + } + + private void LoadMapData(ProceduralLevelScreen createdLevel) + { + //createdLevel.InitializeChests(true); // Can't remember why this was put here. It was disabled because it was shifting chests twice, screwing up their positions. + + using (Stream stream = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameMapData, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + using (BinaryReader reader = new BinaryReader(stream)) + { + // Loading room visited state. + int numRooms = reader.ReadInt32(); + List roomsVisited = new List(); + for (int i = 0; i < numRooms; i++) + roomsVisited.Add(reader.ReadBoolean()); + + // Loading bonus room states. + int numBonusRooms = reader.ReadInt32(); + List bonusRoomStates = new List(); + for (int i = 0; i < numBonusRooms; i++) + bonusRoomStates.Add(reader.ReadBoolean()); + + // Loading bonus room data. + List bonusRoomData = new List(); + for (int i = 0; i < numBonusRooms; i++) + bonusRoomData.Add(reader.ReadInt32()); + + // Loading chest types + int numChests = reader.ReadInt32(); + List chestTypes = new List(); + for (int i = 0; i < numChests; i++) + chestTypes.Add(reader.ReadByte()); + + // Loading chest states + numChests = reader.ReadInt32(); + List chestStates = new List(); + for (int i = 0; i < numChests; i++) + chestStates.Add(reader.ReadBoolean()); + + // Loading fairy chest states + numChests = reader.ReadInt32(); + List fairyChestStates = new List(); + for (int i = 0; i < numChests; i++) + fairyChestStates.Add(reader.ReadBoolean()); + + // Loading enemy states + int numEnemies = reader.ReadInt32(); + List enemyStates = new List(); + for (int i = 0; i < numEnemies; i++) + enemyStates.Add(reader.ReadBoolean()); + + // Loading breakable object states + int numBreakables = reader.ReadInt32(); + List breakableStates = new List(); + for (int i = 0; i < numBreakables; i++) + breakableStates.Add(reader.ReadBoolean()); + + //int roomCounter = 0; + int bonusRoomCounter = 0; + int chestTypeCounter = 0; + int chestCounter = 0; + int fairyChestCounter = 0; + int enemyCounter = 0; + int breakablesCounter = 0; + + //foreach (RoomObj room in createdLevel.RoomList) + //{ + // if (room.Name != "Boss") + // { + // int counter = 0; + // foreach (GameObj obj in room.GameObjList) + // { + // if (obj is ChestObj) + // counter++; + // } + // Console.WriteLine(counter); + // } + //} + + foreach (RoomObj room in createdLevel.RoomList) + { + //DO NOT set the state of rooms visited yet. This must be done AFTER chest states, otherwise the map won't update properly. + + // Setting the state of bonus rooms. + if (numBonusRooms > 0) + { + BonusRoomObj bonusRoom = room as BonusRoomObj; + if (bonusRoom != null) + { + bool bonusRoomState = bonusRoomStates[bonusRoomCounter]; + int roomData = bonusRoomData[bonusRoomCounter]; + + bonusRoomCounter++; + + if (bonusRoomState == true) + bonusRoom.RoomCompleted = true; + + bonusRoom.ID = roomData; + } + } + + // Setting the state of enemies. + // Only bring enemies back to life if you are locking the castle (i.e. not reloading a file but starting a new lineage). + if (numEnemies > 0) + { + if (Game.PlayerStats.LockCastle == false) + { + if (room.Name != "Boss" && room.Name != "ChallengeBoss")// && room.Name != "Bonus") + { + foreach (EnemyObj enemy in room.EnemyList) + { + bool enemyState = enemyStates[enemyCounter]; + enemyCounter++; + + if (enemyState == true) + enemy.KillSilently(); + } + } + } + } + + // Setting the states of chests. + if (room.Name != "Bonus" && room.Name != "Boss" && room.Name != "Compass" && room.Name != "ChallengeBoss") // Don't save bonus room chests or breakables. + { + foreach (GameObj obj in room.GameObjList) + { + // Only save breakable states if the castle is not locked. + if (Game.PlayerStats.LockCastle == false) + { + if (numBreakables > 0) + { + BreakableObj breakable = obj as BreakableObj; + if (breakable != null) + { + bool breakableState = breakableStates[breakablesCounter]; + breakablesCounter++; + if (breakableState == true) + breakable.ForceBreak(); + } + } + } + + //if (numChests > 0) + //{ + ChestObj chest = obj as ChestObj; + if (chest != null) + { + chest.IsProcedural = false; + byte chestType = chestTypes[chestTypeCounter]; + chestTypeCounter++; + chest.ChestType = chestType; + + bool chestState = chestStates[chestCounter]; + chestCounter++; + + if (chestState == true) + chest.ForceOpen(); + + // Only reset fairy chests if you are locking the castle (i.e. not reloading a file but starting a new lineage). + if (Game.PlayerStats.LockCastle == false) + { + FairyChestObj fairyChest = chest as FairyChestObj; + if (fairyChest != null) + { + bool fairyChestState = fairyChestStates[fairyChestCounter]; + fairyChestCounter++; + + if (fairyChestState == true) + fairyChest.SetChestFailed(true); + } + } + } + //} + } + } + } + + if (numRooms > 0) + { + List roomsVisitedList = new List(); + // Setting rooms visited states after the chests have been set. + //foreach (RoomObj room in createdLevel.RoomList) + //{ + // bool roomState = roomsVisited[roomCounter]; + // roomCounter++; + + // if (roomState == true) + // roomsVisitedList.Add(room); + //} + + int roomsVisitedCount = roomsVisited.Count; + for (int i = 0; i < roomsVisitedCount; i++) + { + if (roomsVisited[i] == true) + roomsVisitedList.Add(createdLevel.RoomList[i]); + } + + createdLevel.MapRoomsUnveiled = roomsVisitedList; + } + + reader.Close(); + } + stream.Close(); + } + } + + private void LoadLineageData() + { + using (Stream stream = m_storageContainer.OpenFile("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameLineage, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + using (BinaryReader reader = new BinaryReader(stream)) + { + Console.WriteLine("///// PLAYER LINEAGE DATA - BEGIN LOADING /////"); + + // Loading the currently created branch. + List loadedBranches = new List(); + int numChildren = reader.ReadInt32(); + + for (int i = 0; i < numChildren; i++) + { + PlayerLineageData data = new PlayerLineageData(); + + data.Name = reader.ReadString(); + data.Spell = reader.ReadByte(); + data.Class = reader.ReadByte(); + data.HeadPiece = reader.ReadByte(); + data.ChestPiece = reader.ReadByte(); + data.ShoulderPiece = reader.ReadByte(); + data.Age = reader.ReadByte(); + data.ChildAge = reader.ReadByte(); + data.Traits = new Vector2(reader.ReadByte(), reader.ReadByte()); + data.IsFemale = reader.ReadBoolean(); + + if (Game.PlayerStats.RevisionNumber > 0) + data.RomanNumeral = reader.ReadString(); + + loadedBranches.Add(data); + } + + if (loadedBranches.Count > 0) + { + // Loading the CurrentBranches into Game.PlayerStats. + Game.PlayerStats.CurrentBranches = loadedBranches; + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + Console.WriteLine("Loading Current Branch Lineage Data"); + List currentBranches = Game.PlayerStats.CurrentBranches; + for (int i = 0; i < numChildren; i++) + { + Console.WriteLine("Player Name: " + currentBranches[i].Name); + Console.WriteLine("Spell: " + currentBranches[i].Name); + Console.WriteLine("Class: " + currentBranches[i].Name); + Console.WriteLine("Head Piece: " + currentBranches[i].HeadPiece); + Console.WriteLine("Chest Piece: " + currentBranches[i].ChestPiece); + Console.WriteLine("Shoulder Piece: " + currentBranches[i].ShoulderPiece); + Console.WriteLine("Player Age: " + currentBranches[i].Age); + Console.WriteLine("Player Child Age: " + currentBranches[i].ChildAge); + Console.WriteLine("Traits: " + currentBranches[i].Traits.X + ", " + currentBranches[i].Traits.Y); + Console.WriteLine("Is Female: " + currentBranches[i].IsFemale); + if (Game.PlayerStats.RevisionNumber > 0) + Console.WriteLine("Roman Number:" + currentBranches[i].RomanNumeral); + } + currentBranches = null; + } + } + + loadedBranches = null; + + //////////////////////////////////////// + + // Loading family tree info + + List familyTree = new List(); + int numBranches = reader.ReadInt32(); + + for (int i = 0; i < numBranches; i++) + { + FamilyTreeNode data = new FamilyTreeNode(); + data.Name = reader.ReadString(); + data.Age = reader.ReadByte(); + data.Class = reader.ReadByte(); + data.HeadPiece = reader.ReadByte(); + data.ChestPiece = reader.ReadByte(); + data.ShoulderPiece = reader.ReadByte(); + data.NumEnemiesBeaten = reader.ReadInt32(); + data.BeatenABoss = reader.ReadBoolean(); + data.Traits.X = reader.ReadByte(); + data.Traits.Y = reader.ReadByte(); + data.IsFemale = reader.ReadBoolean(); + if (Game.PlayerStats.RevisionNumber > 0) + data.RomanNumeral = reader.ReadString(); + familyTree.Add(data); + } + + if (familyTree.Count > 0) + { + // Loading the created Family Tree list into Game.PlayerStats. + Game.PlayerStats.FamilyTreeArray = familyTree; + + if (LevelEV.SHOW_SAVELOAD_DEBUG_TEXT == true) + { + List familyTreeArray = Game.PlayerStats.FamilyTreeArray; + Console.WriteLine("Loading Family Tree Data"); + Console.WriteLine("Number of Branches: " + numBranches); + for (int i = 0; i < numBranches; i++) + { + Console.WriteLine("/// Saving branch"); + Console.WriteLine("Name: " + familyTreeArray[i].Name); + Console.WriteLine("Age: " + familyTreeArray[i].Age); + Console.WriteLine("Class: " + familyTreeArray[i].Class); + Console.WriteLine("Head Piece: " + familyTreeArray[i].HeadPiece); + Console.WriteLine("Chest Piece: " + familyTreeArray[i].ChestPiece); + Console.WriteLine("Shoulder Piece: " + familyTreeArray[i].ShoulderPiece); + Console.WriteLine("Number of Enemies Beaten: " + familyTreeArray[i].NumEnemiesBeaten); + Console.WriteLine("Beaten a Boss: " + familyTreeArray[i].BeatenABoss); + Console.WriteLine("Traits: " + familyTreeArray[i].Traits.X + ", " + familyTreeArray[i].Traits.Y); + Console.WriteLine("Is Female: " + familyTreeArray[i].IsFemale); + if (Game.PlayerStats.RevisionNumber > 0) + Console.WriteLine("Roman Numeral: " + familyTreeArray[i].RomanNumeral); + } + familyTreeArray = null; + } + } + + familyTree = null; + + /////////////////////////////////////////// + Console.WriteLine("///// PLAYER LINEAGE DATA - LOAD COMPLETE /////"); + + reader.Close(); + } + stream.Close(); + } + } + + public bool FileExists(SaveType saveType) + { + bool disposeStorage = true; + if (m_storageContainer != null && m_storageContainer.IsDisposed == false) + disposeStorage = false; // Don't dispose the storage container because FileExists() was called from LoadData(). + + GetStorageContainer(); + + bool fileExists = false; + switch (saveType) + { + case (SaveType.PlayerData): + fileExists = m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNamePlayer); + break; + case (SaveType.UpgradeData): + fileExists = m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameUpgrades); + break; + case (SaveType.Map): + fileExists = m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameMap); + break; + case (SaveType.MapData): + fileExists = m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameMapData); + break; + case (SaveType.Lineage): + fileExists = m_storageContainer.FileExists("Profile" + Game.GameConfig.ProfileSlot + "/" + m_fileNameLineage); + break; + } + + if (disposeStorage == true) + { + m_storageContainer.Dispose(); + m_storageContainer = null; + } + + return fileExists; + } + + public StorageContainer GetContainer() + { + return m_storageContainer; + } + + public void GetSaveHeader(byte profile, out byte playerClass, out string playerName, out int playerLevel, out bool playerIsDead, out int castlesBeaten, out bool isFemale) + { + playerName = null; + playerClass = 0; + playerLevel = 0; + playerIsDead = false; + castlesBeaten = 0; + isFemale = false; + + GetStorageContainer(); + + if (m_storageContainer.FileExists("Profile" + profile + "/" + m_fileNamePlayer)) + { + using (Stream stream = m_storageContainer.OpenFile("Profile" + profile + "/" + m_fileNamePlayer, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + using (BinaryReader reader = new BinaryReader(stream)) + { + reader.ReadInt32(); // Gold + reader.ReadInt32(); // Health + reader.ReadInt32(); // Mana + reader.ReadByte(); // Age + reader.ReadByte(); // Child Age + reader.ReadByte(); // Spell + playerClass = reader.ReadByte(); + reader.ReadByte(); // Special Item + reader.ReadByte(); // TraitX + reader.ReadByte(); // TraitY + playerName = reader.ReadString(); + + reader.ReadByte(); // Head Piece + reader.ReadByte(); // Shoulder Piece + reader.ReadByte(); // Chest Piece + reader.ReadByte(); // Diary Entry + reader.ReadInt32(); // Bonus Health + reader.ReadInt32(); // Bonus Strength + reader.ReadInt32(); // Bonus Mana + reader.ReadInt32(); // Bonus Defense + reader.ReadInt32(); // Bonus Weight + reader.ReadInt32(); // Bonus Magic + + // Reading lich stats. + reader.ReadInt32(); + reader.ReadInt32(); + reader.ReadSingle(); + + // Reading boss progress states + reader.ReadBoolean(); + reader.ReadBoolean(); + reader.ReadBoolean(); + reader.ReadBoolean(); + reader.ReadBoolean(); + reader.ReadBoolean(); + + // Reading new game plus progress + castlesBeaten = reader.ReadInt32(); + reader.ReadInt32(); + + // Loading misc flags + reader.ReadBoolean(); + reader.ReadBoolean(); + reader.ReadBoolean(); + + reader.ReadBoolean(); + reader.ReadBoolean(); + reader.ReadBoolean(); + reader.ReadBoolean(); + reader.ReadBoolean(); + playerIsDead = reader.ReadBoolean(); + reader.ReadBoolean(); + reader.ReadBoolean(); + isFemale = reader.ReadBoolean(); + + reader.Close(); + } + stream.Close(); + } + } + + if (m_storageContainer.FileExists("Profile" + profile + "/" + m_fileNameUpgrades)) + { + using (Stream stream = m_storageContainer.OpenFile("Profile" + profile + "/" + m_fileNameUpgrades, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + using (BinaryReader reader = new BinaryReader(stream)) + { + for (int i = 0; i < EquipmentCategoryType.Total; i++) + { + for (int k = 0; k < EquipmentBaseType.Total; k++) + reader.ReadByte(); + } + + for (int i = 0; i < EquipmentCategoryType.Total; i++) + { + for (int k = 0; k < EquipmentAbilityType.Total; k++) + reader.ReadByte(); + } + + for (int i = 0; i < EquipmentCategoryType.Total; i++) + reader.ReadSByte(); + + for (int i = 0; i < EquipmentCategoryType.Total; i++) + reader.ReadSByte(); + + int levelCounter = 0; + for (int i = 0; i < (int)SkillType.DIVIDER - 2; i++) //The starting 2 traits are null and filler. + { + int traitLevel = reader.ReadInt32(); + for (int k = 0; k < traitLevel; k++) + levelCounter++; + } + + playerLevel = levelCounter; + reader.Close(); + } + stream.Close(); + } + } + + m_storageContainer.Dispose(); + m_storageContainer = null; + } + } + + public enum SavingState + { + NotSaving, + ReadyToSelectStorageDevice, + SelectingStorageDevice, + + ReadyToOpenStorageContainer, // once we have a storage device start here + OpeningStorageContainer, + ReadyToSave, + } + + public enum SaveType + { + None, + PlayerData, + UpgradeData, + Map, + MapData, + Lineage, + } +} + diff --git a/RogueCastle/src/Managers/TextManager.cs b/RogueCastle/src/Managers/TextManager.cs new file mode 100644 index 0000000..c25363f --- /dev/null +++ b/RogueCastle/src/Managers/TextManager.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; + +namespace RogueCastle +{ + public class TextManager : IDisposableObj + { + private int m_poolSize = 0; + private DS2DPool m_resourcePool; + + public bool IsDisposed { get { return m_isDisposed; } } + private bool m_isDisposed = false; + + public TextManager(int poolSize) + { + m_poolSize = poolSize; + m_resourcePool = new DS2DPool(); + } + + public void Initialize() + { + for (int i = 0; i < m_poolSize; i++) + { + TextObj poolObj = new TextObj(null); + poolObj.Visible = false; + poolObj.TextureColor = Color.White; + poolObj.OutlineWidth = 2; + m_resourcePool.AddToPool(poolObj); + } + } + + public void DisplayNumberStringText(int amount, string textLocID, Color color, Vector2 position) + { + // If pool is depleted don't display number string text. In theory, + // this should never happen. The only place this happens is when + // player plays ChestBonusRoomObj game, bets a lot of money, wins, + // don't collect the gold, then collects all the gold at the same + // time triggering a bunch of "XYZ coins" text. --Dave + if (m_resourcePool.CurrentPoolSize < 2) return; // needs 2 objects for display + + TextObj fullTextCheck = m_resourcePool.CheckOut(); + fullTextCheck.Font = Game.JunicodeFont; + fullTextCheck.FontSize = 14; + fullTextCheck.Text = amount + " " + LocaleBuilder.getString(textLocID, fullTextCheck); + + int textWidth = fullTextCheck.Width; + m_resourcePool.CheckIn(fullTextCheck); + + // Changing text settings + TextObj amountText = m_resourcePool.CheckOut(); + amountText.Font = Game.HerzogFont; + amountText.Text = amount.ToString(); + amountText.Align = Types.TextAlign.Left; + amountText.FontSize = 18; + amountText.TextureColor = color; + amountText.Position = new Vector2(position.X - textWidth / 2f, position.Y - amountText.Height / 2f); + amountText.Visible = true; + //amountText.Y -= amountText.Height / 2f; + + TextObj regularText = m_resourcePool.CheckOut(); + regularText.Font = Game.JunicodeFont; + regularText.Text = " " + LocaleBuilder.getString(textLocID, regularText); + regularText.FontSize = 14; + regularText.Align = Types.TextAlign.Left; + regularText.TextureColor = color; + regularText.Position = amountText.Position; + regularText.X += amountText.Width; + regularText.Y -= 5; + regularText.Visible = true; + + // Applying effect to text + Tween.By(amountText, 0.3f, Quad.EaseOut, "Y", "-60"); + Tween.To(amountText, 0.2f, Linear.EaseNone, "delay", "0.5", "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "DestroyText", amountText); + + Tween.By(regularText, 0.3f, Quad.EaseOut, "Y", "-60"); + Tween.To(regularText, 0.2f, Linear.EaseNone, "delay", "0.5", "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "DestroyText", regularText); + } + + public void DisplayStringNumberText(string textLocID, int amount, Color color, Vector2 position) + { + TextObj fullTextCheck = m_resourcePool.CheckOut(); + fullTextCheck.Font = Game.JunicodeFont; + fullTextCheck.FontSize = 14; + fullTextCheck.Text = LocaleBuilder.getString(textLocID, fullTextCheck) + " " + amount; + + int textWidth = fullTextCheck.Width; + m_resourcePool.CheckIn(fullTextCheck); + + // Changing text settings + TextObj regularText = m_resourcePool.CheckOut(); + regularText.Font = Game.JunicodeFont; + regularText.Text = LocaleBuilder.getString(textLocID, regularText) + " "; + regularText.FontSize = 14; + regularText.TextureColor = color; + regularText.Position = new Vector2(position.X - textWidth / 2f, position.Y - regularText.Height / 2f); + regularText.Visible = true; + + TextObj amountText = m_resourcePool.CheckOut(); + amountText.Font = Game.HerzogFont; + amountText.Text = amount.ToString(); + amountText.FontSize = 18; + amountText.TextureColor = color; + amountText.Position = new Vector2(regularText.X + regularText.Width, regularText.Y + 5); + amountText.Visible = true; + + // Applying effect to text + Tween.By(amountText, 0.3f, Quad.EaseOut, "Y", "-60"); + Tween.To(amountText, 0.2f, Linear.EaseNone, "delay", "0.5", "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "DestroyText", amountText); + + Tween.By(regularText, 0.3f, Quad.EaseOut, "Y", "-60"); + Tween.To(regularText, 0.2f, Linear.EaseNone, "delay", "0.5", "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "DestroyText", regularText); + } + + public void DisplayNumberText(int amount, Color color, Vector2 position) + { + // Changing text settings + TextObj amountText = m_resourcePool.CheckOut(); + amountText.Font = Game.HerzogFont; + amountText.Text = amount.ToString(); + amountText.FontSize = 18; + amountText.TextureColor = color; + amountText.Align = Types.TextAlign.Centre; + amountText.Visible = true; + amountText.Position = position; + amountText.Y -= amountText.Height / 2f; + + // Applying effect to text + Tween.By(amountText, 0.3f, Quad.EaseOut, "Y", "-60"); + Tween.To(amountText, 0.2f, Linear.EaseNone, "delay", "0.5", "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "DestroyText", amountText); + } + + public void DisplayStringText(string textLocID, Color color, Vector2 position) + { + TextObj regularText = m_resourcePool.CheckOut(); + regularText.Font = Game.JunicodeFont; + regularText.Text = LocaleBuilder.getString(textLocID, regularText); + regularText.Align = Types.TextAlign.Centre; + regularText.FontSize = 14; + regularText.TextureColor = color; + regularText.Position = position; + regularText.Visible = true; + + Tween.By(regularText, 0.3f, Quad.EaseOut, "Y", "-60"); + Tween.To(regularText, 0.2f, Linear.EaseNone, "delay", "0.5", "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "DestroyText", regularText); + } + + public void DestroyText(TextObj obj) + { + obj.Opacity = 1; + obj.Align = Types.TextAlign.Left; + obj.Visible = false; + m_resourcePool.CheckIn(obj); + } + + public void Draw(Camera2D camera) + { + foreach (TextObj obj in m_resourcePool.ActiveObjsList) + obj.Draw(camera); + } + + public void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Text Manager"); + + m_resourcePool.Dispose(); + m_resourcePool = null; + m_isDisposed = true; + } + } + + public int ActiveTextObjs + { + get { return m_resourcePool.NumActiveObjs; } + } + + public int TotalPoolSize + { + get { return m_resourcePool.TotalPoolSize; } + } + + public int CurrentPoolSize + { + get { return TotalPoolSize - ActiveTextObjs; } + } + } +} diff --git a/RogueCastle/src/Program.cs b/RogueCastle/src/Program.cs new file mode 100644 index 0000000..1db577d --- /dev/null +++ b/RogueCastle/src/Program.cs @@ -0,0 +1,173 @@ +using System; +using System.IO; +using SteamWorksWrapper; +using SDL3; + +namespace RogueCastle +{ + public static class Program + { + /// + /// The main entry point for the application. + /// + static void Main(string[] args) + { + Environment.SetEnvironmentVariable("FNA_PLATFORM_BACKEND", "SDL3"); + + bool loadGame = true; + + if (LevelEV.CREATE_RETAIL_VERSION == true)// && LevelEV.CREATE_INSTALLABLE == false) + { + Steamworks.Init(); + loadGame = Steamworks.WasInit; + } + + // Don't really need this anymore... -flibit + //if (loadGame == true) + { +#if true + // Dave's custom EV settings for localization testing + //LevelEV.RUN_TESTROOM = true;// false; // true; // false; + //LevelEV.LOAD_SPLASH_SCREEN = false; // true; // false; + //LevelEV.CREATE_RETAIL_VERSION = false; + //LevelEV.SHOW_DEBUG_TEXT = false; // true; +#endif + + if (LevelEV.CREATE_RETAIL_VERSION == true) + { + LevelEV.SHOW_ENEMY_RADII = false; + LevelEV.ENABLE_DEBUG_INPUT = false; + LevelEV.UNLOCK_ALL_ABILITIES = false; + LevelEV.TESTROOM_LEVELTYPE = GameTypes.LevelType.CASTLE; + LevelEV.TESTROOM_REVERSE = false; + LevelEV.RUN_TESTROOM = false; + LevelEV.SHOW_DEBUG_TEXT = false; + LevelEV.LOAD_TITLE_SCREEN = false; + LevelEV.LOAD_SPLASH_SCREEN = true; + LevelEV.SHOW_SAVELOAD_DEBUG_TEXT = false; + LevelEV.DELETE_SAVEFILE = false; + LevelEV.CLOSE_TESTROOM_DOORS = false; + LevelEV.RUN_TUTORIAL = false; + LevelEV.RUN_DEMO_VERSION = false; + LevelEV.DISABLE_SAVING = false; + LevelEV.RUN_CRASH_LOGS = true; + LevelEV.WEAKEN_BOSSES = false; + LevelEV.ENABLE_BACKUP_SAVING = true; + LevelEV.ENABLE_OFFSCREEN_CONTROL = false; + LevelEV.SHOW_FPS = false; + LevelEV.SAVE_FRAMES = false; + LevelEV.UNLOCK_ALL_DIARY_ENTRIES = false; + LevelEV.ENABLE_BLITWORKS_SPLASH = false; + } + + if (args.Length == 1 && LevelEV.CREATE_RETAIL_VERSION == false) + { + using (Game game = new Game(args[0])) + { + LevelEV.RUN_TESTROOM = true; + LevelEV.DISABLE_SAVING = true; + game.Run(); + } + } + else + { + if (LevelEV.RUN_CRASH_LOGS == true) + { + try + { + using (Game game = new Game()) + { + game.Run(); + } + } + catch (Exception e) + { + string date = DateTime.Now.ToString("dd-mm-yyyy_HH-mm-ss"); + if (!Directory.Exists(Program.OSDir)) + Directory.CreateDirectory(Program.OSDir); + string configFilePath = Path.Combine(Program.OSDir, "CrashLog_" + date + ".log"); + + //using (StreamWriter writer = new StreamWriter("CrashLog_" + date + ".log", false)) + using (StreamWriter writer = new StreamWriter(configFilePath, false)) + { + writer.WriteLine(e.ToString()); + } + + Console.WriteLine(e.ToString()); + SDL.SDL_ShowSimpleMessageBox( + SDL.SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR, + "SAVE THIS MESSAGE!", + e.ToString(), + IntPtr.Zero + ); + } + } + else + { + using (Game game = new Game()) + { + game.Run(); + } + } + } + } + //else + //{ + // #if STEAM + // SDL.SDL_ShowSimpleMessageBox( + // SDL.SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR, + // "Launch Error", + // "Please load Rogue Legacy from the Steam client", + // IntPtr.Zero + // ); + // #endif + //} + Steamworks.Shutdown(); + } + + public static readonly string OSDir = GetOSDir(); + private static string GetOSDir() + { + string os = SDL.SDL_GetPlatform(); + if ( os.Equals("Linux") || + os.Equals("FreeBSD") || + os.Equals("OpenBSD") || + os.Equals("NetBSD") ) + { + string osDir = Environment.GetEnvironmentVariable("XDG_CONFIG_HOME"); + if (string.IsNullOrEmpty(osDir)) + { + osDir = Environment.GetEnvironmentVariable("HOME"); + if (string.IsNullOrEmpty(osDir)) + { + return "."; // Oh well. + } + else + { + return Path.Combine(osDir, ".config", "RogueLegacy"); + } + } + return Path.Combine(osDir, "RogueLegacy"); + } + else if (os.Equals("Mac OS X")) + { + string osDir = Environment.GetEnvironmentVariable("HOME"); + if (string.IsNullOrEmpty(osDir)) + { + return "."; // Oh well. + } + return Path.Combine(osDir, "Library/Application Support/RogueLegacy"); + } + else if (!os.Equals("Windows")) + { + throw new NotSupportedException("Unhandled SDL3 platform!"); + } + else + { + string appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + return Path.Combine(appdata, "Rogue Legacy"); + } + } + } +} + diff --git a/RogueCastle/src/ProjectileIconPool.cs b/RogueCastle/src/ProjectileIconPool.cs new file mode 100644 index 0000000..9a04e76 --- /dev/null +++ b/RogueCastle/src/ProjectileIconPool.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class ProjectileIconPool : IDisposable + { + private bool m_isDisposed = false; + private DS2DPool m_resourcePool; + private int m_poolSize = 0; + private ProjectileManager m_projectileManager; + private RCScreenManager m_screenManager; + + public ProjectileIconPool(int poolSize, ProjectileManager projectileManager, RCScreenManager screenManager) + { + m_poolSize = poolSize; // Please keep this pool small + m_resourcePool = new DS2DPool(); + + m_projectileManager = projectileManager; + m_screenManager = screenManager; + } + + public void Initialize() + { + for (int i = 0; i < m_poolSize; i++) + { + ProjectileIconObj poolObj = new ProjectileIconObj(); + //poolObj.AnimationDelay = 1 / 30f; + poolObj.Visible = false; + poolObj.ForceDraw = true; + poolObj.TextureColor = Color.White; + m_resourcePool.AddToPool(poolObj); + } + } + + public void AddIcon(ProjectileObj projectile) + { + ProjectileIconObj icon = m_resourcePool.CheckOut(); + icon.Visible = true; + icon.ForceDraw = true; + icon.AttachedProjectile = projectile; // Linking the projectile and the icon. + projectile.AttachedIcon = icon; + } + + + public void DestroyIcon(ProjectileObj projectile) + { + ProjectileIconObj icon = projectile.AttachedIcon; + icon.Visible = false; + icon.Rotation = 0; + icon.TextureColor = Color.White; + icon.Opacity = 1; + icon.Flip = SpriteEffects.None; + icon.Scale = new Vector2(1, 1); + m_resourcePool.CheckIn(icon); + + //obj.AnimationDelay = 1 / 30f; + + icon.AttachedProjectile = null; // De-linking the projectile and the icon. + projectile.AttachedIcon = null; + } + + public void DestroyAllIcons() + { + foreach (ProjectileObj projectile in m_projectileManager.ActiveProjectileList) + { + if (projectile.AttachedIcon != null) + DestroyIcon(projectile); + } + } + + public void Update(Camera2D camera) + { + PlayerObj player = m_screenManager.Player; + + foreach (ProjectileObj projectile in m_projectileManager.ActiveProjectileList) + { + if (projectile.ShowIcon == true) // Make sure to only show icons if this flag is set to true. + { + if (projectile.AttachedIcon == null) + { + if (CollisionMath.Intersects(projectile.Bounds, camera.Bounds) == false) // Projectile is outside of the camera bounds. + { + // Using 1 because it needs a margin of error. + if ((projectile.AccelerationX > 1 && projectile.X < player.X && (projectile.Y > camera.Bounds.Top && projectile.Y < camera.Bounds.Bottom)) || + (projectile.AccelerationX < -1 && projectile.X > player.X && (projectile.Y > camera.Bounds.Top && projectile.Y < camera.Bounds.Bottom)) || + (projectile.AccelerationY > 1 && projectile.Y < player.Y && (projectile.X > camera.Bounds.Left && projectile.X < camera.Bounds.Right)) || + (projectile.AccelerationY < -1 && projectile.Y > player.Y && (projectile.X > camera.Bounds.Left && projectile.X < camera.Bounds.Right))) + AddIcon(projectile); + } + } + else + { + if (CollisionMath.Intersects(projectile.Bounds, camera.Bounds) == true) // Destroy projectile icons if they get in camera range. + DestroyIcon(projectile); + } + } + } + + // A check to make sure projectiles that die do not have a lingering icon attached to them. + for (int i = 0; i < m_resourcePool.ActiveObjsList.Count; i++) + { + if (m_resourcePool.ActiveObjsList[i].AttachedProjectile.IsAlive == false) + { + DestroyIcon(m_resourcePool.ActiveObjsList[i].AttachedProjectile); + i--; + } + } + + foreach (ProjectileIconObj projIcon in m_resourcePool.ActiveObjsList) + projIcon.Update(camera); + } + + public void Draw(Camera2D camera) + { + if (Game.PlayerStats.Traits.X != TraitType.TunnelVision && Game.PlayerStats.Traits.Y != TraitType.TunnelVision) + { + foreach (ProjectileIconObj projIcon in m_resourcePool.ActiveObjsList) + projIcon.Draw(camera); + } + } + + + public void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Projectile Icon Pool"); + + m_resourcePool.Dispose(); + m_resourcePool = null; + m_isDisposed = true; + m_projectileManager = null; + m_screenManager = null; + } + } + + public bool IsDisposed + { + get { return m_isDisposed; } + } + + + public int ActiveTextObjs + { + get { return m_resourcePool.NumActiveObjs; } + } + + public int TotalPoolSize + { + get { return m_resourcePool.TotalPoolSize; } + } + + public int CurrentPoolSize + { + get { return TotalPoolSize - ActiveTextObjs; } + } + } +} diff --git a/RogueCastle/src/SWManager.cs b/RogueCastle/src/SWManager.cs new file mode 100644 index 0000000..a06a6c1 --- /dev/null +++ b/RogueCastle/src/SWManager.cs @@ -0,0 +1,143 @@ +using System; +using System.Runtime.InteropServices; + +namespace SteamWorksWrapper +{ + public class Steamworks + { + private enum ESteamAPIInitResult + { + k_ESteamAPIInitResult_OK = 0, + k_ESteamAPIInitResult_FailedGeneric = 1, + k_ESteamAPIInitResult_NoSteamClient = 2, + k_ESteamAPIInitResult_VersionMismatch = 3, + } + + [DllImport("steam_api", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern ESteamAPIInitResult SteamAPI_InitFlat(IntPtr errMsg); + + [DllImport("steam_api", CallingConvention = CallingConvention.Cdecl)] + private static extern void SteamAPI_Shutdown(); + + [DllImport("steam_api", CallingConvention = CallingConvention.Cdecl)] + private static extern void SteamAPI_RunCallbacks(); + + [DllImport("steam_api", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr SteamInternal_CreateInterface( + [MarshalAs(UnmanagedType.LPStr)] + string pchVersion + ); + + [DllImport("steam_api", CallingConvention = CallingConvention.Cdecl)] + private static extern int SteamAPI_GetHSteamUser(); + + [DllImport("steam_api", CallingConvention = CallingConvention.Cdecl)] + private static extern int SteamAPI_GetHSteamPipe(); + + [DllImport("steam_api", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr SteamAPI_ISteamClient_GetISteamUserStats( + IntPtr steamClient, + int steamUser, + int steamPipe, + [MarshalAs(UnmanagedType.LPStr)] + string pchVersion + ); + + [DllImport("steam_api", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool SteamAPI_ISteamUserStats_RequestCurrentStats( + IntPtr instance + ); + + [DllImport("steam_api", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool SteamAPI_ISteamUserStats_StoreStats( + IntPtr instance + ); + + [DllImport("steam_api", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool SteamAPI_ISteamUserStats_SetAchievement( + IntPtr instance, + [MarshalAs(UnmanagedType.LPStr)] + string name + ); + + [DllImport("steam_api", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool SteamAPI_ISteamUserStats_GetAchievement( + IntPtr instance, + [MarshalAs(UnmanagedType.LPStr)] + string name, + [MarshalAs(UnmanagedType.I1)] + out bool achieved + ); + + public static bool WasInit = false; + private static IntPtr steamUserStats; + + public static void Init() + { + try + { + WasInit = SteamAPI_InitFlat(IntPtr.Zero) == ESteamAPIInitResult.k_ESteamAPIInitResult_OK; + } + catch + { + WasInit = false; + } + if (WasInit) + { + IntPtr steamClient = SteamInternal_CreateInterface( + "SteamClient021" + ); + int steamUser = SteamAPI_GetHSteamUser(); + int steamPipe = SteamAPI_GetHSteamPipe(); + steamUserStats = SteamAPI_ISteamClient_GetISteamUserStats( + steamClient, + steamUser, + steamPipe, + "STEAMUSERSTATS_INTERFACE_VERSION012" + ); + SteamAPI_ISteamUserStats_RequestCurrentStats(steamUserStats); + } + } + + public static void Shutdown() + { + if (WasInit) + { + SteamAPI_Shutdown(); + } + } + + public static void Update() + { + if (WasInit) + { + SteamAPI_RunCallbacks(); + } + } + + public static void UnlockAchievement(string name) + { + if (WasInit) + { + SteamAPI_ISteamUserStats_SetAchievement(steamUserStats, name); + SteamAPI_ISteamUserStats_StoreStats(steamUserStats); + SteamAPI_RunCallbacks(); + } + } + + public static bool IsAchievementUnlocked(string name) + { + bool achieved = false; + if (WasInit) + { + SteamAPI_ISteamUserStats_GetAchievement(steamUserStats, name, out achieved); + } + return achieved; + } + } +} diff --git a/RogueCastle/src/Screens/Base Objects/RCScreenManager.cs b/RogueCastle/src/Screens/Base Objects/RCScreenManager.cs new file mode 100644 index 0000000..5ad4f24 --- /dev/null +++ b/RogueCastle/src/Screens/Base Objects/RCScreenManager.cs @@ -0,0 +1,599 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Tweener; +using Tweener.Ease; + +namespace RogueCastle +{ + public class RCScreenManager : ScreenManager + { + private GameOverScreen m_gameOverScreen; + private SkillScreen m_traitScreen; + private EnchantressScreen m_enchantressScreen; + private BlacksmithScreen m_blacksmithScreen; + private GetItemScreen m_getItemScreen; + private DialogueScreen m_dialogueScreen; + private MapScreen m_mapScreen; + private PauseScreen m_pauseScreen; + private OptionsScreen m_optionsScreen; + private ProfileCardScreen m_profileCardScreen; + private CreditsScreen m_creditsScreen; + private SkillUnlockScreen m_skillUnlockScreen; + private DiaryEntryScreen m_diaryEntryScreen; + private DeathDefiedScreen m_deathDefyScreen; + private DiaryFlashbackScreen m_flashbackScreen; + private TextScreen m_textScreen; + private GameOverBossScreen m_gameOverBossScreen; + + private ProfileSelectScreen m_profileSelectScreen; + + private VirtualScreen m_virtualScreen; + + private bool m_isTransitioning = false; + + private bool m_inventoryVisible = false; + + private PlayerObj m_player; + private SpriteObj m_blackTransitionIn, m_blackScreen, m_blackTransitionOut; + private bool m_isWipeTransitioning = false; + + private int m_currentScreenType; + public int currentScreenType + { get { return m_currentScreenType; } } + + public RCScreenManager(Game Game) + : base(Game) + { + } + + public override void Initialize() + { + InitializeScreens(); + base.Initialize(); // Camera gets initialized here. + + m_virtualScreen = new VirtualScreen(GlobalEV.ScreenWidth, GlobalEV.ScreenHeight, Camera.GraphicsDevice); + Game.Window.ClientSizeChanged += new EventHandler(Window_ClientSizeChanged); + Game.Deactivated += new EventHandler(PauseGame); + + // Setting up the event handling for window dragging. + // THIS HAS BEEN DISABLED BECAUSE WE ADDED MOUSE BUTTONS AS BINDABLE + //System.Windows.Forms.Form winForm = System.Windows.Forms.Control.FromHandle(Game.Window.Handle) as System.Windows.Forms.Form; + //if (winForm != null) + // winForm.MouseCaptureChanged += new EventHandler(PauseGame); + + //Camera.GraphicsDevice.DeviceReset += new EventHandler(ReinitializeContent); + //Window.AllowUserResizing = true; + } + + public void PauseGame(object sender, EventArgs e) + { + ///Microsoft.Xna.Framework.WindowsGameForm + //Console.WriteLine(sender is Microsoft.Xna.Framework.GameWindow); + //Console.WriteLine(sender); + ProceduralLevelScreen level = CurrentScreen as ProceduralLevelScreen; + if (level != null && (level.CurrentRoom is EndingRoomObj == false))// && RogueCastle.Game.PlayerStats.TutorialComplete == true) + DisplayScreen(ScreenType.Pause, true); + } + + public void ReinitializeContent(object sender, EventArgs e) + { + m_virtualScreen.ReinitializeRTs(Game.GraphicsDevice); + + foreach (Screen screen in m_screenArray) + screen.DisposeRTs(); + + foreach (Screen screen in m_screenArray) + screen.ReinitializeRTs(); + } + + public void ReinitializeCamera(GraphicsDevice graphicsDevice) + { + m_camera.Dispose(); + m_camera = new Camera2D(graphicsDevice, EngineEV.ScreenWidth, EngineEV.ScreenHeight); + } + + private List m_screenCleanupList = new List(); + public void InitializeScreens() + { + if (m_gameOverScreen != null) + m_screenCleanupList.Add(m_gameOverScreen); + m_gameOverScreen = new GameOverScreen(); + + if (m_traitScreen != null) + m_screenCleanupList.Add(m_traitScreen); + m_traitScreen = new SkillScreen(); + + if (m_blacksmithScreen != null) + m_screenCleanupList.Add(m_blacksmithScreen); + m_blacksmithScreen = new BlacksmithScreen(); + + if (m_getItemScreen != null) + m_screenCleanupList.Add(m_getItemScreen); + m_getItemScreen = new GetItemScreen(); + + if (m_enchantressScreen != null) + m_screenCleanupList.Add(m_enchantressScreen); + m_enchantressScreen = new EnchantressScreen(); + + if (m_dialogueScreen != null) + m_screenCleanupList.Add(m_dialogueScreen); + m_dialogueScreen = new DialogueScreen(); + + if (m_pauseScreen != null) + m_screenCleanupList.Add(m_pauseScreen); + m_pauseScreen = new PauseScreen(); + + if (m_optionsScreen != null) + m_screenCleanupList.Add(m_optionsScreen); + m_optionsScreen = new OptionsScreen(); + + if (m_profileCardScreen != null) + m_screenCleanupList.Add(m_profileCardScreen); + m_profileCardScreen = new ProfileCardScreen(); + + if (m_creditsScreen != null) + m_screenCleanupList.Add(m_creditsScreen); + m_creditsScreen = new CreditsScreen(); + + if (m_skillUnlockScreen != null) + m_screenCleanupList.Add(m_skillUnlockScreen); + m_skillUnlockScreen = new SkillUnlockScreen(); + + if (m_diaryEntryScreen != null) + m_screenCleanupList.Add(m_diaryEntryScreen); + m_diaryEntryScreen = new DiaryEntryScreen(); + + if (m_deathDefyScreen != null) + m_screenCleanupList.Add(m_deathDefyScreen); + m_deathDefyScreen = new DeathDefiedScreen(); + + if (m_textScreen != null) + m_screenCleanupList.Add(m_textScreen); + m_textScreen = new TextScreen(); + + if (m_flashbackScreen != null) + m_screenCleanupList.Add(m_flashbackScreen); + m_flashbackScreen = new DiaryFlashbackScreen(); + + if (m_gameOverBossScreen != null) + m_screenCleanupList.Add(m_gameOverBossScreen); + m_gameOverBossScreen = new GameOverBossScreen(); + + if (m_profileSelectScreen != null) + m_screenCleanupList.Add(m_profileSelectScreen); + m_profileSelectScreen = new ProfileSelectScreen(); + } + + public override void LoadContent() + { + m_gameOverScreen.LoadContent(); + m_traitScreen.LoadContent(); + m_blacksmithScreen.LoadContent(); + m_getItemScreen.LoadContent(); + m_enchantressScreen.LoadContent(); + m_dialogueScreen.LoadContent(); + m_pauseScreen.LoadContent(); + m_optionsScreen.LoadContent(); + m_profileCardScreen.LoadContent(); + m_creditsScreen.LoadContent(); + m_skillUnlockScreen.LoadContent(); + m_diaryEntryScreen.LoadContent(); + m_deathDefyScreen.LoadContent(); + m_textScreen.LoadContent(); + m_flashbackScreen.LoadContent(); + m_gameOverBossScreen.LoadContent(); + m_profileSelectScreen.LoadContent(); + + if (IsContentLoaded == false) + { + m_blackTransitionIn = new SpriteObj("Blank_Sprite"); + m_blackTransitionIn.Rotation = 15; + m_blackTransitionIn.Scale = new Vector2(1320 / m_blackTransitionIn.Width, 2000 / m_blackTransitionIn.Height); + m_blackTransitionIn.TextureColor = Color.Black; + m_blackTransitionIn.ForceDraw = true; + + m_blackScreen = new SpriteObj("Blank_Sprite"); + m_blackScreen.Scale = new Vector2(1320 / m_blackScreen.Width, 720 / m_blackScreen.Height); + m_blackScreen.TextureColor = Color.Black; + m_blackScreen.ForceDraw = true; + + m_blackTransitionOut = new SpriteObj("Blank_Sprite"); + m_blackTransitionOut.Rotation = 15; + m_blackTransitionOut.Scale = new Vector2(1320 / m_blackTransitionOut.Width, 2000 / m_blackTransitionOut.Height); + m_blackTransitionOut.TextureColor = Color.Black; + m_blackTransitionOut.ForceDraw = true; + + m_blackTransitionIn.X = 0; + m_blackTransitionIn.X = 1320 - m_blackTransitionIn.Bounds.Left; + m_blackScreen.X = m_blackTransitionIn.X; + m_blackTransitionOut.X = m_blackScreen.X + m_blackScreen.Width; + m_blackTransitionIn.Visible = false; + m_blackScreen.Visible = false; + m_blackTransitionOut.Visible = false; + + LoadPlayer(); + } + + base.LoadContent(); + } + + private void Window_ClientSizeChanged(object sender, EventArgs e) + { + m_virtualScreen.PhysicalResolutionChanged(); + EngineEV.RefreshEngine(Camera.GraphicsDevice); + Console.WriteLine("resolution changed"); + } + + private void LoadPlayer() + { + if (m_player == null) + { + m_player = new PlayerObj("PlayerIdle_Character", PlayerIndex.One, (Game as Game).PhysicsManager, null, (Game as Game)); + m_player.Position = new Vector2(200, 200); + m_player.Initialize(); + } + } + + public void DisplayScreen(int screenType, bool pauseOtherScreens, List objList = null) + { + LoadPlayer(); + + if (pauseOtherScreens == true) + { + // This needs to be changed so that the ScreenManager holds a reference to the ProceduralLevelScreen. + foreach (Screen screen in GetScreens()) + { + if (screen == CurrentScreen) + { + screen.PauseScreen(); + break; + } + } + } + + m_currentScreenType = screenType; + //if (CurrentScreen != null && !(CurrentScreen is ProceduralLevelScreen)) + // RemoveScreen(CurrentScreen, false); + + // This currently has no checks to see if the screen is already in the screenmanager's screen list. + switch (screenType) + { + case (ScreenType.CDGSplash): + case(ScreenType.BlitWorks): + case (ScreenType.Title): + case(ScreenType.TitleWhite): + case (ScreenType.StartingRoom): + case (ScreenType.DemoStart): + case(ScreenType.DemoEnd): + case (ScreenType.Lineage): + this.LoadScreen((byte)screenType, true); + break; + case (ScreenType.Level): + if (RogueCastle.Game.PlayerStats.LockCastle == true || (this.CurrentScreen is ProceduralLevelScreen == false)) + this.LoadScreen((byte)screenType, true); + else + this.LoadScreen((byte)screenType, false); + break; + case (ScreenType.Skill): + this.AddScreen(m_traitScreen, null); + break; + case(ScreenType.GameOver): + m_gameOverScreen.PassInData(objList); + this.AddScreen(m_gameOverScreen, null); + break; + case (ScreenType.GameOverBoss): + m_gameOverBossScreen.PassInData(objList); + this.AddScreen(m_gameOverBossScreen, null); + break; + case (ScreenType.Blacksmith): + m_blacksmithScreen.Player = m_player; + this.AddScreen(m_blacksmithScreen, null); + break; + case (ScreenType.GetItem): + m_getItemScreen.PassInData(objList); + this.AddScreen(m_getItemScreen, null); + break; + case (ScreenType.Enchantress): + m_enchantressScreen.Player = m_player; + this.AddScreen(m_enchantressScreen, null); + break; + case (ScreenType.Dialogue): + this.AddScreen(m_dialogueScreen, null); + break; + case (ScreenType.Map): + m_mapScreen.SetPlayer(m_player); + this.AddScreen(m_mapScreen, null); + break; + case (ScreenType.Pause): + GetLevelScreen().CurrentRoom.DarkenRoom(); + this.AddScreen(m_pauseScreen, null); + break; + case (ScreenType.Options): + m_optionsScreen.PassInData(objList); + this.AddScreen(m_optionsScreen, null); + break; + case(ScreenType.ProfileCard): + this.AddScreen(m_profileCardScreen, null); + break; + case (ScreenType.Credits): + this.LoadScreen(ScreenType.Credits, true); + break; + case (ScreenType.SkillUnlock): + m_skillUnlockScreen.PassInData(objList); + this.AddScreen(m_skillUnlockScreen, null); + break; + case (ScreenType.DiaryEntry): + this.AddScreen(m_diaryEntryScreen, null); + break; + case (ScreenType.DeathDefy): + this.AddScreen(m_deathDefyScreen, null); + break; + case (ScreenType.Text): + m_textScreen.PassInData(objList); + this.AddScreen(m_textScreen, null); + break; + case (ScreenType.TutorialRoom): + this.LoadScreen(ScreenType.TutorialRoom, true); + break; + case (ScreenType.Ending): + GetLevelScreen().CameraLockedToPlayer = false; + GetLevelScreen().DisableRoomTransitioning = true; + Player.Position = new Vector2(100, 100); //HHHAACCK + this.LoadScreen(ScreenType.Ending, true); + break; + case (ScreenType.DiaryFlashback): + this.AddScreen(m_flashbackScreen, null); + break; + case (ScreenType.ProfileSelect): + this.AddScreen(m_profileSelectScreen, null); + break; + } + + if (m_isWipeTransitioning == true) + EndWipeTransition(); + } + + public void AddRoomsToMap(List roomList) + { + m_mapScreen.AddRooms(roomList); + } + + public void AddIconsToMap(List roomList) + { + m_mapScreen.AddAllIcons(roomList); + } + + public void RefreshMapScreenChestIcons(RoomObj room) + { + m_mapScreen.RefreshMapChestIcons(room); + } + + public void ActivateMapScreenTeleporter() + { + m_mapScreen.IsTeleporter = true; + } + + public void HideCurrentScreen() + { + this.RemoveScreen(this.CurrentScreen, false); + + ProceduralLevelScreen level = CurrentScreen as ProceduralLevelScreen; + if (level != null) + level.UnpauseScreen(); + + if (m_isWipeTransitioning == true) + EndWipeTransition(); + } + + public void ForceResolutionChangeCheck() + { + m_virtualScreen.PhysicalResolutionChanged(); + EngineEV.RefreshEngine(this.Game.GraphicsDevice); + } + + // This is overridden so that a custom LoadScreen can be passed in. + private void LoadScreen(byte screenType, bool wipeTransition) + { + m_currentScreenType = ScreenType.Loading; + foreach (Screen screen in m_screenArray) + { + screen.DrawIfCovered = true; + ProceduralLevelScreen levelScreen = screen as ProceduralLevelScreen; + if (levelScreen != null) + { + m_player.AttachLevel(levelScreen); + levelScreen.Player = m_player; + + AttachMap(levelScreen); + } + } + + // Double check this. This doesn't seem right. + if (m_gameOverScreen != null) + { + this.InitializeScreens(); + this.LoadContent(); // Since all screens are disposed, their content needs to be loaded again. Hacked. + } + + // Create and activate the loading screen. + LoadingScreen loadingScreen = new LoadingScreen(screenType, wipeTransition); + m_isTransitioning = true; + + this.AddScreen(loadingScreen, PlayerIndex.One); + + // This has been moved to PerformCleanUp(). + //GC.Collect(); // Should this be called? Most people say don't, but I want to ensure that collection occurs during the loading screen, not some random moment later. + } + + public void PerformCleanUp() + { + foreach (Screen screen in m_screenCleanupList) + { + if (screen.IsDisposed == false && screen.IsContentLoaded == true) + screen.Dispose(); + } + m_screenCleanupList.Clear(); + + GC.Collect(); // Should this be called? Most people say don't, but I want to ensure that collection occurs during the loading screen, not some random moment later. + } + + public void LoadingComplete(int screenType) + { + m_currentScreenType = screenType; + } + + public override void RemoveScreen(Screen screen, bool disposeScreen) + { + if (screen is LoadingScreen) + m_isTransitioning = false; + base.RemoveScreen(screen, disposeScreen); + } + + public void AttachMap(ProceduralLevelScreen level) + { + if (m_mapScreen != null) + m_mapScreen.Dispose(); + m_mapScreen = new MapScreen(level); + } + + public override void Update(GameTime gameTime) + { + m_virtualScreen.Update(); + if (m_isTransitioning == false) + base.Update(gameTime); + else + { + Camera.GameTime = gameTime; + if (CurrentScreen != null) + { + CurrentScreen.Update(gameTime); + CurrentScreen.HandleInput(); + } + } + } + + public override void Draw(GameTime gameTime) + { + m_virtualScreen.BeginCapture(); + Camera.GraphicsDevice.Clear(Color.Black); + + // Must be called after BeginCapture(), in case graphics virtualization fails and the device is hard reset. + if (Camera.GameTime == null) + Camera.GameTime = gameTime; + + base.Draw(gameTime); + + m_virtualScreen.EndCapture(); + Camera.GraphicsDevice.Clear(Color.Black); + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null); + m_virtualScreen.Draw(Camera); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + m_blackTransitionIn.Draw(Camera); + m_blackTransitionOut.Draw(Camera); + m_blackScreen.Draw(Camera); + Camera.End(); + + if (LevelEV.ENABLE_DEBUG_INPUT == true) + { + Camera.Begin(); + string forcedGenderString = "None"; + switch (RogueCastle.Game.PlayerStats.ForceLanguageGender) + { + case (1): + forcedGenderString = "Male"; + break; + case (2): + forcedGenderString = "Female"; + break; + } + + string godModeString = "Off"; + if (RogueCastle.Game.PlayerStats.GodMode == true) + godModeString = "On"; + Camera.DrawString(RogueCastle.Game.PixelArtFont, "Forced Gender Language: " + forcedGenderString, new Vector2(10, 10), Color.White); + Camera.DrawString(RogueCastle.Game.PixelArtFont, "God Mode: " + godModeString, new Vector2(10, 30), Color.White); + Camera.End(); + } + } + + public void StartWipeTransition() + { + m_isWipeTransitioning = true; + m_blackTransitionIn.Visible = true; + m_blackScreen.Visible = true; + m_blackTransitionOut.Visible = true; + + m_blackTransitionIn.X = 0; + m_blackTransitionOut.Y = -500; + m_blackTransitionIn.X = 1320 - m_blackTransitionIn.Bounds.Left; + m_blackScreen.X = m_blackTransitionIn.X; + m_blackTransitionOut.X = m_blackScreen.X + m_blackScreen.Width; + + Tween.By(m_blackTransitionIn, 0.15f, Quad.EaseInOut, "X", (-m_blackTransitionIn.X).ToString()); + Tween.By(m_blackScreen, 0.15f, Quad.EaseInOut, "X", (-m_blackTransitionIn.X).ToString()); + Tween.By(m_blackTransitionOut, 0.15f, Quad.EaseInOut, "X", (-m_blackTransitionIn.X).ToString()); + //Tween.AddEndHandlerToLastTween(this, "EndWipeTransition"); + } + + public void EndWipeTransition() + { + m_isWipeTransitioning = false; + + m_blackTransitionOut.Y = -500; + Tween.By(m_blackTransitionIn, 0.25f, Quad.EaseInOut, "X", "-3000"); + Tween.By(m_blackScreen, 0.25f, Quad.EaseInOut, "X", "-3000"); + Tween.By(m_blackTransitionOut, 0.25f, Quad.EaseInOut, "X", "-3000"); + } + + public void UpdatePauseScreenIcons() + { + m_pauseScreen.UpdatePauseScreenIcons(); + } + + public bool InventoryVisible + { + get { return m_inventoryVisible; } + } + + public ProceduralLevelScreen GetLevelScreen() + { + foreach (Screen screen in GetScreens()) + { + ProceduralLevelScreen level = screen as ProceduralLevelScreen; + if (level != null) + return level; + } + return null; + } + + public RenderTarget2D RenderTarget + { + get { return m_virtualScreen.RenderTarget; } + } + + public DialogueScreen DialogueScreen + { + get { return m_dialogueScreen; } + } + + public SkillScreen SkillScreen + { + get { return m_traitScreen; } + } + + public PlayerObj Player + { + get { return m_player; } + } + + public bool IsTransitioning + { + get { return m_isTransitioning; } + } + } +} diff --git a/RogueCastle/src/Screens/BlacksmithScreen.cs b/RogueCastle/src/Screens/BlacksmithScreen.cs new file mode 100644 index 0000000..03c9889 --- /dev/null +++ b/RogueCastle/src/Screens/BlacksmithScreen.cs @@ -0,0 +1,1094 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using DS2DEngine; +using Tweener; +using Tweener.Ease; +using InputSystem; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Audio; + +namespace RogueCastle +{ + public class BlacksmithScreen : Screen + { + private const int m_startingCategoryIndex = 6; + + private ObjContainer m_blacksmithUI; + private SpriteObj m_selectionIcon; + public float BackBufferOpacity { get; set; } + private int m_currentCategoryIndex = 0; + private int m_currentEquipmentIndex = 0; + + private List m_masterIconArray; + private ObjContainer[] m_activeIconArray; + + private List m_newIconList; + private int m_newIconListIndex; + private TextObj m_playerMoney; + + private SpriteObj m_equippedIcon; + + // Text objects + private TextObj m_equipmentDescriptionText; + private ObjContainer m_textInfoTitleContainer; + private ObjContainer m_textInfoStatContainer; + private ObjContainer m_textInfoStatModContainer; + private ObjContainer m_unlockCostContainer; + private TextObj m_addPropertiesTitleText; + private TextObj m_addPropertiesText; + private TextObj m_equipmentTitleText; + + private bool m_inCategoryMenu = true; + + public PlayerObj Player { get; set; } + + private KeyIconTextObj m_confirmText; + private KeyIconTextObj m_cancelText; + private KeyIconTextObj m_navigationText; + + private bool m_lockControls = false; + private Cue m_rainSound; + + public BlacksmithScreen() + { + m_currentCategoryIndex = m_startingCategoryIndex; + + m_masterIconArray = new List(); + for (int i = 0; i < EquipmentCategoryType.Total; i++) + { + m_masterIconArray.Add(new ObjContainer[EquipmentBaseType.Total]); + } + } + + public override void LoadContent() + { + m_blacksmithUI = new ObjContainer("BlacksmithUI_Character"); + m_blacksmithUI.Position = new Vector2(1320 / 2, 720 / 2); + + m_playerMoney = new TextObj(Game.GoldFont); + m_playerMoney.Align = Types.TextAlign.Left; + m_playerMoney.Text = "1000"; + m_playerMoney.FontSize = 30; + m_playerMoney.OverrideParentScale = true; + m_playerMoney.Position = new Vector2(210, -225); + m_playerMoney.AnchorY = 10; + m_blacksmithUI.AddChild(m_playerMoney); + + for (int i = 0; i < m_blacksmithUI.NumChildren; i++) + m_blacksmithUI.GetChildAt(i).Scale = Vector2.Zero; + + m_selectionIcon = new SpriteObj("BlacksmithUI_SelectionIcon_Sprite"); + m_selectionIcon.PlayAnimation(true); + m_selectionIcon.Scale = Vector2.Zero; + m_selectionIcon.AnimationDelay = 1 / 10f; + m_selectionIcon.ForceDraw = true; + + m_equipmentDescriptionText = new TextObj(Game.JunicodeFont); + m_equipmentDescriptionText.Align = Types.TextAlign.Centre; + m_equipmentDescriptionText.FontSize = 12; + m_equipmentDescriptionText.Position = new Vector2(230, -20); + m_equipmentDescriptionText.Text = LocaleBuilder.getString("LOC_ID_BLACKSMITH_SCREEN_12", m_equipmentDescriptionText); + m_equipmentDescriptionText.WordWrap(190); + m_equipmentDescriptionText.Scale = Vector2.Zero; + m_blacksmithUI.AddChild(m_equipmentDescriptionText); + + foreach (ObjContainer[] iconArray in m_masterIconArray) + { + Vector2 initialPosition = m_blacksmithUI.GetChildAt(m_startingCategoryIndex).AbsPosition; + initialPosition.X += 85; + float startingX = initialPosition.X; + float iconXOffset = 70; + float iconYOffset = 80; + + for (int i = 0; i < iconArray.Length; i++) + { + iconArray[i] = new ObjContainer("BlacksmithUI_QuestionMarkIcon_Character"); + iconArray[i].Position = initialPosition; + iconArray[i].Scale = Vector2.Zero; + iconArray[i].ForceDraw = true; + + initialPosition.X += iconXOffset; + if (initialPosition.X > startingX + (iconXOffset * 4)) + { + initialPosition.X = startingX; + initialPosition.Y += iconYOffset; + } + } + } + + InitializeTextObjs(); + + m_equippedIcon = new SpriteObj("BlacksmithUI_EquippedIcon_Sprite"); + + m_confirmText = new KeyIconTextObj(Game.JunicodeFont); + m_confirmText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_confirmText); // dummy locID to add TextObj to language refresh list + m_confirmText.FontSize = 12; + m_confirmText.Position = new Vector2(50, 550); + m_confirmText.ForceDraw = true; + + m_cancelText = new KeyIconTextObj(Game.JunicodeFont); + m_cancelText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_cancelText); // dummy locID to add TextObj to language refresh list + m_cancelText.FontSize = 12; + m_cancelText.Position = new Vector2(m_confirmText.X, m_confirmText.Y + 40); + m_cancelText.ForceDraw = true; + + m_navigationText = new KeyIconTextObj(Game.JunicodeFont); + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_navigationText); // dummy locID to add TextObj to language refresh list + m_navigationText.FontSize = 12; + m_navigationText.Position = new Vector2(m_confirmText.X, m_confirmText.Y + 80); + m_navigationText.ForceDraw = true; + + m_newIconList = new List(); + for (int i = 0; i < 25; i++) + { + SpriteObj newIcon = new SpriteObj("BlacksmithUI_NewIcon_Sprite"); + newIcon.Visible = false; + newIcon.Scale = new Vector2(1.1f, 1.1f); + m_newIconList.Add(newIcon); + } + + base.LoadContent(); + } + + private void InitializeTextObjs() + { + m_textInfoTitleContainer = new ObjContainer(); + m_textInfoStatContainer = new ObjContainer(); + m_textInfoStatModContainer = new ObjContainer(); + + string[] nameIDArray = { "LOC_ID_BLACKSMITH_SCREEN_1", "LOC_ID_BLACKSMITH_SCREEN_2", "LOC_ID_BLACKSMITH_SCREEN_3", "LOC_ID_BLACKSMITH_SCREEN_4", "LOC_ID_BLACKSMITH_SCREEN_5", "LOC_ID_BLACKSMITH_SCREEN_6" }; + Vector2 textPosition = Vector2.Zero; + + TextObj textObj = new TextObj(); + textObj.Font = Game.JunicodeFont; + textObj.FontSize = 10; + textObj.Text = "0"; + textObj.ForceDraw = true; + + for (int i = 0; i < nameIDArray.Length; i++) + { + textObj.Position = textPosition; + m_textInfoTitleContainer.AddChild(textObj.Clone() as TextObj); + m_textInfoStatContainer.AddChild(textObj.Clone() as TextObj); + m_textInfoStatModContainer.AddChild(textObj.Clone() as TextObj); + (m_textInfoTitleContainer.GetChildAt(i) as TextObj).Align = Types.TextAlign.Right; + (m_textInfoTitleContainer.GetChildAt(i) as TextObj).Text = LocaleBuilder.getString(nameIDArray[i], m_textInfoTitleContainer.GetChildAt(i) as TextObj); + + textPosition.Y += m_textInfoTitleContainer.GetChildAt(i).Height - 5; + } + + m_addPropertiesTitleText = new TextObj(); + m_addPropertiesTitleText.Font = Game.JunicodeFont; + m_addPropertiesTitleText.FontSize = 8; + m_addPropertiesTitleText.TextureColor = new Color(237, 202, 138); + m_addPropertiesTitleText.Text = LocaleBuilder.getString("LOC_ID_BLACKSMITH_SCREEN_7", m_addPropertiesTitleText); + + m_addPropertiesText = new TextObj(); + m_addPropertiesText.Font = Game.JunicodeFont; + m_addPropertiesText.FontSize = 8; + m_addPropertiesText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_addPropertiesText); // dummy locID to add TextObj to language refresh list + + m_unlockCostContainer = new ObjContainer(); + TextObj coinText = new TextObj(); + coinText.Font = Game.JunicodeFont; + coinText.FontSize = 10; + coinText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", coinText); // dummy locID to add TextObj to language refresh list + coinText.TextureColor = Color.Yellow; + coinText.Position = new Vector2(50, 9); + m_unlockCostContainer.AddChild(new SpriteObj("BlacksmithUI_CoinBG_Sprite")); + m_unlockCostContainer.AddChild(coinText); + + m_equipmentTitleText = new TextObj(Game.JunicodeFont); + m_equipmentTitleText.ForceDraw = true; + m_equipmentTitleText.FontSize = 12; + m_equipmentTitleText.DropShadow = new Vector2(2, 2); + m_equipmentTitleText.ScaleX = 0.9f; + m_equipmentTitleText.TextureColor = new Color(237, 202, 138); + m_equipmentTitleText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_equipmentTitleText); // dummy locID to add TextObj to language refresh list + + // This is where all the plate textobjs are positioned. + m_textInfoTitleContainer.Position = new Vector2(m_blacksmithUI.X + 205, m_blacksmithUI.Y - m_blacksmithUI.Height / 2 + 45); + m_textInfoStatContainer.Position = new Vector2(m_textInfoTitleContainer.X + 15, m_textInfoTitleContainer.Y); + m_textInfoStatModContainer.Position = new Vector2(m_textInfoStatContainer.X + 75, m_textInfoStatContainer.Y); + m_addPropertiesTitleText.Position = new Vector2(m_blacksmithUI.X + 125, m_textInfoStatModContainer.Bounds.Bottom - 3); + m_addPropertiesText.Position = new Vector2(m_addPropertiesTitleText.X + 15, m_addPropertiesTitleText.Bounds.Bottom); + m_unlockCostContainer.Position = new Vector2(m_blacksmithUI.X + 114, 485); + m_equipmentTitleText.Position = new Vector2(m_blacksmithUI.X + 125, m_textInfoTitleContainer.Y - 45); + + m_textInfoTitleContainer.Visible = false; + m_textInfoStatContainer.Visible = false; + m_textInfoStatModContainer.Visible = false; + m_addPropertiesTitleText.Visible = false; + m_addPropertiesText.Visible = false; + m_unlockCostContainer.Visible = false; + m_equipmentTitleText.Visible = false; + } + + // Displays the icons in a category when you move up and down the category list. + private void DisplayCategory(int equipmentType) + { + float tweenSpeed = 0.2f; + float delay = 0; + // Tween out the current active icon array. + if (m_activeIconArray != null) + { + for (int i = 0; i < EquipmentBaseType.Total; i++) + { + Tween.StopAllContaining(m_activeIconArray[i], false); + Tween.To(m_activeIconArray[i], tweenSpeed, Back.EaseIn, "delay", delay.ToString(), "ScaleX", "0", "ScaleY", "0"); + } + } + + m_activeIconArray = m_masterIconArray[equipmentType]; + delay = 0.2f; + for (int i = 0; i < EquipmentBaseType.Total; i++) + { + Tween.To(m_activeIconArray[i], tweenSpeed, Back.EaseOut, "delay", delay.ToString(), "ScaleX", "1", "ScaleY", "1"); + } + + foreach (SpriteObj icon in m_newIconList) + { + Tween.StopAllContaining(icon, false); + icon.Scale = Vector2.Zero; + Tween.To(icon, tweenSpeed, Back.EaseOut, "delay", delay.ToString(), "ScaleX", "1", "ScaleY", "1"); + } + + UpdateNewIcons(); + + m_equippedIcon.Scale = Vector2.Zero; + Tween.StopAllContaining(m_equippedIcon, false); + Tween.To(m_equippedIcon, tweenSpeed, Back.EaseOut, "delay", delay.ToString(), "ScaleX", "1", "ScaleY", "1"); + } + + public void EaseInMenu() + { + float tweenSpeed = 0.4f; + + // Tween in the menu background. + Tween.To(m_blacksmithUI.GetChildAt(0), tweenSpeed, Back.EaseOut, "ScaleX", "1", "ScaleY", "1"); + + // Tween in the selection halo icon. + Tween.To(m_selectionIcon, tweenSpeed, Back.EaseOut, "delay", "0.25", "ScaleX", "1", "ScaleY", "1"); + float delay = 0.2f; + + // Tween in the Category icons and the title text. + for (int i = m_startingCategoryIndex; i < m_blacksmithUI.NumChildren - 3; i++) + { + delay += 0.05f; + // Scaling in the Category icons. + Tween.To(m_blacksmithUI.GetChildAt(i), tweenSpeed, Back.EaseOut, "delay", delay.ToString(), "ScaleX", "1", "ScaleY", "1"); + } + + // Tween in the description text. + Tween.To(m_blacksmithUI.GetChildAt(m_blacksmithUI.NumChildren - 1), tweenSpeed, Back.EaseOut, "delay", delay.ToString(), "ScaleX", "1", "ScaleY", "1"); + Tween.To(m_blacksmithUI.GetChildAt(m_blacksmithUI.NumChildren - 2), tweenSpeed, Back.EaseOut, "delay", delay.ToString(), "ScaleX", "1", "ScaleY", "1"); + Tween.To(m_blacksmithUI.GetChildAt(m_blacksmithUI.NumChildren - 3), tweenSpeed, Back.EaseOut, "delay", delay.ToString(), "ScaleX", "1", "ScaleY", "1"); + Tween.AddEndHandlerToLastTween(this, "EaseInComplete"); + } + + public void EaseInComplete() + { + m_lockControls = false; + } + + private void EaseOutMenu() + { + foreach (SpriteObj icon in m_newIconList) + icon.Visible = false; + m_equippedIcon.Visible = false; + + Tween.To(m_confirmText, 0.2f, Linear.EaseNone, "Opacity", "0"); + Tween.To(m_cancelText, 0.2f, Linear.EaseNone, "Opacity", "0"); + Tween.To(m_navigationText, 0.2f, Linear.EaseNone, "Opacity", "0"); + + float tweenSpeed = 0.4f; + float delay = 0f; + + // Tween out the description text and title text. + Tween.To(m_blacksmithUI.GetChildAt(m_blacksmithUI.NumChildren - 2), tweenSpeed, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); // Money text + Tween.To(m_blacksmithUI.GetChildAt(m_blacksmithUI.NumChildren - 3), tweenSpeed, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); // Coin Icon + Tween.To(m_blacksmithUI.GetChildAt(m_blacksmithUI.NumChildren - 4), tweenSpeed, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); // Title Text + + for (int i = m_startingCategoryIndex; i < m_startingCategoryIndex + 5; i++) + { + // Tween out the selection halo icon. + if (m_currentCategoryIndex == i) + Tween.To(m_selectionIcon, tweenSpeed, Back.EaseIn, "delay", delay.ToString(), "ScaleX", "0", "ScaleY", "0"); + + Tween.To(m_blacksmithUI.GetChildAt(i), tweenSpeed, Back.EaseIn, "delay", delay.ToString(), "ScaleX", "0", "ScaleY", "0"); + delay += 0.05f; + } + + + // Resets all the category backgrounds. + for (int i = m_startingCategoryIndex - 5; i < m_startingCategoryIndex; i++) + { + m_blacksmithUI.GetChildAt(i).Scale = Vector2.Zero; + } + + // Tween out the visible equipment icons. + for (int i = 0; i < m_activeIconArray.Length; i++) + { + Tween.To(m_activeIconArray[i], tweenSpeed, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + } + + // Tween out the menu background. + Tween.To(m_blacksmithUI.GetChildAt(0), tweenSpeed, Back.EaseIn, "delay", "0.3", "ScaleX", "0", "ScaleY", "0"); + //Tween.AddEndHandlerToLastTween((ScreenManager as RCScreenManager), "HideCurrentScreen"); + Tween.RunFunction(tweenSpeed + 0.35f, ScreenManager, "HideCurrentScreen"); + } + + private void UpdateIconStates() + { + for (int i = 0; i < Game.PlayerStats.GetBlueprintArray.Count; i++) + { + for (int k = 0; k < Game.PlayerStats.GetBlueprintArray[i].Length; k++) + { + byte state = Game.PlayerStats.GetBlueprintArray[i][k]; + if (state == EquipmentState.NotFound) + m_masterIconArray[i][k].ChangeSprite("BlacksmithUI_QuestionMarkIcon_Character"); + else + { + m_masterIconArray[i][k].ChangeSprite("BlacksmithUI_" + EquipmentCategoryType.ToStringEN(i) + ((k % 5) + 1).ToString() + "Icon_Character"); + for (int j = 1; j < m_masterIconArray[i][k].NumChildren; j++) + m_masterIconArray[i][k].GetChildAt(j).Opacity = 0.2f; + } + + if (state > EquipmentState.FoundAndSeen) + { + for (int j = 1; j < m_masterIconArray[i][k].NumChildren; j++) + m_masterIconArray[i][k].GetChildAt(j).Opacity = 1f; + + int colourIndex = 1; + if (i == EquipmentCategoryType.Sword) + colourIndex = 2; + + EquipmentData equipmentData = Game.EquipmentSystem.GetEquipmentData(i, k); + m_masterIconArray[i][k].GetChildAt(colourIndex).TextureColor = equipmentData.FirstColour; + + if (i != EquipmentCategoryType.Cape) + { + colourIndex++; + m_masterIconArray[i][k].GetChildAt(colourIndex).TextureColor = equipmentData.SecondColour; + } + } + } + } + } + + private void UpdateNewIcons() + { + // Updates the player hud in case you equip the blood armor. + if (Player != null) + { + if (Player.CurrentMana > Player.MaxMana) + Player.CurrentMana = Player.MaxMana; + if (Player.CurrentHealth > Player.MaxHealth) + Player.CurrentHealth = Player.MaxHealth; + } + + UpdateMoneyText(); + + m_newIconListIndex = 0; + foreach (SpriteObj sprite in m_newIconList) + sprite.Visible = false; + + for (int i = 0; i < Game.PlayerStats.GetBlueprintArray[CurrentCategoryIndex].Length; i++) + { + byte state = Game.PlayerStats.GetBlueprintArray[CurrentCategoryIndex][i]; + + if (state == EquipmentState.FoundButNotSeen) + { + ObjContainer equipmentIcon = m_masterIconArray[CurrentCategoryIndex][i]; + + SpriteObj newIcon = m_newIconList[m_newIconListIndex]; + newIcon.Visible = true; + newIcon.Position = m_masterIconArray[CurrentCategoryIndex][i].AbsPosition; + newIcon.X -= 20; + newIcon.Y -= 30; + m_newIconListIndex++; + } + } + + + sbyte equippedItemIndex = Game.PlayerStats.GetEquippedArray[CurrentCategoryIndex]; + if (equippedItemIndex > -1) + { + m_equippedIcon.Position = new Vector2(m_activeIconArray[equippedItemIndex].AbsPosition.X + 18, m_activeIconArray[equippedItemIndex].AbsPosition.Y + 18); + m_equippedIcon.Visible = true; + } + else + m_equippedIcon.Visible = false; + } + + public override void OnEnter() + { + if (m_rainSound != null) + m_rainSound.Dispose(); + + bool isSnowing = (DateTime.Now.Month == 12 || DateTime.Now.Month == 1); + + if (isSnowing == false) + m_rainSound = SoundManager.PlaySound("Rain1_Filtered"); + else + m_rainSound = SoundManager.PlaySound("snowloop_filtered"); + + if (Game.PlayerStats.TotalBlueprintsFound >= (EquipmentBaseType.Total * EquipmentCategoryType.Total)) + GameUtil.UnlockAchievement("FEAR_OF_THROWING_STUFF_OUT"); + + m_lockControls = true; + SoundManager.PlaySound("ShopMenuOpen"); + + m_confirmText.Opacity = 0; + m_cancelText.Opacity = 0; + m_navigationText.Opacity = 0; + + Tween.To(m_confirmText, 0.2f, Linear.EaseNone, "Opacity", "1"); + Tween.To(m_cancelText, 0.2f, Linear.EaseNone, "Opacity", "1"); + Tween.To(m_navigationText, 0.2f, Linear.EaseNone, "Opacity", "1"); + + m_confirmText.Text = LocaleBuilder.getString("LOC_ID_BLACKSMITH_SCREEN_8_NEW", m_confirmText); + m_cancelText.Text = LocaleBuilder.getString("LOC_ID_BLACKSMITH_SCREEN_9_NEW", m_cancelText); + + if (InputManager.GamePadIsConnected(PlayerIndex.One) == false) + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_BLACKSMITH_SCREEN_10", m_navigationText); + else + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_BLACKSMITH_SCREEN_11_NEW", m_navigationText); + + m_currentEquipmentIndex = 0; + m_inCategoryMenu = true; + m_selectionIcon.Position = m_blacksmithUI.GetChildAt(m_startingCategoryIndex).AbsPosition; + m_currentCategoryIndex = m_startingCategoryIndex; + UpdateIconStates(); + DisplayCategory(EquipmentCategoryType.Sword); + EaseInMenu(); + Tween.To(this, 0.2f, Linear.EaseNone, "BackBufferOpacity", "0.5"); + UpdateIconSelectionText(); + + RefreshTextObjs(); + base.OnEnter(); + } + + public override void OnExit() + { + if (m_rainSound != null) + m_rainSound.Stop(AudioStopOptions.Immediate); + + for (int i = 0; i < m_blacksmithUI.NumChildren; i++) + m_blacksmithUI.GetChildAt(i).Scale = Vector2.Zero; + + foreach (ObjContainer[] iconArray in m_masterIconArray) + { + for (int i = 0; i < iconArray.Length; i++) + iconArray[i].Scale = Vector2.Zero; + } + m_selectionIcon.Scale = Vector2.Zero; + + + // Hack to make sure player's HP/MP goes up and down according to the item equipped. + Player.CurrentHealth = Player.MaxHealth; + Player.CurrentMana = Player.MaxMana; + + (ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData, SaveType.UpgradeData); + + bool unlockAchievement = true; + foreach (sbyte equipmentType in Game.PlayerStats.GetEquippedArray) + { + if (equipmentType == -1) + { + unlockAchievement = false; + break; + } + } + if (unlockAchievement == true) + GameUtil.UnlockAchievement("FEAR_OF_NUDITY"); + + base.OnExit(); + } + + public override void HandleInput() + { + if (m_lockControls == false) + { + if (m_inCategoryMenu == true) + CategorySelectionInput(); + else + EquipmentSelectionInput(); + } + + base.HandleInput(); + } + + private void CategorySelectionInput() + { + int currentCategoryIndex = m_currentCategoryIndex; + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + m_currentCategoryIndex--; + if (m_currentCategoryIndex < m_startingCategoryIndex) + m_currentCategoryIndex = m_startingCategoryIndex + 4; + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN2)) + { + m_currentCategoryIndex++; + if (m_currentCategoryIndex > m_startingCategoryIndex + 4) + m_currentCategoryIndex = m_startingCategoryIndex; + } + + if (currentCategoryIndex != m_currentCategoryIndex) + { + SoundManager.PlaySound("ShopBSMenuMove"); + + m_selectionIcon.Position = m_blacksmithUI.GetChildAt(m_currentCategoryIndex).AbsPosition; + for (int i = 1; i < 6; i++) + { + if (i == 1) + m_blacksmithUI.GetChildAt(i).Scale = new Vector2(1, 1); + else + m_blacksmithUI.GetChildAt(i).Scale = Vector2.Zero; + } + + if (m_currentCategoryIndex != m_startingCategoryIndex) + m_blacksmithUI.GetChildAt(m_currentCategoryIndex - 5).Scale = new Vector2(1, 1); + else + m_blacksmithUI.GetChildAt(m_currentCategoryIndex - 5).Scale = Vector2.Zero; + + DisplayCategory(m_currentCategoryIndex - m_startingCategoryIndex); + } + + // Player is stepping out of the category menu, effectively closing the blacksmith screen. + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + m_lockControls = true; + Tween.To(this, 0.2f, Linear.EaseNone, "delay", "0.5", "BackBufferOpacity", "0"); + EaseOutMenu(); + Tween.RunFunction(0.13f, typeof(SoundManager), "PlaySound", "ShopMenuClose"); + } + + // Player is stepping into the category, to select a specific piece of equipment to purchase or equip. + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + m_inCategoryMenu = false; + m_currentEquipmentIndex = 0; + m_selectionIcon.Position = m_activeIconArray[m_currentEquipmentIndex].AbsPosition; + byte state = Game.PlayerStats.GetBlueprintArray[CurrentCategoryIndex][m_currentEquipmentIndex]; + if (state == EquipmentState.FoundButNotSeen) + Game.PlayerStats.GetBlueprintArray[CurrentCategoryIndex][m_currentEquipmentIndex] = EquipmentState.FoundAndSeen; + UpdateNewIcons(); + UpdateIconSelectionText(); + SoundManager.PlaySound("ShopMenuConfirm"); + } + } + + private void EquipmentSelectionInput() + { + int storedEquipmentIndex = m_currentEquipmentIndex; + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + m_currentEquipmentIndex -= 5; + if (m_currentEquipmentIndex < 0) + m_currentEquipmentIndex += 15; + } + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN2)) + { + m_currentEquipmentIndex += 5; + if (m_currentEquipmentIndex > 14) + m_currentEquipmentIndex -= 15; + } + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT2)) + { + m_currentEquipmentIndex--; + if ((m_currentEquipmentIndex + 1) % 5 == 0) + m_currentEquipmentIndex += 5; + } + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT2)) + { + m_currentEquipmentIndex++; + if (m_currentEquipmentIndex % 5 == 0) + m_currentEquipmentIndex -= 5; + } + + if (storedEquipmentIndex != m_currentEquipmentIndex) + { + byte state = Game.PlayerStats.GetBlueprintArray[CurrentCategoryIndex][m_currentEquipmentIndex]; + if (state == EquipmentState.FoundButNotSeen) + Game.PlayerStats.GetBlueprintArray[CurrentCategoryIndex][m_currentEquipmentIndex] = EquipmentState.FoundAndSeen; + UpdateNewIcons(); + UpdateIconSelectionText(); + m_selectionIcon.Position = m_activeIconArray[m_currentEquipmentIndex].AbsPosition; + SoundManager.PlaySound("ShopBSMenuMove"); + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + SoundManager.PlaySound("ShopMenuCancel"); + m_inCategoryMenu = true; + m_selectionIcon.Position = m_blacksmithUI.GetChildAt(m_currentCategoryIndex).AbsPosition; + UpdateIconSelectionText(); + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + int equipmentCategory = m_currentCategoryIndex - m_startingCategoryIndex; + int purchasedState = Game.PlayerStats.GetBlueprintArray[equipmentCategory][m_currentEquipmentIndex]; + int equippedIndex = Game.PlayerStats.GetEquippedArray[equipmentCategory]; + + // Purchasing a previously locked piece of equipment. + if (purchasedState < EquipmentState.Purchased && purchasedState > EquipmentState.NotFound) + { + EquipmentData equipmentData = Game.EquipmentSystem.GetEquipmentData(equipmentCategory, m_currentEquipmentIndex); + if (Game.PlayerStats.Gold >= equipmentData.Cost) + { + SoundManager.PlaySound("ShopMenuUnlock"); + Game.PlayerStats.Gold -= equipmentData.Cost; + UpdateMoneyText(); // flibit added this, purchases didn't update display! + Game.PlayerStats.GetBlueprintArray[equipmentCategory][m_currentEquipmentIndex] = EquipmentState.Purchased; + + ObjContainer icon = m_masterIconArray[equipmentCategory][m_currentEquipmentIndex]; + icon.ChangeSprite("BlacksmithUI_" + EquipmentCategoryType.ToStringEN(equipmentCategory) + ((m_currentEquipmentIndex % 5) + 1).ToString() + "Icon_Character"); + + for (int j = 1; j < icon.NumChildren; j++) + icon.GetChildAt(j).Opacity = 1f; + + int colourIndex = 1; + if (equipmentCategory == EquipmentCategoryType.Sword) + colourIndex = 2; + + icon.GetChildAt(colourIndex).TextureColor = equipmentData.FirstColour; + + if (equipmentCategory != EquipmentCategoryType.Cape) + { + colourIndex++; + icon.GetChildAt(colourIndex).TextureColor = equipmentData.SecondColour; + } + + purchasedState = EquipmentState.Purchased; + UpdateIconSelectionText(); + } + else + SoundManager.PlaySound("ShopMenuUnlockFail"); + } + + // Changing the currently equipped equipment piece. + if (equippedIndex != m_currentEquipmentIndex && purchasedState == EquipmentState.Purchased) + { + EquipmentData equipmentData = Game.EquipmentSystem.GetEquipmentData(equipmentCategory, m_currentEquipmentIndex); + int currentEquippedItem = Game.PlayerStats.GetEquippedArray[equipmentCategory]; + int weightReduction = 0; + if (currentEquippedItem != -1) + weightReduction = Game.EquipmentSystem.GetEquipmentData(equipmentCategory, currentEquippedItem).Weight; + + if (equipmentData.Weight + Player.CurrentWeight - weightReduction <= Player.MaxWeight) + { + SoundManager.PlaySound("ShopBSEquip"); // this should be an equip sound. + + Game.PlayerStats.GetEquippedArray[equipmentCategory] = (sbyte)m_currentEquipmentIndex; + UpdateIconSelectionText(); + Vector3 playerPart = PlayerPart.GetPartIndices(equipmentCategory); + + if (playerPart.X != PlayerPart.None) + Player.GetChildAt((int)playerPart.X).TextureColor = equipmentData.FirstColour; + if (playerPart.Y != PlayerPart.None) + Player.GetChildAt((int)playerPart.Y).TextureColor = equipmentData.SecondColour; + if (playerPart.Z != PlayerPart.None) + Player.GetChildAt((int)playerPart.Z).TextureColor = equipmentData.SecondColour; + + // Special handling to tint the female's boobs. + if (equipmentCategory == EquipmentCategoryType.Chest && playerPart.X != PlayerPart.None) + Player.GetChildAt(PlayerPart.Boobs).TextureColor = equipmentData.FirstColour; + + UpdateNewIcons(); + } + else + Console.WriteLine("cannot equip. too heavy. Weight:" + (equipmentData.Weight + Player.CurrentWeight - weightReduction)); + } + else if (equippedIndex == m_currentEquipmentIndex) // Unequipping + { + Game.PlayerStats.GetEquippedArray[equipmentCategory] = -1; + Player.UpdateEquipmentColours(); + UpdateIconSelectionText(); + UpdateNewIcons(); + } + } + } + + private void UpdateIconSelectionText() + { + m_equipmentDescriptionText.Position = new Vector2(-1000, -1000); + m_textInfoTitleContainer.Visible = false; + m_textInfoStatContainer.Visible = false; + m_textInfoStatModContainer.Visible = false; + m_addPropertiesTitleText.Visible = false; + m_addPropertiesText.Visible = false; + m_unlockCostContainer.Visible = false; + m_equipmentTitleText.Visible = false; + + if (m_inCategoryMenu == true) + { + m_equipmentDescriptionText.Text = LocaleBuilder.getString("LOC_ID_BLACKSMITH_SCREEN_12", m_equipmentDescriptionText); + } + else + { + if (Game.PlayerStats.GetBlueprintArray[m_currentCategoryIndex - m_startingCategoryIndex][m_currentEquipmentIndex] == EquipmentState.NotFound) + { + m_equipmentDescriptionText.Position = new Vector2(230, -20); + m_equipmentDescriptionText.Text = LocaleBuilder.getString("LOC_ID_BLACKSMITH_SCREEN_13", m_equipmentDescriptionText); + } + else if (Game.PlayerStats.GetBlueprintArray[m_currentCategoryIndex - m_startingCategoryIndex][m_currentEquipmentIndex] < EquipmentState.Purchased) + { + m_equipmentDescriptionText.Text = LocaleBuilder.getString("LOC_ID_BLACKSMITH_SCREEN_14", m_equipmentDescriptionText); + (m_unlockCostContainer.GetChildAt(1) as TextObj).Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_BLACKSMITH_SCREEN_16_NEW"), Game.EquipmentSystem.GetEquipmentData(m_currentCategoryIndex - m_startingCategoryIndex, m_currentEquipmentIndex).Cost.ToString()); + //(m_unlockCostContainer.GetChildAt(1) as TextObj).Text = Game.EquipmentSystem.GetEquipmentData(m_currentCategoryIndex - m_startingCategoryIndex, m_currentEquipmentIndex).Cost.ToString() + " " + LocaleBuilder.getResourceString("LOC_ID_BLACKSMITH_SCREEN_16"); + + m_unlockCostContainer.Visible = true; + m_textInfoTitleContainer.Visible = true; + m_textInfoStatContainer.Visible = true; + m_textInfoStatModContainer.Visible = true; + m_addPropertiesTitleText.Visible = true; + m_addPropertiesText.Visible = true; + m_equipmentTitleText.Visible = true; + + m_textInfoTitleContainer.Opacity = 0.5f; + m_textInfoStatContainer.Opacity = 0.5f; + m_textInfoStatModContainer.Opacity = 0.5f; + m_addPropertiesTitleText.Opacity = 0.5f; + m_addPropertiesText.Opacity = 0.5f; + m_equipmentTitleText.Opacity = 0.5f; + + UpdateEquipmentDataText(); + } + else + { + // This code displays all the information for the stats. + m_textInfoTitleContainer.Visible = true; + m_textInfoStatContainer.Visible = true; + m_textInfoStatModContainer.Visible = true; + m_addPropertiesTitleText.Visible = true; + m_addPropertiesText.Visible = true; + m_equipmentTitleText.Visible = true; + + m_textInfoTitleContainer.Opacity = 1; + m_textInfoStatContainer.Opacity = 1; + m_textInfoStatModContainer.Opacity = 1; + m_addPropertiesTitleText.Opacity = 1; + m_addPropertiesText.Opacity = 1; + m_equipmentTitleText.Opacity = 1; + + UpdateEquipmentDataText(); + } + } + } + + // Updates the base player stats text and the bonus attribute text that a piece of equipment gives you. + private void UpdateEquipmentDataText() + { + (m_textInfoStatContainer.GetChildAt(0) as TextObj).Text = Player.MaxHealth.ToString(); + (m_textInfoStatContainer.GetChildAt(1) as TextObj).Text = Player.MaxMana.ToString(); + (m_textInfoStatContainer.GetChildAt(2) as TextObj).Text = Player.Damage.ToString(); + (m_textInfoStatContainer.GetChildAt(3) as TextObj).Text = Player.TotalMagicDamage.ToString(); + (m_textInfoStatContainer.GetChildAt(4) as TextObj).Text = Player.TotalArmor.ToString(); + (m_textInfoStatContainer.GetChildAt(5) as TextObj).Text = Player.CurrentWeight.ToString() + "/" + Player.MaxWeight.ToString(); + + int selectedCategoryIndex = m_currentCategoryIndex - m_startingCategoryIndex; + EquipmentData equipmentData = Game.EquipmentSystem.GetEquipmentData(selectedCategoryIndex, m_currentEquipmentIndex); + int currentEquippedIndex = Game.PlayerStats.GetEquippedArray[selectedCategoryIndex]; + EquipmentData currentEquipmentData = new EquipmentData(); + if (currentEquippedIndex > -1) + currentEquipmentData = Game.EquipmentSystem.GetEquipmentData(selectedCategoryIndex, currentEquippedIndex); + + //if (Game.PlayerStats.GetEquippedArray[m_currentCategoryIndex - m_startingCategoryIndex] != m_currentEquipmentIndex) + //{ + + bool isEquippedItem = Game.PlayerStats.GetEquippedArray[CurrentCategoryIndex] == m_currentEquipmentIndex; + + int bonusHealth = equipmentData.BonusHealth - currentEquipmentData.BonusHealth; + + // In case we want equipment to accurately reflect class multiplier effects. + //int bonusHealth = (int)Math.Round((equipmentData.BonusHealth - currentEquipmentData.BonusHealth) * Player.ClassTotalHPMultiplier, MidpointRounding.AwayFromZero); + + if (isEquippedItem == true) + bonusHealth = -equipmentData.BonusHealth; + TextObj textObj1 = m_textInfoStatModContainer.GetChildAt(0) as TextObj; + + if (bonusHealth > 0) + { + textObj1.TextureColor = Color.Cyan; + textObj1.Text = "+" + bonusHealth.ToString(); + } + else if (bonusHealth < 0) + { + textObj1.TextureColor = Color.Red; + textObj1.Text = bonusHealth.ToString(); + } + else + textObj1.Text = ""; + + TextObj textObj2 = m_textInfoStatModContainer.GetChildAt(1) as TextObj; + int bonusMana = equipmentData.BonusMana - currentEquipmentData.BonusMana; + if (isEquippedItem == true) + bonusMana = -equipmentData.BonusMana; + if (bonusMana > 0) + { + textObj2.TextureColor = Color.Cyan; + textObj2.Text = "+" + bonusMana.ToString(); + } + else if (bonusMana < 0) + { + textObj2.TextureColor = Color.Red; + textObj2.Text = bonusMana.ToString(); + } + else + textObj2.Text = ""; + + TextObj textObj3 = m_textInfoStatModContainer.GetChildAt(2) as TextObj; + int bonusDamage = equipmentData.BonusDamage - currentEquipmentData.BonusDamage; + if (isEquippedItem == true) + bonusDamage = -equipmentData.BonusDamage; + if (bonusDamage > 0) + { + textObj3.TextureColor = Color.Cyan; + textObj3.Text = "+" + bonusDamage.ToString(); + } + else if (bonusDamage < 0) + { + textObj3.TextureColor = Color.Red; + textObj3.Text = bonusDamage.ToString(); + } + else + textObj3.Text = ""; + + TextObj textObj4 = m_textInfoStatModContainer.GetChildAt(3) as TextObj; + int bonusMagic = equipmentData.BonusMagic - currentEquipmentData.BonusMagic; + if (isEquippedItem == true) + bonusMagic = -equipmentData.BonusMagic; + if (bonusMagic > 0) + { + textObj4.TextureColor = Color.Cyan; + textObj4.Text = "+" + bonusMagic.ToString(); + } + else if (bonusMagic < 0) + { + textObj4.TextureColor = Color.Red; + textObj4.Text = bonusMagic.ToString(); + } + else + textObj4.Text = ""; + + TextObj textObj5 = m_textInfoStatModContainer.GetChildAt(4) as TextObj; + int bonusArmor = equipmentData.BonusArmor - currentEquipmentData.BonusArmor; + if (isEquippedItem == true) + bonusArmor = -equipmentData.BonusArmor; + if (bonusArmor > 0) + { + textObj5.TextureColor = Color.Cyan; + textObj5.Text = "+" + bonusArmor.ToString(); + } + else if (bonusArmor < 0) + { + textObj5.TextureColor = Color.Red; + textObj5.Text = bonusArmor.ToString(); + } + else + textObj5.Text = ""; + + TextObj textObj6 = m_textInfoStatModContainer.GetChildAt(5) as TextObj; + int weight = equipmentData.Weight - currentEquipmentData.Weight; + if (isEquippedItem == true) + weight = -equipmentData.Weight; + if (weight > 0) + { + textObj6.TextureColor = Color.Red; + textObj6.Text = "+" + weight.ToString(); + } + else if (weight < 0) + { + textObj6.TextureColor = Color.Cyan; + textObj6.Text = weight.ToString(); + } + else + textObj6.Text = ""; + //} + //else + //{ + // for (int i = 0; i < 5; i++) + // (m_textInfoStatModContainer.GetChildAt(i) as TextObj).Text = ""; + //} + + Vector2[] specialAttributeArray = equipmentData.SecondaryAttribute; + m_addPropertiesText.Text = ""; + if (specialAttributeArray != null) + { + foreach (Vector2 attrib in specialAttributeArray) + { + if (attrib.X != 0) + { + if (attrib.X < 7) // Temp hack to get stats displaying percentages properly. + m_addPropertiesText.Text += "+" + (attrib.Y * 100).ToString() + "% " + LocaleBuilder.getResourceString(EquipmentSecondaryDataType.ToStringID((int)attrib.X)) + "\n"; + else + m_addPropertiesText.Text += "+" + attrib.Y.ToString() + " " + LocaleBuilder.getResourceString(EquipmentSecondaryDataType.ToStringID((int)attrib.X)) + "\n"; + } + } + if (specialAttributeArray.Length == 0) + m_addPropertiesText.Text = LocaleBuilder.getResourceString("LOC_ID_BLACKSMITH_SCREEN_15"); // "None" + } + else + m_addPropertiesText.Text = LocaleBuilder.getResourceString("LOC_ID_BLACKSMITH_SCREEN_15"); // "None" + + //m_equipmentTitleText.Text = LocaleBuilder.getResourceString(EquipmentBaseType.ToStringID(m_currentEquipmentIndex)) + " " + LocaleBuilder.getResourceString(EquipmentCategoryType.ToStringID(selectedCategoryIndex)); + m_equipmentTitleText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_BASE_FORMAT", true), LocaleBuilder.getResourceString(EquipmentBaseType.ToStringID(m_currentEquipmentIndex), true), LocaleBuilder.getResourceString(EquipmentCategoryType.ToStringID(selectedCategoryIndex), true)); + } + + private void UpdateMoneyText() + { + m_playerMoney.Text = Game.PlayerStats.Gold.ToString(); + ProceduralLevelScreen level = Game.ScreenManager.GetLevelScreen(); + if (level != null) + level.UpdatePlayerHUD(); + } + + public override void Draw(GameTime gameTime) + { + Camera.Begin(); + Camera.Draw(Game.GenericTexture, new Rectangle(0, 0, 1320, 720), Color.Black * BackBufferOpacity); + m_blacksmithUI.Draw(Camera); + m_selectionIcon.Draw(Camera); + + //m_textInfoContainer.DrawOutline(Camera, 2); + m_textInfoTitleContainer.Draw(Camera); + m_textInfoStatContainer.Draw(Camera); + m_textInfoStatModContainer.Draw(Camera); + m_addPropertiesTitleText.Draw(Camera); + m_addPropertiesText.Draw(Camera); + m_unlockCostContainer.Draw(Camera); + m_equipmentTitleText.Draw(Camera); + + foreach (ObjContainer[] iconArray in m_masterIconArray) + { + for (int i = 0; i < iconArray.Length; i++) + iconArray[i].Draw(Camera); + } + + m_navigationText.Draw(Camera); + m_cancelText.Draw(Camera); + m_confirmText.Draw(Camera); + + m_equippedIcon.Draw(Camera); + + foreach (SpriteObj icon in m_newIconList) + icon.Draw(Camera); + + Camera.End(); + base.Draw(gameTime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Blacksmith Screen"); + + if (m_rainSound != null) + m_rainSound.Dispose(); + m_rainSound = null; + + m_blacksmithUI.Dispose(); + m_blacksmithUI = null; + m_equipmentDescriptionText.Dispose(); + m_equipmentDescriptionText = null; + m_selectionIcon.Dispose(); + m_selectionIcon = null; + m_equipmentTitleText.Dispose(); + m_equipmentTitleText = null; + + m_activeIconArray = null; + + foreach (ObjContainer[] iconArray in m_masterIconArray) + { + for (int i = 0; i < iconArray.Length; i++) + { + iconArray[i].Dispose(); + iconArray[i] = null; + } + Array.Clear(iconArray, 0, iconArray.Length); + } + m_masterIconArray.Clear(); + m_masterIconArray = null; + + m_textInfoStatContainer.Dispose(); + m_textInfoStatContainer = null; + m_textInfoTitleContainer.Dispose(); + m_textInfoTitleContainer = null; + m_textInfoStatModContainer.Dispose(); + m_textInfoStatModContainer = null; + m_unlockCostContainer.Dispose(); + m_unlockCostContainer = null; + m_addPropertiesText.Dispose(); + m_addPropertiesText = null; + m_addPropertiesTitleText.Dispose(); + m_addPropertiesTitleText = null; + m_equippedIcon.Dispose(); + m_equippedIcon = null; + Player = null; + + m_confirmText.Dispose(); + m_confirmText = null; + m_cancelText.Dispose(); + m_cancelText = null; + m_navigationText.Dispose(); + m_navigationText = null; + + m_playerMoney = null; + foreach (SpriteObj sprite in m_newIconList) + sprite.Dispose(); + m_newIconList.Clear(); + m_newIconList = null; + + base.Dispose(); + } + } + + private int CurrentCategoryIndex + { + get { return m_currentCategoryIndex - m_startingCategoryIndex; } + } + + public override void RefreshTextObjs() + { + /* + m_confirmText.Text = "[Input:" + InputMapType.MENU_CONFIRM1 + "] " + LocaleBuilder.getResourceString("LOC_ID_BLACKSMITH_SCREEN_8"); + m_cancelText.Text = "[Input:" + InputMapType.MENU_CANCEL1 + "] " + LocaleBuilder.getResourceString("LOC_ID_BLACKSMITH_SCREEN_9"); + + if (InputManager.GamePadIsConnected(PlayerIndex.One) == false) + m_navigationText.Text = LocaleBuilder.getResourceString("LOC_ID_BLACKSMITH_SCREEN_10"); + else + m_navigationText.Text = "[Button:LeftStick] " + LocaleBuilder.getResourceString("LOC_ID_BLACKSMITH_SCREEN_11"); + */ + + m_addPropertiesTitleText.ScaleX = 1; + (m_unlockCostContainer.GetChildAt(1) as TextObj).ScaleX = 1; + switch(LocaleBuilder.languageType) + { + case(LanguageType.French): + (m_unlockCostContainer.GetChildAt(1) as TextObj).ScaleX = 0.9f; + m_addPropertiesTitleText.ScaleX = 0.9f; + break; + case(LanguageType.Spanish_Spain): + case(LanguageType.German): + case(LanguageType.Polish): + (m_unlockCostContainer.GetChildAt(1) as TextObj).ScaleX = 0.9f; + break; + } + + Game.ChangeBitmapLanguage(m_blacksmithUI.GetChildAt(m_blacksmithUI.NumChildren - 4) as SpriteObj, "BlacksmithUI_Title_Sprite"); + foreach (SpriteObj icon in m_newIconList) + Game.ChangeBitmapLanguage(icon, "BlacksmithUI_NewIcon_Sprite"); + + UpdateIconSelectionText(); + UpdateEquipmentDataText(); + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Screens/BlitWorksSplashScreen.cs b/RogueCastle/src/Screens/BlitWorksSplashScreen.cs new file mode 100644 index 0000000..753f295 --- /dev/null +++ b/RogueCastle/src/Screens/BlitWorksSplashScreen.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using Microsoft.Xna.Framework.Audio; + +namespace RogueCastle +{ + public class BlitWorksSplashScreen : Screen + { + private SpriteObj m_logo; + private SpriteObj m_logoIcon; + private SoundEffect m_blitSFX; + + public override void LoadContent() + { + m_logo = new SpriteObj("Blitworks_FullLogo"); + m_logo.Position = new Vector2(GlobalEV.ScreenWidth / 2, GlobalEV.ScreenHeight / 2); + m_logo.ForceDraw = true; + + m_logoIcon = new SpriteObj("Blitworks_IconOnly"); + m_logoIcon.Position = new Vector2(GlobalEV.ScreenWidth / 2, GlobalEV.ScreenHeight / 2 - (40 * m_logo.ScaleX)); + m_logoIcon.ForceDraw = true; + + m_blitSFX = ScreenManager.Game.Content.Load("Audio/sfx_blitworks_logo"); + + base.LoadContent(); + } + + public override void OnEnter() + { + m_logo.Opacity = 0; + m_logoIcon.Opacity = 0; + + Tween.RunFunction(0.5f, this, "PlayBlitSplash"); + base.OnEnter(); + } + + public void PlayBlitSplash() + { + m_blitSFX.Play(0.25f, 0, 0); + m_logoIcon.Opacity = 1; + Tween.To(m_logo, 0.25f, Tween.EaseNone, "Opacity", "1"); + Tween.To(m_logoIcon, 0.5f, Tween.EaseNone, "Opacity", "0", "ScaleX", "2", "ScaleY", "2"); + m_logo.Opacity = 1; + Tween.To(m_logo, 0.25f, Tween.EaseNone, "delay", "2.5", "Opacity", "0"); + m_logo.Opacity = 0; + Tween.AddEndHandlerToLastTween(this, "LoadNextScreen"); + } + + public void LoadNextScreen() + { + if ((ScreenManager.Game as Game).SaveManager.FileExists(SaveType.PlayerData)) + { + //try + //{ + (ScreenManager.Game as Game).SaveManager.LoadFiles(null, SaveType.PlayerData); + + if (Game.PlayerStats.ShoulderPiece < 1 || Game.PlayerStats.HeadPiece < 1 || Game.PlayerStats.ChestPiece < 1) + Game.PlayerStats.TutorialComplete = false; + else + { + if (Game.PlayerStats.TutorialComplete == false) + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.TutorialRoom, true, null); + else + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Title, true, null); + } + //} + //catch + //{ + // Console.WriteLine(" Could not load Player data."); + // Game.PlayerStats.TutorialComplete = false; + //} + } + else + { + if (Game.PlayerStats.TutorialComplete == false) + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.TutorialRoom, true, null); + else + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Title, true, null); + } + } + + public override void Update(GameTime gameTime) + { + base.Update(gameTime); + } + + public override void Draw(GameTime gameTime) + { + Camera.GraphicsDevice.Clear(Color.Black); + Camera.Begin(); + m_logo.Draw(Camera); + m_logoIcon.Draw(Camera); + Camera.End(); + base.Draw(gameTime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Blitworks Splash Screen"); + + m_logo.Dispose(); + m_logo = null; + m_logoIcon.Dispose(); + m_logoIcon = null; + m_blitSFX.Dispose(); + m_blitSFX = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Screens/CDGSplashScreen.cs b/RogueCastle/src/Screens/CDGSplashScreen.cs new file mode 100644 index 0000000..0553523 --- /dev/null +++ b/RogueCastle/src/Screens/CDGSplashScreen.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using System.Threading; + +namespace RogueCastle +{ + public class CDGSplashScreen : Screen + { + private SpriteObj m_logo; + private TextObj m_loadingText; + private bool m_levelDataLoaded = false; + private bool m_fadingOut = false; + private float m_totalElapsedTime = 0; + + public override void LoadContent() + { + m_logo = new SpriteObj("CDGLogo_Sprite"); + m_logo.Position = new Vector2(1320 / 2, 720 / 2); + m_logo.Rotation = 90; + m_logo.ForceDraw = true; + + m_loadingText = new TextObj(Game.JunicodeFont); + m_loadingText.FontSize = 18; + m_loadingText.Align = Types.TextAlign.Right; + m_loadingText.Text = LocaleBuilder.getString("LOC_ID_SPLASH_SCREEN_1", m_loadingText); + m_loadingText.TextureColor = new Color(100, 100, 100); + m_loadingText.Position = new Vector2(1320 - 40, 720 - 90); + m_loadingText.ForceDraw = true; + m_loadingText.Opacity = 0; + base.LoadContent(); + } + + public override void OnEnter() + { + // Level data loading is multithreaded. + m_levelDataLoaded = false; + m_fadingOut = false; + Thread loadingThread = new Thread(LoadLevelData); + loadingThread.Start(); + + m_logo.Opacity = 0; + Tween.To(m_logo, 1, Linear.EaseNone, "delay", "0.5", "Opacity", "1"); + Tween.RunFunction(0.75f, typeof(SoundManager), "PlaySound", "CDGSplashCreak"); + //Tween.AddEndHandlerToLastTween(typeof(SoundManager), "PlaySound", "CDGSplashCreak"); + base.OnEnter(); + } + + private void LoadLevelData() + { + lock (this) + { + LevelBuilder2.Initialize(); + LevelParser.ParseRooms("Map_1x1", ScreenManager.Game.Content); + LevelParser.ParseRooms("Map_1x2", ScreenManager.Game.Content); + LevelParser.ParseRooms("Map_1x3", ScreenManager.Game.Content); + LevelParser.ParseRooms("Map_2x1", ScreenManager.Game.Content); + LevelParser.ParseRooms("Map_2x2", ScreenManager.Game.Content); + LevelParser.ParseRooms("Map_2x3", ScreenManager.Game.Content); + LevelParser.ParseRooms("Map_3x1", ScreenManager.Game.Content); + LevelParser.ParseRooms("Map_3x2", ScreenManager.Game.Content); + LevelParser.ParseRooms("Map_Special", ScreenManager.Game.Content); + LevelParser.ParseRooms("Map_DLC1", ScreenManager.Game.Content, true); + LevelBuilder2.IndexRoomList(); + m_levelDataLoaded = true; + } + } + + public void LoadNextScreen() + { + if (LevelEV.ENABLE_BLITWORKS_SPLASH == true) + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.BlitWorks, true, null); + else + { + if ((ScreenManager.Game as Game).SaveManager.FileExists(SaveType.PlayerData)) + { + //try + //{ + (ScreenManager.Game as Game).SaveManager.LoadFiles(null, SaveType.PlayerData); + + if (Game.PlayerStats.ShoulderPiece < 1 || Game.PlayerStats.HeadPiece < 1 || Game.PlayerStats.ChestPiece < 1) + Game.PlayerStats.TutorialComplete = false; + else + { + if (Game.PlayerStats.TutorialComplete == false) + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.TutorialRoom, true, null); + else + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Title, true, null); + } + //} + //catch + //{ + // Console.WriteLine(" Could not load Player data."); + // Game.PlayerStats.TutorialComplete = false; + //} + } + else + { + if (Game.PlayerStats.TutorialComplete == false) + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.TutorialRoom, true, null); + else + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Title, true, null); + } + } + } + + public override void Update(GameTime gameTime) + { + if (m_levelDataLoaded == false && m_logo.Opacity == 1) + { + float opacity = (float)Math.Abs(Math.Sin(m_totalElapsedTime)); + m_totalElapsedTime += (float)gameTime.ElapsedGameTime.TotalSeconds; + m_loadingText.Opacity = opacity; + } + + if (m_levelDataLoaded == true && m_fadingOut == false) + { + m_fadingOut = true; + float logoOpacity = m_logo.Opacity; + m_logo.Opacity = 1; + Tween.To(m_logo, 1, Linear.EaseNone, "delay", "1.5", "Opacity", "0"); + Tween.AddEndHandlerToLastTween(this, "LoadNextScreen"); + Tween.To(m_loadingText, 0.5f, Tween.EaseNone, "Opacity", "0"); + m_logo.Opacity = logoOpacity; + } + + base.Update(gameTime); + } + + public override void Draw(GameTime gameTime) + { + Camera.GraphicsDevice.Clear(Color.Black); + Camera.Begin(); + m_logo.Draw(Camera); + m_loadingText.Draw(Camera); + Camera.End(); + base.Draw(gameTime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing CDG Splash Screen"); + + m_logo.Dispose(); + m_logo = null; + m_loadingText.Dispose(); + m_loadingText = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Screens/CreditsScreen.cs b/RogueCastle/src/Screens/CreditsScreen.cs new file mode 100644 index 0000000..e9b7b62 --- /dev/null +++ b/RogueCastle/src/Screens/CreditsScreen.cs @@ -0,0 +1,1437 @@ +//#define XBOX_CREDITS +//#define PLAYSTATION_CREDITS +//#define SWITCH_CREDITS + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class CreditsScreen : Screen + { + private const float m_scrollDuration = 75; + private bool m_allowExit; + public bool IsEnding; + + private List m_creditsNameList; + private List m_creditsTitleList; + + private SpriteObj m_bg1, m_bg2, m_bg3, m_bgOutside; + private SpriteObj m_ground1, m_ground2, m_ground3; + private SpriteObj m_border1, m_border2, m_border3; + private SpriteObj m_prop1; + private ObjContainer m_prop2, m_prop3; + + private ObjContainer m_playerSprite; + private ObjContainer m_wifeSprite; + private ObjContainer m_childSprite1, m_childSprite2; + private int m_wifeChest, m_wifeShoulders, m_wifeHead; + private int m_child1Chest, m_child1Shoulders, m_child1Head; + private int m_child2Chest, m_child2Shoulders, m_child2Head; + + private SpriteObj m_sideBorderLeft; + private SpriteObj m_sideBorderRight; + private SpriteObj m_sideBorderTop; + private SpriteObj m_sideBorderBottom; + + private ObjContainer m_manor; + private string[] m_backgroundStrings; + private int m_backgroundIndex = 0; + + private float m_backgroundSwapTimer; + + private TextObj m_thanksForPlayingText; + private TextObj m_totalPlayTime; + private TextObj m_totalDeaths; + + private SkyObj m_sky; + private RenderTarget2D m_skyRenderTarget; + private RenderTarget2D m_backgroundRenderTarget; + + private KeyIconTextObj m_continueText; + private bool m_displayingContinueText; + float m_scrollDistance = 0; + + private SpriteObj m_glauber; + private SpriteObj m_teddy; + private SpriteObj m_kenny; + private SpriteObj m_gordon; + private SpriteObj m_judson; + private SpriteObj m_mc; + + private Color m_skinColour1 = new Color(231, 175, 131, 255); + private Color m_skinColour2 = new Color(199, 109, 112, 255); + private Color m_lichColour1 = new Color(255, 255, 255, 255); + private Color m_lichColour2 = new Color(198, 198, 198, 255); + + public override void LoadContent() + { + m_bgOutside = new SpriteObj("TraitsBG_Sprite"); + m_bgOutside.ForceDraw = true; + m_bgOutside.Visible = false; + m_bgOutside.Scale = new Vector2(1320f / m_bgOutside.Width, 1320f / m_bgOutside.Width); + + m_bg1 = new SpriteObj("CastleBG1_Sprite"); + m_bg1.Position = new Vector2(1320 / 2f, 200); + m_bg1.Scale = new Vector2(2, 2); + m_bg2 = m_bg1.Clone() as SpriteObj; + m_bg2.X -= m_bg1.Width; + m_bg3 = m_bg2.Clone() as SpriteObj; + m_bg3.X -= m_bg2.Width; + + m_ground1 = new SpriteObj("CastleFG1_Sprite"); + m_ground1.Position = new Vector2(1320 / 2f, 440); + m_ground1.Scale = new Vector2(2, 2); + m_ground2 = m_ground1.Clone() as SpriteObj; + m_ground2.X -= m_ground1.Width; + m_ground3 = m_ground2.Clone() as SpriteObj; + m_ground3.X -= m_ground2.Width; + + m_border1 = new SpriteObj("CastleBorder_Sprite"); // TowerBorder2_Sprite + m_border1.Position = new Vector2(1320 / 2f, 440); + m_border1.Scale = new Vector2(2, 2); + m_border2 = m_border1.Clone() as SpriteObj; + m_border2.X -= m_border1.Width; + m_border3 = m_border2.Clone() as SpriteObj; + m_border3.X -= m_border2.Width; + + m_prop1 = new SpriteObj("CastleAssetWindow1_Sprite"); + m_prop1.Position = new Vector2(0, 220); + m_prop1.Scale = new Vector2(2, 2); + m_prop2 = new ObjContainer("CastleAssetBackTorch_Character"); + m_prop2.Position = new Vector2(500, 330); + m_prop2.Scale = new Vector2(2, 2); + m_prop2.AnimationDelay = 1 / 10f; + m_prop2.PlayAnimation(true); + m_prop3 = new ObjContainer("CastleAssetCandle1_Character"); + m_prop3.Position = new Vector2(1000, 440); + m_prop3.Scale = new Vector2(2, 2); + + m_playerSprite = new ObjContainer("PlayerWalking_Character"); + m_playerSprite.Position = new Vector2(1320 / 2f - 20, 400); + m_playerSprite.PlayAnimation(true); + m_playerSprite.AnimationDelay = 1 / 10f; + m_playerSprite.Flip = SpriteEffects.FlipHorizontally; + m_playerSprite.OutlineWidth = 2; + + Color darkPink = new Color(251, 156, 172); + m_wifeSprite = new ObjContainer("PlayerWalking_Character"); + m_wifeSprite.Position = new Vector2(-200, 400); + m_wifeSprite.PlayAnimation(true); + m_wifeSprite.AnimationDelay = 1 / 10f; + m_wifeSprite.OutlineWidth = 2; + m_wifeSprite.Scale = new Vector2(2, 2); + m_wifeSprite.GetChildAt(PlayerPart.Bowtie).TextureColor = darkPink; + m_wifeSprite.GetChildAt(PlayerPart.Hair).TextureColor = Color.Red; + m_wifeSprite.GetChildAt(PlayerPart.Cape).TextureColor = Color.Red; + m_wifeSprite.GetChildAt(PlayerPart.Neck).TextureColor = Color.Red; + m_wifeSprite.GetChildAt(PlayerPart.Sword2).TextureColor = new Color(11, 172, 239); + + m_childSprite1 = new ObjContainer("PlayerWalking_Character"); + m_childSprite1.Position = new Vector2(-270, 415); + m_childSprite1.PlayAnimation(true); + m_childSprite1.AnimationDelay = 1 / 10f; + m_childSprite1.OutlineWidth = 2; + m_childSprite1.Scale = new Vector2(1.2f, 1.2f); + m_childSprite1.GetChildAt(PlayerPart.Bowtie).TextureColor = darkPink; + m_childSprite1.GetChildAt(PlayerPart.Hair).TextureColor = Color.Red; + m_childSprite1.GetChildAt(PlayerPart.Cape).TextureColor = Color.Red; + m_childSprite1.GetChildAt(PlayerPart.Neck).TextureColor = Color.Red; + m_childSprite1.GetChildAt(PlayerPart.Sword2).TextureColor = new Color(11, 172, 239); + + m_childSprite2 = new ObjContainer("PlayerWalking_Character"); + m_childSprite2.Position = new Vector2(-330, 420); + m_childSprite2.PlayAnimation(true); + m_childSprite2.AnimationDelay = 1 / 10f; + m_childSprite2.OutlineWidth = 2; + m_childSprite2.Scale = new Vector2(1, 1); + m_childSprite2.GetChildAt(PlayerPart.Bowtie).TextureColor = darkPink; + m_childSprite2.GetChildAt(PlayerPart.Hair).TextureColor = Color.Red; + m_childSprite2.GetChildAt(PlayerPart.Cape).TextureColor = Color.Red; + m_childSprite2.GetChildAt(PlayerPart.Neck).TextureColor = Color.Red; + m_childSprite2.GetChildAt(PlayerPart.Sword2).TextureColor = new Color(11, 172, 239); + + m_sideBorderLeft = new SpriteObj("Blank_Sprite"); + m_sideBorderLeft.Scale = new Vector2(900f / m_sideBorderLeft.Width, 500f / m_sideBorderLeft.Height); + m_sideBorderLeft.Position = new Vector2(-450, 0); + m_sideBorderLeft.TextureColor = Color.Black; + m_sideBorderLeft.ForceDraw = true; + m_sideBorderRight = m_sideBorderLeft.Clone() as SpriteObj; + m_sideBorderRight.Position = new Vector2(850, 0); + m_sideBorderTop = m_sideBorderLeft.Clone() as SpriteObj; + m_sideBorderTop.Scale = new Vector2(1,1); + m_sideBorderTop.Scale = new Vector2(1320f/ m_sideBorderTop.Width, 240/m_sideBorderTop.Height); + m_sideBorderTop.Position = Vector2.Zero; + m_sideBorderBottom= m_sideBorderLeft.Clone() as SpriteObj; + m_sideBorderBottom.Scale = new Vector2(1,1); + m_sideBorderBottom.Scale = new Vector2(1340f / m_sideBorderBottom.Width, 720f / m_sideBorderBottom.Height); + m_sideBorderBottom.Position = new Vector2(0, 460); + + m_manor = new ObjContainer("TraitsCastle_Character"); + m_manor.Scale = new Vector2(2, 2); + m_manor.Visible = false; + + for (int i = 0; i < m_manor.NumChildren; i++) + { + m_manor.GetChildAt(i).Visible = false; + } + + foreach (SkillObj skill in SkillSystem.SkillArray) + { + if (skill.CurrentLevel > 0) + m_manor.GetChildAt(SkillSystem.GetManorPiece(skill)).Visible = true; + } + + m_thanksForPlayingText = new TextObj(Game.JunicodeLargeFont); + m_thanksForPlayingText.FontSize = 32; + m_thanksForPlayingText.Align = Types.TextAlign.Centre; + m_thanksForPlayingText.Text = LocaleBuilder.getString("LOC_ID_CREDITS_SCREEN_1", m_thanksForPlayingText); //"Thanks for playing!" + //m_thanksForPlayingText.OutlineWidth = 2; + m_thanksForPlayingText.DropShadow = new Vector2(2, 2); + m_thanksForPlayingText.Position = new Vector2(1320 / 2f, 480); + m_thanksForPlayingText.Opacity = 0; + + m_totalDeaths = m_thanksForPlayingText.Clone() as TextObj; + m_totalDeaths.FontSize = 20; + m_totalDeaths.Position = m_thanksForPlayingText.Position; + m_totalDeaths.Y += 90; + m_totalDeaths.Opacity = 0; + m_totalDeaths.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_totalDeaths); // dummy locID to add TextObj to language refresh list + m_totalPlayTime = m_thanksForPlayingText.Clone() as TextObj; + m_totalPlayTime.FontSize = 20; + m_totalPlayTime.Position = m_totalDeaths.Position; + m_totalPlayTime.Y += 50; + m_totalPlayTime.Opacity = 0; + m_totalPlayTime.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_totalPlayTime); // dummy locID to add TextObj to language refresh list + + m_continueText = new KeyIconTextObj(Game.JunicodeFont); + m_continueText.FontSize = 14; + m_continueText.Align = Types.TextAlign.Right; + m_continueText.Position = new Vector2(1320 - 50, 650); + m_continueText.ForceDraw = true; + m_continueText.Opacity = 0; + m_continueText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_continueText); // dummy locID to add TextObj to language refresh list + + int teamXPos = 200; + Vector2 teamScale = new Vector2(1.5f, 1.5f); + m_glauber = new SpriteObj("Glauber_Sprite"); + m_glauber.Scale = teamScale; + m_glauber.ForceDraw = true; + m_glauber.OutlineWidth = 2; + m_glauber.X = teamXPos; + m_teddy = new SpriteObj("Teddy_Sprite"); + m_teddy.Scale = teamScale; + m_teddy.ForceDraw = true; + m_teddy.OutlineWidth = 2; + m_teddy.X = teamXPos; + m_kenny = new SpriteObj("Kenny_Sprite"); + m_kenny.Scale = teamScale; + m_kenny.ForceDraw = true; + m_kenny.OutlineWidth = 2; + m_kenny.X = teamXPos; + m_gordon = new SpriteObj("Gordon_Sprite"); + m_gordon.Scale = teamScale; + m_gordon.ForceDraw = true; + m_gordon.OutlineWidth = 2; + m_gordon.X = teamXPos; + m_judson = new SpriteObj("Judson_Sprite"); + m_judson.Scale = teamScale; + m_judson.ForceDraw = true; + m_judson.OutlineWidth = 2; + m_judson.X = teamXPos; + m_mc = new SpriteObj("MC_Sprite"); + m_mc.Scale = teamScale; + m_mc.ForceDraw = true; + m_mc.OutlineWidth = 2; + m_mc.X = teamXPos; + + InitializeCredits(); + + base.LoadContent(); + } + + public override void ReinitializeRTs() + { + m_sky.ReinitializeRT(Camera); + m_skyRenderTarget = new RenderTarget2D(Camera.GraphicsDevice, 1320, 720, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + m_backgroundRenderTarget = new RenderTarget2D(Camera.GraphicsDevice, 1320, 720, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + base.ReinitializeRTs(); + } + + private void InitializeCredits() + { + m_creditsNameList = new List(); + m_creditsTitleList = new List(); + + m_backgroundStrings = new string[] { "Garden", "Tower", "Dungeon", "Outside", "Manor" }; + + string[] creditsNames = null; + creditsNames = new string[] + { + "[@LOC_ID_CREDITS_SCREEN_6" /*"Developed By"*/, "Cellar Door Games", + "", "", + "[@LOC_ID_CREDITS_SCREEN_7" /*"Design & Story"*/, "Teddy Lee", + "", "", + "[@LOC_ID_CREDITS_SCREEN_8" /*"Programming"*/, "Kenny Lee", + "", "", +#if SWITCH_CREDITS + "[@LOC_ID_CREDITS_SCREEN_9" /*"Production"*/, "Ryan Lee", +#else + "[@LOC_ID_CREDITS_SCREEN_9" /*"Production"*/, "Marie-Christine Bourdua", +#endif + "", "", + "[@LOC_ID_CREDITS_SCREEN_10" /*"Art"*/, "Glauber Kotaki", + "", "", + "[@LOC_ID_CREDITS_SCREEN_11" /*"Music & Audio Design"*/, "Gordon McGladdery (A Shell in the Pit)", + "", "", + "[@LOC_ID_CREDITS_SCREEN_12" /*"Music"*/, "Judson Cowan (Tettix)", + "", "", + "[@LOC_ID_CREDITS_SCREEN_13" /*"Marketing & Story"*/, "Benny Lee", + "", "", + "[@LOC_ID_CREDITS_SCREEN_25" /*"Additional Programming"*/, "David Man", + "", "", + + "[@LOC_ID_CREDITS_SCREEN_14" /*"Additional Audio Design"*/,"Alessio Mellina", + "","", + "[@LOC_ID_CREDITS_SCREEN_15" /*"Additional Background Art"*/, "John Won", + "","", +#if SWITCH_CREDITS + "[@LOC_ID_CREDITS_SCREEN_16" /*"Business Support"*/, "Michelle Lee", +#else + "[@LOC_ID_CREDITS_SCREEN_16" /*"Business Support"*/, "Ryan & Michelle Lee", +#endif + "","", + "[@LOC_ID_CREDITS_SCREEN_17" /*"Super Special Thanks: Turbo Edition"*/, "Jenny Lee", + "","", + "[@LOC_ID_CREDITS_SCREEN_18" /*"Special Thanks"*/, "Amber Campbell (Phedran), Amir Rao, Blair Hurm Cowan, Caitlin Groves", "Doug Culp, Eric Lee Lewis, Nathan Vella, Priscila Garcia, Rima Singh", "Scott Barcik, Stephen Goldstein, Tyler Mayes, Will Turnbull", "John 'Duke' Wain", + "","", + "[@LOC_ID_CREDITS_SCREEN_19" /*"Additional Thanks"*/, "Jake Hirshey, Joshua Hornsby, Mark Wallace", "Peter Lee, Sean Fleming", +#if XBOX_CREDITS || PLAYSTATION_CREDITS + "","", + "","", + "","", + "[@LOC_ID_CREDITS_SCREEN_26",/*"Adaptation by"*/ "Abstraction Games", + "","", + "Ralph Egas", + "Erik Bastianen", + "Wilco Schroo", + "Coen Campman", + "Adrian Francis", + "Rutger Janssen", + "Jorge Lorenzon", + "Frédéric Schertenleib", + "Tj'ièn Twijnstra", + "","", + "","", + "","", + "[@LOC_ID_CREDITS_QA", "Testronic Labs", +#endif +#if SWITCH_CREDITS + "","", + "","", + "","", + "[@LOC_ID_CREDITS_SCREEN_26",/*"Adaptation by"*/ "BlitWorks SL", + "","", + "Tony Cabello", + "Oscar Serrano", + "Guillermo NWDD", + "Julio Garcia", + "Daniel Lancha", + "Javier Moya", + "Miguel Pascual", + "","", + "","", + "","", + "[@LOC_ID_CREDITS_QA", "Lollipop Robot", + "","", + "Pablo Granada", + "Luis Moyano", + "Oscar Navalon", + "Francesc Sanchez", + "Daniel Segarra", +#endif +#if !XBOX_CREDITS && !PLAYSTATION_CREDITS && !SWITCH_CREDITS + "","", + "","", + "","", + "[@LOC_ID_CREDITS_SCREEN_20" /*"Mac/Linux Adaptation by"*/, "Ethan 'flibitijibibo' Lee", + "","", + "[@LOC_ID_CREDITS_SCREEN_21" /*"Mac/Linux QA Team"*/, "David Gow, Forrest Loomis,", "Jorgen Tjerno, Marcus Moller, Matthias Niess, ", "Stanislaw Gackowski, Stefano Angeleri", +#endif + "","", + "","", + "","", + "[@LOC_ID_CREDITS_SCREEN_23" /*"Primary Localization by"*/, "Babel Media", + "","", + "[@LOC_ID_CREDITS_SCREEN_24" /*"Chinese & Add'l Localization by"*/, "Universally Speaking", + "Tobias Gut (" + LocaleBuilder.getResourceString("LOC_ID_OPTIONS_LANGUAGE_GERMAN") + ")", + "Virtualname (" + LocaleBuilder.getResourceString("LOC_ID_OPTIONS_LANGUAGE_CHINESE") + ")", +#if XBOX_CREDITS + "","", + "","", + "","", + "[Microsoft ID@Xbox", "Chris Charla", "Dave Mianowski", "Wally Barger", +#endif +#if PLAYSTATION_CREDITS + "","", + "","", + "","", + "[@LOC_ID_CREDITS_JAPAN " /*"Japanese Localization & Production By"*/, "8-4, Ltd.", + "","", + "","", + "","", + "[Sony Computer Entertainment", "Alessandro Bovenzi", "Annie Meltzer", "Ben Andac", "Eddie Ramirez", "Justin Massongil", "Laura Casey", "Maimoona Block", "Norma Green", "Rey Gutierrez", "Ryan Clements", "Shahid Kamal Ahmad", "Shane Bettenhausen", "Akinari Ito", "Teppei Fujita", +#endif +#if SWITCH_CREDITS + "","", + "","", + "","", + "[Nintendo", "Kirk Scott", "Sara Popescu", +#endif + "","", + "", + "@LOC_ID_CREDITS_SCREEN_22" /*"Thanks to all our fans for their support!"*/, + }; + + int yCounter = 0; + for (int i = 0; i < creditsNames.Length; i++) + { + TextObj textObj = new TextObj(Game.JunicodeFont); + textObj.FontSize = 12; + string text = creditsNames[i]; + if (text.Length > 0 && text.StartsWith("[")) + { + text = text.Remove(0, 1); + textObj.FontSize = 10; + } + textObj.DropShadow = new Vector2(2, 2); + textObj.Align = Types.TextAlign.Centre; + textObj.Position = new Vector2(1320 / 2f, 720 + yCounter); + + try + { + if (text.Length > 0 && text.StartsWith("@")) + { + text = text.Remove(0, 1); + textObj.Text = LocaleBuilder.getString(text, textObj); + } + else + textObj.Text = text; + } + catch + { + textObj.ChangeFontNoDefault(Game.NotoSansSCFont); + if (text.Length > 0 && text.StartsWith("@")) + { + text = text.Remove(0, 1); + textObj.Text = LocaleBuilder.getString(text, textObj); + } + else + textObj.Text = text; + } + + + yCounter += 30; + + PositionTeam(creditsNames[i], new Vector2(textObj.Bounds.Left - 50, textObj.Y)); + m_creditsNameList.Add(textObj); + + //TextObj titlesTextObj = new TextObj(Game.JunicodeFont); + //titlesTextObj.FontSize = 12; + ////titlesTextObj.OutlineWidth = 2; + //titlesTextObj.DropShadow = new Vector2(2, 2); + //titlesTextObj.Align = Types.TextAlign.Centre; + //titlesTextObj.Position = new Vector2(1320 / 2f, 720 + yCounter); + + //if (i < creditsTitles.Length) + //{ + // titlesTextObj.Text = creditsTitles[i]; + // m_creditsTitleList.Add(titlesTextObj); + // if (i < creditsTitles.Length - 1) + // yCounter += 200; + // else + // yCounter += 40; + //} + //else + // yCounter += 40; + + //TextObj nameTextObj = titlesTextObj.Clone() as TextObj; + //nameTextObj.Text = creditsNames[i]; + //nameTextObj.FontSize = 16; + //nameTextObj.Y += 40; + //m_creditsNameList.Add(nameTextObj); + + //PositionTeam(creditsNames[i], new Vector2(nameTextObj.Bounds.Left - 50, nameTextObj.Y)); + } + } + + private void PositionTeam(string name, Vector2 position) + { + if (name.Contains("Teddy")) + m_teddy.Position = position; + else if (name.Contains("Kenny")) + { + m_kenny.Position = position; + m_kenny.X -= 10; + } + else if (name.Contains("Glauber")) + { + m_glauber.Position = position; + m_glauber.X -= 0; + } + else if (name.Contains("Gordon")) + { + m_gordon.Position = position; + m_gordon.X += 135; + } + else if (name.Contains("Judson")) + { + m_judson.Position = position; + m_judson.X += 60; + } + else if (name.Contains("Marie")) + { + m_mc.Position = position; + m_mc.X += 60; + } + } + + public override void OnEnter() + { + m_allowExit = false; + + float hoursPlayed = (Game.PlayerStats.TotalHoursPlayed + Game.HoursPlayedSinceLastSave); + int minutes = (int)((hoursPlayed - (int)(hoursPlayed)) * 60f); + Console.WriteLine("Hours played: " + hoursPlayed + " minutes: " + minutes); + + m_totalDeaths.Text = LocaleBuilder.getResourceString("LOC_ID_CREDITS_SCREEN_2") /*"Total Children"*/ + ": " + Game.PlayerStats.TimesDead.ToString(); + if (minutes < 10) + m_totalPlayTime.Text = LocaleBuilder.getResourceString("LOC_ID_CREDITS_SCREEN_3") /*"Time Played"*/ + " - " + (int)hoursPlayed + ":0" + minutes; + else + m_totalPlayTime.Text = LocaleBuilder.getResourceString("LOC_ID_CREDITS_SCREEN_3") /*"Time Played"*/ + " - " + (int)hoursPlayed + ":" + minutes; + + Camera.Position = Vector2.Zero; + m_displayingContinueText = false; + m_continueText.Text = LocaleBuilder.getString("LOC_ID_CREDITS_SCREEN_4_NEW", m_continueText); + //Tween.To(m_continueText, 1, Tween.EaseNone, "delay", "2", "Opacity", "1"); + + if (m_sky == null) // Hack + { + m_sky = new SkyObj(null); + m_skyRenderTarget = new RenderTarget2D(Camera.GraphicsDevice, 1320, 720, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + m_sky.LoadContent(Camera); + m_backgroundRenderTarget = new RenderTarget2D(Camera.GraphicsDevice, 1320, 720, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + } + + SetPlayerStyle("Walking"); + + // Only play a song if you're entering from the title screen. Otherwise just let the other song leak in. + if (IsEnding == false) + SoundManager.PlayMusic("CreditsSong", true, 1); + + //if (IsEnding == true) + // SoundManager.PlayMusic("EndSongDrums", true, 1); + //else + // SoundManager.PlayMusic("CreditsSong", true, 1); + + m_scrollDistance = -(m_creditsNameList[m_creditsNameList.Count - 1].Y + 100); + + foreach (TextObj title in m_creditsTitleList) + Tween.By(title, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + foreach (TextObj name in m_creditsNameList) + Tween.By(name, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + + Tween.By(m_teddy, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + Tween.By(m_kenny, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + Tween.By(m_glauber, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + Tween.By(m_gordon, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + Tween.By(m_judson, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + Tween.By(m_mc, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + + if (IsEnding == false) + { + m_sideBorderLeft.X += 200; + m_sideBorderRight.X -= 200; + Tween.RunFunction(m_scrollDuration + 1, this, "ResetScroll"); + } + + base.OnEnter(); + } + + public void SetPlayerStyle(string animationType) + { + m_playerSprite.ChangeSprite("Player" + animationType + "_Character"); + + PlayerObj player = (ScreenManager as RCScreenManager).Player; + for (int i = 0; i < m_playerSprite.NumChildren; i++) + { + m_playerSprite.GetChildAt(i).TextureColor = player.GetChildAt(i).TextureColor; + m_playerSprite.GetChildAt(i).Visible = player.GetChildAt(i).Visible; + } + m_playerSprite.GetChildAt(PlayerPart.Light).Visible = false; + m_playerSprite.Scale = player.Scale; + + if (Game.PlayerStats.Traits.X == TraitType.Baldness || Game.PlayerStats.Traits.Y == TraitType.Baldness) + m_playerSprite.GetChildAt(PlayerPart.Hair).Visible = false; + + m_playerSprite.GetChildAt(PlayerPart.Glasses).Visible = false; + if (Game.PlayerStats.SpecialItem == SpecialItemType.Glasses) + m_playerSprite.GetChildAt(PlayerPart.Glasses).Visible = true; + + if (Game.PlayerStats.Class == ClassType.Knight || Game.PlayerStats.Class == ClassType.Knight2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("Player" + animationType + "Shield_Sprite"); + } + else if (Game.PlayerStats.Class == ClassType.Banker || Game.PlayerStats.Class == ClassType.Banker2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("Player" + animationType + "Lamp_Sprite"); + } + else if (Game.PlayerStats.Class == ClassType.Wizard || Game.PlayerStats.Class == ClassType.Wizard2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("Player" + animationType + "Beard_Sprite"); + } + else if (Game.PlayerStats.Class == ClassType.Ninja || Game.PlayerStats.Class == ClassType.Ninja2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("Player" + animationType + "Headband_Sprite"); + } + else if (Game.PlayerStats.Class == ClassType.Barbarian || Game.PlayerStats.Class == ClassType.Barbarian2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("Player" + animationType + "Horns_Sprite"); + } + else + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = false; + + // Special code for dragon. + m_playerSprite.GetChildAt(PlayerPart.Wings).Visible = false; + if (Game.PlayerStats.Class == ClassType.Dragon) + { + m_playerSprite.GetChildAt(PlayerPart.Wings).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Head).ChangeSprite("Player" + animationType + "Head" + PlayerPart.DragonHelm + "_Sprite"); + } + + if (Game.PlayerStats.Class == ClassType.Traitor) + m_playerSprite.GetChildAt(PlayerPart.Head).ChangeSprite("Player" + animationType + "Head" + PlayerPart.IntroHelm + "_Sprite"); + + // This is for male/female counterparts + if (Game.PlayerStats.IsFemale == false) + { + m_playerSprite.GetChildAt(PlayerPart.Boobs).Visible = false; + m_playerSprite.GetChildAt(PlayerPart.Bowtie).Visible = false; + } + else + { + m_playerSprite.GetChildAt(PlayerPart.Boobs).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Bowtie).Visible = true; + } + + if (Game.PlayerStats.Traits.X == TraitType.Gigantism || Game.PlayerStats.Traits.Y == TraitType.Gigantism) + m_playerSprite.Scale = new Vector2(GameEV.TRAIT_GIGANTISM, GameEV.TRAIT_GIGANTISM); + if (Game.PlayerStats.Traits.X == TraitType.Dwarfism || Game.PlayerStats.Traits.Y == TraitType.Dwarfism) + m_playerSprite.Scale = new Vector2(GameEV.TRAIT_DWARFISM, GameEV.TRAIT_DWARFISM); + + if (Game.PlayerStats.Traits.X == TraitType.Ectomorph || Game.PlayerStats.Traits.Y == TraitType.Ectomorph) + { + m_playerSprite.ScaleX *= 0.825f; + m_playerSprite.ScaleY *= 1.25f; + } + + if (Game.PlayerStats.Traits.X == TraitType.Endomorph || Game.PlayerStats.Traits.Y == TraitType.Endomorph) + { + m_playerSprite.ScaleX *= 1.25f; + m_playerSprite.ScaleY *= 1.175f; + } + + if (Game.PlayerStats.Class == ClassType.SpellSword || Game.PlayerStats.Class == ClassType.SpellSword2) + { + m_playerSprite.OutlineColour = Color.White; + m_playerSprite.GetChildAt(PlayerPart.Sword1).Visible = false; + m_playerSprite.GetChildAt(PlayerPart.Sword2).Visible = false; + } + else + { + m_playerSprite.OutlineColour = Color.Black; + m_playerSprite.GetChildAt(PlayerPart.Sword1).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Sword2).Visible = true; + } + + // Setting the player's proper parts. + string headPart = (m_playerSprite.GetChildAt(PlayerPart.Head) as IAnimateableObj).SpriteName; + int numberIndex = headPart.IndexOf("_") - 1; + headPart = headPart.Remove(numberIndex, 1); + if (Game.PlayerStats.Class == ClassType.Dragon) + headPart = headPart.Replace("_", PlayerPart.DragonHelm + "_"); + else if (Game.PlayerStats.Class == ClassType.Traitor) + headPart = headPart.Replace("_", PlayerPart.IntroHelm + "_"); + else + headPart = headPart.Replace("_", Game.PlayerStats.HeadPiece + "_"); + m_playerSprite.GetChildAt(PlayerPart.Head).ChangeSprite(headPart); + + string chestPart = (m_playerSprite.GetChildAt(PlayerPart.Chest) as IAnimateableObj).SpriteName; + numberIndex = chestPart.IndexOf("_") - 1; + chestPart = chestPart.Remove(numberIndex, 1); + chestPart = chestPart.Replace("_", Game.PlayerStats.ChestPiece + "_"); + m_playerSprite.GetChildAt(PlayerPart.Chest).ChangeSprite(chestPart); + + string shoulderAPart = (m_playerSprite.GetChildAt(PlayerPart.ShoulderA) as IAnimateableObj).SpriteName; + numberIndex = shoulderAPart.IndexOf("_") - 1; + shoulderAPart = shoulderAPart.Remove(numberIndex, 1); + shoulderAPart = shoulderAPart.Replace("_", Game.PlayerStats.ShoulderPiece + "_"); + m_playerSprite.GetChildAt(PlayerPart.ShoulderA).ChangeSprite(shoulderAPart); + + string shoulderBPart = (m_playerSprite.GetChildAt(PlayerPart.ShoulderB) as IAnimateableObj).SpriteName; + numberIndex = shoulderBPart.IndexOf("_") - 1; + shoulderBPart = shoulderBPart.Remove(numberIndex, 1); + shoulderBPart = shoulderBPart.Replace("_", Game.PlayerStats.ShoulderPiece + "_"); + m_playerSprite.GetChildAt(PlayerPart.ShoulderB).ChangeSprite(shoulderBPart); + + // Reposition the player's Y after changing his scale. + m_playerSprite.PlayAnimation(true); + m_playerSprite.CalculateBounds(); + m_playerSprite.Y = 435 - (m_playerSprite.Bounds.Bottom - m_playerSprite.Y); + } + + public override void OnExit() + { + Tween.StopAllContaining(this, false); + base.OnExit(); + } + + public override void Update(GameTime gameTime) + { + if (IsEnding == true) + { + m_sky.Update(gameTime); + + float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds; + + UpdateBackground(elapsedTime); + + if (m_backgroundIndex < m_backgroundStrings.Length) + { + m_backgroundSwapTimer += elapsedTime; + + if (m_backgroundSwapTimer >= m_scrollDuration / m_backgroundStrings.Length) + { + SwapBackground(m_backgroundStrings[m_backgroundIndex]); + m_backgroundIndex++; + m_backgroundSwapTimer = 0; + } + } + } + + base.Update(gameTime); + } + + public void ResetScroll() + { + foreach (TextObj title in m_creditsTitleList) + { + title.Y += -m_scrollDistance; + Tween.By(title, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + } + + foreach (TextObj name in m_creditsNameList) + { + name.Y += -m_scrollDistance; + Tween.By(name, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + + PositionTeam(name.Text, new Vector2(name.Bounds.Left - 50, name.Y)); + } + + Tween.By(m_teddy, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + Tween.By(m_kenny, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + Tween.By(m_glauber, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + Tween.By(m_gordon, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + Tween.By(m_judson, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + Tween.By(m_mc, m_scrollDuration, Tween.EaseNone, "Y", m_scrollDistance.ToString()); + + Tween.RunFunction(m_scrollDuration + 1, this, "ResetScroll"); + } + + public override void HandleInput() + { + if (IsEnding == false || (IsEnding == true && m_allowExit == true)) + { + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + if (m_displayingContinueText == true) + { + Tween.StopAll(false); + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Title, true); + } + else + { + m_displayingContinueText = true; + Tween.StopAllContaining(m_continueText, false); + Tween.To(m_continueText, 0.5f, Tween.EaseNone, "Opacity", "1"); + Tween.RunFunction(4, this, "HideContinueText"); + } + } + } + + base.HandleInput(); + } + + public void HideContinueText() + { + m_displayingContinueText = false; + Tween.To(m_continueText, 0.5f, Tween.EaseNone, "delay", "0", "Opacity", "0"); + } + + private void UpdateBackground(float elapsedTime) + { + int movespeed = 200; + + m_bg1.X += movespeed * elapsedTime; + m_bg2.X += movespeed * elapsedTime; + m_bg3.X += movespeed * elapsedTime; + + if (m_bg1.X > 930) + m_bg1.X = m_bg3.X - m_bg3.Width; + if (m_bg2.X > 930) + m_bg2.X = m_bg1.X - m_bg1.Width; + if (m_bg3.X > 930) + m_bg3.X = m_bg2.X - m_bg2.Width; + + m_ground1.X += movespeed * elapsedTime; + m_ground2.X += movespeed * elapsedTime; + m_ground3.X += movespeed * elapsedTime; + + if (m_ground1.X > 930) + m_ground1.X = m_ground3.X - m_ground3.Width; + if (m_ground2.X > 930) + m_ground2.X = m_ground1.X - m_ground1.Width; + if (m_ground3.X > 930) + m_ground3.X = m_ground2.X - m_ground2.Width; + + m_border1.X += movespeed * elapsedTime; + m_border2.X += movespeed * elapsedTime; + m_border3.X += movespeed * elapsedTime; + + if (m_border1.X > 930) + m_border1.X = m_border3.X - m_border3.Width; + if (m_border2.X > 930) + m_border2.X = m_border1.X - m_border1.Width; + if (m_border3.X > 930) + m_border3.X = m_border2.X - m_border2.Width; + + m_prop1.X += movespeed * elapsedTime; + m_prop2.X += movespeed * elapsedTime; + m_prop3.X += movespeed * elapsedTime; + + if (m_prop1.X > 930) + m_prop1.X -= CDGMath.RandomInt(1000, 3000); + if (m_prop2.X > 930) + m_prop2.X -= CDGMath.RandomInt(1000, 3000); + if (m_prop3.X > 930) + m_prop3.X -= CDGMath.RandomInt(1000, 3000); + } + + public void SwapBackground(string levelType) + { + Tween.By(m_sideBorderLeft, 0.5f, Tween.EaseNone, "X", "200"); + Tween.By(m_sideBorderRight, 0.5f, Tween.EaseNone, "X", "-200"); + Tween.AddEndHandlerToLastTween(this, "PerformSwap", levelType); + } + + public void PerformSwap(string levelType) + { + m_manor.Y = 0; + m_bgOutside.Y = 0; + m_bgOutside.Visible = false; + m_manor.Visible = false; + m_ground1.Visible = m_ground2.Visible = m_ground3.Visible = true; + m_border1.Visible = m_border2.Visible = m_border3.Visible = true; + m_prop1.Visible = m_prop2.Visible = m_prop3.Visible = true; + + switch (levelType) + { + case ("Castle"): + m_bg1.ChangeSprite("CastleBG1_Sprite"); + m_bg2.ChangeSprite("CastleBG1_Sprite"); + m_bg3.ChangeSprite("CastleBG1_Sprite"); + m_ground1.ChangeSprite("CastleFG1_Sprite"); + m_ground2.ChangeSprite("CastleFG1_Sprite"); + m_ground3.ChangeSprite("CastleFG1_Sprite"); + m_border1.ChangeSprite("CastleBorder_Sprite"); + m_border2.ChangeSprite("CastleBorder_Sprite"); + m_border3.ChangeSprite("CastleBorder_Sprite"); + + m_prop1.ChangeSprite("CastleAssetWindow1_Sprite"); + m_prop2.ChangeSprite("CastleAssetBackTorch_Character"); + m_prop2.PlayAnimation(true); + m_prop2.AnimationDelay = 1 / 10f; + m_prop3.ChangeSprite("CastleAssetCandle1_Character"); + break; + case ("Tower"): + m_bg1.ChangeSprite("TowerBG2_Sprite"); + m_bg2.ChangeSprite("TowerBG2_Sprite"); + m_bg3.ChangeSprite("TowerBG2_Sprite"); + m_ground1.ChangeSprite("TowerFG2_Sprite"); + m_ground2.ChangeSprite("TowerFG2_Sprite"); + m_ground3.ChangeSprite("TowerFG2_Sprite"); + m_border1.ChangeSprite("TowerBorder2_Sprite"); + m_border2.ChangeSprite("TowerBorder2_Sprite"); + m_border3.ChangeSprite("TowerBorder2_Sprite"); + + m_prop1.ChangeSprite("TowerHole4_Sprite"); + m_prop2.Visible = false; + m_prop3.ChangeSprite("TowerPedestal2_Character"); + break; + case ("Dungeon"): + m_bg1.ChangeSprite("DungeonBG1_Sprite"); + m_bg2.ChangeSprite("DungeonBG1_Sprite"); + m_bg3.ChangeSprite("DungeonBG1_Sprite"); + m_ground1.ChangeSprite("DungeonFG1_Sprite"); + m_ground2.ChangeSprite("DungeonFG1_Sprite"); + m_ground3.ChangeSprite("DungeonFG1_Sprite"); + m_border1.ChangeSprite("DungeonBorder_Sprite"); + m_border2.ChangeSprite("DungeonBorder_Sprite"); + m_border3.ChangeSprite("DungeonBorder_Sprite"); + + m_prop1.ChangeSprite("DungeonPrison1_Sprite"); + m_prop2.ChangeSprite("DungeonChain2_Character"); + m_prop3.ChangeSprite("DungeonTorch2_Character"); + break; + case ("Garden"): + m_bg1.ChangeSprite("GardenBG_Sprite"); + m_bg2.ChangeSprite("GardenBG_Sprite"); + m_bg3.ChangeSprite("GardenBG_Sprite"); + m_ground1.ChangeSprite("GardenFG_Sprite"); + m_ground2.ChangeSprite("GardenFG_Sprite"); + m_ground3.ChangeSprite("GardenFG_Sprite"); + m_border1.ChangeSprite("GardenBorder_Sprite"); + m_border2.ChangeSprite("GardenBorder_Sprite"); + m_border3.ChangeSprite("GardenBorder_Sprite"); + + m_prop1.ChangeSprite("GardenFloatingRock3_Sprite"); + m_prop2.ChangeSprite("GardenFairy_Character"); + m_prop2.PlayAnimation(true); + m_prop2.AnimationDelay = 1 / 10f; + m_prop3.ChangeSprite("GardenLampPost1_Character"); + break; + case ("Outside"): + m_bg1.ChangeSprite("GardenBG_Sprite"); + m_bg2.ChangeSprite("GardenBG_Sprite"); + m_bg3.ChangeSprite("GardenBG_Sprite"); + m_ground1.ChangeSprite("GardenFG_Sprite"); + m_ground2.ChangeSprite("GardenFG_Sprite"); + m_ground3.ChangeSprite("GardenFG_Sprite"); + m_border1.ChangeSprite("StartingRoomFloor_Sprite"); + m_border2.ChangeSprite("StartingRoomFloor_Sprite"); + m_border3.ChangeSprite("StartingRoomFloor_Sprite"); + + m_prop1.ChangeSprite("DungeonPrison1_Sprite"); + m_prop1.Visible = false; + m_prop2.ChangeSprite("CreditsGrass_Character"); + m_prop2.Y = 440; // Hack to link it to the ground. + m_prop3.ChangeSprite("CreditsTree_Character"); + m_bgOutside.Visible = true; + break; + case ("Manor"): + m_bgOutside.Visible = true; + m_manor.Visible = true; + m_ground1.Visible = m_ground2.Visible = m_ground3.Visible = false; + m_border1.Visible = m_border2.Visible = m_border3.Visible = false; + m_manor.Y = -260; + m_bgOutside.Y = -260; + m_manor.X -= 300; + m_bgOutside.X -= 300; + + m_prop1.Visible = false; + m_prop2.Visible = false; + m_prop3.Visible = false; + + Tween.By(m_manor, 3f, Tween.EaseNone, "X", "300"); + Tween.By(m_bgOutside, 3f, Tween.EaseNone, "X", "300"); + Tween.By(m_playerSprite, 3.5f, Tween.EaseNone, "X", "-150"); + Tween.AddEndHandlerToLastTween(this, "CreditsComplete"); + + Tween.By(m_sideBorderTop, 2.5f, Tween.EaseNone, "Y", "-500"); + break; + } + + if (levelType != "Manor") + { + Tween.By(m_sideBorderLeft, 0.5f, Tween.EaseNone, "X", "-200"); + Tween.By(m_sideBorderRight, 0.5f, Tween.EaseNone, "X", "200"); + } + else + { + Tween.By(m_sideBorderLeft, 3f, Tween.EaseNone, "X", "-800"); + Tween.By(m_sideBorderRight, 3f, Tween.EaseNone, "X", "800"); + } + } + + public void CreditsComplete() + { + SetPlayerStyle("Idle"); + + Tween.RunFunction(0.5f, this, "SetPlayerStyle", "LevelUp"); + Tween.RunFunction(0.6f, m_playerSprite, "PlayAnimation", false); + Tween.To(m_thanksForPlayingText, 2, Tween.EaseNone, "Opacity", "1"); + Tween.To(m_totalDeaths, 2, Tween.EaseNone,"delay", "0.2", "Opacity", "1"); + Tween.To(m_totalPlayTime, 2, Tween.EaseNone, "delay", "0.4", "Opacity", "1"); + + Tween.RunFunction(1, this, "BringWife"); + Tween.RunFunction(1.1f, this, "BringChild1"); + Tween.RunFunction(3f, this, "BringChild2"); + } + + public void BringWife() + { + m_wifeSprite.GetChildAt(PlayerPart.Glasses).Visible = false; + m_wifeSprite.GetChildAt(PlayerPart.Extra).Visible = false; + m_wifeSprite.GetChildAt(PlayerPart.Light).Visible = false; + m_wifeSprite.GetChildAt(PlayerPart.Wings).Visible = false; + + m_wifeChest = CDGMath.RandomInt(1, PlayerPart.NumChestPieces); + m_wifeHead = CDGMath.RandomInt(1, PlayerPart.NumHeadPieces); + m_wifeShoulders = CDGMath.RandomInt(1, PlayerPart.NumShoulderPieces); + + m_wifeSprite.GetChildAt(PlayerPart.Chest).ChangeSprite("PlayerWalkingChest" + m_wifeChest + "_Sprite"); + m_wifeSprite.GetChildAt(PlayerPart.Head).ChangeSprite("PlayerWalkingHead" + m_wifeHead + "_Sprite"); + m_wifeSprite.GetChildAt(PlayerPart.ShoulderA).ChangeSprite("PlayerWalkingShoulderA" + m_wifeShoulders + "_Sprite"); + m_wifeSprite.GetChildAt(PlayerPart.ShoulderB).ChangeSprite("PlayerWalkingShoulderB" + m_wifeShoulders + "_Sprite"); + + if ((Game.PlayerStats.IsFemale == false && (Game.PlayerStats.Traits.X != TraitType.Gay && Game.PlayerStats.Traits.Y != TraitType.Gay)) || + ((Game.PlayerStats.IsFemale == true && (Game.PlayerStats.Traits.X == TraitType.Gay || Game.PlayerStats.Traits.Y == TraitType.Gay)))) + { + m_wifeSprite.GetChildAt(PlayerPart.Bowtie).Visible = true; + m_wifeSprite.GetChildAt(PlayerPart.Boobs).Visible = true; + } + else + { + m_wifeSprite.GetChildAt(PlayerPart.Bowtie).Visible = false; + m_wifeSprite.GetChildAt(PlayerPart.Boobs).Visible = false; + } + + m_wifeSprite.PlayAnimation(true); + Tween.By(m_wifeSprite, 3, Tween.EaseNone, "X", "600"); + Tween.AddEndHandlerToLastTween(this, "LevelUpWife"); + } + + public void LevelUpWife() + { + m_wifeSprite.ChangeSprite("PlayerLevelUp_Character"); + m_wifeSprite.GetChildAt(PlayerPart.Glasses).Visible = false; + m_wifeSprite.GetChildAt(PlayerPart.Extra).Visible = false; + m_wifeSprite.GetChildAt(PlayerPart.Light).Visible = false; + m_wifeSprite.GetChildAt(PlayerPart.Wings).Visible = false; + + if ((Game.PlayerStats.IsFemale == false && (Game.PlayerStats.Traits.X != TraitType.Gay && Game.PlayerStats.Traits.Y != TraitType.Gay)) || + ((Game.PlayerStats.IsFemale == true && (Game.PlayerStats.Traits.X == TraitType.Gay || Game.PlayerStats.Traits.Y == TraitType.Gay)))) + { + m_wifeSprite.GetChildAt(PlayerPart.Bowtie).Visible = true; + m_wifeSprite.GetChildAt(PlayerPart.Boobs).Visible = true; + } + else + { + m_wifeSprite.GetChildAt(PlayerPart.Bowtie).Visible = false; + m_wifeSprite.GetChildAt(PlayerPart.Boobs).Visible = false; + } + + m_wifeSprite.GetChildAt(PlayerPart.Chest).ChangeSprite("PlayerLevelUpChest" + m_wifeChest + "_Sprite"); + m_wifeSprite.GetChildAt(PlayerPart.Head).ChangeSprite("PlayerLevelUpHead" + m_wifeHead + "_Sprite"); + m_wifeSprite.GetChildAt(PlayerPart.ShoulderA).ChangeSprite("PlayerLevelUpShoulderA" + m_wifeShoulders + "_Sprite"); + m_wifeSprite.GetChildAt(PlayerPart.ShoulderB).ChangeSprite("PlayerLevelUpShoulderB" + m_wifeShoulders + "_Sprite"); + m_wifeSprite.PlayAnimation(false); + } + + public void BringChild1() + { + m_childSprite1.GetChildAt(PlayerPart.Glasses).Visible = false; + m_childSprite1.GetChildAt(PlayerPart.Extra).Visible = false; + m_childSprite1.GetChildAt(PlayerPart.Light).Visible = false; + m_childSprite1.GetChildAt(PlayerPart.Wings).Visible = false; + + m_child1Chest = CDGMath.RandomInt(1, PlayerPart.NumChestPieces); + m_child1Head = CDGMath.RandomInt(1, PlayerPart.NumHeadPieces); + m_child1Shoulders = CDGMath.RandomInt(1, PlayerPart.NumShoulderPieces); + + bool isFemale = false; + if (CDGMath.RandomInt(0, 1) > 0) isFemale = true; + if (isFemale == true) + { + m_childSprite1.GetChildAt(PlayerPart.Bowtie).Visible = true; + m_childSprite1.GetChildAt(PlayerPart.Boobs).Visible = true; + } + else + { + m_childSprite1.GetChildAt(PlayerPart.Bowtie).Visible = false; + m_childSprite1.GetChildAt(PlayerPart.Boobs).Visible = false; + } + + m_childSprite1.GetChildAt(PlayerPart.Chest).ChangeSprite("PlayerWalkingChest" + m_child1Chest + "_Sprite"); + m_childSprite1.GetChildAt(PlayerPart.Head).ChangeSprite("PlayerWalkingHead" + m_child1Head + "_Sprite"); + m_childSprite1.GetChildAt(PlayerPart.ShoulderA).ChangeSprite("PlayerWalkingShoulderA" + m_child1Shoulders + "_Sprite"); + m_childSprite1.GetChildAt(PlayerPart.ShoulderB).ChangeSprite("PlayerWalkingShoulderB" + m_child1Shoulders + "_Sprite"); + m_childSprite1.PlayAnimation(true); + Tween.By(m_childSprite1, 3, Tween.EaseNone, "X", "600"); + Tween.AddEndHandlerToLastTween(this, "LevelUpChild1", isFemale); + } + + public void LevelUpChild1(bool isFemale) + { + m_childSprite1.ChangeSprite("PlayerLevelUp_Character"); + m_childSprite1.GetChildAt(PlayerPart.Glasses).Visible = false; + m_childSprite1.GetChildAt(PlayerPart.Extra).Visible = false; + m_childSprite1.GetChildAt(PlayerPart.Light).Visible = false; + m_childSprite1.GetChildAt(PlayerPart.Wings).Visible = false; + + if (isFemale == true) + { + m_childSprite1.GetChildAt(PlayerPart.Bowtie).Visible = true; + m_childSprite1.GetChildAt(PlayerPart.Boobs).Visible = true; + } + else + { + m_childSprite1.GetChildAt(PlayerPart.Bowtie).Visible = false; + m_childSprite1.GetChildAt(PlayerPart.Boobs).Visible = false; + } + + m_childSprite1.GetChildAt(PlayerPart.Chest).ChangeSprite("PlayerLevelUpChest" + m_child1Chest + "_Sprite"); + m_childSprite1.GetChildAt(PlayerPart.Head).ChangeSprite("PlayerLevelUpHead" + m_child1Head + "_Sprite"); + m_childSprite1.GetChildAt(PlayerPart.ShoulderA).ChangeSprite("PlayerLevelUpShoulderA" + m_child1Shoulders + "_Sprite"); + m_childSprite1.GetChildAt(PlayerPart.ShoulderB).ChangeSprite("PlayerLevelUpShoulderB" + m_child1Shoulders + "_Sprite"); + m_childSprite1.PlayAnimation(false); + } + + public void BringChild2() + { + m_childSprite2.GetChildAt(PlayerPart.Glasses).Visible = false; + m_childSprite2.GetChildAt(PlayerPart.Extra).Visible = false; + m_childSprite2.GetChildAt(PlayerPart.Light).Visible = false; + m_childSprite2.GetChildAt(PlayerPart.Wings).Visible = false; + + bool isFemale = false; + if (CDGMath.RandomInt(0, 1) > 0) isFemale = true; + if (isFemale == true) + { + m_childSprite2.GetChildAt(PlayerPart.Bowtie).Visible = true; + m_childSprite2.GetChildAt(PlayerPart.Boobs).Visible = true; + } + else + { + m_childSprite2.GetChildAt(PlayerPart.Bowtie).Visible = false; + m_childSprite2.GetChildAt(PlayerPart.Boobs).Visible = false; + } + + m_child2Chest = CDGMath.RandomInt(1, PlayerPart.NumChestPieces); + m_child2Head = CDGMath.RandomInt(1, PlayerPart.NumHeadPieces); + m_child2Shoulders = CDGMath.RandomInt(1, PlayerPart.NumShoulderPieces); + + m_childSprite2.GetChildAt(PlayerPart.Chest).ChangeSprite("PlayerWalkingChest" + m_child2Chest + "_Sprite"); + m_childSprite2.GetChildAt(PlayerPart.Head).ChangeSprite("PlayerWalkingHead" + m_child2Head + "_Sprite"); + m_childSprite2.GetChildAt(PlayerPart.ShoulderA).ChangeSprite("PlayerWalkingShoulderA" + m_child2Shoulders + "_Sprite"); + m_childSprite2.GetChildAt(PlayerPart.ShoulderB).ChangeSprite("PlayerWalkingShoulderB" + m_child2Shoulders + "_Sprite"); + m_childSprite2.PlayAnimation(true); + Tween.By(m_childSprite2, 2, Tween.EaseNone, "X", "600"); + Tween.AddEndHandlerToLastTween(this, "LevelUpChild2", isFemale); + } + + public void LevelUpChild2(bool isFemale) + { + m_childSprite2.ChangeSprite("PlayerLevelUp_Character"); + m_childSprite2.GetChildAt(PlayerPart.Glasses).Visible = false; + m_childSprite2.GetChildAt(PlayerPart.Extra).Visible = false; + m_childSprite2.GetChildAt(PlayerPart.Light).Visible = false; + m_childSprite2.GetChildAt(PlayerPart.Wings).Visible = false; + + if (isFemale == true) + { + m_childSprite2.GetChildAt(PlayerPart.Bowtie).Visible = true; + m_childSprite2.GetChildAt(PlayerPart.Boobs).Visible = true; + } + else + { + m_childSprite2.GetChildAt(PlayerPart.Bowtie).Visible = false; + m_childSprite2.GetChildAt(PlayerPart.Boobs).Visible = false; + } + + m_childSprite2.GetChildAt(PlayerPart.Chest).ChangeSprite("PlayerLevelUpChest" + m_child2Chest + "_Sprite"); + m_childSprite2.GetChildAt(PlayerPart.Head).ChangeSprite("PlayerLevelUpHead" + m_child2Head + "_Sprite"); + m_childSprite2.GetChildAt(PlayerPart.ShoulderA).ChangeSprite("PlayerLevelUpShoulderA" + m_child2Shoulders + "_Sprite"); + m_childSprite2.GetChildAt(PlayerPart.ShoulderB).ChangeSprite("PlayerLevelUpShoulderB" + m_child2Shoulders + "_Sprite"); + m_childSprite2.PlayAnimation(false); + + //This is the last moment of animation. Allow the player to skip. + m_allowExit = true; + m_displayingContinueText = true; + Tween.StopAllContaining(m_continueText, false); + Tween.To(m_continueText, 0.5f, Tween.EaseNone, "Opacity", "1"); + } + + + public override void Draw(GameTime gametime) + { + Camera.GraphicsDevice.SetRenderTarget(m_skyRenderTarget); + Camera.GraphicsDevice.Clear(Color.Black); + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointWrap, null, null); + m_sky.Draw(Camera); + Camera.End(); + + Camera.GraphicsDevice.SetRenderTarget(m_backgroundRenderTarget); + Camera.GraphicsDevice.Clear(Color.Black); + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); + + m_bg1.Draw(Camera); + m_bg2.Draw(Camera); + m_bg3.Draw(Camera); + + m_bgOutside.Draw(Camera); + + m_ground1.Draw(Camera); + m_ground2.Draw(Camera); + m_ground3.Draw(Camera); + + m_border1.Draw(Camera); + m_border2.Draw(Camera); + m_border3.Draw(Camera); + + m_manor.Draw(Camera); + + m_prop1.Draw(Camera); + m_prop2.Draw(Camera); + m_prop3.Draw(Camera); + + m_playerSprite.Draw(Camera); + Game.ColourSwapShader.Parameters["desiredTint"].SetValue(m_playerSprite.GetChildAt(PlayerPart.Head).TextureColor.ToVector4()); + + if (Game.PlayerStats.Class == ClassType.Lich || Game.PlayerStats.Class == ClassType.Lich2) + { + // This is the Tint Removal effect, that removes the tint from his face. + Game.ColourSwapShader.Parameters["Opacity"].SetValue(m_playerSprite.Opacity); + Game.ColourSwapShader.Parameters["ColourSwappedOut1"].SetValue(m_skinColour1.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn1"].SetValue(m_lichColour1.ToVector4()); + + Game.ColourSwapShader.Parameters["ColourSwappedOut2"].SetValue(m_skinColour2.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn2"].SetValue(m_lichColour2.ToVector4()); + } + else if (Game.PlayerStats.Class == ClassType.Assassin || Game.PlayerStats.Class == ClassType.Assassin2) + { + // This is the Tint Removal effect, that removes the tint from his face. + Game.ColourSwapShader.Parameters["Opacity"].SetValue(m_playerSprite.Opacity); + Game.ColourSwapShader.Parameters["ColourSwappedOut1"].SetValue(m_skinColour1.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn1"].SetValue(Color.Black.ToVector4()); + + Game.ColourSwapShader.Parameters["ColourSwappedOut2"].SetValue(m_skinColour2.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn2"].SetValue(Color.Black.ToVector4()); + + } + else + { + Game.ColourSwapShader.Parameters["Opacity"].SetValue(1); + Game.ColourSwapShader.Parameters["ColourSwappedOut1"].SetValue(m_skinColour1.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn1"].SetValue(m_skinColour1.ToVector4()); + + Game.ColourSwapShader.Parameters["ColourSwappedOut2"].SetValue(m_skinColour2.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn2"].SetValue(m_skinColour2.ToVector4()); + } + + Camera.End(); + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, Game.ColourSwapShader); + m_playerSprite.GetChildAt(PlayerPart.Head).Draw(Camera); + Camera.End(); + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null); + if (Game.PlayerStats.IsFemale == true) + m_playerSprite.GetChildAt(PlayerPart.Bowtie).Draw(Camera); + m_playerSprite.GetChildAt(PlayerPart.Extra).Draw(Camera); + + m_wifeSprite.Draw(Camera); + m_childSprite1.Draw(Camera); + m_childSprite2.Draw(Camera); + + m_sideBorderLeft.Draw(Camera); + m_sideBorderRight.Draw(Camera); + m_sideBorderTop.Draw(Camera); + m_sideBorderBottom.Draw(Camera); + + m_teddy.Draw(Camera); + m_kenny.Draw(Camera); + m_glauber.Draw(Camera); + m_gordon.Draw(Camera); + m_judson.Draw(Camera); + m_mc.Draw(Camera); + + Camera.End(); + + Camera.GraphicsDevice.SetRenderTarget((ScreenManager as RCScreenManager).RenderTarget); + Camera.GraphicsDevice.Textures[1] = m_skyRenderTarget; + Camera.GraphicsDevice.Textures[1].GraphicsDevice.SamplerStates[1] = SamplerState.LinearClamp; + Camera.GraphicsDevice.SetRenderTarget((ScreenManager as RCScreenManager).RenderTarget); + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, Game.ParallaxEffect); + Camera.Draw(m_backgroundRenderTarget, Vector2.Zero, Color.White); + Camera.End(); + + // Drawing the text separately because it causes purple outlines with the Parallax effect. + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + + Rectangle bounds = new Rectangle(0, 0, 1320, 720); + foreach (TextObj title in m_creditsTitleList) + { + if (CollisionMath.Intersects(title.Bounds, bounds)) + title.Draw(Camera); + } + + foreach (TextObj name in m_creditsNameList) + { + if (CollisionMath.Intersects(name.Bounds, bounds)) + name.Draw(Camera); + } + + m_thanksForPlayingText.Draw(Camera); + m_totalDeaths.Draw(Camera); + m_totalPlayTime.Draw(Camera); + + m_continueText.Draw(Camera); + Camera.End(); + + base.Draw(gametime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Credits Screen"); + + Array.Clear(m_backgroundStrings, 0, m_backgroundStrings.Length); + m_backgroundStrings = null; + + m_playerSprite.Dispose(); + m_playerSprite = null; + + m_wifeSprite.Dispose(); + m_wifeSprite = null; + + m_childSprite1.Dispose(); + m_childSprite1 = null; + m_childSprite2.Dispose(); + m_childSprite2 = null; + + m_manor.Dispose(); + m_manor = null; + + m_thanksForPlayingText.Dispose(); + m_thanksForPlayingText = null; + + m_sideBorderRight.Dispose(); + m_sideBorderRight = null; + m_sideBorderLeft.Dispose(); + m_sideBorderLeft = null; + m_sideBorderTop.Dispose(); + m_sideBorderTop = null; + m_sideBorderBottom.Dispose(); + m_sideBorderBottom = null; + + m_bgOutside.Dispose(); + m_bgOutside = null; + + if (m_sky != null) + m_sky.Dispose(); + m_sky = null; + if (m_skyRenderTarget != null) + m_skyRenderTarget.Dispose(); + m_skyRenderTarget = null; + if (m_backgroundRenderTarget != null) + m_backgroundRenderTarget.Dispose(); + m_backgroundRenderTarget = null; + + foreach (TextObj title in m_creditsTitleList) + title.Dispose(); + m_creditsTitleList.Clear(); + m_creditsTitleList = null; + + foreach (TextObj name in m_creditsNameList) + name.Dispose(); + m_creditsNameList.Clear(); + m_creditsNameList = null; + + m_bg1.Dispose(); + m_bg2.Dispose(); + m_bg3.Dispose(); + + m_ground1.Dispose(); + m_ground2.Dispose(); + m_ground3.Dispose(); + + m_border1.Dispose(); + m_border2.Dispose(); + m_border3.Dispose(); + + m_prop1.Dispose(); + m_prop2.Dispose(); + m_prop3.Dispose(); + + m_prop1 = null; + m_prop2 = null; + m_prop3 = null; + + m_bg1 = null; + m_bg2 = null; + m_bg3 = null; + + m_ground1 = null; + m_ground2 = null; + m_ground3 = null; + + m_border1 = null; + m_border2 = null; + m_border3 = null; + + m_teddy.Dispose(); + m_kenny.Dispose(); + m_glauber.Dispose(); + m_gordon.Dispose(); + m_judson.Dispose(); + m_mc.Dispose(); + + m_teddy = null; + m_kenny = null; + m_glauber = null; + m_gordon = null; + m_judson = null; + m_mc = null; + + m_continueText.Dispose(); + m_continueText = null; + + m_totalDeaths.Dispose(); + m_totalDeaths = null; + m_totalPlayTime.Dispose(); + m_totalPlayTime = null; + + base.Dispose(); + } + } + + public override void RefreshTextObjs() + { + float hoursPlayed = (Game.PlayerStats.TotalHoursPlayed + Game.HoursPlayedSinceLastSave); + int minutes = (int)((hoursPlayed - (int)(hoursPlayed)) * 60f); + m_totalDeaths.Text = LocaleBuilder.getResourceString("LOC_ID_CREDITS_SCREEN_2") /*"Total Children"*/ + ": " + Game.PlayerStats.TimesDead.ToString(); + if (minutes < 10) + m_totalPlayTime.Text = LocaleBuilder.getResourceString("LOC_ID_CREDITS_SCREEN_3") /*"Time Played"*/ + " - " + (int)hoursPlayed + ":0" + minutes; + else + m_totalPlayTime.Text = LocaleBuilder.getResourceString("LOC_ID_CREDITS_SCREEN_3") /*"Time Played"*/ + " - " + (int)hoursPlayed + ":" + minutes; + //m_continueText.Text = LocaleBuilder.getResourceString("LOC_ID_CREDITS_SCREEN_4") + " [Input:" + InputMapType.MENU_CONFIRM1 + "] " + LocaleBuilder.getResourceString("LOC_ID_CREDITS_SCREEN_5"); + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Screens/DeathDefiedScreen.cs b/RogueCastle/src/Screens/DeathDefiedScreen.cs new file mode 100644 index 0000000..d2fdc1a --- /dev/null +++ b/RogueCastle/src/Screens/DeathDefiedScreen.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using InputSystem; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class DeathDefiedScreen : Screen + { + private PlayerObj m_player; + private SpriteObj m_spotlight; + + private SpriteObj m_titlePlate; + private SpriteObj m_title; + + public float BackBufferOpacity { get; set; } + private Vector2 m_cameraPos; + + private string m_songName; + private float m_storedMusicVolume; + + public DeathDefiedScreen() + { + } + + public override void LoadContent() + { + Vector2 shadowOffset = new Vector2(2, 2); + Color textColour = new Color(255, 254, 128); + + m_spotlight = new SpriteObj("GameOverSpotlight_Sprite"); + m_spotlight.Rotation = 90; + m_spotlight.ForceDraw = true; + m_spotlight.Position = new Vector2(1320 / 2, 40 + m_spotlight.Height); + + m_titlePlate = new SpriteObj("SkillUnlockTitlePlate_Sprite"); + m_titlePlate.Position = new Vector2(1320 / 2f, 720 / 2f - 200); + m_titlePlate.ForceDraw = true; + + m_title = new SpriteObj("DeathDefyText_Sprite"); + m_title.Position = m_titlePlate.Position; + m_title.Y -= 40; + m_title.ForceDraw = true; + + base.LoadContent(); + } + + public override void OnEnter() + { + m_cameraPos = new Vector2(Camera.X, Camera.Y); + + if (m_player == null) + m_player = (ScreenManager as RCScreenManager).Player; + + m_titlePlate.Scale = Vector2.Zero; + m_title.Scale = Vector2.Zero; + m_title.Opacity = 1; + m_titlePlate.Opacity = 1; + + m_storedMusicVolume = SoundManager.GlobalMusicVolume; + m_songName = SoundManager.GetCurrentMusicName(); + Tween.To(typeof(SoundManager), 1, Tween.EaseNone, "GlobalMusicVolume", (m_storedMusicVolume * 0.1f).ToString()); + SoundManager.PlaySound("Player_Death_FadeToBlack"); + + m_player.Visible = true; + m_player.Opacity = 1; + + m_spotlight.Opacity = 0; + + // Spotlight, Player slain text, and Backbuffer animation. + Tween.To(this, 0.5f, Linear.EaseNone, "BackBufferOpacity", "1"); + Tween.To(m_spotlight, 0.1f, Linear.EaseNone, "delay", "1", "Opacity", "1"); + Tween.AddEndHandlerToLastTween(typeof(SoundManager), "PlaySound", "Player_Death_Spotlight"); + Tween.To(Camera, 1, Quad.EaseInOut, "X", this.m_player.AbsX.ToString(), "Y", (this.m_player.Bounds.Bottom - 10).ToString(), "Zoom", "1"); + Tween.RunFunction(2f, this, "PlayerLevelUpAnimation"); + + Game.ChangeBitmapLanguage(m_title, "DeathDefyText_Sprite"); + + base.OnEnter(); + } + + public void PlayerLevelUpAnimation() + { + m_player.ChangeSprite("PlayerLevelUp_Character"); + m_player.PlayAnimation(false); + + Tween.To(m_titlePlate, 0.5f, Back.EaseOut, "ScaleX", "1", "ScaleY", "1"); + Tween.To(m_title, 0.5f, Back.EaseOut, "delay", "0.1", "ScaleX", "0.8", "ScaleY", "0.8"); + Tween.RunFunction(0.1f, typeof(SoundManager), "PlaySound", "GetItemStinger3"); + Tween.RunFunction(2, this, "ExitTransition"); + } + + public void ExitTransition() + { + Tween.To(typeof(SoundManager), 1, Tween.EaseNone, "GlobalMusicVolume", m_storedMusicVolume.ToString()); + + Tween.To(Camera, 1, Quad.EaseInOut, "X", m_cameraPos.X.ToString(), "Y", m_cameraPos.Y.ToString()); + Tween.To(m_spotlight, 0.5f, Tween.EaseNone, "Opacity", "0"); + Tween.To(m_titlePlate, 0.5f, Tween.EaseNone, "Opacity", "0"); + Tween.To(m_title, 0.5f, Tween.EaseNone, "Opacity", "0"); + Tween.To(this, 0.2f, Tween.EaseNone, "delay", "1", "BackBufferOpacity", "0"); + Tween.AddEndHandlerToLastTween(ScreenManager, "HideCurrentScreen"); + } + + public override void Draw(GameTime gameTime) + { + //Camera.GraphicsDevice.Clear(Color.Black); + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, Camera.GetTransformation()); // Parallax Effect has been disabled in favour of ripple effect for now. + Camera.Draw(Game.GenericTexture, new Rectangle((int)Camera.TopLeftCorner.X - 10, (int)Camera.TopLeftCorner.Y - 10, 1340, 740), Color.Black * BackBufferOpacity); + + m_player.Draw(Camera); + Camera.End(); + + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null); // Parallax Effect has been disabled in favour of ripple effect for now. + m_spotlight.Draw(Camera); + m_titlePlate.Draw(Camera); + m_title.Draw(Camera); + Camera.End(); + + base.Draw(gameTime); + } + + public override void RefreshTextObjs() + { + Game.ChangeBitmapLanguage(m_title, "DeathDefyText_Sprite"); + + base.RefreshTextObjs(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Death Defied Screen"); + + m_player = null; + m_spotlight.Dispose(); + m_spotlight = null; + + m_title.Dispose(); + m_title = null; + m_titlePlate.Dispose(); + m_titlePlate = null; + + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Screens/DemoEndScreen.cs b/RogueCastle/src/Screens/DemoEndScreen.cs new file mode 100644 index 0000000..a04f534 --- /dev/null +++ b/RogueCastle/src/Screens/DemoEndScreen.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using System.IO; +using System.Globalization; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class DemoEndScreen : Screen + { + public float BackBufferOpacity { get; set; } + + private TextObj m_text; + private SpriteObj m_playerShrug; + + public DemoEndScreen() + { + + } + + public override void LoadContent() + { + m_text = new TextObj(Game.JunicodeLargeFont); + m_text.FontSize = 20; + m_text.Text = "Thanks for playing the Rogue Legacy Demo. You're pretty good at games.";//"Hey dudes, thanks for beating the demo.\nLet's go for a burger....\n Ha! Ha! Ha! Ha!";//"Thank you for playing the Rogue Legacy demo.\nPlease show your support, and help spread the word.";//"Thanks for playing the demo of Rogue Legacy. That's it for now."; + m_text.ForceDraw = true; + m_text.Position = new Vector2(1320 / 2f - m_text.Width / 2f, 720 / 2f - m_text.Height / 2f - 30); + + m_playerShrug = new SpriteObj("PlayerShrug_Sprite"); + m_playerShrug.ForceDraw = true; + m_playerShrug.Position = new Vector2(1320 / 2f, m_text.Bounds.Bottom + 100); + m_playerShrug.Scale = new Vector2(3, 3); + base.LoadContent(); + } + + public override void OnEnter() + { + BackBufferOpacity = 1; + Tween.RunFunction(8, ScreenManager, "DisplayScreen", ScreenType.Title, true, typeof(List)); + base.OnEnter(); + } + + public override void Draw(GameTime gametime) + { + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null); + Camera.Draw(Game.GenericTexture, new Rectangle(0, 0, 1320, 720), Color.Black * BackBufferOpacity); + + m_playerShrug.Draw(Camera); + + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + m_text.Draw(Camera); + + Camera.End(); + base.Draw(gametime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_playerShrug.Dispose(); + m_playerShrug = null; + + m_text.Dispose(); + m_text = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Screens/DemoStartScreen.cs b/RogueCastle/src/Screens/DemoStartScreen.cs new file mode 100644 index 0000000..d40f3d9 --- /dev/null +++ b/RogueCastle/src/Screens/DemoStartScreen.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using System.IO; +using System.Globalization; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class DemoStartScreen : Screen + { + public float BackBufferOpacity { get; set; } + + private TextObj m_text; + + public DemoStartScreen() + { + + } + + public override void LoadContent() + { + m_text = new TextObj(Game.JunicodeLargeFont); + m_text.FontSize = 20; + m_text.Text = "This is a demo of Rogue Legacy.\nThere may be bugs, and some assets are missing, but we hope you enjoy it."; + //"This is a beta demo of Rogue Legacy.\nThough the game is not bug-free and there are missing art and audio assets,\nwe hope you enjoy it.";//"The following is a beta demo of Rogue Legacy."; + m_text.ForceDraw = true; + m_text.Position = new Vector2(1320 / 2f - m_text.Width / 2f, 720 / 2f - m_text.Height / 2f - 30); + base.LoadContent(); + } + + public override void OnEnter() + { + BackBufferOpacity = 1; + Tween.RunFunction(7, ScreenManager, "DisplayScreen", ScreenType.CDGSplash, true, typeof(List)); + base.OnEnter(); + } + + public override void Draw(GameTime gametime) + { + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null); + Camera.Draw(Game.GenericTexture, new Rectangle(0, 0, 1320, 720), Color.Black * BackBufferOpacity); + + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + m_text.Draw(Camera); + + Camera.End(); + base.Draw(gametime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + // Done + m_text.Dispose(); + m_text = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Screens/DialogueScreen.cs b/RogueCastle/src/Screens/DialogueScreen.cs new file mode 100644 index 0000000..b6b0006 --- /dev/null +++ b/RogueCastle/src/Screens/DialogueScreen.cs @@ -0,0 +1,507 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using InputSystem; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Graphics; +using System.Reflection; + +namespace RogueCastle +{ + + public class DialogueScreen : Screen + { + private ObjContainer m_dialogContainer; + private byte m_dialogCounter; + private string[] m_dialogTitles; + private string[] m_dialogText; + private float m_dialogContinueIconY; + private string m_dialogueObjName; + public float BackBufferOpacity { get; set; } + + // Variables for endhandlers + private MethodInfo m_confirmMethodInfo; + private object m_confirmMethodObj; + private object[] m_confirmArgs; + + private MethodInfo m_cancelMethodInfo; + private object m_cancelMethodObj; + private object[] m_cancelArgs; + + // Variables for dialogue choice system + private bool m_runChoiceDialogue = false; + private ObjContainer m_dialogChoiceContainer; + private bool m_runCancelEndHandler = false; + private byte m_highlightedChoice = 2; + private bool m_lockControls = false; + + private float m_textScrollSpeed = 0.03f; + + private float m_inputDelayTimer = 0; // The timer that makes sure you can't press inputs too soon. + private bool m_forceMaleDialogue = false; + + private object[] m_stringFormatArgs; + + public DialogueScreen() + { + } + + public override void LoadContent() + { + TextObj dialogText = new TextObj(Game.JunicodeFont); + dialogText.FontSize = 12; + dialogText.Align = Types.TextAlign.Left; + + TextObj dialogSpeakerText = new TextObj(Game.JunicodeFont); + dialogSpeakerText.FontSize = 14; + dialogSpeakerText.Text = "Blacksmith"; + dialogSpeakerText.DropShadow = new Vector2(2, 2); + dialogSpeakerText.TextureColor = new Color(236, 197, 132); + + m_dialogContainer = new ObjContainer("DialogBox_Character"); + //m_dialogContainer.Position = new Vector2(1320 / 2, m_dialogContainer.Height); + m_dialogContainer.Position = new Vector2(1320 / 2, 100); + m_dialogContainer.AddChild(dialogSpeakerText); + m_dialogContainer.ForceDraw = true; + dialogSpeakerText.Position = new Vector2(-m_dialogContainer.Width / 2.2f, -m_dialogContainer.Height / 1.6f); + + m_dialogContainer.AddChild(dialogText); + dialogText.Position = new Vector2(-m_dialogContainer.Width / 2.15f, -m_dialogContainer.Height / 3.5f); + dialogText.Text = "This is a test to see how much text I can fit onto this dialog box without it running out of space. The text " + + "needs to be defined after the dialog text position is set, because the dialogtext width affects the entire width of the dialog container, " + + "which in END."; + dialogText.WordWrap(850); + dialogText.DropShadow = new Vector2(2, 3); + + SpriteObj continueTextIcon = new SpriteObj("ContinueTextIcon_Sprite"); + continueTextIcon.Position = new Vector2(m_dialogContainer.GetChildAt(2).Bounds.Right, m_dialogContainer.GetChildAt(2).Bounds.Bottom); + m_dialogContainer.AddChild(continueTextIcon); + m_dialogContinueIconY = continueTextIcon.Y; + //m_dialogContainer.Scale = Vector2.Zero; + + TextObj choice1Text = new TextObj(Game.JunicodeFont); + choice1Text.FontSize = 12; + choice1Text.Text = "Yes"; + choice1Text.Align = Types.TextAlign.Centre; + TextObj choice2Text = new TextObj(Game.JunicodeFont); + choice2Text.FontSize = 12; + choice2Text.Text = "No"; + choice2Text.Align = Types.TextAlign.Centre; + + m_dialogChoiceContainer = new ObjContainer(); + + SpriteObj statPlate = new SpriteObj("GameOverStatPlate_Sprite"); + m_dialogChoiceContainer.AddChild(statPlate); + SpriteObj choiceHighlight = new SpriteObj("DialogueChoiceHighlight_Sprite"); + m_dialogChoiceContainer.AddChild(choiceHighlight); + m_dialogChoiceContainer.ForceDraw = true; + m_dialogChoiceContainer.Position = new Vector2(1320 / 2, 720/2); + + m_dialogChoiceContainer.AddChild(choice1Text); + choice1Text.Y -= 40; + m_dialogChoiceContainer.AddChild(choice2Text); + choice2Text.Y += 7; + choiceHighlight.Position = new Vector2(choice1Text.X, choice1Text.Y + choiceHighlight.Height / 2 + 3); + m_dialogChoiceContainer.Scale = Vector2.Zero; + m_dialogChoiceContainer.Visible = false; + + base.LoadContent(); + } + + public void SetDialogue(string dialogueObjName) + { + m_dialogueObjName = dialogueObjName; + + m_forceMaleDialogue = false; + //if (dialogueObjName == "Meet Blacksmith" || dialogueObjName.Contains("DiaryEntry")) + if (dialogueObjName.Contains("DiaryEntry")) + m_forceMaleDialogue = true; + + m_confirmMethodObj = null; + m_confirmMethodInfo = null; + if (m_confirmArgs != null) + Array.Clear(m_confirmArgs, 0, m_confirmArgs.Length); + + m_cancelMethodObj = null; + m_cancelMethodInfo = null; + if (m_cancelArgs != null) + Array.Clear(m_cancelArgs, 0, m_cancelArgs.Length); + + if (m_stringFormatArgs != null) + Array.Clear(m_stringFormatArgs, 0, m_stringFormatArgs.Length); + m_stringFormatArgs = null; + } + + public void SetDialogue(string dialogueObjName, params object[] args) + { + SetDialogue(dialogueObjName); + m_stringFormatArgs = args; // Must be called after SetDialogue(string). + } + + public void SetConfirmEndHandler(object methodObject, string functionName, params object[] args) + { + m_confirmMethodObj = methodObject; + m_confirmMethodInfo = methodObject.GetType().GetMethod(functionName); + m_confirmArgs = args; + } + + public void SetConfirmEndHandler(Type methodType, string functionName, params object[] args) + { + Type[] argList = new Type[args.Length]; + for (int i = 0; i < args.Length; i++) + argList[i] = args[i].GetType(); + + m_confirmMethodInfo = methodType.GetMethod(functionName, argList); + m_confirmArgs = args; + + if (m_confirmMethodInfo == null) + { + m_confirmMethodInfo = methodType.GetMethod(functionName, new Type[] { args[0].GetType().MakeArrayType() }); + m_confirmArgs = new object[1]; + m_confirmArgs[0] = args; + } + + m_confirmMethodObj = null; + } + + public void SetCancelEndHandler(object methodObject, string functionName, params object[] args) + { + m_cancelMethodObj = methodObject; + m_cancelMethodInfo = methodObject.GetType().GetMethod(functionName); + m_cancelArgs = args; + } + + public void SetCancelEndHandler(Type methodType, string functionName, params object[] args) + { + Type[] argList = new Type[args.Length]; + for (int i = 0; i < args.Length; i++) + argList[i] = args[i].GetType(); + + m_cancelMethodInfo = methodType.GetMethod(functionName, argList); + m_cancelArgs = args; + + if (m_cancelMethodInfo == null) + { + m_cancelMethodInfo = methodType.GetMethod(functionName, new Type[] { args[0].GetType().MakeArrayType() }); + m_cancelArgs = new object[1]; + m_cancelArgs[0] = args; + } + + m_cancelMethodObj = null; + } + + public void SetDialogueChoice(string dialogueObjName) + { + DialogueObj choiceDialogue = DialogueManager.GetText(dialogueObjName); + (m_dialogChoiceContainer.GetChildAt(2) as TextObj).Text = LocaleBuilder.getString(choiceDialogue.Speakers[0], m_dialogChoiceContainer.GetChildAt(2) as TextObj); + (m_dialogChoiceContainer.GetChildAt(3) as TextObj).Text = LocaleBuilder.getString(choiceDialogue.Dialogue[0], m_dialogChoiceContainer.GetChildAt(3) as TextObj); + + if (Game.PlayerStats.Traits.X == TraitType.Dyslexia || Game.PlayerStats.Traits.Y == TraitType.Dyslexia) + { + (m_dialogChoiceContainer.GetChildAt(2) as TextObj).RandomizeSentence(false); + (m_dialogChoiceContainer.GetChildAt(3) as TextObj).RandomizeSentence(false); + } + + m_runChoiceDialogue = true; + } + + public override void HandleInput() + { + if (m_lockControls == false && m_inputDelayTimer <= 0) + { + if (m_dialogChoiceContainer.Visible == false) + { + // // Special code in case you start the dialogue with a choice sequence, instead of showing dialogue, pressing confirm, then showing the choice. + // if (m_dialogCounter == m_dialogText.Length - 1 && m_runChoiceDialogue == true) + // { + // SpriteObj continueTextIcon1 = m_dialogContainer.GetChildAt(3) as SpriteObj; + // continueTextIcon1.ChangeSprite("EndTextIcon_Sprite"); + // if (m_runChoiceDialogue == true) + // { + // TextObj dialogueText = (m_dialogContainer.GetChildAt(2) as TextObj); + // dialogueText.StopTypeWriting(true); + // m_dialogChoiceContainer.Visible = true; + // Tweener.Tween.To(m_dialogChoiceContainer, 0.3f, Tweener.Ease.Back.EaseOut, "ScaleX", "1", "ScaleY", "1"); + // } + // } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + if (m_dialogCounter < m_dialogText.Length - 1) + { + TextObj dialogueTitle = (m_dialogContainer.GetChildAt(1) as TextObj); + TextObj dialogueText = (m_dialogContainer.GetChildAt(2) as TextObj); + if (dialogueText.IsTypewriting == false) + { + m_dialogCounter++; + dialogueTitle.Text = LocaleBuilder.getString(m_dialogTitles[m_dialogCounter], dialogueTitle, m_forceMaleDialogue); + if (m_stringFormatArgs != null) + dialogueText.Text = string.Format(LocaleBuilder.getString(m_dialogText[m_dialogCounter], dialogueText, m_forceMaleDialogue), m_stringFormatArgs); + else + dialogueText.Text = LocaleBuilder.getString(m_dialogText[m_dialogCounter], dialogueText, m_forceMaleDialogue); + if (Game.PlayerStats.Traits.X == TraitType.Dyslexia || Game.PlayerStats.Traits.Y == TraitType.Dyslexia) + { + dialogueTitle.RandomizeSentence(false); + dialogueText.RandomizeSentence(false); + } + dialogueText.WordWrap(850); + dialogueText.BeginTypeWriting(m_dialogText[m_dialogCounter].Length * m_textScrollSpeed, "dialogue_tap"); + } + else + dialogueText.StopTypeWriting(true); + } + else + { + if (m_runChoiceDialogue == false && (m_dialogContainer.GetChildAt(2) as TextObj).IsTypewriting == false) + { + m_lockControls = true; + SoundManager.PlaySound("DialogMenuClose"); + + //Tweener.Tween.To(m_dialogContainer, 0.3f, Tweener.Ease.Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + Tweener.Tween.To(m_dialogContainer, 0.3f, Tweener.Ease.Quad.EaseIn, "Opacity", "0", "Y", "0"); + Tweener.Tween.To(this, 0.3f, Tweener.Ease.Linear.EaseNone, "BackBufferOpacity", "0"); + Tweener.Tween.AddEndHandlerToLastTween(this, "ExitScreen"); + } + else + (m_dialogContainer.GetChildAt(2) as TextObj).StopTypeWriting(true); + } + + SpriteObj continueTextIcon = m_dialogContainer.GetChildAt(3) as SpriteObj; + if (m_dialogCounter == m_dialogText.Length - 1) + { + continueTextIcon.ChangeSprite("EndTextIcon_Sprite"); + if (m_runChoiceDialogue == true) + { + TextObj dialogueText = (m_dialogContainer.GetChildAt(2) as TextObj); + dialogueText.StopTypeWriting(true); + m_dialogChoiceContainer.Visible = true; + Tweener.Tween.To(m_dialogChoiceContainer, 0.3f, Tweener.Ease.Back.EaseOut, "ScaleX", "1", "ScaleY", "1"); + SoundManager.PlaySound("DialogOpenBump"); + } + } + else + continueTextIcon.ChangeSprite("ContinueTextIcon_Sprite"); + } + } + else + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN2)) + { + SoundManager.PlaySound("frame_swap"); + m_highlightedChoice++; + if (m_highlightedChoice > 3) + m_highlightedChoice = 2; + m_dialogChoiceContainer.GetChildAt(1).Y = m_dialogChoiceContainer.GetChildAt(m_highlightedChoice).Y + m_dialogChoiceContainer.GetChildAt(1).Height / 2 + 3; + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + SoundManager.PlaySound("frame_swap"); + m_highlightedChoice--; + if (m_highlightedChoice < 2) + m_highlightedChoice = 3; + m_dialogChoiceContainer.GetChildAt(1).Y = m_dialogChoiceContainer.GetChildAt(m_highlightedChoice).Y + m_dialogChoiceContainer.GetChildAt(1).Height / 2 + 3; + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + m_runCancelEndHandler = false; + if (m_highlightedChoice == 3) + { + m_runCancelEndHandler = true; + SoundManager.PlaySound("DialogueMenuCancel"); + } + else + SoundManager.PlaySound("DialogueMenuConfirm"); + + m_lockControls = true; + SoundManager.PlaySound("DialogMenuClose"); + + //Tweener.Tween.To(m_dialogContainer, 0.3f, Tweener.Ease.Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + Tweener.Tween.To(m_dialogContainer, 0.3f, Tweener.Ease.Quad.EaseInOut, "Opacity", "0", "Y", "100"); + Tweener.Tween.To(this, 0.3f, Tweener.Ease.Linear.EaseNone, "BackBufferOpacity", "0"); + Tweener.Tween.To(m_dialogChoiceContainer, 0.3f, Tweener.Ease.Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + Tweener.Tween.AddEndHandlerToLastTween(this, "ExitScreen"); + } + else if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + m_highlightedChoice = 3; + m_dialogChoiceContainer.GetChildAt(1).Y = m_dialogChoiceContainer.GetChildAt(m_highlightedChoice).Y + m_dialogChoiceContainer.GetChildAt(1).Height / 2 + 3; + m_runCancelEndHandler = true; + SoundManager.PlaySound("DialogueMenuCancel"); + + m_lockControls = true; + SoundManager.PlaySound("DialogMenuClose"); + + //Tweener.Tween.To(m_dialogContainer, 0.3f, Tweener.Ease.Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + Tweener.Tween.To(m_dialogContainer, 0.3f, Tweener.Ease.Quad.EaseInOut, "Opacity", "0", "Y", "100"); + Tweener.Tween.To(this, 0.3f, Tweener.Ease.Linear.EaseNone, "BackBufferOpacity", "0"); + Tweener.Tween.To(m_dialogChoiceContainer, 0.3f, Tweener.Ease.Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + Tweener.Tween.AddEndHandlerToLastTween(this, "ExitScreen"); + } + } + } + + base.HandleInput(); + } + + public override void Update(GameTime gameTime) + { + if (m_inputDelayTimer > 0) + m_inputDelayTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds; + + if (m_dialogChoiceContainer.Visible == false) + { + // Special code in case you start the dialogue with a choice sequence, instead of showing dialogue, pressing confirm, then showing the choice. + if (m_dialogCounter == m_dialogText.Length - 1 && m_runChoiceDialogue == true) + { + SpriteObj continueTextIcon1 = m_dialogContainer.GetChildAt(3) as SpriteObj; + continueTextIcon1.ChangeSprite("EndTextIcon_Sprite"); + if (m_runChoiceDialogue == true) + { + //SoundManager.PlaySound("DialogOpenBump"); + TextObj dialogueText = (m_dialogContainer.GetChildAt(2) as TextObj); + dialogueText.StopTypeWriting(true); + m_dialogChoiceContainer.Visible = true; + Tweener.Tween.To(m_dialogChoiceContainer, 0.3f, Tweener.Ease.Back.EaseOut, "ScaleX", "1", "ScaleY", "1"); + Tweener.Tween.RunFunction(0.1f, typeof(SoundManager), "PlaySound", "DialogOpenBump"); + } + } + } + + base.Update(gameTime); + } + + public override void Draw(GameTime gameTime) + { + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearWrap, null, null); + Camera.Draw(Game.GenericTexture, new Rectangle(0, 0, 1320, 720), Color.Black * BackBufferOpacity); + m_dialogContainer.Draw(Camera); + if (m_dialogContainer.ScaleX > 0) + m_dialogContainer.GetChildAt(3).Y = m_dialogContinueIconY + (float)Math.Sin(Game.TotalGameTime * 20) * 2; + + m_dialogChoiceContainer.Draw(Camera); + Camera.End(); + base.Draw(gameTime); + } + + public override void OnEnter() + { + m_inputDelayTimer = 0.5f; + + //SoundManager.PlaySound("DialogueMenuOpen"); + SoundManager.PlaySound("DialogOpen"); + m_lockControls = false; + m_runCancelEndHandler = false; + m_highlightedChoice = 2; // 2 == Confirm. 3 == Cancel + m_dialogChoiceContainer.Scale = new Vector2(1, 1); + m_dialogChoiceContainer.GetChildAt(1).Y = m_dialogChoiceContainer.GetChildAt(m_highlightedChoice).Y + m_dialogChoiceContainer.GetChildAt(1).Height / 2 + 3; + m_dialogChoiceContainer.Scale = Vector2.Zero; + + DialogueObj dialogueObj = DialogueManager.GetText(m_dialogueObjName); + string[] names = dialogueObj.Speakers; + string[] text = dialogueObj.Dialogue; + SpriteObj continueTextIcon = m_dialogContainer.GetChildAt(3) as SpriteObj; + if (text.Length > 1) + continueTextIcon.ChangeSprite("ContinueTextIcon_Sprite"); + else + continueTextIcon.ChangeSprite("EndTextIcon_Sprite"); + + m_dialogCounter = 0; + m_dialogTitles = names; + m_dialogText = text; + + m_dialogContainer.Scale = Vector2.One; + m_dialogContainer.Opacity = 0; + //m_dialogContainer.Y -= 100; + + if (m_stringFormatArgs != null) + (m_dialogContainer.GetChildAt(2) as TextObj).Text = string.Format(LocaleBuilder.getString(text[m_dialogCounter], m_dialogContainer.GetChildAt(2) as TextObj, m_forceMaleDialogue), m_stringFormatArgs); + else + (m_dialogContainer.GetChildAt(2) as TextObj).Text = LocaleBuilder.getString(text[m_dialogCounter], m_dialogContainer.GetChildAt(2) as TextObj, m_forceMaleDialogue); + (m_dialogContainer.GetChildAt(2) as TextObj).WordWrap(850); + (m_dialogContainer.GetChildAt(1) as TextObj).Text = LocaleBuilder.getString(names[m_dialogCounter], m_dialogContainer.GetChildAt(1) as TextObj, m_forceMaleDialogue); + if (Game.PlayerStats.Traits.X == TraitType.Dyslexia || Game.PlayerStats.Traits.Y == TraitType.Dyslexia) + { + (m_dialogContainer.GetChildAt(2) as TextObj).RandomizeSentence(false); + (m_dialogContainer.GetChildAt(1) as TextObj).RandomizeSentence(false); + } + (m_dialogContainer.GetChildAt(2) as TextObj).BeginTypeWriting(text[m_dialogCounter].Length * m_textScrollSpeed, "dialogue_tap"); + + Tweener.Tween.To(m_dialogContainer, 0.3f, Tweener.Ease.Quad.EaseInOut, "Opacity", "1", "Y", "150"); + Tweener.Tween.To(this, 0.3f, Tweener.Ease.Linear.EaseNone, "BackBufferOpacity", "0.5"); + + base.OnEnter(); + } + + public void ExitScreen() + { + // All this needs to be set BEFORE you call the end handler. + (ScreenManager as RCScreenManager).HideCurrentScreen(); + m_runChoiceDialogue = false; + m_dialogChoiceContainer.Visible = false; + m_dialogChoiceContainer.Scale = Vector2.Zero; + + if (m_runCancelEndHandler == false) + { + if (m_confirmMethodInfo != null) + m_confirmMethodInfo.Invoke(m_confirmMethodObj, m_confirmArgs); + } + else + { + if (m_cancelMethodInfo != null) + m_cancelMethodInfo.Invoke(m_cancelMethodObj, m_cancelArgs); + } + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Dialogue Screen"); + + m_confirmMethodObj = null; + m_confirmMethodInfo = null; + if (m_confirmArgs != null) + Array.Clear(m_confirmArgs, 0, m_confirmArgs.Length); + m_confirmArgs = null; + + m_cancelMethodObj = null; + m_cancelMethodInfo = null; + if (m_cancelArgs != null) + Array.Clear(m_cancelArgs, 0, m_cancelArgs.Length); + m_cancelArgs = null; + + m_dialogContainer.Dispose(); + m_dialogContainer = null; + m_dialogChoiceContainer.Dispose(); + m_dialogChoiceContainer = null; + + //if (m_dialogText != null) + // Array.Clear(m_dialogText, 0, m_dialogText.Length); + m_dialogText = null; + //if (m_dialogTitles != null) + // Array.Clear(m_dialogTitles, 0, m_dialogTitles.Length); + m_dialogTitles = null; + + if (m_stringFormatArgs != null) + Array.Clear(m_stringFormatArgs, 0, m_stringFormatArgs.Length); + m_stringFormatArgs = null; + base.Dispose(); + } + } + + public override void RefreshTextObjs() + { + // need to manually reapply word wrap since TextObj.Text assignment doesn't do it + if (m_dialogContainer != null && m_dialogContainer.GetChildAt(2) != null) + (m_dialogContainer.GetChildAt(2) as TextObj).WordWrap(850); + + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Screens/DiaryEntryScreen.cs b/RogueCastle/src/Screens/DiaryEntryScreen.cs new file mode 100644 index 0000000..ee0a8cb --- /dev/null +++ b/RogueCastle/src/Screens/DiaryEntryScreen.cs @@ -0,0 +1,319 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using System.IO; +using System.Globalization; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class DiaryEntryScreen : Screen + { + public float BackBufferOpacity { get; set; } + + private SpriteObj m_titleText; + private List m_diaryList; + private int m_entryIndex = 0; + private int m_entryRow = 0; + private ObjContainer m_selectedEntry; + private int m_unlockedEntries = 0; + private float m_inputDelay = 0; + + public DiaryEntryScreen() + { + m_diaryList = new List(); + this.DrawIfCovered = true; + } + + public override void LoadContent() + { + // Loading Teleporter objects. + m_titleText = new SpriteObj("DiaryEntryTitleText_Sprite"); + m_titleText.ForceDraw = true; + m_titleText.X = GlobalEV.ScreenWidth / 2; + m_titleText.Y = GlobalEV.ScreenHeight * 0.1f; + + int startingX = 260;//250;//350; + int startingY = 150; + int xPosition = startingX; + int yPosition = startingY; + int yOffset = 100; + int xOffset = 200; + int xChange = 5;//4; + int xCounter = 0; + for (int i = 0; i < LevelEV.TOTAL_JOURNAL_ENTRIES; i++) //TEDDY CHANGING i< 20 to the LEVELEV.Journals THINGAMABOB + { + ObjContainer entry = new ObjContainer("DialogBox_Character"); + entry.ForceDraw = true; + entry.Scale = new Vector2(180f / entry.Width, 50f / entry.Height); + entry.Position = new Vector2(xPosition, yPosition); + + TextObj entryTitle = new TextObj(Game.JunicodeFont); + switch (LocaleBuilder.languageType) + { + case(LanguageType.Russian): + case(LanguageType.Polish): + entryTitle.Text = LocaleBuilder.getString("LOC_ID_DIARY_ENTRY_SCREEN_1", entryTitle) /*"Entry #"*/ + " " + (i + 1); + break; + default: + entryTitle.Text = LocaleBuilder.getString("LOC_ID_DIARY_ENTRY_SCREEN_1", entryTitle) /*"Entry #"*/ + (i + 1); + break; + } + entryTitle.OverrideParentScale = true; + entryTitle.OutlineWidth = 2; + entryTitle.FontSize = 12; + entryTitle.Y -= 64; + entryTitle.Align = Types.TextAlign.Centre; + + entry.AddChild(entryTitle); + m_diaryList.Add(entry); + + xCounter++; + xPosition += xOffset; + if (xCounter >= xChange) + { + xCounter = 0; + xPosition = startingX; + yPosition += yOffset; + } + + if (i > 13) entry.Visible = false; + } + + base.LoadContent(); + } + + public override void OnEnter() + { + // First refresh text + RefreshTextObjs(); + + SoundManager.PlaySound("DialogOpen"); + + m_inputDelay = 0.5f; + m_entryRow = 1; + m_entryIndex = 0; + UpdateSelection(); + m_unlockedEntries = Game.PlayerStats.DiaryEntry; + if (LevelEV.UNLOCK_ALL_DIARY_ENTRIES == true) + m_unlockedEntries = LevelEV.TOTAL_JOURNAL_ENTRIES - 1; + + if (m_unlockedEntries >= LevelEV.TOTAL_JOURNAL_ENTRIES - 1) + GameUtil.UnlockAchievement("LOVE_OF_BOOKS"); + + for (int i = 0; i < m_diaryList.Count; i++) + { + if (i < m_unlockedEntries) + m_diaryList[i].Visible = true; + else + m_diaryList[i].Visible = false; + } + + BackBufferOpacity = 0; + Tween.To(this, 0.2f, Tween.EaseNone, "BackBufferOpacity", "0.7"); + + m_titleText.Opacity = 0; + Tween.To(m_titleText, 0.25f, Tween.EaseNone, "Opacity", "1"); + + // Fade in effect. + int delayCounter = 0; + float delay = 0; + foreach (ObjContainer diary in m_diaryList) + { + if (diary.Visible == true) + { + diary.Opacity = 0; + + if (delayCounter >= 5) + { + delayCounter = 0; + delay += 0.05f; + } + delayCounter++; + Tween.To(diary, 0.25f, Tween.EaseNone, "delay", delay.ToString(), "Opacity", "1"); + Tween.By(diary, 0.25f, Quad.EaseOut, "delay", delay.ToString(), "Y", "50"); + } + } + + base.OnEnter(); + } + + private void ExitTransition() + { + SoundManager.PlaySound("DialogMenuClose"); + + int delayCounter = 0; + float delay = 0; + foreach (ObjContainer diary in m_diaryList) + { + if (diary.Visible == true) + { + diary.Opacity = 1; + + if (delayCounter >= 5) + { + delayCounter = 0; + delay += 0.05f; + } + delayCounter++; + Tween.To(diary, 0.25f, Tween.EaseNone, "delay", delay.ToString(), "Opacity", "0"); + Tween.By(diary, 0.25f, Quad.EaseOut, "delay", delay.ToString(), "Y", "-50"); + } + } + + m_titleText.Opacity = 1; + Tween.To(m_titleText, 0.25f, Tween.EaseNone, "Opacity", "0"); + + m_inputDelay = 1f; + Tween.To(this, 0.5f, Tween.EaseNone, "BackBufferOpacity", "0"); + Tween.AddEndHandlerToLastTween(ScreenManager, "HideCurrentScreen"); + } + + public override void HandleInput() + { + if (m_inputDelay <= 0) + { + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + DisplayEntry(); + else if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + ExitTransition(); + + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT2)) + { + if (m_entryIndex > 0 && m_diaryList[m_entryIndex - 1].Visible == true) + { + SoundManager.PlaySound("frame_swap"); + m_entryIndex--; + } + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT2)) + { + if (m_entryIndex < m_diaryList.Count - 1 && m_diaryList[m_entryIndex + 1].Visible == true) + { + m_entryIndex++; + SoundManager.PlaySound("frame_swap"); + } + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + if (m_entryRow > 1 && m_diaryList[m_entryIndex - 5].Visible == true) + { + m_entryRow--; + m_entryIndex -= 5; + SoundManager.PlaySound("frame_swap"); + } + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN2)) + { + if (m_entryRow < 5 && m_diaryList[m_entryIndex + 5].Visible == true) + { + m_entryRow++; + m_entryIndex += 5; + SoundManager.PlaySound("frame_swap"); + } + } + + if (m_entryRow > 5) + m_entryRow = 5; + if (m_entryRow < 1) + m_entryRow = 1; + + if (m_entryIndex >= m_entryRow * 5) + m_entryIndex = m_entryRow * 5 - 1; + if (m_entryIndex < m_entryRow * 5 - 5) + m_entryIndex = m_entryRow * 5 - 5; + + UpdateSelection(); + + base.HandleInput(); + } + } + + private void DisplayEntry() + { + RCScreenManager manager = ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("DiaryEntry" + m_entryIndex); + manager.DisplayScreen(ScreenType.Dialogue, true); + } + + private void UpdateSelection() + { + if (m_selectedEntry != null) + m_selectedEntry.TextureColor = Color.White; + + m_selectedEntry = m_diaryList[m_entryIndex]; + m_selectedEntry.TextureColor = Color.Yellow; + } + + public override void Update(GameTime gameTime) + { + if (m_inputDelay > 0) + m_inputDelay -= (float)gameTime.ElapsedGameTime.TotalSeconds; + base.Update(gameTime); + } + + public override void Draw(GameTime gametime) + { + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null); + Camera.Draw(Game.GenericTexture, new Rectangle(0, 0, GlobalEV.ScreenWidth, GlobalEV.ScreenHeight), Color.Black * BackBufferOpacity); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + + m_titleText.Draw(Camera); + foreach (ObjContainer obj in m_diaryList) + obj.Draw(Camera); + + Camera.End(); + base.Draw(gametime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Diary Entry Screen"); + + foreach (ObjContainer obj in m_diaryList) + obj.Dispose(); + m_diaryList.Clear(); + m_diaryList = null; + m_selectedEntry = null; + + m_titleText.Dispose(); + m_titleText = null; + base.Dispose(); + } + } + + public override void RefreshTextObjs() + { + int i = 0; + foreach (ObjContainer obj in m_diaryList) + { + if (obj.GetChildAt(obj.NumChildren - 1) is TextObj) + { + switch (LocaleBuilder.languageType) + { + case (LanguageType.Russian): + case (LanguageType.Polish): + (obj.GetChildAt(obj.NumChildren - 1) as TextObj).Text = LocaleBuilder.getResourceString("LOC_ID_DIARY_ENTRY_SCREEN_1") /*"Entry #"*/ + " " + (i + 1); + break; + default: + (obj.GetChildAt(obj.NumChildren - 1) as TextObj).Text = LocaleBuilder.getResourceString("LOC_ID_DIARY_ENTRY_SCREEN_1") /*"Entry #"*/ + (i + 1); + break; + } + } + i++; + } + + Game.ChangeBitmapLanguage(m_titleText, "DiaryEntryTitleText_Sprite"); + + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Screens/DiaryFlashbackScreen.cs b/RogueCastle/src/Screens/DiaryFlashbackScreen.cs new file mode 100644 index 0000000..7a20f32 --- /dev/null +++ b/RogueCastle/src/Screens/DiaryFlashbackScreen.cs @@ -0,0 +1,296 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Tweener; +using Tweener.Ease; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + class DiaryFlashbackScreen : Screen + { + + private BackgroundObj m_background; + private List m_lineageArray; + private Vector2 m_storedCameraPos; + private RenderTarget2D m_sepiaRT; + private SpriteObj m_filmGrain; + + public float BackBufferOpacity { get; set; } + + public DiaryFlashbackScreen() + { + m_lineageArray = new List(); + } + + public override void LoadContent() + { + m_filmGrain = new SpriteObj("FilmGrain_Sprite"); + m_filmGrain.ForceDraw = true; + m_filmGrain.Scale = new Vector2(2.015f, 2.05f); + m_filmGrain.X -= 5; + m_filmGrain.Y -= 5; + m_filmGrain.PlayAnimation(true); + m_filmGrain.AnimationDelay = 1 / 30f; + + base.LoadContent(); + } + + public override void ReinitializeRTs() + { + m_sepiaRT = new RenderTarget2D(Camera.GraphicsDevice, 1320, 720, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + if (m_background != null) + m_background.Dispose(); + m_background = new BackgroundObj("LineageScreenBG_Sprite"); + m_background.SetRepeated(true, true, Camera); + m_background.X -= 1320 * 5; + base.ReinitializeRTs(); + } + + public override void OnEnter() + { + GameUtil.UnlockAchievement("LOVE_OF_BOOKS"); + + BackBufferOpacity = 0; + Tween.To(this, 0.05f, Tween.EaseNone, "BackBufferOpacity", "1"); + BackBufferOpacity = 1; + Tween.To(this, 1, Tween.EaseNone, "delay", "0.1", "BackBufferOpacity", "0"); + BackBufferOpacity = 0; + + m_storedCameraPos = Camera.Position; + Camera.Position = Vector2.Zero; + + // Yet another hack. Can't put this in LoadContent because Camera isn't assigned at that time. + if (m_background == null) + { + m_sepiaRT = new RenderTarget2D(Camera.GraphicsDevice, 1320, 720, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + m_background = new BackgroundObj("LineageScreenBG_Sprite"); + m_background.SetRepeated(true, true, Camera); + m_background.X -= 1320 * 5; + } + + //CreateLineageObjs(); + CreateLineageObjDebug(); + Camera.X = m_lineageArray[m_lineageArray.Count - 1].X; + SoundManager.PlaySound("Cutsc_Thunder"); + Tween.RunFunction(1, this, "Cutscene1"); + + base.OnEnter(); + } + + public void Cutscene1() + { + SoundManager.PlaySound("Cutsc_PictureMove"); + Tween.To(Camera, m_lineageArray.Count * 0.2f, Quad.EaseInOut, "X", m_lineageArray[0].X.ToString()); + Tween.AddEndHandlerToLastTween(this, "Cutscene2"); + } + + public void Cutscene2() + { + LineageObj frame = m_lineageArray[0]; + frame.ForceDraw = true; + Tween.RunFunction(1, frame, "DropFrame"); + Tween.RunFunction(4.5f, this, "ExitTransition"); + } + + public void ExitTransition() + { + SoundManager.PlaySound("Cutsc_Picture_Break"); + Tween.To(this, 0.05f, Tween.EaseNone, "BackBufferOpacity", "1"); + Tween.RunFunction(0.1f, ScreenManager, "HideCurrentScreen"); + } + + public override void OnExit() + { + foreach (LineageObj obj in m_lineageArray) + obj.Dispose(); + m_lineageArray.Clear(); + Camera.Position = m_storedCameraPos; + base.OnExit(); + } + + private void CreateLineageObjs() + { + int currentEra = GameEV.BASE_ERA; + int xPosOffset = 400; + int xPos = 0; + + if (Game.PlayerStats.FamilyTreeArray.Count > 10) + { + for (int i = 0; i < 10; i++) + { + FamilyTreeNode treeData = Game.PlayerStats.FamilyTreeArray[i]; + + LineageObj lineageObj = new LineageObj(null, true); + lineageObj.IsDead = true; + lineageObj.Age = treeData.Age; + lineageObj.ChildAge = treeData.ChildAge; + lineageObj.Class = treeData.Class; + lineageObj.RomanNumeral = treeData.RomanNumeral; + lineageObj.IsFemale = treeData.IsFemale; + lineageObj.PlayerName = treeData.Name; + lineageObj.SetPortrait(treeData.HeadPiece, treeData.ShoulderPiece, treeData.ChestPiece); + lineageObj.NumEnemiesKilled = treeData.NumEnemiesBeaten; + lineageObj.BeatenABoss = treeData.BeatenABoss; + lineageObj.SetTraits(treeData.Traits); + lineageObj.UpdateAge(currentEra); + lineageObj.UpdateData(); + lineageObj.UpdateClassRank(); + currentEra = currentEra + lineageObj.Age; + + lineageObj.X = xPos; + xPos += xPosOffset; + + m_lineageArray.Add(lineageObj); + } + } + else + { + foreach (FamilyTreeNode treeData in Game.PlayerStats.FamilyTreeArray) + { + LineageObj lineageObj = new LineageObj(null, true); + lineageObj.IsDead = true; + lineageObj.Age = treeData.Age; + lineageObj.ChildAge = treeData.ChildAge; + lineageObj.Class = treeData.Class; + lineageObj.IsFemale = treeData.IsFemale; + lineageObj.RomanNumeral = treeData.RomanNumeral; + lineageObj.PlayerName = treeData.Name; + lineageObj.SetPortrait(treeData.HeadPiece, treeData.ShoulderPiece, treeData.ChestPiece); + lineageObj.NumEnemiesKilled = treeData.NumEnemiesBeaten; + lineageObj.BeatenABoss = treeData.BeatenABoss; + lineageObj.SetTraits(treeData.Traits); + lineageObj.UpdateAge(currentEra); + lineageObj.UpdateData(); + lineageObj.UpdateClassRank(); + currentEra = currentEra + lineageObj.Age; + + lineageObj.X = xPos; + xPos += xPosOffset; + + m_lineageArray.Add(lineageObj); + } + } + } + + private void CreateLineageObjDebug() + { + int currentEra = GameEV.BASE_ERA; + int xPosOffset = 400; + int xPos = 0; + + for (int i = 0; i < 10; i++) + { + FamilyTreeNode treeData; + + if (i > Game.PlayerStats.FamilyTreeArray.Count - 1) + { + treeData = new FamilyTreeNode() + { + Age = (byte)CDGMath.RandomInt(15, 30), + ChildAge = (byte)CDGMath.RandomInt(15, 30), + Name = Game.NameArray[CDGMath.RandomInt(0, Game.NameArray.Count - 1)], + HeadPiece = (byte)CDGMath.RandomInt(1, 5), + ShoulderPiece = (byte)CDGMath.RandomInt(1, 5), + ChestPiece = (byte)CDGMath.RandomInt(1, 5), + }; + } + else + treeData = Game.PlayerStats.FamilyTreeArray[i]; + + LineageObj lineageObj = new LineageObj(null, true); + lineageObj.IsDead = true; + lineageObj.Age = treeData.Age; + lineageObj.ChildAge = treeData.ChildAge; + lineageObj.Class = treeData.Class; + lineageObj.RomanNumeral = treeData.RomanNumeral; + lineageObj.IsFemale = treeData.IsFemale; + lineageObj.PlayerName = treeData.Name; + lineageObj.SetPortrait(treeData.HeadPiece, treeData.ShoulderPiece, treeData.ChestPiece); + lineageObj.NumEnemiesKilled = treeData.NumEnemiesBeaten; + lineageObj.BeatenABoss = treeData.BeatenABoss; + lineageObj.SetTraits(treeData.Traits); + lineageObj.UpdateAge(currentEra); + lineageObj.UpdateData(); + lineageObj.UpdateClassRank(); + currentEra = currentEra + lineageObj.Age; + + lineageObj.X = xPos; + xPos += xPosOffset; + + m_lineageArray.Add(lineageObj); + } + } + + public override void Draw(GameTime gametime) + { + // Hack to make an infinite scroll. + if (Camera.X > m_background.X + 1320 * 5) + m_background.X = Camera.X; + if (Camera.X < m_background.X) + m_background.X = Camera.X - 1320; + + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearWrap, null, null, null, Camera.GetTransformation()); + m_background.Draw(Camera); + foreach (LineageObj obj in m_lineageArray) + obj.Draw(Camera); + Camera.End(); + + Camera.GraphicsDevice.SetRenderTarget(m_sepiaRT); + Game.HSVEffect.Parameters["Saturation"].SetValue(0.2f); + Game.HSVEffect.Parameters["Brightness"].SetValue(0.1f); + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, Game.HSVEffect); + Camera.Draw((ScreenManager as RCScreenManager).RenderTarget, Vector2.Zero, Color.White); + Camera.End(); + + Camera.GraphicsDevice.SetRenderTarget((ScreenManager as RCScreenManager).RenderTarget); + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null); + Color sepia = new Color(180, 150, 80); + Camera.Draw(m_sepiaRT, Vector2.Zero, sepia); + + m_filmGrain.Draw(Camera); + Camera.End(); + + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null); + Camera.Draw(Game.GenericTexture, new Rectangle(0, 0, 1320, 720), Color.White * BackBufferOpacity); + Camera.End(); + + + base.Draw(gametime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Diary Flashback Screen"); + + if (m_background != null) + m_background.Dispose(); + m_background = null; + foreach (LineageObj obj in m_lineageArray) + obj.Dispose(); + m_lineageArray.Clear(); + m_lineageArray = null; + m_filmGrain.Dispose(); + m_filmGrain = null; + if (m_sepiaRT != null) + m_sepiaRT.Dispose(); + m_sepiaRT = null; + base.Dispose(); + } + } + + public override void RefreshTextObjs() + { + foreach (LineageObj obj in m_lineageArray) + { + obj.RefreshTextObjs(); + } + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Screens/EnchantressScreen.cs b/RogueCastle/src/Screens/EnchantressScreen.cs new file mode 100644 index 0000000..7eaff30 --- /dev/null +++ b/RogueCastle/src/Screens/EnchantressScreen.cs @@ -0,0 +1,857 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using DS2DEngine; +using Tweener; +using Tweener.Ease; +using InputSystem; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Audio; + +namespace RogueCastle +{ + public class EnchantressScreen : Screen + { + private const int m_startingCategoryIndex = 6; + + private ObjContainer m_enchantressUI; + private SpriteObj m_selectionIcon; + public float BackBufferOpacity { get; set; } + private int m_currentCategoryIndex = 0; + private int m_currentEquipmentIndex = 0; + + private List m_masterIconArray; + private SpriteObj[] m_activeIconArray; + + private List m_newIconList; + private int m_newIconListIndex; + private TextObj m_playerMoney; + + private SpriteObj m_equippedIcon; + + // Text objects + private TextObj m_equipmentDescriptionText; + private TextObj m_descriptionText; + private ObjContainer m_unlockCostContainer; + private TextObj m_instructionsTitleText; + private KeyIconTextObj m_instructionsText; + + private TextObj m_equipmentTitleText; // The actual title of the currently selected piece of equipment. + + private bool m_inCategoryMenu = true; + + public PlayerObj Player { get; set; } + + private bool m_lockControls = false; + + private KeyIconTextObj m_confirmText; + private KeyIconTextObj m_cancelText; + private KeyIconTextObj m_navigationText; + + private Cue m_rainSound; + + public EnchantressScreen() + { + m_currentCategoryIndex = m_startingCategoryIndex; + + m_masterIconArray = new List(); + for (int i = 0; i < EquipmentCategoryType.Total; i++) + { + m_masterIconArray.Add(new SpriteObj[EquipmentAbilityType.Total]); + } + + } + + public override void LoadContent() + { + m_enchantressUI = new ObjContainer("BlacksmithUI_Character"); + m_enchantressUI.Position = new Vector2(1320 / 2, 720 / 2); + + m_playerMoney = new TextObj(Game.GoldFont); + m_playerMoney.Align = Types.TextAlign.Left; + m_playerMoney.Text = "1000"; + m_playerMoney.FontSize = 30; + m_playerMoney.OverrideParentScale = true; + m_playerMoney.Position = new Vector2(210, -225); + m_playerMoney.AnchorY = 10; + m_enchantressUI.AddChild(m_playerMoney); + + // Changing the title text from "The Blacksmith" to "The Enchantress". + m_enchantressUI.GetChildAt(m_enchantressUI.NumChildren - 3).ChangeSprite("EnchantressUI_Title_Sprite"); + + for (int i = 0; i < m_enchantressUI.NumChildren; i++) + m_enchantressUI.GetChildAt(i).Scale = Vector2.Zero; + + m_selectionIcon = new SpriteObj("BlacksmithUI_SelectionIcon_Sprite"); + m_selectionIcon.PlayAnimation(true); + m_selectionIcon.Scale = Vector2.Zero; + m_selectionIcon.AnimationDelay = 1 / 10f; + m_selectionIcon.ForceDraw = true; + + m_equipmentDescriptionText = new TextObj(Game.JunicodeFont); + m_equipmentDescriptionText.Align = Types.TextAlign.Centre; + m_equipmentDescriptionText.FontSize = 12; + m_equipmentDescriptionText.Position = new Vector2(230, -20); + m_equipmentDescriptionText.Text = LocaleBuilder.getString("LOC_ID_ENCHANTRESS_SCREEN_1", m_equipmentDescriptionText); //"Select a category" + m_equipmentDescriptionText.WordWrap(190); + m_equipmentDescriptionText.Scale = Vector2.Zero; + m_enchantressUI.AddChild(m_equipmentDescriptionText); + + foreach (SpriteObj[] iconArray in m_masterIconArray) + { + Vector2 initialPosition = m_enchantressUI.GetChildAt(m_startingCategoryIndex).AbsPosition; + initialPosition.X += 85; + float startingX = initialPosition.X; + float iconXOffset = 70; + float iconYOffset = 80; + + for (int i = 0; i < iconArray.Length; i++) + { + iconArray[i] = new SpriteObj("BlacksmithUI_QuestionMarkIcon_Sprite"); + iconArray[i].Position = initialPosition; + iconArray[i].Scale = Vector2.Zero; + iconArray[i].ForceDraw = true; + + initialPosition.X += iconXOffset; + if (initialPosition.X > startingX + (iconXOffset * 4)) + { + initialPosition.X = startingX; + initialPosition.Y += iconYOffset; + } + } + } + + InitializeTextObjs(); + + m_equippedIcon = new SpriteObj("BlacksmithUI_EquippedIcon_Sprite"); + + m_confirmText = new KeyIconTextObj(Game.JunicodeFont); + m_confirmText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_confirmText); // dummy locID to add TextObj to language refresh list + m_confirmText.FontSize = 12; + m_confirmText.Position = new Vector2(50, 550); + m_confirmText.ForceDraw = true; + + m_cancelText = new KeyIconTextObj(Game.JunicodeFont); + m_cancelText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_cancelText); // dummy locID to add TextObj to language refresh list + m_cancelText.FontSize = 12; + m_cancelText.Position = new Vector2(m_confirmText.X, m_confirmText.Y + 40); + m_cancelText.ForceDraw = true; + + m_navigationText = new KeyIconTextObj(Game.JunicodeFont); + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_navigationText); // dummy locID to add TextObj to language refresh list + m_navigationText.FontSize = 12; + m_navigationText.Position = new Vector2(m_confirmText.X, m_confirmText.Y + 80); + m_navigationText.ForceDraw = true; + + m_newIconList = new List(); + for (int i = 0; i < EquipmentAbilityType.Total * 5; i++) + { + SpriteObj newIcon = new SpriteObj("BlacksmithUI_NewIcon_Sprite"); + newIcon.Visible = false; + newIcon.Scale = new Vector2(1.1f, 1.1f); + m_newIconList.Add(newIcon); + } + + base.LoadContent(); + } + + private void InitializeTextObjs() + { + m_descriptionText = new TextObj(Game.JunicodeFont); + m_descriptionText.FontSize = 9; + m_descriptionText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_descriptionText); // dummy locID to add TextObj to language refresh list + //m_descriptionText.DropShadow = new Vector2(2, 2); + + m_instructionsTitleText = new TextObj(); + m_instructionsTitleText.Font = Game.JunicodeFont; + m_instructionsTitleText.FontSize = 10; + m_instructionsTitleText.TextureColor = new Color(237, 202, 138); + m_instructionsTitleText.Text = LocaleBuilder.getString("LOC_ID_ENCHANTRESS_SCREEN_5", m_instructionsTitleText) + ":"; //"Instructions:" + + m_instructionsText = new KeyIconTextObj(); + m_instructionsText.Font = Game.JunicodeFont; + m_instructionsText.FontSize = 10; + m_instructionsText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_instructionsText); // dummy locID to add TextObj to language refresh list + + m_unlockCostContainer = new ObjContainer(); + TextObj coinText = new TextObj(); + coinText.Font = Game.JunicodeFont; + coinText.FontSize = 10; + coinText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", coinText); // dummy locID to add TextObj to language refresh list + coinText.TextureColor = Color.Yellow; + coinText.Position = new Vector2(50, 9); + m_unlockCostContainer.AddChild(new SpriteObj("BlacksmithUI_CoinBG_Sprite")); + m_unlockCostContainer.AddChild(coinText); + + m_descriptionText.Position = new Vector2(m_enchantressUI.X + 140, m_enchantressUI.Y - m_enchantressUI.Height / 2 + 20 + 40); + m_instructionsTitleText.Position = new Vector2(m_enchantressUI.X + 140, m_descriptionText.Bounds.Bottom + 20); + m_instructionsText.Position = new Vector2(m_instructionsTitleText.X, m_instructionsTitleText.Bounds.Bottom); + m_unlockCostContainer.Position = new Vector2(m_enchantressUI.X + 114, 485); + + m_equipmentTitleText = new TextObj(Game.JunicodeFont); + m_equipmentTitleText.ForceDraw = true; + m_equipmentTitleText.FontSize = 10; + m_equipmentTitleText.DropShadow = new Vector2(2, 2); + m_equipmentTitleText.TextureColor = new Color(237, 202, 138); + m_equipmentTitleText.Position = new Vector2(m_enchantressUI.X + 140, m_descriptionText.Y - 50); + m_equipmentTitleText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_equipmentTitleText); // dummy locID to add TextObj to language refresh list + + m_descriptionText.Visible = false; + m_instructionsTitleText.Visible = false; + m_instructionsText.Visible = false; + m_unlockCostContainer.Visible = false; + } + + // Displays the icons in a category when you move up and down the category list. + private void DisplayCategory(int equipmentType) + { + float tweenSpeed = 0.2f; + float delay = 0; + // Tween out the current active icon array. + if (m_activeIconArray != null) + { + for (int i = 0; i < EquipmentAbilityType.Total; i++) + { + Tween.StopAllContaining(m_activeIconArray[i], false); + Tween.To(m_activeIconArray[i], tweenSpeed, Back.EaseIn, "delay", delay.ToString(), "ScaleX", "0", "ScaleY", "0"); + } + } + + m_activeIconArray = m_masterIconArray[equipmentType]; + delay = 0.25f; + for (int i = 0; i < EquipmentAbilityType.Total; i++) + { + Tween.To(m_activeIconArray[i], tweenSpeed, Back.EaseOut, "delay", delay.ToString(), "ScaleX", "1", "ScaleY", "1"); + } + + foreach (SpriteObj icon in m_newIconList) + { + Tween.StopAllContaining(icon, false); + icon.Scale = Vector2.Zero; + Tween.To(icon, tweenSpeed, Back.EaseOut, "delay", delay.ToString(), "ScaleX", "1", "ScaleY", "1"); + } + + UpdateNewIcons(); + + m_equippedIcon.Scale = Vector2.Zero; + Tween.StopAllContaining(m_equippedIcon, false); + Tween.To(m_equippedIcon, tweenSpeed, Back.EaseOut, "delay", delay.ToString(), "ScaleX", "1", "ScaleY", "1"); + } + + public void EaseInMenu() + { + float tweenSpeed = 0.4f; + + // Tween in the menu background. + Tween.To(m_enchantressUI.GetChildAt(0), tweenSpeed, Back.EaseOut, "ScaleX", "1", "ScaleY", "1"); + + // Tween in the selection halo icon. + Tween.To(m_selectionIcon, tweenSpeed, Back.EaseOut, "delay", "0.25", "ScaleX", "1", "ScaleY", "1"); + float delay = 0.2f; + + // Tween in the Category icons and the title text. + for (int i = m_startingCategoryIndex; i < m_enchantressUI.NumChildren - 3; i++) + { + delay += 0.05f; + // Scaling in the Category icons. + Tween.To(m_enchantressUI.GetChildAt(i), tweenSpeed, Back.EaseOut, "delay", delay.ToString(), "ScaleX", "1", "ScaleY", "1"); + } + + // Tween in the description text. + Tween.To(m_enchantressUI.GetChildAt(m_enchantressUI.NumChildren - 1), tweenSpeed, Back.EaseOut, "delay", delay.ToString(), "ScaleX", "1", "ScaleY", "1"); + Tween.To(m_enchantressUI.GetChildAt(m_enchantressUI.NumChildren - 2), tweenSpeed, Back.EaseOut, "delay", delay.ToString(), "ScaleX", "1", "ScaleY", "1"); + Tween.To(m_enchantressUI.GetChildAt(m_enchantressUI.NumChildren - 3), tweenSpeed, Back.EaseOut, "delay", delay.ToString(), "ScaleX", "1", "ScaleY", "1"); + Tween.AddEndHandlerToLastTween(this, "EaseInComplete"); + } + + public void EaseInComplete() + { + m_lockControls = false; + } + + private void EaseOutMenu() + { + foreach (SpriteObj icon in m_newIconList) + icon.Visible = false; + m_equippedIcon.Visible = false; + + Tween.To(m_confirmText, 0.2f, Linear.EaseNone, "Opacity", "0"); + Tween.To(m_cancelText, 0.2f, Linear.EaseNone, "Opacity", "0"); + Tween.To(m_navigationText, 0.2f, Linear.EaseNone, "Opacity", "0"); + + float tweenSpeed = 0.4f; + float delay = 0f; + + // Tween out the description text and title text and equipped icon. + Tween.To(m_enchantressUI.GetChildAt(m_enchantressUI.NumChildren - 2), tweenSpeed, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); // Money text + Tween.To(m_enchantressUI.GetChildAt(m_enchantressUI.NumChildren - 3), tweenSpeed, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); // Coin Icon + Tween.To(m_enchantressUI.GetChildAt(m_enchantressUI.NumChildren - 4), tweenSpeed, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); // Title Text + + for (int i = m_startingCategoryIndex; i < m_startingCategoryIndex + 5; i++) + { + // Tween out the selection halo icon. + if (m_currentCategoryIndex == i) + Tween.To(m_selectionIcon, tweenSpeed, Back.EaseIn, "delay", delay.ToString(), "ScaleX", "0", "ScaleY", "0"); + + Tween.To(m_enchantressUI.GetChildAt(i), tweenSpeed, Back.EaseIn, "delay", delay.ToString(), "ScaleX", "0", "ScaleY", "0"); + delay += 0.05f; + } + + + // Resets all the category backgrounds. + for (int i = m_startingCategoryIndex - 5; i < m_startingCategoryIndex; i++) + { + m_enchantressUI.GetChildAt(i).Scale = Vector2.Zero; + } + + // Tween out the visible equipment icons. + for (int i = 0; i < m_activeIconArray.Length; i++) + { + Tween.To(m_activeIconArray[i], tweenSpeed, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + } + + // Tween out the menu background. + Tween.To(m_enchantressUI.GetChildAt(0), tweenSpeed, Back.EaseIn, "delay", "0.3", "ScaleX", "0", "ScaleY", "0"); + //Tween.AddEndHandlerToLastTween((ScreenManager as RCScreenManager), "HideCurrentScreen"); + Tween.RunFunction(tweenSpeed + 0.35f, ScreenManager, "HideCurrentScreen"); + } + + private void UpdateIconStates() + { + for (int i = 0; i < Game.PlayerStats.GetRuneArray.Count; i++) + { + for (int k = 0; k < Game.PlayerStats.GetRuneArray[i].Length; k++) + { + byte state = Game.PlayerStats.GetRuneArray[i][k]; + if (state == EquipmentState.NotFound) + m_masterIconArray[i][k].ChangeSprite("BlacksmithUI_QuestionMarkIcon_Sprite"); + else + { + m_masterIconArray[i][k].ChangeSprite(EquipmentAbilityType.Icon(k)); + m_masterIconArray[i][k].Opacity = 0.2f; + } + + if (state >= EquipmentState.Purchased) + m_masterIconArray[i][k].Opacity = 1f; + } + } + } + + public override void OnEnter() + { + if (m_rainSound != null) + m_rainSound.Dispose(); + + bool isSnowing = (DateTime.Now.Month == 12 || DateTime.Now.Month == 1); + if (isSnowing == false) + m_rainSound = SoundManager.PlaySound("Rain1_Filtered"); + else + m_rainSound = SoundManager.PlaySound("snowloop_filtered"); + + if (Game.PlayerStats.TotalRunesFound >= (EquipmentAbilityType.Total * EquipmentCategoryType.Total)) + GameUtil.UnlockAchievement("LOVE_OF_KNOWLEDGE"); + + m_lockControls = true; + SoundManager.PlaySound("ShopMenuOpen"); + + m_confirmText.Opacity = 0; + m_cancelText.Opacity = 0; + m_navigationText.Opacity = 0; + + Tween.To(m_confirmText, 0.2f, Linear.EaseNone, "Opacity", "1"); + Tween.To(m_cancelText, 0.2f, Linear.EaseNone, "Opacity", "1"); + Tween.To(m_navigationText, 0.2f, Linear.EaseNone, "Opacity", "1"); + + m_confirmText.Text = LocaleBuilder.getString("LOC_ID_ENCHANTRESS_SCREEN_6_NEW", m_confirmText); //"select/equip" + m_cancelText.Text = LocaleBuilder.getString("LOC_ID_ENCHANTRESS_SCREEN_7_NEW", m_cancelText); //"cancel/close menu" + + if (InputManager.GamePadIsConnected(PlayerIndex.One) == false) + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_ENCHANTRESS_SCREEN_8", m_navigationText); //"Arrow keys to navigate" + else + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_ENCHANTRESS_SCREEN_9_NEW", m_navigationText); //"to navigate" + + m_currentEquipmentIndex = 0; + m_inCategoryMenu = true; + m_selectionIcon.Position = m_enchantressUI.GetChildAt(m_startingCategoryIndex).AbsPosition; + m_currentCategoryIndex = m_startingCategoryIndex; + UpdateIconStates(); + DisplayCategory(EquipmentCategoryType.Sword); + EaseInMenu(); + Tween.To(this, 0.2f, Linear.EaseNone, "BackBufferOpacity", "0.5"); + UpdateIconSelectionText(); + + RefreshTextObjs(); + base.OnEnter(); + } + + public override void OnExit() + { + if (m_rainSound != null) + m_rainSound.Stop(AudioStopOptions.Immediate); + + for (int i = 0; i < m_enchantressUI.NumChildren; i++) + { + m_enchantressUI.GetChildAt(i).Scale = Vector2.Zero; + } + + foreach (SpriteObj[] iconArray in m_masterIconArray) + { + for (int i = 0; i < iconArray.Length; i++) + { + iconArray[i].Scale = Vector2.Zero; + } + } + m_selectionIcon.Scale = Vector2.Zero; + + (ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData, SaveType.UpgradeData); + + bool unlockAchievement = true; + foreach (sbyte equipmentType in Game.PlayerStats.GetEquippedRuneArray) + { + if (equipmentType == -1) + { + unlockAchievement = false; + break; + } + } + if (unlockAchievement == true) + GameUtil.UnlockAchievement("LOVE_OF_CHANGE"); + + base.OnExit(); + } + + public override void HandleInput() + { + if (m_lockControls == false) + { + if (m_inCategoryMenu == true) + CategorySelectionInput(); + else + EquipmentSelectionInput(); + } + + base.HandleInput(); + } + + private void CategorySelectionInput() + { + int currentCategoryIndex = m_currentCategoryIndex; + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + m_currentCategoryIndex--; + if (m_currentCategoryIndex < m_startingCategoryIndex) + m_currentCategoryIndex = m_startingCategoryIndex + 4; + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN2)) + { + m_currentCategoryIndex++; + if (m_currentCategoryIndex > m_startingCategoryIndex + 4) + m_currentCategoryIndex = m_startingCategoryIndex; + } + + if (currentCategoryIndex != m_currentCategoryIndex) + { + SoundManager.PlaySound("ShopBSMenuMove"); + + m_selectionIcon.Position = m_enchantressUI.GetChildAt(m_currentCategoryIndex).AbsPosition; + for (int i = 1; i < 6; i++) + { + if (i == 1) + m_enchantressUI.GetChildAt(i).Scale = new Vector2(1, 1); + else + m_enchantressUI.GetChildAt(i).Scale = Vector2.Zero; + } + + if (m_currentCategoryIndex != m_startingCategoryIndex) + m_enchantressUI.GetChildAt(m_currentCategoryIndex - 5).Scale = new Vector2(1, 1); + else + m_enchantressUI.GetChildAt(m_currentCategoryIndex - 5).Scale = Vector2.Zero; + + DisplayCategory(m_currentCategoryIndex - m_startingCategoryIndex); + } + + // Player is stepping out of the category menu, effectively closing the blacksmith screen. + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + m_lockControls = true; + Tween.To(this, 0.2f, Linear.EaseNone, "delay", "0.5", "BackBufferOpacity", "0"); + EaseOutMenu(); + Tween.RunFunction(0.13f, typeof(SoundManager), "PlaySound", "ShopMenuClose"); + } + + // Player is stepping into the category, to select a specific piece of equipment to purchase or equip. + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + m_inCategoryMenu = false; + m_currentEquipmentIndex = 0; + m_selectionIcon.Position = m_activeIconArray[m_currentEquipmentIndex].AbsPosition; + byte state = Game.PlayerStats.GetRuneArray[CurrentCategoryIndex][m_currentEquipmentIndex]; + if (state == EquipmentState.FoundButNotSeen) + Game.PlayerStats.GetRuneArray[CurrentCategoryIndex][m_currentEquipmentIndex] = EquipmentState.FoundAndSeen; + UpdateNewIcons(); + UpdateIconSelectionText(); + SoundManager.PlaySound("ShopMenuConfirm"); + } + } + + private void EquipmentSelectionInput() + { + int storedEquipmentIndex = m_currentEquipmentIndex; + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + if (m_currentEquipmentIndex > 4) + m_currentEquipmentIndex -= 5; + if (m_currentEquipmentIndex < 0) + m_currentEquipmentIndex = 0; + } + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN2)) + { + if (m_currentEquipmentIndex < EquipmentAbilityType.Total - 5) + m_currentEquipmentIndex += 5; + if (m_currentEquipmentIndex > EquipmentAbilityType.Total - 1) + m_currentEquipmentIndex -= 5; + } + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT2)) + { + m_currentEquipmentIndex--; + if ((m_currentEquipmentIndex + 1) % 5 == 0) + m_currentEquipmentIndex++; + } + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT2)) + { + m_currentEquipmentIndex++; + if (m_currentEquipmentIndex % 5 == 0 || (m_currentEquipmentIndex > EquipmentAbilityType.Total - 1)) + m_currentEquipmentIndex--; + } + + if (storedEquipmentIndex != m_currentEquipmentIndex) + { + byte state = Game.PlayerStats.GetRuneArray[CurrentCategoryIndex][m_currentEquipmentIndex]; + if (state == EquipmentState.FoundButNotSeen) + Game.PlayerStats.GetRuneArray[CurrentCategoryIndex][m_currentEquipmentIndex] = EquipmentState.FoundAndSeen; + UpdateNewIcons(); + UpdateIconSelectionText(); + m_selectionIcon.Position = m_activeIconArray[m_currentEquipmentIndex].AbsPosition; + SoundManager.PlaySound("ShopBSMenuMove"); + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + SoundManager.PlaySound("ShopMenuCancel"); + m_inCategoryMenu = true; + m_selectionIcon.Position = m_enchantressUI.GetChildAt(m_currentCategoryIndex).AbsPosition; + UpdateIconSelectionText(); + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + int equipmentCategory = m_currentCategoryIndex - m_startingCategoryIndex; + int purchasedState = Game.PlayerStats.GetRuneArray[equipmentCategory][m_currentEquipmentIndex]; + int equippedIndex = Game.PlayerStats.GetEquippedRuneArray[equipmentCategory]; + + // Purchasing a previously locked piece of equipment. + if (purchasedState < EquipmentState.Purchased && purchasedState > EquipmentState.NotFound) + { + int cost = Game.EquipmentSystem.GetAbilityCost(equipmentCategory, m_currentEquipmentIndex); + + if (Game.PlayerStats.Gold >= cost) + { + SoundManager.PlaySound("ShopMenuUnlock"); + Game.PlayerStats.Gold -= cost; + Game.PlayerStats.GetRuneArray[equipmentCategory][m_currentEquipmentIndex] = EquipmentState.Purchased; + Game.PlayerStats.GetEquippedRuneArray[equipmentCategory] = (sbyte)m_currentEquipmentIndex; + Player.AttachedLevel.UpdatePlayerHUDAbilities(); + + SpriteObj icon = m_masterIconArray[equipmentCategory][m_currentEquipmentIndex]; + //icon.ChangeSprite(EquipmentAbilityType.Icon(m_currentEquipmentIndex % 5)); + icon.Opacity = 1f; + + purchasedState = EquipmentState.Purchased; + UpdateIconSelectionText(); + } + } + + // Changing the currently equipped equipment piece. + if (equippedIndex != m_currentEquipmentIndex && purchasedState == EquipmentState.Purchased) + { + m_equippedIcon.Scale = new Vector2(1, 1); + m_equippedIcon.Position = m_activeIconArray[m_currentEquipmentIndex].AbsPosition; + m_equippedIcon.Position += new Vector2(18, 18); + Game.PlayerStats.GetEquippedRuneArray[equipmentCategory] = (sbyte)m_currentEquipmentIndex; + Player.AttachedLevel.UpdatePlayerHUDAbilities(); + SoundManager.PlaySound("ShopBSEquip"); // this should be an equip sound. + + UpdateIconSelectionText(); + UpdateNewIcons(); + } + else if (equippedIndex == m_currentEquipmentIndex) // Unequipping + { + m_equippedIcon.Scale = Vector2.Zero; + Game.PlayerStats.GetEquippedRuneArray[equipmentCategory] = -1; + Player.AttachedLevel.UpdatePlayerHUDAbilities(); + UpdateNewIcons(); + } + } + } + + private void UpdateIconSelectionText() + { + m_equipmentDescriptionText.Position = new Vector2(-1000, -1000); + m_descriptionText.Visible = false; + m_instructionsTitleText.Visible = false; + m_instructionsText.Visible = false; + m_unlockCostContainer.Visible = false; + m_equipmentTitleText.Visible = false; + + if (m_inCategoryMenu == true) + { + m_equipmentDescriptionText.Text = LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_1"); //"Select a category" + } + else + { + if (Game.PlayerStats.GetRuneArray[m_currentCategoryIndex - m_startingCategoryIndex][m_currentEquipmentIndex] == EquipmentState.NotFound) + { + m_equipmentDescriptionText.Position = new Vector2(230, -20); + m_equipmentDescriptionText.Text = LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_10"); //"Rune needed" + } + else if (Game.PlayerStats.GetRuneArray[m_currentCategoryIndex - m_startingCategoryIndex][m_currentEquipmentIndex] < EquipmentState.Purchased) + { + m_equipmentDescriptionText.Text = LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_11"); //"Purchase Info Here" + (m_unlockCostContainer.GetChildAt(1) as TextObj).Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_12_NEW"), Game.EquipmentSystem.GetAbilityCost(m_currentCategoryIndex - m_startingCategoryIndex, m_currentEquipmentIndex).ToString()); + //(m_unlockCostContainer.GetChildAt(1) as TextObj).Text = Game.EquipmentSystem.GetAbilityCost(m_currentCategoryIndex - m_startingCategoryIndex, m_currentEquipmentIndex).ToString() + " " + LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_12"); //"to unlock" + + m_unlockCostContainer.Visible = true; + m_descriptionText.Visible = true; + m_instructionsTitleText.Visible = true; + m_instructionsText.Visible = true; + m_equipmentTitleText.Visible = true; + + m_descriptionText.Opacity = 0.5f; + m_instructionsTitleText.Opacity = 0.5f; + m_instructionsText.Opacity = 0.5f; + m_equipmentTitleText.Opacity = 0.5f; + + UpdateEquipmentDataText(); + } + else + { + // This code displays all the information for the stats. + m_descriptionText.Visible = true; + m_instructionsTitleText.Visible = true; + m_instructionsText.Visible = true; + m_equipmentTitleText.Visible = true; + + m_descriptionText.Opacity = 1; + m_instructionsTitleText.Opacity = 1; + m_instructionsText.Opacity = 1; + m_equipmentTitleText.Opacity = 1; + + UpdateEquipmentDataText(); + + } + } + } + + // Updates the base player stats text and the bonus attribute text that a piece of equipment gives you. + private void UpdateEquipmentDataText() + { + m_equipmentTitleText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_RUNE_BASE_FORMAT", true), LocaleBuilder.getResourceString(EquipmentAbilityType.ToStringID(m_currentEquipmentIndex), true), LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_13"), true) /*"Rune"*/ + "\n(" + LocaleBuilder.getResourceString(EquipmentCategoryType.ToStringID2(m_currentCategoryIndex - m_startingCategoryIndex), true) + ")"; + + m_descriptionText.Text = LocaleBuilder.getResourceString(EquipmentAbilityType.DescriptionID(m_currentEquipmentIndex)); + m_descriptionText.WordWrap(195); + m_descriptionText.Y = m_equipmentTitleText.Y + 60; + + m_instructionsTitleText.Position = new Vector2(m_enchantressUI.X + 140, m_descriptionText.Bounds.Bottom + 20); // Must reposition to take word wrap into account. + m_instructionsText.Text = EquipmentAbilityType.Instructions(m_currentEquipmentIndex); + m_instructionsText.WordWrap(200); + + m_instructionsText.Position = new Vector2(m_instructionsTitleText.X, m_instructionsTitleText.Bounds.Bottom); + //m_equipmentTitleText.Text = EquipmentAbilityType.ToString(m_currentEquipmentIndex) + " Enchantment"; + //m_equipmentTitleText.Text = EquipmentCategoryType.ToString2(m_currentCategoryIndex - m_startingCategoryIndex) + " " + EquipmentAbilityType.ToString(m_currentEquipmentIndex) + " Rune"; + } + + private void UpdateNewIcons() + { + UpdateMoneyText(); + + m_newIconListIndex = 0; + foreach (SpriteObj sprite in m_newIconList) + sprite.Visible = false; + + for (int i = 0; i < Game.PlayerStats.GetRuneArray[CurrentCategoryIndex].Length; i++) + { + byte state = Game.PlayerStats.GetRuneArray[CurrentCategoryIndex][i]; + if (state == EquipmentState.FoundButNotSeen) + { + SpriteObj equipmentIcon = m_masterIconArray[CurrentCategoryIndex][i]; + + SpriteObj newIcon = m_newIconList[m_newIconListIndex]; + newIcon.Visible = true; + newIcon.Position = m_masterIconArray[CurrentCategoryIndex][i].AbsPosition; + newIcon.X -= 20; + newIcon.Y -= 30; + m_newIconListIndex++; + } + } + + + sbyte equippedItemIndex = Game.PlayerStats.GetEquippedRuneArray[CurrentCategoryIndex]; + if (equippedItemIndex > -1) + { + m_equippedIcon.Position = new Vector2(m_activeIconArray[equippedItemIndex].AbsPosition.X + 18, m_activeIconArray[equippedItemIndex].AbsPosition.Y + 18); + m_equippedIcon.Visible = true; + } + else + m_equippedIcon.Visible = false; + } + + + private void UpdateMoneyText() + { + m_playerMoney.Text = Game.PlayerStats.Gold.ToString(); + ProceduralLevelScreen level = Game.ScreenManager.GetLevelScreen(); + if (level != null) + level.UpdatePlayerHUD(); + } + + public override void Draw(GameTime gameTime) + { + Camera.Begin(); + Camera.Draw(Game.GenericTexture, new Rectangle(0, 0, 1320, 720), Color.Black * BackBufferOpacity); + m_enchantressUI.Draw(Camera); + m_selectionIcon.Draw(Camera); + + //m_textInfoContainer.DrawOutline(Camera, 2); + m_descriptionText.Draw(Camera); + if (Game.PlayerStats.GetRuneArray[CurrentCategoryIndex][m_currentEquipmentIndex] > EquipmentState.FoundAndSeen) + { + m_instructionsTitleText.Draw(Camera); + m_instructionsText.Draw(Camera); + } + m_unlockCostContainer.Draw(Camera); + m_equipmentTitleText.Draw(Camera); + + foreach (SpriteObj[] iconArray in m_masterIconArray) + { + for (int i = 0; i < iconArray.Length; i++) + iconArray[i].Draw(Camera); + } + + m_navigationText.Draw(Camera); + m_cancelText.Draw(Camera); + m_confirmText.Draw(Camera); + + m_equippedIcon.Draw(Camera); + + foreach (SpriteObj icon in m_newIconList) + icon.Draw(Camera); + + Camera.End(); + base.Draw(gameTime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Enchantress Screen"); + + if (m_rainSound != null) + m_rainSound.Dispose(); + m_rainSound = null; + + m_enchantressUI.Dispose(); + m_enchantressUI = null; + m_equipmentDescriptionText.Dispose(); + m_equipmentDescriptionText = null; + m_selectionIcon.Dispose(); + m_selectionIcon = null; + + m_equipmentTitleText.Dispose(); + m_equipmentTitleText = null; + + m_activeIconArray = null; + + foreach (SpriteObj[] iconArray in m_masterIconArray) + { + for (int i = 0; i < iconArray.Length; i++) + { + iconArray[i].Dispose(); + iconArray[i] = null; + } + Array.Clear(iconArray, 0, iconArray.Length); + } + m_masterIconArray.Clear(); + m_masterIconArray = null; + + m_descriptionText.Dispose(); + m_descriptionText = null; + m_unlockCostContainer.Dispose(); + m_unlockCostContainer = null; + m_instructionsText.Dispose(); + m_instructionsText = null; + m_instructionsTitleText.Dispose(); + m_instructionsTitleText = null; + m_equippedIcon.Dispose(); + m_equippedIcon = null; + Player = null; + + m_confirmText.Dispose(); + m_confirmText = null; + m_cancelText.Dispose(); + m_cancelText = null; + m_navigationText.Dispose(); + m_navigationText = null; + + m_playerMoney = null; + foreach (SpriteObj sprite in m_newIconList) + sprite.Dispose(); + m_newIconList.Clear(); + m_newIconList = null; + + base.Dispose(); + } + } + + private int CurrentCategoryIndex + { + get { return m_currentCategoryIndex - m_startingCategoryIndex; } + } + + public override void RefreshTextObjs() + { + m_instructionsTitleText.Text = LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_5") + ":"; //"Instructions:" + + /* + m_confirmText.Text = "[Input:" + InputMapType.MENU_CONFIRM1 + "] " + LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_6"); //"select/equip" + m_cancelText.Text = "[Input:" + InputMapType.MENU_CANCEL1 + "] " + LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_7"); //"cancel/close menu" + + if (InputManager.GamePadIsConnected(PlayerIndex.One) == false) + m_navigationText.Text = LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_8"); //"Arrow keys to navigate" + else + m_navigationText.Text = "[Button:LeftStick] " + LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_9"); //"to navigate" + */ + + (m_unlockCostContainer.GetChildAt(1) as TextObj).ScaleX = 1; + switch (LocaleBuilder.languageType) + { + case (LanguageType.French): + case (LanguageType.Spanish_Spain): + case (LanguageType.German): + case (LanguageType.Polish): + (m_unlockCostContainer.GetChildAt(1) as TextObj).ScaleX = 0.9f; + break; + } + + Game.ChangeBitmapLanguage(m_enchantressUI.GetChildAt(m_enchantressUI.NumChildren - 4) as SpriteObj, "EnchantressUI_Title_Sprite"); + foreach (SpriteObj icon in m_newIconList) + Game.ChangeBitmapLanguage(icon, "BlacksmithUI_NewIcon_Sprite"); + + UpdateIconSelectionText(); + UpdateEquipmentDataText(); + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Screens/GameOverBossScreen.cs b/RogueCastle/src/Screens/GameOverBossScreen.cs new file mode 100644 index 0000000..630d902 --- /dev/null +++ b/RogueCastle/src/Screens/GameOverBossScreen.cs @@ -0,0 +1,345 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using InputSystem; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class GameOverBossScreen : Screen + { + private EnemyObj_LastBoss m_lastBoss; + + private ObjContainer m_dialoguePlate; + private KeyIconTextObj m_continueText; + private SpriteObj m_playerGhost; + + private SpriteObj m_king; + private SpriteObj m_spotlight; + public float BackBufferOpacity { get; set; } + + private LineageObj m_playerFrame; + private FrameSoundObj m_bossFallSound; + private FrameSoundObj m_bossKneesSound; + private Vector2 m_initialCameraPos; + + private bool m_lockControls = false; + + public GameOverBossScreen() + { + DrawIfCovered = true; + } + + public override void PassInData(List objList) + { + m_lastBoss = objList[0] as EnemyObj_LastBoss; + + m_bossKneesSound = new FrameSoundObj(m_lastBoss, 3, "FinalBoss_St2_Deathsceen_Knees"); + m_bossFallSound = new FrameSoundObj(m_lastBoss, 13, "FinalBoss_St2_Deathsceen_Fall"); + base.PassInData(objList); + } + + public override void LoadContent() + { + m_continueText = new KeyIconTextObj(Game.JunicodeFont); + m_continueText.FontSize = 14; + m_continueText.Align = Types.TextAlign.Right; + m_continueText.Opacity = 0; + m_continueText.Position = new Vector2(1320 - 50, 30); + m_continueText.ForceDraw = true; + m_continueText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_continueText); // dummy locID to add TextObj to language refresh list + + Vector2 shadowOffset = new Vector2(2, 2); + Color textColour = new Color(255, 254, 128); + + m_dialoguePlate = new ObjContainer("DialogBox_Character"); + m_dialoguePlate.Position = new Vector2(1320 / 2, 610); + m_dialoguePlate.ForceDraw = true; + + TextObj deathDescription = new TextObj(Game.JunicodeFont); + deathDescription.Align = Types.TextAlign.Centre; + deathDescription.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", deathDescription); // dummy locID to add TextObj to language refresh list + deathDescription.FontSize = 18; + deathDescription.DropShadow = shadowOffset; + deathDescription.Position = new Vector2(0, -m_dialoguePlate.Height / 2 + 25); + m_dialoguePlate.AddChild(deathDescription); + + KeyIconTextObj partingWords = new KeyIconTextObj(Game.JunicodeFont); + partingWords.FontSize = 12; + partingWords.Align = Types.TextAlign.Centre; + partingWords.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", partingWords); // dummy locID to add TextObj to language refresh list + partingWords.DropShadow = shadowOffset; + partingWords.Y = 10; + partingWords.TextureColor = textColour; + m_dialoguePlate.AddChild(partingWords); + + TextObj partingWordsTitle = new TextObj(Game.JunicodeFont); + partingWordsTitle.FontSize = 8; + partingWordsTitle.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", partingWordsTitle); // dummy locID to add TextObj to language refresh list + partingWordsTitle.Y = partingWords.Y; + partingWordsTitle.Y += 40; + partingWordsTitle.X += 20; + partingWordsTitle.DropShadow = shadowOffset; + m_dialoguePlate.AddChild(partingWordsTitle); + + m_playerGhost = new SpriteObj("PlayerGhost_Sprite"); + m_playerGhost.AnimationDelay = 1 / 10f; + + m_spotlight = new SpriteObj("GameOverSpotlight_Sprite"); + m_spotlight.Rotation = 90; + m_spotlight.ForceDraw = true; + m_spotlight.Position = new Vector2(1320 / 2, 40 + m_spotlight.Height); + + m_playerFrame = new LineageObj(null, true); + m_playerFrame.DisablePlaque = true; + + m_king = new SpriteObj("King_Sprite"); + m_king.OutlineWidth = 2; + m_king.AnimationDelay = 1 / 10f; + m_king.PlayAnimation(true); + m_king.Scale = new Vector2(2, 2); + + base.LoadContent(); + } + + public override void OnEnter() + { + m_initialCameraPos = Camera.Position; + SetObjectKilledPlayerText(); + + // Setting the last boss's frame. This needs to be done before the stats are erased for the next play. + m_playerFrame.Opacity = 0; + m_playerFrame.Position = m_lastBoss.Position; + m_playerFrame.SetTraits(Vector2.Zero); + + m_playerFrame.IsFemale = false; + m_playerFrame.Class = ClassType.Knight; + m_playerFrame.Y -= 120; + m_playerFrame.SetPortrait(8, 1, 1); // 8 is the special intro open helm. + m_playerFrame.UpdateData(); + Tween.To(m_playerFrame, 1f, Tween.EaseNone, "delay", "4", "Opacity", "1"); + + SoundManager.StopMusic(0.5f); + m_lockControls = false; + SoundManager.PlaySound("Player_Death_FadeToBlack"); + m_continueText.Text = LocaleBuilder.getString("LOC_ID_GAME_OVER_BOSS_SCREEN_1_NEW", m_continueText); + + m_lastBoss.Visible = true; + m_lastBoss.Opacity = 1; + + m_continueText.Opacity = 0; + m_dialoguePlate.Opacity = 0; + m_playerGhost.Opacity = 0; + m_spotlight.Opacity = 0; + + // Player ghost animation. + m_playerGhost.Position = new Vector2(m_lastBoss.X - m_playerGhost.Width / 2, m_lastBoss.Bounds.Top - 20); + Tween.RunFunction(3, typeof(SoundManager), "PlaySound", "Player_Ghost"); + //m_ghostSoundTween = Tween.RunFunction(5, typeof(SoundManager), "PlaySound", "Player_Ghost"); + Tween.To(m_playerGhost, 0.5f, Linear.EaseNone, "delay", "3", "Opacity", "0.4"); + Tween.By(m_playerGhost, 2, Linear.EaseNone, "delay", "3", "Y", "-150"); + m_playerGhost.Opacity = 0.4f; + Tween.To(m_playerGhost, 0.5f, Linear.EaseNone, "delay", "4", "Opacity", "0"); + m_playerGhost.Opacity = 0; + m_playerGhost.PlayAnimation(true); + + // Spotlight, Player slain text, and Backbuffer animation. + Tween.To(this, 0.5f, Linear.EaseNone, "BackBufferOpacity", "1"); + Tween.To(m_spotlight, 0.1f, Linear.EaseNone, "delay", "1", "Opacity", "1"); + Tween.AddEndHandlerToLastTween(typeof(SoundManager), "PlaySound", "Player_Death_Spotlight"); + Tween.RunFunction(2, typeof(SoundManager), "PlaySound", "FinalBoss_St1_DeathGrunt"); + Tween.RunFunction(1.2f, typeof(SoundManager), "PlayMusic", "GameOverBossStinger", false, 0.5f); + Tween.To(Camera, 1, Quad.EaseInOut, "X", m_lastBoss.AbsX.ToString(), "Y", (m_lastBoss.Bounds.Bottom - 10).ToString()); + Tween.RunFunction(2f, m_lastBoss, "PlayAnimation", false); + //Tween.RunFunction(2f, m_lastBoss, "RunDeathAnimation1"); + + // Setting the dialogue plate info. + //1 = slain text + //2 = parting words + //3 = parting words title. + + (m_dialoguePlate.GetChildAt(2) as TextObj).Text = LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_BOSS_SCREEN_3"); //"The sun... I had forgotten how it feels..." + (m_dialoguePlate.GetChildAt(3) as TextObj).Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_8_NEW"), LocaleBuilder.getResourceString(m_lastBoss.LocStringID)); //"'s Parting Words" + //(m_dialoguePlate.GetChildAt(3) as TextObj).Text = "-" + LocaleBuilder.getResourceString(m_lastBoss.LocStringID) + LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_8"); //"'s Parting Words" + + Tween.To(m_dialoguePlate, 0.5f, Tween.EaseNone, "delay", "2", "Opacity", "1"); + Tween.RunFunction(4f, this, "DropStats"); + Tween.To(m_continueText, 0.4f, Linear.EaseNone, "delay", "4", "Opacity", "1"); + + base.OnEnter(); + } + + public void DropStats() + { + Vector2 randPos = Vector2.Zero; + float delay = 0; + + Vector2 startingPos = Camera.TopLeftCorner; + startingPos.X += 200; + startingPos.Y += 450; + + m_king.Position = startingPos; + m_king.Visible = true; + m_king.StopAnimation(); + m_king.Scale /= 2; + m_king.Opacity = 0; + delay += 0.05f; + Tween.To(m_king, 0f, Tween.EaseNone, "delay", delay.ToString(), "Opacity", "1"); + } + + private void SetObjectKilledPlayerText() + { + TextObj playerSlainText = m_dialoguePlate.GetChildAt(1) as TextObj; + playerSlainText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_BOSS_SCREEN_5_NEW"), LocaleBuilder.getResourceString(m_lastBoss.LocStringID), Game.NameHelper()); + //playerSlainText.Text = m_lastBoss.Name + " " + LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_BOSS_SCREEN_5") + " " + Game.PlayerStats.PlayerName; + } + + public override void HandleInput() + { + if (m_lockControls == false) + { + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + if (m_continueText.Opacity == 1) + { + m_lockControls = true; + ExitTransition(); + //Game.ScreenManager.Player.Position = new Vector2(100, 100); + //Game.ScreenManager.HideCurrentScreen(); + + //TextObj endingText = new TextObj(Game.JunicodeLargeFont); + ////endingText.Text = "Every man's life ends the same way.\nIt is only the details of how he lived and\nhow he died that distinguish one man from another.";//"In every conceivable manner, the family is link\n to our past, bridge to our future.";//"I did everything they asked..."; + ////endingText.Text = "Too great a price was paid, for a reward of none...\nTrue clarity can only be gained through self-doubt."; + //endingText.Text = "Every man's life ends the same way.\nIt is only the details of how he lived and\nhow he died that distinguish one man from another.\n- Ernest Hemingway"; + //endingText.FontSize = 25; + //endingText.ForceDraw = true; + //endingText.Align = Types.TextAlign.Centre; + //endingText.Position = new Vector2(1320 / 2f, 720 / 2f - 100); + //endingText.OutlineWidth = 2; + + //List endingTextObj = new List(); + //endingTextObj.Add(1.0f); + //endingTextObj.Add(0.2f); + //endingTextObj.Add(8f); + //endingTextObj.Add(true); + //endingTextObj.Add(endingText); + //endingTextObj.Add(true); + //SoundManager.StopMusic(1); + //Game.ScreenManager.DisplayScreen(ScreenType.Text, true, endingTextObj); + //(ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Ending, true, null); + //Tween.RunFunction(0, ScreenManager, "DisplayScreen", ScreenType.Ending, true, typeof(List)); + } + } + } + base.HandleInput(); + } + + private void ExitTransition() + { + Tween.StopAll(false); + SoundManager.StopMusic(1); + Tween.To(this, 0.5f, Quad.EaseIn, "BackBufferOpacity", "0"); + Tween.To(m_lastBoss, 0.5f, Quad.EaseIn, "Opacity", "0"); + Tween.To(m_dialoguePlate, 0.5f, Quad.EaseIn, "Opacity", "0"); + Tween.To(m_continueText, 0.5f, Quad.EaseIn, "Opacity", "0"); + Tween.To(m_playerGhost, 0.5f, Quad.EaseIn, "Opacity", "0"); + Tween.To(m_king, 0.5f, Quad.EaseIn, "Opacity", "0"); + Tween.To(m_spotlight, 0.5f, Quad.EaseIn, "Opacity", "0"); + Tween.To(m_playerFrame, 0.5f, Quad.EaseIn, "Opacity", "0"); + Tween.To(Camera, 0.5f, Quad.EaseInOut, "X", m_initialCameraPos.X.ToString(), "Y", m_initialCameraPos.Y.ToString()); + Tween.RunFunction(0.5f, ScreenManager, "HideCurrentScreen"); + } + + public override void OnExit() + { + BackBufferOpacity = 0; + Game.ScreenManager.Player.UnlockControls(); + Game.ScreenManager.Player.AttachedLevel.CameraLockedToPlayer = true; + (Game.ScreenManager.GetLevelScreen().CurrentRoom as LastBossRoom).BossCleanup(); + base.OnExit(); + } + + public override void Update(GameTime gameTime) + { + if (m_lastBoss.SpriteName == "EnemyLastBossDeath_Character") + { + m_bossKneesSound.Update(); + m_bossFallSound.Update(); + } + + base.Update(gameTime); + } + + public override void Draw(GameTime gameTime) + { + //Camera.GraphicsDevice.Clear(Color.Black); + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, Camera.GetTransformation()); // Parallax Effect has been disabled in favour of ripple effect for now. + Camera.Draw(Game.GenericTexture, new Rectangle((int)Camera.TopLeftCorner.X - 10, (int)Camera.TopLeftCorner.Y - 10, 1420, 820), Color.Black * BackBufferOpacity); + m_king.Draw(Camera); + m_playerFrame.Draw(Camera); + m_lastBoss.Draw(Camera); + if (m_playerGhost.Opacity > 0) + m_playerGhost.X += (float)Math.Sin(Game.TotalGameTime * 5); + m_playerGhost.Draw(Camera); + Camera.End(); + + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null); // Parallax Effect has been disabled in favour of ripple effect for now. + m_spotlight.Draw(Camera); + m_dialoguePlate.Draw(Camera); + m_continueText.Draw(Camera); + Camera.End(); + + base.Draw(gameTime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Game Over Boss Screen"); + + m_lastBoss = null; + m_dialoguePlate.Dispose(); + m_dialoguePlate = null; + m_continueText.Dispose(); + m_continueText = null; + m_playerGhost.Dispose(); + m_playerGhost = null; + m_spotlight.Dispose(); + m_spotlight = null; + + if (m_bossFallSound != null) + m_bossFallSound.Dispose(); + m_bossFallSound = null; + if (m_bossKneesSound != null) + m_bossKneesSound.Dispose(); + m_bossKneesSound = null; + + m_playerFrame.Dispose(); + m_playerFrame = null; + m_king.Dispose(); + m_king = null; + + base.Dispose(); + } + } + + public override void RefreshTextObjs() + { + //m_continueText.Text = LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_BOSS_SCREEN_1") + " [Input:" + InputMapType.MENU_CONFIRM1 + "] " + LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_BOSS_SCREEN_2"); + SetObjectKilledPlayerText(); + (m_dialoguePlate.GetChildAt(2) as TextObj).Text = LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_BOSS_SCREEN_3"); //"The sun... I had forgotten how it feels..." + (m_dialoguePlate.GetChildAt(3) as TextObj).Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_8_NEW"), LocaleBuilder.getResourceString(m_lastBoss.LocStringID)); //"'s Parting Words" + //(m_dialoguePlate.GetChildAt(3) as TextObj).Text = "-" + m_lastBoss.Name + LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_8"); //"'s Parting Words" + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Screens/GameOverScreen.cs b/RogueCastle/src/Screens/GameOverScreen.cs new file mode 100644 index 0000000..0c1df6f --- /dev/null +++ b/RogueCastle/src/Screens/GameOverScreen.cs @@ -0,0 +1,677 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using InputSystem; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Graphics; +using System.Text.RegularExpressions; + +namespace RogueCastle +{ + public class GameOverScreen : Screen + { + private PlayerObj m_player; + + private ObjContainer m_dialoguePlate; + private KeyIconTextObj m_continueText; + private SpriteObj m_playerGhost; + private SpriteObj m_spotlight; + public float BackBufferOpacity { get; set; } + + private List m_enemyList; + private List m_enemyStoredPositions; + private int m_coinsCollected; + private int m_bagsCollected; + private int m_diamondsCollected; + private int m_bigDiamondsCollected; + + private FrameSoundObj m_playerFallSound; + private FrameSoundObj m_playerSwordSpinSound; + private FrameSoundObj m_playerSwordFallSound; + + private GameObj m_objKilledPlayer; + private LineageObj m_playerFrame; + + private bool m_lockControls = false; + private bool m_droppingStats; + + private int m_gameHint; + + public GameOverScreen() + { + m_enemyStoredPositions = new List(); + } + + public override void PassInData(List objList) + { + if (objList != null) + { + m_player = objList[0] as PlayerObj; + + if (m_playerFallSound == null) + { + m_playerFallSound = new FrameSoundObj(m_player, 14, "Player_Death_BodyFall"); + m_playerSwordSpinSound = new FrameSoundObj(m_player, 2, "Player_Death_SwordTwirl"); + m_playerSwordFallSound = new FrameSoundObj(m_player, 9, "Player_Death_SwordLand"); + } + + m_enemyList = objList[1] as List; + m_coinsCollected = (int)objList[2]; + m_bagsCollected = (int)objList[3]; + m_diamondsCollected = (int)objList[4]; + m_bigDiamondsCollected = (int)objList[5]; + if (objList[6] != null) + m_objKilledPlayer = objList[6] as GameObj; + SetObjectKilledPlayerText(); + + m_enemyStoredPositions.Clear(); + base.PassInData(objList); + } + } + + public override void LoadContent() + { + m_continueText = new KeyIconTextObj(Game.JunicodeFont); + m_continueText.FontSize = 14; + m_continueText.Align = Types.TextAlign.Right; + m_continueText.Opacity = 0; + m_continueText.Position = new Vector2(1320 - 50, 30); + m_continueText.ForceDraw = true; + m_continueText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_continueText); // dummy locID to add TextObj to language refresh list + + Vector2 shadowOffset = new Vector2(2, 2); + Color textColour = new Color(255, 254, 128); + + m_dialoguePlate = new ObjContainer("DialogBox_Character"); + m_dialoguePlate.Position = new Vector2(1320 / 2, 610); + m_dialoguePlate.ForceDraw = true; + + TextObj deathDescription = new TextObj(Game.JunicodeFont); + deathDescription.Align = Types.TextAlign.Centre; + deathDescription.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", deathDescription); // dummy locID to add TextObj to language refresh list + deathDescription.FontSize = 17; + deathDescription.DropShadow = shadowOffset; + deathDescription.Position = new Vector2(0, -m_dialoguePlate.Height / 2 + 25); + m_dialoguePlate.AddChild(deathDescription); + + KeyIconTextObj partingWords = new KeyIconTextObj(Game.JunicodeFont); + partingWords.FontSize = 12; + partingWords.Align = Types.TextAlign.Centre; + partingWords.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", partingWords); // dummy locID to add TextObj to language refresh list + partingWords.DropShadow = shadowOffset; + partingWords.Y = 0; + partingWords.TextureColor = textColour; + m_dialoguePlate.AddChild(partingWords); + + TextObj partingWordsTitle = new TextObj(Game.JunicodeFont); + partingWordsTitle.FontSize = 8; + partingWordsTitle.Text = "";// LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", partingWordsTitle); // dummy locID to add TextObj to language refresh list + partingWordsTitle.Y = partingWords.Y; + partingWordsTitle.Y += 40; + partingWordsTitle.X += 20; + partingWordsTitle.DropShadow = shadowOffset; + m_dialoguePlate.AddChild(partingWordsTitle); + + m_playerGhost = new SpriteObj("PlayerGhost_Sprite"); + m_playerGhost.AnimationDelay = 1 / 10f; + + m_spotlight = new SpriteObj("GameOverSpotlight_Sprite"); + m_spotlight.Rotation = 90; + m_spotlight.ForceDraw = true; + m_spotlight.Position = new Vector2(1320 / 2, 40 + m_spotlight.Height); + + m_playerFrame = new LineageObj(null, true); + m_playerFrame.DisablePlaque = true; + + base.LoadContent(); + } + + public override void OnEnter() + { + m_debugEnemyLocID = -1; + + // Setting the player frame. This needs to be done before the stats are erased for the next play. + m_playerFrame.Opacity = 0; + m_playerFrame.Position = m_player.Position; + m_playerFrame.SetTraits(Game.PlayerStats.Traits); + m_playerFrame.IsFemale = Game.PlayerStats.IsFemale; + m_playerFrame.Class = Game.PlayerStats.Class; + m_playerFrame.Y -= 120; + m_playerFrame.SetPortrait((byte)Game.PlayerStats.HeadPiece, (byte)Game.PlayerStats.ShoulderPiece, (byte)Game.PlayerStats.ChestPiece); + m_playerFrame.UpdateData(); + Tween.To(m_playerFrame, 1f, Tween.EaseNone, "delay", "4", "Opacity", "1"); + + // Creating a new family tree node and saving. + FamilyTreeNode newNode = new FamilyTreeNode() + { + Name = Game.PlayerStats.PlayerName, + Age = Game.PlayerStats.Age, + ChildAge = Game.PlayerStats.ChildAge, + Class = Game.PlayerStats.Class, + HeadPiece = Game.PlayerStats.HeadPiece, + ChestPiece = Game.PlayerStats.ChestPiece, + ShoulderPiece = Game.PlayerStats.ShoulderPiece, + NumEnemiesBeaten = Game.PlayerStats.NumEnemiesBeaten, + BeatenABoss = Game.PlayerStats.NewBossBeaten, + Traits = Game.PlayerStats.Traits, + IsFemale = Game.PlayerStats.IsFemale, + RomanNumeral = Game.PlayerStats.RomanNumeral, + }; + + Vector2 storedTraits = Game.PlayerStats.Traits; + Game.PlayerStats.FamilyTreeArray.Add(newNode); + if (Game.PlayerStats.CurrentBranches != null) + Game.PlayerStats.CurrentBranches.Clear(); + + // Setting necessary after-death flags and saving. + Game.PlayerStats.IsDead = true; + Game.PlayerStats.Traits = Vector2.Zero; + Game.PlayerStats.NewBossBeaten = false; + Game.PlayerStats.RerolledChildren = false; + Game.PlayerStats.HasArchitectFee = false; + Game.PlayerStats.NumEnemiesBeaten = 0; + Game.PlayerStats.LichHealth = 0; + Game.PlayerStats.LichMana = 0; + Game.PlayerStats.LichHealthMod = 1; + Game.PlayerStats.TimesDead++; + Game.PlayerStats.LoadStartingRoom = true; + Game.PlayerStats.EnemiesKilledInRun.Clear(); + + if (Game.PlayerStats.SpecialItem != SpecialItemType.FreeEntrance && + Game.PlayerStats.SpecialItem != SpecialItemType.EyeballToken && + Game.PlayerStats.SpecialItem != SpecialItemType.SkullToken && + Game.PlayerStats.SpecialItem != SpecialItemType.FireballToken && + Game.PlayerStats.SpecialItem != SpecialItemType.BlobToken && + Game.PlayerStats.SpecialItem != SpecialItemType.LastBossToken) + Game.PlayerStats.SpecialItem = SpecialItemType.None; + + // Ensures the prosopagnosia effect kicks in when selecting an heir. + if (storedTraits.X == (int)TraitType.Prosopagnosia || storedTraits.Y == (int)TraitType.Prosopagnosia) + Game.PlayerStats.HasProsopagnosia = true; + + (ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData, SaveType.Lineage, SaveType.MapData); + (ScreenManager.Game as Game).SaveManager.SaveAllFileTypes(true); // Save the backup the moment the player dies. + + // The player's traits need to be restored to so that his death animation matches the player. + Game.PlayerStats.Traits = storedTraits; + + // Setting achievements. + if (Game.PlayerStats.TimesDead >= 20) + GameUtil.UnlockAchievement("FEAR_OF_LIFE"); + + //////////////////////////////////////////////////////////////////////////////// + + SoundManager.StopMusic(0.5f); + m_droppingStats = false; + m_lockControls = false; + SoundManager.PlaySound("Player_Death_FadeToBlack"); + m_continueText.Text = LocaleBuilder.getString("LOC_ID_GAME_OVER_SCREEN_1_NEW", m_continueText); + + m_player.Visible = true; + m_player.Opacity = 1; + + m_continueText.Opacity = 0; + m_dialoguePlate.Opacity = 0; + m_playerGhost.Opacity = 0; + m_spotlight.Opacity = 0; + + // Player ghost animation. + m_playerGhost.Position = new Vector2(m_player.X - m_playerGhost.Width / 2, m_player.Bounds.Top - 20); + Tween.RunFunction(3, typeof(SoundManager), "PlaySound", "Player_Ghost"); + //m_ghostSoundTween = Tween.RunFunction(5, typeof(SoundManager), "PlaySound", "Player_Ghost"); + Tween.To(m_playerGhost, 0.5f, Linear.EaseNone, "delay", "3", "Opacity", "0.4"); + Tween.By(m_playerGhost, 2, Linear.EaseNone, "delay", "3", "Y", "-150"); + m_playerGhost.Opacity = 0.4f; + Tween.To(m_playerGhost, 0.5f, Linear.EaseNone, "delay", "4", "Opacity", "0"); + m_playerGhost.Opacity = 0; + m_playerGhost.PlayAnimation(true); + + // Spotlight, Player slain text, and Backbuffer animation. + Tween.To(this, 0.5f, Linear.EaseNone, "BackBufferOpacity", "1"); + Tween.To(m_spotlight, 0.1f, Linear.EaseNone, "delay", "1", "Opacity", "1"); + Tween.AddEndHandlerToLastTween(typeof(SoundManager), "PlaySound", "Player_Death_Spotlight"); + Tween.RunFunction(1.2f, typeof(SoundManager), "PlayMusic", "GameOverStinger", false, 0.5f); + Tween.To(Camera, 1, Quad.EaseInOut, "X", this.m_player.AbsX.ToString(), "Y", (this.m_player.Bounds.Bottom - 10).ToString(), "Zoom", "1"); + Tween.RunFunction(2f, m_player, "RunDeathAnimation1"); + + // Setting the dialogue plate info. + //1 = slain text + //2 = parting words + //3 = parting words title. + + if (Game.PlayerStats.Traits.X == TraitType.Tourettes || Game.PlayerStats.Traits.Y == TraitType.Tourettes) + { + (m_dialoguePlate.GetChildAt(2) as TextObj).Text = "#)!(%*#@!%^"; // not localized + (m_dialoguePlate.GetChildAt(2) as TextObj).RandomizeSentence(true); + } + else + { + m_gameHint = CDGMath.RandomInt(0, GameEV.GAME_HINTS.GetLength(0) - 1); + (m_dialoguePlate.GetChildAt(2) as TextObj).Text = LocaleBuilder.getResourceString(GameEV.GAME_HINTS[m_gameHint]); + FixHintTextSize(); + //(m_dialoguePlate.GetChildAt(2) as TextObj).Text = + // LocaleBuilder.getResourceString(GameEV.GAME_HINTS[m_gameHint, 0]) + + // GameEV.GAME_HINTS[m_gameHint, 1] + + // LocaleBuilder.getResourceString(GameEV.GAME_HINTS[m_gameHint, 2]); + } + + try + { + (m_dialoguePlate.GetChildAt(3) as TextObj).ChangeFontNoDefault((m_dialoguePlate.GetChildAt(3) as TextObj).defaultFont); + (m_dialoguePlate.GetChildAt(3) as TextObj).Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_8_NEW"), Game.NameHelper()); //"'s Parting Words" + if (LocaleBuilder.languageType != LanguageType.Chinese_Simp && Regex.IsMatch((m_dialoguePlate.GetChildAt(3) as TextObj).Text, @"\p{IsCyrillic}")) + (m_dialoguePlate.GetChildAt(3) as TextObj).ChangeFontNoDefault(Game.RobotoSlabFont); + } + catch + { + (m_dialoguePlate.GetChildAt(3) as TextObj).ChangeFontNoDefault(Game.NotoSansSCFont); + (m_dialoguePlate.GetChildAt(3) as TextObj).Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_8_NEW"), Game.NameHelper()); //"'s Parting Words" + } + //(m_dialoguePlate.GetChildAt(3) as TextObj).Text = "-" + Game.PlayerStats.PlayerName + LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_8"); + + Tween.To(m_dialoguePlate, 0.5f, Tween.EaseNone, "delay", "2", "Opacity", "1"); + Tween.RunFunction(4f, this, "DropStats"); + Tween.To(m_continueText, 0.4f, Linear.EaseNone, "delay", "4", "Opacity", "1"); + + base.OnEnter(); + } + + public override void OnExit() + { + Tween.StopAll(false); + if (m_enemyList != null) + { + m_enemyList.Clear(); + m_enemyList = null; + } + + Game.PlayerStats.Traits = Vector2.Zero; + + BackBufferOpacity = 0; + + base.OnExit(); + } + + public void DropStats() + { + m_droppingStats = true; + Vector2 randPos = Vector2.Zero; + float delay = 0; + + Vector2 startingPos = Camera.TopLeftCorner; + startingPos.X += 200; + startingPos.Y += 450; + // Dropping enemies + + //m_enemyList = new List(); + //for (int i = 0; i < 120; i++) + //{ + // EnemyObj_Skeleton enemy = new EnemyObj_Skeleton(m_player, null, m_player.AttachedLevel, GameTypes.EnemyDifficulty.BASIC); + // enemy.Initialize(); + // m_enemyList.Add(enemy); + //} + + //m_enemyList = new List(); + //EnemyObj_Fireball fireBall = new EnemyObj_Fireball(m_player, null, m_player.AttachedLevel, GameTypes.EnemyDifficulty.MINIBOSS); + //fireBall.Initialize(); + //m_enemyList.Add(fireBall); + + //EnemyObj_Eyeball eyeball = new EnemyObj_Eyeball(m_player, null, m_player.AttachedLevel, GameTypes.EnemyDifficulty.MINIBOSS); + //eyeball.Initialize(); + //m_enemyList.Add(eyeball); + + //EnemyObj_Fairy fairy = new EnemyObj_Fairy(m_player, null, m_player.AttachedLevel, GameTypes.EnemyDifficulty.MINIBOSS); + //fairy.Initialize(); + //m_enemyList.Add(fairy); + + //EnemyObj_Blob blob = new EnemyObj_Blob(m_player, null, m_player.AttachedLevel, GameTypes.EnemyDifficulty.MINIBOSS); + //blob.Initialize(); + //m_enemyList.Add(blob); + + if (m_enemyList != null) + { + foreach (EnemyObj enemy in m_enemyList) + { + m_enemyStoredPositions.Add(enemy.Position); + enemy.Position = startingPos; + enemy.ChangeSprite(enemy.ResetSpriteName); + if (enemy.SpriteName == "EnemyZombieRise_Character") + enemy.ChangeSprite("EnemyZombieWalk_Character"); + enemy.Visible = true; + enemy.Flip = SpriteEffects.FlipHorizontally; + Tween.StopAllContaining(enemy, false); + enemy.Scale = enemy.InternalScale; + enemy.Scale /= 2; + enemy.Opacity = 0; + delay += 0.05f; + + // Special handling for the eyeball boss's pupil. + EnemyObj_Eyeball eyeBoss = enemy as EnemyObj_Eyeball; + if (eyeBoss != null && eyeBoss.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + eyeBoss.ChangeToBossPupil(); + + Tween.To(enemy, 0f, Tween.EaseNone, "delay", delay.ToString(), "Opacity", "1"); + Tween.RunFunction(delay, this, "PlayEnemySound"); + startingPos.X += 25; + if (enemy.X + enemy.Width > Camera.TopLeftCorner.X + 200 + 950) + { + startingPos.Y += 30; + startingPos.X = Camera.TopLeftCorner.X + 200; + } + } + } + } + + public void PlayEnemySound() + { + SoundManager.PlaySound("Enemy_Kill_Plant"); + } + + private void SetObjectKilledPlayerText() + { + TextObj playerSlainText = m_dialoguePlate.GetChildAt(1) as TextObj; + + try + { + playerSlainText.ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(playerSlainText)); + playerSlainText.Text = Game.PlayerStats.PlayerName; + if (LocaleBuilder.languageType != LanguageType.Chinese_Simp && Regex.IsMatch(playerSlainText.Text, @"\p{IsCyrillic}")) + playerSlainText.ChangeFontNoDefault(Game.RobotoSlabFont); + } + catch + { + playerSlainText.ChangeFontNoDefault(Game.NotoSansSCFont); + } + + if (m_debugEnemyLocID > 0) + playerSlainText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_4_NEW"), Game.NameHelper(), LocaleBuilder.getResourceString("LOC_ID_ENEMY_NAME_" + m_debugEnemyLocID)); + else + { + if (m_objKilledPlayer != null) + { + EnemyObj enemy = m_objKilledPlayer as EnemyObj; + ProjectileObj projectile = m_objKilledPlayer as ProjectileObj; + + if (enemy != null) + { + if (enemy.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS || enemy is EnemyObj_LastBoss) + playerSlainText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_3_NEW"), Game.NameHelper(), LocaleBuilder.getResourceString(enemy.LocStringID)); + //playerSlainText.Text = Game.PlayerStats.PlayerName + " " + LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_3") + " " + LocaleBuilder.getResourceString(enemy.LocStringID); + else + playerSlainText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_4_NEW"), Game.NameHelper(), LocaleBuilder.getResourceString(enemy.LocStringID)); + //playerSlainText.Text = Game.PlayerStats.PlayerName + " " + LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_4") + " " + LocaleBuilder.getResourceString(enemy.LocStringID); + } + else if (projectile != null) + { + enemy = projectile.Source as EnemyObj; + if (enemy != null) + { + if (enemy.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS || enemy is EnemyObj_LastBoss) + playerSlainText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_3_NEW"), Game.NameHelper(), LocaleBuilder.getResourceString(enemy.LocStringID)); + //playerSlainText.Text = Game.PlayerStats.PlayerName + " " + LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_3") + " " + LocaleBuilder.getResourceString(enemy.LocStringID); + else + playerSlainText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_4_NEW"), Game.NameHelper(), LocaleBuilder.getResourceString(enemy.LocStringID)); + //playerSlainText.Text = Game.PlayerStats.PlayerName + " " + LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_4") + " " + LocaleBuilder.getResourceString(enemy.LocStringID); + } + else + playerSlainText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_5_NEW"), Game.NameHelper()); + //playerSlainText.Text = Game.PlayerStats.PlayerName + " " + LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_5"); + } + + HazardObj hazard = m_objKilledPlayer as HazardObj; + if (hazard != null) + playerSlainText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_6_NEW"), Game.NameHelper()); + //playerSlainText.Text = Game.PlayerStats.PlayerName + " " + LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_6"); + } + else + playerSlainText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_7_NEW"), Game.NameHelper()); + //playerSlainText.Text = Game.PlayerStats.PlayerName + " " + LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_7"); + } + } + + public override void HandleInput() + { + if (m_lockControls == false) + { + if (m_droppingStats == true) + { + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + if (m_enemyList.Count > 0 && m_enemyList[m_enemyList.Count - 1].Opacity != 1) + { + foreach (EnemyObj enemy in m_enemyList) + { + Tween.StopAllContaining(enemy, false); + enemy.Opacity = 1; + } + Tween.StopAllContaining(this, false); + PlayEnemySound(); + } + else //if (m_continueText.Opacity == 1) + { + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Title, true, null); + m_lockControls = true; + } + } + } + } + base.HandleInput(); + } + + public override void Update(GameTime gameTime) + { + if (LevelEV.ENABLE_DEBUG_INPUT == true) + HandleDebugInput(); + + if (m_player.SpriteName == "PlayerDeath_Character") + { + m_playerFallSound.Update(); + m_playerSwordFallSound.Update(); + m_playerSwordSpinSound.Update(); + } + + base.Update(gameTime); + } + + private int m_debugGameHint = -1; + private int m_debugEnemyLocID = 0; + private int m_debugTotalEnemies = 127; + private void HandleDebugInput() + { + if (InputManager.JustPressed(Keys.Space, PlayerIndex.One)) + { + m_gameHint = m_debugGameHint; + Console.WriteLine("Changing to game hint index: " + m_debugGameHint); + + (m_dialoguePlate.GetChildAt(2) as TextObj).Text = LocaleBuilder.getResourceString(GameEV.GAME_HINTS[m_gameHint]); + //(m_dialoguePlate.GetChildAt(2) as TextObj).Text = + // LocaleBuilder.getString(GameEV.GAME_HINTS[m_gameHint, 0], m_dialoguePlate.GetChildAt(2) as TextObj) + + // GameEV.GAME_HINTS[m_gameHint, 1] + + // LocaleBuilder.getString(GameEV.GAME_HINTS[m_gameHint, 2], m_dialoguePlate.GetChildAt(2) as TextObj); + m_debugGameHint++; + if (m_debugGameHint >= GameEV.GAME_HINTS.GetLength(0)) + m_debugGameHint = 0; + } + + int previousEnemyLocID = m_debugEnemyLocID; + if (InputManager.JustPressed(Keys.OemOpenBrackets, null)) + m_debugEnemyLocID--; + else if (InputManager.JustPressed(Keys.OemCloseBrackets, null)) + m_debugEnemyLocID++; + + if (m_debugEnemyLocID <= 0 && m_debugEnemyLocID != -1) + m_debugEnemyLocID = m_debugTotalEnemies; + else if (m_debugEnemyLocID > m_debugTotalEnemies) + m_debugEnemyLocID = 1; + + if (m_debugEnemyLocID != previousEnemyLocID) + SetObjectKilledPlayerText(); + } + + public override void Draw(GameTime gameTime) + { + //Camera.GraphicsDevice.Clear(Color.Black); + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, Camera.GetTransformation()); // Parallax Effect has been disabled in favour of ripple effect for now. + Camera.Draw(Game.GenericTexture, new Rectangle((int)Camera.TopLeftCorner.X - 10, (int)Camera.TopLeftCorner.Y - 10, 1420, 820), Color.Black * BackBufferOpacity); + foreach (EnemyObj enemy in m_enemyList) + enemy.Draw(Camera); + m_playerFrame.Draw(Camera); + m_player.Draw(Camera); + if (m_playerGhost.Opacity > 0) + m_playerGhost.X += (float)Math.Sin(Game.TotalGameTime * 5) * 60 * (float)gameTime.ElapsedGameTime.TotalSeconds; + m_playerGhost.Draw(Camera); + Camera.End(); + + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null); // Parallax Effect has been disabled in favour of ripple effect for now. + m_spotlight.Draw(Camera); + m_dialoguePlate.Draw(Camera); + m_continueText.Draw(Camera); + Camera.End(); + + base.Draw(gameTime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Game Over Screen"); + + m_player = null; + m_dialoguePlate.Dispose(); + m_dialoguePlate = null; + m_continueText.Dispose(); + m_continueText = null; + m_playerGhost.Dispose(); + m_playerGhost = null; + m_spotlight.Dispose(); + m_spotlight = null; + + if (m_playerFallSound != null) + m_playerFallSound.Dispose(); + m_playerFallSound = null; + if (m_playerSwordFallSound != null) + m_playerSwordFallSound.Dispose(); + m_playerSwordFallSound = null; + if (m_playerSwordSpinSound != null) + m_playerSwordSpinSound.Dispose(); + m_playerSwordSpinSound = null; + + m_objKilledPlayer = null; + + if (m_enemyList != null) + m_enemyList.Clear(); + m_enemyList = null; + if (m_enemyStoredPositions != null) + m_enemyStoredPositions.Clear(); + m_enemyStoredPositions = null; + + m_playerFrame.Dispose(); + m_playerFrame = null; + base.Dispose(); + } + } + + public override void RefreshTextObjs() + { + //m_continueText.Text = LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_1") + " [Input:" + InputMapType.MENU_CONFIRM1 + "] " + LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_2"); + (m_dialoguePlate.GetChildAt(2) as TextObj).ChangeFontNoDefault(LocaleBuilder.GetLanguageFont((m_dialoguePlate.GetChildAt(2) as TextObj))); + (m_dialoguePlate.GetChildAt(3) as TextObj).ChangeFontNoDefault(LocaleBuilder.GetLanguageFont((m_dialoguePlate.GetChildAt(3) as TextObj))); + + if (Game.PlayerStats.Traits.X == TraitType.Tourettes || Game.PlayerStats.Traits.Y == TraitType.Tourettes) + { + (m_dialoguePlate.GetChildAt(2) as TextObj).Text = "#)!(%*#@!%^"; // not localized + (m_dialoguePlate.GetChildAt(2) as TextObj).RandomizeSentence(true); + } + else + { + (m_dialoguePlate.GetChildAt(2) as TextObj).Text = LocaleBuilder.getResourceString(GameEV.GAME_HINTS[m_gameHint]); + //(m_dialoguePlate.GetChildAt(2) as TextObj).Text = + // LocaleBuilder.getResourceString(GameEV.GAME_HINTS[m_gameHint, 0]) + + // GameEV.GAME_HINTS[m_gameHint, 1] + + // LocaleBuilder.getResourceString(GameEV.GAME_HINTS[m_gameHint, 2]); + } + + try + { + (m_dialoguePlate.GetChildAt(3) as TextObj).ChangeFontNoDefault(LocaleBuilder.GetLanguageFont((m_dialoguePlate.GetChildAt(3) as TextObj))); + (m_dialoguePlate.GetChildAt(3) as TextObj).Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_8_NEW"), Game.NameHelper()); //"'s Parting Words" + if (LocaleBuilder.languageType != LanguageType.Chinese_Simp && Regex.IsMatch((m_dialoguePlate.GetChildAt(3) as TextObj).Text, @"\p{IsCyrillic}")) + (m_dialoguePlate.GetChildAt(3) as TextObj).ChangeFontNoDefault(Game.RobotoSlabFont); + } + catch + { + (m_dialoguePlate.GetChildAt(3) as TextObj).ChangeFontNoDefault(Game.NotoSansSCFont); + (m_dialoguePlate.GetChildAt(3) as TextObj).Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_8_NEW"), Game.NameHelper()); //"'s Parting Words" + } + //(m_dialoguePlate.GetChildAt(3) as TextObj).Text = "-" + Game.PlayerStats.PlayerName + LocaleBuilder.getResourceString("LOC_ID_GAME_OVER_SCREEN_8"); + + FixHintTextSize(); + SetObjectKilledPlayerText(); + base.RefreshTextObjs(); + } + + private void FixHintTextSize() + { + TextObj partingWords = (m_dialoguePlate.GetChildAt(2) as TextObj); + partingWords.FontSize = 12; + partingWords.ScaleX = 1; + + switch (LocaleBuilder.languageType) + { + case(LanguageType.Russian): + if (m_gameHint == 6) + { + partingWords.FontSize = 11; + partingWords.ScaleX = 0.9f; + } + break; + case(LanguageType.French): + if (m_gameHint == 12 || m_gameHint == 20) + partingWords.ScaleX = 0.9f; + else if (m_gameHint == 35) + { + partingWords.FontSize = 10; + partingWords.ScaleX = 0.9f; + } + break; + case(LanguageType.German): + switch (m_gameHint) + { + case(18): + case(27): + case(29): + case(30): + case(35): + partingWords.ScaleX = 0.9f; + break; + } + break; + case(LanguageType.Portuguese_Brazil): + if (m_gameHint == 18) + partingWords.ScaleX = 0.9f; + break; + case(LanguageType.Polish): + if (m_gameHint == 18) + partingWords.ScaleX = 0.9f; + break; + case(LanguageType.Spanish_Spain): + if (m_gameHint == 29) + partingWords.ScaleX = 0.9f; + else if (m_gameHint == 35) + { + partingWords.FontSize = 11; + partingWords.ScaleX = 0.9f; + } + break; + } + } + } +} diff --git a/RogueCastle/src/Screens/GetItemScreen.cs b/RogueCastle/src/Screens/GetItemScreen.cs new file mode 100644 index 0000000..295ba44 --- /dev/null +++ b/RogueCastle/src/Screens/GetItemScreen.cs @@ -0,0 +1,705 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Tweener; +using Tweener.Ease; +using InputSystem; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Audio; + +namespace RogueCastle +{ + public class GetItemScreen : Screen + { + public float BackBufferOpacity { get; set; } + + /// Level Up Animation Variables /// + private SpriteObj m_levelUpBGImage; + private SpriteObj[] m_levelUpParticles; + + private byte m_itemType = GetItemType.None; + private Vector2 m_itemInfo; + private SpriteObj m_itemSprite; + private SpriteObj m_itemFoundSprite; + private TextObj m_itemFoundText; + private Vector2 m_itemStartPos; + private Vector2 m_itemEndPos; + private bool m_itemSpinning = false; + + private KeyIconTextObj m_continueText; + + private bool m_lockControls = false; + + private Cue m_buildUpSound; + private string m_songName; + private float m_storedMusicVolume; + + // Only for trip stat drops. + private SpriteObj m_tripStat1, m_tripStat2; + private TextObj m_tripStat1FoundText, m_tripStat2FoundText; + private Vector2 m_tripStatData; + + public GetItemScreen() + { + this.DrawIfCovered = true; + BackBufferOpacity = 0; + m_itemEndPos = new Vector2(1320 / 2f, 720 / 2f + 50); + } + + public override void LoadContent() + { + ////////// Loading Level up animation effects. + m_levelUpBGImage = new SpriteObj("BlueprintFoundBG_Sprite"); + m_levelUpBGImage.ForceDraw = true; + m_levelUpBGImage.Visible = false; + + m_levelUpParticles = new SpriteObj[10]; + for (int i = 0; i < m_levelUpParticles.Length; i++) + { + m_levelUpParticles[i] = new SpriteObj("LevelUpParticleFX_Sprite"); + m_levelUpParticles[i].AnimationDelay = 1 / 24f; + m_levelUpParticles[i].ForceDraw = true; + m_levelUpParticles[i].Visible = false; + } + + m_itemSprite = new SpriteObj("BlueprintIcon_Sprite"); + m_itemSprite.ForceDraw = true; + m_itemSprite.OutlineWidth = 2; + + m_tripStat1 = m_itemSprite.Clone() as SpriteObj; + m_tripStat2 = m_itemSprite.Clone() as SpriteObj; + + m_itemFoundText = new TextObj(Game.JunicodeFont); + m_itemFoundText.FontSize = 18; + m_itemFoundText.Align = Types.TextAlign.Centre; + m_itemFoundText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_itemFoundText); // dummy locID to add TextObj to language refresh list + m_itemFoundText.Position = m_itemEndPos; + m_itemFoundText.Y += 70; + m_itemFoundText.ForceDraw = true; + m_itemFoundText.OutlineWidth = 2; + + m_tripStat1FoundText = m_itemFoundText.Clone() as TextObj; + m_tripStat1FoundText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_tripStat1FoundText); // dummy locID to add TextObj to language refresh list + m_tripStat2FoundText = m_itemFoundText.Clone() as TextObj; + m_tripStat2FoundText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_tripStat2FoundText); // dummy locID to add TextObj to language refresh list + + m_itemFoundSprite = new SpriteObj("BlueprintFoundText_Sprite"); + m_itemFoundSprite.ForceDraw = true; + m_itemFoundSprite.Visible = false; + + m_continueText = new KeyIconTextObj(Game.JunicodeFont); + m_continueText.FontSize = 14; + m_continueText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_continueText); // dummy locID to add TextObj to language refresh list + //m_continueText.Align = Types.TextAlign.Centre; + //m_continueText.Position = new Vector2(1320 - m_continueText.Width, 720 - m_continueText.Height - 10); + m_continueText.Align = Types.TextAlign.Right; + m_continueText.Position = new Vector2(1320 - 20, 720 - m_continueText.Height - 10); + m_continueText.ForceDraw = true; + + base.LoadContent(); + } + + public override void PassInData(List objList) + { + m_itemStartPos = (Vector2)objList[0]; + m_itemType = (byte)objList[1]; + m_itemInfo = (Vector2)objList[2]; + if (m_itemType == GetItemType.TripStatDrop) + m_tripStatData = (Vector2)objList[3]; + + base.PassInData(objList); + } + + public override void OnEnter() + { + m_tripStat1.Visible = false; + m_tripStat2.Visible = false; + m_tripStat1.Scale = Vector2.One; + m_tripStat2.Scale = Vector2.One; + + // Do not auto save the game for fountain pieces. Otherwise the 'neo' player stats and equipment will be saved as well. + if (m_itemType != GetItemType.FountainPiece) + (ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData, SaveType.UpgradeData); + m_itemSprite.Rotation = 0; + m_itemSprite.Scale = Vector2.One; + m_itemStartPos.X -= Camera.TopLeftCorner.X; + m_itemStartPos.Y -= Camera.TopLeftCorner.Y; + + m_storedMusicVolume = SoundManager.GlobalMusicVolume; + m_songName = SoundManager.GetCurrentMusicName(); + m_lockControls = true; + m_continueText.Opacity = 0; + + m_continueText.Text = LocaleBuilder.getString("LOC_ID_GET_ITEM_SCREEN_1_NEW", m_continueText); + + m_itemFoundText.Position = m_itemEndPos; + m_itemFoundText.Y += 70; + + m_itemFoundText.Scale = Vector2.Zero; + + m_tripStat1FoundText.Position = m_itemFoundText.Position; + m_tripStat2FoundText.Position = m_itemFoundText.Position; + m_tripStat1FoundText.Scale = Vector2.Zero; + m_tripStat2FoundText.Scale = Vector2.Zero; + m_tripStat1FoundText.Visible = false; + m_tripStat2FoundText.Visible = false; + + switch (m_itemType) + { + case (GetItemType.Blueprint): + m_itemSpinning = true; + m_itemSprite.ChangeSprite("BlueprintIcon_Sprite"); + m_itemFoundSprite.ChangeSprite("BlueprintFoundText_Sprite"); + m_itemFoundText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_BASE_FORMAT", true), LocaleBuilder.getResourceString(EquipmentBaseType.ToStringID((int)m_itemInfo.Y), true), LocaleBuilder.getResourceString(EquipmentCategoryType.ToStringID((int)m_itemInfo.X), true)); + + break; + case (GetItemType.Rune): + m_itemSpinning = true; + m_itemSprite.ChangeSprite("RuneIcon_Sprite"); + m_itemFoundSprite.ChangeSprite("RuneFoundText_Sprite"); + //m_itemFoundText.Text = LocaleBuilder.getResourceString(EquipmentAbilityType.ToStringID((int)m_itemInfo.Y)) + " " + LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_13") /* Rune */ + " (" + LocaleBuilder.getResourceString(EquipmentCategoryType.ToStringID2((int)m_itemInfo.X)) + ")"; + m_itemFoundText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_RUNE_BASE_FORMAT", true), LocaleBuilder.getResourceString(EquipmentAbilityType.ToStringID((int)m_itemInfo.Y), true), LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_13"), true) /*"Rune"*/ + "\n(" + LocaleBuilder.getResourceString(EquipmentCategoryType.ToStringID2((int)m_itemInfo.X), true) + ")"; + m_itemSprite.AnimationDelay = 1 / 20f; + + GameUtil.UnlockAchievement("LOVE_OF_MAGIC"); + break; + case (GetItemType.StatDrop): + case (GetItemType.TripStatDrop): + + m_itemSprite.ChangeSprite(this.GetStatSpriteName((int)m_itemInfo.X)); + m_itemFoundText.Text = this.GetStatText((int)m_itemInfo.X); + m_itemSprite.AnimationDelay = 1 / 20f; + m_itemFoundSprite.ChangeSprite("StatFoundText_Sprite"); + + if (m_itemType == GetItemType.TripStatDrop) + { + m_tripStat1FoundText.Visible = true; + m_tripStat2FoundText.Visible = true; + + m_tripStat1.ChangeSprite(this.GetStatSpriteName((int)m_tripStatData.X)); + m_tripStat2.ChangeSprite(this.GetStatSpriteName((int)m_tripStatData.Y)); + m_tripStat1.Visible = true; + m_tripStat2.Visible = true; + m_tripStat1.AnimationDelay = 1 / 20f; + m_tripStat2.AnimationDelay = 1 / 20f; + Tween.RunFunction(0.1f, m_tripStat1, "PlayAnimation", true); // Adds a delay to the trip stat animations (so that they don't animate all at the same time). + Tween.RunFunction(0.2f, m_tripStat2, "PlayAnimation", true); // Adds a delay to the trip stat animations (so that they don't animate all at the same time). + m_tripStat1FoundText.Text = this.GetStatText((int)m_tripStatData.X); + m_tripStat2FoundText.Text = this.GetStatText((int)m_tripStatData.Y); + + m_itemFoundText.Y += 50; + m_tripStat1FoundText.Y = m_itemFoundText.Y + 50; + } + + break; + case (GetItemType.SpecialItem): + m_itemSprite.ChangeSprite(SpecialItemType.SpriteName((byte)m_itemInfo.X)); + m_itemFoundSprite.ChangeSprite("ItemFoundText_Sprite"); + m_itemFoundText.Text = LocaleBuilder.getString(SpecialItemType.ToStringID((byte)m_itemInfo.X), m_itemFoundText); + break; + case (GetItemType.Spell): + m_itemSprite.ChangeSprite(SpellType.Icon((byte)m_itemInfo.X)); + m_itemFoundSprite.ChangeSprite("SpellFoundText_Sprite"); + m_itemFoundText.Text = LocaleBuilder.getString(SpellType.ToStringID((byte)m_itemInfo.X), m_itemFoundText); + break; + case (GetItemType.FountainPiece): + m_itemSprite.ChangeSprite(GetMedallionImage((int)m_itemInfo.X)); // This needs to change to reflect the stat stored in m_itemInfo.X + m_itemFoundSprite.ChangeSprite("ItemFoundText_Sprite"); + if (m_itemInfo.X == ItemDropType.FountainPiece5) + m_itemFoundText.Text = LocaleBuilder.getString("LOC_ID_GET_ITEM_SCREEN_8", m_itemFoundText); + else + m_itemFoundText.Text = LocaleBuilder.getString("LOC_ID_GET_ITEM_SCREEN_9", m_itemFoundText); + break; + } + + m_itemSprite.PlayAnimation(true); + ItemSpinAnimation(); + + RefreshTextObjs(); + + base.OnEnter(); + } + + private void ItemSpinAnimation() + { + m_itemSprite.Scale = Vector2.One; + m_itemSprite.Position = m_itemStartPos; + + m_buildUpSound = SoundManager.PlaySound("GetItemBuildupStinger"); + Tween.To(typeof(SoundManager), 1, Tween.EaseNone, "GlobalMusicVolume", (m_storedMusicVolume * 0.1f).ToString()); + m_itemSprite.Scale = new Vector2(35f / m_itemSprite.Height, 35f / m_itemSprite.Height); + Tween.By(m_itemSprite, 0.5f, Back.EaseOut, "Y", "-150"); + Tween.RunFunction(0.7f, this, "ItemSpinAnimation2"); + + // Trip stat code. + m_tripStat1.Scale = Vector2.One; + m_tripStat2.Scale = Vector2.One; + + m_tripStat1.Position = m_itemStartPos; + m_tripStat2.Position = m_itemStartPos; + Tween.By(m_tripStat1, 0.5f, Back.EaseOut, "Y", "-150", "X", "50"); + m_tripStat1.Scale = new Vector2(35f / m_tripStat1.Height, 35f / m_tripStat1.Height); + Tween.By(m_tripStat2, 0.5f, Back.EaseOut, "Y", "-150", "X", "-50"); + m_tripStat2.Scale = new Vector2(35f / m_tripStat2.Height, 35f / m_tripStat2.Height); + } + + public void ItemSpinAnimation2() + { + Tween.RunFunction(0.2f, typeof(SoundManager), "PlaySound", "GetItemStinger3"); + if (m_buildUpSound != null && m_buildUpSound.IsPlaying) + m_buildUpSound.Stop(AudioStopOptions.AsAuthored); + Tween.To(m_itemSprite, 0.2f, Quad.EaseOut, "ScaleX", "0.1", "ScaleY", "0.1"); + Tween.AddEndHandlerToLastTween(this, "ItemSpinAnimation3"); + + ////////////// Animations for trip stat. + Tween.To(m_tripStat1, 0.2f, Quad.EaseOut, "ScaleX", "0.1", "ScaleY", "0.1"); + Tween.To(m_tripStat2, 0.2f, Quad.EaseOut, "ScaleX", "0.1", "ScaleY", "0.1"); + } + + public void ItemSpinAnimation3() + { + Vector2 spriteScale = m_itemSprite.Scale; + m_itemSprite.Scale = Vector2.One; + float itemScale = 130f / m_itemSprite.Height; + m_itemSprite.Scale = spriteScale; + //Tween.To(m_itemSprite, 0.2f, Tween.EaseNone, "ScaleX", "1.2", "ScaleY", "1.2"); + Tween.To(m_itemSprite, 0.2f, Tween.EaseNone, "ScaleX", itemScale.ToString(), "ScaleY", itemScale.ToString()); + Tween.To(m_itemSprite, 0.2f, Tween.EaseNone, "X", (1320 / 2).ToString(), "Y", (720 / 2 + 30).ToString()); + Tween.To(m_itemFoundText, 0.3f, Back.EaseOut, "ScaleX", "1", "ScaleY", "1"); + Tween.To(m_continueText, 0.3f, Linear.EaseNone, "Opacity", "1"); + + ////////////////// Animations for trip stats. + spriteScale = m_tripStat1.Scale; + m_tripStat1.Scale = Vector2.One; + itemScale = 130f / m_tripStat1.Height; + m_tripStat1.Scale = spriteScale; + Tween.To(m_tripStat1, 0.2f, Tween.EaseNone, "ScaleX", itemScale.ToString(), "ScaleY", itemScale.ToString()); + Tween.To(m_tripStat1, 0.2f, Tween.EaseNone, "X", (1320 / 2 + 170).ToString(), "Y", (720 / 2 + 30).ToString()); + + spriteScale = m_tripStat2.Scale; + m_tripStat2.Scale = Vector2.One; + itemScale = 130f / m_tripStat2.Height; + m_tripStat2.Scale = spriteScale; + Tween.To(m_tripStat2, 0.2f, Tween.EaseNone, "ScaleX", itemScale.ToString(), "ScaleY", itemScale.ToString()); + Tween.To(m_tripStat2, 0.2f, Tween.EaseNone, "X", (1320 / 2 - 170).ToString(), "Y", (720 / 2 + 30).ToString()); + + Tween.To(m_tripStat1FoundText, 0.3f, Back.EaseOut, "ScaleX", "1", "ScaleY", "1"); + Tween.To(m_tripStat2FoundText, 0.3f, Back.EaseOut, "ScaleX", "1", "ScaleY", "1"); + + ///////////////////////////////////// + + for (int i = 0; i < m_levelUpParticles.Length; i++) + { + m_levelUpParticles[i].AnimationDelay = 0; + m_levelUpParticles[i].Visible = true; + m_levelUpParticles[i].Scale = new Vector2(0.1f, 0.1f); + m_levelUpParticles[i].Opacity = 0; + m_levelUpParticles[i].Position = new Vector2(GlobalEV.ScreenWidth / 2f, GlobalEV.ScreenHeight / 2f); + m_levelUpParticles[i].Position += new Vector2(CDGMath.RandomInt(-100, 100), CDGMath.RandomInt(-50, 50)); + float randDelay = CDGMath.RandomFloat(0, 0.5f); + Tween.To(m_levelUpParticles[i], 0.2f, Tweener.Ease.Linear.EaseNone, "delay", randDelay.ToString(), "Opacity", "1"); + Tween.To(m_levelUpParticles[i], 0.5f, Tweener.Ease.Linear.EaseNone, "delay", randDelay.ToString(), "ScaleX", "2", "ScaleY", "2"); + Tween.To(m_levelUpParticles[i], randDelay, Tweener.Ease.Linear.EaseNone); + Tween.AddEndHandlerToLastTween(m_levelUpParticles[i], "PlayAnimation", false); + } + + m_itemFoundSprite.Position = new Vector2(GlobalEV.ScreenWidth / 2f, GlobalEV.ScreenHeight / 2f - 170); + m_itemFoundSprite.Scale = Vector2.Zero; + m_itemFoundSprite.Visible = true; + Tween.To(m_itemFoundSprite, 0.5f, Tweener.Ease.Back.EaseOut, "delay", "0.05", "ScaleX", "1", "ScaleY", "1"); + + m_levelUpBGImage.Position = m_itemFoundSprite.Position; + m_levelUpBGImage.Y += 30; + m_levelUpBGImage.Scale = Vector2.Zero; + m_levelUpBGImage.Visible = true; + Tween.To(m_levelUpBGImage, 0.5f, Tweener.Ease.Back.EaseOut, "ScaleX", "1", "ScaleY", "1"); + + Tween.To(this, 0.5f, Linear.EaseNone, "BackBufferOpacity", "0.5"); + if (m_itemSpinning == true) + m_itemSprite.Rotation = -25; + m_itemSpinning = false; + + Tween.RunFunction(0.5f, this, "UnlockControls"); + } + + public void UnlockControls() + { + m_lockControls = false; + } + + public void ExitScreenTransition() + { + if ((int)m_itemInfo.X == ItemDropType.FountainPiece5) + { + m_itemInfo = Vector2.Zero; + List data = new List(); + data.Add(SkillUnlockType.Traitor); + Game.ScreenManager.DisplayScreen(ScreenType.SkillUnlock, true, data); + } + else + { + m_lockControls = true; + Tween.To(typeof(SoundManager), 1, Tween.EaseNone, "GlobalMusicVolume", m_storedMusicVolume.ToString()); + + Tween.To(m_itemSprite, 0.4f, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + Tween.To(m_itemFoundText, 0.4f, Back.EaseIn, "delay", "0.1", "ScaleX", "0", "ScaleY", "0"); + Tween.To(this, 0.4f, Back.EaseIn, "BackBufferOpacity", "0"); + Tween.To(m_levelUpBGImage, 0.4f, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + Tween.To(m_itemFoundSprite, 0.4f, Back.EaseIn, "delay", "0.1", "ScaleX", "0", "ScaleY", "0"); + Tween.To(m_continueText, 0.4f, Linear.EaseNone, "delay", "0.1", "Opacity", "0"); + Tween.AddEndHandlerToLastTween((ScreenManager as RCScreenManager), "HideCurrentScreen"); + + Tween.To(m_tripStat1, 0.4f, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + Tween.To(m_tripStat2, 0.4f, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + Tween.To(m_tripStat1FoundText, 0.4f, Back.EaseIn, "delay", "0.1", "ScaleX", "0", "ScaleY", "0"); + Tween.To(m_tripStat2FoundText, 0.4f, Back.EaseIn, "delay", "0.1", "ScaleX", "0", "ScaleY", "0"); + } + } + + public override void Update(GameTime gameTime) + { + if (m_itemSpinning == true) + m_itemSprite.Rotation += (1200 * (float)gameTime.ElapsedGameTime.TotalSeconds); + //m_itemSprite.Rotation += 20; + base.Update(gameTime); + } + + public override void HandleInput() + { + if (m_lockControls == false) + { + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + ExitScreenTransition(); + + if (LevelEV.ENABLE_DEBUG_INPUT == true) + HandleDebugInput(); + } + + base.HandleInput(); + } + + private void HandleDebugInput() + { + Vector2 previousItemInfo = m_itemInfo; + switch (m_itemType) + { + case (GetItemType.Blueprint): + if (InputManager.JustPressed(Keys.OemOpenBrackets, null)) + { + m_itemInfo.Y--; + if (m_itemInfo.Y < 0) + { + m_itemInfo.X--; + m_itemInfo.Y = EquipmentBaseType.Total - 1; + if (m_itemInfo.X < 0) + m_itemInfo.X = EquipmentCategoryType.Total - 1; + } + } + else if (InputManager.JustPressed(Keys.OemCloseBrackets, null)) + { + m_itemInfo.Y++; + if (m_itemInfo.Y >= EquipmentBaseType.Total) + { + m_itemInfo.X++; + m_itemInfo.Y = 0; + if (m_itemInfo.X >= EquipmentCategoryType.Total) + m_itemInfo.X = 0; + } + } + if (previousItemInfo != m_itemInfo) + m_itemFoundText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_BASE_FORMAT", true), LocaleBuilder.getResourceString(EquipmentBaseType.ToStringID((int)m_itemInfo.Y), true), LocaleBuilder.getResourceString(EquipmentCategoryType.ToStringID((int)m_itemInfo.X), true)); + break; + case (GetItemType.Rune): + if (InputManager.JustPressed(Keys.OemOpenBrackets, null)) + { + m_itemInfo.Y--; + if (m_itemInfo.Y < 0) + { + m_itemInfo.X--; + m_itemInfo.Y = EquipmentAbilityType.Total - 1; + if (m_itemInfo.X < 0) + m_itemInfo.X = EquipmentCategoryType.Total - 1; + } + } + else if (InputManager.JustPressed(Keys.OemCloseBrackets, null)) + { + m_itemInfo.Y++; + if (m_itemInfo.Y >= EquipmentAbilityType.Total) + { + m_itemInfo.X++; + m_itemInfo.Y = 0; + if (m_itemInfo.X >= EquipmentCategoryType.Total) + m_itemInfo.X = 0; + } + } + if (previousItemInfo != m_itemInfo) + m_itemFoundText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_RUNE_BASE_FORMAT", true), LocaleBuilder.getResourceString(EquipmentAbilityType.ToStringID((int)m_itemInfo.Y), true), LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_13"), true) /*"Rune"*/ + " (" + LocaleBuilder.getResourceString(EquipmentCategoryType.ToStringID2((int)m_itemInfo.X), true) + ")"; + break; + case (GetItemType.StatDrop): + if (InputManager.JustPressed(Keys.OemOpenBrackets, null)) + { + m_itemInfo.X--; + if (m_itemInfo.X < ItemDropType.Stat_Strength) + m_itemInfo.X = ItemDropType.Stat_Weight; + } + else if (InputManager.JustPressed(Keys.OemCloseBrackets, null)) + { + m_itemInfo.X++; + if (m_itemInfo.X > ItemDropType.Stat_Weight) + m_itemInfo.X = ItemDropType.Stat_Strength; + } + + if (previousItemInfo != m_itemInfo) + m_itemFoundText.Text = this.GetStatText((int)m_itemInfo.X); + break; + case (GetItemType.SpecialItem): + if (InputManager.JustPressed(Keys.OemOpenBrackets, null)) + { + m_itemInfo.X--; + if (m_itemInfo.X == SpecialItemType.Total) + m_itemInfo.X--; + if (m_itemInfo.X < SpecialItemType.FreeEntrance) + m_itemInfo.X = SpecialItemType.LastBossToken; + } + else if (InputManager.JustPressed(Keys.OemCloseBrackets, null)) + { + m_itemInfo.X++; + if (m_itemInfo.X == SpecialItemType.Total) + m_itemInfo.X++; + if (m_itemInfo.X > SpecialItemType.LastBossToken) + m_itemInfo.X = SpecialItemType.FreeEntrance; + } + + if (previousItemInfo != m_itemInfo) + m_itemFoundText.Text = LocaleBuilder.getString(SpecialItemType.ToStringID((byte)m_itemInfo.X), m_itemFoundText); + break; + case (GetItemType.Spell): + if (InputManager.JustPressed(Keys.OemOpenBrackets, null)) + { + m_itemInfo.X--; + if (m_itemInfo.X < SpellType.Dagger) + m_itemInfo.X = SpellType.Total - 1; + } + else if (InputManager.JustPressed(Keys.OemCloseBrackets, null)) + { + m_itemInfo.X++; + if (m_itemInfo.X > SpellType.Total - 1) + m_itemInfo.X = SpellType.Dagger; + } + + if (previousItemInfo != m_itemInfo) + m_itemFoundText.Text = LocaleBuilder.getString(SpellType.ToStringID((byte)m_itemInfo.X), m_itemFoundText); + + break; + case (GetItemType.FountainPiece): + if (InputManager.JustPressed(Keys.OemOpenBrackets, null) || (InputManager.JustPressed(Keys.OemCloseBrackets, null))) + { + if (m_itemInfo.X != ItemDropType.FountainPiece5) + m_itemInfo.X = ItemDropType.FountainPiece5; + else + m_itemInfo.X = ItemDropType.FountainPiece1; + } + + if (previousItemInfo != m_itemInfo) + { + if (m_itemInfo.X == ItemDropType.FountainPiece5) + m_itemFoundText.Text = LocaleBuilder.getString("LOC_ID_GET_ITEM_SCREEN_8", m_itemFoundText); + else + m_itemFoundText.Text = LocaleBuilder.getString("LOC_ID_GET_ITEM_SCREEN_9", m_itemFoundText); + } + break; + } + } + + public override void Draw(GameTime gameTime) + { + Camera.Begin(SpriteSortMode.Immediate, null, SamplerState.LinearClamp, null, null); + Camera.Draw(Game.GenericTexture, new Rectangle(0, 0, GlobalEV.ScreenWidth, GlobalEV.ScreenHeight), Color.Black * BackBufferOpacity); + + //// Level up animation sprites. + m_levelUpBGImage.Draw(Camera); + foreach (SpriteObj sprite in m_levelUpParticles) + sprite.Draw(Camera); + + m_itemFoundSprite.Draw(Camera); + m_itemFoundText.Draw(Camera); + m_tripStat1FoundText.Draw(Camera); + m_tripStat2FoundText.Draw(Camera); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + m_itemSprite.Draw(Camera); + m_tripStat1.Draw(Camera); + m_tripStat2.Draw(Camera); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + m_continueText.Draw(Camera); + Camera.End(); + + base.Draw(gameTime); + } + + private string GetStatSpriteName(int type) + { + switch (type) + { + case (ItemDropType.Stat_MaxHealth): + return "Heart_Sprite"; + case (ItemDropType.Stat_MaxMana): + return "ManaCrystal_Sprite"; + case (ItemDropType.Stat_Strength): + return "Sword_Sprite"; + case (ItemDropType.Stat_Magic): + return "MagicBook_Sprite"; + case (ItemDropType.Stat_Defense): + return "Shield_Sprite"; + case (ItemDropType.Stat_Weight): + return "Backpack_Sprite"; + } + return ""; + } + + private string GetStatText(int type) + { + switch (type) + { + case (ItemDropType.Stat_MaxHealth): + return LocaleBuilder.getResourceString("LOC_ID_GET_ITEM_SCREEN_2") + ": +" + (GameEV.ITEM_STAT_MAXHP_AMOUNT * (1 + Game.PlayerStats.TimesCastleBeaten)); + case (ItemDropType.Stat_MaxMana): + return LocaleBuilder.getResourceString("LOC_ID_GET_ITEM_SCREEN_3") + ": +" + (GameEV.ITEM_STAT_MAXMP_AMOUNT * (1 + Game.PlayerStats.TimesCastleBeaten)); + case (ItemDropType.Stat_Strength): + return LocaleBuilder.getResourceString("LOC_ID_GET_ITEM_SCREEN_4") + ": +" + (GameEV.ITEM_STAT_STRENGTH_AMOUNT * (1 + Game.PlayerStats.TimesCastleBeaten)); + case (ItemDropType.Stat_Magic): + return LocaleBuilder.getResourceString("LOC_ID_GET_ITEM_SCREEN_5") + ": +" + (GameEV.ITEM_STAT_MAGIC_AMOUNT * (1 + Game.PlayerStats.TimesCastleBeaten)); + case (ItemDropType.Stat_Defense): + return LocaleBuilder.getResourceString("LOC_ID_GET_ITEM_SCREEN_6") + ": +" + (GameEV.ITEM_STAT_ARMOR_AMOUNT * (1 + Game.PlayerStats.TimesCastleBeaten)); + case (ItemDropType.Stat_Weight): + return LocaleBuilder.getResourceString("LOC_ID_GET_ITEM_SCREEN_7") + ": +" + (GameEV.ITEM_STAT_WEIGHT_AMOUNT * (1 + Game.PlayerStats.TimesCastleBeaten)); + } + return ""; + } + + private string GetMedallionImage(int medallionType) + { + switch (medallionType) + { + case (ItemDropType.FountainPiece1): + return "MedallionPiece1_Sprite"; + case(ItemDropType.FountainPiece2): + return "MedallionPiece2_Sprite"; + case (ItemDropType.FountainPiece3): + return "MedallionPiece3_Sprite"; + case (ItemDropType.FountainPiece4): + return "MedallionPiece4_Sprite"; + case (ItemDropType.FountainPiece5): + return "MedallionPiece5_Sprite"; + } + return ""; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Get Item Screen"); + + m_continueText.Dispose(); + m_continueText = null; + m_levelUpBGImage.Dispose(); + m_levelUpBGImage = null; + + foreach (SpriteObj sprite in m_levelUpParticles) + sprite.Dispose(); + Array.Clear(m_levelUpParticles, 0, m_levelUpParticles.Length); + m_levelUpParticles = null; + + m_buildUpSound = null; + + m_itemSprite.Dispose(); + m_itemSprite = null; + m_itemFoundSprite.Dispose(); + m_itemFoundSprite = null; + m_itemFoundText.Dispose(); + m_itemFoundText = null; + + m_tripStat1.Dispose(); + m_tripStat2.Dispose(); + m_tripStat1 = null; + m_tripStat2 = null; + m_tripStat1FoundText.Dispose(); + m_tripStat2FoundText.Dispose(); + m_tripStat1FoundText = null; + m_tripStat2FoundText = null; + base.Dispose(); + } + } + + public override void RefreshTextObjs() + { + //m_continueText.Text = "[Input:" + InputMapType.MENU_CONFIRM1 + "] " + LocaleBuilder.getResourceString("LOC_ID_GET_ITEM_SCREEN_1"); + switch (m_itemType) + { + case (GetItemType.Blueprint): + m_itemFoundText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_BASE_FORMAT", true), LocaleBuilder.getResourceString(EquipmentBaseType.ToStringID((int)m_itemInfo.Y), true), LocaleBuilder.getResourceString(EquipmentCategoryType.ToStringID((int)m_itemInfo.X), true)); + break; + case (GetItemType.Rune): + m_itemFoundText.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_RUNE_BASE_FORMAT", true), LocaleBuilder.getResourceString(EquipmentAbilityType.ToStringID((int)m_itemInfo.Y), true), LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_13"), true) /*"Rune"*/ + " (" + LocaleBuilder.getResourceString(EquipmentCategoryType.ToStringID2((int)m_itemInfo.X), true) + ")"; + //m_itemFoundText.Text = LocaleBuilder.getResourceString(EquipmentAbilityType.ToStringID((int)m_itemInfo.Y)) + " " + LocaleBuilder.getResourceString("LOC_ID_ENCHANTRESS_SCREEN_13") /* Rune */ + " (" + LocaleBuilder.getResourceString(EquipmentCategoryType.ToStringID2((int)m_itemInfo.X)) + ")"; + break; + case (GetItemType.StatDrop): + case (GetItemType.TripStatDrop): + m_itemFoundText.Text = this.GetStatText((int)m_itemInfo.X); + if (m_itemType == GetItemType.TripStatDrop) + { + m_tripStat1FoundText.Text = this.GetStatText((int)m_tripStatData.X); + m_tripStat2FoundText.Text = this.GetStatText((int)m_tripStatData.Y); + } + break; + case (GetItemType.SpecialItem): + m_itemFoundText.Text = LocaleBuilder.getString(SpecialItemType.ToStringID((byte)m_itemInfo.X), m_itemFoundText); + break; + case (GetItemType.Spell): + m_itemFoundText.Text = LocaleBuilder.getString(SpellType.ToStringID((byte)m_itemInfo.X), m_itemFoundText); + break; + case (GetItemType.FountainPiece): + if (m_itemInfo.X == ItemDropType.FountainPiece5) + m_itemFoundText.Text = LocaleBuilder.getString("LOC_ID_GET_ITEM_SCREEN_8", m_itemFoundText); + else + m_itemFoundText.Text = LocaleBuilder.getString("LOC_ID_GET_ITEM_SCREEN_9", m_itemFoundText); + break; + } + + RefreshBitmaps(); + + base.RefreshTextObjs(); + } + + private void RefreshBitmaps() + { + switch (m_itemType) + { + case (GetItemType.Blueprint): + Game.ChangeBitmapLanguage(m_itemFoundSprite, "BlueprintFoundText_Sprite"); + break; + case (GetItemType.Rune): + Game.ChangeBitmapLanguage(m_itemFoundSprite, "RuneFoundText_Sprite"); + break; + case (GetItemType.StatDrop): + case (GetItemType.TripStatDrop): + Game.ChangeBitmapLanguage(m_itemFoundSprite, "StatFoundText_Sprite"); + break; + case (GetItemType.SpecialItem): + case (GetItemType.FountainPiece): + Game.ChangeBitmapLanguage(m_itemFoundSprite, "ItemFoundText_Sprite"); + break; + case (GetItemType.Spell): + Game.ChangeBitmapLanguage(m_itemFoundSprite, "SpellFoundText_Sprite"); + break; + } + + } + } +} diff --git a/RogueCastle/src/Screens/LineageScreen.cs b/RogueCastle/src/Screens/LineageScreen.cs new file mode 100644 index 0000000..54cf1ee --- /dev/null +++ b/RogueCastle/src/Screens/LineageScreen.cs @@ -0,0 +1,1076 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using DS2DEngine; +using Microsoft.Xna.Framework.Audio; +using Microsoft.Xna.Framework.Input; +using InputSystem; +using System.Text.RegularExpressions; + +namespace RogueCastle +{ + public class LineageScreen : Screen + { + private SpriteObj m_titleText; + + private LineageObj m_startingLineageObj; + private LineageObj m_selectedLineageObj; + + private int m_selectedLineageIndex = 0; + private List m_currentBranchArray; + private List m_masterArray; + + private Vector2 m_startingPoint; + private Vector2 m_currentPoint; + + private BackgroundObj m_background; + private SpriteObj m_bgShadow; + private Tweener.TweenObject m_selectTween; + + private int m_xPosOffset = 400; + + private ObjContainer m_descriptionPlate; + private int m_xShift = 0; + + private float m_storedMusicVol; + + private KeyIconTextObj m_confirmText; + private KeyIconTextObj m_navigationText; + private KeyIconTextObj m_rerollText; + + private bool m_lockControls; + + public LineageScreen() + { + m_startingPoint = new Vector2(1320 / 2, 720 / 2); + m_currentPoint = m_startingPoint; + } + + public override void LoadContent() + { + Game.HSVEffect.Parameters["Saturation"].SetValue(0); // What is this for? + + m_background = new BackgroundObj("LineageScreenBG_Sprite"); + m_background.SetRepeated(true, true, Camera); + m_background.X -= 1320 * 5; + + m_bgShadow = new SpriteObj("LineageScreenShadow_Sprite"); + m_bgShadow.Scale = new Vector2(11, 11); + m_bgShadow.Y -= 10; + m_bgShadow.ForceDraw = true; + m_bgShadow.Opacity = 0.9f; + m_bgShadow.Position = new Vector2(1320 / 2f, 720 / 2f); + + m_titleText = new SpriteObj("LineageTitleText_Sprite"); + m_titleText.X = GlobalEV.ScreenWidth / 2; + m_titleText.Y = GlobalEV.ScreenHeight * 0.1f; + m_titleText.ForceDraw = true; + + int xPlatePos = 20; + m_descriptionPlate = new ObjContainer("LineageScreenPlate_Character"); + m_descriptionPlate.ForceDraw = true; + m_descriptionPlate.Position = new Vector2(1320 - m_descriptionPlate.Width - 30, (720 - m_descriptionPlate.Height)/2f); + + TextObj playerTitle = new TextObj(Game.JunicodeFont); + playerTitle.FontSize = 12; + playerTitle.Align = Types.TextAlign.Centre; + playerTitle.OutlineColour = new Color(181, 142, 39); + playerTitle.OutlineWidth = 2; + playerTitle.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", playerTitle); // dummy locID to add TextObj to language refresh list + playerTitle.OverrideParentScale = true; + playerTitle.Position = new Vector2(m_descriptionPlate.Width / 2f, 15); + playerTitle.LimitCorners = true; + m_descriptionPlate.AddChild(playerTitle); + + TextObj className = playerTitle.Clone() as TextObj; + className.FontSize = 10; + className.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", className); // dummy locID to add TextObj to language refresh list + className.Align = Types.TextAlign.Left; + className.X = xPlatePos; + className.Y += 40; + m_descriptionPlate.AddChild(className); + + KeyIconTextObj classDescription = new KeyIconTextObj(Game.JunicodeFont); + classDescription.FontSize = 8; + classDescription.OutlineColour = className.OutlineColour; + classDescription.OutlineWidth = 2; + classDescription.OverrideParentScale = true; + classDescription.Position = className.Position; + classDescription.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", classDescription); // dummy locID to add TextObj to language refresh list + classDescription.Align = Types.TextAlign.Left; + classDescription.Y += 30; + classDescription.X = xPlatePos + 20; + classDescription.LimitCorners = true; + m_descriptionPlate.AddChild(classDescription); + + for (int i = 0; i < 2; i++) + { + TextObj traitName = className.Clone() as TextObj; + traitName.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", traitName); // dummy locID to add TextObj to language refresh list + traitName.X = xPlatePos; + traitName.Align = Types.TextAlign.Left; + if (i > 0) + traitName.Y = m_descriptionPlate.GetChildAt(m_descriptionPlate.NumChildren -1).Y + 50; + m_descriptionPlate.AddChild(traitName); + + TextObj traitDescription = className.Clone() as TextObj; + traitDescription.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", traitDescription); // dummy locID to add TextObj to language refresh list + traitDescription.X = xPlatePos + 20; + traitDescription.FontSize = 8; + traitDescription.Align = Types.TextAlign.Left; + m_descriptionPlate.AddChild(traitDescription); + } + + TextObj spellName = className.Clone() as TextObj; + spellName.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", spellName); // dummy locID to add TextObj to language refresh list + spellName.FontSize = 10; + spellName.X = xPlatePos; + spellName.Align = Types.TextAlign.Left; + m_descriptionPlate.AddChild(spellName); + + //TextObj spellDescription = className.Clone() as TextObj; + KeyIconTextObj spellDescription = new KeyIconTextObj(Game.JunicodeFont); + spellDescription.OutlineColour = new Color(181, 142, 39); + spellDescription.OutlineWidth = 2; + spellDescription.OverrideParentScale = true; + spellDescription.Position = new Vector2(m_descriptionPlate.Width / 2f, 15); + spellDescription.Y += 40; + spellDescription.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", spellDescription); // dummy locID to add TextObj to language refresh list + spellDescription.X = xPlatePos + 20; + spellDescription.FontSize = 8; + spellDescription.Align = Types.TextAlign.Left; + spellDescription.LimitCorners = true; + //spellDescription.ForcedScale = new Vector2(1.5f, 1.5f); + m_descriptionPlate.AddChild(spellDescription); + + m_masterArray = new List(); + m_currentBranchArray = new List(); + + Vector2 startingPos = Vector2.Zero; // The starting position for the current branch to be added. + + m_confirmText = new KeyIconTextObj(Game.JunicodeFont); + m_confirmText.ForceDraw = true; + m_confirmText.FontSize = 12; + m_confirmText.DropShadow = new Vector2(2, 2); + m_confirmText.Position = new Vector2(1320 - 40, 630); + m_confirmText.Align = Types.TextAlign.Right; + m_confirmText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_confirmText); // dummy locID to add TextObj to language refresh list + + m_navigationText = new KeyIconTextObj(Game.JunicodeFont); + m_navigationText.Align = Types.TextAlign.Right; + m_navigationText.FontSize = 12; + m_navigationText.DropShadow = new Vector2(2, 2); + m_navigationText.Position = new Vector2(m_confirmText.X, m_confirmText.Y + 40); + m_navigationText.ForceDraw = true; + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_navigationText); // dummy locID to add TextObj to language refresh list + + m_rerollText = new KeyIconTextObj(Game.JunicodeFont); + m_rerollText.Align = Types.TextAlign.Left; + m_rerollText.FontSize = 12; + m_rerollText.DropShadow = new Vector2(2, 2); + m_rerollText.ForceDraw = true; + m_rerollText.Position = new Vector2(0 + 30, GlobalEV.ScreenHeight - 50); + m_rerollText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_rerollText); // dummy locID to add TextObj to language refresh list + + base.LoadContent(); + } + + public override void ReinitializeRTs() + { + m_background.SetRepeated(true, true, Camera); + base.ReinitializeRTs(); + } + + private void UpdateDescriptionPlate() + { + LineageObj selectedObj = m_currentBranchArray[m_selectedLineageIndex]; + + TextObj knightName = m_descriptionPlate.GetChildAt(1) as TextObj; + try + { + knightName.ChangeFontNoDefault(knightName.defaultFont); + knightName.Text = Game.NameHelper(selectedObj.PlayerName, selectedObj.RomanNumeral, selectedObj.IsFemale); + if (LocaleBuilder.languageType != LanguageType.Chinese_Simp && Regex.IsMatch(knightName.Text, @"\p{IsCyrillic}")) + knightName.ChangeFontNoDefault(Game.RobotoSlabFont); + } + catch + { + knightName.ChangeFontNoDefault(Game.NotoSansSCFont); + knightName.Text = Game.NameHelper(selectedObj.PlayerName, selectedObj.RomanNumeral, selectedObj.IsFemale); + } + + TextObj className = m_descriptionPlate.GetChildAt(2) as TextObj; + className.Text = LocaleBuilder.getResourceString("LOC_ID_LINEAGE_SCREEN_5") + " - " + LocaleBuilder.getResourceString(ClassType.ToStringID(selectedObj.Class, selectedObj.IsFemale)); // "Class - ???" + KeyIconTextObj classDescription = m_descriptionPlate.GetChildAt(3) as KeyIconTextObj; + classDescription.Text = LocaleBuilder.getResourceStringCustomFemale(ClassType.DescriptionID(selectedObj.Class), selectedObj.IsFemale); + classDescription.WordWrap(340); + + TextObj trait1Name = m_descriptionPlate.GetChildAt(4) as TextObj; + trait1Name.Y = classDescription.Y + classDescription.Height + 5; + TextObj trait1Description = m_descriptionPlate.GetChildAt(5) as TextObj; + trait1Description.Y = trait1Name.Y + 30; + + int spellY = (int)trait1Name.Y; + + if (selectedObj.Traits.X > 0) + { + trait1Name.Text = LocaleBuilder.getResourceString("LOC_ID_LINEAGE_SCREEN_6") + " - " + LocaleBuilder.getResourceString(TraitType.ToStringID((byte)selectedObj.Traits.X)); + trait1Description.Text = LocaleBuilder.getResourceString(TraitType.DescriptionID((byte)selectedObj.Traits.X, selectedObj.IsFemale)); + trait1Description.WordWrap(340); + + spellY = (int)trait1Description.Y + trait1Description.Height + 5; + } + else + { + spellY = (int)trait1Name.Y + trait1Name.Height + 5; + trait1Name.Text = LocaleBuilder.getResourceString("LOC_ID_LINEAGE_SCREEN_7"); + trait1Description.Text = ""; + } + + TextObj trait2Name = m_descriptionPlate.GetChildAt(6) as TextObj; + trait2Name.Y = trait1Description.Y + trait1Description.Height + 5; + TextObj trait2Description = m_descriptionPlate.GetChildAt(7) as TextObj; + trait2Description.Y = trait2Name.Y + 30; + + if (selectedObj.Traits.Y > 0) + { + trait2Name.Text = LocaleBuilder.getResourceString("LOC_ID_LINEAGE_SCREEN_6") + " - " + LocaleBuilder.getResourceString(TraitType.ToStringID((byte)selectedObj.Traits.Y)); + trait2Description.Text = LocaleBuilder.getResourceString(TraitType.DescriptionID((byte)selectedObj.Traits.Y, selectedObj.IsFemale)); + trait2Description.WordWrap(340); + + spellY = (int)trait2Description.Y + trait2Description.Height + 5; + } + else + { + trait2Name.Text = ""; + trait2Description.Text = ""; + } + + if (Game.PlayerStats.HasProsopagnosia == true) + { + trait1Name.Visible = false; + trait2Name.Visible = false; + trait1Description.Visible = false; + trait2Description.Visible = false; + + spellY = (int)trait1Name.Y; + } + else + { + trait1Name.Visible = true; + trait2Name.Visible = true; + trait1Description.Visible = true; + trait2Description.Visible = true; + } + + TextObj spellName = m_descriptionPlate.GetChildAt(8) as TextObj; + spellName.Text = LocaleBuilder.getResourceString("LOC_ID_LINEAGE_SCREEN_8") + " - " + LocaleBuilder.getResourceString(SpellType.ToStringID(selectedObj.Spell)); + spellName.Y = spellY; + KeyIconTextObj spellDescription = m_descriptionPlate.GetChildAt(9) as KeyIconTextObj; + spellDescription.Text = "[Input:" + InputMapType.PLAYER_SPELL1 + "] " + LocaleBuilder.getResourceString(SpellType.DescriptionID(selectedObj.Spell)); + spellDescription.Y = spellName.Y + 30; + spellDescription.WordWrap(340); + } + + /// + /// Creates a current branch for the lineage. + /// + /// The number of lineages in a branch to create + /// Where to start placing the centre lineage + /// Set this to false if you don't want to create random traits for this lineage. Useful when only loading lineages. + /// Whether to randomize the player portrait or not. Setting false sets all armor pieces to 1. + /// Whether this is an active branch or not. Active branches will be coloured, non-actives will be greyed out. + private void AddLineageRow(int numLineages, Vector2 position, bool createEmpty, bool randomizePortrait) + { + // Setting whether this lineage obj was the path the player went down. + if (m_selectedLineageObj != null) + { + m_selectedLineageObj.ForceDraw = false; + m_selectedLineageObj.Y = 0; + } + + m_currentPoint = position; + m_currentBranchArray.Clear(); + + int[] yPosArray3 = new int[] { -450, 0, 450 }; + int[] yPosArray2 = new int[] { -200, 200 }; + + for (int i = 0; i < numLineages; i++) + { + LineageObj obj = new LineageObj(this, createEmpty); + + if (randomizePortrait == true) + obj.RandomizePortrait(); + + obj.ForceDraw = true; + obj.X = position.X + m_xPosOffset; + + int[] posArray = yPosArray3; + if (numLineages == 2) + posArray = yPosArray2; + + obj.Y = posArray[i]; + + m_currentBranchArray.Add(obj); + + if (obj.Traits.X == TraitType.Vertigo || obj.Traits.Y == TraitType.Vertigo) + obj.FlipPortrait = true; + + obj.HasProsopagnosia = Game.PlayerStats.HasProsopagnosia; + } + + m_currentPoint = m_currentBranchArray[1].Position; + Camera.Position = m_currentPoint; + m_selectedLineageObj = m_currentBranchArray[1]; + m_selectedLineageIndex = 1; + } + + public override void OnEnter() + { + (Game.ScreenManager.Game as RogueCastle.Game).InitializeMaleNameArray(false); + (Game.ScreenManager.Game as RogueCastle.Game).InitializeFemaleNameArray(false); + + m_lockControls = false; + SoundManager.PlayMusic("SkillTreeSong", true, 1); + + m_storedMusicVol = SoundManager.GlobalMusicVolume; + SoundManager.GlobalMusicVolume = 0; + if (SoundManager.AudioEngine != null) + SoundManager.AudioEngine.GetCategory("Legacy").SetVolume(m_storedMusicVol); + + // This is probably unnecessary. + //if (Game.LineageSongCue != null && Game.LineageSongCue.IsPlaying) + //{ + // Game.LineageSongCue.Stop(AudioStopOptions.Immediate); + // Game.LineageSongCue.Dispose(); + //} + + //Game.LineageSongCue = SoundManager.GetMusicCue("LegacySong"); + //Game.LineageSongCue.Play(); + + if (Game.LineageSongCue != null && Game.LineageSongCue.IsPlaying) + { + Game.LineageSongCue.Stop(AudioStopOptions.Immediate); + Game.LineageSongCue.Dispose(); + } + Game.LineageSongCue = SoundManager.GetMusicCue("LegacySong"); + if (Game.LineageSongCue != null) + Game.LineageSongCue.Play(); + + //Camera.Position = new Vector2(1320 / 2, 720 / 2); + + // Lineage Data loaded on start menu. + + LoadFamilyTreeData(); + LoadCurrentBranches(); + + Camera.Position = m_selectedLineageObj.Position; + UpdateDescriptionPlate(); + + m_confirmText.Text = LocaleBuilder.getString("LOC_ID_LINEAGE_SCREEN_1_NEW", m_confirmText); + + if (InputManager.GamePadIsConnected(PlayerIndex.One) == true) + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_LINEAGE_SCREEN_2_NEW", m_navigationText); + else + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_LINEAGE_SCREEN_3", m_navigationText); + + m_rerollText.Text = LocaleBuilder.getString("LOC_ID_LINEAGE_SCREEN_4_NEW", m_rerollText); + if (SkillSystem.GetSkill(SkillType.Randomize_Children).ModifierAmount > 0 && Game.PlayerStats.RerolledChildren == false) + m_rerollText.Visible = true; + else + m_rerollText.Visible = false; + + Game.ChangeBitmapLanguage(m_titleText, "LineageTitleText_Sprite"); + + base.OnEnter(); + } + + public void LoadFamilyTreeData() + { + m_masterArray.Clear(); + + // Create a base entry to represent the very first knight (not playable and not saved). + int currentEra = GameEV.BASE_ERA; + + if (Game.PlayerStats.FamilyTreeArray != null && Game.PlayerStats.FamilyTreeArray.Count > 0) + { + int xPos = 0; + + // Loading the family tree. + foreach (FamilyTreeNode treeData in Game.PlayerStats.FamilyTreeArray) + { + LineageObj lineageObj = new LineageObj(this, true); + lineageObj.IsDead = true; + lineageObj.Age = treeData.Age; + lineageObj.ChildAge = treeData.ChildAge; + lineageObj.Class = treeData.Class; + lineageObj.IsFemale = treeData.IsFemale; // Must go before PlayerName + lineageObj.RomanNumeral = treeData.RomanNumeral; // Must go before PlayerName + lineageObj.PlayerName = treeData.Name; + lineageObj.SetPortrait(treeData.HeadPiece, treeData.ShoulderPiece, treeData.ChestPiece); + lineageObj.NumEnemiesKilled = treeData.NumEnemiesBeaten; + lineageObj.BeatenABoss = treeData.BeatenABoss; + lineageObj.SetTraits(treeData.Traits); + lineageObj.UpdateAge(currentEra); + lineageObj.UpdateData(); + lineageObj.UpdateClassRank(); + currentEra = currentEra + lineageObj.Age; + + lineageObj.X = xPos; + xPos += m_xPosOffset; + + m_masterArray.Add(lineageObj); + + if (lineageObj.Traits.X == TraitType.Vertigo || lineageObj.Traits.Y == TraitType.Vertigo) + lineageObj.FlipPortrait = true; + } + } + else + { + // This automatically adds one person to the family tree if it starts empty. + int xPos = 0; + + LineageObj lineageObj = new LineageObj(this, true); + lineageObj.IsDead = true; + lineageObj.Age = 30; + lineageObj.ChildAge = 5; + lineageObj.Class = ClassType.Knight; + lineageObj.PlayerName = "Johannes"; + lineageObj.SetPortrait(1, 1, 1); + lineageObj.NumEnemiesKilled = 50; + lineageObj.BeatenABoss = false; + lineageObj.UpdateAge(currentEra); + lineageObj.UpdateData(); + lineageObj.UpdateClassRank(); + currentEra = currentEra + lineageObj.Age; + + lineageObj.X = xPos; + xPos += m_xPosOffset; + + m_masterArray.Add(lineageObj); + + if (lineageObj.Traits.X == TraitType.Vertigo || lineageObj.Traits.Y == TraitType.Vertigo) + lineageObj.FlipPortrait = true; + } + } + + public void LoadCurrentBranches() + { + if (Game.PlayerStats.CurrentBranches == null || Game.PlayerStats.CurrentBranches.Count < 1) + { + AddLineageRow(3, m_masterArray[m_masterArray.Count - 1].Position, false, true); + + // Save the current branches if a new set is saved. + List branchArray = new List(); + for (int i = 0; i < m_currentBranchArray.Count; i++) + { + PlayerLineageData newBranch = new PlayerLineageData(); + newBranch.IsFemale = m_currentBranchArray[i].IsFemale; // Must go before name + newBranch.RomanNumeral = m_currentBranchArray[i].RomanNumeral; // Must go before name + newBranch.Name = m_currentBranchArray[i].PlayerName; + newBranch.HeadPiece = m_currentBranchArray[i].HeadPiece; + newBranch.ShoulderPiece = m_currentBranchArray[i].ShoulderPiece; + newBranch.ChestPiece = m_currentBranchArray[i].ChestPiece; + newBranch.Class = m_currentBranchArray[i].Class; + newBranch.Spell = m_currentBranchArray[i].Spell; + newBranch.Traits= m_currentBranchArray[i].Traits; + newBranch.Age = m_currentBranchArray[i].Age; + newBranch.ChildAge = m_currentBranchArray[i].ChildAge; + newBranch.IsFemale = m_currentBranchArray[i].IsFemale; + branchArray.Add(newBranch); + } + Game.PlayerStats.CurrentBranches = branchArray; + (ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.Lineage); + } + else + { + AddLineageRow(3, m_masterArray[m_masterArray.Count - 1].Position, true, true); + List loadedLineageArray = Game.PlayerStats.CurrentBranches; + for (int i = 0; i < m_currentBranchArray.Count; i++) + { + m_currentBranchArray[i].IsFemale = loadedLineageArray[i].IsFemale; // Must go before name + m_currentBranchArray[i].RomanNumeral = loadedLineageArray[i].RomanNumeral; // Must go before name + m_currentBranchArray[i].PlayerName = loadedLineageArray[i].Name; + m_currentBranchArray[i].SetPortrait(loadedLineageArray[i].HeadPiece, loadedLineageArray[i].ShoulderPiece, loadedLineageArray[i].ChestPiece); + m_currentBranchArray[i].Spell = loadedLineageArray[i].Spell; + m_currentBranchArray[i].Class = loadedLineageArray[i].Class; + m_currentBranchArray[i].ClearTraits(); // Necessary to reset the lineage objs trait index pointer. + m_currentBranchArray[i].Traits = loadedLineageArray[i].Traits; + m_currentBranchArray[i].Age = loadedLineageArray[i].Age; + m_currentBranchArray[i].ChildAge = loadedLineageArray[i].ChildAge; + m_currentBranchArray[i].UpdateData(); + } + } + } + + public override void OnExit() + { + float delayAmount = 1 / 60f; + float volume = m_storedMusicVol; + float volumeAmount = m_storedMusicVol / 120f; + for (int i = 0; i < 120; i++) + { + Tweener.Tween.RunFunction(delayAmount * i, this, "ReduceMusic", volume); + volume -= volumeAmount; + } + Tweener.Tween.RunFunction(2, this, "StopLegacySong"); + + Game.PlayerStats.CurrentBranches = null; + + //SaveFamilyTree(false); + // 2 pieces of info should be passed into Game.PlayerStats before calling save: + // 1. The current selected traits for the player. (Happens in StartGame()) + // 2. The family tree. (Happens just above these comments) + // Save the current lineage stats. + //(ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.Lineage); + + if (Game.PlayerStats.Class == ClassType.Dragon) + GameUtil.UnlockAchievement("FEAR_OF_GRAVITY"); + + if (Game.PlayerStats.Traits == Vector2.Zero) + GameUtil.UnlockAchievement("FEAR_OF_IMPERFECTIONS"); + + base.OnExit(); + } + + public void ReduceMusic(float newVolume) + { + //Console.WriteLine(newVolume + " " + (m_storedMusicVol - newVolume)); + if (SoundManager.AudioEngine != null) + { + SoundManager.AudioEngine.GetCategory("Legacy").SetVolume(newVolume); + SoundManager.GlobalMusicVolume += m_storedMusicVol - newVolume; + if (SoundManager.GlobalMusicVolume > m_storedMusicVol) + SoundManager.GlobalMusicVolume = m_storedMusicVol; + } + } + + public void StopLegacySong() + { + if (Game.LineageSongCue != null && Game.LineageSongCue.IsPlaying == true) + Game.LineageSongCue.Stop(AudioStopOptions.Immediate); + if (Game.LineageSongCue != null) + { + Game.LineageSongCue.Dispose(); + Game.LineageSongCue = null; + } + + SoundManager.GlobalMusicVolume = m_storedMusicVol; + } + + public override void Update(GameTime gameTime) + { + if (m_background != null && m_background.isContentLost == true) + ReinitializeRTs(); + + m_bgShadow.Opacity = 0.8f + (0.05f * ((float)Math.Sin(Game.TotalGameTime * 4))); + + if (Game.LineageSongCue != null && Game.LineageSongCue.IsPlaying == false) + { + Game.LineageSongCue.Dispose(); + Game.LineageSongCue = SoundManager.GetMusicCue("LegacySong"); + Game.LineageSongCue.Play(); + SoundManager.StopMusic(0); + SoundManager.PlayMusic("SkillTreeSong", true, 1); + } + + base.Update(gameTime); + } + + public override void HandleInput() + { + if (m_lockControls == false) + { + if (m_selectTween == null || (m_selectTween != null && m_selectTween.Active == false)) + { + LineageObj previousLineageObj = m_selectedLineageObj; + int previousLineageIndex = m_selectedLineageIndex; + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_MAP) && SkillSystem.GetSkill(SkillType.Randomize_Children).ModifierAmount > 0 && Game.PlayerStats.RerolledChildren == false) + { + m_lockControls = true; + SoundManager.PlaySound("frame_woosh_01", "frame_woosh_02"); + + if (m_xShift != 0) + { + m_xShift = 0; + Tweener.Tween.By(m_descriptionPlate, 0.2f, Tweener.Ease.Back.EaseOut, "delay", "0.2", "X", "-600"); + m_selectTween = Tweener.Tween.To(Camera, 0.3f, Tweener.Ease.Quad.EaseOut, "delay", "0.2", "X", (m_masterArray.Count * m_xPosOffset).ToString()); + } + + (ScreenManager as RCScreenManager).StartWipeTransition(); + Tweener.Tween.RunFunction(0.2f, this, "RerollCurrentBranch"); + } + + //if (Game.GlobalInput.JustPressed(InputMapType.MENU_MAP)) + //{ + // //SaveFamilyTree(true); + // AddLineageRow(3, m_selectedLineageObj.Position, false, true); + // m_selectedLineageIndex = 1; + // UpdateDescriptionPlate(); + + // FamilyTreeNode newNode = new FamilyTreeNode() + // { + // Name = m_selectedLineageObj.PlayerName, + // Age = (byte)CDGMath.RandomInt(18, 30), + // ChildAge = (byte)CDGMath.RandomInt(2, 5), + // Class = m_selectedLineageObj.Class, + // HeadPiece = m_selectedLineageObj.HeadPiece, + // ChestPiece = m_selectedLineageObj.ChestPiece, + // ShoulderPiece = m_selectedLineageObj.ShoulderPiece, + // NumEnemiesBeaten = CDGMath.RandomInt(0, 50), + // BeatenABoss = false, + // Traits = m_selectedLineageObj.Traits, + // }; + // Game.PlayerStats.FamilyTreeArray.Add(newNode); + // LoadFamilyTreeData(); + //} + + if (Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT2)) + { + if (Camera.X > m_masterArray[0].X + 10) // Make sure the camera doesn't go too far to the left. + { + SoundManager.PlaySound("frame_swoosh_01"); + m_selectTween = Tweener.Tween.By(Camera, 0.3f, Tweener.Ease.Quad.EaseOut, "X", (-m_xPosOffset).ToString()); + if (m_xShift == 0) + Tweener.Tween.By(m_descriptionPlate, 0.2f, Tweener.Ease.Back.EaseIn, "X", "600"); + m_xShift--; + } + } + else if (Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT2)) + { + if (m_xShift < 0) + { + SoundManager.PlaySound("frame_swoosh_01"); + m_selectTween = Tweener.Tween.By(Camera, 0.3f, Tweener.Ease.Quad.EaseOut, "X", (m_xPosOffset).ToString()); + m_xShift++; + if (m_xShift == 0) + Tweener.Tween.By(m_descriptionPlate, 0.2f, Tweener.Ease.Back.EaseOut, "X", "-600"); + } + } + + if (m_xShift == 0) + { + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + if (m_selectedLineageIndex > 0) + SoundManager.PlaySound("frame_swap"); + + m_selectedLineageIndex--; + + if (m_selectedLineageIndex < 0) + m_selectedLineageIndex = 0; + + if (m_selectedLineageIndex != previousLineageIndex) + { + UpdateDescriptionPlate(); + + m_selectTween = Tweener.Tween.By(m_currentBranchArray[0], 0.3f, Tweener.Ease.Quad.EaseOut, "Y", "450"); + Tweener.Tween.By(m_currentBranchArray[1], 0.3f, Tweener.Ease.Quad.EaseOut, "Y", "450"); + Tweener.Tween.By(m_currentBranchArray[2], 0.3f, Tweener.Ease.Quad.EaseOut, "Y", "450"); + } + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN2)) + { + if (m_selectedLineageIndex < m_currentBranchArray.Count - 1) + SoundManager.PlaySound("frame_swap"); + + m_selectedLineageIndex++; + + if (m_selectedLineageIndex > m_currentBranchArray.Count - 1) + m_selectedLineageIndex = m_currentBranchArray.Count - 1; + + if (m_selectedLineageIndex != previousLineageIndex) + { + UpdateDescriptionPlate(); + + m_selectTween = Tweener.Tween.By(m_currentBranchArray[0], 0.3f, Tweener.Ease.Quad.EaseOut, "Y", "-450"); + Tweener.Tween.By(m_currentBranchArray[1], 0.3f, Tweener.Ease.Quad.EaseOut, "Y", "-450"); + Tweener.Tween.By(m_currentBranchArray[2], 0.3f, Tweener.Ease.Quad.EaseOut, "Y", "-450"); + } + } + } + + m_selectedLineageObj = m_currentBranchArray[m_selectedLineageIndex]; + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + if (m_xShift == 0) + { + if (previousLineageObj == m_selectedLineageObj) + { + RCScreenManager manager = ScreenManager as RCScreenManager; + + m_storedFemalePlayerStat = Game.PlayerStats.IsFemale; + Game.PlayerStats.IsFemale = m_selectedLineageObj.IsFemale; + manager.DialogueScreen.SetDialogue("LineageChoiceWarning"); + + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "StartGame"); + //manager.DialogueScreen.SetCancelEndHandler(typeof(Console), "WriteLine", "Canceling Selection"); + manager.DialogueScreen.SetCancelEndHandler(this, "CancelSelection"); + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Dialogue, true); + } + } + else + { + m_xShift = 0; + SoundManager.PlaySound("frame_woosh_01", "frame_woosh_02"); + Tweener.Tween.By(m_descriptionPlate, 0.2f, Tweener.Ease.Back.EaseOut, "X", "-600"); + m_selectTween = Tweener.Tween.To(Camera, 0.3f, Tweener.Ease.Quad.EaseOut, "X", (m_masterArray.Count * m_xPosOffset).ToString()); + } + } + base.HandleInput(); + } + + if (LevelEV.ENABLE_DEBUG_INPUT == true) + HandleDebugInput(); + } + } + + private bool m_storedFemalePlayerStat; + public void CancelSelection() + { + Console.WriteLine("Canceling selection."); + Game.PlayerStats.IsFemale = m_storedFemalePlayerStat; + } + + private int m_debugNameArrayIndex = 0; + private void HandleDebugInput() + { + // Debug for easier localization testing. + Vector2 traits = m_currentBranchArray[m_selectedLineageIndex].Traits; + Vector2 previousTraits = traits; + bool lineageObjChanged = false; + + if (InputManager.JustPressed(Keys.OemQuotes, null) ||InputManager.JustPressed(Keys.OemSemicolon, null)) + { + (ScreenManager.Game as RogueCastle.Game).InitializeFemaleNameArray(true); + (ScreenManager.Game as RogueCastle.Game).InitializeMaleNameArray(true); + } + + List nameArray = Game.NameArray; + if (m_currentBranchArray[m_selectedLineageIndex].IsFemale == true) + nameArray = Game.FemaleNameArray; + int previousNameIndex = m_debugNameArrayIndex; + + if (InputManager.JustPressed(Keys.B, PlayerIndex.One)) + m_debugNameArrayIndex--; + else if (InputManager.JustPressed(Keys.N, PlayerIndex.One)) + m_debugNameArrayIndex++; + + if (m_debugNameArrayIndex < 0) + m_debugNameArrayIndex = nameArray.Count - 1; + else if (m_debugNameArrayIndex >= nameArray.Count) + m_debugNameArrayIndex = 0; + + if (previousNameIndex != m_debugNameArrayIndex) + { + lineageObjChanged = true; + m_currentBranchArray[m_selectedLineageIndex].PlayerName = nameArray[m_debugNameArrayIndex]; + } + + if (InputManager.JustPressed(Keys.M, PlayerIndex.One)) + traits.X--; + else if (InputManager.JustPressed(Keys.OemComma, PlayerIndex.One)) + traits.X++; + + if (InputManager.JustPressed(Keys.OemPeriod, PlayerIndex.One)) + traits.Y--; + else if (InputManager.JustPressed(Keys.OemQuestion, PlayerIndex.One)) + traits.Y++; + + if (traits.X >= TraitType.Total) + traits.X = TraitType.None; + else if (traits.X < TraitType.None) + traits.X = TraitType.Total - 1; + if (traits.Y >= TraitType.Total) + traits.Y = TraitType.None; + else if (traits.Y < TraitType.None) + traits.Y = TraitType.Total - 1; + + if (traits != previousTraits) + { + m_currentBranchArray[m_selectedLineageIndex].Traits = traits; + lineageObjChanged = true; + } + + byte spell = m_currentBranchArray[m_selectedLineageIndex].Spell; + byte previousSpell = spell; + if (InputManager.JustPressed(Keys.OemOpenBrackets, PlayerIndex.One)) + { + if (spell == SpellType.None) + spell = SpellType.Total - 1; + else + spell--; + } + else if (InputManager.JustPressed(Keys.OemCloseBrackets, PlayerIndex.One)) + spell++; + + if (spell < SpellType.None) + spell = SpellType.Total - 1; + else if (spell >= SpellType.Total) + spell = SpellType.None; + + if (spell != previousSpell) + { + m_currentBranchArray[m_selectedLineageIndex].Spell = spell; + lineageObjChanged = true; + } + + byte currentClass = m_currentBranchArray[m_selectedLineageIndex].Class; + byte previousClass = currentClass; + if (InputManager.JustPressed(Keys.OemMinus, PlayerIndex.One)) + { + if (currentClass == ClassType.Knight) + currentClass = ClassType.Traitor; + else + currentClass--; + } + else if (InputManager.JustPressed(Keys.OemPlus, PlayerIndex.One)) + currentClass++; + + if (currentClass < ClassType.Knight) + currentClass = ClassType.Traitor; + else if (currentClass > ClassType.Traitor) + currentClass = ClassType.Knight; + + if (currentClass != previousClass) + { + m_currentBranchArray[m_selectedLineageIndex].Class = currentClass; + lineageObjChanged = true; + } + + if (lineageObjChanged == true) + { + m_currentBranchArray[m_selectedLineageIndex].UpdateData(); + UpdateDescriptionPlate(); + } + } + + public void RerollCurrentBranch() + { + m_rerollText.Visible = false; + Game.PlayerStats.RerolledChildren = true; + (ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData); // Hopefully saving player data here doesn't screw things up. + + Game.PlayerStats.CurrentBranches.Clear(); + LoadCurrentBranches(); // Clears the current branches, creates 3 new ones, and saves them. + (ScreenManager as RCScreenManager).EndWipeTransition(); + UpdateDescriptionPlate(); + m_lockControls = false; + } + + public void StartGame() + { + //m_selectedLineageObj.TraitArray[0] = new PlayerTraitData() {TraitType = TraitType.Knockback_Immune }; + //Game.PlayerStats.CurrentLineageData = m_selectedLineageObj.Data.Clone(); + Game.PlayerStats.HeadPiece = m_selectedLineageObj.HeadPiece; + Game.PlayerStats.ShoulderPiece = m_selectedLineageObj.ShoulderPiece; + Game.PlayerStats.ChestPiece = m_selectedLineageObj.ChestPiece; + Game.PlayerStats.IsFemale = m_selectedLineageObj.IsFemale; + Game.PlayerStats.Class = m_selectedLineageObj.Class; + Game.PlayerStats.Traits = m_selectedLineageObj.Traits; + Game.PlayerStats.Spell = m_selectedLineageObj.Spell; + Game.PlayerStats.PlayerName = m_selectedLineageObj.PlayerName; + Game.PlayerStats.Age = m_selectedLineageObj.Age; + Game.PlayerStats.ChildAge = m_selectedLineageObj.ChildAge; + Game.PlayerStats.RomanNumeral = m_selectedLineageObj.RomanNumeral; + Game.PlayerStats.HasProsopagnosia = false; + + // Save the next 3 spells for regular wizard in case you level up with wizard class in the next run. + if (Game.PlayerStats.Class == ClassType.Wizard || Game.PlayerStats.Class == ClassType.Wizard2) + { + //byte[] spellArray = ClassType.GetSpellList(ClassType.Wizard2); + //List spellList = new List(); + //foreach (byte spell in spellArray) + // spellList.Add(spell); + //int spellIndex = spellList.IndexOf(Game.PlayerStats.Spell); + //spellList.Clear(); + //spellList = null; + + //byte[] wizardSpells = new byte[3]; + //for (int i = 0; i < 3; i++) + //{ + // wizardSpells[i] = spellArray[spellIndex]; + // spellIndex++; + // if (spellIndex >= spellArray.Length) + // spellIndex = 0; + //} + + //Game.PlayerStats.WizardSpellList = new Vector3(wizardSpells[0], wizardSpells[1], wizardSpells[2]); + Game.PlayerStats.WizardSpellList = SpellType.GetNext3Spells(); + } + + // Clear out the saved Branches in PlayerStats.CurrentBranches + Game.PlayerStats.CurrentBranches.Clear(); + + // This loads the starting room, then puts the skill screen on top of it. How does this work? + // The call is done in LoadingScreen. First it adds the level, disables anything that could cause problems in the level, then adds the skill tree. + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.StartingRoom, true); + } + + + public override void Draw(GameTime gameTime) + { + // Hack to make an infinite scroll. + if (Camera.X > m_background.X + 1320 * 5) + m_background.X = Camera.X; + if (Camera.X < m_background.X) + m_background.X = Camera.X - 1320; + + //float parallaxAmount = 0;// 0.25f; + //m_background.X = Camera.Bounds.Center.X * parallaxAmount; + //m_background.Y = Camera.Bounds.Center.Y * parallaxAmount; + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearWrap, null, null, null, Camera.GetTransformation()); + m_background.Draw(Camera); + Camera.End(); + + //Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null); + //m_bgShadow.Draw(Camera); + //Camera.End(); + + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, Camera.GetTransformation()); + + foreach (LineageObj lineageObj in m_masterArray) + lineageObj.Draw(Camera); + + foreach (LineageObj lineageObj in m_currentBranchArray) + lineageObj.Draw(Camera); + + Camera.End(); + + if (Camera.Zoom >= 1) + { + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null); + m_bgShadow.Draw(Camera); + + m_titleText.Draw(Camera); + m_confirmText.Draw(Camera); + m_navigationText.Draw(Camera); + m_rerollText.Draw(Camera); + //m_controlsUpDown.Draw(Camera); + //m_controlsLeftRight.Draw(Camera); + + //m_infoPlate.Draw(Camera); + m_descriptionPlate.Draw(Camera); + //Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + Camera.End(); + } + + base.Draw(gameTime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Lineage Screen"); + + m_titleText.Dispose(); + m_titleText = null; + + m_selectedLineageObj = null; + + foreach (LineageObj obj in m_currentBranchArray) + obj.Dispose(); + + m_currentBranchArray.Clear(); + m_currentBranchArray = null; + + foreach (LineageObj obj in m_masterArray) + { + if (obj.IsDisposed == false) + obj.Dispose(); + } + + m_masterArray.Clear(); + m_masterArray = null; + + if (m_startingLineageObj != null) + m_startingLineageObj.Dispose(); + m_startingLineageObj = null; + + m_background.Dispose(); + m_background = null; + m_bgShadow.Dispose(); + m_bgShadow = null; + m_selectTween = null; + m_descriptionPlate.Dispose(); + m_descriptionPlate = null; + + m_confirmText.Dispose(); + m_confirmText = null; + m_navigationText.Dispose(); + m_navigationText = null; + m_rerollText.Dispose(); + m_rerollText = null; + //if (Game.LineageSongCue != null && Game.LineageSongCue.IsPlaying == true) + // Game.LineageSongCue.Stop(AudioStopOptions.Immediate); + //if (Game.LineageSongCue != null) + // Game.LineageSongCue.Dispose(); + //Game.LineageSongCue = null; + base.Dispose(); + } + } + + // Number of times a name is used. + public int NameCopies(string name) + { + int nameCopies = 0; + foreach (LineageObj data in m_masterArray) + { + if (data.PlayerName.Contains(name)) + nameCopies++; + } + + return nameCopies; + } + + public bool CurrentBranchNameCopyFound(string name) + { + foreach (LineageObj data in m_currentBranchArray) + { + if (Game.PlayerStats.RevisionNumber <= 0) + { + if (data.PlayerName.Contains(name)) + return true; + } + else + { + if (data.PlayerName == name) // This should be okay to do now because of the name format change. + return true; + } + } + return false; + } + + public override void RefreshTextObjs() + { + foreach (LineageObj data in m_masterArray) + data.RefreshTextObjs(); + foreach (LineageObj data in m_currentBranchArray) + data.RefreshTextObjs(); + + Game.ChangeBitmapLanguage(m_titleText, "LineageTitleText_Sprite"); + + UpdateDescriptionPlate(); + + /* + m_confirmText.Text = "[Input:" + InputMapType.MENU_CONFIRM1 + "] " + LocaleBuilder.getResourceString("LOC_ID_LINEAGE_SCREEN_1"); + + if (InputManager.GamePadIsConnected(PlayerIndex.One) == true) + m_navigationText.Text = "[Button:LeftStick] " + LocaleBuilder.getResourceString("LOC_ID_LINEAGE_SCREEN_2"); + else + m_navigationText.Text = LocaleBuilder.getResourceString("LOC_ID_LINEAGE_SCREEN_3"); + + m_rerollText.Text = "[Input:" + InputMapType.MENU_MAP + "] " + LocaleBuilder.getResourceString("LOC_ID_LINEAGE_SCREEN_4"); + */ + + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Screens/LoadingScreen.cs b/RogueCastle/src/Screens/LoadingScreen.cs new file mode 100644 index 0000000..8b08afb --- /dev/null +++ b/RogueCastle/src/Screens/LoadingScreen.cs @@ -0,0 +1,479 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using System.Threading; +using Microsoft.Xna.Framework.Graphics; +using Tweener; +using Tweener.Ease; + +namespace RogueCastle +{ + public class LoadingScreen : Screen + { + private TextObj m_loadingText; + + private byte m_screenTypeToLoad = 0; + private bool m_isLoading = false; + private bool m_loadingComplete = false; + private Screen m_levelToLoad = null; + + private ImpactEffectPool m_effectPool; + + private ObjContainer m_gateSprite; + + private SpriteObj m_blackTransitionIn, m_blackScreen, m_blackTransitionOut; + private bool m_wipeTransition = false; + private bool m_gameCrashed = false; + + // Special transition code purely for the introduction. + public float BackBufferOpacity { get; set; } + + public LoadingScreen(byte screenType, bool wipeTransition) + { + m_screenTypeToLoad = screenType; + m_effectPool = new ImpactEffectPool(50); + m_wipeTransition = wipeTransition; + } + + public override void LoadContent() + { + m_loadingText = new TextObj(); + m_loadingText.Font = Game.JunicodeLargeFont; + m_loadingText.Text = LocaleBuilder.getString("LOC_ID_LOADING_SCREEN_1", m_loadingText); //"Building" + m_loadingText.Align = Types.TextAlign.Centre; + m_loadingText.FontSize = 40; + m_loadingText.OutlineWidth = 4; + m_loadingText.ForceDraw = true; + + m_gateSprite = new ObjContainer("LoadingScreenGate_Character"); + m_gateSprite.ForceDraw = true; + m_gateSprite.Scale = new Vector2(2, 2); + m_gateSprite.Y -= m_gateSprite.Height; + + m_effectPool.Initialize(); + + m_blackTransitionIn = new SpriteObj("Blank_Sprite"); + m_blackTransitionIn.Rotation = 15; + m_blackTransitionIn.Scale = new Vector2(1320 / m_blackTransitionIn.Width, 2000 / m_blackTransitionIn.Height); + m_blackTransitionIn.TextureColor = Color.Black; + m_blackTransitionIn.ForceDraw = true; + //m_blackTransitionIn.Visible = false; + + m_blackScreen = new SpriteObj("Blank_Sprite"); + m_blackScreen.Scale = new Vector2(1320 / m_blackScreen.Width, 720 / m_blackScreen.Height); + m_blackScreen.TextureColor = Color.Black; + m_blackScreen.ForceDraw = true; + //m_blackScreen.Visible = false; + + m_blackTransitionOut = new SpriteObj("Blank_Sprite"); + m_blackTransitionOut.Rotation = 15; + m_blackTransitionOut.Scale = new Vector2(1320 / m_blackTransitionOut.Width, 2000 / m_blackTransitionOut.Height); + m_blackTransitionOut.TextureColor = Color.Black; + m_blackTransitionOut.ForceDraw = true; + //m_blackTransitionOut.Visible = false; + + + base.LoadContent(); + } + + public override void OnEnter() + { + BackBufferOpacity = 0; + m_gameCrashed = false; + + if (Game.PlayerStats.Traits.X == TraitType.TheOne || Game.PlayerStats.Traits.Y == TraitType.TheOne) + m_loadingText.Text = LocaleBuilder.getString("LOC_ID_LOADING_SCREEN_4", m_loadingText); //"Jacking In" + else if (Game.PlayerStats.Traits.X == TraitType.Nostalgic || Game.PlayerStats.Traits.Y == TraitType.Nostalgic) + m_loadingText.Text = LocaleBuilder.getString("LOC_ID_LOADING_SCREEN_3", m_loadingText); //"Reminiscing" + else if (Game.PlayerStats.Traits.X == TraitType.Baldness || Game.PlayerStats.Traits.Y == TraitType.Baldness) + m_loadingText.Text = LocaleBuilder.getString("LOC_ID_LOADING_SCREEN_2", m_loadingText); //"Balding" + else + m_loadingText.Text = LocaleBuilder.getString("LOC_ID_LOADING_SCREEN_1", m_loadingText); //"Building" + + if (m_loadingComplete == false) + { + // A special transition for the intro sequence. + if (m_screenTypeToLoad == ScreenType.TitleWhite) + { + Tween.To(this, 0.05f, Tween.EaseNone, "BackBufferOpacity", "1"); + Tween.RunFunction(1, this, "BeginThreading"); + //Tween.AddEndHandlerToLastTween(this, "BeginThreading"); + } + else + { + m_blackTransitionIn.X = 0; + m_blackTransitionIn.X = 1320 - m_blackTransitionIn.Bounds.Left; + m_blackScreen.X = m_blackTransitionIn.X; + m_blackTransitionOut.X = m_blackScreen.X + m_blackScreen.Width; + + if (m_wipeTransition == false) + { + SoundManager.PlaySound("GateDrop"); + Tween.To(m_gateSprite, 0.5f, Tween.EaseNone, "Y", "0"); + Tween.RunFunction(0.3f, m_effectPool, "LoadingGateSmokeEffect", 40); + Tween.RunFunction(0.3f, typeof(SoundManager), "PlaySound", "GateSlam"); + Tween.RunFunction(0.55f, this, "ShakeScreen", 4, true, true); + Tween.RunFunction(0.65f, this, "StopScreenShake"); + Tween.RunFunction(1.5f, this, "BeginThreading"); // Make sure the gate tween animation is done before executing the thread. + } + else + { + Tween.By(m_blackTransitionIn, 0.15f, Quad.EaseIn, "X", (-m_blackTransitionIn.X).ToString()); + Tween.By(m_blackScreen, 0.15f, Quad.EaseIn, "X", (-m_blackTransitionIn.X).ToString()); + Tween.By(m_blackTransitionOut, 0.2f, Quad.EaseIn, "X", (-m_blackTransitionIn.X).ToString()); + Tween.AddEndHandlerToLastTween(this, "BeginThreading"); + } + } + base.OnEnter(); + } + } + + public void BeginThreading() + { + Tween.StopAll(false); + // Object loading is multithreaded. + Thread loadingThread = new Thread(BeginLoading); + /* flibit didn't like this + if (loadingThread.CurrentCulture.Name != "en-US") + { + loadingThread.CurrentCulture = new System.Globalization.CultureInfo("en-US", false); + loadingThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US", false); + } + */ + loadingThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; + loadingThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture; + loadingThread.Start(); + } + + private void BeginLoading() + { + m_isLoading = true; + m_loadingComplete = false; + switch (m_screenTypeToLoad) + { + case (ScreenType.CDGSplash): + m_levelToLoad = new CDGSplashScreen(); + lock (m_levelToLoad) + m_loadingComplete = true; + break; + case(ScreenType.BlitWorks): + m_levelToLoad = new BlitWorksSplashScreen(); + lock (m_levelToLoad) + m_loadingComplete = true; + break; + case (ScreenType.DemoEnd): + m_levelToLoad = new DemoEndScreen(); + lock (m_levelToLoad) + m_loadingComplete = true; + break; + case (ScreenType.DemoStart): + m_levelToLoad = new DemoStartScreen(); + lock (m_levelToLoad) + m_loadingComplete = true; + break; + case (ScreenType.Credits): + m_levelToLoad = new CreditsScreen(); + + // This is a check to see if you should load the special ending credits or the regular one. + // It does this by seeing if a titlescreen exists in the screen list. If it does, it means you loaded from the title screen and should not get the special credits. + bool loadEnding = true; + foreach (Screen screen in ScreenManager.GetScreens()) + { + if (screen is TitleScreen) + { + loadEnding = false; + break; + } + } + (m_levelToLoad as CreditsScreen).IsEnding = loadEnding; + + lock (m_levelToLoad) + m_loadingComplete = true; + break; + case (ScreenType.Title): + case (ScreenType.TitleWhite): + m_levelToLoad = new TitleScreen(); + lock (m_levelToLoad) + { + m_loadingComplete = true; + } + break; + case (ScreenType.Lineage): + m_levelToLoad = new LineageScreen(); + lock (m_levelToLoad) + { + m_loadingComplete = true; + } + break; + case (ScreenType.Level): + case (ScreenType.Ending): + case (ScreenType.StartingRoom): + case (ScreenType.TutorialRoom): + RCScreenManager manager = ScreenManager as RCScreenManager; + + AreaStruct[] levelStruct = Game.Area1List; + + m_levelToLoad = null; + + // Creating the level. + if (m_screenTypeToLoad == ScreenType.StartingRoom) + m_levelToLoad = LevelBuilder2.CreateStartingRoom(); + else if (m_screenTypeToLoad == ScreenType.TutorialRoom) + m_levelToLoad = LevelBuilder2.CreateTutorialRoom(); + else if (m_screenTypeToLoad == ScreenType.Ending) + m_levelToLoad = LevelBuilder2.CreateEndingRoom(); + else + { + ProceduralLevelScreen level = (ScreenManager as RCScreenManager).GetLevelScreen(); + // Player is loading a level from the starting room. + if (level != null) + { + if (Game.PlayerStats.LockCastle == true) // Castle is locked. Load the saved map. + { + try + { + m_levelToLoad = (ScreenManager.Game as Game).SaveManager.LoadMap(); + } + catch + { + m_gameCrashed = true; + } + + if (m_gameCrashed == false) + { + (ScreenManager.Game as Game).SaveManager.LoadFiles(m_levelToLoad as ProceduralLevelScreen, SaveType.MapData); + Game.PlayerStats.LockCastle = false; // Must go after loading map data, because map data uses the LockCastle flag to determine whether or not to reset enemies & fairy chests. + } + } + else // Castle is not locked. Load a new map. + m_levelToLoad = LevelBuilder2.CreateLevel(level.RoomList[0], levelStruct); + } + else // Player is loading from the title screen. + { + if (Game.PlayerStats.LoadStartingRoom == true) // New game. Player has started in the starting room. + { + Console.WriteLine("This should only be used for debug purposes"); + m_levelToLoad = LevelBuilder2.CreateLevel(null, levelStruct); + (ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.Map, SaveType.MapData); + } + else // Player has saved data. Load the saved map and saved map data. + { + try + { + m_levelToLoad = (ScreenManager.Game as Game).SaveManager.LoadMap(); + (ScreenManager.Game as Game).SaveManager.LoadFiles(m_levelToLoad as ProceduralLevelScreen, SaveType.MapData); + } + catch + { + m_gameCrashed = true; + } + + if (m_gameCrashed == false) + { + //(ScreenManager.Game as Game).SaveManager.LoadFiles(m_levelToLoad as ProceduralLevelScreen, SaveType.MapData); + Game.ScreenManager.Player.Position = new Vector2((m_levelToLoad as ProceduralLevelScreen).RoomList[1].X, 720 - 300); // Sets the player in the castle entrance. + } + } + } + } + + if (m_gameCrashed == false) + { + lock (m_levelToLoad) + { + ProceduralLevelScreen level = m_levelToLoad as ProceduralLevelScreen; + level.Player = manager.Player; + manager.Player.AttachLevel(level); + for (int i = 0; i < level.RoomList.Count; i++) + level.RoomList[i].RoomNumber = i + 1; + manager.AttachMap(level); + if (m_wipeTransition == false) + Thread.Sleep(100); + m_loadingComplete = true; + } + } + break; + } + } + + public override void Update(GameTime gameTime) + { + if (m_gameCrashed == true) + { + //Game.ScreenManager.DialogueScreen.SetDialogue("Save File Error"); + //Game.ScreenManager.DialogueScreen.SetConfirmEndHandler((ScreenManager.Game as Game).SaveManager, "LoadAutosave"); + //Game.ScreenManager.DisplayScreen(ScreenType.Dialogue, false, null); + (ScreenManager.Game as Game).SaveManager.ForceBackup(); + } + + if (m_isLoading == true && m_loadingComplete == true && m_gameCrashed == false) + EndLoading(); + + //m_gateSprite.GetChildAt(1).Rotation += 2; + //m_gateSprite.GetChildAt(2).Rotation -= 2; + + float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds; + + m_gateSprite.GetChildAt(1).Rotation += (120 * elapsedSeconds); + m_gateSprite.GetChildAt(2).Rotation -= (120 * elapsedSeconds); + + if (m_shakeScreen == true) + UpdateShake(); + + base.Update(gameTime); + } + + public void EndLoading() + { + m_isLoading = false; + ScreenManager manager = ScreenManager; + + foreach (Screen screen in ScreenManager.GetScreens()) + { + if (screen != this) + manager.RemoveScreen(screen, true); + else + manager.RemoveScreen(screen, false); // Don't dispose the loading screen just yet. + } + + this.ScreenManager = manager; // Since RemoveScreen removes the reference to the ScreenManager, we need to re-add the reference (for now). + m_levelToLoad.DrawIfCovered = true; + + if (m_screenTypeToLoad == ScreenType.StartingRoom) + { + // Only display the skill screen if the player has died before. + if (Game.PlayerStats.IsDead == true) + (m_levelToLoad as ProceduralLevelScreen).DisableRoomOnEnter = true; // We don't want to call the levelscreens' OnEnter while the skill screen is being added. + ScreenManager.AddScreen(m_levelToLoad, PlayerIndex.One); + if (Game.PlayerStats.IsDead == true) + { + ScreenManager.AddScreen((ScreenManager as RCScreenManager).SkillScreen, PlayerIndex.One); + (m_levelToLoad as ProceduralLevelScreen).DisableRoomOnEnter = false; + } + m_levelToLoad.UpdateIfCovered = false; // We don't want the levelscreen to update while the skillscreen is being added. + } + else + { + ScreenManager.AddScreen(m_levelToLoad, PlayerIndex.One); + m_levelToLoad.UpdateIfCovered = true; // This is needed so that the screen still plays when the screen is swiping or gate is rising. + } + + ScreenManager.AddScreen(this, PlayerIndex.One); + (ScreenManager as RCScreenManager).LoadingComplete(m_screenTypeToLoad); + + (ScreenManager as RCScreenManager).PerformCleanUp(); + AddFinalTransition(); + } + + public void AddFinalTransition() + { + if (m_screenTypeToLoad == ScreenType.TitleWhite) + { + BackBufferOpacity = 1; + Tween.To(this, 2f, Tween.EaseNone, "BackBufferOpacity", "0"); + Tween.AddEndHandlerToLastTween(ScreenManager, "RemoveScreen", this, true); + } + else + { + if (m_wipeTransition == false) + { + SoundManager.PlaySound("GateRise"); + Tween.To(m_gateSprite, 1f, Tween.EaseNone, "Y", (-m_gateSprite.Height).ToString()); + Tween.AddEndHandlerToLastTween(ScreenManager, "RemoveScreen", this, true); + } + else + { + m_blackTransitionOut.Y = -500; + Tween.By(m_blackTransitionIn, 0.2f, Tween.EaseNone, "X", (-m_blackTransitionIn.Bounds.Width).ToString()); + Tween.By(m_blackScreen, 0.2f, Tween.EaseNone, "X", (-m_blackTransitionIn.Bounds.Width).ToString()); + Tween.By(m_blackTransitionOut, 0.2f, Tween.EaseNone, "X", (-m_blackTransitionIn.Bounds.Width).ToString()); + Tween.AddEndHandlerToLastTween(ScreenManager, "RemoveScreen", this, true); + } + } + } + + public override void Draw(GameTime gameTime) + { + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); + if (m_screenTypeToLoad != ScreenType.TitleWhite) + { + if (m_wipeTransition == false) + { + m_gateSprite.Draw(Camera); + m_effectPool.Draw(Camera); + m_loadingText.Position = new Vector2(m_gateSprite.X + 995, m_gateSprite.Y + 540); + m_loadingText.Draw(Camera); + } + else + { + m_blackTransitionIn.Draw(Camera); + m_blackTransitionOut.Draw(Camera); + m_blackScreen.Draw(Camera); + } + } + + Camera.Draw(Game.GenericTexture, new Rectangle(0, 0, 1320, 720), Color.White * BackBufferOpacity); + + Camera.End(); + + base.Draw(gameTime); + } + + private bool m_horizontalShake; + private bool m_verticalShake; + private bool m_shakeScreen; + private float m_screenShakeMagnitude; + + public void ShakeScreen(float magnitude, bool horizontalShake = true, bool verticalShake = true) + { + m_screenShakeMagnitude = magnitude; + m_horizontalShake = horizontalShake; + m_verticalShake = verticalShake; + m_shakeScreen = true; + } + + public void UpdateShake() + { + if (m_horizontalShake == true) + m_gateSprite.X = CDGMath.RandomPlusMinus() * (CDGMath.RandomFloat(0,1) * m_screenShakeMagnitude); + + if (m_verticalShake == true) + m_gateSprite.Y = CDGMath.RandomPlusMinus() * (CDGMath.RandomFloat(0,1) * m_screenShakeMagnitude); + } + + + public void StopScreenShake() + { + m_shakeScreen = false; + m_gateSprite.X = 0; + m_gateSprite.Y = 0; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Loading Screen"); + + m_loadingText.Dispose(); + m_loadingText = null; + m_levelToLoad = null; + m_gateSprite.Dispose(); + m_gateSprite = null; + m_effectPool.Dispose(); + m_effectPool = null; + + m_blackTransitionIn.Dispose(); + m_blackTransitionIn = null; + m_blackScreen.Dispose(); + m_blackScreen = null; + m_blackTransitionOut.Dispose(); + m_blackTransitionOut = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Screens/MapScreen.cs b/RogueCastle/src/Screens/MapScreen.cs new file mode 100644 index 0000000..334bf61 --- /dev/null +++ b/RogueCastle/src/Screens/MapScreen.cs @@ -0,0 +1,470 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using InputSystem; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class MapScreen : Screen + { + private MapObj m_mapDisplay; + private ObjContainer m_legend; + + // Teleporter objects. + private SpriteObj[] m_teleporterList; + + private SpriteObj m_titleText; + private ObjContainer m_playerIcon; + private int m_selectedTeleporter; + + private KeyIconTextObj m_continueText; + private KeyIconTextObj m_recentreText; + private KeyIconTextObj m_navigationText; + private TextObj m_alzheimersQuestionMarks; + + public MapScreen(ProceduralLevelScreen level) + { + m_mapDisplay = new MapObj(false, level); + + m_alzheimersQuestionMarks = new TextObj(Game.JunicodeLargeFont); + m_alzheimersQuestionMarks.FontSize = 30; + m_alzheimersQuestionMarks.ForceDraw = true; + m_alzheimersQuestionMarks.Text = "?????"; + m_alzheimersQuestionMarks.Align = Types.TextAlign.Centre; + m_alzheimersQuestionMarks.Position = new Vector2(1320 / 2f, 720 / 2f - m_alzheimersQuestionMarks.Height / 2f); + } + + private void FindRoomTitlePos(List roomList, GameTypes.LevelType levelType, out Vector2 pos) + { + float leftMost = float.MaxValue; + float rightMost = -float.MaxValue; + float topMost = float.MaxValue; + float bottomMost = -float.MaxValue; + + foreach (RoomObj room in roomList) + { + if (room.Name != "Boss") + { + if (room.LevelType == levelType || (room.LevelType == GameTypes.LevelType.CASTLE && (room.Name == "Start" || room.Name == "CastleEntrance"))) + { + if (room.X < leftMost) + leftMost = room.X; + if (room.X + room.Width > rightMost) + rightMost = room.X + room.Width; + if (room.Y < topMost) + topMost = room.Y; + if (room.Y + room.Height > bottomMost) + bottomMost = room.Y + room.Height; + } + } + } + + pos = new Vector2((rightMost + leftMost) / 2f, (bottomMost + topMost) / 2f); + pos = new Vector2(pos.X / 1320f * 60, pos.Y / 720f * 32); + } + + public void SetPlayer(PlayerObj player) + { + m_mapDisplay.SetPlayer(player); + } + + public override void LoadContent() + { + //m_mapDisplay.SetPlayer((ScreenManager as RCScreenManager).GetLevelScreen().Player); + m_mapDisplay.InitializeAlphaMap(new Rectangle(50, 50, 1320 - 100, 720 - 100), Camera); + //m_mapDisplay.CameraOffset = new Vector2(100, 720 / 2f); + m_mapDisplay.CameraOffset = new Vector2(1320 / 2, 720 / 2); + + m_legend = new ObjContainer(); + m_legend.ForceDraw = true; + SpriteObj legendBG = new SpriteObj("TraitsScreenPlate_Sprite"); + m_legend.AddChild(legendBG); + legendBG.Scale = new Vector2(0.75f, 0.58f); + + TextObj legendTitle = new TextObj(Game.JunicodeFont); + legendTitle.Align = Types.TextAlign.Centre; + legendTitle.Position = new Vector2(m_legend.Width/2 * legendBG.ScaleX, m_legend.Bounds.Top + 10); + legendTitle.Text = LocaleBuilder.getString("LOC_ID_MAP_SCREEN_5", legendTitle); //"Legend" + legendTitle.FontSize = 12; + legendTitle.DropShadow = new Vector2(2, 2); + legendTitle.TextureColor = new Color(213, 213, 173); + + m_legend.AddChild(legendTitle); + m_legend.AnimationDelay = 1 / 30f; + m_legend.Position = new Vector2(1320 - m_legend.Width - 20, 720 - m_legend.Height - 20); + + SpriteObj playerIcon = new SpriteObj("MapPlayerIcon_Sprite"); + playerIcon.Position = new Vector2(30, 60); + playerIcon.PlayAnimation(); + m_legend.AddChild(playerIcon); + + int iconYOffset = 30; + SpriteObj bossIcon = new SpriteObj("MapBossIcon_Sprite"); + bossIcon.Position = new Vector2(playerIcon.X, playerIcon.Y + iconYOffset); + bossIcon.PlayAnimation(); + m_legend.AddChild(bossIcon); + + SpriteObj lockedChestIcon = new SpriteObj("MapLockedChestIcon_Sprite"); + lockedChestIcon.Position = new Vector2(playerIcon.X, bossIcon.Y + iconYOffset); + lockedChestIcon.PlayAnimation(); + m_legend.AddChild(lockedChestIcon); + + SpriteObj fairyChestIcon = new SpriteObj("MapFairyChestIcon_Sprite"); + fairyChestIcon.Position = new Vector2(playerIcon.X, lockedChestIcon.Y + iconYOffset); + fairyChestIcon.PlayAnimation(); + m_legend.AddChild(fairyChestIcon); + + SpriteObj openedChestIcon = new SpriteObj("MapChestUnlocked_Sprite"); + openedChestIcon.Position = new Vector2(playerIcon.X, fairyChestIcon.Y + iconYOffset); + m_legend.AddChild(openedChestIcon); + + SpriteObj teleporterIcon = new SpriteObj("MapTeleporterIcon_Sprite"); + teleporterIcon.Position = new Vector2(playerIcon.X, openedChestIcon.Y + iconYOffset); + teleporterIcon.PlayAnimation(); + m_legend.AddChild(teleporterIcon); + + SpriteObj bonusIcon = new SpriteObj("MapBonusIcon_Sprite"); + bonusIcon.Position = new Vector2(playerIcon.X, teleporterIcon.Y + iconYOffset); + bonusIcon.PlayAnimation(true); + m_legend.AddChild(bonusIcon); + + TextObj legendText; + + legendText = new TextObj(Game.JunicodeFont); + legendText.Position = new Vector2(playerIcon.X + 40, 55); + legendText.Text = LocaleBuilder.getString("LOC_ID_MAP_SCREEN_6", legendText); //"You are here" + legendText.FontSize = 10; + legendText.DropShadow = new Vector2(2, 2); + m_legend.AddChild(legendText); + + legendText = new TextObj(Game.JunicodeFont); + legendText.Position = new Vector2(playerIcon.X + 40, 55 + iconYOffset); + legendText.Text = LocaleBuilder.getString("LOC_ID_MAP_SCREEN_7", legendText); //"Boss location" + legendText.FontSize = 10; + legendText.DropShadow = new Vector2(2, 2); + m_legend.AddChild(legendText); + + legendText = new TextObj(Game.JunicodeFont); + legendText.Position = new Vector2(playerIcon.X + 40, 55 + iconYOffset + iconYOffset); + legendText.Text = LocaleBuilder.getString("LOC_ID_MAP_SCREEN_8", legendText); //"Unopened chest" + legendText.FontSize = 10; + legendText.DropShadow = new Vector2(2, 2); + m_legend.AddChild(legendText); + + legendText = new TextObj(Game.JunicodeFont); + legendText.Position = new Vector2(playerIcon.X + 40, 55 + iconYOffset + iconYOffset + iconYOffset); + legendText.Text = LocaleBuilder.getString("LOC_ID_MAP_SCREEN_9", legendText); //"Fairy chest" + legendText.FontSize = 10; + legendText.DropShadow = new Vector2(2, 2); + m_legend.AddChild(legendText); + + legendText = new TextObj(Game.JunicodeFont); + legendText.Position = new Vector2(playerIcon.X + 40, 55 + iconYOffset + iconYOffset + iconYOffset + iconYOffset); + legendText.Text = LocaleBuilder.getString("LOC_ID_MAP_SCREEN_10", legendText); //"Opened chest" + legendText.FontSize = 10; + legendText.DropShadow = new Vector2(2, 2); + m_legend.AddChild(legendText); + + legendText = new TextObj(Game.JunicodeFont); + legendText.Position = new Vector2(playerIcon.X + 40, 55 + iconYOffset + iconYOffset + iconYOffset + iconYOffset + iconYOffset); + legendText.Text = LocaleBuilder.getString("LOC_ID_MAP_SCREEN_11", legendText); //"Teleporter" + legendText.FontSize = 10; + legendText.DropShadow = new Vector2(2, 2); + m_legend.AddChild(legendText); + + legendText = new TextObj(Game.JunicodeFont); + legendText.Position = new Vector2(playerIcon.X + 40, 55 + iconYOffset + iconYOffset + iconYOffset + iconYOffset + iconYOffset + iconYOffset); + legendText.Text = LocaleBuilder.getString("LOC_ID_MAP_SCREEN_12", legendText); //"Bonus Room" + legendText.FontSize = 10; + legendText.DropShadow = new Vector2(2, 2); + m_legend.AddChild(legendText); + + playerIcon.X += 4;// hack to properly position player icon. + playerIcon.Y += 4;// hack to properly position player icon. + + // Loading Teleporter objects. + m_titleText = new SpriteObj("TeleporterTitleText_Sprite"); + m_titleText.ForceDraw = true; + m_titleText.X = GlobalEV.ScreenWidth / 2; + m_titleText.Y = GlobalEV.ScreenHeight * 0.1f; + + m_playerIcon = new ObjContainer("PlayerWalking_Character"); + m_playerIcon.Scale = new Vector2(0.6f, 0.6f); + m_playerIcon.AnimationDelay = 1 / 10f; + m_playerIcon.PlayAnimation(true); + m_playerIcon.ForceDraw = true; + m_playerIcon.OutlineWidth = 2; + + m_playerIcon.GetChildAt(PlayerPart.Cape).TextureColor = Color.Red; + m_playerIcon.GetChildAt(PlayerPart.Hair).TextureColor = Color.Red; + m_playerIcon.GetChildAt(PlayerPart.Neck).TextureColor = Color.Red; + m_playerIcon.GetChildAt(PlayerPart.Light).Visible = false; + m_playerIcon.GetChildAt(PlayerPart.Boobs).Visible = false; + m_playerIcon.GetChildAt(PlayerPart.Bowtie).Visible = false; + m_playerIcon.GetChildAt(PlayerPart.Wings).Visible = false; + m_playerIcon.GetChildAt(PlayerPart.Extra).Visible = false; + m_playerIcon.GetChildAt(PlayerPart.Glasses).Visible = false; + + m_continueText = new KeyIconTextObj(Game.JunicodeFont); + m_continueText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_continueText); // dummy locID to add TextObj to language refresh list + m_continueText.FontSize = 12; + m_continueText.ForceDraw = true; + m_continueText.Position = new Vector2(50, 200 - m_continueText.Height - 40); + //m_continueText.ForcedScale = new Vector2(0.5f, 0.5f); // Added for PS3 + + m_recentreText = new KeyIconTextObj(Game.JunicodeFont); + m_recentreText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_recentreText); // dummy locID to add TextObj to language refresh list + m_recentreText.FontSize = 12; + m_recentreText.Position = new Vector2(m_continueText.X, 200 - m_continueText.Height - 80); + m_recentreText.ForceDraw = true; + + m_navigationText = new KeyIconTextObj(Game.JunicodeFont); + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_navigationText); // dummy locID to add TextObj to language refresh list + m_navigationText.FontSize = 12; + m_navigationText.Position = new Vector2(m_continueText.X, 200 - m_continueText.Height - 120); + m_navigationText.ForceDraw = true; + + base.LoadContent(); + } + + public override void ReinitializeRTs() + { + m_mapDisplay.InitializeAlphaMap(new Rectangle(50, 50, 1320 - 100, 720 - 100), Camera); + base.ReinitializeRTs(); + } + + public void AddRooms(List roomList) + { + m_mapDisplay.AddAllRooms(roomList); + } + + public void RefreshMapChestIcons(RoomObj room) + { + m_mapDisplay.RefreshChestIcons(room); + } + + public override void OnEnter() + { + SoundManager.PlaySound("Map_On"); + + m_mapDisplay.CentreAroundPlayer(); + + if (IsTeleporter == false && (Game.PlayerStats.Traits.X == TraitType.Alzheimers || Game.PlayerStats.Traits.Y == TraitType.Alzheimers)) + m_mapDisplay.DrawNothing = true; + else + m_mapDisplay.DrawNothing = false; + + m_continueText.Text = LocaleBuilder.getString("LOC_ID_MAP_SCREEN_1_NEW", m_continueText); //"to close map" + m_recentreText.Text = LocaleBuilder.getString("LOC_ID_MAP_SCREEN_2_NEW", m_recentreText); //"to center on player" + if (InputManager.GamePadIsConnected(PlayerIndex.One) == false) + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_MAP_SCREEN_3", m_navigationText); //"Use arrow keys to move map" + else + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_MAP_SCREEN_4_NEW", m_navigationText); //"to move map" + + if (IsTeleporter && m_teleporterList.Length > 0) + { + //PlayerObj player = (ScreenManager as RCScreenManager).GetLevelScreen().Player; + //for (int i = 0; i < m_playerIcon.NumChildren; i++) + // m_playerIcon.GetChildAt(i).TextureColor = player.GetChildAt(i).TextureColor; + + //m_selectedTeleporter = 0; + SpriteObj icon = m_teleporterList[m_selectedTeleporter]; + m_playerIcon.Position = new Vector2(icon.X + 14 / 2f, icon.Y - 20); + m_mapDisplay.CentreAroundTeleporter(m_selectedTeleporter); + } + + Game.ChangeBitmapLanguage(m_titleText, "TeleporterTitleText_Sprite"); + + base.OnEnter(); + } + + public override void OnExit() + { + SoundManager.PlaySound("Map_Off"); + + IsTeleporter = false; + base.OnExit(); + } + + public override void HandleInput() + { + if (Game.GlobalInput.JustPressed(InputMapType.MENU_MAP) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + { + Game.ScreenManager.Player.UnlockControls(); + (this.ScreenManager as RCScreenManager).HideCurrentScreen(); + } + + if (IsTeleporter == false) + { + float movementAmount = 5f; + if (Game.GlobalInput.Pressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_UP2)) + m_mapDisplay.CameraOffset.Y += movementAmount; + else if (Game.GlobalInput.Pressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_DOWN2)) + m_mapDisplay.CameraOffset.Y -= movementAmount; + + if (Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_LEFT2)) + m_mapDisplay.CameraOffset.X += movementAmount; + else if (Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.Pressed(InputMapType.PLAYER_RIGHT2)) + m_mapDisplay.CameraOffset.X -= movementAmount; + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + m_mapDisplay.CentreAroundPlayer(); + } + else + { + int previousSelection = m_selectedTeleporter; + + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT2)) + { + m_selectedTeleporter++; + if (m_selectedTeleporter >= m_teleporterList.Length) + m_selectedTeleporter = 0; + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT2)) + { + m_selectedTeleporter--; + if (m_selectedTeleporter < 0 && m_teleporterList.Length > 0) + m_selectedTeleporter = m_teleporterList.Length - 1; + else if (m_selectedTeleporter < 0 && m_teleporterList.Length <= 0) + m_selectedTeleporter = 0; + } + + if (previousSelection != m_selectedTeleporter) + m_mapDisplay.CentreAroundTeleporter(m_selectedTeleporter, true); + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + m_mapDisplay.TeleportPlayer(m_selectedTeleporter); + (this.ScreenManager as RCScreenManager).HideCurrentScreen(); + } + } + + base.HandleInput(); + } + + public override void Draw(GameTime gameTime) + { + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); + m_mapDisplay.DrawRenderTargets(Camera); + Camera.End(); + + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); + Camera.GraphicsDevice.SetRenderTarget(Game.ScreenManager.RenderTarget); + Camera.GraphicsDevice.Clear(Color.Black); + + Camera.Draw((ScreenManager as RCScreenManager).GetLevelScreen().RenderTarget, Vector2.Zero, Color.White * 0.3f); // Comment in this line if you want the back screen drawn. + m_mapDisplay.Draw(Camera); + + if (IsTeleporter == true && m_teleporterList.Length > 0) + { + m_titleText.Draw(Camera); + SpriteObj icon = m_teleporterList[m_selectedTeleporter]; + m_playerIcon.Position = new Vector2(icon.X + 14, icon.Y - 20); + m_playerIcon.Draw(Camera); + } + + if (IsTeleporter == false) + { + m_recentreText.Draw(Camera); + m_navigationText.Draw(Camera); + } + + if (IsTeleporter == false && (Game.PlayerStats.Traits.X == TraitType.Alzheimers || Game.PlayerStats.Traits.Y == TraitType.Alzheimers)) + m_alzheimersQuestionMarks.Draw(Camera); + + m_continueText.Draw(Camera); + m_legend.Draw(Camera); + Camera.End(); + base.Draw(gameTime); // Doesn't do anything. + } + + public void AddAllIcons(List roomList) + { + m_mapDisplay.AddAllIcons(roomList); + } + + public override void DisposeRTs() + { + m_mapDisplay.DisposeRTs(); + base.DisposeRTs(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Map Screen"); + + if (m_mapDisplay != null) + m_mapDisplay.Dispose(); + m_mapDisplay = null; + if (m_legend != null) + m_legend.Dispose(); + m_legend = null; + + if (m_playerIcon != null) + m_playerIcon.Dispose(); + m_playerIcon = null; + if (m_teleporterList != null) + Array.Clear(m_teleporterList, 0, m_teleporterList.Length); + m_teleporterList = null; + if (m_titleText != null) + m_titleText.Dispose(); + m_titleText = null; + if (m_continueText != null) + m_continueText.Dispose(); + m_continueText = null; + if (m_recentreText != null) + m_recentreText.Dispose(); + m_recentreText = null; + if (m_navigationText != null) + m_navigationText.Dispose(); + m_navigationText = null; + + m_alzheimersQuestionMarks.Dispose(); + m_alzheimersQuestionMarks = null; + + base.Dispose(); + } + } + + private bool m_isTeleporter = false; + public bool IsTeleporter + { + get { return m_isTeleporter; } + set + { + m_mapDisplay.DrawTeleportersOnly = value; + m_isTeleporter = value; + if (value == true) + { + if (m_teleporterList != null) + Array.Clear(m_teleporterList, 0, m_teleporterList.Length); + m_teleporterList = m_mapDisplay.TeleporterList(); + } + } + } + + public override void RefreshTextObjs() + { + /* + m_continueText.Text = "[Input:" + InputMapType.MENU_MAP + "] " + LocaleBuilder.getResourceString("LOC_ID_MAP_SCREEN_1"); //"to close map" + m_recentreText.Text = "[Input:" + InputMapType.MENU_CONFIRM1 + "] " + LocaleBuilder.getResourceString("LOC_ID_MAP_SCREEN_2"); //"to center on player" + if (InputManager.GamePadIsConnected(PlayerIndex.One) == false) + m_navigationText.Text = LocaleBuilder.getResourceString("LOC_ID_MAP_SCREEN_3"); //"Use arrow keys to move map" + else + m_navigationText.Text = "[Button:LeftStick] " + LocaleBuilder.getResourceString("LOC_ID_MAP_SCREEN_4"); //"to move map" + */ + Game.ChangeBitmapLanguage(m_titleText, "TeleporterTitleText_Sprite"); + + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Screens/OptionsScreen.cs b/RogueCastle/src/Screens/OptionsScreen.cs new file mode 100644 index 0000000..ab6c912 --- /dev/null +++ b/RogueCastle/src/Screens/OptionsScreen.cs @@ -0,0 +1,469 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using System.IO; +using System.Globalization; +using Microsoft.Xna.Framework.Input; +using InputSystem; + +namespace RogueCastle +{ + public class OptionsScreen : Screen + { + public float BackBufferOpacity { get; set; } + private OptionsObj m_selectedOption; + private int m_selectedOptionIndex = 0; + private bool m_changingControls = false; + + private List m_optionsArray; + + private ObjContainer m_bgSprite; + private bool m_transitioning = false; + + //private OptionsObj m_deleteSaveObj; + private OptionsObj m_backToMenuObj; + + private KeyIconTextObj m_confirmText; + private KeyIconTextObj m_cancelText; + private KeyIconTextObj m_navigationText; + + private SpriteObj m_optionsTitle; + private SpriteObj m_changeControlsTitle; + + private SpriteObj m_optionsBar; + private TextObj m_quickDropText; + private OptionsObj m_quickDropObj; + private OptionsObj m_reduceQualityObj; + private OptionsObj m_enableSteamCloudObj; + private OptionsObj m_unlockTraitorObj; + private int m_unlockTraitorIndex = 0; + + bool m_titleScreenOptions; + + public OptionsScreen() + { + m_optionsArray = new List(); + this.UpdateIfCovered = true; + this.DrawIfCovered = true; + m_titleScreenOptions = true; + } + + public override void LoadContent() + { + m_bgSprite = new ObjContainer("SkillUnlockPlate_Character"); + m_bgSprite.ForceDraw = true; + + m_optionsTitle = new SpriteObj("OptionsScreenTitle_Sprite"); + m_bgSprite.AddChild(m_optionsTitle); + m_optionsTitle.Position = new Vector2(0, -m_bgSprite.Width / 2f + 60); + + m_changeControlsTitle = new SpriteObj("OptionsScreenChangeControls_Sprite"); + m_bgSprite.AddChild(m_changeControlsTitle); + m_changeControlsTitle.Position = new Vector2(1320, m_optionsTitle.Y); + + if (!(Environment.GetEnvironmentVariable("SteamTenfoot") == "1" || Environment.GetEnvironmentVariable("SteamDeck") == "1")) + { + m_optionsArray.Add(new ResolutionOptionsObj(this)); + m_optionsArray.Add(new FullScreenOptionsObj(this)); + } + m_reduceQualityObj = new ReduceQualityOptionsObj(this); + m_optionsArray.Add(m_reduceQualityObj); + m_optionsArray.Add(new MusicVolOptionsObj(this)); + m_optionsArray.Add(new SFXVolOptionsObj(this)); + m_quickDropObj = new QuickDropOptionsObj(this); + m_optionsArray.Add(m_quickDropObj); + m_optionsArray.Add(new DeadZoneOptionsObj(this)); + m_optionsArray.Add(new ChangeControlsOptionsObj(this)); + m_unlockTraitorObj = new UnlockTraitorOptionsObj(this); + m_unlockTraitorObj.X = 420; + m_unlockTraitorIndex = m_optionsArray.Count; + //m_optionsArray.Add(m_unlockTraitorObj); // Added at OnEnter() + +// m_enableSteamCloudObj = new SteamCloudOptionsObj(this); +//#if STEAM +// m_optionsArray.Add(m_enableSteamCloudObj); +//#endif + //m_deleteSaveObj = new DeleteSaveOptionsObj(this); + //m_optionsArray.Add(m_deleteSaveObj); + + m_optionsArray.Add(new LanguageOptionsObj(this)); + + m_optionsArray.Add(new ExitProgramOptionsObj(this)); + m_backToMenuObj = new BackToMenuOptionsObj(this); + m_backToMenuObj.X = 420; + + for (int i = 0; i < m_optionsArray.Count; i++) + { + m_optionsArray[i].X = 420; + m_optionsArray[i].Y = 160 + (i * 30); + } + + //m_backToMenuObj.Position = m_deleteSaveObj.Position; + + m_optionsBar = new SpriteObj("OptionsBar_Sprite"); + m_optionsBar.ForceDraw = true; + m_optionsBar.Position = new Vector2(m_optionsArray[0].X - 20, m_optionsArray[0].Y); + + m_confirmText = new KeyIconTextObj(Game.JunicodeFont); + m_confirmText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_confirmText); // dummy locID to add TextObj to language refresh list + m_confirmText.DropShadow = new Vector2(2, 2); + m_confirmText.FontSize = 12; + m_confirmText.Align = Types.TextAlign.Right; + m_confirmText.Position = new Vector2(1290, 570); + m_confirmText.ForceDraw = true; + + m_cancelText = new KeyIconTextObj(Game.JunicodeFont); + m_cancelText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_cancelText); // dummy locID to add TextObj to language refresh list + m_cancelText.Align = Types.TextAlign.Right; + m_cancelText.DropShadow = new Vector2(2, 2); + m_cancelText.FontSize = 12; + m_cancelText.Position = new Vector2(m_confirmText.X, m_confirmText.Y + 40); + m_cancelText.ForceDraw = true; + + m_navigationText = new KeyIconTextObj(Game.JunicodeFont); + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_navigationText); // dummy locID to add TextObj to language refresh list + m_navigationText.Align = Types.TextAlign.Right; + m_navigationText.DropShadow = new Vector2(2, 2); + m_navigationText.FontSize = 12; + m_navigationText.Position = new Vector2(m_confirmText.X, m_confirmText.Y + 80); + m_navigationText.ForceDraw = true; + + m_quickDropText = new TextObj(Game.JunicodeFont); + m_quickDropText.FontSize = 8; + m_quickDropText.Text = "*Quick drop allows you to drop down ledges and down-attack in \nthe air by pressing DOWN"; + m_quickDropText.Position = new Vector2(420, 620); + m_quickDropText.ForceDraw = true; + m_quickDropText.DropShadow = new Vector2(2, 2); + base.LoadContent(); + } + + public override void PassInData(List objList) + { + m_titleScreenOptions = (bool)objList[0]; + base.PassInData(objList); + } + + public override void OnEnter() + { + RefreshTextObjs(); + + m_quickDropText.Visible = false; + + if (InputManager.GamePadIsConnected(PlayerIndex.One)) + { + m_confirmText.ForcedScale = new Vector2(0.7f, 0.7f); + m_cancelText.ForcedScale = new Vector2(0.7f, 0.7f); + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_SCREEN_2_NEW", m_navigationText); + } + else + { + m_confirmText.ForcedScale = new Vector2(1f, 1f); + m_cancelText.ForcedScale = new Vector2(1f, 1f); + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_SCREEN_3", m_navigationText); + } + m_confirmText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_SCREEN_4_NEW", m_confirmText); + m_cancelText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_SCREEN_5_NEW", m_cancelText); + + m_confirmText.Opacity = 0; + m_cancelText.Opacity = 0; + m_navigationText.Opacity = 0; + + Tween.To(m_confirmText, 0.2f, Tween.EaseNone, "Opacity", "1"); + Tween.To(m_cancelText, 0.2f, Tween.EaseNone, "Opacity", "1"); + Tween.To(m_navigationText, 0.2f, Tween.EaseNone, "Opacity", "1"); + + Tween.RunFunction(0.1f, typeof(SoundManager), "PlaySound", "DialogueMenuOpen"); + //SoundManager.PlaySound("DialogueMenuOpen"); + + + if (m_optionsArray.Contains(m_backToMenuObj) == false) + m_optionsArray.Insert(m_optionsArray.Count - 1, m_backToMenuObj); + if (m_titleScreenOptions == true) + m_optionsArray.RemoveAt(m_optionsArray.Count - 2); // Remove the second last entry because the last entry is "Exit Program" + + // Adding the traitor menu if the traitor has been unlocked. Will be removed on menu exit. + if (Game.GameConfig.UnlockTraitor > 0) + m_optionsArray.Insert(m_unlockTraitorIndex, m_unlockTraitorObj); + + m_transitioning = true; + Tween.To(this, 0.2f, Tween.EaseNone, "BackBufferOpacity", "0.8"); + + //(m_optionsArray[0] as ResolutionOptionsObj).Initialize(); // The resolutionObj needs to be initialized every time. + + m_selectedOptionIndex = 0; + m_selectedOption = m_optionsArray[m_selectedOptionIndex]; + m_selectedOption.IsActive = false; + + m_bgSprite.Position = new Vector2(1320 / 2f, 0); + m_bgSprite.Opacity = 0; + Tween.To(m_bgSprite, 0.5f, Tweener.Ease.Quad.EaseOut, "Y", (720 / 2f).ToString()); + Tween.AddEndHandlerToLastTween(this, "EndTransition"); + Tween.To(m_bgSprite, 0.2f, Tween.EaseNone, "Opacity", "1"); + + int counter = 0; + foreach (OptionsObj obj in m_optionsArray) + { + obj.Y = 160 + (counter * 30) - (720 / 2f); + obj.Opacity = 0; + Tween.By(obj, 0.5f, Tweener.Ease.Quad.EaseOut, "Y", (720 / 2f).ToString()); + Tween.To(obj, 0.2f, Tween.EaseNone, "Opacity", "1"); + obj.Initialize(); + counter++; + } + + m_optionsBar.Opacity = 0; + Tween.To(m_optionsBar, 0.2f, Tween.EaseNone, "Opacity", "1"); + + base.OnEnter(); + } + + public void EndTransition() + { + m_transitioning = false; + } + + private void ExitTransition() + { + SoundManager.PlaySound("DialogMenuClose"); + + m_transitioning = true; + + + Tween.To(m_confirmText, 0.2f, Tween.EaseNone, "Opacity", "0"); + Tween.To(m_cancelText, 0.2f, Tween.EaseNone, "Opacity", "0"); + Tween.To(m_navigationText, 0.2f, Tween.EaseNone, "Opacity", "0"); + + Tween.To(this, 0.2f, Tween.EaseNone, "BackBufferOpacity", "0"); + Tween.To(m_optionsBar, 0.2f, Tween.EaseNone, "Opacity", "0"); + + m_bgSprite.Position = new Vector2(1320 / 2f, 720 / 2f); + m_bgSprite.Opacity = 1; + Tween.To(m_bgSprite, 0.5f, Tweener.Ease.Quad.EaseOut, "Y", "0"); + Tween.To(m_bgSprite, 0.2f, Tween.EaseNone, "Opacity", "0"); + + int counter = 0; + foreach (OptionsObj obj in m_optionsArray) + { + obj.Y = 160 + (counter * 30); + obj.Opacity = 1; + Tween.By(obj, 0.5f, Tweener.Ease.Quad.EaseOut, "Y", (-(720 / 2f)).ToString()); + Tween.To(obj, 0.2f, Tween.EaseNone, "Opacity", "0"); + counter++; + } + + Tween.AddEndHandlerToLastTween(ScreenManager, "HideCurrentScreen"); + } + + public override void OnExit() + { + m_selectedOption.IsActive = false; + m_selectedOption.IsSelected = false; + m_selectedOption = null; + (ScreenManager.Game as Game).SaveConfig(); + (ScreenManager as RCScreenManager).UpdatePauseScreenIcons(); + + // Remove the unlock traitor option. + if (m_optionsArray.Contains(m_unlockTraitorObj)) + m_optionsArray.Remove(m_unlockTraitorObj); + base.OnExit(); + } + + public override void HandleInput() + { + if (m_transitioning == false) // No input until the screen is fully displayed. + { + if (m_selectedOption.IsActive == true) + m_selectedOption.HandleInput(); + else + { + if (m_selectedOption.IsActive == false) + { + int previousSelectedOptionIndex = m_selectedOptionIndex; + + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + if (m_selectedOptionIndex > 0) + SoundManager.PlaySound("frame_swap"); + m_selectedOptionIndex--; + } + else if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN2)) + { + if (m_selectedOptionIndex < m_optionsArray.Count - 1) + SoundManager.PlaySound("frame_swap"); + m_selectedOptionIndex++; + } + + if (m_selectedOptionIndex < 0) + m_selectedOptionIndex = m_optionsArray.Count - 1; + if (m_selectedOptionIndex > m_optionsArray.Count - 1) + m_selectedOptionIndex = 0; + + if (previousSelectedOptionIndex != m_selectedOptionIndex) + { + if (m_selectedOption != null) + m_selectedOption.IsSelected = false; + + m_selectedOption = m_optionsArray[m_selectedOptionIndex]; + m_selectedOption.IsSelected = true; + } + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + SoundManager.PlaySound("Option_Menu_Select"); + m_selectedOption.IsActive = true; + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_OPTIONS) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + ExitTransition(); + } + + + if (m_selectedOption == m_quickDropObj) + { + m_quickDropText.Visible = true; + m_quickDropText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_SCREEN_1", m_quickDropText, true); + } + else if (m_selectedOption == m_reduceQualityObj) + { + m_quickDropText.Visible = true; + m_quickDropText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_SCREEN_8", m_quickDropText, true); + } + else if (m_selectedOption == m_enableSteamCloudObj) + { + m_quickDropText.Visible = true; + m_quickDropText.Text = LocaleBuilder.getString("LOC_ID_OPTIONS_SCREEN_9", m_quickDropText, true); + } + else + m_quickDropText.Visible = false; + } + else + m_quickDropText.Visible = false; + + base.HandleInput(); + } + + public override void Update(GameTime gameTime) + { + foreach (OptionsObj obj in m_optionsArray) + obj.Update(gameTime); + + m_optionsBar.Position = new Vector2(m_selectedOption.X - 15, m_selectedOption.Y); + + base.Update(gameTime); + } + + public void ToggleControlsConfig() + { + if (m_changingControls == false) + { + foreach (OptionsObj obj in m_optionsArray) + Tweener.Tween.By(obj, 0.3f, Tweener.Ease.Quad.EaseInOut, "X", "-1320"); + Tweener.Tween.By(m_optionsTitle, 0.3f, Tweener.Ease.Quad.EaseInOut, "X", "-1320"); + Tweener.Tween.By(m_changeControlsTitle, 0.3f, Tweener.Ease.Quad.EaseInOut, "X", "-1320"); + m_changingControls = true; + } + else + { + foreach (OptionsObj obj in m_optionsArray) + Tweener.Tween.By(obj, 0.3f, Tweener.Ease.Quad.EaseInOut, "X", "1320"); + Tweener.Tween.By(m_optionsTitle, 0.3f, Tweener.Ease.Quad.EaseInOut, "X", "1320"); + Tweener.Tween.By(m_changeControlsTitle, 0.3f, Tweener.Ease.Quad.EaseInOut, "X", "1320"); + m_changingControls = false; + } + } + + public override void Draw(GameTime gametime) + { + Camera.Begin(); + Camera.Draw(Game.GenericTexture, new Rectangle(0, 0, GlobalEV.ScreenWidth, GlobalEV.ScreenHeight), Color.Black * BackBufferOpacity); + m_bgSprite.Draw(Camera); + foreach (OptionsObj obj in m_optionsArray) + obj.Draw(Camera); + + m_quickDropText.Draw(Camera); + + m_confirmText.Draw(Camera); + m_cancelText.Draw(Camera); + m_navigationText.Draw(Camera); + m_optionsBar.Draw(Camera); + Camera.End(); + + base.Draw(gametime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Options Screen"); + + foreach (OptionsObj obj in m_optionsArray) + obj.Dispose(); + + m_optionsArray.Clear(); + m_optionsArray = null; + m_bgSprite.Dispose(); + m_bgSprite = null; + m_optionsTitle = null; + m_changeControlsTitle = null; + //m_deleteSaveObj = null; + m_backToMenuObj = null; + + m_confirmText.Dispose(); + m_confirmText = null; + m_cancelText.Dispose(); + m_cancelText = null; + m_navigationText.Dispose(); + m_navigationText = null; + + m_optionsBar.Dispose(); + m_optionsBar = null; + + m_selectedOption = null; + + m_quickDropText.Dispose(); + m_quickDropText = null; + m_quickDropObj = null; + m_enableSteamCloudObj = null; + m_reduceQualityObj = null; + m_unlockTraitorObj = null; + base.Dispose(); + } + } + + public override void RefreshTextObjs() + { + /* + if (InputManager.GamePadIsConnected(PlayerIndex.One)) + m_navigationText.Text = "[Button:LeftStick] " + LocaleBuilder.getResourceString("LOC_ID_OPTIONS_SCREEN_2"); + else + m_navigationText.Text = LocaleBuilder.getResourceString("LOC_ID_OPTIONS_SCREEN_3"); + m_confirmText.Text = "[Input:" + InputMapType.MENU_CONFIRM1 + "] " + LocaleBuilder.getResourceString("LOC_ID_OPTIONS_SCREEN_4"); + m_cancelText.Text = "[Input:" + InputMapType.MENU_CANCEL1 + "] " + LocaleBuilder.getResourceString("LOC_ID_OPTIONS_SCREEN_5"); + */ + + foreach (OptionsObj obj in m_optionsArray) + obj.RefreshTextObjs(); + + Game.ChangeBitmapLanguage(m_optionsTitle, "OptionsScreenTitle_Sprite"); + Game.ChangeBitmapLanguage(m_changeControlsTitle, "OptionsScreenChangeControls_Sprite"); + + m_quickDropText.ScaleX = 1; + switch (LocaleBuilder.languageType) + { + case(LanguageType.Russian): + case(LanguageType.German): + m_quickDropText.ScaleX = 0.9f; + break; + } + + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Screens/PauseScreen.cs b/RogueCastle/src/Screens/PauseScreen.cs new file mode 100644 index 0000000..05bfbf5 --- /dev/null +++ b/RogueCastle/src/Screens/PauseScreen.cs @@ -0,0 +1,518 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using Microsoft.Xna.Framework.Graphics; +using InputSystem; +using Microsoft.Xna.Framework.Input; +using System.Text.RegularExpressions; + +namespace RogueCastle +{ + public class PauseScreen : Screen + { + private SpriteObj m_titleText; + private List m_infoObjList; + + private SpriteObj m_profileCard; + private SpriteObj m_optionsIcon; + + private KeyIconTextObj m_profileCardKey; + private KeyIconTextObj m_optionsKey; + + private float m_inputDelay = 0; + + public PauseScreen() + { + this.DrawIfCovered = true; + } + + public override void LoadContent() + { + m_titleText = new SpriteObj("GamePausedTitleText_Sprite"); + m_titleText.X = GlobalEV.ScreenWidth / 2; + m_titleText.Y = GlobalEV.ScreenHeight * 0.1f; + m_titleText.ForceDraw = true; + + m_infoObjList = new List(); + m_infoObjList.Add(new PauseInfoObj()); // Adding an info obj for the player. + + m_profileCard = new SpriteObj("TitleProfileCard_Sprite"); + m_profileCard.OutlineWidth = 2; + m_profileCard.Scale = new Vector2(2, 2); + m_profileCard.Position = new Vector2(m_profileCard.Width, 720 - m_profileCard.Height); + m_profileCard.ForceDraw = true; + + m_optionsIcon = new SpriteObj("TitleOptionsIcon_Sprite"); + m_optionsIcon.Scale = new Vector2(2, 2); + m_optionsIcon.OutlineWidth = m_profileCard.OutlineWidth; + m_optionsIcon.Position = new Vector2(1320 - m_optionsIcon.Width * 2 + 120, m_profileCard.Y); + m_optionsIcon.ForceDraw = true; + + m_profileCardKey = new KeyIconTextObj(Game.JunicodeFont); + m_profileCardKey.Align = Types.TextAlign.Centre; + m_profileCardKey.FontSize = 12; + m_profileCardKey.Text = "[Input:" + InputMapType.MENU_PROFILECARD + "]"; + m_profileCardKey.Position = new Vector2(m_profileCard.X, m_profileCard.Bounds.Top - m_profileCardKey.Height - 10); + m_profileCardKey.ForceDraw = true; + + m_optionsKey = new KeyIconTextObj(Game.JunicodeFont); + m_optionsKey.Align = Types.TextAlign.Centre; + m_optionsKey.FontSize = 12; + m_optionsKey.Text = "[Input:" + InputMapType.MENU_OPTIONS + "]"; + m_optionsKey.Position = new Vector2(m_optionsIcon.X, m_optionsIcon.Bounds.Top - m_optionsKey.Height - 10); + m_optionsKey.ForceDraw = true; + + base.LoadContent(); + } + + public override void OnEnter() + { + m_classDebugCounter = 0; + UpdatePauseScreenIcons(); + + m_inputDelay = 0.5f; + + if (SoundManager.IsMusicPlaying) + SoundManager.PauseMusic(); + + SoundManager.PlaySound("Pause_Toggle"); + + ProceduralLevelScreen level = (ScreenManager as RCScreenManager).GetLevelScreen(); + + foreach (PauseInfoObj infoObj in m_infoObjList) + { + infoObj.Reset(); + infoObj.Visible = false; + } + + PlayerObj player = (ScreenManager as RCScreenManager).Player; + PauseInfoObj playerInfo = m_infoObjList[0]; + playerInfo.Visible = true; + + playerInfo.AddItem("LOC_ID_PAUSE_SCREEN_1", ClassType.ToStringID(Game.PlayerStats.Class, Game.PlayerStats.IsFemale), true); + playerInfo.AddItem("LOC_ID_PAUSE_SCREEN_2", player.Damage.ToString()); + playerInfo.AddItem("LOC_ID_PAUSE_SCREEN_3", player.TotalMagicDamage.ToString()); + playerInfo.AddItem("LOC_ID_PAUSE_SCREEN_4", player.TotalArmor.ToString()); + playerInfo.ResizePlate(); + + playerInfo.X = player.X - Camera.TopLeftCorner.X; + playerInfo.Y = player.Bounds.Bottom - Camera.TopLeftCorner.Y + playerInfo.Height / 2f - 20; + + if (Game.PlayerStats.TutorialComplete == false) + playerInfo.SetName("LOC_ID_PAUSE_SCREEN_8", true); // ????? (no name yet) + else + playerInfo.SetName(Game.NameHelper()); + playerInfo.SetNamePosition(new Vector2(playerInfo.X, player.Bounds.Top - Camera.TopLeftCorner.Y - 40)); + + playerInfo.Visible = player.Visible; + + // Adding more pause info objs to the screen if the current room has more enemies than the previous one. + int infoObjListCount = m_infoObjList.Count - 1; + //for (int i = infoObjListCount; i < level.CurrentRoom.EnemyList.Count; i++) + for (int i = infoObjListCount; i < level.CurrentRoom.EnemyList.Count + level.CurrentRoom.TempEnemyList.Count; i++) + m_infoObjList.Add(new PauseInfoObj() { Visible = false }); + + for (int i = 1; i < level.CurrentRoom.EnemyList.Count + 1; i++) // +1 because the first infoObjList object is the player's data. + { + EnemyObj enemy = level.CurrentRoom.EnemyList[i - 1]; + + if (enemy.NonKillable == false && enemy.IsKilled == false && enemy.Visible == true) + { + PauseInfoObj enemyInfo = m_infoObjList[i]; + enemyInfo.Visible = true; + //enemyInfo.AddItem("Name: ", enemy.Name); + if (LevelEV.CREATE_RETAIL_VERSION == false) + enemyInfo.AddItem("LOC_ID_PAUSE_SCREEN_5", enemy.Level.ToString()); + else + enemyInfo.AddItem("LOC_ID_PAUSE_SCREEN_5", ((int)(enemy.Level * LevelEV.ENEMY_LEVEL_FAKE_MULTIPLIER)).ToString()); + enemyInfo.AddItem("LOC_ID_PAUSE_SCREEN_2", enemy.Damage.ToString()); + enemyInfo.AddItem("LOC_ID_PAUSE_SCREEN_6", enemy.CurrentHealth + "/" + enemy.MaxHealth); + enemyInfo.ResizePlate(); + + enemyInfo.X = enemy.X - Camera.TopLeftCorner.X; + enemyInfo.Y = enemy.Bounds.Bottom - Camera.TopLeftCorner.Y + enemyInfo.Height / 2f - 20; + + enemyInfo.SetName(enemy.LocStringID, true); + enemyInfo.SetNamePosition(new Vector2(enemyInfo.X, enemy.Bounds.Top - Camera.TopLeftCorner.Y - 40)); + } + } + + int tempEnemyIndex = level.CurrentRoom.EnemyList.Count; + for (int i = 0; i < level.CurrentRoom.TempEnemyList.Count; i++) + { + EnemyObj enemy = level.CurrentRoom.TempEnemyList[i]; + + if (enemy.NonKillable == false && enemy.IsKilled == false) + { + PauseInfoObj enemyInfo = m_infoObjList[i + 1 + tempEnemyIndex]; + enemyInfo.Visible = true; + //enemyInfo.AddItem("Name: ", enemy.Name); + if (LevelEV.CREATE_RETAIL_VERSION == false) + enemyInfo.AddItem("LOC_ID_PAUSE_SCREEN_5", enemy.Level.ToString()); + else + enemyInfo.AddItem("LOC_ID_PAUSE_SCREEN_5", ((int)(enemy.Level * LevelEV.ENEMY_LEVEL_FAKE_MULTIPLIER)).ToString()); + enemyInfo.AddItem("LOC_ID_PAUSE_SCREEN_2", enemy.Damage.ToString()); + enemyInfo.AddItem("LOC_ID_PAUSE_SCREEN_6", enemy.CurrentHealth + "/" + enemy.MaxHealth); + enemyInfo.ResizePlate(); + + enemyInfo.X = enemy.X - Camera.TopLeftCorner.X; + enemyInfo.Y = enemy.Bounds.Bottom - Camera.TopLeftCorner.Y + enemyInfo.Height / 2f - 20; + + enemyInfo.SetName(enemy.LocStringID, true); + enemyInfo.SetNamePosition(new Vector2(enemyInfo.X, enemy.Bounds.Top - Camera.TopLeftCorner.Y - 40)); + } + } + + Game.ChangeBitmapLanguage(m_titleText, "GamePausedTitleText_Sprite"); + base.OnEnter(); + } + + public void UpdatePauseScreenIcons() + { + m_profileCardKey.Text = "[Input:" + InputMapType.MENU_PROFILECARD + "]"; + m_optionsKey.Text = "[Input:" + InputMapType.MENU_OPTIONS + "]"; + } + + public override void OnExit() + { + if (SoundManager.IsMusicPaused) + SoundManager.ResumeMusic(); + + SoundManager.PlaySound("Resume_Toggle"); + + foreach (PauseInfoObj obj in m_infoObjList) + obj.Visible = false; + base.OnExit(); + } + + public override void HandleInput() + { + if (m_inputDelay <= 0) + { + if (Game.GlobalInput.JustPressed(InputMapType.MENU_PROFILECARD) && Game.PlayerStats.TutorialComplete == true) // this needs to be unified. + (this.ScreenManager as RCScreenManager).DisplayScreen(ScreenType.ProfileCard, true, null); + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_OPTIONS)) + { + List optionsData = new List(); + optionsData.Add(false); + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Options, false, optionsData); + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_PAUSE)) + { + (ScreenManager as RCScreenManager).GetLevelScreen().UnpauseScreen(); + (ScreenManager as RCScreenManager).HideCurrentScreen(); + } + + if (LevelEV.ENABLE_DEBUG_INPUT == true) + HandleDebugInput(); + + base.HandleInput(); + } + } + + private sbyte m_classDebugCounter = 0; + private void HandleDebugInput() + { + sbyte currentDebugClass = (sbyte)(Game.PlayerStats.Class + m_classDebugCounter); + sbyte previousDebugClass = currentDebugClass; + + if (InputManager.JustPressed(Keys.OemOpenBrackets, PlayerIndex.One)) + { + if (currentDebugClass == ClassType.Knight) + m_classDebugCounter = (sbyte)(ClassType.Traitor - Game.PlayerStats.Class); + else + m_classDebugCounter--; + + currentDebugClass = (sbyte)(Game.PlayerStats.Class + m_classDebugCounter); + } + else if (InputManager.JustPressed(Keys.OemCloseBrackets, PlayerIndex.One)) + { + if (currentDebugClass == ClassType.Traitor) + m_classDebugCounter = (sbyte)(-Game.PlayerStats.Class); + else + m_classDebugCounter++; + currentDebugClass = (sbyte)(Game.PlayerStats.Class + m_classDebugCounter); + } + + if (currentDebugClass != previousDebugClass) + { + PlayerObj player = (ScreenManager as RCScreenManager).Player; + PauseInfoObj playerInfo = m_infoObjList[0]; + playerInfo.Visible = true; + (playerInfo.GetChildAt(2) as TextObj).Text = LocaleBuilder.getString(ClassType.ToStringID((byte)currentDebugClass, Game.PlayerStats.IsFemale), (playerInfo.GetChildAt(2) as TextObj)); + playerInfo.ResizePlate(); + + playerInfo.X = player.X - Camera.TopLeftCorner.X; + playerInfo.Y = player.Bounds.Bottom - Camera.TopLeftCorner.Y + playerInfo.Height / 2f - 20; + //playerInfo.SetNamePosition(new Vector2(playerInfo.X, player.Bounds.Top - Camera.TopLeftCorner.Y - 40)); + } + } + + public override void Update(GameTime gameTime) + { + if (m_inputDelay > 0) + m_inputDelay -= (float)gameTime.ElapsedGameTime.TotalSeconds; + base.Update(gameTime); + } + + public override void Draw(GameTime gameTime) + { + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null); // Anything that is affected by the godray should be drawn here. + m_titleText.Draw(Camera); + foreach (PauseInfoObj infoObj in m_infoObjList) + infoObj.Draw(Camera); + + if (Game.PlayerStats.TutorialComplete == true) + m_profileCardKey.Draw(Camera); + + m_optionsKey.Draw(Camera); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + m_optionsIcon.Draw(Camera); + + if (Game.PlayerStats.TutorialComplete == true) + m_profileCard.Draw(Camera); + + Camera.End(); + base.Draw(gameTime); + } + + public override void RefreshTextObjs() + { + Game.ChangeBitmapLanguage(m_titleText, "GamePausedTitleText_Sprite"); + + PauseInfoObj playerInfo = m_infoObjList[0]; + if (Game.PlayerStats.TutorialComplete == false) + playerInfo.SetName("LOC_ID_PAUSE_SCREEN_8", true); // ????? (no name yet) + else + playerInfo.SetName(Game.NameHelper()); + + foreach (PauseInfoObj infoObj in m_infoObjList) + { + if (infoObj.Visible == true) + infoObj.ResizePlate(); + } + + base.RefreshTextObjs(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Pause Screen"); + + foreach (PauseInfoObj obj in m_infoObjList) + obj.Dispose(); + m_infoObjList.Clear(); + m_infoObjList = null; + + m_titleText.Dispose(); + m_titleText = null; + + m_profileCard.Dispose(); + m_profileCard = null; + m_optionsIcon.Dispose(); + m_optionsIcon = null; + + m_profileCardKey.Dispose(); + m_profileCardKey = null; + m_optionsKey.Dispose(); + m_optionsKey = null; + base.Dispose(); + } + } + + private class PauseInfoObj : ObjContainer + { + private List m_textList; // The title for the text + private List m_textDataList; // The data for the text + + private int m_arrayIndex = 0; + + private ObjContainer m_namePlate; + private TextObj m_name; + + public PauseInfoObj() + : base("GameOverStatPlate_Character") + { + this.ForceDraw = true; + m_textList = new List(); + m_textDataList = new List(); + + m_namePlate = new ObjContainer("DialogBox_Character"); + m_namePlate.ForceDraw = true; + + m_name = new TextObj(Game.JunicodeFont); + m_name.Align = Types.TextAlign.Centre; + m_name.Text = ""; + m_name.FontSize = 8; + m_name.Y -= 45; + m_name.OverrideParentScale = true; + m_name.DropShadow = new Vector2(2, 2); + m_namePlate.AddChild(m_name); + } + + public void SetName(string name, bool isLocalized = false) + { + if (isLocalized) + { + try + { + m_name.ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_name)); + m_name.Text = LocaleBuilder.getString(name, m_name); + if (LocaleBuilder.languageType != LanguageType.Chinese_Simp && Regex.IsMatch(m_name.Text, @"\p{IsCyrillic}")) + m_name.ChangeFontNoDefault(Game.RobotoSlabFont); + } + catch + { + m_name.ChangeFontNoDefault(Game.NotoSansSCFont); + m_name.Text = LocaleBuilder.getString(name, m_name); + } + } + else + { + try + { + m_name.ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_name)); + m_name.Text = name; + if (LocaleBuilder.languageType != LanguageType.Chinese_Simp && Regex.IsMatch(m_name.Text, @"\p{IsCyrillic}")) + m_name.ChangeFontNoDefault(Game.RobotoSlabFont); + } + catch + { + m_name.ChangeFontNoDefault(Game.NotoSansSCFont); + m_name.Text = name; + } + } + m_namePlate.Scale = Vector2.One; + m_namePlate.Scale = new Vector2((m_name.Width + 70f) / m_namePlate.Width, (m_name.Height + 20f) / m_namePlate.Height); + } + + public void SetNamePosition(Vector2 pos) + { + m_namePlate.Position = pos; + } + + public void AddItem(string title, string data, bool localizedData = false) + { + TextObj titleText; + if (m_textList.Count <= m_arrayIndex) + titleText = new TextObj(Game.JunicodeFont); + else + titleText = m_textList[m_arrayIndex]; + + titleText.FontSize = 8; + titleText.Text = LocaleBuilder.getString(title, titleText); + titleText.Align = Types.TextAlign.Right; + titleText.Y = _objectList[0].Bounds.Top + titleText.Height + (m_arrayIndex * 20); + titleText.DropShadow = new Vector2(2,2); + if (m_textList.Count <= m_arrayIndex) + { + this.AddChild(titleText); + m_textList.Add(titleText); + } + + TextObj dataText; + if (m_textDataList.Count <= m_arrayIndex) + dataText = new TextObj(Game.JunicodeFont); + else + dataText = m_textDataList[m_arrayIndex]; + dataText.FontSize = 8; + if (localizedData) + dataText.Text = LocaleBuilder.getString(data, dataText); + else + dataText.Text = data; + dataText.Y = titleText.Y; + dataText.DropShadow = new Vector2(2, 2); + if (m_textDataList.Count <= m_arrayIndex) + { + this.AddChild(dataText); + m_textDataList.Add(dataText); + } + + m_arrayIndex++; + } + + // Should be called once all items have been added. + public void ResizePlate() + { + _objectList[0].ScaleY = 1; + _objectList[0].ScaleY = (float)(_objectList[1].Height * (_objectList.Count + 1)/2) / (float)_objectList[0].Height; + + int longestTitle = 0; + foreach (TextObj obj in m_textList) + { + if (obj.Width > longestTitle) + longestTitle = obj.Width; + } + + int longestData = 0; + foreach (TextObj obj in m_textDataList) + { + if (obj.Width > longestData) + longestData = obj.Width; + } + + _objectList[0].ScaleX = 1; + _objectList[0].ScaleX = (float)(longestTitle + longestData + 50) / (float)_objectList[0].Width; + + int newTitleXPos = (int)(-(_objectList[0].Width / 2f) + longestTitle) + 25; + int newTitleYPos = (int)(_objectList[0].Height / (m_textList.Count + 2)); + + for (int i = 0; i < m_textList.Count; i++) + { + m_textList[i].X = newTitleXPos; + m_textList[i].Y = _objectList[0].Bounds.Top + newTitleYPos + (newTitleYPos * i); + + m_textDataList[i].X = newTitleXPos; + m_textDataList[i].Y = m_textList[i].Y; + } + } + + public override void Draw(Camera2D camera) + { + if (this.Visible == true) + { + m_namePlate.Draw(camera); + m_name.Draw(camera); + } + base.Draw(camera); + } + + public void Reset() + { + foreach (TextObj obj in m_textList) + obj.Text = ""; + + foreach (TextObj obj in m_textDataList) + obj.Text = ""; + + m_arrayIndex = 0; + } + + public override void Dispose() + { + if (IsDisposed == false) + { + m_textList.Clear(); + m_textList = null; + + m_textDataList.Clear(); + m_textDataList = null; + + m_namePlate.Dispose(); + m_namePlate = null; + m_name = null; + base.Dispose(); + } + } + } + } +} diff --git a/RogueCastle/src/Screens/ProceduralLevelScreen.cs b/RogueCastle/src/Screens/ProceduralLevelScreen.cs new file mode 100644 index 0000000..b595c6a --- /dev/null +++ b/RogueCastle/src/Screens/ProceduralLevelScreen.cs @@ -0,0 +1,3362 @@ +//#define OLD_CONSOLE_CREDITS +//#define SWITCH_CREDITS + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using SpriteSystem; +using Microsoft.Xna.Framework.Graphics; +using InputSystem; +using Microsoft.Xna.Framework.Input; +using Tweener; +using Tweener.Ease; + +namespace RogueCastle +{ + public class ProceduralLevelScreen : Screen + { + private List m_roomList; // Make sure to dispose this list. Even though rooms are taken from LevelBuilder, clones are made so that the level builder collection is not modified. + private PlayerObj m_player; + + protected int m_leftMostBorder = int.MaxValue; + protected int m_rightMostBorder = -int.MaxValue; + protected int m_topMostBorder = int.MaxValue; + protected int m_bottomMostBorder = -int.MaxValue; + + protected int LeftDoorPercent = 80; + protected int RightDoorPercent = 80; + protected int TopDoorPercent = 80; + protected int BottomDoorPercent = 80; + + protected TextManager m_textManager; + protected PhysicsManager m_physicsManager; + protected ProjectileManager m_projectileManager; + protected ItemDropManager m_itemDropManager; + + protected RoomObj m_currentRoom; + protected MapObj m_miniMapDisplay; + private SpriteObj m_mapBG; + + private InputMap m_inputMap; + private const byte INPUT_TOGGLEMAP = 0; + private const byte INPUT_TOGGLEZOOM = 1; + private const byte INPUT_LEFTCONTROL = 2; + private const byte INPUT_LEFT = 3; + private const byte INPUT_RIGHT = 4; + private const byte INPUT_UP = 5; + private const byte INPUT_DOWN = 6; + private const byte INPUT_DISPLAYROOMINFO = 7; + + private List m_enemyStartPositions; + private List m_tempEnemyStartPositions; + + private PlayerHUDObj m_playerHUD; + + private EnemyHUDObj m_enemyHUD; + private EnemyObj m_lastEnemyHit; + private float m_enemyHUDDuration = 2.0f; + private float m_enemyHUDCounter = 0; + + /// Death Animation Variables /// + public float BackBufferOpacity { get; set; } + + private List m_killedEnemyObjList; + private int m_coinsCollected = 0; + private int m_bagsCollected = 0; + private int m_diamondsCollected = 0; + private int m_blueprintsCollected = 0; + private int m_bigDiamondsCollected = 0; + + private GameObj m_objKilledPlayer; + private RenderTarget2D m_roomBWRenderTarget; // A special render target that is created so that rooms can draw their backgrounds. + // Created in level instead of having each room create their own, to save massive VRAM. + + // Effects for dynamic lighting //// + SpriteObj m_dungeonLight; + SpriteObj m_traitAura; + + //////////////////////////////////// + + ImpactEffectPool m_impactEffectPool; + + private TextObj m_roomTitle; + private TextObj m_roomEnteringTitle; + public bool CameraLockedToPlayer { get; set; } + + // Black borders for cinematic scenes. + private SpriteObj m_blackBorder1; + private SpriteObj m_blackBorder2; + private int m_borderSize; + + private List m_chestList; + public bool LoadGameData = false; + private ProjectileIconPool m_projectileIconPool; + + // Code needed for spells + private float m_enemyPauseDuration = 0; + private bool m_enemiesPaused = false; + + public float ShoutMagnitude { get; set; } + + // Code for objective plate. + private ObjContainer m_objectivePlate; + private TweenObject m_objectivePlateTween; + + public SkyObj m_sky; + private SpriteObj m_whiteBG; + + public bool DisableRoomOnEnter { get; set; } // Sometimes I need to currentRoom.OnEnter(). + + // Variables for the credits that appear in the beginning. + private TextObj m_creditsText; + private TextObj m_creditsTitleText; + private string[] m_creditsTextList; + private string[] m_creditsTextTitleList; + private int m_creditsIndex = 0; + private SpriteObj m_filmGrain; + + // Variables for the compass. + private SpriteObj m_compassBG; + private SpriteObj m_compass; + private DoorObj m_compassDoor; + private bool m_compassDisplayed = false; + + public bool DisableSongUpdating { get; set; } + public bool DisableRoomTransitioning { get; set; } + + public TextObj DebugTextObj; + + public bool JukeboxEnabled { get; set; } + + private float m_elapsedScreenShake = 0; + + public ProceduralLevelScreen() + { + DisableRoomTransitioning = false; + m_roomList = new List(); + m_textManager = new TextManager(700); //200 TEDDY RAISING POOL TO 500 + m_projectileManager = new ProjectileManager(this, 700); + m_enemyStartPositions = new List(); + m_tempEnemyStartPositions = new List(); + + m_impactEffectPool = new ImpactEffectPool(2000); + CameraLockedToPlayer = true; + + m_roomTitle = new TextObj(); + m_roomTitle.Font = Game.JunicodeLargeFont; + //m_roomTitle.Align = Types.TextAlign.Centre; + m_roomTitle.Align = Types.TextAlign.Right; + m_roomTitle.Opacity = 0; + m_roomTitle.FontSize = 40; + m_roomTitle.Position = new Vector2(1320 - 50, 720 - 150); + //m_roomTitle.Position = new Vector2(1320 / 2, 720 / 2 - 150); + m_roomTitle.OutlineWidth = 2; + //m_roomTitle.DropShadow = new Vector2(4, 4); + + m_roomEnteringTitle = m_roomTitle.Clone() as TextObj; + m_roomEnteringTitle.Text = LocaleBuilder.getString("LOC_ID_LEVEL_SCREEN_1", m_roomEnteringTitle); //"Now Entering" + m_roomEnteringTitle.FontSize = 24; + m_roomEnteringTitle.Y -= 50; + + m_inputMap = new InputMap(PlayerIndex.One, false); + m_inputMap.AddInput(INPUT_TOGGLEMAP, Keys.Y); + m_inputMap.AddInput(INPUT_TOGGLEZOOM, Keys.U); + m_inputMap.AddInput(INPUT_LEFTCONTROL, Keys.LeftControl); + m_inputMap.AddInput(INPUT_LEFT, Keys.Left); + m_inputMap.AddInput(INPUT_RIGHT, Keys.Right); + m_inputMap.AddInput(INPUT_UP, Keys.Up); + m_inputMap.AddInput(INPUT_DOWN, Keys.Down); + m_inputMap.AddInput(INPUT_DISPLAYROOMINFO, Keys.OemTilde); + + m_chestList = new List(); + m_miniMapDisplay = new MapObj(true, this); // Must be called before CheckForRoomTransition() since rooms are added to the map during that call. + + m_killedEnemyObjList = new List(); + } + + public override void LoadContent() + { + DebugTextObj = new TextObj(Game.JunicodeFont); + DebugTextObj.FontSize = 26; + DebugTextObj.Align = Types.TextAlign.Centre; + DebugTextObj.Text = ""; + DebugTextObj.ForceDraw = true; + + m_projectileIconPool = new ProjectileIconPool(200, m_projectileManager, ScreenManager as RCScreenManager); + m_projectileIconPool.Initialize(); + + m_textManager.Initialize(); + + m_impactEffectPool.Initialize(); + + m_physicsManager = (ScreenManager.Game as Game).PhysicsManager; + m_physicsManager.SetGravity(0, -GlobalEV.GRAVITY); + + m_projectileManager.Initialize(); + m_physicsManager.Initialize(ScreenManager.Camera); + + m_itemDropManager = new ItemDropManager(600, m_physicsManager); + m_itemDropManager.Initialize(); + + m_playerHUD = new PlayerHUDObj(); + m_playerHUD.SetPosition(new Vector2(20, 40)); + + m_enemyHUD = new EnemyHUDObj(); + m_enemyHUD.Position = new Vector2(GlobalEV.ScreenWidth / 2 - m_enemyHUD.Width / 2, 20); + + m_miniMapDisplay.SetPlayer(m_player); + m_miniMapDisplay.InitializeAlphaMap(new Rectangle(1320 - 250, 50, 200, 100), Camera); + + InitializeAllRooms(true); // Required to initialize all the render targets for each room. Must be called before InitializeEnemies/Chests() so that the room's level is set. + InitializeEnemies(); + InitializeChests(true); + InitializeRenderTargets(); + + m_mapBG = new SpriteObj("MinimapBG_Sprite"); + m_mapBG.Position = new Vector2(1320 - 250, 50); + m_mapBG.ForceDraw = true; + + UpdateCamera(); + + m_borderSize = 100; + m_blackBorder1 = new SpriteObj("Blank_Sprite"); + m_blackBorder1.TextureColor = Color.Black; + m_blackBorder1.Scale = new Vector2(1340f / m_blackBorder1.Width, m_borderSize/m_blackBorder1.Height); + m_blackBorder2 = new SpriteObj("Blank_Sprite"); + m_blackBorder2.TextureColor = Color.Black; + m_blackBorder2.Scale = new Vector2(1340f / m_blackBorder2.Width, m_borderSize / m_blackBorder2.Height); + m_blackBorder1.ForceDraw = true; + m_blackBorder2.ForceDraw = true; + m_blackBorder1.Y = -m_borderSize; + m_blackBorder2.Y = 720; + + m_dungeonLight = new SpriteObj("LightSource_Sprite"); + m_dungeonLight.ForceDraw = true; + m_dungeonLight.Scale = new Vector2(12, 12); + m_traitAura = new SpriteObj("LightSource_Sprite"); + m_traitAura.ForceDraw = true; + + // Objective plate + m_objectivePlate = new ObjContainer("DialogBox_Character"); + m_objectivePlate.ForceDraw = true; + TextObj objTitle = new TextObj(Game.JunicodeFont); + objTitle.Position = new Vector2(-400, -60); + objTitle.OverrideParentScale = true; + objTitle.FontSize = 10; + objTitle.Text = LocaleBuilder.getString("LOC_ID_LEVEL_SCREEN_2", objTitle); //"Fairy Chest Objective:" + objTitle.TextureColor = Color.Red; + objTitle.OutlineWidth = 2; + m_objectivePlate.AddChild(objTitle); + + TextObj objDescription = new TextObj(Game.JunicodeFont); + objDescription.OverrideParentScale = true; + objDescription.Position = new Vector2(objTitle.X, objTitle.Y + 40); + objDescription.ForceDraw = true; + objDescription.FontSize = 9; + objDescription.Text = LocaleBuilder.getString("LOC_ID_LEVEL_SCREEN_3", objDescription); //"Reach the chest in 15 seconds:" + objDescription.WordWrap(250); + objDescription.OutlineWidth = 2; + m_objectivePlate.AddChild(objDescription); + + TextObj objProgress = new TextObj(Game.JunicodeFont); + objProgress.OverrideParentScale = true; + objProgress.Position = new Vector2(objDescription.X, objDescription.Y + 35); + objProgress.ForceDraw = true; + objProgress.FontSize = 9; + objProgress.Text = LocaleBuilder.getString("LOC_ID_LEVEL_SCREEN_4", objProgress); //"Time Remaining:" + objProgress.WordWrap(250); + objProgress.OutlineWidth = 2; + m_objectivePlate.AddChild(objProgress); + + m_objectivePlate.Scale = new Vector2(250f / m_objectivePlate.GetChildAt(0).Width, 130f / m_objectivePlate.GetChildAt(0).Height); + m_objectivePlate.Position = new Vector2(1170 + 300, 250); + + SpriteObj objectiveLine1 = new SpriteObj("Blank_Sprite"); + objectiveLine1.TextureColor = Color.Red; + objectiveLine1.Position = new Vector2(objDescription.X, objDescription.Y + 20); + objectiveLine1.ForceDraw = true; + objectiveLine1.OverrideParentScale = true; + objectiveLine1.ScaleY = 0.5f; + m_objectivePlate.AddChild(objectiveLine1); + + SpriteObj objectiveLine2 = new SpriteObj("Blank_Sprite"); + objectiveLine2.TextureColor = Color.Red; + objectiveLine2.Position = new Vector2(objDescription.X, objectiveLine1.Y + 35); + objectiveLine2.ForceDraw = true; + objectiveLine2.OverrideParentScale = true; + objectiveLine2.ScaleY = 0.5f; + m_objectivePlate.AddChild(objectiveLine2); + base.LoadContent(); // Doesn't do anything. + + m_sky = new SkyObj(this); + m_sky.LoadContent(Camera); + + m_whiteBG = new SpriteObj("Blank_Sprite"); + m_whiteBG.Opacity = 0; + m_whiteBG.Scale = new Vector2(1320f / m_whiteBG.Width, 720f/m_whiteBG.Height); + + m_filmGrain = new SpriteObj("FilmGrain_Sprite"); + m_filmGrain.ForceDraw = true; + m_filmGrain.Scale = new Vector2(2.015f, 2.05f); + m_filmGrain.X -= 5; + m_filmGrain.Y -= 5; + m_filmGrain.PlayAnimation(true); + m_filmGrain.AnimationDelay = 1 / 30f; + + m_compassBG = new SpriteObj("CompassBG_Sprite"); + m_compassBG.ForceDraw = true; + m_compassBG.Position = new Vector2(1320 / 2f, 90); + m_compassBG.Scale = Vector2.Zero; + m_compass = new SpriteObj("Compass_Sprite"); + m_compass.Position = m_compassBG.Position; + m_compass.ForceDraw = true; + m_compass.Scale = Vector2.Zero; + + InitializeCreditsText(); + } + + private void InitializeCreditsText() + { + m_creditsTextTitleList = new string[] + { + "LOC_ID_TUTORIAL_CREDITS_TITLE_1", + "LOC_ID_TUTORIAL_CREDITS_TITLE_2", + "LOC_ID_TUTORIAL_CREDITS_TITLE_3", + "LOC_ID_TUTORIAL_CREDITS_TITLE_4", + "LOC_ID_TUTORIAL_CREDITS_TITLE_5", + "LOC_ID_TUTORIAL_CREDITS_TITLE_6", + "LOC_ID_TUTORIAL_CREDITS_TITLE_7", +#if OLD_CONSOLE_CREDITS || SWITCH_CREDITS + "LOC_ID_CREDITS_SCREEN_26", + //"Japanese Localization & Production By", // This is not translated +#endif + "LOC_ID_TUTORIAL_CREDITS_TITLE_8" + }; + + m_creditsTextList = new string[] + { + "Cellar Door Games", + "Teddy Lee", + "Kenny Lee", +#if SWITCH_CREDITS + "Ryan Lee", +#else + "Marie-Christine Bourdua", +#endif + "Glauber Kotaki", + "Gordon McGladdery", + "Judson Cowan", +#if OLD_CONSOLE_CREDITS + "Abstraction Games", + //"8-4, Ltd.", // The Japanese Localization text above needs to be translated before this can be uncommented out. +#endif +#if SWITCH_CREDITS + "BlitWorks SL", +#endif + "Rogue Legacy", + }; + + m_creditsText = new TextObj(Game.JunicodeFont); + m_creditsText.FontSize = 20; + m_creditsText.Text = "Cellar Door Games"; + m_creditsText.DropShadow = new Vector2(2, 2); + m_creditsText.Opacity = 0; + + m_creditsTitleText = m_creditsText.Clone() as TextObj; + m_creditsTitleText.FontSize = 14; + m_creditsTitleText.Position = new Vector2(50, 580); + + m_creditsText.Position = m_creditsTitleText.Position; + m_creditsText.Y += 35; + m_creditsTitleText.X += 5; + } + + public void DisplayCreditsText(bool resetIndex) + { + if (resetIndex == true) + m_creditsIndex = 0; + + m_creditsTitleText.Opacity = 0; + m_creditsText.Opacity = 0; + + if (m_creditsIndex < m_creditsTextList.Length) + { + m_creditsTitleText.Opacity = 0; + m_creditsText.Opacity = 0; + + m_creditsTitleText.Text = LocaleBuilder.getString(m_creditsTextTitleList[m_creditsIndex], m_creditsTitleText); + m_creditsText.Text = m_creditsTextList[m_creditsIndex]; + + // Tween text in. + Tween.To(m_creditsTitleText, 0.5f, Tween.EaseNone, "Opacity", "1"); + Tween.To(m_creditsText, 0.5f, Tween.EaseNone, "delay", "0.2", "Opacity", "1"); + m_creditsTitleText.Opacity = 1; + m_creditsText.Opacity = 1; + + // Tween text out. + Tween.To(m_creditsTitleText, 0.5f, Tween.EaseNone, "delay", "4", "Opacity", "0"); + Tween.To(m_creditsText, 0.5f, Tween.EaseNone, "delay", "4.2", "Opacity", "0"); + m_creditsTitleText.Opacity = 0; + m_creditsText.Opacity = 0; + + m_creditsIndex++; + Tween.RunFunction(8, this, "DisplayCreditsText", false); + } + } + + public void StopCreditsText() + { + m_creditsIndex = 0; + Tween.StopAllContaining(m_creditsTitleText, false); + Tween.StopAllContaining(m_creditsText, false); + Tween.StopAllContaining(this, false); + m_creditsTitleText.Opacity = 0; + } + + public override void ReinitializeRTs() + { + m_sky.ReinitializeRT(Camera); + m_miniMapDisplay.InitializeAlphaMap(new Rectangle(1320 - 250, 50, 200, 100), Camera); + InitializeRenderTargets(); + InitializeAllRooms(false); + + if (CurrentRoom == null || CurrentRoom.Name != "Start") + { + if (CurrentRoom.Name == "ChallengeBoss") + { + //m_foregroundSprite.TextureColor = Color.Black; + //m_backgroundSprite.TextureColor = Color.Black; + m_backgroundSprite.Scale = Vector2.One; + m_backgroundSprite.ChangeSprite("NeoBG_Sprite", ScreenManager.Camera); + m_backgroundSprite.Scale = new Vector2(2, 2); + + m_foregroundSprite.Scale = Vector2.One; + m_foregroundSprite.ChangeSprite("NeoFG_Sprite", ScreenManager.Camera); + m_foregroundSprite.Scale = new Vector2(2, 2); + } + else + { + switch (CurrentRoom.LevelType) + { + case (GameTypes.LevelType.CASTLE): + m_backgroundSprite.Scale = Vector2.One; + m_foregroundSprite.Scale = Vector2.One; + m_backgroundSprite.ChangeSprite("CastleBG1_Sprite", ScreenManager.Camera); + m_foregroundSprite.ChangeSprite("CastleFG1_Sprite", ScreenManager.Camera); + m_backgroundSprite.Scale = new Vector2(2, 2); + m_foregroundSprite.Scale = new Vector2(2, 2); + break; + case (GameTypes.LevelType.TOWER): + m_backgroundSprite.Scale = Vector2.One; + m_foregroundSprite.Scale = Vector2.One; + m_backgroundSprite.ChangeSprite("TowerBG2_Sprite", ScreenManager.Camera); + m_foregroundSprite.ChangeSprite("TowerFG2_Sprite", ScreenManager.Camera); + m_backgroundSprite.Scale = new Vector2(2, 2); + m_foregroundSprite.Scale = new Vector2(2, 2); + break; + case (GameTypes.LevelType.DUNGEON): + m_backgroundSprite.Scale = Vector2.One; + m_foregroundSprite.Scale = Vector2.One; + m_backgroundSprite.ChangeSprite("DungeonBG1_Sprite", ScreenManager.Camera); + m_foregroundSprite.ChangeSprite("DungeonFG1_Sprite", ScreenManager.Camera); + m_backgroundSprite.Scale = new Vector2(2, 2); + m_foregroundSprite.Scale = new Vector2(2, 2); + break; + case (GameTypes.LevelType.GARDEN): + m_backgroundSprite.Scale = Vector2.One; + m_foregroundSprite.Scale = Vector2.One; + m_backgroundSprite.ChangeSprite("GardenBG_Sprite", ScreenManager.Camera); + m_foregroundSprite.ChangeSprite("GardenFG_Sprite", ScreenManager.Camera); + m_backgroundSprite.Scale = new Vector2(2, 2); + m_foregroundSprite.Scale = new Vector2(2, 2); + break; + } + } + + if (Game.PlayerStats.Traits.X == TraitType.TheOne || Game.PlayerStats.Traits.Y == TraitType.TheOne) + { + m_foregroundSprite.Scale = Vector2.One; + m_foregroundSprite.ChangeSprite("NeoFG_Sprite", ScreenManager.Camera); + m_foregroundSprite.Scale = new Vector2(2, 2); + } + } + + m_backgroundSprite.Position = CurrentRoom.Position; + m_foregroundSprite.Position = CurrentRoom.Position; + + base.ReinitializeRTs(); + } + + // Removes the previous room's objects from the physics manager and adds the new room's objects. + // Not performance heavy because removing and adding objects to physics manager is O(1), with the exception of Clear(), which is O(n). + private void LoadPhysicsObjects(RoomObj room) + { + Rectangle expandedRoomRect = new Rectangle((int)room.X - 100, (int)room.Y - 100, room.Width + 200, room.Height + 200); // An expanded bounds of the room. + //m_physicsManager.ObjectList.Clear(); + m_physicsManager.RemoveAllObjects(); + + foreach (TerrainObj obj in CurrentRoom.TerrainObjList) + m_physicsManager.AddObject(obj); + + foreach (ProjectileObj obj in m_projectileManager.ActiveProjectileList) + m_physicsManager.AddObject(obj); + + foreach (GameObj obj in CurrentRoom.GameObjList) + { + IPhysicsObj physicsObj = obj as IPhysicsObj; + if (physicsObj != null && obj.Bounds.Intersects(expandedRoomRect)) // Not sure why we're doing a bounds intersect check. + { + BreakableObj breakable = obj as BreakableObj; + if (breakable != null && breakable.Broken == true) // Don't add broken breakables to the list. + continue; + m_physicsManager.AddObject(physicsObj); + } + } + + // This is needed for entering boss doors. + foreach (DoorObj door in CurrentRoom.DoorList) + m_physicsManager.AddObject(door); + + foreach (EnemyObj enemy in CurrentRoom.EnemyList) + { + m_physicsManager.AddObject(enemy); + + if (enemy is EnemyObj_BallAndChain) // Special handling to add the separate entity ball for the ball and chain dude. + { + if (enemy.IsKilled == false) + { + m_physicsManager.AddObject((enemy as EnemyObj_BallAndChain).BallAndChain); + if (enemy.Difficulty > GameTypes.EnemyDifficulty.BASIC) + m_physicsManager.AddObject((enemy as EnemyObj_BallAndChain).BallAndChain2); + } + } + } + + foreach (EnemyObj enemy in CurrentRoom.TempEnemyList) + m_physicsManager.AddObject(enemy); + + m_physicsManager.AddObject(m_player); + } + + public void InitializeEnemies() + { + //int enemyLevel = 1; + //int enemyDifficulty = (int)GameTypes.EnemyDifficulty.BASIC; + //int levelCounter = 0; + + List terrainCollList = new List(); + + foreach (RoomObj room in m_roomList) + { + foreach (EnemyObj enemy in room.EnemyList) + { + enemy.SetPlayerTarget(m_player); + enemy.SetLevelScreen(this); // Must be called before enemy.Initialize(). + + int roomLevel = room.Level; + // Special handling for boss rooms. + if (room.Name == "Boss" && room.LinkedRoom != null) + { + //int roomLevel = room.LinkedRoom.RoomNumber; + roomLevel = room.LinkedRoom.Level; + int bossEnemyLevel = (int)(roomLevel / (LevelEV.ROOM_LEVEL_MOD + Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.RoomLevelDown) * GameEV.RUNE_GRACE_ROOM_LEVEL_LOSS)); + enemy.Level = bossEnemyLevel; + } + else + { + int enemyLevel = (int)(roomLevel / (LevelEV.ROOM_LEVEL_MOD + Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.RoomLevelDown) * GameEV.RUNE_GRACE_ROOM_LEVEL_LOSS)); + if (enemyLevel < 1) enemyLevel = 1; + enemy.Level = enemyLevel; // Call this before Initialize(), since Initialie sets their starting health and so on. + } + + int enemyDifficulty = (int)(enemy.Level / LevelEV.ENEMY_LEVEL_DIFFICULTY_MOD); + if (enemyDifficulty > (int)GameTypes.EnemyDifficulty.EXPERT) + enemyDifficulty = (int)GameTypes.EnemyDifficulty.EXPERT; + + if (enemy.IsProcedural == true) + { + if (enemy.Difficulty == GameTypes.EnemyDifficulty.EXPERT) + enemy.Level += LevelEV.ENEMY_EXPERT_LEVEL_MOD; + if ((int)enemy.Difficulty < enemyDifficulty) + enemy.SetDifficulty((GameTypes.EnemyDifficulty)enemyDifficulty, false); + } + else + { + if (enemy.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + { + if (room is ArenaBonusRoom) // Level up arena room enemies by expert level instead of miniboss. + enemy.Level += LevelEV.ENEMY_EXPERT_LEVEL_MOD; + else + enemy.Level += LevelEV.ENEMY_MINIBOSS_LEVEL_MOD; + } + } + + //if (enemy.Difficulty == GameTypes.EnemyDifficulty.EXPERT) + // enemy.Level += LevelEV.ENEMY_EXPERT_LEVEL_MOD; // If an enemy is already expert, then he is a yellow orb, and should gain these extra level. + //else if (enemy.Difficulty == GameTypes.EnemyDifficulty.MINIBOSS) + // enemy.Level += LevelEV.ENEMY_MINIBOSS_LEVEL_MOD; // Minibosses gain these extra levels. + //else if (enemy.IsProcedural == true && (int)enemy.Difficulty < enemyDifficulty) // Only change the difficulty of procedural enemies and if they're not yellows and they're lower difficulty. + // enemy.SetDifficulty((GameTypes.EnemyDifficulty)enemyDifficulty, false); + + enemy.Initialize(); + + // Positioning each enemy to the ground closest below them. But don't do it if they fly. + if (enemy.IsWeighted == true) + { + float closestGround = float.MaxValue; + TerrainObj closestTerrain = null; + terrainCollList.Clear(); + Rectangle enemyBoundsRect = new Rectangle((int)enemy.X, (int)enemy.TerrainBounds.Bottom, 1, 5000); + foreach (TerrainObj terrainObj in room.TerrainObjList) + { + if (terrainObj.Rotation == 0) + { + if (terrainObj.Bounds.Top >= enemy.TerrainBounds.Bottom && CollisionMath.Intersects(terrainObj.Bounds, enemyBoundsRect)) + terrainCollList.Add(terrainObj); + } + else + { + if (CollisionMath.RotatedRectIntersects(enemyBoundsRect, 0, Vector2.Zero, terrainObj.TerrainBounds, terrainObj.Rotation, Vector2.Zero)) + terrainCollList.Add(terrainObj); + } + } + + foreach (TerrainObj terrain in terrainCollList) + { + bool collides = false; + int groundDist = 0; + if (terrain.Rotation == 0) + { + collides = true; + groundDist = terrain.TerrainBounds.Top - enemy.TerrainBounds.Bottom; + } + else + { + Vector2 pt1, pt2; + if (terrain.Width > terrain.Height) // If rotated objects are done correctly. + { + pt1 = CollisionMath.UpperLeftCorner(terrain.TerrainBounds, terrain.Rotation, Vector2.Zero); + pt2 = CollisionMath.UpperRightCorner(terrain.TerrainBounds, terrain.Rotation, Vector2.Zero); + } + else // If rotated objects are done Teddy's incorrect way. + { + if (terrain.Rotation > 0) // ROTCHECK + { + pt1 = CollisionMath.LowerLeftCorner(terrain.TerrainBounds, terrain.Rotation, Vector2.Zero); + pt2 = CollisionMath.UpperLeftCorner(terrain.TerrainBounds, terrain.Rotation, Vector2.Zero); + } + else + { + pt1 = CollisionMath.UpperRightCorner(terrain.TerrainBounds, terrain.Rotation, Vector2.Zero); + pt2 = CollisionMath.LowerRightCorner(terrain.TerrainBounds, terrain.Rotation, Vector2.Zero); + } + } + + // A check to make sure the enemy collides with the correct slope. + if (enemy.X > pt1.X && enemy.X < pt2.X) + collides = true; + + float u = pt2.X - pt1.X; + float v = pt2.Y - pt1.Y; + float x = pt1.X; + float y = pt1.Y; + float x1 = enemy.X; + + groundDist = (int)(y + (x1 - x) * (v / u)) - enemy.TerrainBounds.Bottom; + } + + if (collides == true && groundDist < closestGround && groundDist > 0) + { + closestGround = groundDist; + closestTerrain = terrain; + } + } + + //foreach (TerrainObj terrainObj in room.TerrainObjList) + //{ + // if (terrainObj.Y >= enemy.Y) + // { + // if (terrainObj.Y - enemy.Y < closestGround && CollisionMath.Intersects(terrainObj.Bounds, new Rectangle((int)enemy.X, (int)(enemy.Y + (terrainObj.Y - enemy.Y) + 5), enemy.Width, (int)(enemy.Height / 2)))) + // { + // closestGround = terrainObj.Y - enemy.Y; + // closestTerrain = terrainObj; + // } + // } + //} + + if (closestTerrain != null) + { + enemy.UpdateCollisionBoxes(); + if (closestTerrain.Rotation == 0) + enemy.Y = closestTerrain.Y - (enemy.TerrainBounds.Bottom - enemy.Y); + else + HookEnemyToSlope(enemy, closestTerrain); + } + } + } + } + } + + private void HookEnemyToSlope(IPhysicsObj enemy, TerrainObj terrain) + { + float y1 = float.MaxValue; + Vector2 pt1, pt2; + if (terrain.Width > terrain.Height) // If rotated objects are done correctly. + { + pt1 = CollisionMath.UpperLeftCorner(terrain.TerrainBounds, terrain.Rotation, Vector2.Zero); + pt2 = CollisionMath.UpperRightCorner(terrain.TerrainBounds, terrain.Rotation, Vector2.Zero); + } + else // If rotated objects are done Teddy's incorrect way. + { + if (terrain.Rotation > 0) // ROTCHECK + { + pt1 = CollisionMath.LowerLeftCorner(terrain.TerrainBounds, terrain.Rotation, Vector2.Zero); + pt2 = CollisionMath.UpperLeftCorner(terrain.TerrainBounds, terrain.Rotation, Vector2.Zero); + } + else + { + pt1 = CollisionMath.UpperRightCorner(terrain.TerrainBounds, terrain.Rotation, Vector2.Zero); + pt2 = CollisionMath.LowerRightCorner(terrain.TerrainBounds, terrain.Rotation, Vector2.Zero); + } + } + + //if (enemy.X > pt1.X + 10 && enemy.X < pt2.X - 10) + { + float u = pt2.X - pt1.X; + float v = pt2.Y - pt1.Y; + float x = pt1.X; + float y = pt1.Y; + float x1 = enemy.X; + + y1 = y + (x1 - x) * (v / u); + + enemy.UpdateCollisionBoxes(); + y1 -= (enemy.Bounds.Bottom - enemy.Y) + (5 * (enemy as GameObj).ScaleX); + enemy.Y = (float)Math.Round(y1, MidpointRounding.ToEven); + } + } + + public void InitializeChests(bool resetChests) + { + m_chestList.Clear(); + + //int chestLevel = 1; + //int levelCounter = 0; // Every 5 times a room is iterated, the chest's level goes up. + + foreach (RoomObj room in RoomList) + { + //if (room.Name != "Secret") // Do not modify chests for secret rooms yet. + { + foreach (GameObj obj in room.GameObjList) + { + ChestObj chest = obj as ChestObj; + if (chest != null && chest.ChestType != ChestType.Fairy)// && room.Name != "Bonus") // Do not modify chests for bonus rooms or fairy chests. + { + //chest.Level = chestLevel; // Setting the chest level. + chest.Level = (int)(room.Level / (LevelEV.ROOM_LEVEL_MOD + Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.RoomLevelDown) * GameEV.RUNE_GRACE_ROOM_LEVEL_LOSS)); + + if (chest.IsProcedural == true) // Ensures chests loaded from a save file are not overwritten. + { + // Closes the chests. + if (resetChests == true) + chest.ResetChest(); + + + // Turning the chest into a brown, silver, or gold chest. + + int chestRoll = CDGMath.RandomInt(1, 100); + int chestType = 0; + for (int i = 0; i < GameEV.CHEST_TYPE_CHANCE.Length; i++) + { + chestType += GameEV.CHEST_TYPE_CHANCE[i]; + if (chestRoll <= chestType) + { + if (i == 0) + chest.ChestType = ChestType.Brown; + else if (i == 1) + chest.ChestType = ChestType.Silver; + else + chest.ChestType = ChestType.Gold; + break; + } + } + ////////////////////////////////////////////////////////// + } + m_chestList.Add(chest); + } + else if (chest != null && chest.ChestType == ChestType.Fairy) + { + FairyChestObj fairyChest = chest as FairyChestObj; + if (fairyChest != null) + { + if (chest.IsProcedural == true) + { + if (resetChests == true) + fairyChest.ResetChest(); + } + //fairyChest.SetPlayer(m_player); + fairyChest.SetConditionType(); + } + } + m_chestList.Add(chest); + + // Code to properly recentre chests (since their anchor points were recently modified in the spritesheet. + if (chest != null) + { + chest.X += chest.Width / 2; + chest.Y += 60; // The height of a tile. + } + } + } + + //if (room.Level % LevelEV.ROOM_LEVEL_MOD == 0) + // chestLevel++; + + //levelCounter++; + //if (levelCounter >= LevelEV.ROOM_LEVEL_MOD) + //{ + // levelCounter = 0; + // chestLevel++; + //} + } + } + + private Texture2D m_castleBorderTexture, m_towerBorderTexture, m_dungeonBorderTexture, m_gardenBorderTexture; + private Texture2D m_neoBorderTexture; + + public void InitializeAllRooms(bool loadContent) + { + m_castleBorderTexture = (new SpriteObj("CastleBorder_Sprite") { Scale = new Vector2(2, 2) }).ConvertToTexture(Camera, true, SamplerState.PointWrap); + string castleCornerTextureString = "CastleCorner_Sprite"; + string castleCornerLTextureString = "CastleCornerL_Sprite"; + + m_towerBorderTexture = (new SpriteObj("TowerBorder2_Sprite") { Scale = new Vector2(2, 2) }).ConvertToTexture(Camera, true, SamplerState.PointWrap); + string towerCornerTextureString = "TowerCorner_Sprite"; + string towerCornerLTextureString = "TowerCornerL_Sprite"; + + m_dungeonBorderTexture = (new SpriteObj("DungeonBorder_Sprite") { Scale = new Vector2(2, 2) }).ConvertToTexture(Camera, true, SamplerState.PointWrap); + string dungeonCornerTextureString = "DungeonCorner_Sprite"; + string dungeonCornerLTextureString = "DungeonCornerL_Sprite"; + + m_gardenBorderTexture = (new SpriteObj("GardenBorder_Sprite") { Scale = new Vector2(2, 2) }).ConvertToTexture(Camera, true, SamplerState.PointWrap); + string gardenCornerTextureString = "GardenCorner_Sprite"; + string gardenCornerLTextureString = "GardenCornerL_Sprite"; + + m_neoBorderTexture = (new SpriteObj("NeoBorder_Sprite") { Scale = new Vector2(2, 2) }).ConvertToTexture(Camera, true, SamplerState.PointWrap); + string futureCornerTextureString = "NeoCorner_Sprite"; + string futureCornerLTextureString = "NeoCornerL_Sprite"; + + if (Game.PlayerStats.Traits.X == TraitType.TheOne || Game.PlayerStats.Traits.Y == TraitType.TheOne) + { + castleCornerLTextureString = dungeonCornerLTextureString = towerCornerLTextureString = gardenCornerLTextureString = futureCornerLTextureString; + castleCornerTextureString = dungeonCornerTextureString = towerCornerTextureString = gardenCornerTextureString = futureCornerTextureString; + } + // These textures need to be stored and released during dispose(). + + int roomLevel = 0; + roomLevel = Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.RoomLevelUp) * GameEV.RUNE_CURSE_ROOM_LEVEL_GAIN; + + if (m_roomBWRenderTarget != null) + m_roomBWRenderTarget.Dispose(); + m_roomBWRenderTarget = new RenderTarget2D(Camera.GraphicsDevice, GlobalEV.ScreenWidth, GlobalEV.ScreenHeight, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + + foreach (RoomObj room in RoomList) + { + int roomLevelMod = 0; + switch (room.LevelType) + { + case(GameTypes.LevelType.CASTLE): + roomLevelMod = LevelEV.CASTLE_ROOM_LEVEL_BOOST; + break; + case (GameTypes.LevelType.GARDEN): + roomLevelMod = LevelEV.GARDEN_ROOM_LEVEL_BOOST - 2; // Subtracting 2 for each subsequent number of Linker rooms there are on the map. + break; + case (GameTypes.LevelType.TOWER): + roomLevelMod = LevelEV.TOWER_ROOM_LEVEL_BOOST - 4; + break; + case (GameTypes.LevelType.DUNGEON): + roomLevelMod = LevelEV.DUNGEON_ROOM_LEVEL_BOOST - 6; + break; + } + + if (Game.PlayerStats.TimesCastleBeaten == 0) + room.Level = roomLevel + roomLevelMod; + else + room.Level = roomLevel + roomLevelMod + (LevelEV.NEWGAMEPLUS_LEVEL_BASE + ((Game.PlayerStats.TimesCastleBeaten - 1) * LevelEV.NEWGAMEPLUS_LEVEL_APPRECIATION)); //TEDDY DELETING 1 from TimesCastleBeaten CAUSE APPRECIATION SHOULDNT KICK IN. + + roomLevel++; + + if (loadContent == true) + room.LoadContent(Camera.GraphicsDevice); + + room.InitializeRenderTarget(m_roomBWRenderTarget); + + if (room.Name == "ChallengeBoss") + { + foreach (BorderObj border in room.BorderList) + { + border.SetBorderTextures(m_neoBorderTexture, futureCornerTextureString, futureCornerLTextureString); + border.NeoTexture = m_neoBorderTexture; + } + } + else + { + foreach (BorderObj border in room.BorderList) + { + switch (room.LevelType) + { + case (GameTypes.LevelType.TOWER): + border.SetBorderTextures(m_towerBorderTexture, towerCornerTextureString, towerCornerLTextureString); + break; + case (GameTypes.LevelType.DUNGEON): + border.SetBorderTextures(m_dungeonBorderTexture, dungeonCornerTextureString, dungeonCornerLTextureString); + break; + case (GameTypes.LevelType.GARDEN): + border.SetBorderTextures(m_gardenBorderTexture, gardenCornerTextureString, gardenCornerLTextureString); + border.TextureOffset = new Vector2(0, -18); + break; + case (GameTypes.LevelType.CASTLE): + default: + border.SetBorderTextures(m_castleBorderTexture, castleCornerTextureString, castleCornerLTextureString); + break; + } + border.NeoTexture = m_neoBorderTexture; + } + } + + bool addTerrainBoxToBreakables = false; + if (Game.PlayerStats.Traits.X == TraitType.NoFurniture || Game.PlayerStats.Traits.Y == TraitType.NoFurniture) + addTerrainBoxToBreakables = true; + + foreach (GameObj obj in room.GameObjList) + { + HazardObj hazard = obj as HazardObj; + if (hazard != null) + hazard.InitializeTextures(Camera); + + HoverObj hoverObj = obj as HoverObj; + if (hoverObj != null) + hoverObj.SetStartingPos(hoverObj.Position); + + if (addTerrainBoxToBreakables == true) + { + BreakableObj breakableObj = obj as BreakableObj; + + if (breakableObj != null && breakableObj.HitBySpellsOnly == false && breakableObj.HasTerrainHitBox == false) + { + breakableObj.CollisionBoxes.Add(new CollisionBox(breakableObj.RelativeBounds.X, breakableObj.RelativeBounds.Y, breakableObj.Width, breakableObj.Height, Consts.TERRAIN_HITBOX, breakableObj)); + breakableObj.DisableHitboxUpdating = true; + breakableObj.UpdateTerrainBox(); + } + } + } + + if (LevelEV.RUN_TESTROOM == true && loadContent == true) + { + foreach (GameObj obj in room.GameObjList) + { + if (obj is PlayerStartObj) + m_player.Position = obj.Position; + } + } + + if ((room.Name == "Boss" || room.Name == "ChallengeBoss") && room.LinkedRoom != null) + { + CloseBossDoor(room.LinkedRoom, room.LevelType); + //OpenChallengeBossDoor(room.LinkedRoom, room.LevelType); // Extra content added to link challenge boss rooms. + //if (Game.PlayerStats.ChallengeLastBossBeaten == false && Game.PlayerStats.ChallengeLastBossUnlocked == true) + // OpenLastBossChallengeDoors(); + } + } + } + + public void CloseBossDoor(RoomObj linkedRoom, GameTypes.LevelType levelType) + { + bool closeDoor = false; + + switch (levelType) + { + case (GameTypes.LevelType.CASTLE): + if (Game.PlayerStats.EyeballBossBeaten == true) + closeDoor = true; + break; + case (GameTypes.LevelType.DUNGEON): + if (Game.PlayerStats.BlobBossBeaten == true) + closeDoor = true; + break; + case (GameTypes.LevelType.GARDEN): + if (Game.PlayerStats.FairyBossBeaten == true) + closeDoor = true; + break; + case (GameTypes.LevelType.TOWER): + if (Game.PlayerStats.FireballBossBeaten == true) + closeDoor = true; + break; + } + + if (closeDoor == true) + { + foreach (DoorObj door in linkedRoom.DoorList) + { + if (door.IsBossDoor == true) + { + // Change the door graphic to closed. + foreach (GameObj obj in linkedRoom.GameObjList) + { + if (obj.Name == "BossDoor") + { + obj.ChangeSprite((obj as SpriteObj).SpriteName.Replace("Open", "")); + obj.TextureColor = Color.White; + obj.Opacity = 1; + linkedRoom.LinkedRoom = null; + break; + } + } + + // Lock the door. + door.Locked = true; + break; + } + } + } + + OpenChallengeBossDoor(linkedRoom, levelType); // Extra content added to link challenge boss rooms. + //if (Game.PlayerStats.ChallengeLastBossBeaten == false && Game.PlayerStats.ChallengeLastBossUnlocked == true) + if (Game.PlayerStats.ChallengeLastBossUnlocked == true) + OpenLastBossChallengeDoors(); + } + + public void OpenLastBossChallengeDoors() + { + LastBossChallengeRoom lastBossChallengeRoom = null; + foreach (RoomObj room in RoomList) + { + if (room.Name == "ChallengeBoss") + { + if (room is LastBossChallengeRoom) + { + lastBossChallengeRoom = room as LastBossChallengeRoom; + break; + } + } + } + + foreach (RoomObj room in RoomList) + { + if (room.Name == "EntranceBoss") + { + bool linkChallengeBossRoom = false; + + // Make sure to only link rooms with bosses that are beaten. + if (room.LevelType == GameTypes.LevelType.CASTLE && Game.PlayerStats.EyeballBossBeaten == true) + linkChallengeBossRoom = true; + else if (room.LevelType == GameTypes.LevelType.DUNGEON && Game.PlayerStats.BlobBossBeaten == true) + linkChallengeBossRoom = true; + else if (room.LevelType == GameTypes.LevelType.GARDEN && Game.PlayerStats.FairyBossBeaten == true) + linkChallengeBossRoom = true; + else if (room.LevelType == GameTypes.LevelType.TOWER && Game.PlayerStats.FireballBossBeaten == true) + linkChallengeBossRoom = true; + + if (linkChallengeBossRoom == true) + { + foreach (DoorObj door in room.DoorList) + { + if (door.IsBossDoor == true) + { + room.LinkedRoom = lastBossChallengeRoom; + + foreach (GameObj obj in room.GameObjList) + { + if (obj.Name == "BossDoor") + { + // Change the door graphic to close + if (Game.PlayerStats.ChallengeLastBossBeaten == true) + { + if ((obj as SpriteObj).SpriteName.Contains("Open") == true) + obj.ChangeSprite((obj as SpriteObj).SpriteName.Replace("Open", "")); + //obj.TextureColor = new Color(0, 255, 255); + //obj.Opacity = 0.6f; + obj.TextureColor = Color.White; + obj.Opacity = 1; + room.LinkedRoom = null; + door.Locked = true; + } + else + { + // Change the door graphic to open + if ((obj as SpriteObj).SpriteName.Contains("Open") == false) + obj.ChangeSprite((obj as SpriteObj).SpriteName.Replace("_Sprite", "Open_Sprite")); + obj.TextureColor = new Color(0, 255, 255); + obj.Opacity = 0.6f; + + // Unlock the door. It now leads to the challenge room. + door.Locked = false; + } + break; + } + } + } + } + } + } + } + } + + public void OpenChallengeBossDoor(RoomObj linkerRoom, GameTypes.LevelType levelType) + { + bool openSpecialBossDoor = false; + + switch (levelType) + { + case (GameTypes.LevelType.CASTLE): + if (Game.PlayerStats.EyeballBossBeaten == true && Game.PlayerStats.ChallengeEyeballBeaten == false && Game.PlayerStats.ChallengeEyeballUnlocked == true) + openSpecialBossDoor = true; + break; + case (GameTypes.LevelType.DUNGEON): + if (Game.PlayerStats.BlobBossBeaten == true && Game.PlayerStats.ChallengeBlobBeaten == false && Game.PlayerStats.ChallengeBlobUnlocked == true) + openSpecialBossDoor = true; + break; + case (GameTypes.LevelType.GARDEN): + if (Game.PlayerStats.FairyBossBeaten == true && Game.PlayerStats.ChallengeSkullBeaten == false && Game.PlayerStats.ChallengeSkullUnlocked == true) + openSpecialBossDoor = true; + break; + case (GameTypes.LevelType.TOWER): + if (Game.PlayerStats.FireballBossBeaten == true && Game.PlayerStats.ChallengeFireballBeaten == false && Game.PlayerStats.ChallengeFireballUnlocked == true) + openSpecialBossDoor = true; + break; + } + + if (openSpecialBossDoor == true) + { + RoomObj linkedRoom = LevelBuilder2.GetChallengeBossRoomFromRoomList(levelType, m_roomList); + linkerRoom.LinkedRoom = linkedRoom; + + foreach (DoorObj door in linkerRoom.DoorList) + { + if (door.IsBossDoor == true) + { + // Change the door graphic to open + foreach (GameObj obj in linkerRoom.GameObjList) + { + if (obj.Name == "BossDoor") + { + obj.ChangeSprite((obj as SpriteObj).SpriteName.Replace("_Sprite", "Open_Sprite")); + obj.TextureColor = new Color(0,255,255); + obj.Opacity = 0.6f; + break; + } + } + + // Unlock the door. It now leads to the challenge room. + door.Locked = false; + break; + } + } + } + } + + public void AddRooms(List roomsToAdd) + { + foreach (RoomObj room in roomsToAdd) + { + m_roomList.Add(room); + if (room.X < m_leftMostBorder) + m_leftMostBorder = (int)room.X; + if (room.X + room.Width > m_rightMostBorder) + m_rightMostBorder = (int)room.X + room.Width; + if (room.Y < m_topMostBorder) + m_topMostBorder = (int)room.Y; + if (room.Y + room.Height > m_bottomMostBorder) + m_bottomMostBorder = (int)room.Y + room.Height; + } + } + + public void AddRoom(RoomObj room) + { + m_roomList.Add(room); + if (room.X < m_leftMostBorder) + m_leftMostBorder = (int)room.X; + if (room.X + room.Width > m_rightMostBorder) + m_rightMostBorder = (int)room.X + room.Width; + if (room.Y < m_topMostBorder) + m_topMostBorder = (int)room.Y; + if (room.Y + room.Height > m_bottomMostBorder) + m_bottomMostBorder = (int)room.Y + room.Height; + } + + private void CheckForRoomTransition() + { + if (m_player != null) + { + foreach (RoomObj roomObj in m_roomList) + { + if (roomObj != CurrentRoom) + { + if (roomObj.Bounds.Contains((int)m_player.X, (int)m_player.Y)) + { + // This was moved here. If causing problems, remove this one and uncomment the one lower in this function. + ResetEnemyPositions(); // Must be called before the current room is set. Resets the positions of all enemies in the previous room. + + // Before changing rooms, reset enemy logic. + if (CurrentRoom != null) + { + foreach (EnemyObj enemy in EnemyList) + enemy.ResetState(); + } + + if (m_enemiesPaused == true) + UnpauseAllEnemies(); + + m_player.RoomTransitionReset(); + + m_miniMapDisplay.AddRoom(roomObj); // Add the room to the map display the moment you enter it. + // Save the player data and map data upon transition to new room. + if (roomObj.Name != "Start") + (ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData, SaveType.MapData); + + // Override texture colour if challenge room + if (roomObj.Name == "ChallengeBoss") + { + //m_foregroundSprite.TextureColor = Color.Black; + //m_backgroundSprite.TextureColor = Color.Black; + m_backgroundSprite.Scale = Vector2.One; + m_backgroundSprite.ChangeSprite("NeoBG_Sprite", ScreenManager.Camera); + m_backgroundSprite.Scale = new Vector2(2, 2); + + m_foregroundSprite.Scale = Vector2.One; + m_foregroundSprite.ChangeSprite("NeoFG_Sprite", ScreenManager.Camera); + m_foregroundSprite.Scale = new Vector2(2, 2); + } + //else + //{ + // m_foregroundSprite.TextureColor = Color.White; + // m_backgroundSprite.TextureColor = Color.White; + //} + + // This code only happens if the level type you are entering is different from the previous one you were in. + if ((CurrentRoom == null || CurrentLevelType != roomObj.LevelType || (CurrentRoom != null && CurrentRoom.Name == "ChallengeBoss")) && roomObj.Name != "Start") + { + if (roomObj.Name != "ChallengeBoss") + { + switch (roomObj.LevelType) + { + case (GameTypes.LevelType.CASTLE): + m_backgroundSprite.Scale = Vector2.One; + m_foregroundSprite.Scale = Vector2.One; + m_backgroundSprite.ChangeSprite("CastleBG1_Sprite", ScreenManager.Camera); + m_foregroundSprite.ChangeSprite("CastleFG1_Sprite", ScreenManager.Camera); + m_backgroundSprite.Scale = new Vector2(2, 2); + m_foregroundSprite.Scale = new Vector2(2, 2); + break; + case (GameTypes.LevelType.TOWER): + m_backgroundSprite.Scale = Vector2.One; + m_foregroundSprite.Scale = Vector2.One; + m_backgroundSprite.ChangeSprite("TowerBG2_Sprite", ScreenManager.Camera); + m_foregroundSprite.ChangeSprite("TowerFG2_Sprite", ScreenManager.Camera); + m_backgroundSprite.Scale = new Vector2(2, 2); + m_foregroundSprite.Scale = new Vector2(2, 2); + break; + case (GameTypes.LevelType.DUNGEON): + m_backgroundSprite.Scale = Vector2.One; + m_foregroundSprite.Scale = Vector2.One; + m_backgroundSprite.ChangeSprite("DungeonBG1_Sprite", ScreenManager.Camera); + m_foregroundSprite.ChangeSprite("DungeonFG1_Sprite", ScreenManager.Camera); + m_backgroundSprite.Scale = new Vector2(2, 2); + m_foregroundSprite.Scale = new Vector2(2, 2); + break; + case (GameTypes.LevelType.GARDEN): + m_backgroundSprite.Scale = Vector2.One; + m_foregroundSprite.Scale = Vector2.One; + m_backgroundSprite.ChangeSprite("GardenBG_Sprite", ScreenManager.Camera); + m_foregroundSprite.ChangeSprite("GardenFG_Sprite", ScreenManager.Camera); + m_backgroundSprite.Scale = new Vector2(2, 2); + m_foregroundSprite.Scale = new Vector2(2, 2); + break; + } + } + + if (Game.PlayerStats.Traits.X == TraitType.TheOne || Game.PlayerStats.Traits.Y == TraitType.TheOne) + { + m_foregroundSprite.Scale = Vector2.One; + m_foregroundSprite.ChangeSprite("NeoFG_Sprite", ScreenManager.Camera); + m_foregroundSprite.Scale = new Vector2(2, 2); + } + + // Setting shadow intensity. + if (roomObj.LevelType == GameTypes.LevelType.DUNGEON || Game.PlayerStats.Traits.X == TraitType.Glaucoma || Game.PlayerStats.Traits.Y == TraitType.Glaucoma || roomObj.Name == "Compass") + Game.ShadowEffect.Parameters["ShadowIntensity"].SetValue(0.7f); + else + Game.ShadowEffect.Parameters["ShadowIntensity"].SetValue(0); + + // Tower frame parallaxing effect. + //if (roomObj.LevelType == GameTypes.LevelType.TOWER) + //{ + // m_gameObjStartPos.Clear(); + // foreach (GameObj obj in roomObj.GameObjList) + // m_gameObjStartPos.Add(obj.Position); + //} + + //m_roomTitle.Text = "Now Entering\n" + WordBuilder.BuildDungeonName(roomObj.LevelType); + m_roomTitle.Text = LocaleBuilder.getString(WordBuilder.BuildDungeonNameLocID(roomObj.LevelType), m_roomTitle); + if (Game.PlayerStats.Traits.X == TraitType.Dyslexia || Game.PlayerStats.Traits.Y == TraitType.Dyslexia) + m_roomTitle.RandomizeSentence(false); + + m_roomTitle.Opacity = 0; + + if (roomObj.Name != "Boss" && roomObj.Name != "Tutorial" && roomObj.Name != "Ending" && roomObj.Name != "ChallengeBoss")// && roomObj.Name != "CastleEntrance") + { + Tween.StopAllContaining(m_roomEnteringTitle, false); + Tween.StopAllContaining(m_roomTitle, false); + m_roomTitle.Opacity = 0; + m_roomEnteringTitle.Opacity = 0; + + if (m_player.X > roomObj.Bounds.Center.X) + { + m_roomTitle.X = 50; + m_roomTitle.Align = Types.TextAlign.Left; + m_roomEnteringTitle.X = 70; + m_roomEnteringTitle.Align = Types.TextAlign.Left; + } + else + { + m_roomTitle.X = 1320 - 50; + m_roomTitle.Align = Types.TextAlign.Right; + m_roomEnteringTitle.X = 1320 - 70; + m_roomEnteringTitle.Align = Types.TextAlign.Right; + } + + Tween.To(m_roomTitle, 0.5f, Linear.EaseNone, "delay", "0.2", "Opacity", "1"); + m_roomTitle.Opacity = 1; // This is necessary because the tweener stores the initial value of the property when it is called. + Tween.To(m_roomTitle, 0.5f, Linear.EaseNone, "delay", "2.2", "Opacity", "0"); + m_roomTitle.Opacity = 0; + + Tween.To(m_roomEnteringTitle, 0.5f, Linear.EaseNone,"Opacity", "1"); + m_roomEnteringTitle.Opacity = 1; // This is necessary because the tweener stores the initial value of the property when it is called. + Tween.To(m_roomEnteringTitle, 0.5f, Linear.EaseNone, "delay", "2", "Opacity", "0"); + m_roomEnteringTitle.Opacity = 0; + } + else + { + Tween.StopAllContaining(m_roomEnteringTitle, false); + Tween.StopAllContaining(m_roomTitle, false); + m_roomTitle.Opacity = 0; + m_roomEnteringTitle.Opacity = 0; + } + + JukeboxEnabled = false; + Console.WriteLine("Now entering " + roomObj.LevelType); + } + + //ResetEnemyPositions(); // Must be called before the current room is set. Resets the positions of all enemies in the previous room. + + if (m_currentRoom != null) + m_currentRoom.OnExit(); // Call on exit if exiting from a room. This also removes all dementia enemies from the room. IMPORTANT. + + m_currentRoom = roomObj; // Sets to newly entered room to be the current room. + + // Necessary to keep track of which room the player is in otherwise it won't load in the correct room at start up. + //if (m_currentRoom.Name == "Boss" && LevelEV.RUN_TESTROOM == false) + // Game.PlayerStats.RespawnPos = m_currentRoom.LinkedRoom.Position; + //(ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData); // Saving player data. + + //if (m_currentRoom.Name != "Start" && m_currentRoom.Name != "CastleEntrance") + // (ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.MapData); // Saving map data. + + m_backgroundSprite.Position = CurrentRoom.Position; + m_foregroundSprite.Position = CurrentRoom.Position; + m_gardenParallaxFG.Position = CurrentRoom.Position; + + if (SoundManager.IsMusicPaused == true) + SoundManager.ResumeMusic(); + + if (DisableSongUpdating == false && JukeboxEnabled == false) + UpdateLevelSong(); + + if (m_currentRoom.Player == null) + m_currentRoom.Player = m_player; + //m_currentRoom.OnEnter(); + + if (m_currentRoom.Name != "Start" && m_currentRoom.Name != "Tutorial" && m_currentRoom.Name != "Ending" && + m_currentRoom.Name != "CastleEntrance" && m_currentRoom.Name != "Bonus" && m_currentRoom.Name != "Throne" && + m_currentRoom.Name != "Secret" && m_currentRoom.Name != "Boss" && m_currentRoom.LevelType != GameTypes.LevelType.NONE && m_currentRoom.Name != "ChallengeBoss") + { + if (Game.PlayerStats.Traits.X == TraitType.Dementia || Game.PlayerStats.Traits.Y == TraitType.Dementia) + { + if (CDGMath.RandomFloat(0, 1) < GameEV.TRAIT_DEMENTIA_SPAWN_CHANCE) + SpawnDementiaEnemy(); + } + } + + if (m_currentRoom.HasFairyChest)// && ScreenManager.GetScreens().Length > 0) + m_currentRoom.DisplayFairyChestInfo(); + + m_tempEnemyStartPositions.Clear(); + m_enemyStartPositions.Clear(); // Clear out the start position array. + foreach (EnemyObj enemy in CurrentRoom.EnemyList) // Saves all enemy positions in the new room to an array for when the player exits the room. + m_enemyStartPositions.Add(enemy.Position); + foreach (EnemyObj enemy in CurrentRoom.TempEnemyList) // Saves all enemy positions in the new room to an array for when the player exits the room. + m_tempEnemyStartPositions.Add(enemy.Position); + + m_projectileManager.DestroyAllProjectiles(false); + LoadPhysicsObjects(roomObj); + //m_miniMapDisplay.AddRoom(roomObj); // Add the room to the map display. + m_itemDropManager.DestroyAllItemDrops(); + m_projectileIconPool.DestroyAllIcons(); // Destroys all icons for projectiles in the room. + + m_enemyPauseDuration = 0; // Resets the enemy pause counter. Don't unpause all enemies because they will unpause when Enemy.ResetState() is called. + + + if (LevelEV.SHOW_ENEMY_RADII == true) + { + foreach (EnemyObj enemy in roomObj.EnemyList) + { + enemy.InitializeDebugRadii(); + } + } + m_lastEnemyHit = null; // Clear out last enemy hit. + + foreach (GameObj obj in m_currentRoom.GameObjList) + { + FairyChestObj chest = obj as FairyChestObj; + if (chest != null && chest.IsOpen == false) // Always reset chests. + { + //chest.State = ChestConditionChecker.STATE_LOCKED; + //chest.TextureColor = Color.White; + //chest.ResetChest(); + } + + //ObjContainer objContainer = obj as ObjContainer; + IAnimateableObj objContainer = obj as IAnimateableObj; + // This is the code that sets the frame rate and whether to animate objects in the room. + if (objContainer != null && objContainer.TotalFrames > 1 && !(objContainer is ChestObj) && !(obj is BreakableObj)) // What's this code for? + { + objContainer.AnimationDelay = 1 / 10f; + objContainer.PlayAnimation(true); + } + } + + if (DisableRoomOnEnter == false) + m_currentRoom.OnEnter(); + break; + } + } + } + } + } + + private void UpdateLevelSong() + { + //if (!(m_currentRoom is StartingRoomObj) && !(m_currentRoom is IntroRoomObj) && SoundManager.IsMusicPlaying == false) + if (CurrentRoom.Name != "Start" && CurrentRoom.Name != "Tutorial" && CurrentRoom.Name != "Ending" && SoundManager.IsMusicPlaying == false) + { + if (m_currentRoom is CarnivalShoot1BonusRoom || m_currentRoom is CarnivalShoot2BonusRoom) + SoundManager.PlayMusic("PooyanSong", true, 1); + else + { + switch (m_currentRoom.LevelType) + { + default: + case (GameTypes.LevelType.CASTLE): + SoundManager.PlayMusic("CastleSong", true, 1); + break; + case (GameTypes.LevelType.GARDEN): + SoundManager.PlayMusic("GardenSong", true, 1); + break; + case (GameTypes.LevelType.TOWER): + SoundManager.PlayMusic("TowerSong", true, 1); + break; + case (GameTypes.LevelType.DUNGEON): + SoundManager.PlayMusic("DungeonSong", true, 1); + break; + } + } + } + else if (!(m_currentRoom is StartingRoomObj) && SoundManager.IsMusicPlaying == true) + { + if ((m_currentRoom is CarnivalShoot1BonusRoom || m_currentRoom is CarnivalShoot2BonusRoom) && SoundManager.GetCurrentMusicName() != "PooyanSong") + SoundManager.PlayMusic("PooyanSong", true, 1); + else + { + if (m_currentRoom.LevelType == GameTypes.LevelType.CASTLE && SoundManager.GetCurrentMusicName() != "CastleSong") + SoundManager.PlayMusic("CastleSong", true, 1); + else if (m_currentRoom.LevelType == GameTypes.LevelType.GARDEN && SoundManager.GetCurrentMusicName() != "GardenSong") + SoundManager.PlayMusic("GardenSong", true, 1); + else if (m_currentRoom.LevelType == GameTypes.LevelType.DUNGEON && SoundManager.GetCurrentMusicName() != "DungeonSong") + SoundManager.PlayMusic("DungeonSong", true, 1); + else if (m_currentRoom.LevelType == GameTypes.LevelType.TOWER && SoundManager.GetCurrentMusicName() != "TowerSong") + SoundManager.PlayMusic("TowerSong", true, 1); + } + } + } + + private float m_fakeElapsedTotalHour = (1f / 60f) / (60f * 60f); + public override void Update(GameTime gameTime) + { + //if (InputManager.JustPressed(Keys.L, PlayerIndex.One)) + //{ + // if (Camera.Zoom != 2) + // Camera.Zoom = 2; + // else + // Camera.Zoom = 1; + //} + //if (InputManager.JustPressed(Keys.K, PlayerIndex.One)) + //{ + // if (Camera.Zoom != 0.5) + // Camera.Zoom = 0.5f; + // else + // Camera.Zoom = 1; + //} + + //if (InputManager.JustPressed(Keys.B, null)) + // this.ResetEnemyPositions(); + + float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds; + m_projectileIconPool.Update(Camera); + + if (this.IsPaused == false) + { + //TotalGameTimeHours = (float)gameTime.TotalGameTime.TotalHours; + float elapsedTotalHours = (float)gameTime.ElapsedGameTime.TotalHours; + if (elapsedTotalHours <= 0) // This is a check to ensure total GameTime is always incremented. + elapsedTotalHours = m_fakeElapsedTotalHour; + Game.HoursPlayedSinceLastSave += elapsedTotalHours; + + m_sky.Update(gameTime); + + if (m_enemyPauseDuration > 0) + { + m_enemyPauseDuration -= elapsed; + if (m_enemyPauseDuration <= 0) + StopTimeStop(); + } + + CurrentRoom.Update(gameTime); + + if (m_player != null) + m_player.Update(gameTime); + + m_enemyHUD.Update(gameTime); + m_playerHUD.Update(m_player); + + m_projectileManager.Update(gameTime); + m_physicsManager.Update(gameTime); + + // Only check for room transitions if the player steps out of the camera zone. + if (DisableRoomTransitioning == false && CollisionMath.Intersects(new Rectangle((int)m_player.X, (int)m_player.Y, 1,1), Camera.Bounds) == false) + CheckForRoomTransition(); + + if ((m_inputMap.Pressed(INPUT_LEFTCONTROL) == false || (m_inputMap.Pressed(INPUT_LEFTCONTROL) == true && (LevelEV.RUN_DEMO_VERSION == true || LevelEV.CREATE_RETAIL_VERSION == true))) && CameraLockedToPlayer == true) + UpdateCamera(); // Must be called AFTER the PhysicsManager Update() because the PhysicsManager changes the player's position depending on what he/she is colliding with. + + if (Game.PlayerStats.SpecialItem == SpecialItemType.Compass && CurrentRoom.Name != "Start" && CurrentRoom.Name !="Tutorial" && CurrentRoom.Name != "Boss" && CurrentRoom.Name != "Throne" && CurrentRoom.Name != "ChallengeBoss") + { + if (m_compassDisplayed == false) // Display compass here + DisplayCompass(); + else + UpdateCompass(); + } + else + { + if (m_compassDisplayed == true && CurrentRoom.Name != "Compass") + HideCompass(); + } + + // This means the objective plate is displayed. Now we are checking to make sure if any enemy of player collides with it, change its opacity. + if (m_objectivePlate.X == 1170) + { + bool objectivePlateCollides = false; + Rectangle objectivePlateAbsRect = m_objectivePlate.Bounds; + objectivePlateAbsRect.X += (int)Camera.TopLeftCorner.X; + objectivePlateAbsRect.Y += (int)Camera.TopLeftCorner.Y; + + if (CollisionMath.Intersects(m_player.Bounds, objectivePlateAbsRect)) + objectivePlateCollides = true; + + if (objectivePlateCollides == false) + { + foreach (EnemyObj enemy in CurrentRoom.EnemyList) + { + if (CollisionMath.Intersects(enemy.Bounds, objectivePlateAbsRect)) + { + objectivePlateCollides = true; + break; + } + } + } + + if (objectivePlateCollides == true) + m_objectivePlate.Opacity = 0.5f; + else + m_objectivePlate.Opacity = 1; + } + + if (CurrentRoom != null && (CurrentRoom is BonusRoomObj == false)) + { + if (m_elapsedScreenShake > 0) + { + m_elapsedScreenShake -= elapsed; + if (m_elapsedScreenShake <= 0) + { + if (Game.PlayerStats.Traits.X == (int)TraitType.Clonus || Game.PlayerStats.Traits.Y == (int)TraitType.Clonus) + { + ShakeScreen(1, true, true); + GamePad.SetVibration(PlayerIndex.One, 0.25f, 0.25f); + Tween.RunFunction(CDGMath.RandomFloat(1, 1.5f), this, "StopScreenShake"); + m_elapsedScreenShake = CDGMath.RandomFloat(GameEV.TRAIT_CLONUS_MIN, GameEV.TRAIT_CLONUS_MAX); + } + } + } + + if (m_shakeScreen == true) + UpdateShake(); + } + } + + base.Update(gameTime); // Necessary to update the ScreenManager. + } + + public void UpdateCamera() + { + if (m_player != null) + { + ScreenManager.Camera.X = (int)(m_player.Position.X + GlobalEV.Camera_XOffset); + ScreenManager.Camera.Y = (int)(m_player.Position.Y + GlobalEV.Camera_YOffset); + } + + if (m_currentRoom != null) + { + //Constrain the X-Axis of the camera to the current room. + if (ScreenManager.Camera.Width < m_currentRoom.Width) + { + if (ScreenManager.Camera.Bounds.Left < m_currentRoom.Bounds.Left) + ScreenManager.Camera.X = (int)(m_currentRoom.Bounds.Left + ScreenManager.Camera.Width * 0.5f); + else if (ScreenManager.Camera.Bounds.Right > m_currentRoom.Bounds.Right) + ScreenManager.Camera.X = (int)(m_currentRoom.Bounds.Right - ScreenManager.Camera.Width * 0.5f); + } + else + ScreenManager.Camera.X = (int)(m_currentRoom.X + m_currentRoom.Width * 0.5f); + + //Constrain the Y-Axis of the camera to the current room. + if (ScreenManager.Camera.Height < m_currentRoom.Height) + { + if (ScreenManager.Camera.Bounds.Top < m_currentRoom.Bounds.Top) + ScreenManager.Camera.Y = (int)(m_currentRoom.Bounds.Top + ScreenManager.Camera.Height * 0.5f); + else if (ScreenManager.Camera.Bounds.Bottom > m_currentRoom.Bounds.Bottom) + ScreenManager.Camera.Y = (int)(m_currentRoom.Bounds.Bottom - ScreenManager.Camera.Height * 0.5f); + } + else + ScreenManager.Camera.Y = (int)(m_currentRoom.Y + m_currentRoom.Height * 0.5f); + } + } + + //HandleInput is called AFTER Update(). + public override void HandleInput() + { + if (Game.GlobalInput.JustPressed(InputMapType.MENU_PAUSE) && CurrentRoom.Name != "Ending") + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Pause, true); + + if (LevelEV.ENABLE_DEBUG_INPUT == true) + HandleDebugInput(); + + if (m_player != null && (m_inputMap.Pressed(INPUT_LEFTCONTROL) == false || (m_inputMap.Pressed(INPUT_LEFTCONTROL) == true && (LevelEV.RUN_DEMO_VERSION == true || LevelEV.CREATE_RETAIL_VERSION == true))) && m_player.IsKilled == false) + m_player.HandleInput(); + + base.HandleInput(); + } + + private void HandleDebugInput() + { + if (InputManager.JustPressed(Keys.RightControl, null)) + { + if (SoundManager.GetCurrentMusicName() == "CastleSong") + SoundManager.PlayMusic("TowerSong", true, 0.5f); + else if (SoundManager.GetCurrentMusicName() == "TowerSong") + SoundManager.PlayMusic("DungeonBoss", true, 0.5f); + else + SoundManager.PlayMusic("CastleSong", true, 0.5f); + } + + if (m_inputMap.JustPressed(INPUT_TOGGLEMAP)) + { + m_miniMapDisplay.AddAllRooms(m_roomList); + //(ScreenManager as RCScreenManager).AddRoomsToMap(m_miniMapDisplay.AddedRoomsList); + //(ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Map, true, null); + } + + if (m_inputMap.JustPressed(INPUT_DISPLAYROOMINFO)) + LevelEV.SHOW_DEBUG_TEXT = !LevelEV.SHOW_DEBUG_TEXT; + + if (m_inputMap.JustPressed(INPUT_TOGGLEZOOM)) + { + //CameraLockedToPlayer = false; + if (Camera.Zoom < 1) + Camera.Zoom = 1; + else + //Tween.To(Camera, 4, Quad.EaseInOut, "Zoom", "0.05"); + Camera.Zoom = 0.05f; + } + + float debugCameraSpeed = 2000; + if (m_inputMap.Pressed(INPUT_LEFTCONTROL) && m_inputMap.Pressed(INPUT_LEFT)) + Camera.X -= debugCameraSpeed * (float)Camera.GameTime.ElapsedGameTime.TotalSeconds; + else if (m_inputMap.Pressed(INPUT_LEFTCONTROL) && m_inputMap.Pressed(INPUT_RIGHT)) + Camera.X += debugCameraSpeed * (float)Camera.GameTime.ElapsedGameTime.TotalSeconds; + + if (m_inputMap.Pressed(INPUT_LEFTCONTROL) && m_inputMap.Pressed(INPUT_UP)) + Camera.Y -= debugCameraSpeed * (float)Camera.GameTime.ElapsedGameTime.TotalSeconds; + else if (m_inputMap.Pressed(INPUT_LEFTCONTROL) && m_inputMap.Pressed(INPUT_DOWN)) + Camera.Y += debugCameraSpeed * (float)Camera.GameTime.ElapsedGameTime.TotalSeconds; + + if (InputManager.JustPressed(Keys.C, null)) + ToggleMagentaBG(); + + //if (InputManager.JustPressed(Keys.H, null)) + // ZoomOutAllObjects(); + } + + private void UpdateCompass() + { + if (m_compassDoor == null && CurrentRoom.Name != "Ending" && CurrentRoom.Name != "Boss" && CurrentRoom.Name != "Start" && CurrentRoom.Name != "Tutorial" && CurrentRoom.Name !=" ChallengeBoss") + { + Console.WriteLine("Creating new bonus room for compass"); + RoomObj roomToLink = null; + EnemyObj enemyToLink = null; + + List acceptableRooms = new List(); + foreach (RoomObj room in m_roomList) + { + bool hasEnemies = false; + foreach (EnemyObj enemy in room.EnemyList) + { + if (enemy.IsWeighted == true) + { + hasEnemies = true; + break; + } + } + + // No need to check for CastleEntrance or linker because they have no enemies in them. + if (room.Name != "Ending" && room.Name != "Tutorial" && room.Name != "Boss" && room.Name != "Secret" && room.Name != "Bonus" && hasEnemies == true && room.Name != "ChallengeBoss") + acceptableRooms.Add(room); + } + + if (acceptableRooms.Count > 0) + { + roomToLink = acceptableRooms[CDGMath.RandomInt(0, acceptableRooms.Count - 1)]; + int counter = 0; + while (enemyToLink == null || enemyToLink.IsWeighted == false) + { + enemyToLink = roomToLink.EnemyList[counter]; + counter++; + } + + DoorObj door = new DoorObj(roomToLink, 120, 180, GameTypes.DoorType.OPEN); + door.Position = enemyToLink.Position; + door.IsBossDoor = true; + door.DoorPosition = "None"; + door.AddCollisionBox(0, 0, door.Width, door.Height, Consts.TERRAIN_HITBOX); // This adds the terrain collision box for terrain objects. + door.AddCollisionBox(0, 0, door.Width, door.Height, Consts.BODY_HITBOX); // This adds a body collision box to terrain objects. + + float closestGround = float.MaxValue; + TerrainObj closestTerrain = null; + foreach (TerrainObj terrainObj in roomToLink.TerrainObjList) + { + if (terrainObj.Y >= door.Y) + { + if (terrainObj.Y - door.Y < closestGround && CollisionMath.Intersects(terrainObj.Bounds, new Rectangle((int)door.X, (int)(door.Y + (terrainObj.Y - door.Y) + 5), door.Width, (int)(door.Height / 2)))) + { + closestGround = terrainObj.Y - door.Y; + closestTerrain = terrainObj; + } + } + } + + if (closestTerrain != null) + { + door.UpdateCollisionBoxes(); + if (closestTerrain.Rotation == 0) + door.Y = closestTerrain.Y - (door.TerrainBounds.Bottom - door.Y); + else + HookEnemyToSlope(door, closestTerrain); + } + + roomToLink.DoorList.Add(door); + + roomToLink.LinkedRoom = m_roomList[m_roomList.Count - 1]; // The last room is always the compass room. + roomToLink.LinkedRoom.LinkedRoom = roomToLink; + roomToLink.LinkedRoom.LevelType = roomToLink.LevelType; + + string castleCornerTextureString = "CastleCorner_Sprite"; + string castleCornerLTextureString = "CastleCornerL_Sprite"; + string towerCornerTextureString = "TowerCorner_Sprite"; + string towerCornerLTextureString = "TowerCornerL_Sprite"; + string dungeonCornerTextureString = "DungeonCorner_Sprite"; + string dungeonCornerLTextureString = "DungeonCornerL_Sprite"; + string gardenCornerTextureString = "GardenCorner_Sprite"; + string gardenCornerLTextureString = "GardenCornerL_Sprite"; + + if (Game.PlayerStats.Traits.X == TraitType.TheOne || Game.PlayerStats.Traits.Y == TraitType.TheOne) + { + string futureCornerTextureString = "NeoCorner_Sprite"; + string futureCornerLTextureString = "NeoCornerL_Sprite"; + castleCornerLTextureString = dungeonCornerLTextureString = towerCornerLTextureString = gardenCornerLTextureString = futureCornerLTextureString; + castleCornerTextureString = dungeonCornerTextureString = towerCornerTextureString = gardenCornerTextureString = futureCornerTextureString; + } + + foreach (BorderObj border in roomToLink.LinkedRoom.BorderList) + { + switch (roomToLink.LinkedRoom.LevelType) + { + case (GameTypes.LevelType.TOWER): + border.SetBorderTextures(m_towerBorderTexture, towerCornerTextureString, towerCornerLTextureString); + break; + case (GameTypes.LevelType.DUNGEON): + border.SetBorderTextures(m_dungeonBorderTexture, dungeonCornerTextureString, dungeonCornerLTextureString); + break; + case (GameTypes.LevelType.GARDEN): + border.SetBorderTextures(m_gardenBorderTexture, gardenCornerTextureString, gardenCornerLTextureString); + border.TextureOffset = new Vector2(0, -18); + break; + case (GameTypes.LevelType.CASTLE): + default: + border.SetBorderTextures(m_castleBorderTexture, castleCornerTextureString, castleCornerLTextureString); + break; + } + } + + m_compassDoor = door; + } + } + + if (m_compassDoor != null) + m_compass.Rotation = CDGMath.AngleBetweenPts(m_player.Position, new Vector2(m_compassDoor.Bounds.Center.X, m_compassDoor.Bounds.Center.Y)); + } + + public void RemoveCompassDoor() + { + if (m_compassDoor != null) + { + m_compassDoor.Room.DoorList.Remove(m_compassDoor); + m_compassDoor.Dispose(); + m_compassDoor = null; + } + } + + private void DisplayCompass() + { + Tween.StopAllContaining(m_compassBG, false); + Tween.StopAllContaining(m_compass, false); + Tween.To(m_compassBG, 0.5f, Back.EaseOutLarge, "ScaleX", "1", "ScaleY", "1"); + Tween.To(m_compass, 0.5f, Back.EaseOutLarge, "ScaleX", "1", "ScaleY", "1"); + m_compassDisplayed = true; + } + + private void HideCompass() + { + Tween.StopAllContaining(m_compassBG, false); + Tween.StopAllContaining(m_compass, false); + Tween.To(m_compassBG, 0.5f, Back.EaseInLarge, "ScaleX", "0", "ScaleY", "0"); + Tween.To(m_compass, 0.5f, Back.EaseInLarge, "ScaleX", "0", "ScaleY", "0"); + m_compassDisplayed = false; + RemoveCompassDoor(); + } + + private RenderTarget2D m_finalRenderTarget; // The final render target that is drawn. + private RenderTarget2D m_fgRenderTarget; // The render target that the foreground is drawn on. + private RenderTarget2D m_bgRenderTarget; // The render target that the background is drawn on. + private RenderTarget2D m_skyRenderTarget; // The sky is drawn on this render target. + + // Special pixel shader render targets. + private RenderTarget2D m_shadowRenderTarget; // The render target used to drawn the shadows in the dungeon. + private RenderTarget2D m_lightSourceRenderTarget; // Also used to calculate shadows. Maybe these can be merged somehow. + private RenderTarget2D m_traitAuraRenderTarget; // A render target used to draw trait effects like near sighted. + + private BackgroundObj m_foregroundSprite, m_backgroundSprite, m_backgroundParallaxSprite, m_gardenParallaxFG; + + private const SurfaceFormat fgTargetFormat = SurfaceFormat.Color; + private const SurfaceFormat effectTargetFormat = SurfaceFormat.Color; + + public void InitializeRenderTargets() + { + int screenWidth = GlobalEV.ScreenWidth; + int screenHeight = GlobalEV.ScreenHeight; + + if (LevelEV.SAVE_FRAMES == true) + { + screenWidth /= 2; + screenHeight /= 2; + } + + // Initializing foreground render target. + if (m_fgRenderTarget != null) + m_fgRenderTarget.Dispose(); + m_fgRenderTarget = new RenderTarget2D(Camera.GraphicsDevice, screenWidth, screenHeight, false, fgTargetFormat, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + + if (m_shadowRenderTarget != null) m_shadowRenderTarget.Dispose(); + m_shadowRenderTarget = new RenderTarget2D(Camera.GraphicsDevice, screenWidth, screenHeight, false, effectTargetFormat, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + + Camera.Begin(); + Camera.GraphicsDevice.SetRenderTarget(m_shadowRenderTarget); + Camera.GraphicsDevice.Clear(Color.Black); // Requires no wrap. + Camera.End(); + + if (m_lightSourceRenderTarget != null) m_lightSourceRenderTarget.Dispose(); + m_lightSourceRenderTarget = new RenderTarget2D(Camera.GraphicsDevice, screenWidth, screenHeight, false, effectTargetFormat, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + + if (m_finalRenderTarget != null) m_finalRenderTarget.Dispose(); + m_finalRenderTarget = new RenderTarget2D(Camera.GraphicsDevice, GlobalEV.ScreenWidth, GlobalEV.ScreenHeight, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + + if (m_skyRenderTarget != null) m_skyRenderTarget.Dispose(); + m_skyRenderTarget = new RenderTarget2D(Camera.GraphicsDevice, screenWidth, screenHeight, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + + if (m_bgRenderTarget != null) m_bgRenderTarget.Dispose(); + m_bgRenderTarget = new RenderTarget2D(Camera.GraphicsDevice, GlobalEV.ScreenWidth, GlobalEV.ScreenHeight, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + + if (m_traitAuraRenderTarget != null) m_traitAuraRenderTarget.Dispose(); + m_traitAuraRenderTarget = new RenderTarget2D(Camera.GraphicsDevice, screenWidth, screenHeight, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + + InitializeBackgroundObjs(); + } + + public void InitializeBackgroundObjs() + { + if (m_foregroundSprite != null) + m_foregroundSprite.Dispose(); + + m_foregroundSprite = new BackgroundObj("CastleFG1_Sprite"); + m_foregroundSprite.SetRepeated(true, true, Camera, SamplerState.PointWrap); + m_foregroundSprite.Scale = new Vector2(2, 2); + + ///////////////////////////////////////////////////////// + + // Initializing background render target. + if (m_backgroundSprite != null) + m_backgroundSprite.Dispose(); + + m_backgroundSprite = new BackgroundObj("CastleBG1_Sprite"); + m_backgroundSprite.SetRepeated(true, true, Camera, SamplerState.PointWrap); // Must be called before anything else. + m_backgroundSprite.Scale = new Vector2(2f, 2f); + + if (m_backgroundParallaxSprite != null) + m_backgroundParallaxSprite.Dispose(); + + m_backgroundParallaxSprite = new BackgroundObj("TowerBGFrame_Sprite"); + m_backgroundParallaxSprite.SetRepeated(true, true, Camera, SamplerState.PointWrap); + m_backgroundParallaxSprite.Scale = new Vector2(2, 2); + + ///////////////////////////////////////////////////////// + // Initializing the parallaxing background render target. + if (m_gardenParallaxFG != null) + m_gardenParallaxFG.Dispose(); + + m_gardenParallaxFG = new BackgroundObj("ParallaxDifferenceClouds_Sprite"); + m_gardenParallaxFG.SetRepeated(true, true, Camera, SamplerState.LinearWrap); + m_gardenParallaxFG.TextureColor = Color.White; + //m_gardenParallaxFG.ForceDraw = true; + m_gardenParallaxFG.Scale = new Vector2(3, 3); + m_gardenParallaxFG.Opacity = 0.7f; + m_gardenParallaxFG.ParallaxSpeed = new Vector2(0.3f, 0); + } + + // All objects that need to be drawn on a render target before being drawn the back buffer go here. + public void DrawRenderTargets() + { + // This happens if graphics virtualization fails two times in a row. Buggy XNA RenderTarget2Ds. + if (m_backgroundSprite.Texture.IsContentLost == true) + this.ReinitializeRTs(); + + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, null, null, null, Camera.GetTransformation()); + // Drawing the B/W outline of the room to wallpaper on the FG and BG later. + if (CurrentRoom != null) + CurrentRoom.DrawRenderTargets(Camera); // Requires LinearWrap. + Camera.End(); + + ///////// ALL DRAW CALLS THAT REQUIRE A MATRIX TRANSFORMATION GO HERE ///////////////// + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointWrap, null, null, null, Camera.GetTransformation()); + + // Drawing the tiled foreground onto m_fgRenderTarget. + Camera.GraphicsDevice.SetRenderTarget(m_fgRenderTarget); + m_foregroundSprite.Draw(Camera); // Requires PointWrap. + + // Setting sampler state to Linear Wrap since most RTs below require it. + //Camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap; + + // Drawing the trait aura onto m_traitAuraRenderTarget (used for trait effects). + if (m_enemiesPaused == false) + { + if (Game.PlayerStats.Traits.X == TraitType.NearSighted || Game.PlayerStats.Traits.Y == TraitType.NearSighted) + m_traitAura.Scale = new Vector2(15, 15); + else if (Game.PlayerStats.Traits.X == TraitType.FarSighted || Game.PlayerStats.Traits.Y == TraitType.FarSighted) + m_traitAura.Scale = new Vector2(8, 8); + else + m_traitAura.Scale = new Vector2(10, 10); + } + Camera.GraphicsDevice.SetRenderTarget(m_traitAuraRenderTarget); + Camera.GraphicsDevice.Clear(Color.Transparent); + if (CurrentRoom != null) + { + m_traitAura.Position = m_player.Position; + m_traitAura.Draw(Camera); // Requires LinearWrap. + } + + // Drawing a light source onto a transparent m_lightSourceRenderTarget (used for dungeon lighting). + Camera.GraphicsDevice.SetRenderTarget(m_lightSourceRenderTarget); + Camera.GraphicsDevice.Clear(Color.Transparent); + if (CurrentRoom != null) + { + m_dungeonLight.Position = m_player.Position; + m_dungeonLight.Draw(Camera); // Requires LinearWrap. + } + + // Drawing a completely black RT onto m_shadowRenderTarget for the shadows in the dungeon. + //Camera.GraphicsDevice.SetRenderTarget(m_shadowRenderTarget); + //Camera.GraphicsDevice.Clear(Color.Black); // Requires no wrap. + Camera.End(); + + // Separated the mini map draw calls to deferred to speed up performance. Had to separate them from the sky render target. + ///////// ALL DRAW CALLS THAT DO NOT REQUIRE A MATRIX TRANSFORMATION GO HERE ///////////////// + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); + + // Making the map render targets. + m_miniMapDisplay.DrawRenderTargets(Camera); // Requires PointClamp + Camera.End(); + + // Drawing the sky parallax background to m_skyRenderTarget. + Camera.GraphicsDevice.SetRenderTarget(m_skyRenderTarget); + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, null, null); + //Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointWrap; + m_sky.Draw(Camera); // Requires PointWrap. + Camera.End(); + + // Setting the render target back to the main render target. + //Camera.GraphicsDevice.SetRenderTarget(m_finalRenderTarget); + } + + static Vector2 MoveInCircle(GameTime gameTime, float speed) + { + double time = Game.TotalGameTime * speed; + + float x = (float)Math.Cos(time); + float y = (float)Math.Sin(time); + + return new Vector2(x, y); + } + + private bool m_toggleMagentaBG = false; + + private void ToggleMagentaBG() + { + m_toggleMagentaBG = !m_toggleMagentaBG; + } + + public override void Draw(GameTime gameTime) + { + //Camera.Zoom = 2; + //BackBufferOpacity = 1; //TEDDY - ADDED FOR THE BLACKENING OF THE BG FOR SNAPSHOTS + DrawRenderTargets(); + + Camera.GraphicsDevice.SetRenderTarget(m_bgRenderTarget); + ///////// DRAWING BACKGROUND ///////////////////////// + // If the foreground and background effect are merged into one effect, this draw call can be removed. + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, null, null, null, Camera.GetTransformation()); + m_backgroundSprite.Draw(Camera); + + if (CurrentRoom != null && Camera.Zoom == 1 && (m_inputMap.Pressed(INPUT_LEFTCONTROL) == false || (m_inputMap.Pressed(INPUT_LEFTCONTROL) == true && (LevelEV.RUN_DEMO_VERSION == true || LevelEV.CREATE_RETAIL_VERSION == true)))) + { + CurrentRoom.DrawBGObjs(Camera); + // This line isn't being drawn anyway for some reason. + //if (CurrentRoom.LevelType == GameTypes.LevelType.TOWER) + // m_backgroundParallaxSprite.Draw(Camera); + } + else + { + // Debug drawing. Holding control allows you to zoom around. + foreach (RoomObj room in m_roomList) + room.DrawBGObjs(Camera); + } + Camera.End(); + + Camera.GraphicsDevice.SetRenderTarget(m_finalRenderTarget); + Camera.GraphicsDevice.Clear(Color.Black); + if (m_enemiesPaused == true) + Camera.GraphicsDevice.Clear(Color.White); + Camera.GraphicsDevice.Textures[1] = m_skyRenderTarget; + Camera.GraphicsDevice.Textures[1].GraphicsDevice.SamplerStates[1] = SamplerState.LinearClamp; + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, Game.ParallaxEffect); // Parallax Effect has been disabled in favour of ripple effect for now. + if (m_enemiesPaused == false) + Camera.Draw(m_bgRenderTarget, Vector2.Zero, Color.White); + Camera.End(); + ////////////////////////////////////////////////////// + + //////// DRAWING FOREGROUND/////////// + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, RasterizerState.CullNone, Game.BWMaskEffect, Camera.GetTransformation()); + Camera.GraphicsDevice.Textures[1] = m_fgRenderTarget; + Camera.GraphicsDevice.Textures[1].GraphicsDevice.SamplerStates[1] = SamplerState.PointClamp; + Camera.Draw(CurrentRoom.BGRender, Camera.TopLeftCorner, Color.White); + Camera.End(); + /////////////////////////////////////////// + + //////// IMPORTANT!!!! ////////////////// + // At this point in time, m_fgRenderTarget, m_bgRenderTarget, and m_skyRenderTarget are no longer needed. + // They can now be (and should be) re-used for whatever rendertarget processes you need. + // This will cut down immensely on the render targets needed for the game. + //////////////////////////////////////// + + ////// DRAWING ACTUAL LEVEL /////////////////////////////////// + if (LevelEV.SHOW_ENEMY_RADII == false) + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, null, null, null, Camera.GetTransformation()); // Set SpriteSortMode to immediate to allow instant changes to samplerstates. + else + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, null, null, null, Camera.GetTransformation()); + // IT is currently necessary to draw all rooms for debug purposes. + //if (CurrentRoom != null && Camera.Zoom == 1 && (m_inputMap.Pressed(INPUT_LEFTCONTROL) == false || (m_inputMap.Pressed(INPUT_LEFTCONTROL) == true && LevelEV.RUN_DEMO_VERSION == true))) + CurrentRoom.Draw(Camera); + //else + //{ + // foreach (RoomObj room in m_roomList) + // room.Draw(Camera); + //} + + + if (LevelEV.SHOW_ENEMY_RADII == true) + { + foreach (EnemyObj enemy in m_currentRoom.EnemyList) + { + enemy.DrawDetectionRadii(Camera); + } + } + + m_projectileManager.Draw(Camera); + + if (m_enemiesPaused == true) + { + Camera.End(); + //Camera.GraphicsDevice.SetRenderTarget(m_invertRenderTarget); // Removing m_invertRenderTarget by re-using m_bgRenderTarget. + Camera.GraphicsDevice.SetRenderTarget(m_bgRenderTarget); + Camera.GraphicsDevice.Textures[1] = m_traitAuraRenderTarget; + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, Game.InvertShader); + Camera.Draw(m_finalRenderTarget, Vector2.Zero, Color.White); + Camera.End(); + + Game.HSVEffect.Parameters["Saturation"].SetValue(0); + Game.HSVEffect.Parameters["UseMask"].SetValue(true); + Camera.GraphicsDevice.SetRenderTarget(m_finalRenderTarget); + Camera.GraphicsDevice.Textures[1] = m_traitAuraRenderTarget; + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, Game.HSVEffect); + Camera.Draw(m_bgRenderTarget, Vector2.Zero, Color.White); + //Camera.Draw(m_invertRenderTarget, Vector2.Zero, Color.White); // Removing m_invertRenderTarget by re-using m_bgRenderTarget. + //Camera.End(); + } + + Camera.End(); + + if (m_toggleMagentaBG == true) + Camera.GraphicsDevice.Clear(Color.Magenta); + // SpriteSortMode changed to deferred. + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, Camera.GetTransformation()); + + ////// Death animation sprites. + Camera.Draw(Game.GenericTexture, new Rectangle((int)Camera.TopLeftCorner.X, (int)Camera.TopLeftCorner.Y, 1320, 720), Color.Black * BackBufferOpacity); + + // Player + //Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + if (m_player.IsKilled == false) + m_player.Draw(Camera); + + if (LevelEV.CREATE_RETAIL_VERSION == false) + { + DebugTextObj.Position = new Vector2(Camera.X, Camera.Y - 300); + DebugTextObj.Draw(Camera); + } + + m_itemDropManager.Draw(Camera); + m_impactEffectPool.Draw(Camera); + Camera.End(); + + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearWrap, null, null, null, Camera.GetTransformation()); + //Camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap; + m_textManager.Draw(Camera); + + //// Special code for parallaxing the Garden FG. + if (CurrentRoom.LevelType == GameTypes.LevelType.TOWER) + { + //m_gardenParallaxFG.Position = CurrentRoom.Position - Camera.Position; + m_gardenParallaxFG.Draw(Camera); + } + + //Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + m_whiteBG.Draw(Camera); + + //ScreenManager.Camera.Draw_CameraBox(); + //m_physicsManager.DrawAllCollisionBoxes(Camera, Game.GenericTexture, Consts.TERRAIN_HITBOX); + //m_physicsManager.DrawAllCollisionBoxes(ScreenManager.Camera, Game.GenericTexture, Consts.WEAPON_HITBOX); + //m_physicsManager.DrawAllCollisionBoxes(ScreenManager.Camera, Game.GenericTexture, Consts.BODY_HITBOX); + + Camera.End(); + + /////////// DRAWING THE SHADOWS & LIGHTING ////////////////////////////// + if ((CurrentLevelType == GameTypes.LevelType.DUNGEON || Game.PlayerStats.Traits.X == TraitType.Glaucoma || Game.PlayerStats.Traits.Y == TraitType.Glaucoma) + && (Game.PlayerStats.Class != ClassType.Banker2 || (Game.PlayerStats.Class == ClassType.Banker2 && Player.LightOn == false))) + { + // Can't do this because switching from a rendertarget and back is a bug in XNA that causes a purple screen. Might work with Monogame. + //Camera.GraphicsDevice.SetRenderTarget(m_bgRenderTarget); + //Camera.GraphicsDevice.Clear(Color.Black); + //Camera.GraphicsDevice.SetRenderTarget(m_finalRenderTarget); + Camera.GraphicsDevice.Textures[1] = m_lightSourceRenderTarget; + Camera.GraphicsDevice.Textures[1].GraphicsDevice.SamplerStates[1] = SamplerState.LinearClamp; + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, Game.ShadowEffect); + if (LevelEV.SAVE_FRAMES == true) + Camera.Draw(m_shadowRenderTarget, Vector2.Zero, null, Color.White, 0, Vector2.Zero, new Vector2(2, 2), SpriteEffects.None, 1); + else + Camera.Draw(m_shadowRenderTarget, Vector2.Zero, Color.White); + Camera.End(); + } + + // Myopia effect. + if (CurrentRoom.Name != "Ending") + { + if ((Game.PlayerStats.Traits.X == TraitType.NearSighted || Game.PlayerStats.Traits.Y == TraitType.NearSighted) && Game.PlayerStats.SpecialItem != SpecialItemType.Glasses) + { + Game.GaussianBlur.InvertMask = true; + Game.GaussianBlur.Draw(m_finalRenderTarget, Camera, m_traitAuraRenderTarget); + } + // Hyperopia effect. + else if ((Game.PlayerStats.Traits.X == TraitType.FarSighted || Game.PlayerStats.Traits.Y == TraitType.FarSighted) && Game.PlayerStats.SpecialItem != SpecialItemType.Glasses) + { + Game.GaussianBlur.InvertMask = false; + Game.GaussianBlur.Draw(m_finalRenderTarget, Camera, m_traitAuraRenderTarget); + } + } + + /////////// DRAWING MINIMAP & ENEMY HUD////////////////////////////////// + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearWrap, null, null); + + m_projectileIconPool.Draw(Camera); + + m_playerHUD.Draw(Camera); + + if (m_lastEnemyHit != null && m_enemyHUDCounter > 0) + m_enemyHUD.Draw(Camera); + + if (m_enemyHUDCounter > 0) + m_enemyHUDCounter -= (float)gameTime.ElapsedGameTime.TotalSeconds; + + if (CurrentRoom.Name != "Start" && CurrentRoom.Name != "Boss" && CurrentRoom.Name != "ChallengeBoss" && m_miniMapDisplay.Visible == true) + { + m_mapBG.Draw(Camera); + m_miniMapDisplay.Draw(Camera); + } + + if (CurrentRoom.Name != "Boss" && CurrentRoom.Name != "Ending") + { + m_compassBG.Draw(Camera); + m_compass.Draw(Camera); + } + + m_objectivePlate.Draw(Camera); + m_roomEnteringTitle.Draw(Camera); + m_roomTitle.Draw(Camera); + + if (CurrentRoom.Name != "Ending") + { + if ((Game.PlayerStats.TutorialComplete == false || Game.PlayerStats.Traits.X == TraitType.Nostalgic || Game.PlayerStats.Traits.Y == TraitType.Nostalgic) && Game.PlayerStats.SpecialItem != SpecialItemType.Glasses) + m_filmGrain.Draw(Camera); + } + Camera.End(); + + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); + m_blackBorder1.Draw(Camera); + m_blackBorder2.Draw(Camera); + + Camera.End(); + ////////////////////////////////////////////////////////////// + + // This is where you apply all the rendertarget effects. + + // Applying the Fus Ro Dah ripple effect, applying it to m_finalRenderTarget, and saving it to another RT. + //Camera.GraphicsDevice.SetRenderTarget(m_rippleRenderTarget); + Camera.GraphicsDevice.SetRenderTarget(m_bgRenderTarget); + Game.RippleEffect.Parameters["width"].SetValue(ShoutMagnitude); + + Vector2 playerPos = m_player.Position - Camera.TopLeftCorner; + if (Game.PlayerStats.Class == ClassType.Barbarian || Game.PlayerStats.Class == ClassType.Barbarian2) + { + Game.RippleEffect.Parameters["xcenter"].SetValue(playerPos.X / 1320f); + Game.RippleEffect.Parameters["ycenter"].SetValue(playerPos.Y / 720f); + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, Game.RippleEffect); + } + else + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null); + + Camera.Draw(m_finalRenderTarget, Vector2.Zero, Color.White); + Camera.End(); + + // Changing to the final Screen manager RenderTarget. This is where the final drawing goes. + Camera.GraphicsDevice.SetRenderTarget((ScreenManager as RCScreenManager).RenderTarget); + + if (CurrentRoom.Name != "Ending") + { + // Colour blind effect. + if ((Game.PlayerStats.Traits.X == TraitType.ColorBlind || Game.PlayerStats.Traits.Y == TraitType.ColorBlind) && Game.PlayerStats.SpecialItem != SpecialItemType.Glasses) + { + Game.HSVEffect.Parameters["Saturation"].SetValue(0); + Game.HSVEffect.Parameters["Brightness"].SetValue(0); + Game.HSVEffect.Parameters["Contrast"].SetValue(0); + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, Game.HSVEffect); + } + else if ((Game.PlayerStats.TutorialComplete == false || Game.PlayerStats.Traits.X == TraitType.Nostalgic || Game.PlayerStats.Traits.Y == TraitType.Nostalgic) && Game.PlayerStats.SpecialItem != SpecialItemType.Glasses) + { + Camera.GraphicsDevice.SetRenderTarget(m_finalRenderTarget); + Game.HSVEffect.Parameters["Saturation"].SetValue(0.2f); + Game.HSVEffect.Parameters["Brightness"].SetValue(0.1f); + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, Game.HSVEffect); + Camera.Draw(m_bgRenderTarget, Vector2.Zero, Color.White); + Camera.End(); + + Camera.GraphicsDevice.SetRenderTarget(m_bgRenderTarget); + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null); + Color sepia = new Color(180, 150, 80); + Camera.Draw(m_finalRenderTarget, Vector2.Zero, sepia); + m_creditsText.Draw(Camera); + m_creditsTitleText.Draw(Camera); + Camera.End(); + + Camera.GraphicsDevice.SetRenderTarget((ScreenManager as RCScreenManager).RenderTarget); + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null); + } + else + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null); + } + else + Camera.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null); + + Camera.Draw(m_bgRenderTarget, Vector2.Zero, Color.White); + + Camera.End(); + + base.Draw(gameTime); // Doesn't do anything. + } + + public void RunWhiteSlashEffect() + { + m_whiteBG.Position = CurrentRoom.Position; + m_whiteBG.Scale = Vector2.One; + m_whiteBG.Scale = new Vector2(CurrentRoom.Width / m_whiteBG.Width, m_currentRoom.Height / m_whiteBG.Height); + m_whiteBG.Opacity = 1; + Tween.To(m_whiteBG, 0.2f, Tween.EaseNone, "Opacity", "0"); + Tween.RunFunction(0.2f, this, "RunWhiteSlash2"); + } + + public void RunWhiteSlash2() + { + m_whiteBG.Position = CurrentRoom.Position; + m_whiteBG.Scale = Vector2.One; + m_whiteBG.Scale = new Vector2(CurrentRoom.Width / m_whiteBG.Width, m_currentRoom.Height / m_whiteBG.Height); + m_whiteBG.Opacity = 1; + Tween.To(m_whiteBG, 0.2f, Tween.EaseNone, "Opacity", "0"); + } + + // Same as RunWhiteSlash but calls a different sfx. + public void LightningEffectTwice() + { + m_whiteBG.Position = CurrentRoom.Position; + m_whiteBG.Scale = Vector2.One; + m_whiteBG.Scale = new Vector2(CurrentRoom.Width / m_whiteBG.Width, m_currentRoom.Height / m_whiteBG.Height); + m_whiteBG.Opacity = 1; + Tween.To(m_whiteBG, 0.2f, Tween.EaseNone, "Opacity", "0"); + Tween.RunFunction(0.2f, this, "LightningEffectOnce"); + } + + public void LightningEffectOnce() + { + m_whiteBG.Position = CurrentRoom.Position; + m_whiteBG.Scale = Vector2.One; + m_whiteBG.Scale = new Vector2(CurrentRoom.Width / m_whiteBG.Width, m_currentRoom.Height / m_whiteBG.Height); + m_whiteBG.Opacity = 1; + Tween.To(m_whiteBG, 1, Tween.EaseNone, "Opacity", "0"); + SoundManager.PlaySound("LightningClap1", "LightningClap2"); + } + + public void SpawnDementiaEnemy() + { + List enemyObjList = new List(); + + foreach (EnemyObj enemy in m_currentRoom.EnemyList) + { + if (enemy.Type != EnemyType.Turret && enemy.Type != EnemyType.SpikeTrap && enemy.Type != EnemyType.Platform && + enemy.Type != EnemyType.Portrait && enemy.Type != EnemyType.Eyeball && enemy.Type != EnemyType.Starburst) + enemyObjList.Add(enemy); + } + + if (enemyObjList.Count > 0) + { + EnemyObj enemy = enemyObjList[CDGMath.RandomInt(0, enemyObjList.Count - 1)]; + byte[] enemyList = null; + + if (enemy.IsWeighted == true) + enemyList = LevelEV.DEMENTIA_GROUND_LIST; + else + enemyList = LevelEV.DEMENTIA_FLIGHT_LIST; + + EnemyObj newEnemy = EnemyBuilder.BuildEnemy(enemyList[CDGMath.RandomInt(0, enemyList.Length - 1)], null, null, null, GameTypes.EnemyDifficulty.BASIC, true); + newEnemy.Position = enemy.Position; // Make sure this is set before calling AddEnemyToCurrentRoom() + newEnemy.SaveToFile = false; + newEnemy.IsDemented = true; + newEnemy.NonKillable = true; + newEnemy.GivesLichHealth = false; + AddEnemyToCurrentRoom(newEnemy); + } + } + + public void AddEnemyToCurrentRoom(EnemyObj enemy) + { + //m_currentRoom.EnemyList.Add(enemy); + m_currentRoom.TempEnemyList.Add(enemy); // Add enemy to the temp list instead of the real one. + m_physicsManager.AddObject(enemy); + //m_enemyStartPositions.Add(enemy.Position); + m_tempEnemyStartPositions.Add(enemy.Position); + enemy.SetPlayerTarget(m_player); + enemy.SetLevelScreen(this); + enemy.Initialize(); + } + + public void RemoveEnemyFromCurrentRoom(EnemyObj enemy, Vector2 startingPos) + { + m_currentRoom.TempEnemyList.Remove(enemy); + m_physicsManager.RemoveObject(enemy); + m_tempEnemyStartPositions.Remove(startingPos); + } + + public void RemoveEnemyFromRoom(EnemyObj enemy, RoomObj room, Vector2 startingPos) + { + room.TempEnemyList.Remove(enemy); + m_physicsManager.RemoveObject(enemy); + m_tempEnemyStartPositions.Remove(startingPos); + } + + public void RemoveEnemyFromRoom(EnemyObj enemy, RoomObj room) + { + int enemyIndex = room.TempEnemyList.IndexOf(enemy); + if (enemyIndex != -1) + { + room.TempEnemyList.RemoveAt(enemyIndex); + m_physicsManager.RemoveObject(enemy); + m_tempEnemyStartPositions.RemoveAt(enemyIndex); + } + } + + public void ResetEnemyPositions() + { + for (int i = 0; i < m_enemyStartPositions.Count; i++) + CurrentRoom.EnemyList[i].Position = m_enemyStartPositions[i]; + + for (int i = 0; i < m_tempEnemyStartPositions.Count; i++) + CurrentRoom.TempEnemyList[i].Position = m_tempEnemyStartPositions[i]; + } + + public override void PauseScreen() + { + if (this.IsPaused == false) + { + Tweener.Tween.PauseAll(); + CurrentRoom.PauseRoom(); + ItemDropManager.PauseAllAnimations(); + m_impactEffectPool.PauseAllAnimations(); + if (m_enemiesPaused == false) // Only pause the projectiles if they aren't already paused via time stop. + m_projectileManager.PauseAllProjectiles(true); + SoundManager.PauseAllSounds("Pauseable"); + + m_player.PauseAnimation(); + GamePad.SetVibration(PlayerIndex.One, 0, 0); + + base.PauseScreen(); + } + } + + public override void UnpauseScreen() + { + if (this.IsPaused == true) + { + Tweener.Tween.ResumeAll(); + CurrentRoom.UnpauseRoom(); + ItemDropManager.ResumeAllAnimations(); + m_impactEffectPool.ResumeAllAnimations(); + if (m_enemiesPaused == false) // Only unpause all projectiles if enemies are paused. + m_projectileManager.UnpauseAllProjectiles(); + SoundManager.ResumeAllSounds("Pauseable"); + + m_player.ResumeAnimation(); + base.UnpauseScreen(); + } + } + + public void RunGameOver() + { + m_player.Opacity = 1; + m_killedEnemyObjList.Clear(); + List enemiesKilledInRun = Game.PlayerStats.EnemiesKilledInRun; + + int roomSize = m_roomList.Count; + for (int i = 0; i < enemiesKilledInRun.Count; i++) + { + if (enemiesKilledInRun[i].X != -1 && enemiesKilledInRun[i].Y != -1) + { + if ((int)enemiesKilledInRun[i].X < roomSize) + { + RoomObj room = m_roomList[(int)enemiesKilledInRun[i].X]; + int numEnemies = room.EnemyList.Count; + if ((int)enemiesKilledInRun[i].Y < numEnemies) + { + EnemyObj enemy = m_roomList[(int)enemiesKilledInRun[i].X].EnemyList[(int)enemiesKilledInRun[i].Y]; + m_killedEnemyObjList.Add(enemy); + } + } + } + + //EnemyObj enemy = m_roomList[(int)enemiesKilledInRun[i].X].EnemyList[(int)enemiesKilledInRun[i].Y]; + //m_killedEnemyObjList.Add(enemy); + } + + List dataList = new List(); + dataList.Add(m_player); + dataList.Add(m_killedEnemyObjList); + dataList.Add(m_coinsCollected); + dataList.Add(m_bagsCollected); + dataList.Add(m_diamondsCollected); + dataList.Add(m_bigDiamondsCollected); + dataList.Add(m_objKilledPlayer); + + Tween.RunFunction(0, ScreenManager, "DisplayScreen", ScreenType.GameOver, true, dataList); + } + + public void RunCinematicBorders(float duration) + { + StopCinematicBorders(); + m_blackBorder1.Opacity = 1; + m_blackBorder2.Opacity = 1; + m_blackBorder1.Y = 0; + m_blackBorder2.Y = 720 - m_borderSize; + float fadeSpeed = 1f; + Tween.By(m_blackBorder1, fadeSpeed, Quad.EaseInOut, "delay", (duration - fadeSpeed).ToString(), "Y", (-m_borderSize).ToString()); + Tween.By(m_blackBorder2, fadeSpeed, Quad.EaseInOut, "delay", (duration - fadeSpeed).ToString(),"Y", m_borderSize.ToString()); + Tween.To(m_blackBorder1, fadeSpeed, Linear.EaseNone, "delay", (duration - fadeSpeed + 0.2f).ToString(), "Opacity", "0"); + Tween.To(m_blackBorder2, fadeSpeed, Linear.EaseNone, "delay", (duration - fadeSpeed + 0.2f).ToString(), "Opacity", "0"); + } + + public void StopCinematicBorders() + { + Tween.StopAllContaining(m_blackBorder1, false); + Tween.StopAllContaining(m_blackBorder2, false); + } + + public void DisplayMap(bool isTeleporterScreen) + { + //m_miniMapDisplay.AddAllRooms(m_roomList); + (ScreenManager as RCScreenManager).AddRoomsToMap(m_miniMapDisplay.AddedRoomsList); + if (isTeleporterScreen == true) + (ScreenManager as RCScreenManager).ActivateMapScreenTeleporter(); + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Map, true); + } + + public void PauseAllEnemies() + { + m_enemiesPaused = true; + CurrentRoom.PauseRoom(); + foreach (EnemyObj enemy in CurrentRoom.EnemyList) + enemy.PauseEnemy(); + + foreach (EnemyObj enemy in CurrentRoom.TempEnemyList) + enemy.PauseEnemy(); + + m_projectileManager.PauseAllProjectiles(false); + } + + public void CastTimeStop(float duration) + { + SoundManager.PlaySound("Cast_TimeStart"); + SoundManager.PauseMusic(); + m_enemyPauseDuration = duration; + PauseAllEnemies(); + Tween.To(m_traitAura, 0.2f, Tween.EaseNone, "ScaleX", "100", "ScaleY", "100"); + } + + public void StopTimeStop() + { + SoundManager.PlaySound("Cast_TimeStop"); + SoundManager.ResumeMusic(); + Tween.To(m_traitAura, 0.2f, Tween.EaseNone, "ScaleX", "0", "ScaleY", "0"); + Tween.AddEndHandlerToLastTween(this, "UnpauseAllEnemies"); + } + + public void UnpauseAllEnemies() + { + Game.HSVEffect.Parameters["UseMask"].SetValue(false); + m_enemiesPaused = false; + + CurrentRoom.UnpauseRoom(); + + foreach (EnemyObj enemy in CurrentRoom.EnemyList) + enemy.UnpauseEnemy(); + + foreach (EnemyObj enemy in CurrentRoom.TempEnemyList) + enemy.UnpauseEnemy(); + + m_projectileManager.UnpauseAllProjectiles(); + } + + public void DamageAllEnemies(int damage) + { + // Do temp enemies first otherwise one of them will get hit twice. + List tempEnemyList = new List(); // Necessary because TempEnemyList is a list that is continually modified. + tempEnemyList.AddRange(CurrentRoom.TempEnemyList); + foreach (EnemyObj enemy in tempEnemyList) + { + if (enemy.IsDemented == false && enemy.IsKilled == false) + enemy.HitEnemy(damage, enemy.Position, true); + } + + tempEnemyList.Clear(); + tempEnemyList = null; + + foreach (EnemyObj enemy in CurrentRoom.EnemyList) + { + if (enemy.IsDemented == false && enemy.IsKilled == false) + enemy.HitEnemy(damage, enemy.Position, true); + } + } + + public virtual void Reset() + { + BackBufferOpacity = 0; + + m_killedEnemyObjList.Clear(); + + m_bigDiamondsCollected = 0; + m_diamondsCollected = 0; + m_coinsCollected = 0; + m_bagsCollected = 0; + m_blueprintsCollected = 0; + + if (m_player != null) + { + m_player.Reset(); + m_player.ResetLevels(); + m_player.Position = new Vector2(200, 200); + //UpdatePlayerHUDHP(); + //UpdatePlayerHUDMP(); + } + + ResetEnemyPositions(); + + foreach (RoomObj room in m_roomList) + room.Reset(); + + InitializeChests(false); + + + foreach (RoomObj room in RoomList) + { + foreach (GameObj obj in room.GameObjList) + { + BreakableObj breakableObj = obj as BreakableObj; + if (breakableObj != null) + breakableObj.Reset(); + } + } + + m_projectileManager.DestroyAllProjectiles(true); + Game.ShadowEffect.Parameters["ShadowIntensity"].SetValue(0); + } + + public override void DisposeRTs() + { + m_fgRenderTarget.Dispose(); + m_fgRenderTarget = null; + m_bgRenderTarget.Dispose(); + m_bgRenderTarget = null; + m_skyRenderTarget.Dispose(); + m_skyRenderTarget = null; + m_finalRenderTarget.Dispose(); + m_finalRenderTarget = null; + + m_shadowRenderTarget.Dispose(); + m_shadowRenderTarget = null; + m_lightSourceRenderTarget.Dispose(); + m_lightSourceRenderTarget = null; + m_traitAuraRenderTarget.Dispose(); + m_traitAuraRenderTarget = null; + + m_foregroundSprite.Dispose(); + m_foregroundSprite = null; + m_backgroundSprite.Dispose(); + m_backgroundSprite = null; + m_backgroundParallaxSprite.Dispose(); + m_backgroundParallaxSprite = null; + m_gardenParallaxFG.Dispose(); + m_gardenParallaxFG = null; + + m_roomBWRenderTarget.Dispose(); + m_roomBWRenderTarget = null; + + m_miniMapDisplay.DisposeRTs(); + base.DisposeRTs(); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Procedural Level Screen"); + + Tween.StopAll(false); + + m_currentRoom = null; + DisposeRTs(); + foreach (RoomObj room in m_roomList) + room.Dispose(); + m_roomList.Clear(); + m_roomList = null; + m_enemyStartPositions.Clear(); + m_enemyStartPositions = null; + m_tempEnemyStartPositions.Clear(); + m_tempEnemyStartPositions = null; + m_textManager.Dispose(); + m_textManager = null; + //m_physicsManager.Dispose(); // Don't dispose the Physics manager since it's created in Game.cs and needs to remain persistent. + m_physicsManager = null; + m_projectileManager.Dispose(); + m_projectileManager = null; + m_itemDropManager.Dispose(); + m_itemDropManager = null; + m_currentRoom = null; + m_miniMapDisplay.Dispose(); + m_miniMapDisplay = null; + m_mapBG.Dispose(); + m_mapBG = null; + m_inputMap.Dispose(); + m_inputMap = null; + m_lastEnemyHit = null; + m_playerHUD.Dispose(); + m_playerHUD = null; + m_player = null; + m_enemyHUD.Dispose(); + m_enemyHUD = null; + m_impactEffectPool.Dispose(); + m_impactEffectPool = null; + + m_blackBorder1.Dispose(); + m_blackBorder1 = null; + m_blackBorder2.Dispose(); + m_blackBorder2 = null; + + m_chestList.Clear(); + m_chestList = null; + + m_projectileIconPool.Dispose(); + m_projectileIconPool = null; + + m_objKilledPlayer = null; + + m_dungeonLight.Dispose(); + m_dungeonLight = null; + m_traitAura.Dispose(); + m_traitAura = null; + + m_killedEnemyObjList.Clear(); + m_killedEnemyObjList = null; + + m_roomEnteringTitle.Dispose(); + m_roomEnteringTitle = null; + m_roomTitle.Dispose(); + m_roomTitle = null; + + m_creditsText.Dispose(); + m_creditsText = null; + m_creditsTitleText.Dispose(); + m_creditsTitleText = null; + Array.Clear(m_creditsTextTitleList, 0, m_creditsTextTitleList.Length); + Array.Clear(m_creditsTextList, 0, m_creditsTextList.Length); + m_creditsTextTitleList = null; + m_creditsTextList = null; + m_filmGrain.Dispose(); + m_filmGrain = null; + + m_objectivePlate.Dispose(); + m_objectivePlate = null; + m_objectivePlateTween = null; + + m_sky.Dispose(); + m_sky = null; + m_whiteBG.Dispose(); + m_whiteBG = null; + + m_compassBG.Dispose(); + m_compassBG = null; + m_compass.Dispose(); + m_compass = null; + + if (m_compassDoor != null) + m_compassDoor.Dispose(); + m_compassDoor = null; + + m_castleBorderTexture.Dispose(); + m_gardenBorderTexture.Dispose(); + m_towerBorderTexture.Dispose(); + m_dungeonBorderTexture.Dispose(); + m_neoBorderTexture.Dispose(); + + m_castleBorderTexture = null; + m_gardenBorderTexture = null; + m_towerBorderTexture = null; + m_dungeonBorderTexture = null; + + DebugTextObj.Dispose(); + DebugTextObj = null; + + base.Dispose(); // Sets the IsDisposed flag to true. + } + } + + public void SetLastEnemyHit(EnemyObj enemy) + { + m_lastEnemyHit = enemy; + m_enemyHUDCounter = m_enemyHUDDuration; + //m_enemyHUD.UpdateEnemyInfo(m_lastEnemyHit.Name, m_lastEnemyHit.Level, m_lastEnemyHit.CurrentHealth / (float)m_lastEnemyHit.MaxHealth); + m_enemyHUD.UpdateEnemyInfo(m_lastEnemyHit.LocStringID, m_lastEnemyHit.Level, m_lastEnemyHit.CurrentHealth / (float)m_lastEnemyHit.MaxHealth); + } + + public void KillEnemy(EnemyObj enemy) + { + if (enemy.SaveToFile == true) + { + Vector2 killedEnemy = new Vector2(m_roomList.IndexOf(CurrentRoom), CurrentRoom.EnemyList.IndexOf(enemy)); + + if (killedEnemy.X < 0 || killedEnemy.Y < 0) + throw new Exception("Could not find killed enemy in either CurrentRoom or CurrentRoom.EnemyList. This may be because the enemy was a blob"); + Game.PlayerStats.EnemiesKilledInRun.Add(killedEnemy); + } + } + + public void ItemDropCollected(int itemDropType) + { + switch (itemDropType) + { + case (ItemDropType.Coin): + m_coinsCollected++; + break; + case (ItemDropType.MoneyBag): + m_bagsCollected++; + break; + case (ItemDropType.Diamond): + m_diamondsCollected++; + break; + case(ItemDropType.BigDiamond): + m_bigDiamondsCollected++; + break; + case (ItemDropType.Blueprint): + case (ItemDropType.Redprint): + m_blueprintsCollected++; + break; + } + } + + public void RefreshMapChestIcons() + { + m_miniMapDisplay.RefreshChestIcons(CurrentRoom); + (ScreenManager as RCScreenManager).RefreshMapScreenChestIcons(CurrentRoom); + } + + public void DisplayObjective(string objectiveTitleID, string objectiveDescriptionID, string objectiveProgressID, bool tween) + { + //SoundManager.Play3DSound(this, Game.ScreenManager.Player,"FairyChest_Start"); + // Objective Lines. + (m_objectivePlate.GetChildAt(4) as SpriteObj).ScaleX = 0; + (m_objectivePlate.GetChildAt(5) as SpriteObj).ScaleX = 0; + + m_objectivePlate.GetChildAt(2).Opacity = 1f; + m_objectivePlate.GetChildAt(3).Opacity = 1f; + m_objectivePlate.X = 1170 + 300; + + if (m_objectivePlateTween != null && m_objectivePlateTween.TweenedObject == m_objectivePlate && m_objectivePlateTween.Active == true) + m_objectivePlateTween.StopTween(false); + + (m_objectivePlate.GetChildAt(1) as TextObj).Text = LocaleBuilder.getString(objectiveTitleID, m_objectivePlate.GetChildAt(1) as TextObj); + (m_objectivePlate.GetChildAt(2) as TextObj).Text = LocaleBuilder.getString(objectiveDescriptionID, m_objectivePlate.GetChildAt(2) as TextObj); + (m_objectivePlate.GetChildAt(3) as TextObj).Text = LocaleBuilder.getString(objectiveProgressID, m_objectivePlate.GetChildAt(3) as TextObj); + + if (tween == true) + m_objectivePlateTween = Tween.By(m_objectivePlate, 0.5f, Back.EaseOut, "X", "-300"); + else + m_objectivePlate.X -= 300; + } + + public void ResetObjectivePlate(bool tween) + { + if (m_objectivePlate != null) + { + m_objectivePlate.X = 1170; + + if (m_objectivePlateTween != null && m_objectivePlateTween.TweenedObject == m_objectivePlate && m_objectivePlateTween.Active == true) + m_objectivePlateTween.StopTween(false); + + if (tween == true) + Tween.By(m_objectivePlate, 0.5f, Back.EaseIn, "X", "300"); + else + m_objectivePlate.X += 300; + } + } + + // progress parameter is actual display string + public void UpdateObjectiveProgress(string progress) + { + (m_objectivePlate.GetChildAt(3) as TextObj).Text = progress; + } + + public void ObjectiveFailed() + { + (m_objectivePlate.GetChildAt(1) as TextObj).Text = LocaleBuilder.getString("LOC_ID_LEVEL_SCREEN_6", m_objectivePlate.GetChildAt(1) as TextObj); //"Objective Failed" + m_objectivePlate.GetChildAt(2).Opacity = 0.3f; + m_objectivePlate.GetChildAt(3).Opacity = 0.3f; + } + + public void ObjectiveComplete() + { + // objective lines + //Tween.By(m_objectivePlate.GetChildAt(4), 0.3f, Tween.EaseNone, "ScaleX", (m_objectivePlate.GetChildAt(2).Width / 5).ToString()); + //if ((m_objectivePlate.GetChildAt(3) as TextObj).Text != "") + // Tween.By(m_objectivePlate.GetChildAt(5), 0.3f, Tween.EaseNone, "delay", "0.2", "ScaleX", (m_objectivePlate.GetChildAt(3).Width / 5).ToString()); + + m_objectivePlate.GetChildAt(2).Opacity = 0.3f; + m_objectivePlate.GetChildAt(3).Opacity = 0.3f; + + m_objectivePlate.X = 1170; + + if (m_objectivePlateTween != null && m_objectivePlateTween.TweenedObject == m_objectivePlate && m_objectivePlateTween.Active == true) + m_objectivePlateTween.StopTween(false); + + (m_objectivePlate.GetChildAt(1) as TextObj).Text = LocaleBuilder.getString("LOC_ID_LEVEL_SCREEN_5", m_objectivePlate.GetChildAt(1) as TextObj); //"Objective Complete!" + //m_objectivePlateTween = Tween.By(m_objectivePlate, 0.5f, Back.EaseIn, "delay", "1", "X", "300"); + } + + public override void OnEnter() + { + (ScreenManager.Game as Game).SaveManager.ResetAutosave(); + m_player.DisableAllWeight = false; // Fixes bug where you translocate right before enter the castle, resulting in screwed up gravity. + m_player.StopAllSpells(); + StopScreenShake(); + + ShoutMagnitude = 3; + + // Setting up player. + if (Game.PlayerStats.Traits.X == TraitType.Gigantism || Game.PlayerStats.Traits.Y == TraitType.Gigantism) + m_player.Scale = new Vector2(GameEV.TRAIT_GIGANTISM, GameEV.TRAIT_GIGANTISM);//(3.5f, 3.5f); + else if (Game.PlayerStats.Traits.X == TraitType.Dwarfism || Game.PlayerStats.Traits.Y == TraitType.Dwarfism) + m_player.Scale = new Vector2(GameEV.TRAIT_DWARFISM, GameEV.TRAIT_DWARFISM); + else + m_player.Scale = new Vector2(2, 2); + + // Modifying the player's scale based on traits. + if (Game.PlayerStats.Traits.X == TraitType.Ectomorph || Game.PlayerStats.Traits.Y == TraitType.Ectomorph) + { + m_player.ScaleX *= 0.825f; + m_player.ScaleY *= 1.15f; + //m_player.Scale = new Vector2(1.8f, 2.2f); + } + else if (Game.PlayerStats.Traits.X == TraitType.Endomorph || Game.PlayerStats.Traits.Y == TraitType.Endomorph) + { + m_player.ScaleX *= 1.25f; + m_player.ScaleY *= 1.175f; + //m_player.Scale = new Vector2(2.5f, 2f); + } + + if (Game.PlayerStats.Traits.X == TraitType.Clonus || Game.PlayerStats.Traits.Y == TraitType.Clonus) + { + m_elapsedScreenShake = CDGMath.RandomFloat(GameEV.TRAIT_CLONUS_MIN, GameEV.TRAIT_CLONUS_MAX); + } + + m_player.CurrentHealth = Game.PlayerStats.CurrentHealth; + m_player.CurrentMana = Game.PlayerStats.CurrentMana; + + if (LevelEV.RUN_TESTROOM == true) + { + Game.ScreenManager.Player.CurrentHealth = Game.ScreenManager.Player.MaxHealth; + Game.ScreenManager.Player.CurrentMana = Game.ScreenManager.Player.MaxMana; + } + + m_player.UpdateInternalScale(); + + CheckForRoomTransition(); + UpdateCamera(); + UpdatePlayerHUDAbilities(); + m_player.UpdateEquipmentColours(); + m_player.StopAllSpells(); + + // Adding treasure chest icons to map for Spelunker. + if (Game.PlayerStats.Class == ClassType.Banker2) + { + m_miniMapDisplay.AddAllIcons(this.RoomList); + (ScreenManager as RCScreenManager).AddIconsToMap(this.RoomList); + } + + //// Adding teleporters to all bosses already beaten. + //if (Game.PlayerStats.EyeballBossBeaten) + // m_miniMapDisplay.AddLinkerRoom(GameTypes.LevelType.CASTLE, this.RoomList); + //if (Game.PlayerStats.FairyBossBeaten) + // m_miniMapDisplay.AddLinkerRoom(GameTypes.LevelType.GARDEN, this.RoomList); + //if (Game.PlayerStats.FireballBossBeaten) + // m_miniMapDisplay.AddLinkerRoom(GameTypes.LevelType.TOWER, this.RoomList); + //if (Game.PlayerStats.BlobBossBeaten) + // m_miniMapDisplay.AddLinkerRoom(GameTypes.LevelType.DUNGEON, this.RoomList); + + if (Game.PlayerStats.EyeballBossBeaten == true) + GameUtil.UnlockAchievement("FEAR_OF_EYES"); + if (Game.PlayerStats.FairyBossBeaten == true) + GameUtil.UnlockAchievement("FEAR_OF_GHOSTS"); + if (Game.PlayerStats.BlobBossBeaten == true) + GameUtil.UnlockAchievement("FEAR_OF_SLIME"); + if (Game.PlayerStats.FireballBossBeaten == true) + GameUtil.UnlockAchievement("FEAR_OF_FIRE"); + if (Game.PlayerStats.LastbossBeaten == true || Game.PlayerStats.TimesCastleBeaten > 0) + GameUtil.UnlockAchievement("FEAR_OF_FATHERS"); + if (Game.PlayerStats.TimesCastleBeaten > 1) + GameUtil.UnlockAchievement("FEAR_OF_TWINS"); + + if (Game.PlayerStats.ChallengeEyeballBeaten == true) + GameUtil.UnlockAchievement("FEAR_OF_BLINDNESS"); + if (Game.PlayerStats.ChallengeSkullBeaten == true) + GameUtil.UnlockAchievement("FEAR_OF_BONES"); + if (Game.PlayerStats.ChallengeFireballBeaten == true) + GameUtil.UnlockAchievement("FEAR_OF_CHEMICALS"); + if (Game.PlayerStats.ChallengeBlobBeaten == true) + GameUtil.UnlockAchievement("FEAR_OF_SPACE"); + if (Game.PlayerStats.ChallengeLastBossBeaten == true) + GameUtil.UnlockAchievement("FEAR_OF_RELATIVES"); + + bool skeletonMBKilled = false; + bool plantMBKilled = false; + bool paintingMBKilled = false; + bool knightMBKilled = false; + bool wizardMBKilled = false; + if (Game.PlayerStats.EnemiesKilledList[EnemyType.Skeleton].W > 0) + skeletonMBKilled = true; + if (Game.PlayerStats.EnemiesKilledList[EnemyType.Plant].W > 0) + plantMBKilled = true; + if (Game.PlayerStats.EnemiesKilledList[EnemyType.Portrait].W > 0) + paintingMBKilled = true; + if (Game.PlayerStats.EnemiesKilledList[EnemyType.Knight].W > 0) + knightMBKilled = true; + if (Game.PlayerStats.EnemiesKilledList[EnemyType.EarthWizard].W > 0) + wizardMBKilled = true; + + if (skeletonMBKilled && plantMBKilled && paintingMBKilled && knightMBKilled && wizardMBKilled) + GameUtil.UnlockAchievement("FEAR_OF_ANIMALS"); + + if ((Game.PlayerStats.TotalHoursPlayed + Game.HoursPlayedSinceLastSave) >= 20) + GameUtil.UnlockAchievement("FEAR_OF_SLEEP"); + + if (Game.PlayerStats.TotalRunesFound > 10) + GameUtil.UnlockAchievement("LOVE_OF_MAGIC"); + + base.OnEnter(); + } + + public override void OnExit() + { + StopScreenShake(); + if (m_currentRoom != null) + m_currentRoom.OnExit(); // Call on exit if exiting from a room. + + SoundManager.StopAllSounds("Default"); + SoundManager.StopAllSounds("Pauseable"); + base.OnExit(); + } + + public void RevealMorning() + { + m_sky.MorningOpacity = 0; + Tween.To(m_sky, 2, Tween.EaseNone, "MorningOpacity", "1"); + } + + public void ZoomOutAllObjects() + { + Vector2 centrePt = new Vector2(CurrentRoom.Bounds.Center.X, CurrentRoom.Bounds.Center.Y); + List objPositions = new List(); + float delay = 0; + + foreach (GameObj obj in CurrentRoom.GameObjList) + { + int zoomXAmount = 0; + int zoomYAmount = 0; + + if (obj.Y < centrePt.Y) + zoomYAmount = CurrentRoom.Bounds.Top - (int)(obj.Bounds.Top + obj.Bounds.Height); + else + zoomYAmount = CurrentRoom.Bounds.Bottom - (int)(obj.Bounds.Top); + + if (obj.X < centrePt.X) + zoomXAmount = (int)(CurrentRoom.Bounds.Left - (obj.Bounds.Left + obj.Bounds.Width)); + else + zoomXAmount = (int)(CurrentRoom.Bounds.Right - (obj.Bounds.Left)); + + if (Math.Abs(zoomXAmount) > Math.Abs(zoomYAmount)) + { + objPositions.Add(new Vector2(0, zoomYAmount)); + Tween.By(obj, 0.5f, Back.EaseIn, "delay", delay.ToString(), "Y", zoomYAmount.ToString()); + } + else + { + objPositions.Add(new Vector2(zoomXAmount, 0)); + Tween.By(obj, 0.5f, Back.EaseIn, "delay", delay.ToString(), "X", zoomXAmount.ToString()); + } + delay += 0.05f; + } + Tween.RunFunction(delay + 0.5f, this, "ZoomInAllObjects", objPositions); + //Tween.AddEndHandlerToLastTween(this, "ZoomInAllObjects", objPositions); + } + + public void ZoomInAllObjects(List objPositions) + { + int counter = 0; + float delay = 1; + foreach (GameObj obj in CurrentRoom.GameObjList) + { + Tween.By(obj, 0.5f, Back.EaseOut,"delay", delay.ToString(), "X", (-objPositions[counter].X).ToString(), "Y", (-objPositions[counter].Y).ToString()); + counter++; + delay += 0.05f; + } + } + + public void UpdateLevel(GameTypes.LevelType levelType) + { + switch (levelType) + { + case (GameTypes.LevelType.CASTLE): + m_backgroundSprite.Scale = Vector2.One; + m_foregroundSprite.Scale = Vector2.One; + m_backgroundSprite.ChangeSprite("CastleBG1_Sprite", ScreenManager.Camera); + m_foregroundSprite.ChangeSprite("CastleFG1_Sprite", ScreenManager.Camera); + m_backgroundSprite.Scale = new Vector2(2, 2); + m_foregroundSprite.Scale = new Vector2(2, 2); + break; + case (GameTypes.LevelType.TOWER): + m_backgroundSprite.Scale = Vector2.One; + m_foregroundSprite.Scale = Vector2.One; + m_backgroundSprite.ChangeSprite("TowerBG2_Sprite", ScreenManager.Camera); + m_foregroundSprite.ChangeSprite("TowerFG2_Sprite", ScreenManager.Camera); + m_backgroundSprite.Scale = new Vector2(2, 2); + m_foregroundSprite.Scale = new Vector2(2, 2); + break; + case (GameTypes.LevelType.DUNGEON): + m_backgroundSprite.Scale = Vector2.One; + m_foregroundSprite.Scale = Vector2.One; + m_backgroundSprite.ChangeSprite("DungeonBG1_Sprite", ScreenManager.Camera); + m_foregroundSprite.ChangeSprite("DungeonFG1_Sprite", ScreenManager.Camera); + m_backgroundSprite.Scale = new Vector2(2, 2); + m_foregroundSprite.Scale = new Vector2(2, 2); + break; + case (GameTypes.LevelType.GARDEN): + m_backgroundSprite.Scale = Vector2.One; + m_foregroundSprite.Scale = Vector2.One; + m_backgroundSprite.ChangeSprite("GardenBG_Sprite", ScreenManager.Camera); + m_foregroundSprite.ChangeSprite("GardenFG_Sprite", ScreenManager.Camera); + m_backgroundSprite.Scale = new Vector2(2, 2); + m_foregroundSprite.Scale = new Vector2(2, 2); + break; + } + + // Setting shadow intensity. + if (levelType == GameTypes.LevelType.DUNGEON) + Game.ShadowEffect.Parameters["ShadowIntensity"].SetValue(0.7f); + else + Game.ShadowEffect.Parameters["ShadowIntensity"].SetValue(0); + } + + private bool m_horizontalShake; + private bool m_verticalShake; + private bool m_shakeScreen; + private float m_screenShakeMagnitude; + + public void ShakeScreen(float magnitude, bool horizontalShake = true, bool verticalShake = true) + { + m_screenShakeMagnitude = magnitude; + m_horizontalShake = horizontalShake; + m_verticalShake = verticalShake; + m_shakeScreen = true; + } + + // This shake is specific to the Clonus trait. + public void UpdateShake() + { + if (m_horizontalShake == true) + Player.AttachedLevel.Camera.X += CDGMath.RandomPlusMinus() * (CDGMath.RandomFloat(0, 1) * m_screenShakeMagnitude); + + if (m_verticalShake == true) + Player.AttachedLevel.Camera.Y += CDGMath.RandomPlusMinus() * (CDGMath.RandomFloat(0, 1) * m_screenShakeMagnitude); + } + + public void StopScreenShake() + { + GamePad.SetVibration(PlayerIndex.One, 0, 0); + m_shakeScreen = false; + } + + public void RefreshPlayerHUDPos() + { + m_playerHUD.SetPosition(new Vector2(20, 40)); + } + + public void UpdatePlayerHUD() + { + m_playerHUD.Update(m_player); + } + + public void ForcePlayerHUDLevel(int level) + { + m_playerHUD.forcedPlayerLevel = level; + } + + public void UpdatePlayerHUDAbilities() + { + m_playerHUD.UpdateAbilityIcons(); + } + + public void UpdatePlayerHUDSpecialItem() + { + m_playerHUD.UpdateSpecialItemIcon(); + } + + public void UpdatePlayerSpellIcon() + { + m_playerHUD.UpdateSpellIcon(); + } + + public void SetMapDisplayVisibility(bool visible) + { + m_miniMapDisplay.Visible = visible; + } + + public void SetPlayerHUDVisibility(bool visible) + { + m_playerHUD.Visible = visible; + } + + public List MapRoomsUnveiled + { + get { return m_miniMapDisplay.AddedRoomsList; } + set + { + m_miniMapDisplay.ClearRoomsAdded(); + m_miniMapDisplay.AddAllRooms(value); + //(ScreenManager as RCScreenManager).AddRoomsToMap(value); + } + } + + public List MapRoomsAdded + { + get { return m_miniMapDisplay.AddedRoomsList; } + } + + public PlayerObj Player + { + get { return m_player; } + set { m_player = value; } + } + + public List RoomList + { + get { return m_roomList; } + } + + public PhysicsManager PhysicsManager + { + get { return m_physicsManager; } + } + + public RoomObj CurrentRoom + { + get { return m_currentRoom; } + } + + public ProjectileManager ProjectileManager + { + get { return m_projectileManager; } + } + + public List EnemyList + { + get { return CurrentRoom.EnemyList; } + } + + public List ChestList + { + get { return m_chestList; } + } + + public TextManager TextManager + { + get { return m_textManager; } + } + + public ImpactEffectPool ImpactEffectPool + { + get { return m_impactEffectPool; } + } + + public ItemDropManager ItemDropManager + { + get { return m_itemDropManager; } + } + + public GameTypes.LevelType CurrentLevelType + { + get { return m_currentRoom.LevelType; } + } + + public int LeftBorder + { + get { return m_leftMostBorder; } + } + + public int RightBorder + { + get { return m_rightMostBorder; } + } + + public int TopBorder + { + get { return m_topMostBorder; } + } + + public int BottomBorder + { + get { return m_bottomMostBorder; } + } + + public void SetObjectKilledPlayer(GameObj obj) + { + m_objKilledPlayer = obj; + } + + public RenderTarget2D RenderTarget + { + get { return m_finalRenderTarget; } + } + + public bool EnemiesPaused + { + get { return m_enemiesPaused; } + } + + public override void RefreshTextObjs() + { + foreach (RoomObj room in m_roomList) + room.RefreshTextObjs(); + + m_playerHUD.RefreshTextObjs(); + m_enemyHUD.RefreshTextObjs(); + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Screens/ProfileCardScreen.cs b/RogueCastle/src/Screens/ProfileCardScreen.cs new file mode 100644 index 0000000..49b5b33 --- /dev/null +++ b/RogueCastle/src/Screens/ProfileCardScreen.cs @@ -0,0 +1,1031 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Tweener; +using Tweener.Ease; +using InputSystem; +using Microsoft.Xna.Framework.Input; +using System.Text.RegularExpressions; + +namespace RogueCastle +{ + public class ProfileCardScreen : Screen + { + public float BackBufferOpacity { get; set; } + private ObjContainer m_frontCard; + private ObjContainer m_backCard; + + private PlayerHUDObj m_playerHUD; + + // Front card objects. + private TextObj m_playerName; + private TextObj m_money; + private TextObj m_levelClass; + private SpriteObj m_playerBG; + private TextObj m_frontTrait1; + private TextObj m_frontTrait2; + private TextObj m_author; + private TextObj m_playerStats; + private SpriteObj m_spellIcon; + private TextObj m_classDescription; + + // Back card objects. + private List m_dataList1, m_dataList2; + private TextObj m_equipmentTitle; + private TextObj m_runesTitle; + private List m_equipmentList; + private List m_runeBackTitleList; + private List m_runeBackDescriptionList; + + private ObjContainer m_playerSprite; + private SpriteObj m_tombStoneSprite; + private bool m_playerInAir = false; + + private Color m_skinColour1 = new Color(231, 175, 131, 255); + private Color m_skinColour2 = new Color(199, 109, 112, 255); + private Color m_lichColour1 = new Color(255, 255, 255, 255); + private Color m_lichColour2 = new Color(198, 198, 198, 255); + + private KeyIconTextObj m_cancelText; + + public ProfileCardScreen() + { + m_equipmentList = new List(); + m_runeBackTitleList = new List(); + m_runeBackDescriptionList = new List(); + } + + public override void LoadContent() + { + m_frontCard = new ObjContainer("CardFront_Character"); + m_frontCard.ForceDraw = true; + m_frontCard.Position = new Vector2(145, 30); + m_frontCard.GetChildAt(0).TextureColor = Color.Red; // BG + m_frontCard.GetChildAt(2).TextureColor = Color.Red; // Border + LoadFrontCard(); + + m_backCard = new ObjContainer("CardBack_Character"); + m_backCard.ForceDraw = true; + m_backCard.Position = new Vector2(m_frontCard.X + m_backCard.Width + 100, m_frontCard.Y); + m_backCard.AddChild(m_playerName.Clone() as GameObj); + m_backCard.GetChildAt(0).TextureColor = Color.Red; // BG + m_backCard.GetChildAt(2).TextureColor = Color.Red; // Border + LoadBackCard(); + + m_playerSprite = new ObjContainer("PlayerIdle_Character"); + m_playerSprite.ForceDraw = true; + m_playerSprite.Scale = new Vector2(2, 2); + m_playerSprite.OutlineWidth = 2; + + m_tombStoneSprite = new SpriteObj("Tombstone_Sprite"); + m_tombStoneSprite.ForceDraw = true; + m_tombStoneSprite.Scale = new Vector2(3, 3); + m_tombStoneSprite.OutlineWidth = 2; + + m_spellIcon = new SpriteObj(SpellType.Icon(12)); + m_spellIcon.Position = new Vector2(350, 295); + m_spellIcon.OutlineWidth = 2; + m_spellIcon.ForceDraw = true; + + m_cancelText = new KeyIconTextObj(Game.JunicodeFont); + m_cancelText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_cancelText); // dummy locID to add TextObj to language refresh list + m_cancelText.Align = Types.TextAlign.Right; + m_cancelText.DropShadow = new Vector2(2, 2); + m_cancelText.FontSize = 12; + m_cancelText.Position = new Vector2(1290, 650); + m_cancelText.ForceDraw = true; + + base.LoadContent(); + } + + private void LoadFrontCard() + { + TextObj templateText = new TextObj(Game.JunicodeFont); + templateText.Text = ""; + templateText.FontSize = 10; + templateText.ForceDraw = true; + templateText.TextureColor = Color.Black; + //templateText.DropShadow = new Vector2(2, 2); + + m_playerName = templateText.Clone() as TextObj; + m_playerName.Text = "Sir Archibald the IV"; + m_playerName.Position = new Vector2(50, 43); + m_frontCard.AddChild(m_playerName); + + m_money = templateText.Clone() as TextObj; + m_money.Position = new Vector2(m_frontCard.GetChildAt(3).X + 30, m_playerName.Y); // Child at index 3 is the coin icon. + m_money.Text = "0"; + m_frontCard.AddChild(m_money); + + m_levelClass = templateText.Clone() as TextObj; + m_levelClass.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_levelClass); // dummy locID to add TextObj to language refresh list + //m_levelClass.Position = new Vector2(m_playerName.X, 370); + m_levelClass.Position = new Vector2(m_playerName.X, 260); + m_frontCard.AddChild(m_levelClass); + + m_playerBG = new SpriteObj("CardDungeonBG_Sprite"); + //m_playerBG.Position = new Vector2(45, 80); + m_playerBG.Position = new Vector2(45, 220 + 80); + m_frontCard.AddChildAt(1, m_playerBG); + + m_playerHUD = new PlayerHUDObj(); + m_playerHUD.ForceDraw = true; + m_playerHUD.ShowBarsOnly = true; + //m_playerHUD.SetPosition(new Vector2(m_frontCard.X + 46, m_frontCard.Y + 64)); + m_playerHUD.SetPosition(new Vector2(m_frontCard.X + 46, m_frontCard.Y + 220 + 64)); + m_frontCard.AddChild(m_playerHUD); + + // Loading front card stats. + + m_frontTrait1 = new TextObj(Game.JunicodeFont); + m_frontTrait1.FontSize = 7; + m_frontTrait1.TextureColor = Color.Black; + //m_frontTrait1.Position = new Vector2(50, 550); + m_frontTrait1.Position = new Vector2(50, 550 - 320); + m_frontTrait1.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_frontTrait1); // dummy locID to add TextObj to language refresh list + m_frontCard.AddChild(m_frontTrait1); + + m_frontTrait2 = m_frontTrait1.Clone() as TextObj; + m_frontTrait2.Y -= 20; + m_frontTrait2.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_frontTrait2); // dummy locID to add TextObj to language refresh list + m_frontCard.AddChild(m_frontTrait2); + + m_classDescription = new TextObj(Game.JunicodeFont); + m_classDescription.FontSize = 8; + m_classDescription.TextureColor = Color.Black; + m_classDescription.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_classDescription); // dummy locID to add TextObj to language refresh list + //m_classDescription.Position = new Vector2(50, 410); + m_classDescription.Position = new Vector2(50, 410 - 320); + m_frontCard.AddChild(m_classDescription); + + m_author = new TextObj(Game.JunicodeFont); + m_author.FontSize = 8; + m_author.TextureColor = Color.White; + m_author.Text = "Glauber Kotaki"; + m_author.X = m_playerName.X; + m_author.Y = 590; + //m_frontCard.AddChild(m_author); + + m_playerStats = templateText.Clone() as TextObj; + m_playerStats.Text = "10/10"; + m_playerStats.Align = Types.TextAlign.Centre; + m_playerStats.Position = new Vector2(387, 579); + //m_frontCard.AddChild(m_playerStats); + } + + private void LoadBackCard() + { + TextObj templateText = new TextObj(Game.JunicodeFont); + templateText.Text = ""; + templateText.FontSize = 9; + templateText.ForceDraw = true; + templateText.TextureColor = Color.Black; + + m_dataList1 = new List(); + m_dataList2 = new List(); + + string[] list1LocIds = new string[] { "LOC_ID_PROFILE_CARD_SCREEN_1", "LOC_ID_PROFILE_CARD_SCREEN_2", "LOC_ID_PROFILE_CARD_SCREEN_3", "LOC_ID_PROFILE_CARD_SCREEN_4" }; + string[] list2LocIds = new string[] { "LOC_ID_PROFILE_CARD_SCREEN_5", "LOC_ID_PROFILE_CARD_SCREEN_6", "LOC_ID_PROFILE_CARD_SCREEN_7", "LOC_ID_PROFILE_CARD_SCREEN_8" }; + + int startingY = 90; + for (int i = 0; i < list1LocIds.Length; i++) + { + TextObj listTitle = templateText.Clone() as TextObj; + listTitle.Align = Types.TextAlign.Right; + listTitle.Text = LocaleBuilder.getString(list1LocIds[i], listTitle); + listTitle.Position = new Vector2(120, startingY); + m_backCard.AddChild(listTitle); + + TextObj listData = templateText.Clone() as TextObj; + listData.Text = "0"; + listData.Position = new Vector2(listTitle.X + 15, startingY); + m_dataList1.Add(listData); + m_backCard.AddChild(listData); + + TextObj listTitle2 = templateText.Clone() as TextObj; + listTitle2.Align = Types.TextAlign.Right; + listTitle2.Text = LocaleBuilder.getString(list2LocIds[i], listTitle2); + listTitle2.Position = new Vector2(350, startingY); + m_backCard.AddChild(listTitle2); + + TextObj listData2 = templateText.Clone() as TextObj; + listData2.Text = "0"; + listData2.Position = new Vector2(listTitle2.X + 15, startingY); + m_dataList2.Add(listData2); + m_backCard.AddChild(listData2); + + startingY += 20; + } + + m_equipmentTitle = templateText.Clone() as TextObj; + m_equipmentTitle.FontSize = 12; + m_equipmentTitle.Text = LocaleBuilder.getString("LOC_ID_PROFILE_CARD_SCREEN_9", m_equipmentTitle) + ":"; + m_equipmentTitle.Position = new Vector2(50, 180); + m_backCard.AddChild(m_equipmentTitle); + + m_runesTitle = templateText.Clone() as TextObj; + m_runesTitle.FontSize = 12; + m_runesTitle.Text = LocaleBuilder.getString("LOC_ID_PROFILE_CARD_SCREEN_10", m_runesTitle) + ":"; + m_runesTitle.Position = new Vector2(m_equipmentTitle.X, 330); + m_backCard.AddChild(m_runesTitle); + + for (int i = 0; i < Game.PlayerStats.GetEquippedArray.Length; i++) + { + TextObj equipment = templateText.Clone() as TextObj; + equipment.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", equipment); // dummy locID to add TextObj to language refresh list + equipment.Position = new Vector2(80, m_equipmentTitle.Y + 50); + m_equipmentList.Add(equipment); + m_backCard.AddChild(equipment); + } + + // Loading runes + + for (int i = 0; i < EquipmentAbilityType.Total - 1; i++) // -1 because the last one is ManaHPGain, which don't display since its shown in Vamp and ManaGain seperately. + { + TextObj runeTitle = templateText.Clone() as TextObj; + runeTitle.X = 60; + runeTitle.Text = LocaleBuilder.getString(EquipmentAbilityType.ToStringID2(i), runeTitle); + runeTitle.FontSize = 7; + m_runeBackTitleList.Add(runeTitle); + m_backCard.AddChild(runeTitle); + + TextObj runeDescription = templateText.Clone() as TextObj; + runeDescription.X = runeTitle.Bounds.Right + 10; + runeDescription.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", runeDescription); // dummy locID to add TextObj to language refresh list + runeDescription.FontSize = 7; + m_runeBackDescriptionList.Add(runeDescription); + m_backCard.AddChild(runeDescription); + } + + // Special architect's fee rune. + TextObj architectFeeTitle = templateText.Clone() as TextObj; + architectFeeTitle.X = 60; + architectFeeTitle.Text = LocaleBuilder.getString(EquipmentAbilityType.ToStringID2(EquipmentAbilityType.ArchitectFee), architectFeeTitle); + architectFeeTitle.FontSize = 7; + m_runeBackTitleList.Add(architectFeeTitle); + m_backCard.AddChild(architectFeeTitle); + + TextObj architectFeeDescription = templateText.Clone() as TextObj; + architectFeeDescription.X = architectFeeTitle.Bounds.Right + 10; + architectFeeDescription.FontSize = 7; + m_runeBackDescriptionList.Add(architectFeeDescription); + m_backCard.AddChild(architectFeeDescription); + + // Special architect's fee rune. + TextObj newGamePlusGoldTitle = templateText.Clone() as TextObj; + newGamePlusGoldTitle.X = 60; + newGamePlusGoldTitle.Text = LocaleBuilder.getString(EquipmentAbilityType.ToStringID2(EquipmentAbilityType.NewGamePlusGoldBonus), newGamePlusGoldTitle); + newGamePlusGoldTitle.FontSize = 7; + m_runeBackTitleList.Add(newGamePlusGoldTitle); + m_backCard.AddChild(newGamePlusGoldTitle); + + TextObj newGamePlusGoldDescription = templateText.Clone() as TextObj; + newGamePlusGoldDescription.X = newGamePlusGoldTitle.Bounds.Right + 10; + newGamePlusGoldDescription.FontSize = 7; + m_runeBackDescriptionList.Add(newGamePlusGoldDescription); + m_backCard.AddChild(newGamePlusGoldDescription); + } + + public override void OnEnter() + { + m_classDebugCounter = 0; + m_traitsDebugCounter = Vector2.Zero; + + SoundManager.PlaySound("StatCard_In"); + LoadCardColour(); + + m_spellIcon.ChangeSprite(SpellType.Icon(Game.PlayerStats.Spell)); + string[] randBG = new string[] { "CardCastleBG_Sprite", "CardGardenBG_Sprite", "CardDungeonBG_Sprite", "CardTowerBG_Sprite" }; + m_playerBG.ChangeSprite(randBG[CDGMath.RandomInt(0, 3)]); + randBG = null; + + m_frontCard.Y = 1500; + m_backCard.Y = 1500; + Tween.To(this, 0.2f, Tween.EaseNone, "BackBufferOpacity", "0.7"); + Tween.To(m_frontCard, 0.4f, Back.EaseOut, "Y", "30"); + Tween.To(m_backCard, 0.4f, Back.EaseOut, "delay", "0.2", "Y", "30"); + + PlayerObj player = (ScreenManager as RCScreenManager).Player; + LoadFrontCardStats(player); + LoadBackCardStats(player); + + ChangeParts(player); + + m_playerHUD.Update(player); + + if (InputManager.GamePadIsConnected(PlayerIndex.One)) + m_cancelText.ForcedScale = new Vector2(0.7f, 0.7f); + else + m_cancelText.ForcedScale = new Vector2(1f, 1f); + + m_cancelText.Text = LocaleBuilder.getString("LOC_ID_PROFILE_CARD_SCREEN_11_NEW", m_cancelText); + //m_cancelText.Text = "[Input:" + InputMapType.MENU_CANCEL1 + "] " + LocaleBuilder.getString("LOC_ID_PROFILE_CARD_SCREEN_11", m_cancelText); + m_cancelText.Opacity = 0; + Tween.To(m_cancelText, 0.2f, Tween.EaseNone, "Opacity", "1"); + + string[] authorNames = new string[] { "Glauber Kotaki", "Kenny Lee", "Teddy Lee", "Gordon McGladdery", "Judson Cowan" }; + m_author.Text = authorNames[CDGMath.RandomInt(0, authorNames.Length - 1)]; + Array.Clear(authorNames, 0, authorNames.Length); + + base.OnEnter(); + } + + private void ChangeParts(PlayerObj player) + { + // Player style must be set before changing his actual parts, otherwise the parts will reset to their defaults (1). + + // Attack animations must be removed for dragon class. + string[] playerGroundActions = null; + if (Game.PlayerStats.Class == ClassType.Dragon) + playerGroundActions = new string[] { "Idle", "Walking", "LevelUp", "Dash", "FrontDash" }; + else + playerGroundActions = new string[] { "Idle", "Attacking3", "Walking", "LevelUp", "Dash", "FrontDash" }; + + string[] playerAirActions = null; + if (Game.PlayerStats.Class == ClassType.Dragon) + playerAirActions = new string[] { "Jumping", "Falling" }; + else + playerAirActions = new string[] { "Jumping", "AirAttack", "Falling" }; + + if (CDGMath.RandomInt(0, 1) == 0) + { + m_playerInAir = true; + SetPlayerStyle(playerAirActions[CDGMath.RandomInt(0, playerAirActions.Length - 1)]); + } + else + { + m_playerInAir = false; + SetPlayerStyle(playerGroundActions[CDGMath.RandomInt(0, playerGroundActions.Length - 1)]); + } + + for (int i = 0; i < player.NumChildren; i++) + { + SpriteObj playerPart = player.GetChildAt(i) as SpriteObj; + SpriteObj playerSpritePart = m_playerSprite.GetChildAt(i) as SpriteObj; + playerSpritePart.TextureColor = playerPart.TextureColor; + } + + string headPart = (m_playerSprite.GetChildAt(PlayerPart.Head) as IAnimateableObj).SpriteName; + int numberIndex = headPart.IndexOf("_") - 1; + headPart = headPart.Remove(numberIndex, 1); + if (Game.PlayerStats.Class == ClassType.Dragon) + headPart = headPart.Replace("_", PlayerPart.DragonHelm + "_"); + else if (Game.PlayerStats.Class == ClassType.Traitor) + headPart = headPart.Replace("_", PlayerPart.IntroHelm + "_"); + else + headPart = headPart.Replace("_", Game.PlayerStats.HeadPiece + "_"); + m_playerSprite.GetChildAt(PlayerPart.Head).ChangeSprite(headPart); + + string chestPart = (m_playerSprite.GetChildAt(PlayerPart.Chest) as IAnimateableObj).SpriteName; + numberIndex = chestPart.IndexOf("_") - 1; + chestPart = chestPart.Remove(numberIndex, 1); + chestPart = chestPart.Replace("_", Game.PlayerStats.ChestPiece + "_"); + m_playerSprite.GetChildAt(PlayerPart.Chest).ChangeSprite(chestPart); + + string shoulderAPart = (m_playerSprite.GetChildAt(PlayerPart.ShoulderA) as IAnimateableObj).SpriteName; + numberIndex = shoulderAPart.IndexOf("_") - 1; + shoulderAPart = shoulderAPart.Remove(numberIndex, 1); + shoulderAPart = shoulderAPart.Replace("_", Game.PlayerStats.ShoulderPiece + "_"); + m_playerSprite.GetChildAt(PlayerPart.ShoulderA).ChangeSprite(shoulderAPart); + + string shoulderBPart = (m_playerSprite.GetChildAt(PlayerPart.ShoulderB) as IAnimateableObj).SpriteName; + numberIndex = shoulderBPart.IndexOf("_") - 1; + shoulderBPart = shoulderBPart.Remove(numberIndex, 1); + shoulderBPart = shoulderBPart.Replace("_", Game.PlayerStats.ShoulderPiece + "_"); + m_playerSprite.GetChildAt(PlayerPart.ShoulderB).ChangeSprite(shoulderBPart); + } + + public void SetPlayerStyle(string animationType) + { + m_playerSprite.ChangeSprite("Player" + animationType + "_Character"); + + PlayerObj player = (ScreenManager as RCScreenManager).Player; + for (int i = 0; i < m_playerSprite.NumChildren; i++) + { + m_playerSprite.GetChildAt(i).TextureColor = player.GetChildAt(i).TextureColor; + m_playerSprite.GetChildAt(i).Visible = player.GetChildAt(i).Visible; + } + m_playerSprite.GetChildAt(PlayerPart.Light).Visible = false; + m_playerSprite.Scale = player.Scale; + + if (Game.PlayerStats.Traits.X == TraitType.Baldness || Game.PlayerStats.Traits.Y == TraitType.Baldness) + m_playerSprite.GetChildAt(PlayerPart.Hair).Visible = false; + + m_playerSprite.GetChildAt(PlayerPart.Glasses).Visible = false; + if (Game.PlayerStats.SpecialItem == SpecialItemType.Glasses) + m_playerSprite.GetChildAt(PlayerPart.Glasses).Visible = true; + + if (Game.PlayerStats.Class == ClassType.Knight || Game.PlayerStats.Class == ClassType.Knight2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("Player" + animationType + "Shield_Sprite"); + } + else if (Game.PlayerStats.Class == ClassType.Banker || Game.PlayerStats.Class == ClassType.Banker2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("Player" + animationType + "Lamp_Sprite"); + } + else if (Game.PlayerStats.Class == ClassType.Wizard || Game.PlayerStats.Class == ClassType.Wizard2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("Player" + animationType + "Beard_Sprite"); + } + else if (Game.PlayerStats.Class == ClassType.Ninja || Game.PlayerStats.Class == ClassType.Ninja2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("Player" + animationType + "Headband_Sprite"); + } + else if (Game.PlayerStats.Class == ClassType.Barbarian || Game.PlayerStats.Class == ClassType.Barbarian2) + { + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Extra).ChangeSprite("Player" + animationType + "Horns_Sprite"); + } + else + m_playerSprite.GetChildAt(PlayerPart.Extra).Visible = false; + + // Special code for dragon. + m_playerSprite.GetChildAt(PlayerPart.Wings).Visible = false; + if (Game.PlayerStats.Class == ClassType.Dragon) + { + m_playerSprite.GetChildAt(PlayerPart.Wings).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Head).ChangeSprite("Player" + animationType + "Head" + PlayerPart.DragonHelm + "_Sprite"); + } + + // This is for male/female counterparts + if (Game.PlayerStats.IsFemale == false) + { + m_playerSprite.GetChildAt(PlayerPart.Boobs).Visible = false; + m_playerSprite.GetChildAt(PlayerPart.Bowtie).Visible = false; + } + else + { + m_playerSprite.GetChildAt(PlayerPart.Boobs).Visible = true; + m_playerSprite.GetChildAt(PlayerPart.Bowtie).Visible = true; + } + + if (Game.PlayerStats.Traits.X == TraitType.Gigantism || Game.PlayerStats.Traits.Y == TraitType.Gigantism) + m_playerSprite.Scale = new Vector2(GameEV.TRAIT_GIGANTISM, GameEV.TRAIT_GIGANTISM); + if (Game.PlayerStats.Traits.X == TraitType.Dwarfism || Game.PlayerStats.Traits.Y == TraitType.Dwarfism) + m_playerSprite.Scale = new Vector2(GameEV.TRAIT_DWARFISM, GameEV.TRAIT_DWARFISM); + + if (Game.PlayerStats.Traits.X == TraitType.Ectomorph || Game.PlayerStats.Traits.Y == TraitType.Ectomorph) + { + m_playerSprite.ScaleX *= 0.825f; + m_playerSprite.ScaleY *= 1.25f; + } + + if (Game.PlayerStats.Traits.X == TraitType.Endomorph || Game.PlayerStats.Traits.Y == TraitType.Endomorph) + { + m_playerSprite.ScaleX *= 1.25f; + m_playerSprite.ScaleY *= 1.175f; + } + + if (Game.PlayerStats.Class == ClassType.SpellSword || Game.PlayerStats.Class == ClassType.SpellSword2) + m_playerSprite.OutlineColour = Color.White; + else + m_playerSprite.OutlineColour = Color.Black; + + // Reposition the player's Y after changing his scale. + m_playerSprite.CalculateBounds(); + m_playerSprite.Y = 435 - (m_playerSprite.Bounds.Bottom - m_playerSprite.Y); + } + + public void ExitScreenTransition() + { + SoundManager.PlaySound("StatCard_Out"); + + Tween.To(m_cancelText, 0.2f, Tween.EaseNone, "Opacity", "0"); + + m_frontCard.Y = 30; + m_backCard.Y = 30; + + Tween.To(this, 0.2f, Tween.EaseNone, "delay", "0.3", "BackBufferOpacity", "0"); + Tween.To(m_frontCard, 0.4f, Back.EaseIn, "Y", "1500"); + Tween.To(m_backCard, 0.4f, Back.EaseIn, "delay", "0.2", "Y", "1500"); + Tween.AddEndHandlerToLastTween(ScreenManager, "HideCurrentScreen"); + + base.OnExit(); + } + + private void LoadCardColour() + { + Color frontColor = Color.Red; + Color backColor = Color.Red; + + switch (Game.PlayerStats.Class) + { + case (ClassType.Assassin): + case (ClassType.Assassin2): + frontColor = backColor = Color.Green; + break; + case (ClassType.Knight): + case (ClassType.Knight2): + frontColor = backColor = Color.White; + break; + case (ClassType.Barbarian): + case (ClassType.Barbarian2): + frontColor = backColor = Color.Red; + break; + case (ClassType.Wizard): + case (ClassType.Wizard2): + frontColor = backColor = Color.Blue; + break; + case (ClassType.Banker): + case (ClassType.Banker2): + frontColor = backColor = Color.Gold; + break; + case (ClassType.Lich): + case (ClassType.Lich2): + frontColor = backColor = Color.Black; + break; + case (ClassType.SpellSword): + case (ClassType.SpellSword2): + frontColor = Color.Blue; + backColor = Color.Red; + break; + case (ClassType.Ninja): + case (ClassType.Ninja2): + frontColor = backColor = Color.Gray; + break; + case(ClassType.Dragon): + frontColor = Color.White; + backColor = Color.Green; + break; + } + + m_frontCard.GetChildAt(0).TextureColor = frontColor; // BG + m_frontCard.GetChildAt(3).TextureColor = frontColor; // Border + m_backCard.GetChildAt(0).TextureColor = backColor; + m_backCard.GetChildAt(2).TextureColor = backColor; + + m_frontCard.GetChildAt(2).TextureColor = new Color(235, 220, 185);//new Color(230, 215, 175); // Border + m_backCard.GetChildAt(1).TextureColor = new Color(235, 220, 185); + } + + private void LoadFrontCardStats(PlayerObj player) + { + // Setting trait data and positions. + m_frontTrait1.Visible = false; + m_frontTrait2.Visible = false; + + byte trait1Data = (byte)(Game.PlayerStats.Traits.X + m_traitsDebugCounter.X); + if (trait1Data != TraitType.None) + { + m_frontTrait1.Text = LocaleBuilder.getResourceString(TraitType.ToStringID(trait1Data)) + ": " + LocaleBuilder.getResourceString(TraitType.ProfileCardDescriptionID(trait1Data)); + m_frontTrait1.Visible = true; + } + + byte trait2Data = (byte)(Game.PlayerStats.Traits.Y + m_traitsDebugCounter.Y); + if (trait2Data != TraitType.None) + { + m_frontTrait2.Y = m_frontTrait1.Y; + if (trait1Data != TraitType.None) + m_frontTrait2.Y -= 20; + m_frontTrait2.Text = LocaleBuilder.getResourceString(TraitType.ToStringID(trait2Data)) + ": " + LocaleBuilder.getResourceString(TraitType.ProfileCardDescriptionID(trait2Data)); + m_frontTrait2.Visible = true; + } + + try + { + m_playerName.ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_playerName)); + m_playerName.Text = Game.NameHelper(); + if (LocaleBuilder.languageType != LanguageType.Chinese_Simp && Regex.IsMatch(m_playerName.Text, @"\p{IsCyrillic}")) + m_playerName.ChangeFontNoDefault(Game.RobotoSlabFont); + } + catch + { + m_playerName.ChangeFontNoDefault(Game.NotoSansSCFont); + m_playerName.Text = Game.NameHelper(); + } + //m_playerStats.Text = (int)(player.Damage / 10f) + "/" + (int)(player.MaxHealth / 100f); + m_playerStats.Text = (int)(player.Damage / 20f) + "/" + (int)(player.MaxHealth / 50f); + m_levelClass.Text = LocaleBuilder.getResourceString("LOC_ID_PROFILE_CARD_SCREEN_12") + " " + Game.PlayerStats.CurrentLevel + " - " + LocaleBuilder.getResourceString(ClassType.ToStringID((byte)(Game.PlayerStats.Class + m_classDebugCounter), Game.PlayerStats.IsFemale)); + m_money.Text = Game.PlayerStats.Gold.ToString(); + m_classDescription.Text = ClassType.ProfileCardDescription((byte)(Game.PlayerStats.Class + m_classDebugCounter)); + } + + private void LoadBackCardStats(PlayerObj player) + { + // Loading player base stats. + for (int i = 0; i < m_dataList1.Count; i++) + { + switch (i) + { + case (0): + m_dataList1[i].Text = player.MaxHealth.ToString(); + m_dataList2[i].Text = player.Damage.ToString(); + break; + case (1): + m_dataList1[i].Text = player.MaxMana.ToString(); + m_dataList2[i].Text = player.TotalMagicDamage.ToString(); + break; + case (2): + m_dataList1[i].Text = player.TotalArmor.ToString() + "(" + (int)(player.TotalDamageReduc * 100) + "%)"; + float critChance = player.TotalCritChance * 100; + m_dataList2[i].Text = ((int)(Math.Round(critChance, MidpointRounding.AwayFromZero))).ToString() + "%"; + break; + case (3): + m_dataList1[i].Text = player.CurrentWeight + "/" + player.MaxWeight; + m_dataList2[i].Text = ((int)(player.TotalCriticalDamage * 100)).ToString() + "%"; + break; + } + } + + // Loading equipment. + sbyte[] playerEquipment = Game.PlayerStats.GetEquippedArray; + int startingY = (int)m_equipmentTitle.Y + 40; + for (int i = 0; i < Game.PlayerStats.GetEquippedArray.Length; i++) + { + m_equipmentList[i].Visible = false; + m_equipmentList[i].Y = startingY; + if (playerEquipment[i] != -1) + { + m_equipmentList[i].Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_BASE_FORMAT", true), LocaleBuilder.getResourceString(EquipmentBaseType.ToStringID(playerEquipment[i]), true), LocaleBuilder.getResourceString(EquipmentCategoryType.ToStringID(i), true)); + m_equipmentList[i].Visible = true; + startingY += 20; + } + } + + // Loading runes + startingY = (int)m_runesTitle.Y + 40; + for (int i = 0; i < m_runeBackTitleList.Count; i++) + { + m_runeBackTitleList[i].Y = startingY; + m_runeBackDescriptionList[i].Y = startingY; + + m_runeBackTitleList[i].Visible = false; + m_runeBackDescriptionList[i].Visible = false; + + float dataNumber = 0; + + switch (i) + { + case (EquipmentAbilityType.Dash): + dataNumber = player.TotalAirDashes; + break; + case (EquipmentAbilityType.DoubleJump): + dataNumber = player.TotalDoubleJumps; + break; + case (EquipmentAbilityType.Flight): + dataNumber = player.TotalFlightTime; + break; + case (EquipmentAbilityType.Vampirism): + dataNumber = player.TotalVampBonus; + break; + case (EquipmentAbilityType.ManaGain): + dataNumber = player.ManaGain; + break; + case (EquipmentAbilityType.DamageReturn): + dataNumber = player.TotalDamageReturn * 100; + break; + case (EquipmentAbilityType.GoldGain): + dataNumber = player.TotalGoldBonus * 100; + break; + case (EquipmentAbilityType.MovementSpeed): + //float traitMod = 0; + //if (Game.PlayerStats.Traits.X == TraitType.Hyperactive || Game.PlayerStats.Traits.Y == TraitType.Hyperactive) + // traitMod = GameEV.TRAIT_MOVESPEED_AMOUNT; + //dataNumber = (player.GetEquipmentSecondaryAttrib(EquipmentSecondaryDataType.MoveSpeed) + traitMod + + //(Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.MovementSpeed) * GameEV.RUNE_MOVEMENTSPEED_MOD)) * + //player.ClassMoveSpeedMultiplier * 100; + dataNumber = (player.TotalMovementSpeedPercent * 100) - 100; + break; + //case (EquipmentAbilityType.ManaHPGain): // DO NOT ADD. This is replaced by vamp and siphon + // dataNumber = Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.ManaHPGain) * GameEV.RUNE_MANAHPGAIN; + // break; + case (EquipmentAbilityType.RoomLevelDown): + dataNumber = Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.RoomLevelDown) * GameEV.RUNE_GRACE_ROOM_LEVEL_LOSS; + break; + case (EquipmentAbilityType.RoomLevelUp): + dataNumber = Game.PlayerStats.GetNumberOfEquippedRunes(EquipmentAbilityType.RoomLevelUp) * GameEV.RUNE_CURSE_ROOM_LEVEL_GAIN; + break; + } + + if (dataNumber > 0) + { + m_runeBackDescriptionList[i].Text = "(" + EquipmentAbilityType.ShortDescription(i, dataNumber) + ")"; + m_runeBackDescriptionList[i].X = m_runeBackTitleList[i].Bounds.Right + 10; + m_runeBackTitleList[i].Visible = true; + m_runeBackDescriptionList[i].Visible = true; + startingY += 20; + } + } + + // Special handling for the architect's fee. The architect rune is always the last one on the list. + if (Game.PlayerStats.HasArchitectFee == true) + { + m_runeBackDescriptionList[m_runeBackDescriptionList.Count - 2].ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_runeBackDescriptionList[m_runeBackDescriptionList.Count - 2])); + m_runeBackDescriptionList[m_runeBackDescriptionList.Count - 2].Text = "(" + EquipmentAbilityType.ShortDescription(EquipmentAbilityType.ArchitectFee, 0) + ")"; + m_runeBackDescriptionList[m_runeBackDescriptionList.Count - 2].X = m_runeBackTitleList[m_runeBackDescriptionList.Count - 2].Bounds.Right + 10; + m_runeBackDescriptionList[m_runeBackDescriptionList.Count - 2].Visible = true; + m_runeBackTitleList[m_runeBackDescriptionList.Count - 2].Visible = true; + startingY += 20; + } + // Special handling for the architect's fee. The architect rune is always the last one on the list. + if (Game.PlayerStats.TimesCastleBeaten > 0) + { + m_runeBackDescriptionList[m_runeBackDescriptionList.Count - 1].ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_runeBackDescriptionList[m_runeBackDescriptionList.Count - 1])); + m_runeBackDescriptionList[m_runeBackDescriptionList.Count - 1].Text = "(" + EquipmentAbilityType.ShortDescription(EquipmentAbilityType.NewGamePlusGoldBonus, ((int)(GameEV.NEWGAMEPLUS_GOLDBOUNTY *100) * Game.PlayerStats.TimesCastleBeaten)) + ")"; + m_runeBackDescriptionList[m_runeBackDescriptionList.Count - 1].X = m_runeBackTitleList[m_runeBackDescriptionList.Count - 1].Bounds.Right + 10; + m_runeBackDescriptionList[m_runeBackDescriptionList.Count - 1].Visible = true; + m_runeBackTitleList[m_runeBackDescriptionList.Count - 1].Visible = true; + if (Game.PlayerStats.HasArchitectFee == true) + { + m_runeBackDescriptionList[m_runeBackDescriptionList.Count - 1].Y = startingY; + m_runeBackTitleList[m_runeBackDescriptionList.Count - 1].Y = startingY; + } + //startingY += 20; + } + + try + { + (m_backCard.GetChildAt(3) as TextObj).ChangeFontNoDefault(LocaleBuilder.GetLanguageFont((m_backCard.GetChildAt(3) as TextObj))); + (m_backCard.GetChildAt(3) as TextObj).Text = Game.NameHelper(); + if (LocaleBuilder.languageType != LanguageType.Chinese_Simp && Regex.IsMatch((m_backCard.GetChildAt(3) as TextObj).Text, @"\p{IsCyrillic}")) + (m_backCard.GetChildAt(3) as TextObj).ChangeFontNoDefault(Game.RobotoSlabFont); + } + catch + { + (m_backCard.GetChildAt(3) as TextObj).ChangeFontNoDefault(Game.NotoSansSCFont); + (m_backCard.GetChildAt(3) as TextObj).Text = Game.NameHelper(); + } + } + + public override void HandleInput() + { + if (m_frontCard.Y == 30) // Only accept input once intro tween is complete. + { + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3) + || Game.GlobalInput.JustPressed(InputMapType.MENU_PROFILECARD)) + ExitScreenTransition(); + } + + if (LevelEV.ENABLE_DEBUG_INPUT == true) + HandleDebugInput(); + + base.HandleInput(); + } + + private sbyte m_classDebugCounter = 0; + private Vector2 m_traitsDebugCounter = Vector2.Zero; + private void HandleDebugInput() + { + // Debug testing for class localization. + sbyte currentDebugClass = (sbyte)(Game.PlayerStats.Class + m_classDebugCounter); + sbyte previousDebugClass = currentDebugClass; + + if (InputManager.JustPressed(Keys.OemMinus, PlayerIndex.One)) + { + if (currentDebugClass == ClassType.Knight) + m_classDebugCounter = (sbyte)(ClassType.Traitor - Game.PlayerStats.Class); + else + m_classDebugCounter--; + currentDebugClass = (sbyte)(Game.PlayerStats.Class + m_classDebugCounter); + } + else if (InputManager.JustPressed(Keys.OemPlus, PlayerIndex.One)) + { + if (currentDebugClass == ClassType.Traitor) + m_classDebugCounter = (sbyte)(-Game.PlayerStats.Class); + else + m_classDebugCounter++; + currentDebugClass = (sbyte)(Game.PlayerStats.Class + m_classDebugCounter); + } + + if (previousDebugClass != currentDebugClass) + { + m_classDescription.Text = ClassType.ProfileCardDescription((byte)currentDebugClass); + m_levelClass.Text = LocaleBuilder.getResourceString("LOC_ID_PROFILE_CARD_SCREEN_12") + " " + Game.PlayerStats.CurrentLevel + " - " + LocaleBuilder.getResourceString(ClassType.ToStringID((byte)currentDebugClass, Game.PlayerStats.IsFemale)); + } + + // Debug testing for traits localization. + Vector2 currentDebugTraits = Game.PlayerStats.Traits + m_traitsDebugCounter; + Vector2 previousTraits = currentDebugTraits; + + if (InputManager.JustPressed(Keys.OemPeriod, PlayerIndex.One)) + { + if (currentDebugTraits.X == TraitType.None) + m_traitsDebugCounter.X = (TraitType.Total - 1) - Game.PlayerStats.Traits.X; + else + m_traitsDebugCounter.X--; + + currentDebugTraits = Game.PlayerStats.Traits + m_traitsDebugCounter; + } + else if (InputManager.JustPressed(Keys.OemQuestion, PlayerIndex.One)) + { + if (currentDebugTraits.X == TraitType.Total - 1) + m_traitsDebugCounter.X = -Game.PlayerStats.Traits.X; + else + m_traitsDebugCounter.X++; + + currentDebugTraits = Game.PlayerStats.Traits + m_traitsDebugCounter; + } + + if (InputManager.JustPressed(Keys.M, PlayerIndex.One)) + { + if (currentDebugTraits.Y == TraitType.None) + m_traitsDebugCounter.Y = (TraitType.Total - 1) - Game.PlayerStats.Traits.Y; + else + m_traitsDebugCounter.Y--; + + currentDebugTraits = Game.PlayerStats.Traits + m_traitsDebugCounter; + } + else if (InputManager.JustPressed(Keys.OemComma, PlayerIndex.One)) + { + if (currentDebugTraits.Y == TraitType.Total - 1) + m_traitsDebugCounter.Y = -Game.PlayerStats.Traits.Y; + else + m_traitsDebugCounter.Y++; + + currentDebugTraits = Game.PlayerStats.Traits + m_traitsDebugCounter; + } + + if (currentDebugTraits.X >= TraitType.Total) + currentDebugTraits.X = TraitType.None; + else if (currentDebugTraits.X < TraitType.None) + currentDebugTraits.X = TraitType.Total - 1; + if (currentDebugTraits.Y >= TraitType.Total) + currentDebugTraits.Y = TraitType.None; + else if (currentDebugTraits.Y < TraitType.None) + currentDebugTraits.Y = TraitType.Total - 1; + + if (currentDebugTraits != previousTraits) + { + m_frontTrait1.Visible = false; + m_frontTrait2.Visible = false; + + byte trait1Data = (byte)currentDebugTraits.X; + if (trait1Data != TraitType.None) + { + m_frontTrait1.Text = LocaleBuilder.getResourceString(TraitType.ToStringID(trait1Data)) + ": " + LocaleBuilder.getResourceString(TraitType.ProfileCardDescriptionID(trait1Data)); + m_frontTrait1.Visible = true; + } + + byte trait2Data = (byte)currentDebugTraits.Y; + if (trait2Data != TraitType.None) + { + m_frontTrait2.Y = m_frontTrait1.Y; + if (trait1Data != TraitType.None) + m_frontTrait2.Y -= 20; + m_frontTrait2.Text = LocaleBuilder.getResourceString(TraitType.ToStringID(trait2Data)) + ": " + LocaleBuilder.getResourceString(TraitType.ProfileCardDescriptionID(trait2Data)); + m_frontTrait2.Visible = true; + } + } + } + + public override void Draw(GameTime gametime) + { + m_playerHUD.SetPosition(new Vector2(m_frontCard.X + 46, m_frontCard.Y + 220 + 64)); + + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null); + Camera.Draw(Game.GenericTexture, new Rectangle(0, 0, GlobalEV.ScreenWidth, GlobalEV.ScreenHeight), Color.Black * BackBufferOpacity); + m_frontCard.Draw(Camera); + m_backCard.Draw(Camera); + + m_cancelText.Draw(Camera); + + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + if (Game.PlayerStats.IsDead == true) + { + //m_tombStoneSprite.Position = new Vector2(m_frontCard.X + 240, m_frontCard.Y + 280); + m_tombStoneSprite.Position = new Vector2(m_frontCard.X + 240, m_frontCard.Y + 280 + 220); + m_tombStoneSprite.Draw(Camera); + } + else + { + if (m_playerInAir == true) + //m_playerSprite.Position = new Vector2(m_frontCard.X + 180, m_frontCard.Y + 202); + m_playerSprite.Position = new Vector2(m_frontCard.X + 180, m_frontCard.Y + 202 + 220); + else + { + //m_playerSprite.Position = new Vector2(m_frontCard.X + 160, m_frontCard.Y + 280 - (m_playerSprite.Bounds.Bottom - m_playerSprite.Y)); + m_playerSprite.Position = new Vector2(m_frontCard.X + 160, m_frontCard.Y + 280 - (m_playerSprite.Bounds.Bottom - m_playerSprite.Y) + 220); + } + m_playerSprite.Draw(Camera); + Game.ColourSwapShader.Parameters["desiredTint"].SetValue(m_playerSprite.GetChildAt(PlayerPart.Head).TextureColor.ToVector4()); + if (Game.PlayerStats.Class == ClassType.Lich || Game.PlayerStats.Class == ClassType.Lich2) + { + // This is the Tint Removal effect, that removes the tint from his face. + Game.ColourSwapShader.Parameters["Opacity"].SetValue(m_playerSprite.Opacity); + Game.ColourSwapShader.Parameters["ColourSwappedOut1"].SetValue(m_skinColour1.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn1"].SetValue(m_lichColour1.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedOut2"].SetValue(m_skinColour2.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn2"].SetValue(m_lichColour2.ToVector4()); + } + else if (Game.PlayerStats.Class == ClassType.Assassin || Game.PlayerStats.Class == ClassType.Assassin2) + { + // This is the Tint Removal effect, that removes the tint from his face. + Game.ColourSwapShader.Parameters["Opacity"].SetValue(m_playerSprite.Opacity); + Game.ColourSwapShader.Parameters["ColourSwappedOut1"].SetValue(m_skinColour1.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn1"].SetValue(Color.Black.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedOut2"].SetValue(m_skinColour2.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn2"].SetValue(Color.Black.ToVector4()); + } + else + { + Game.ColourSwapShader.Parameters["Opacity"].SetValue(1); + Game.ColourSwapShader.Parameters["ColourSwappedOut1"].SetValue(m_skinColour1.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn1"].SetValue(m_skinColour1.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedOut2"].SetValue(m_skinColour2.ToVector4()); + Game.ColourSwapShader.Parameters["ColourSwappedIn2"].SetValue(m_skinColour2.ToVector4()); + } + + Camera.End(); + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, Game.ColourSwapShader); + m_playerSprite.GetChildAt(PlayerPart.Head).Draw(Camera); + Camera.End(); + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null); + if (Game.PlayerStats.IsFemale == true) + m_playerSprite.GetChildAt(PlayerPart.Bowtie).Draw(Camera); + m_playerSprite.GetChildAt(PlayerPart.Extra).Draw(Camera); + } + + //m_spellIcon.Position = new Vector2(m_frontCard.X + 380, m_frontCard.Y + 320); + m_spellIcon.Position = new Vector2(m_frontCard.X + 380, m_frontCard.Y + 320 + 220); + m_spellIcon.Draw(Camera); + + Camera.End(); + + base.Draw(gametime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Profile Card Screen"); + + m_frontCard.Dispose(); + m_frontCard = null; + m_backCard.Dispose(); + m_backCard = null; + + // Disposing front card objects. + m_playerName = null; + m_money = null; + m_levelClass = null; + m_playerHUD = null; + m_frontTrait1 = null; + m_frontTrait2 = null; + m_playerBG = null; + m_classDescription = null; + m_author = null; + m_playerStats = null; + + // Disposing back card objects. + m_equipmentTitle = null; + m_runesTitle = null; + m_equipmentList.Clear(); + m_equipmentList = null; + m_runeBackTitleList.Clear(); + m_runeBackTitleList = null; + m_runeBackDescriptionList.Clear(); + m_runeBackDescriptionList = null; + + m_playerSprite.Dispose(); + m_playerSprite = null; + + m_spellIcon.Dispose(); + m_spellIcon = null; + + m_tombStoneSprite.Dispose(); + m_tombStoneSprite = null; + + m_cancelText.Dispose(); + m_cancelText = null; + + // Even though text objs are added to the data lists, they're also added to the cards, which dispose them when the cards are disposed. + m_dataList1.Clear(); + m_dataList1 = null; + m_dataList2.Clear(); + m_dataList2 = null; + base.Dispose(); + } + } + + public override void RefreshTextObjs() + { + m_equipmentTitle.Text = LocaleBuilder.getResourceString("LOC_ID_PROFILE_CARD_SCREEN_9") + ":"; + m_runesTitle.Text = LocaleBuilder.getResourceString("LOC_ID_PROFILE_CARD_SCREEN_10") + ":"; + //m_cancelText.Text = "[Input:" + InputMapType.MENU_CANCEL1 + "] " + LocaleBuilder.getResourceString("LOC_ID_PROFILE_CARD_SCREEN_11"); + + PlayerObj player = (ScreenManager as RCScreenManager).Player; + LoadFrontCardStats(player); + LoadBackCardStats(player); + + // Massive hack. 14 is the index of a text line that is too long in russian. + m_backCard.GetChildAt(14).ScaleX = 1; + switch (LocaleBuilder.languageType) + { + case (LanguageType.Russian): + m_backCard.GetChildAt(14).ScaleX = 0.9f; + break; + } + + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Screens/ProfileSelectScreen.cs b/RogueCastle/src/Screens/ProfileSelectScreen.cs new file mode 100644 index 0000000..f5e67cc --- /dev/null +++ b/RogueCastle/src/Screens/ProfileSelectScreen.cs @@ -0,0 +1,522 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Tweener; +using Tweener.Ease; +using InputSystem; +using System.Text.RegularExpressions; + +namespace RogueCastle +{ + public class ProfileSelectScreen : Screen + { + public float BackBufferOpacity { get; set; } + + private KeyIconTextObj m_confirmText; + private KeyIconTextObj m_cancelText; + private KeyIconTextObj m_navigationText; + private KeyIconTextObj m_deleteProfileText; + + private SpriteObj m_title; + private ObjContainer m_slot1Container, m_slot2Container, m_slot3Container; + + private int m_selectedIndex = 0; + + private bool m_lockControls = false; + + private List m_slotArray; + private ObjContainer m_selectedSlot; + + public ProfileSelectScreen() + { + m_slotArray = new List(); + this.DrawIfCovered = true; + } + + public override void LoadContent() + { + m_title = new SpriteObj("ProfileSelectTitle_Sprite"); + m_title.ForceDraw = true; + + // Template for slot text + TextObj slotText = new TextObj(Game.JunicodeFont); + slotText.Align = Types.TextAlign.Centre; + slotText.Text = LocaleBuilder.getString("LOC_ID_PROFILE_SEL_SCREEN_1", slotText); + slotText.TextureColor = Color.White; + slotText.OutlineWidth = 2; + slotText.FontSize = 10; + slotText.Position = new Vector2(0, -(slotText.Height / 2f)); + + m_slot1Container = new ObjContainer("ProfileSlotBG_Container"); + TextObj slot1Text = slotText.Clone() as TextObj; + slot1Text.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", slot1Text); // dummy locID to add TextObj to language refresh list + m_slot1Container.AddChild(slot1Text); + SpriteObj slot1Title = new SpriteObj("ProfileSlot1Text_Sprite"); + slot1Title.Position = new Vector2(-130, -35); + m_slot1Container.AddChild(slot1Title); + TextObj slot1LvlText = slotText.Clone() as TextObj; + slot1LvlText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", slot1LvlText); // dummy locID to add TextObj to language refresh list + slot1LvlText.Position = new Vector2(120, 15); + m_slot1Container.AddChild(slot1LvlText); + TextObj slot1NGText = slotText.Clone() as TextObj; + slot1NGText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", slot1NGText); // dummy locID to add TextObj to language refresh list + slot1NGText.Position = new Vector2(-120, 15); + m_slot1Container.AddChild(slot1NGText); + m_slot1Container.ForceDraw = true; + + m_slot2Container = new ObjContainer("ProfileSlotBG_Container"); + TextObj slot2Text = slotText.Clone() as TextObj; + slot2Text.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", slot2Text); // dummy locID to add TextObj to language refresh list + m_slot2Container.AddChild(slot2Text); + SpriteObj slot2Title = new SpriteObj("ProfileSlot2Text_Sprite"); + slot2Title.Position = new Vector2(-130, -35); + m_slot2Container.AddChild(slot2Title); + TextObj slot2LvlText = slotText.Clone() as TextObj; + slot2LvlText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", slot2LvlText); // dummy locID to add TextObj to language refresh list + slot2LvlText.Position = new Vector2(120, 15); + m_slot2Container.AddChild(slot2LvlText); + TextObj slot2NGText = slotText.Clone() as TextObj; + slot2NGText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", slot2NGText); // dummy locID to add TextObj to language refresh list + slot2NGText.Position = new Vector2(-120, 15); + m_slot2Container.AddChild(slot2NGText); + m_slot2Container.ForceDraw = true; + + m_slot3Container = new ObjContainer("ProfileSlotBG_Container"); + TextObj slot3Text = slotText.Clone() as TextObj; + slot3Text.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", slot3Text); // dummy locID to add TextObj to language refresh list + m_slot3Container.AddChild(slot3Text); + SpriteObj slot3Title = new SpriteObj("ProfileSlot3Text_Sprite"); + slot3Title.Position = new Vector2(-130, -35); + m_slot3Container.AddChild(slot3Title); + TextObj slot3LvlText = slotText.Clone() as TextObj; + slot3LvlText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", slot3LvlText); // dummy locID to add TextObj to language refresh list + slot3LvlText.Position = new Vector2(120, 15); + m_slot3Container.AddChild(slot3LvlText); + TextObj slot3NGText = slotText.Clone() as TextObj; + slot3NGText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", slot3NGText); // dummy locID to add TextObj to language refresh list + slot3NGText.Position = new Vector2(-120, 15); + m_slot3Container.AddChild(slot3NGText); + m_slot3Container.ForceDraw = true; + + m_slotArray.Add(m_slot1Container); + m_slotArray.Add(m_slot2Container); + m_slotArray.Add(m_slot3Container); + + m_confirmText = new KeyIconTextObj(Game.JunicodeFont); + m_confirmText.Text = LocaleBuilder.getString("LOC_ID_PROFILE_SEL_SCREEN_4", m_confirmText); + m_confirmText.DropShadow = new Vector2(2, 2); + m_confirmText.FontSize = 12; + m_confirmText.Align = Types.TextAlign.Right; + m_confirmText.Position = new Vector2(1290, 570); + m_confirmText.ForceDraw = true; + + m_cancelText = new KeyIconTextObj(Game.JunicodeFont); + m_cancelText.Text = LocaleBuilder.getString("LOC_ID_PROFILE_SEL_SCREEN_5", m_cancelText); + m_cancelText.Align = Types.TextAlign.Right; + m_cancelText.DropShadow = new Vector2(2, 2); + m_cancelText.FontSize = 12; + m_cancelText.Position = new Vector2(m_confirmText.X, m_confirmText.Y + 40); + m_cancelText.ForceDraw = true; + + m_navigationText = new KeyIconTextObj(Game.JunicodeFont); + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_PROFILE_SEL_SCREEN_2", m_navigationText); + m_navigationText.Align = Types.TextAlign.Right; + m_navigationText.DropShadow = new Vector2(2, 2); + m_navigationText.FontSize = 12; + m_navigationText.Position = new Vector2(m_confirmText.X, m_confirmText.Y + 80); + m_navigationText.ForceDraw = true; + + m_deleteProfileText = new KeyIconTextObj(Game.JunicodeFont); + m_deleteProfileText.Text = LocaleBuilder.getString("LOC_ID_PROFILE_SEL_SCREEN_6", m_deleteProfileText); + m_deleteProfileText.Align = Types.TextAlign.Left; + m_deleteProfileText.DropShadow = new Vector2(2, 2); + m_deleteProfileText.FontSize = 12; + m_deleteProfileText.Position = new Vector2(20, m_confirmText.Y + 80); + m_deleteProfileText.ForceDraw = true; + + base.LoadContent(); + } + + public override void OnEnter() + { + SoundManager.PlaySound("DialogOpen"); + m_lockControls = true; + m_selectedIndex = Game.GameConfig.ProfileSlot - 1; + m_selectedSlot = m_slotArray[m_selectedIndex]; + m_selectedSlot.TextureColor = Color.Yellow; + + CheckSaveHeaders(m_slot1Container, 1); + CheckSaveHeaders(m_slot2Container, 2); + CheckSaveHeaders(m_slot3Container, 3); + + m_deleteProfileText.Visible = true; + if (m_slotArray[m_selectedIndex].ID == 0) + m_deleteProfileText.Visible = false; + + Tween.To(this, 0.2f, Tween.EaseNone, "BackBufferOpacity", "0.9"); + + m_title.Position = new Vector2(1320 / 2f, 100); + m_slot1Container.Position = new Vector2(1320 / 2f, 300); + m_slot2Container.Position = new Vector2(1320 / 2f, 420); + m_slot3Container.Position = new Vector2(1320 / 2f, 540); + + TweenInText(m_title, 0); + TweenInText(m_slot1Container, 0.05f); + TweenInText(m_slot2Container, 0.1f); + TweenInText(m_slot3Container, 0.15f); + + Tween.RunFunction(0.5f, this, "UnlockControls"); + + if (InputManager.GamePadIsConnected(PlayerIndex.One)) + { + m_confirmText.ForcedScale = new Vector2(0.7f, 0.7f); + m_cancelText.ForcedScale = new Vector2(0.7f, 0.7f); + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_PROFILE_SEL_SCREEN_2_NEW", m_navigationText); + } + else + { + m_confirmText.ForcedScale = new Vector2(1f, 1f); + m_cancelText.ForcedScale = new Vector2(1f, 1f); + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_PROFILE_SEL_SCREEN_3", m_navigationText); + } + m_confirmText.Text = LocaleBuilder.getString("LOC_ID_PROFILE_SEL_SCREEN_4_NEW", m_confirmText); + m_cancelText.Text = LocaleBuilder.getString("LOC_ID_PROFILE_SEL_SCREEN_5_NEW", m_cancelText); + m_deleteProfileText.Text = LocaleBuilder.getString("LOC_ID_PROFILE_SEL_SCREEN_6_NEW", m_deleteProfileText); + + m_confirmText.Opacity = 0; + m_cancelText.Opacity = 0; + m_navigationText.Opacity = 0; + m_deleteProfileText.Opacity = 0; + + Tween.To(m_confirmText, 0.2f, Tween.EaseNone, "Opacity", "1"); + Tween.To(m_cancelText, 0.2f, Tween.EaseNone, "Opacity", "1"); + Tween.To(m_navigationText, 0.2f, Tween.EaseNone, "Opacity", "1"); + Tween.To(m_deleteProfileText, 0.2f, Tween.EaseNone, "Opacity", "1"); + + Game.ChangeBitmapLanguage(m_title, "ProfileSelectTitle_Sprite"); + Game.ChangeBitmapLanguage(m_slot1Container.GetChildAt(2) as SpriteObj, "ProfileSlot1Text_Sprite"); + Game.ChangeBitmapLanguage(m_slot2Container.GetChildAt(2) as SpriteObj, "ProfileSlot2Text_Sprite"); + Game.ChangeBitmapLanguage(m_slot3Container.GetChildAt(2) as SpriteObj, "ProfileSlot3Text_Sprite"); + + base.OnEnter(); + } + + private void CheckSaveHeaders(ObjContainer container, byte profile) + { + TextObj slotText = container.GetChildAt(1) as TextObj; + TextObj slotLvlText = container.GetChildAt(3) as TextObj; + TextObj slotNGText = container.GetChildAt(4) as TextObj; + slotLvlText.Text = ""; + slotNGText.Text = ""; + string playerName = null; + byte playerClass = 0; + int playerLevel = 0; + bool isDead = false; + int timesCastleBeaten = 0; + bool isFemale = false; + + try + { + (ScreenManager.Game as Game).SaveManager.GetSaveHeader(profile, out playerClass, out playerName, out playerLevel, out isDead, out timesCastleBeaten, out isFemale); + + if (playerName == null) + { + slotText.Text = LocaleBuilder.getResourceString("LOC_ID_PROFILE_SEL_SCREEN_1"); + container.ID = 0; // Container with ID == 0 means it has no save file. + } + else + { + // This call to Game.NameHelper forces a name conversion check every time. This is necessary because it is possible for different profile slots to have different + // save revision numbers. So you have to do the check every time in case that happens only in this scenario (since the check can be a little expensive). + playerName = Game.NameHelper(playerName, "", isFemale, true); + + try + { + slotText.ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(slotText)); + if (isDead == false) + slotText.Text = string.Format(LocaleBuilder.getResourceString(!isFemale ? "LOC_ID_PROFILE_SEL_SCREEN_7_MALE_NEW" : "LOC_ID_PROFILE_SEL_SCREEN_7_FEMALE_NEW"), playerName, LocaleBuilder.getResourceString(ClassType.ToStringID(playerClass, isFemale))); // {0} the {1} + else + slotText.Text = string.Format(LocaleBuilder.getResourceString(!isFemale ? "LOC_ID_PROFILE_SEL_SCREEN_8_MALE_NEW" : "LOC_ID_PROFILE_SEL_SCREEN_8_FEMALE_NEW"), playerName); // {0} the deceased + if (LocaleBuilder.languageType != LanguageType.Chinese_Simp && Regex.IsMatch(slotText.Text, @"\p{IsCyrillic}")) + slotText.ChangeFontNoDefault(Game.RobotoSlabFont); + } + catch + { + slotText.ChangeFontNoDefault(Game.NotoSansSCFont); + if (isDead == false) + slotText.Text = string.Format(LocaleBuilder.getResourceString(!isFemale ? "LOC_ID_PROFILE_SEL_SCREEN_7_MALE_NEW" : "LOC_ID_PROFILE_SEL_SCREEN_7_FEMALE_NEW"), playerName, LocaleBuilder.getResourceString(ClassType.ToStringID(playerClass, isFemale))); // {0} the {1} + else + slotText.Text = string.Format(LocaleBuilder.getResourceString(!isFemale ? "LOC_ID_PROFILE_SEL_SCREEN_8_MALE_NEW" : "LOC_ID_PROFILE_SEL_SCREEN_8_FEMALE_NEW"), playerName); // {0} the deceased + } + + slotLvlText.Text = LocaleBuilder.getResourceString("LOC_ID_PROFILE_SEL_SCREEN_9") + " " + playerLevel; + if (timesCastleBeaten > 0) + slotNGText.Text = LocaleBuilder.getResourceString("LOC_ID_PROFILE_SEL_SCREEN_10") + " " + timesCastleBeaten; + container.ID = 1; // Container with ID == 1 means it has a save file. + } + } + catch + { + slotText.Text = LocaleBuilder.getString("LOC_ID_PROFILE_SEL_SCREEN_1", slotText); + container.ID = 0; // Container with ID == 0 means it has no save file. + } + } + + public void UnlockControls() + { + m_lockControls = false; + } + + private void TweenInText(GameObj obj, float delay) + { + obj.Opacity = 0; + obj.Y -= 50; + Tween.To(obj, 0.5f, Tween.EaseNone, "delay", delay.ToString(), "Opacity", "1"); + Tween.By(obj, 0.5f, Quad.EaseOut, "delay", delay.ToString(), "Y", "50"); + } + + private void ExitTransition() + { + SoundManager.PlaySound("DialogMenuClose"); + + Tween.To(m_confirmText, 0.2f, Tween.EaseNone, "Opacity", "0"); + Tween.To(m_cancelText, 0.2f, Tween.EaseNone, "Opacity", "0"); + Tween.To(m_navigationText, 0.2f, Tween.EaseNone, "Opacity", "0"); + Tween.To(m_deleteProfileText, 0.2f, Tween.EaseNone, "Opacity", "0"); + + m_lockControls = true; + + TweenOutText(m_title, 0); + TweenOutText(m_slot1Container, 0.05f); + TweenOutText(m_slot2Container, 0.1f); + TweenOutText(m_slot3Container, 0.15f); + + Tween.To(this, 0.2f, Tween.EaseNone, "delay", "0.5", "BackBufferOpacity", "0"); + Tween.AddEndHandlerToLastTween(ScreenManager, "HideCurrentScreen"); + } + + private void TweenOutText(GameObj obj, float delay) + { + Tween.To(obj, 0.5f, Tween.EaseNone, "delay", delay.ToString(), "Opacity", "0"); + Tween.By(obj, 0.5f, Quad.EaseInOut, "delay", delay.ToString(), "Y", "-50"); + } + + public override void OnExit() + { + m_slot1Container.TextureColor = Color.White; + m_slot2Container.TextureColor = Color.White; + m_slot3Container.TextureColor = Color.White; + m_lockControls = false; + base.OnExit(); + } + + public override void HandleInput() + { + if (m_lockControls == false) + { + ObjContainer selectedSlot = m_selectedSlot; + + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN2)) + { + m_selectedIndex++; + if (m_selectedIndex >= m_slotArray.Count) + m_selectedIndex = 0; + m_selectedSlot = m_slotArray[m_selectedIndex]; + SoundManager.PlaySound("frame_swap"); + + m_deleteProfileText.Visible = true; + if (m_selectedSlot.ID == 0) + m_deleteProfileText.Visible = false; + } + + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + m_selectedIndex--; + if (m_selectedIndex < 0) + m_selectedIndex = m_slotArray.Count - 1; + m_selectedSlot = m_slotArray[m_selectedIndex]; + SoundManager.PlaySound("frame_swap"); + + m_deleteProfileText.Visible = true; + if (m_selectedSlot.ID == 0) + m_deleteProfileText.Visible = false; + } + + if (m_selectedSlot != selectedSlot) + { + selectedSlot.TextureColor = Color.White; + m_selectedSlot.TextureColor = Color.Yellow; + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + ExitTransition(); + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + { + SoundManager.PlaySound("Map_On"); + + Game.GameConfig.ProfileSlot = (byte)(m_selectedIndex + 1); + Game game = (ScreenManager.Game as Game); + game.SaveConfig(); + + if (game.SaveManager.FileExists(SaveType.PlayerData)) + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Title, true); + else + { + SkillSystem.ResetAllTraits(); + Game.PlayerStats.Dispose(); + Game.PlayerStats = new PlayerStats(); + (ScreenManager as RCScreenManager).Player.Reset(); + Game.ScreenManager.Player.CurrentHealth = Game.PlayerStats.CurrentHealth; + Game.ScreenManager.Player.CurrentMana = Game.PlayerStats.CurrentMana; + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.TutorialRoom, true, null); + } + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_DELETEPROFILE) && m_deleteProfileText.Visible == true) + { + SoundManager.PlaySound("Map_On"); + DeleteSaveAsk(); + } + } + + base.HandleInput(); + } + + public override void Draw(GameTime gametime) + { + Camera.Begin(); + Camera.Draw(Game.GenericTexture, new Rectangle(0, 0, GlobalEV.ScreenWidth, GlobalEV.ScreenHeight), Color.Black * BackBufferOpacity); + + m_title.Draw(Camera); + m_slot1Container.Draw(Camera); + m_slot2Container.Draw(Camera); + m_slot3Container.Draw(Camera); + + m_confirmText.Draw(Camera); + m_cancelText.Draw(Camera); + m_navigationText.Draw(Camera); + m_deleteProfileText.Draw(Camera); + + Camera.End(); + base.Draw(gametime); + } + + public void DeleteSaveAsk() + { + RCScreenManager manager = ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("Delete Save"); + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "DeleteSaveAskAgain"); + manager.DisplayScreen(ScreenType.Dialogue, false, null); + } + + public void DeleteSaveAskAgain() + { + RCScreenManager manager = ScreenManager as RCScreenManager; + manager.DialogueScreen.SetDialogue("Delete Save2"); + manager.DialogueScreen.SetDialogueChoice("ConfirmTest1"); + manager.DialogueScreen.SetConfirmEndHandler(this, "DeleteSave"); + manager.DisplayScreen(ScreenType.Dialogue, false, null); + } + + public void DeleteSave() + { + bool runTutorial = false; + byte storedProfile = Game.GameConfig.ProfileSlot; + + if (Game.GameConfig.ProfileSlot == m_selectedIndex + 1) + runTutorial = true; + + // Doing this to delete the correct profile slot. Will be reverted once the file is deleted. + Game.GameConfig.ProfileSlot = (byte)(m_selectedIndex + 1); + //Game game = (ScreenManager.Game as Game); + //game.SaveConfig(); + + (ScreenManager.Game as Game).SaveManager.ClearAllFileTypes(false); + (ScreenManager.Game as Game).SaveManager.ClearAllFileTypes(true); + + // Reverting profile slot back to stored slot. + Game.GameConfig.ProfileSlot = storedProfile; + + if (runTutorial == true) + { + Game.PlayerStats.Dispose(); + SkillSystem.ResetAllTraits(); + Game.PlayerStats = new PlayerStats(); + (ScreenManager as RCScreenManager).Player.Reset(); + + SoundManager.StopMusic(1); + + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.TutorialRoom, true); + } + else + { + m_deleteProfileText.Visible = false; + CheckSaveHeaders(m_slotArray[m_selectedIndex], (byte)(m_selectedIndex + 1)); + } + } + + public override void Dispose() + { + if (IsDisposed == false) + { + //Console.WriteLine("Disposing Profile Select Screen"); + m_title.Dispose(); + m_title = null; + + m_slot1Container.Dispose(); + m_slot1Container = null; + m_slot2Container.Dispose(); + m_slot2Container = null; + m_slot3Container.Dispose(); + m_slot3Container = null; + + m_slotArray.Clear(); + m_slotArray = null; + + m_selectedSlot = null; + + m_confirmText.Dispose(); + m_confirmText = null; + m_cancelText.Dispose(); + m_cancelText = null; + m_navigationText.Dispose(); + m_navigationText = null; + m_deleteProfileText.Dispose(); + m_deleteProfileText = null; + base.Dispose(); + } + } + + public override void RefreshTextObjs() + { + /* + if (InputManager.GamePadIsConnected(PlayerIndex.One)) + m_navigationText.Text = "[Button:LeftStick] " + LocaleBuilder.getResourceString("LOC_ID_PROFILE_SEL_SCREEN_2"); + else + m_navigationText.Text = LocaleBuilder.getResourceString("LOC_ID_PROFILE_SEL_SCREEN_3"); + m_confirmText.Text = "[Input:" + InputMapType.MENU_CONFIRM1 + "] " + LocaleBuilder.getResourceString("LOC_ID_PROFILE_SEL_SCREEN_4"); + m_cancelText.Text = "[Input:" + InputMapType.MENU_CANCEL1 + "] " + LocaleBuilder.getResourceString("LOC_ID_PROFILE_SEL_SCREEN_5"); + m_deleteProfileText.Text = "[Input:" + InputMapType.MENU_DELETEPROFILE + "] " + LocaleBuilder.getResourceString("LOC_ID_PROFILE_SEL_SCREEN_6"); + */ + + Game.ChangeBitmapLanguage(m_title, "ProfileSelectTitle_Sprite"); + Game.ChangeBitmapLanguage(m_slot1Container.GetChildAt(2) as SpriteObj, "ProfileSlot1Text_Sprite"); + Game.ChangeBitmapLanguage(m_slot2Container.GetChildAt(2) as SpriteObj, "ProfileSlot2Text_Sprite"); + Game.ChangeBitmapLanguage(m_slot3Container.GetChildAt(2) as SpriteObj, "ProfileSlot3Text_Sprite"); + + // Update save slot text + CheckSaveHeaders(m_slot1Container, 1); + CheckSaveHeaders(m_slot2Container, 2); + CheckSaveHeaders(m_slot3Container, 3); + + base.RefreshTextObjs(); + } + } +} \ No newline at end of file diff --git a/RogueCastle/src/Screens/SkillScreen.cs b/RogueCastle/src/Screens/SkillScreen.cs new file mode 100644 index 0000000..4b0ef17 --- /dev/null +++ b/RogueCastle/src/Screens/SkillScreen.cs @@ -0,0 +1,1284 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using DS2DEngine; +using Microsoft.Xna.Framework.Graphics; +using InputSystem; +using Microsoft.Xna.Framework.Input; +using Tweener; +using Tweener.Ease; + +namespace RogueCastle +{ + public class SkillScreen : Screen + { + /* Dialogue plate object order + * 0 = Plate BG + * 1 = Skill Icon + * 2 = Skill Title + * 3 = Skill Description + * 4 = Input Description + * 5 = Stat Base Amount + * 6 = Stat Increase Amount + * 7 = Skill Cost + */ + + private SpriteObj m_bg; + private SpriteObj m_cloud1, m_cloud2, m_cloud3, m_cloud4, m_cloud5; + private SpriteObj m_selectionIcon; + private Vector2 m_selectedTraitIndex; + + private KeyIconTextObj m_continueText; + private KeyIconTextObj m_toggleIconsText; + private KeyIconTextObj m_confirmText; + private KeyIconTextObj m_navigationText; + private SpriteObj m_titleText; + + private ObjContainer m_dialoguePlate; + private ObjContainer m_manor; + private bool m_fadingIn = false; + private bool m_cameraTweening = false; + + private bool m_lockControls = false; + + private ImpactEffectPool m_impactEffectPool; + private GameObj m_shakeObj; + private float m_shakeTimer = 0; + private int m_shakeAmount = 2; + private float m_shakeDelay = 0.01f; + private bool m_shookLeft = false; + private float m_shakeDuration; + + private TextObj m_playerMoney; + private SpriteObj m_coinIcon; + + private SpriteObj m_skillIcon; + private TextObj m_skillTitle; + private TextObj m_skillDescription; + private KeyIconTextObj m_inputDescription; + private SpriteObj m_descriptionDivider; + private TextObj m_skillCurrent; + private TextObj m_skillUpgrade; + private TextObj m_skillLevel; + + private TextObj m_skillCost; + private SpriteObj m_skillCostBG; + + private SkillObj m_lastSkillObj; // for switching languages and updating display + + public SkillScreen() + { + m_selectedTraitIndex = new Vector2(5, 9); // Hack. That is the array index for the starting trait. + m_impactEffectPool = new ImpactEffectPool(1000); + this.DrawIfCovered = true; + } + + public override void LoadContent() + { + m_impactEffectPool.Initialize(); + + m_manor = new ObjContainer("TraitsCastle_Character"); + m_manor.Scale = new Vector2(2, 2); + m_manor.ForceDraw = true; + for (int i = 0; i < m_manor.NumChildren; i++) + { + m_manor.GetChildAt(i).Visible = false; + m_manor.GetChildAt(i).Opacity = 0; + } + + // Adding Dialogue Plate skill info text + m_dialoguePlate = new ObjContainer("TraitsScreenPlate_Container"); + m_dialoguePlate.ForceDraw = true; + m_dialoguePlate.Position = new Vector2(1320 - m_dialoguePlate.Width / 2, 720 / 2); + + m_skillIcon = new SpriteObj("Icon_Health_Up_Sprite"); + m_skillIcon.Position = new Vector2(-110, -200); + m_dialoguePlate.AddChild(m_skillIcon); + + m_skillTitle = new TextObj(Game.JunicodeFont); + m_skillTitle.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_skillTitle); // dummy locID to add TextObj to language refresh list + m_skillTitle.DropShadow = new Vector2(2, 2); + m_skillTitle.TextureColor = new Color(236, 197, 132); + m_skillTitle.Position = new Vector2(m_skillIcon.Bounds.Right + 15, m_skillIcon.Y); + m_skillTitle.FontSize = 12; + m_dialoguePlate.AddChild(m_skillTitle); + + m_skillDescription = new TextObj(Game.JunicodeFont); + m_skillDescription.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_skillDescription); // dummy locID to add TextObj to language refresh list + m_skillDescription.Position = new Vector2(m_dialoguePlate.GetChildAt(1).X - 30, m_dialoguePlate.GetChildAt(1).Bounds.Bottom + 20); + m_skillDescription.FontSize = 10; + m_skillDescription.DropShadow = new Vector2(2, 2); + m_skillDescription.TextureColor = new Color(228, 218, 208); + m_skillDescription.WordWrap(m_dialoguePlate.Width - 50); + m_dialoguePlate.AddChild(m_skillDescription); + + m_inputDescription = new KeyIconTextObj(Game.JunicodeFont); + m_inputDescription.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_inputDescription); // dummy locID to add TextObj to language refresh list + m_inputDescription.Position = new Vector2(m_skillIcon.X - 30, m_skillDescription.Bounds.Bottom + 20); + m_inputDescription.FontSize = 10; + m_inputDescription.DropShadow = new Vector2(2, 2); + m_inputDescription.TextureColor = new Color(228, 218, 208); + m_inputDescription.WordWrap(m_dialoguePlate.Width - 50); + m_dialoguePlate.AddChild(m_inputDescription); + + m_descriptionDivider = new SpriteObj("Blank_Sprite"); + m_descriptionDivider.ScaleX = 250f / m_descriptionDivider.Width; + m_descriptionDivider.ScaleY = 0.25f; + m_descriptionDivider.ForceDraw = true; + m_descriptionDivider.DropShadow = new Vector2(2, 2); + + m_skillCurrent = new TextObj(Game.JunicodeFont); + m_skillCurrent.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_skillCurrent); // dummy locID to add TextObj to language refresh list + m_skillCurrent.Position = new Vector2(m_inputDescription.X, m_inputDescription.Bounds.Bottom + 10); + m_skillCurrent.FontSize = 10; + m_skillCurrent.DropShadow = new Vector2(2, 2); + m_skillCurrent.TextureColor = new Color(228, 218, 208); + m_skillCurrent.WordWrap(m_dialoguePlate.Width - 50); + m_dialoguePlate.AddChild(m_skillCurrent); + + m_skillUpgrade = m_skillCurrent.Clone() as TextObj; + m_skillUpgrade.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_skillUpgrade); // dummy locID to add TextObj to language refresh list + m_skillUpgrade.Y += 15; + //m_skillUpgrade.TextureColor = Color.Yellow; + m_dialoguePlate.AddChild(m_skillUpgrade); + + m_skillLevel = m_skillUpgrade.Clone() as TextObj; + m_skillLevel.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_skillLevel); // dummy locID to add TextObj to language refresh list + m_skillLevel.Y += 15; + //m_skillLevel.TextureColor = new Color(228, 218, 208); + m_dialoguePlate.AddChild(m_skillLevel); + + m_skillCost = new TextObj(Game.JunicodeFont); + m_skillCost.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_skillCost); // dummy locID to add TextObj to language refresh list + //skillCost.Position = new Vector2(skillIcon.X, m_dialoguePlate.Bounds.Bottom - 20); + m_skillCost.X = m_skillIcon.X; + m_skillCost.Y = 182; + m_skillCost.FontSize = 10; + m_skillCost.DropShadow = new Vector2(2, 2); + m_skillCost.TextureColor = Color.Yellow; + m_dialoguePlate.AddChild(m_skillCost); + + m_skillCostBG = new SpriteObj("SkillTreeGoldIcon_Sprite"); + m_skillCostBG.Position = new Vector2(-180, 180); + m_dialoguePlate.AddChild(m_skillCostBG); + + m_dialoguePlate.ForceDraw = true; + + //////////////////////////////////////////// + + m_bg = new SpriteObj("TraitsBG_Sprite"); + m_bg.Scale = new Vector2(1320f / m_bg.Width, 1320f / m_bg.Width); + m_bg.ForceDraw = true; + + m_cloud1 = new SpriteObj("TraitsCloud1_Sprite") { ForceDraw = true }; + m_cloud2 = new SpriteObj("TraitsCloud2_Sprite") { ForceDraw = true }; + m_cloud3 = new SpriteObj("TraitsCloud3_Sprite") { ForceDraw = true }; + m_cloud4 = new SpriteObj("TraitsCloud4_Sprite") { ForceDraw = true }; + m_cloud5 = new SpriteObj("TraitsCloud5_Sprite") { ForceDraw = true }; + float opacity = 1f; + m_cloud1.Opacity = opacity; + m_cloud2.Opacity = opacity; + m_cloud3.Opacity = opacity; + m_cloud4.Opacity = opacity; + m_cloud5.Opacity = opacity; + m_cloud1.Position = new Vector2(CDGMath.RandomInt(0, 1320 + 200), CDGMath.RandomInt(0, 720 / 2)); + m_cloud2.Position = new Vector2(CDGMath.RandomInt(0, 1320 + 200), CDGMath.RandomInt(0, 720 / 2)); + m_cloud3.Position = new Vector2(CDGMath.RandomInt(0, 1320 + 200), CDGMath.RandomInt(0, 720 / 2)); + m_cloud4.Position = new Vector2(CDGMath.RandomInt(0, 1320 + 200), CDGMath.RandomInt(0, 720 / 2)); + m_cloud5.Position = new Vector2(CDGMath.RandomInt(0, 1320 + 200), CDGMath.RandomInt(0, 720 / 2)); + + m_selectionIcon = new SpriteObj("IconHalo_Sprite"); + m_selectionIcon.ForceDraw = true; + m_selectionIcon.AnimationDelay = 1 / 10f; + m_selectionIcon.PlayAnimation(true); + m_selectionIcon.Scale = new Vector2(1.1f, 1.1f); + + m_titleText = new SpriteObj("ManorTitleText_Sprite"); + m_titleText.X = m_titleText.Width/2f + 20; + m_titleText.Y = GlobalEV.ScreenHeight * 0.09f; + m_titleText.ForceDraw = true; + + m_continueText = new KeyIconTextObj(Game.JunicodeFont); + m_continueText.ForceDraw = true; + m_continueText.FontSize = 12; + m_continueText.DropShadow = new Vector2(2, 2); + m_continueText.Position = new Vector2(1320 - 20, 630); + m_continueText.Align = Types.TextAlign.Right; + m_continueText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_continueText); // dummy locID to add TextObj to language refresh list + + m_toggleIconsText = new KeyIconTextObj(Game.JunicodeFont); + m_toggleIconsText.ForceDraw = true; + m_toggleIconsText.FontSize = 12; + m_toggleIconsText.DropShadow = new Vector2(2, 2); + m_toggleIconsText.Position = new Vector2(m_continueText.X, m_continueText.Y + 40); + m_toggleIconsText.Align = Types.TextAlign.Right; + m_toggleIconsText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_toggleIconsText); // dummy locID to add TextObj to language refresh list + + m_confirmText = new KeyIconTextObj(Game.JunicodeFont); + m_confirmText.Align = Types.TextAlign.Right; + m_confirmText.FontSize = 12; + m_confirmText.DropShadow = new Vector2(2, 2); + m_confirmText.Position = new Vector2(1320 - 20, 10); + m_confirmText.ForceDraw = true; + m_confirmText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_confirmText); // dummy locID to add TextObj to language refresh list + + m_navigationText = new KeyIconTextObj(Game.JunicodeFont); + m_navigationText.Align = Types.TextAlign.Right; + m_navigationText.FontSize = 12; + m_navigationText.DropShadow = new Vector2(2, 2); + m_navigationText.Position = new Vector2(m_confirmText.X, m_confirmText.Y + 40); + m_navigationText.ForceDraw = true; + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_navigationText); // dummy locID to add TextObj to language refresh list + + m_coinIcon = new SpriteObj("CoinIcon_Sprite"); + m_coinIcon.Position = new Vector2(1100, 585); + m_coinIcon.Scale = new Vector2(0.9f, 0.9f); + m_coinIcon.ForceDraw = true; + + m_playerMoney = new TextObj(Game.GoldFont); + m_playerMoney.Align = Types.TextAlign.Left; + m_playerMoney.Text = "1000"; + m_playerMoney.FontSize = 30; + m_playerMoney.Position = new Vector2(m_coinIcon.X + 35, m_coinIcon.Y); + m_playerMoney.ForceDraw = true; + + base.LoadContent(); + } + + public override void OnEnter() + { + bool unlockAchievement = true; + foreach (SkillObj skillAchievement in SkillSystem.SkillArray) + { + if (skillAchievement.CurrentLevel < 1) + { + unlockAchievement = false; + break; + } + } + + if (unlockAchievement == true) + GameUtil.UnlockAchievement("FEAR_OF_DECISIONS"); + + if (Game.PlayerStats.CurrentLevel >= 50) + GameUtil.UnlockAchievement("FEAR_OF_WEALTH"); + + m_lockControls = false; + + m_manor.GetChildAt(23).Visible = true; + m_manor.GetChildAt(23).Opacity = 1; + + Camera.Position = new Vector2(1320 / 2f, 720 / 2f); + + SkillObj[] traitArray = SkillSystem.GetSkillArray(); + for (int i = 0; i < traitArray.Length; i++) + { + if (traitArray[i].CurrentLevel > 0) + SetVisible(traitArray[i], false); + } + + if (SoundManager.IsMusicPlaying == false) + SoundManager.PlayMusic("SkillTreeSong", true, 1); + + SkillObj skill = SkillSystem.GetSkill((int)m_selectedTraitIndex.X, (int)m_selectedTraitIndex.Y); + m_selectionIcon.Position = SkillSystem.GetSkillPosition(skill); + + UpdateDescriptionPlate(skill); + + m_dialoguePlate.Visible = true; + m_confirmText.Text = LocaleBuilder.getString("LOC_ID_SKILL_SCREEN_1_NEW", m_confirmText); + //m_confirmText.Text = "[Input:" + InputMapType.MENU_CONFIRM1 + "] " + LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_1"); + m_toggleIconsText.Text = LocaleBuilder.getString("LOC_ID_SKILL_SCREEN_2_NEW", m_toggleIconsText); + //m_toggleIconsText.Text = "[Input:" + InputMapType.MENU_MAP + "] " + LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_2"); + m_continueText.Text = LocaleBuilder.getString("LOC_ID_SKILL_SCREEN_3_NEW", m_continueText); + //m_continueText.Text = "[Input:" + InputMapType.MENU_CANCEL1 + "] " + LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_3"); + + if (InputManager.GamePadIsConnected(PlayerIndex.One) == true) + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_SKILL_SCREEN_4_NEW", m_navigationText); + //m_navigationText.Text = "[Button:LeftStick] " + LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_4"); + else + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_SKILL_SCREEN_5", m_navigationText); + + SkillSystem.UpdateAllTraitSprites(); + + RefreshTextObjs(); + + base.OnEnter(); + } + + public override void OnExit() + { + Game.ScreenManager.Player.AttachedLevel.UpdatePlayerSpellIcon(); + SoundManager.StopMusic(0.5f); + (ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.UpgradeData, SaveType.PlayerData); + base.OnExit(); + } + + public void SetVisible(SkillObj trait, bool fadeIn) + { + int manorIndex = SkillSystem.GetManorPiece(trait); + + if (fadeIn == true) + SetManorPieceVisible(manorIndex, trait); + else + { + GameObj manorObj = m_manor.GetChildAt(manorIndex); + manorObj.Opacity = 1; + manorObj.Visible = true; + foreach (SkillObj linkedTrait in SkillSystem.GetAllConnectingTraits(trait)) + { + if (linkedTrait.Visible == false) + { + linkedTrait.Visible = true; + linkedTrait.Opacity = 1; + } + } + + // Hack to add shadows to specific pieces of the manor. + if (m_manor.GetChildAt(7).Visible == true && m_manor.GetChildAt(16).Visible == true) + (m_manor.GetChildAt(7) as SpriteObj).GoToFrame(2); + + if (m_manor.GetChildAt(6).Visible == true && m_manor.GetChildAt(16).Visible == true) + (m_manor.GetChildAt(6) as SpriteObj).GoToFrame(2); + + if (m_manor.GetChildAt(2).Visible == true) + { + SpriteObj flag = m_manor.GetChildAt(32) as SpriteObj; + flag.Visible = true; + flag.Opacity = 1; + flag.PlayAnimation(true); + flag.OverrideParentAnimationDelay = true; + flag.AnimationDelay = 1 / 30f; + flag.Visible = true; + } + } + } + + public void SetManorPieceVisible(int manorIndex, SkillObj skillObj) + { + GameObj manorPiece = m_manor.GetChildAt(manorIndex); + float transitionDuration = 0; + + if (manorPiece.Visible == false) + { + m_lockControls = true; + //Console.WriteLine(manorIndex); + manorPiece.Visible = true; + Vector2 cloudPos = new Vector2(manorPiece.AbsPosition.X, manorPiece.AbsBounds.Bottom); + + switch (manorIndex) + { + case (0): + case (11): + case (17): + case (22): + case (24): + case (27): + case (28): + // fade code goes here. + transitionDuration = 0.5f; + manorPiece.Opacity = 0; + Tween.To(manorPiece, transitionDuration, Tween.EaseNone, "Opacity", "1"); + break; + case (4): + // Special case for 4. + cloudPos.Y -= 50; + manorPiece.Opacity = 1; + transitionDuration = 3; + manorPiece.Y += manorPiece.Height * 2; + SoundManager.PlaySound("skill_tree_reveal_01", "skill_tree_reveal_02"); + Tween.By(manorPiece, transitionDuration, Quad.EaseOut, "Y", (-(manorPiece.Height * 2)).ToString()); + m_impactEffectPool.SkillTreeDustDuration(cloudPos, true, manorPiece.Width * 2 * 0.25f, transitionDuration); + break; + case (7): + // Special case for 7. + cloudPos.X = manorPiece.AbsBounds.Right - (manorPiece.Width * 2 * 0.25f); + manorPiece.Opacity = 1; + transitionDuration = 3; + manorPiece.Y += manorPiece.Height * 2; + SoundManager.PlaySound("skill_tree_reveal_01", "skill_tree_reveal_02"); + + Tween.By(manorPiece, transitionDuration, Quad.EaseOut, "Y", (-(manorPiece.Height * 2)).ToString()); + m_impactEffectPool.SkillTreeDustDuration(cloudPos, true, manorPiece.Width * 2 * 0.25f, transitionDuration); + break; + case (18): + case (19): + // Special case for 18 and 19 + manorPiece.Opacity = 1; + transitionDuration = 3; + manorPiece.Y += manorPiece.Height * 2; + SoundManager.PlaySound("skill_tree_reveal_01", "skill_tree_reveal_02"); + + Tween.By(manorPiece, transitionDuration, Quad.EaseOut, "Y", (-(manorPiece.Height * 2)).ToString()); + m_impactEffectPool.SkillTreeDustDuration(cloudPos, true, manorPiece.Width * 2 * 0.2f, transitionDuration); + break; + case (16): + // Special case for 16. + manorPiece.Opacity = 1; + transitionDuration = 3; + manorPiece.Y += manorPiece.Height * 2; + SoundManager.PlaySound("skill_tree_reveal_01", "skill_tree_reveal_02"); + + Tween.By(manorPiece, transitionDuration, Quad.EaseOut, "Y", (-(manorPiece.Height * 2)).ToString()); + m_impactEffectPool.SkillTreeDustDuration(cloudPos, true, manorPiece.Width * 2 * 0.5f, transitionDuration); + break; + case (8): + // Special case for 8. + cloudPos.X = manorPiece.AbsBounds.Right - (manorPiece.Width * 2 * 0.25f); + manorPiece.Opacity = 1; + transitionDuration = 3; + manorPiece.Y += manorPiece.Height * 2; + SoundManager.PlaySound("skill_tree_reveal_01", "skill_tree_reveal_02"); + + Tween.By(manorPiece, transitionDuration, Quad.EaseOut, "Y", (-(manorPiece.Height * 2)).ToString()); + m_impactEffectPool.SkillTreeDustDuration(cloudPos, true, manorPiece.Width * 2 * 0.25f, transitionDuration); + break; + case (10): + case (21): + // Grow Upward Slowly + manorPiece.Opacity = 1; + transitionDuration = 3; + manorPiece.Y += manorPiece.Height * 2; + SoundManager.PlaySound("skill_tree_reveal_01", "skill_tree_reveal_02"); + + Tween.By(manorPiece, transitionDuration, Quad.EaseOut, "Y", (-(manorPiece.Height * 2)).ToString()); + m_impactEffectPool.SkillTreeDustDuration(cloudPos, true, manorPiece.Width * 2, transitionDuration); + break; + case (2): + // Special case for 2. Grow quickly + flag appearing. + manorPiece.Opacity = 1; + transitionDuration = 1.5f; + manorPiece.Y += manorPiece.Height * 2; + SoundManager.PlaySound("skill_tree_reveal_short_01", "skill_tree_reveal_short_02"); + + Tween.By(manorPiece, transitionDuration, Quad.EaseOut, "Y", (-(manorPiece.Height * 2)).ToString()); + m_impactEffectPool.SkillTreeDustDuration(cloudPos, true, manorPiece.Width * 2, transitionDuration); + + SpriteObj flag = m_manor.GetChildAt(32) as SpriteObj; + flag.PlayAnimation(true); + flag.OverrideParentAnimationDelay = true; + flag.AnimationDelay = 1 / 30f; + flag.Visible = true; + flag.Opacity = 0; + Tween.To(flag, 0.5f, Tween.EaseNone, "delay", transitionDuration.ToString(), "Opacity", "1"); + break; + case (3): + case(6): + case(9): + case(13): + case(15): + case(25): + case(20): + // Grow upward quickly. + manorPiece.Opacity = 1; + transitionDuration = 1f; + manorPiece.Y += manorPiece.Height * 2; + SoundManager.PlaySound("skill_tree_reveal_short_01", "skill_tree_reveal_short_02"); + + Tween.By(manorPiece, transitionDuration, Quad.EaseOut, "Y", (-(manorPiece.Height * 2)).ToString()); + m_impactEffectPool.SkillTreeDustDuration(cloudPos, true, manorPiece.Width * 2, transitionDuration); + break; + case (1): + case (5): + // Grow Right + manorPiece.Opacity = 1; + transitionDuration = 1f; + manorPiece.X -= manorPiece.Width * 2; + SoundManager.PlaySound("skill_tree_reveal_short_01", "skill_tree_reveal_short_02"); + + Tween.By(manorPiece, transitionDuration, Quad.EaseOut, "X", (manorPiece.Width * 2).ToString()); + m_impactEffectPool.SkillTreeDustDuration(cloudPos, false, manorPiece.Height * 2, transitionDuration); + break; + case (12): + case (14): + // Grow Left + manorPiece.Opacity = 1; + transitionDuration = 1; + manorPiece.X += manorPiece.Width * 2; + cloudPos.X = manorPiece.AbsPosition.X - 60; + SoundManager.PlaySound("skill_tree_reveal_short_01", "skill_tree_reveal_short_02"); + + Tween.By(manorPiece, transitionDuration, Quad.EaseOut, "X", (-(manorPiece.Width * 2)).ToString()); + m_impactEffectPool.SkillTreeDustDuration(cloudPos, false, manorPiece.Height * 2, transitionDuration); + break; + case (29): + case (30): + case (31): + // Scale up. + Tween.RunFunction(0.25f, typeof(SoundManager), "PlaySound", "skill_tree_reveal_bounce"); + manorPiece.Opacity = 1; + manorPiece.Scale = Vector2.Zero; + transitionDuration = 1; + Tween.To(manorPiece, transitionDuration, Bounce.EaseOut, "ScaleX", "1", "ScaleY", "1"); + break; + default: + // Drop the very first piece. + transitionDuration = 0.7f; + Vector2 cloudPos2 = new Vector2(manorPiece.AbsPosition.X, manorPiece.AbsBounds.Bottom); + manorPiece.Opacity = 1; + manorPiece.Y -= 720; + Tween.By(manorPiece, transitionDuration, Quad.EaseIn, "Y", "720"); + Tween.AddEndHandlerToLastTween(m_impactEffectPool, "SkillTreeDustEffect", cloudPos2, true, manorPiece.Width * 2); + Tween.RunFunction(transitionDuration, this, "ShakeScreen", 5, true, true); + Tween.RunFunction(transitionDuration + 0.2f, this, "StopScreenShake"); + //SoundManager.PlaySound("Upgrade_Splash_Tower"); + break; + case (23): // Don't do anything for 23 (ground piece) + break; + } + } + + Tween.RunFunction(transitionDuration, this, "SetSkillIconVisible", skillObj); + + // Hack to add shadows to specific pieces of the manor. + if (m_manor.GetChildAt(7).Visible == true && m_manor.GetChildAt(16).Visible == true) + (m_manor.GetChildAt(7) as SpriteObj).GoToFrame(2); + + if (m_manor.GetChildAt(6).Visible == true && m_manor.GetChildAt(16).Visible == true) + (m_manor.GetChildAt(6) as SpriteObj).GoToFrame(2); + } + + public void SetSkillIconVisible(SkillObj skill) + { + float delay = 0; + foreach (SkillObj linkedTrait in SkillSystem.GetAllConnectingTraits(skill)) + { + if (linkedTrait.Visible == false) + { + linkedTrait.Visible = true; + linkedTrait.Opacity = 0; + Tweener.Tween.To(linkedTrait, 0.2f, Tweener.Ease.Linear.EaseNone, "Opacity", "1"); + delay += 0.2f; + } + } + Tween.RunFunction(delay, this, "UnlockControls"); + Tween.RunFunction(delay, this, "CheckForSkillUnlock", skill, true); + } + + public void CheckForSkillUnlock(SkillObj skill, bool displayScreen) + { + byte skillUnlockType = SkillUnlockType.None; + switch(skill.TraitType) + { + case (SkillType.Smithy): + skillUnlockType = SkillUnlockType.Blacksmith; + break; + case (SkillType.Enchanter): + skillUnlockType = SkillUnlockType.Enchantress; + break; + case (SkillType.Architect): + skillUnlockType = SkillUnlockType.Architect; + break; + case (SkillType.Ninja_Unlock): + skillUnlockType = SkillUnlockType.Ninja; + break; + case (SkillType.Banker_Unlock): + skillUnlockType = SkillUnlockType.Banker; + break; + case (SkillType.Lich_Unlock): + skillUnlockType = SkillUnlockType.Lich; + break; + case (SkillType.Spellsword_Unlock): + skillUnlockType = SkillUnlockType.SpellSword; + break; + case (SkillType.Knight_Up): + skillUnlockType = SkillUnlockType.KnightUp; + if (Game.PlayerStats.Class == ClassType.Knight) Game.PlayerStats.Class = ClassType.Knight2; + break; + case (SkillType.Barbarian_Up): + skillUnlockType = SkillUnlockType.BarbarianUp; + if (Game.PlayerStats.Class == ClassType.Barbarian) Game.PlayerStats.Class = ClassType.Barbarian2; + break; + case (SkillType.Mage_Up): + skillUnlockType = SkillUnlockType.WizardUp; + if (Game.PlayerStats.Class == ClassType.Wizard) Game.PlayerStats.Class = ClassType.Wizard2; + break; + case (SkillType.Ninja_Up): + skillUnlockType = SkillUnlockType.NinjaUp; + if (Game.PlayerStats.Class == ClassType.Ninja) Game.PlayerStats.Class = ClassType.Ninja2; + break; + case (SkillType.Assassin_Up): + skillUnlockType = SkillUnlockType.AssassinUp; + if (Game.PlayerStats.Class == ClassType.Assassin) Game.PlayerStats.Class = ClassType.Assassin2; + break; + case (SkillType.Banker_Up): + skillUnlockType = SkillUnlockType.BankerUp; + if (Game.PlayerStats.Class == ClassType.Banker) Game.PlayerStats.Class = ClassType.Banker2; + break; + case (SkillType.SpellSword_Up): + skillUnlockType = SkillUnlockType.SpellSwordUp; + if (Game.PlayerStats.Class == ClassType.SpellSword) Game.PlayerStats.Class = ClassType.SpellSword2; + break; + case (SkillType.Lich_Up): + skillUnlockType = SkillUnlockType.LichUp; + if (Game.PlayerStats.Class == ClassType.Lich) Game.PlayerStats.Class = ClassType.Lich2; + break; + case (SkillType.SuperSecret): + skillUnlockType = SkillUnlockType.Dragon; + break; + } + + if (skillUnlockType != SkillUnlockType.None && displayScreen == true) + { + List data = new List(); + data.Add(skillUnlockType); + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.SkillUnlock, true, data); + } + } + + public void UnlockControls() + { + m_lockControls = false; + } + + public void StartShake(GameObj obj, float shakeDuration) + { + m_shakeDuration = shakeDuration; + m_shakeObj = obj; + m_shakeTimer = m_shakeDelay; + m_shookLeft = false; + } + + public void EndShake() + { + if (m_shookLeft == true) + m_shakeObj.X += m_shakeAmount; + + m_shakeObj = null; + m_shakeTimer = 0; + } + + public void FadingComplete() + { + m_fadingIn = false; + } + + public override void Update(GameTime gameTime) + { + // Special Handling for secret trait. + if (m_cameraTweening == false) + { + if (m_selectedTraitIndex != new Vector2(7, 1) && Camera.Y != (720 / 2f)) + { + m_cameraTweening = true; + Tween.To(Camera, 0.5f, Quad.EaseOut, "Y", (720 / 2f).ToString()); + Tween.AddEndHandlerToLastTween(this, "EndCameraTween"); + } + } + + float elapsedTime = (float)(gameTime.ElapsedGameTime.TotalSeconds); + + if (m_cloud1.Bounds.Right < -100) + m_cloud1.Position = new Vector2(CDGMath.RandomInt(1320 + 100, 1320 + 200), CDGMath.RandomInt(0, 720 / 2)); + if (m_cloud2.Bounds.Right < -100) + m_cloud2.Position = new Vector2(CDGMath.RandomInt(1320 + 100, 1320 + 200), CDGMath.RandomInt(0, 720 / 2)); + if (m_cloud3.Bounds.Right < -100) + m_cloud3.Position = new Vector2(CDGMath.RandomInt(1320 + 100, 1320 + 200), CDGMath.RandomInt(0, 720 / 2)); + if (m_cloud4.Bounds.Right < -100) + m_cloud4.Position = new Vector2(CDGMath.RandomInt(1320 + 100, 1320 + 200), CDGMath.RandomInt(0, 720 / 2)); + if (m_cloud5.Bounds.Right < -100) + m_cloud5.Position = new Vector2(CDGMath.RandomInt(1320 + 100, 1320 + 200), CDGMath.RandomInt(0, 720 / 2)); + + m_cloud1.X -= 20 * elapsedTime; + m_cloud2.X -= 16 * elapsedTime; + m_cloud3.X -= 15 * elapsedTime; + m_cloud4.X -= 5 * elapsedTime; + m_cloud5.X -= 10 * elapsedTime; + + if (m_shakeDuration > 0) + { + m_shakeDuration -= elapsedTime; + if (m_shakeTimer > 0 && m_shakeObj != null) + { + m_shakeTimer -= elapsedTime; + if (m_shakeTimer <= 0) + { + m_shakeTimer = m_shakeDelay; + if (m_shookLeft == true) + { + m_shookLeft = false; + m_shakeObj.X += m_shakeAmount; + } + else + { + m_shakeObj.X -= m_shakeAmount; + m_shookLeft = true; + } + } + } + } + + if (m_shakeScreen == true) + UpdateShake(); + + base.Update(gameTime); + } + + public override void HandleInput() + { + if (m_cameraTweening == false && m_lockControls == false) + { + bool toggledIcons = false; + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_MAP)) + { + if (SkillSystem.IconsVisible == true) + { + m_toggleIconsText.Text = LocaleBuilder.getString("LOC_ID_SKILL_SCREEN_6_NEW", m_toggleIconsText); + //m_toggleIconsText.Text = "[Input:" + InputMapType.MENU_MAP + "] " + LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_6"); + m_confirmText.Visible = false; + m_continueText.Visible = false; + m_navigationText.Visible = false; + + SkillSystem.HideAllIcons(); + m_selectionIcon.Opacity = 0; + m_dialoguePlate.Opacity = 0; + m_descriptionDivider.Opacity = 0; + m_coinIcon.Opacity = 0; + m_playerMoney.Opacity = 0; + m_titleText.Opacity = 0; + } + else + { + m_toggleIconsText.Text = LocaleBuilder.getString("LOC_ID_SKILL_SCREEN_2_NEW", m_toggleIconsText); + //m_toggleIconsText.Text = "[Input:" + InputMapType.MENU_MAP + "] " + LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_2"); + m_confirmText.Visible = true; + m_continueText.Visible = true; + m_navigationText.Visible = true; + + SkillSystem.ShowAllIcons(); + m_selectionIcon.Opacity = 1; + m_dialoguePlate.Opacity = 1; + m_descriptionDivider.Opacity = 1; + m_coinIcon.Opacity = 1; + m_playerMoney.Opacity = 1; + m_titleText.Opacity = 1; + } + toggledIcons = true; + } + + if (SkillSystem.IconsVisible == true) + { + Vector2 previousTraitIndex = m_selectedTraitIndex; + //m_descriptionText.Visible = false; + //m_dialoguePlate.Visible = false; + + Vector2 traitSelected = new Vector2(-1, -1); + + + if (Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_UP2)) + { + traitSelected = SkillSystem.GetSkillLink((int)m_selectedTraitIndex.X, (int)m_selectedTraitIndex.Y).TopLink; + + // Special handling for the secret trait. + SkillObj secretSkill = SkillSystem.GetSkill(SkillType.SuperSecret); + if (m_cameraTweening == false && secretSkill.Visible == true) + { + if (traitSelected == new Vector2(7, 1)) + { + m_cameraTweening = true; + Tween.To(Camera, 0.5f, Quad.EaseOut, "Y", ((720 / 2f - 300)).ToString()); + Tween.AddEndHandlerToLastTween(this, "EndCameraTween"); + } + } + } + else if ((Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_DOWN2))) + { + traitSelected = SkillSystem.GetSkillLink((int)m_selectedTraitIndex.X, (int)m_selectedTraitIndex.Y).BottomLink; + } + + if ((Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_LEFT2))) + { + traitSelected = SkillSystem.GetSkillLink((int)m_selectedTraitIndex.X, (int)m_selectedTraitIndex.Y).LeftLink; + } + else if ((Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT1) || Game.GlobalInput.JustPressed(InputMapType.PLAYER_RIGHT2))) + { + traitSelected = SkillSystem.GetSkillLink((int)m_selectedTraitIndex.X, (int)m_selectedTraitIndex.Y).RightLink; + } + + if (traitSelected.X != -1 && traitSelected.Y != -1) + { + SkillObj traitToCheck = SkillSystem.GetSkill((int)traitSelected.X, (int)traitSelected.Y); + if (traitToCheck.TraitType != SkillType.Null && traitToCheck.Visible == true) + m_selectedTraitIndex = traitSelected; + } + + if (previousTraitIndex != m_selectedTraitIndex) + { + SkillObj trait = SkillSystem.GetSkill((int)m_selectedTraitIndex.X, (int)m_selectedTraitIndex.Y); + m_selectionIcon.Position = SkillSystem.GetSkillPosition(trait); + + UpdateDescriptionPlate(trait); + SoundManager.PlaySound("ShopMenuMove"); + + trait.Scale = new Vector2(1.1f, 1.1f); + Tween.To(trait, 0.1f, Back.EaseOutLarge, "ScaleX", "1", "ScaleY", "1"); + + m_dialoguePlate.Visible = true; + } + + SkillObj selectedTrait = SkillSystem.GetSkill((int)m_selectedTraitIndex.X, (int)m_selectedTraitIndex.Y); + if ((Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + && Game.PlayerStats.Gold >= selectedTrait.TotalCost && selectedTrait.CurrentLevel < selectedTrait.MaxLevel) + { //TEDDY SWITCHED XP TO GOLD HERE TOO. + SoundManager.PlaySound("TraitUpgrade"); + if (m_fadingIn == false) + { + //TEDDY TEST TO MAKE EVERYTHING COST GOLD //Game.PlayerStats.XP -= selectedTrait.TotalCost; + Game.PlayerStats.Gold -= selectedTrait.TotalCost; + SetVisible(selectedTrait, true); + SkillSystem.LevelUpTrait(selectedTrait, true); + + if (selectedTrait.CurrentLevel >= selectedTrait.MaxLevel) + SoundManager.PlaySound("TraitMaxxed"); + //(ScreenManager.Game as Game).SaveManager.SaveGame(SaveGameManager.SaveType.UpgradeData, null); + //Tweener.Tween.RunFunction(0.5f, (ScreenManager.Game as Game).SaveManager, "SaveGame", SaveGameManager.SaveType.PlayerData, typeof(ProceduralLevelScreen)); + //(ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.UpgradeData, SaveType.PlayerData); + UpdateDescriptionPlate(selectedTrait); + } + } + else if ((Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + && Game.PlayerStats.Gold < selectedTrait.TotalCost) + SoundManager.PlaySound("TraitPurchaseFail"); //TEDDY SWITCHED XP TO GOLD HERE TOO + + if ((Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) && toggledIcons == false) + { + m_lockControls = true; + RCScreenManager screenManager = ScreenManager as RCScreenManager; + ProceduralLevelScreen levelScreen = screenManager.GetLevelScreen(); + levelScreen.Reset(); + //screenManager.HideCurrentScreen(); + if (levelScreen.CurrentRoom is StartingRoomObj) + { + screenManager.StartWipeTransition(); + Tween.RunFunction(0.2f, screenManager, "HideCurrentScreen"); + Tween.RunFunction(0.2f, levelScreen.CurrentRoom, "OnEnter"); + //levelScreen.CurrentRoom.OnEnter(); // Hack to force starting room OnEnter() when exiting trait screen. + } + else + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.StartingRoom, true, null); + + //(ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Lineage, true); + } + + if (LevelEV.ENABLE_DEBUG_INPUT == true) + HandleDebugInput(); + + //if (InputManager.JustPressed(Keys.H, null)) + // ZoomOutAllObjects(); + } + base.HandleInput(); + } + } + + private void HandleDebugInput() + { + if (InputManager.JustPressed(Keys.Q, PlayerIndex.One)) + { + foreach (SkillObj skill in SkillSystem.SkillArray) + { + if (skill.CurrentLevel < skill.MaxLevel) + { + SetVisible(skill, false); + SkillSystem.LevelUpTrait(skill, false); + CheckForSkillUnlock(skill, false); + } + } + } + } + + public void EndCameraTween() + { + m_cameraTweening = false; + } + + public void UpdateDescriptionPlate(SkillObj trait) + { + /* Dialogue plate object order + * 0 = Plate BG + * 1 = Skill Icon + * 2 = Skill Title + * 3 = Skill Description + * 4 = Input Description + * 5 = Stat Base Amount + * 6 = Stat Increase Amount + * 7 = Skill Cost + */ + string spriteName = trait.IconName; + spriteName = spriteName.Replace("Locked", ""); + spriteName = spriteName.Replace("Max", ""); + + m_skillIcon.ChangeSprite(spriteName); + m_skillTitle.Text = LocaleBuilder.getResourceString(trait.NameLocID); + m_skillDescription.Text = LocaleBuilder.getResourceString(trait.DescLocID); + m_skillDescription.WordWrap(280); + m_inputDescription.Text = LocaleBuilder.getResourceString(trait.InputDescLocID); + //m_inputDescription.Text = LocaleBuilder.getResourceString(trait.InputDescLocIDs[0]) + trait.InputDescLocIDs[1] + LocaleBuilder.getResourceString(trait.InputDescLocIDs[2]); + m_inputDescription.WordWrap(280); + m_inputDescription.Y = m_skillDescription.Bounds.Bottom + 10; + + float statBaseAmount = TraitStatType.GetTraitStat(trait.TraitType); + if (statBaseAmount > -1) + { + // Setting the text for the current base data for the skil + // Hack added to make sure crit chance up and gold gain up stats are displayed correctly. + if (statBaseAmount < 1 || trait.TraitType == SkillType.Gold_Gain_Up || trait.TraitType == SkillType.Crit_Chance_Up) // Converting statBaseAmount to a percentage. + { + statBaseAmount *= 100; + statBaseAmount = (int)(Math.Round(statBaseAmount, MidpointRounding.AwayFromZero)); + } + + if (statBaseAmount == 0) + { + statBaseAmount = trait.ModifierAmount; + + // Special handling for crit chance up. + if (trait.TraitType == SkillType.Crit_Chance_Up) + { + statBaseAmount *= 100; + statBaseAmount = (int)(Math.Round(statBaseAmount, MidpointRounding.AwayFromZero)); + } + } + + string colon = ": "; + switch (LocaleBuilder.languageType) + { + case(LanguageType.French): + colon = " : "; + break; + } + m_skillCurrent.Text = LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_7") + colon + statBaseAmount + trait.UnitLocIDs[0] + LocaleBuilder.getResourceString(trait.UnitLocIDs[1]); + + // Setting the text for the upgrade data for the skill. + if (trait.CurrentLevel < trait.MaxLevel) + { + float traitPerLevelModifier = trait.PerLevelModifier; + if (traitPerLevelModifier < 1 && trait.TraitType != SkillType.Invuln_Time_Up) // Converting trait's per level modifier to percentage. + { + traitPerLevelModifier *= 100; + if (trait.TraitType != SkillType.Death_Dodge) + traitPerLevelModifier = (int)(Math.Round(traitPerLevelModifier, MidpointRounding.AwayFromZero)); + } + m_skillUpgrade.Text = LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_8") + colon + "+" + traitPerLevelModifier + trait.UnitLocIDs[0] + LocaleBuilder.getResourceString(trait.UnitLocIDs[1]); + } + else + m_skillUpgrade.Text = LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_8") + colon + "--"; + + // Setting current skill level text. + m_skillLevel.Text = LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_9") + colon + trait.CurrentLevel + "/" + trait.MaxLevel; + + // Changeds periods to commas for decimal values in certain languages (i.e. 1.5 = 1,5). + switch (LocaleBuilder.languageType) + { + case(LanguageType.French): + m_skillCurrent.Text = m_skillCurrent.Text.Replace('.', ','); + m_skillUpgrade.Text = m_skillUpgrade.Text.Replace('.', ','); + break; + } + + // Setting skill cost + string upgrade = LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_11"); //unlock + if (trait.CurrentLevel > 0) + upgrade = LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_12"); //upgrade + m_skillCost.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_10_NEW"), trait.TotalCost.ToString(), upgrade); + + // Positioning the text. + if (m_inputDescription.Text != " " && m_inputDescription.Text != "") + m_skillCurrent.Y = m_inputDescription.Bounds.Bottom + 40; + else + m_skillCurrent.Y = m_skillDescription.Bounds.Bottom + 40; + + m_skillUpgrade.Y = m_skillCurrent.Y + 30; + m_skillLevel.Y = m_skillUpgrade.Y + 30; + m_descriptionDivider.Visible = true; + } + else + { + m_skillCurrent.Text = ""; + m_skillUpgrade.Text = ""; + m_skillLevel.Text = ""; + m_descriptionDivider.Visible = false; + + string upgrade = LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_11"); //unlock + if (trait.CurrentLevel > 0) + upgrade = LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_12"); //upgrade + m_skillCost.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_10_NEW"), trait.TotalCost.ToString(), upgrade); + + } + + m_descriptionDivider.Position = new Vector2(m_skillCurrent.AbsX, m_skillCurrent.AbsY - 20); + + if (trait.CurrentLevel >= trait.MaxLevel) + { + m_skillCost.Visible = false; + m_skillCostBG.Visible = false; + } + else + { + m_skillCost.Visible = true; + m_skillCostBG.Visible = true; + } + + //if (trait.CurrentLevel < trait.MaxLevel) + // (m_dialoguePlate.GetChildAt(7) as TextObj).Text = "Costs " + trait.TotalCost + " Gold";//(m_dialoguePlate.GetChildAt(7) as TextObj).Text = "Costs " + trait.TotalCost + " Tribute"; //TEDDY REPLACING IT TO DISPLAY GOLD + //else + // (m_dialoguePlate.GetChildAt(7) as TextObj).Text = "Skill Mastered"; + + ////if (trait.DisplayStat== true) + // (m_dialoguePlate.GetChildAt(7) as TextObj).Y = m_dialoguePlate.GetChildAt(5).Bounds.Bottom + 0; + ////else + // //(m_dialoguePlate.GetChildAt(7) as TextObj).Y = m_dialoguePlate.GetChildAt(4).Bounds.Bottom + 0; + + //m_dialoguePlate.GetChildAt(3).Y = m_dialoguePlate.Height / 2f - m_dialoguePlate.GetChildAt(3).Height - 100; + + m_playerMoney.Text = Game.PlayerStats.Gold.ToString(); + + m_lastSkillObj = trait; + LanguageFormatLastSkill(); + } + + private void LanguageFormatLastSkill() + { + m_skillTitle.ScaleX = 1; + m_skillTitle.FontSize = 12; + switch (LocaleBuilder.languageType) + { + case (LanguageType.French): + switch (m_lastSkillObj.TraitType) + { + case (SkillType.Spellsword_Unlock): + case (SkillType.SpellSword_Up): + m_skillTitle.ScaleX = 0.9f; + m_skillTitle.FontSize = 11; + break; + case (SkillType.Banker_Unlock): + case (SkillType.Banker_Up): + case (SkillType.Knight_Up): + case (SkillType.Assassin_Up): + case (SkillType.Barbarian_Up): + m_skillTitle.ScaleX = 0.9f; + break; + } + break; + case (LanguageType.German): + if (m_lastSkillObj.TraitType == SkillType.Banker_Unlock || m_lastSkillObj.TraitType == SkillType.Invuln_Time_Up) + m_skillTitle.ScaleX = 0.9f; + break; + case (LanguageType.Spanish_Spain): + if (m_lastSkillObj.TraitType == SkillType.Equip_Up || m_lastSkillObj.TraitType == SkillType.Spellsword_Unlock || m_lastSkillObj.TraitType == SkillType.SpellSword_Up) + m_skillTitle.ScaleX = 0.9f; + break; + case (LanguageType.Portuguese_Brazil): + switch (m_lastSkillObj.TraitType) + { + case (SkillType.Spellsword_Unlock): + case (SkillType.SpellSword_Up): + m_skillTitle.ScaleX = 0.9f; + m_skillTitle.FontSize = 11; + break; + case (SkillType.Banker_Up): + case (SkillType.Mana_Cost_Down): + case (SkillType.Down_Strike_Up): + m_skillTitle.ScaleX = 0.9f; + break; + } + break; + case (LanguageType.Polish): + if (m_lastSkillObj.TraitType == SkillType.Spellsword_Unlock || m_lastSkillObj.TraitType == SkillType.SpellSword_Up) + m_skillTitle.ScaleX = 0.9f; + break; + case (LanguageType.Russian): + if (m_lastSkillObj.TraitType == SkillType.Crit_Chance_Up) + m_skillTitle.ScaleX = 0.9f; + + if (m_lastSkillObj.TraitType == SkillType.Crit_Damage_Up) + m_skillTitle.ScaleX = 0.8f; + + break; + } + } + + public override void Draw(GameTime gameTime) + { + m_cloud1.Y = m_cloud2.Y = m_cloud3.Y = m_cloud4.Y = m_cloud5.Y = Camera.TopLeftCorner.Y * 0.2f; + m_bg.Y = Camera.TopLeftCorner.Y * 0.2f; + + //m_manor.Y = Camera.TopLeftCorner.Y * 0.1f; + + //Camera.GraphicsDevice.Clear(Color.Black); + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null, null, Camera.GetTransformation()); + m_bg.Draw(Camera); + m_cloud1.Draw(Camera); + m_cloud2.Draw(Camera); + m_cloud3.Draw(Camera); + m_cloud4.Draw(Camera); + m_cloud5.Draw(Camera); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + m_manor.Draw(Camera); + m_impactEffectPool.Draw(Camera); + + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + + m_selectionIcon.Draw(Camera); + + foreach (SkillObj trait in SkillSystem.GetSkillArray()) + { + if (trait.TraitType != SkillType.Filler && trait.TraitType != SkillType.Null && trait.Visible == true) + trait.Draw(Camera); + } + + Camera.End(); + + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null); + + m_dialoguePlate.Draw(Camera); + + //m_titleText.Draw(Camera); + m_continueText.Draw(Camera); + m_toggleIconsText.Draw(Camera); + m_confirmText.Draw(Camera); + m_navigationText.Draw(Camera); + + m_playerMoney.Draw(Camera); + + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + m_descriptionDivider.Draw(Camera); + m_coinIcon.Draw(Camera); + + Camera.End(); + base.Draw(gameTime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Skill Screen"); + + m_titleText.Dispose(); + m_titleText = null; + m_bg.Dispose(); + m_bg = null; + m_cloud1.Dispose(); + m_cloud1 = null; + m_cloud2.Dispose(); + m_cloud2 = null; + m_cloud3.Dispose(); + m_cloud3 = null; + m_cloud4.Dispose(); + m_cloud4 = null; + m_cloud5.Dispose(); + m_cloud5 = null; + + m_continueText.Dispose(); + m_continueText = null; + m_toggleIconsText.Dispose(); + m_toggleIconsText = null; + m_confirmText.Dispose(); + m_confirmText = null; + m_navigationText.Dispose(); + m_navigationText = null; + + m_dialoguePlate.Dispose(); + m_dialoguePlate = null; + + m_selectionIcon.Dispose(); + m_selectionIcon = null; + + m_impactEffectPool.Dispose(); + m_impactEffectPool = null; + + m_manor.Dispose(); + m_manor = null; + + m_shakeObj = null; + + m_playerMoney.Dispose(); + m_playerMoney = null; + m_coinIcon.Dispose(); + m_coinIcon = null; + + // These aren't disposed because they're added to m_dialoguePlate, which will dispose them when it is disposed. + m_skillCurrent = null; + m_skillCost = null; + m_skillCostBG = null; + m_skillDescription = null; + m_inputDescription = null; + m_skillUpgrade = null; + m_skillLevel = null; + m_skillIcon = null; + m_skillTitle = null; + m_descriptionDivider.Dispose(); + m_descriptionDivider = null; + m_lastSkillObj = null; + base.Dispose(); + } + } + + private bool m_horizontalShake; + private bool m_verticalShake; + private bool m_shakeScreen; + private float m_screenShakeMagnitude; + + public void ShakeScreen(float magnitude, bool horizontalShake = true, bool verticalShake = true) + { + SoundManager.PlaySound("TowerLand"); + m_screenShakeMagnitude = magnitude; + m_horizontalShake = horizontalShake; + m_verticalShake = verticalShake; + m_shakeScreen = true; + } + + public void UpdateShake() + { + if (m_horizontalShake == true) + { + m_bg.X = CDGMath.RandomPlusMinus() * (CDGMath.RandomFloat(0, 1) * m_screenShakeMagnitude); + m_manor.X = CDGMath.RandomPlusMinus() * (CDGMath.RandomFloat(0, 1) * m_screenShakeMagnitude); + } + + if (m_verticalShake == true) + { + m_bg.Y = CDGMath.RandomPlusMinus() * (CDGMath.RandomFloat(0, 1) * m_screenShakeMagnitude); + m_manor.Y = CDGMath.RandomPlusMinus() * (CDGMath.RandomFloat(0, 1) * m_screenShakeMagnitude); + + } + } + + public void StopScreenShake() + { + m_shakeScreen = false; + m_bg.X = 0; + m_bg.Y = 0; + m_manor.X = 0; + m_manor.Y = 0; + } + + public override void RefreshTextObjs() + { + /* + m_confirmText.Text = "[Input:" + InputMapType.MENU_CONFIRM1 + "] " + LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_1"); + m_toggleIconsText.Text = "[Input:" + InputMapType.MENU_MAP + "] " + LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_2"); + m_continueText.Text = "[Input:" + InputMapType.MENU_CANCEL1 + "] " + LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_3"); + + if (InputManager.GamePadIsConnected(PlayerIndex.One) == true) + m_navigationText.Text = "[Button:LeftStick] " + LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_4"); + else + m_navigationText.Text = LocaleBuilder.getString("LOC_ID_SKILL_SCREEN_5", m_navigationText); + + if (SkillSystem.IconsVisible == true) + m_toggleIconsText.Text = "[Input:" + InputMapType.MENU_MAP + "] " + LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_6"); + else + m_toggleIconsText.Text = "[Input:" + InputMapType.MENU_MAP + "] " + LocaleBuilder.getResourceString("LOC_ID_SKILL_SCREEN_2"); + */ + SkillSystem.RefreshTextObjs(); + + if (m_lastSkillObj != null) + UpdateDescriptionPlate(m_lastSkillObj); + + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/Screens/SkillUnlockScreen.cs b/RogueCastle/src/Screens/SkillUnlockScreen.cs new file mode 100644 index 0000000..65c9de4 --- /dev/null +++ b/RogueCastle/src/Screens/SkillUnlockScreen.cs @@ -0,0 +1,306 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using System.IO; +using System.Globalization; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class SkillUnlockScreen : Screen + { + public float BackBufferOpacity { get; set; } + + private ObjContainer m_plate; + private ObjContainer m_picturePlate; + private SpriteObj m_picture; + private TextObj m_text; + + private SpriteObj m_titlePlate; + private SpriteObj m_title; + + private byte m_skillUnlockType; + + public SkillUnlockScreen() + { + + } + + public override void LoadContent() + { + m_plate = new ObjContainer("SkillUnlockPlate_Character"); + m_plate.Position = new Vector2(1320 / 2f, 720 / 2f); + m_plate.ForceDraw = true; + + m_text = new TextObj(Game.JunicodeFont); + m_text.ForceDraw = true; + m_text.Text = "This is temporary text to see how many sentences can be fit into this area. Hopefully it is quite a bit, as this is the area where we will be comprehensively describing the unlock. It will also be used to determine word wrap length."; + m_text.FontSize = 10; + m_text.WordWrap(340); + m_text.DropShadow = new Vector2(2, 2); + m_plate.AddChild(m_text); + m_text.Position = new Vector2(-110, -100); + + m_picturePlate = new ObjContainer("SkillUnlockPicturePlate_Character"); + m_picturePlate.Position = new Vector2(1320/2f - 300, 720/2f + 50); + m_picturePlate.Rotation = -15; + m_picturePlate.ForceDraw = true; + + m_picture = new SpriteObj("BlacksmithUnlockPicture_Sprite"); + m_picture.ForceDraw = true; + m_picture.OutlineWidth = 1; + m_picture.Position = m_picturePlate.Position; + + m_titlePlate = new SpriteObj("SkillUnlockTitlePlate_Sprite"); + m_titlePlate.Position = new Vector2(1320 / 2f, 720 / 2f - 200); + m_titlePlate.ForceDraw = true; + + m_title = new SpriteObj("ClassUnlockedText_Sprite"); + m_title.Position = m_titlePlate.Position; + m_title.Y -=40; + m_title.ForceDraw = true; + + base.LoadContent(); + } + + public override void PassInData(List objList) + { + m_skillUnlockType = (byte)(objList[0]); + } + + public override void OnEnter() + { + SoundManager.PlaySound("Upgrade_Splash_In"); + + SetData(); + + BackBufferOpacity = 0; + + m_plate.Scale = Vector2.Zero; + //m_picturePlate.Scale = Vector2.Zero; + m_titlePlate.Scale = Vector2.Zero; + m_title.Scale = Vector2.Zero; + + Tween.To(this, 0.2f, Tween.EaseNone, "BackBufferOpacity", "0.7"); + + Tween.To(m_titlePlate, 0.5f, Back.EaseOut, "ScaleX", "1", "ScaleY", "1"); + Tween.To(m_title, 0.5f, Back.EaseOut, "delay", "0.1", "ScaleX", "1", "ScaleY", "1"); + + Tween.To(m_plate, 0.5f, Back.EaseOut, "delay", "0.3", "ScaleX", "1", "ScaleY", "1"); + //Tween.To(m_picturePlate, 0.5f, Back.EaseOut, "delay", "0.4", "ScaleX", "1", "ScaleY", "1"); + + // Different animation. + m_picturePlate.Scale = new Vector2(2, 2); + m_picturePlate.Opacity = 0; + m_picturePlate.Rotation = 0; + + Tween.To(m_picturePlate, 0.3f, Tween.EaseNone, "delay", "0.4", "ScaleX", "1", "ScaleY", "1", "Rotation", "-15"); + Tween.To(m_picturePlate, 0.1f, Tween.EaseNone, "delay", "0.4", "Opacity", "1"); + + m_picture.Scale = new Vector2(2, 2); + m_picture.Opacity = 0; + m_picture.Rotation = 0; + + Tween.To(m_picture, 0.3f, Tween.EaseNone, "delay", "0.4", "ScaleX", "1", "ScaleY", "1", "Rotation", "-15"); + Tween.To(m_picture, 0.1f, Tween.EaseNone, "delay", "0.4", "Opacity", "1"); + + RefreshTextObjs(); + + base.OnEnter(); + } + + private void SetData() + { + switch (m_skillUnlockType) + { + case (SkillUnlockType.Blacksmith): + m_picture.ChangeSprite("BlacksmithUnlockPicture_Sprite"); + m_title.ChangeSprite("SmithyUnlockedText_Sprite"); + break; + case (SkillUnlockType.Enchantress): + m_picture.ChangeSprite("EnchantressUnlockPicture_Sprite"); + m_title.ChangeSprite("EnchantressUnlockedText_Sprite"); + break; + case (SkillUnlockType.Architect): + m_picture.ChangeSprite("ArchitectUnlockPicture_Sprite"); + m_title.ChangeSprite("ArchitectUnlockedText_Sprite"); + break; + case (SkillUnlockType.Ninja): + m_picture.ChangeSprite("NinjaUnlockPicture_Sprite"); + m_title.ChangeSprite("ClassUnlockedText_Sprite"); + break; + case (SkillUnlockType.Banker): + m_picture.ChangeSprite("BankerUnlockPicture_Sprite"); + m_title.ChangeSprite("ClassUnlockedText_Sprite"); + break; + case (SkillUnlockType.Lich): + m_picture.ChangeSprite("LichUnlockPicture_Sprite"); + m_title.ChangeSprite("ClassUnlockedText_Sprite"); + break; + case (SkillUnlockType.SpellSword): + m_picture.ChangeSprite("SpellSwordUnlockPicture_Sprite"); + m_title.ChangeSprite("ClassUnlockedText_Sprite"); + break; + case (SkillUnlockType.KnightUp): + m_picture.ChangeSprite("KnightUpgradePicture_Sprite"); + m_title.ChangeSprite("ClassUpgradedText_Sprite"); + break; + case (SkillUnlockType.WizardUp): + m_picture.ChangeSprite("MageUpgradePicture_Sprite"); + m_title.ChangeSprite("ClassUpgradedText_Sprite"); + break; + case (SkillUnlockType.BarbarianUp): + m_picture.ChangeSprite("BarbarianUpgradePicture_Sprite"); + m_title.ChangeSprite("ClassUpgradedText_Sprite"); + break; + case (SkillUnlockType.AssassinUp): + m_picture.ChangeSprite("AssassinUpgradePicture_Sprite"); + m_title.ChangeSprite("ClassUpgradedText_Sprite"); + break; + case (SkillUnlockType.LichUp): + m_picture.ChangeSprite("LichUpgradePicture_Sprite"); + m_title.ChangeSprite("ClassUpgradedText_Sprite"); + break; + case (SkillUnlockType.SpellSwordUp): + m_picture.ChangeSprite("SpellSwordUpgradePicture_Sprite"); + m_title.ChangeSprite("ClassUpgradedText_Sprite"); + break; + case (SkillUnlockType.NinjaUp): + m_picture.ChangeSprite("NinjaUpgradePicture_Sprite"); + m_title.ChangeSprite("ClassUpgradedText_Sprite"); + break; + case (SkillUnlockType.BankerUp): + m_picture.ChangeSprite("BankerUpgradePicture_Sprite"); + m_title.ChangeSprite("ClassUpgradedText_Sprite"); + break; + case (SkillUnlockType.Dragon): + m_picture.ChangeSprite("DragonUnlockPicture_Sprite"); + m_title.ChangeSprite("ClassUnlockedText_Sprite"); + break; + case (SkillUnlockType.Traitor): + m_picture.ChangeSprite("TraitorUnlockPicture_Sprite"); + m_title.ChangeSprite("ClassUnlockedText_Sprite"); + break; + } + + m_text.Text = LocaleBuilder.getString(SkillUnlockType.DescriptionID(m_skillUnlockType), m_text); + m_text.WordWrap(340); + } + + private void ExitTransition() + { + SoundManager.PlaySound("Upgrade_Splash_Out"); + + Tween.To(m_picture, 0.5f, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + Tween.To(m_picturePlate, 0.5f, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + Tween.To(m_titlePlate, 0.5f, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + Tween.To(m_title, 0.5f, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + Tween.To(m_plate, 0.5f, Back.EaseIn, "ScaleX", "0", "ScaleY", "0"); + + Tween.To(this, 0.2f, Tween.EaseNone, "delay", "0.4", "BackBufferOpacity", "0"); + + Tween.AddEndHandlerToLastTween(ScreenManager, "HideCurrentScreen"); + } + + public override void HandleInput() + { + if (m_plate.ScaleX == 1) + { + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL2) + || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3) || Game.GlobalInput.JustPressed(InputMapType.MENU_CANCEL3)) + ExitTransition(); + } + + base.HandleInput(); + } + + public override void Draw(GameTime gametime) + { + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null); + Camera.Draw(Game.GenericTexture, new Rectangle(0, 0, GlobalEV.ScreenWidth, GlobalEV.ScreenHeight), Color.Black * BackBufferOpacity); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + m_plate.Draw(Camera); + m_titlePlate.Draw(Camera); + m_title.Draw(Camera); + m_picturePlate.Draw(Camera); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + m_picture.Draw(Camera); + Camera.End(); + base.Draw(gametime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing SkillUnlock Screen"); + + m_picturePlate.Dispose(); + m_picturePlate = null; + m_picture.Dispose(); + m_picture = null; + m_text = null; + m_title.Dispose(); + m_title = null; + m_titlePlate.Dispose(); + m_titlePlate = null; + m_plate.Dispose(); + m_plate = null; + + base.Dispose(); + } + } + + public override void RefreshTextObjs() + { + RefreshBitmaps(); + + m_text.ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_text)); + m_text.Text = LocaleBuilder.getString(SkillUnlockType.DescriptionID(m_skillUnlockType), null); + m_text.WordWrap(340); + + base.RefreshTextObjs(); + } + + private void RefreshBitmaps() + { + switch (m_skillUnlockType) + { + case (SkillUnlockType.Blacksmith): + Game.ChangeBitmapLanguage(m_title, "SmithyUnlockedText_Sprite"); + break; + case (SkillUnlockType.Enchantress): + Game.ChangeBitmapLanguage(m_title, "EnchantressUnlockedText_Sprite"); + break; + case (SkillUnlockType.Architect): + Game.ChangeBitmapLanguage(m_title, "ArchitectUnlockedText_Sprite"); + break; + case (SkillUnlockType.Ninja): + case (SkillUnlockType.Banker): + case (SkillUnlockType.Lich): + case (SkillUnlockType.SpellSword): + case (SkillUnlockType.Dragon): + case (SkillUnlockType.Traitor): + Game.ChangeBitmapLanguage(m_title, "ClassUnlockedText_Sprite"); + break; + case (SkillUnlockType.KnightUp): + case (SkillUnlockType.WizardUp): + case (SkillUnlockType.BarbarianUp): + case (SkillUnlockType.AssassinUp): + case (SkillUnlockType.LichUp): + case (SkillUnlockType.SpellSwordUp): + case (SkillUnlockType.NinjaUp): + case (SkillUnlockType.BankerUp): + Game.ChangeBitmapLanguage(m_title, "ClassUpgradedText_Sprite"); + break; + } + } + } +} diff --git a/RogueCastle/src/Screens/TextScreen.cs b/RogueCastle/src/Screens/TextScreen.cs new file mode 100644 index 0000000..68301a8 --- /dev/null +++ b/RogueCastle/src/Screens/TextScreen.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; +using Tweener; +using Tweener.Ease; +using System.IO; +using System.Globalization; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Graphics; + +namespace RogueCastle +{ + public class TextScreen : Screen + { + public float BackBufferOpacity { get; set; } + + private TextObj m_text; + private float m_fadeInSpeed; + private float m_backBufferOpacity; + private bool m_typewriteText; + private float m_textDuration = 0; + private bool m_loadEndingAfterward = false; + + private SpriteObj m_smoke1, m_smoke2, m_smoke3; + + public TextScreen() + { + + } + + public override void LoadContent() + { + Color sepia = new Color(200, 150, 55); + + m_smoke1 = new SpriteObj("TextSmoke_Sprite"); + m_smoke1.ForceDraw = true; + m_smoke1.Scale = new Vector2(2, 2); + m_smoke1.Opacity = 0.3f; + m_smoke1.TextureColor = sepia; + + m_smoke2 = m_smoke1.Clone() as SpriteObj; + m_smoke2.Flip = SpriteEffects.FlipHorizontally; + m_smoke2.Opacity = 0.2f; + + m_smoke3 = m_smoke1.Clone() as SpriteObj; + m_smoke3.Scale = new Vector2(2.5f, 3f); + m_smoke3.Opacity = 0.15f; + + base.LoadContent(); + } + + public override void PassInData(List objList) + { + m_backBufferOpacity = (float)objList[0]; + m_fadeInSpeed = (float)objList[1]; + m_textDuration = (float)objList[2]; + m_typewriteText = (bool)objList[3]; + + TextObj textInfo = objList[4] as TextObj; + if (m_text != null) + { + m_text.Dispose(); + m_text = null; + } + m_text = textInfo.Clone() as TextObj; + //textInfo.Dispose(); // Do not dispose this. + + m_loadEndingAfterward = (bool)objList[5]; + } + + public override void OnEnter() + { + m_smoke1.Position = new Vector2(CDGMath.RandomInt(300, 1000), m_text.Y + m_text.Height/2f - 30 + CDGMath.RandomInt(-100, 100)); + m_smoke2.Position = new Vector2(CDGMath.RandomInt(200, 700), m_text.Y + m_text.Height / 2f - 30 + CDGMath.RandomInt(-50, 50)); + m_smoke3.Position = new Vector2(CDGMath.RandomInt(300, 800), m_text.Y + m_text.Height / 2f - 30 + CDGMath.RandomInt(-100, 100)); + + m_smoke1.Opacity = m_smoke2.Opacity = m_smoke3.Opacity = 0; + Tween.To(m_smoke1, m_fadeInSpeed, Tween.EaseNone, "Opacity", "0.3"); + Tween.To(m_smoke2, m_fadeInSpeed, Tween.EaseNone, "Opacity", "0.2"); + Tween.To(m_smoke3, m_fadeInSpeed, Tween.EaseNone, "Opacity", "0.15"); + + BackBufferOpacity = 0; + m_text.Opacity = 0; + + Tween.To(this, m_fadeInSpeed, Tween.EaseNone, "BackBufferOpacity", m_backBufferOpacity.ToString()); + Tween.To(m_text, m_fadeInSpeed, Tween.EaseNone, "Opacity", "1"); + + if (m_typewriteText == true) + { + m_text.Visible = false; + Tween.RunFunction(m_fadeInSpeed, m_text, "BeginTypeWriting", m_text.Text.Length * 0.05f, ""); + } + else + m_text.Visible = true; + + base.OnEnter(); + } + + private void ExitTransition() + { + if (m_loadEndingAfterward == false) + { + Tween.To(m_smoke1, m_fadeInSpeed, Tween.EaseNone, "Opacity", "0"); + Tween.To(m_smoke2, m_fadeInSpeed, Tween.EaseNone, "Opacity", "0"); + Tween.To(m_smoke3, m_fadeInSpeed, Tween.EaseNone, "Opacity", "0"); + + Tween.To(this, m_fadeInSpeed, Tween.EaseNone, "BackBufferOpacity", "0"); + Tween.To(m_text, m_fadeInSpeed, Tween.EaseNone, "Opacity", "0"); + Tween.AddEndHandlerToLastTween(Game.ScreenManager, "HideCurrentScreen"); + } + else + Game.ScreenManager.DisplayScreen(ScreenType.Ending, true); + } + + public override void Update(GameTime gameTime) + { + float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds; + + m_smoke1.X += 5 * elapsed; + m_smoke2.X += 15 * elapsed; + m_smoke3.X += 10 * elapsed; + + if (m_text.Visible == false && m_text.IsTypewriting) + m_text.Visible = true; + + if (m_textDuration > 0) + { + m_textDuration -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_textDuration <= 0) + ExitTransition(); + } + + base.Update(gameTime); + } + + public override void Draw(GameTime gametime) + { + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null); + Camera.Draw(Game.GenericTexture, new Rectangle(0, 0, 1320, 720), Color.Black * BackBufferOpacity); + + m_smoke1.Draw(Camera); + m_smoke2.Draw(Camera); + m_smoke3.Draw(Camera); + + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + m_text.Draw(Camera); + + Camera.End(); + base.Draw(gametime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Text Screen"); + if (m_text != null) + m_text.Dispose(); + m_text = null; + + m_smoke1.Dispose(); + m_smoke1 = null; + m_smoke2.Dispose(); + m_smoke2 = null; + m_smoke3.Dispose(); + m_smoke3 = null; + base.Dispose(); + } + } + } +} diff --git a/RogueCastle/src/Screens/TitleScreen.cs b/RogueCastle/src/Screens/TitleScreen.cs new file mode 100644 index 0000000..fd41a19 --- /dev/null +++ b/RogueCastle/src/Screens/TitleScreen.cs @@ -0,0 +1,751 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Tweener; +using Tweener.Ease; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using InputSystem; +using Microsoft.Xna.Framework.Input; +using Randomchaos2DGodRays; +using Microsoft.Xna.Framework.Audio; + +namespace RogueCastle +{ + public class TitleScreen : Screen + { + private TextObj m_titleText; + private SpriteObj m_bg; + private SpriteObj m_logo; + private SpriteObj m_castle; + private SpriteObj m_smallCloud1, m_smallCloud2, m_smallCloud3, m_smallCloud4, m_smallCloud5; + private SpriteObj m_largeCloud1, m_largeCloud2, m_largeCloud3, m_largeCloud4; + private KeyIconTextObj m_pressStartText; + private TextObj m_pressStartText2; + private TextObj m_copyrightText; + + private bool m_startPressed = false; + + private RenderTarget2D m_godRayTexture; + private CrepuscularRays m_godRay; + private PostProcessingManager m_ppm; + + private float m_randomSeagullSFX = 0; + private Cue m_seagullCue; + + private SpriteObj m_profileCard; + private SpriteObj m_optionsIcon; + private SpriteObj m_creditsIcon; + + private KeyIconTextObj m_profileCardKey; + private KeyIconTextObj m_optionsKey; + private KeyIconTextObj m_creditsKey; + + private KeyIconTextObj m_profileSelectKey; + + private SpriteObj m_crown; + + private TextObj m_versionNumber; + + private float m_hardCoreModeOpacity = 0; + private bool m_optionsEntered = false; + private bool m_startNewLegacy = false; + private bool m_heroIsDead = false; + private bool m_startNewGamePlus = false; + private bool m_loadStartingRoom = false; + + private SpriteObj m_dlcIcon; + + public override void LoadContent() + { + m_ppm = new PostProcessingManager(ScreenManager.Game, ScreenManager.Camera); + m_godRay = new CrepuscularRays(ScreenManager.Game, Vector2.One * .5f, "GameSpritesheets/flare3", 2f, .97f, .97f, .5f, 1.25f); + //m_godRay = new CrepuscularRays(ScreenManager.Game, Vector2.One * .5f, "GameSpritesheets/flare3", 2f, .97f, .97f, .5f, .75f); + m_ppm.AddEffect(m_godRay); + + m_godRayTexture = new RenderTarget2D(Camera.GraphicsDevice, 1320, 720, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + m_godRay.lightSource = new Vector2(0.495f, 0.3f); + + m_bg = new SpriteObj("TitleBG_Sprite"); + m_bg.Scale = new Vector2(1320f / m_bg.Width, 720f / m_bg.Height); + m_bg.TextureColor = Color.Red; + m_hardCoreModeOpacity = 0f; + + // Code for hardcore mode. + //m_bg.TextureColor = Color.Black; + //m_hardCoreModeOpacity = 0.5f; + + m_logo = new SpriteObj("TitleLogo_Sprite"); + m_logo.Position = new Vector2(1320 / 2, 720 / 2); + m_logo.DropShadow = new Vector2(0, 5); + + m_castle = new SpriteObj("TitleCastle_Sprite"); + m_castle.Scale = new Vector2(2, 2); + m_castle.Position = new Vector2(1320 / 2 - 30, 720 - m_castle.Height/2); + + m_smallCloud1 = new SpriteObj("TitleSmallCloud1_Sprite"); + m_smallCloud1.Position = new Vector2(1320 / 2, 0); + m_smallCloud2 = new SpriteObj("TitleSmallCloud2_Sprite"); + m_smallCloud2.Position = m_smallCloud1.Position; + m_smallCloud3 = new SpriteObj("TitleSmallCloud3_Sprite"); + m_smallCloud3.Position = m_smallCloud1.Position; + m_smallCloud4 = new SpriteObj("TitleSmallCloud4_Sprite"); + m_smallCloud4.Position = m_smallCloud1.Position; + m_smallCloud5 = new SpriteObj("TitleSmallCloud5_Sprite"); + m_smallCloud5.Position = m_smallCloud1.Position; + + m_largeCloud1 = new SpriteObj("TitleLargeCloud1_Sprite"); + m_largeCloud1.Position = new Vector2(0, 720 - m_largeCloud1.Height); + m_largeCloud2 = new SpriteObj("TitleLargeCloud2_Sprite"); + m_largeCloud2.Position = new Vector2(1320 / 3, 720 - m_largeCloud2.Height + 130); + m_largeCloud3 = new SpriteObj("TitleLargeCloud1_Sprite"); + m_largeCloud3.Position = new Vector2(1320/3 * 2, 720 - m_largeCloud3.Height + 50); + m_largeCloud3.Flip = SpriteEffects.FlipHorizontally; + m_largeCloud4 = new SpriteObj("TitleLargeCloud2_Sprite"); + m_largeCloud4.Position = new Vector2(1320, 720 - m_largeCloud4.Height); + m_largeCloud4.Flip = SpriteEffects.FlipHorizontally; + + m_titleText = new TextObj(); + m_titleText.Font = Game.JunicodeFont; + m_titleText.FontSize = 45; + m_titleText.Text = "ROGUE CASTLE"; + m_titleText.Position = new Vector2(1320 / 2, 720 / 2 - 300); + m_titleText.Align = Types.TextAlign.Centre; + + m_copyrightText = new TextObj(Game.JunicodeFont); + m_copyrightText.FontSize = 8; + m_copyrightText.Text = " Copyright(C) 2013-2018, Cellar Door Games Inc. Rogue Legacy(TM) is a trademark or registered trademark of Cellar Door Games Inc. All Rights Reserved."; + m_copyrightText.Align = Types.TextAlign.Centre; + m_copyrightText.Position = new Vector2(1320 / 2, 720 - m_copyrightText.Height - 10); + m_copyrightText.DropShadow = new Vector2(1, 2); + + m_versionNumber = m_copyrightText.Clone() as TextObj; + m_versionNumber.Align = Types.TextAlign.Right; + m_versionNumber.FontSize = 8; + m_versionNumber.Position = new Vector2(1320 - 15, 5); + m_versionNumber.Text = LevelEV.GAME_VERSION; + + m_pressStartText = new KeyIconTextObj(Game.JunicodeFont); + m_pressStartText.FontSize = 20; + m_pressStartText.Text = "Press Enter to begin"; + m_pressStartText.Align = Types.TextAlign.Centre; + m_pressStartText.Position = new Vector2(1320 / 2, 720 / 2 + 200); + m_pressStartText.DropShadow = new Vector2(2, 2); + + m_pressStartText2 = new TextObj(Game.JunicodeFont); + m_pressStartText2.FontSize = 20; + m_pressStartText2.Text = LocaleBuilder.getString("LOC_ID_CLASS_NAME_1_MALE", m_pressStartText2); // dummy locID to add TextObj to language refresh list + m_pressStartText2.Align = Types.TextAlign.Centre; + m_pressStartText2.Position = m_pressStartText.Position; + m_pressStartText2.Y -= m_pressStartText.Height - 5; + m_pressStartText2.DropShadow = new Vector2(2, 2); + + m_profileCard = new SpriteObj("TitleProfileCard_Sprite"); + m_profileCard.OutlineWidth = 2; + m_profileCard.Scale = new Vector2(2, 2); + m_profileCard.Position = new Vector2(m_profileCard.Width, 720 - m_profileCard.Height); + m_profileCard.ForceDraw = true; + + m_optionsIcon = new SpriteObj("TitleOptionsIcon_Sprite"); + m_optionsIcon.Scale = new Vector2(2, 2); + m_optionsIcon.OutlineWidth = m_profileCard.OutlineWidth; + m_optionsIcon.Position = new Vector2(1320 - m_optionsIcon.Width * 2, m_profileCard.Y); + m_optionsIcon.ForceDraw = true; + + m_creditsIcon = new SpriteObj("TitleCreditsIcon_Sprite"); + m_creditsIcon.Scale = new Vector2(2, 2); + m_creditsIcon.OutlineWidth = m_profileCard.OutlineWidth; + m_creditsIcon.Position = new Vector2(m_optionsIcon.X + 120, m_profileCard.Y); + m_creditsIcon.ForceDraw = true; + + m_profileCardKey = new KeyIconTextObj(Game.JunicodeFont); + m_profileCardKey.Align = Types.TextAlign.Centre; + m_profileCardKey.FontSize = 12; + m_profileCardKey.Text = "[Input:" + InputMapType.MENU_PROFILECARD + "]"; + m_profileCardKey.Position = new Vector2(m_profileCard.X, m_profileCard.Bounds.Top - m_profileCardKey.Height - 10); + m_profileCardKey.ForceDraw = true; + + m_optionsKey = new KeyIconTextObj(Game.JunicodeFont); + m_optionsKey.Align = Types.TextAlign.Centre; + m_optionsKey.FontSize = 12; + m_optionsKey.Text = "[Input:" + InputMapType.MENU_OPTIONS + "]"; + m_optionsKey.Position = new Vector2(m_optionsIcon.X, m_optionsIcon.Bounds.Top - m_optionsKey.Height - 10); + m_optionsKey.ForceDraw = true; + + m_creditsKey = new KeyIconTextObj(Game.JunicodeFont); + m_creditsKey.Align = Types.TextAlign.Centre; + m_creditsKey.FontSize = 12; + m_creditsKey.Text = "[Input:" + InputMapType.MENU_CREDITS + "]"; + m_creditsKey.Position = new Vector2(m_creditsIcon.X, m_creditsIcon.Bounds.Top - m_creditsKey.Height - 10); + m_creditsKey.ForceDraw = true; + + m_profileSelectKey = new KeyIconTextObj(Game.JunicodeFont); + m_profileSelectKey.Align = Types.TextAlign.Left; + m_profileSelectKey.FontSize = 10; + m_profileSelectKey.Text = string.Format(LocaleBuilder.getString("LOC_ID_BACK_TO_MENU_OPTIONS_3_NEW", m_profileSelectKey), Game.GameConfig.ProfileSlot); + //m_profileSelectKey.Text = "[Input:" + InputMapType.MENU_PROFILESELECT + "] " + LocaleBuilder.getString("LOC_ID_BACK_TO_MENU_OPTIONS_3", m_profileSelectKey) + " (" + Game.GameConfig.ProfileSlot + ")"; + m_profileSelectKey.Position = new Vector2(30, 15); + m_profileSelectKey.ForceDraw = true; + m_profileSelectKey.DropShadow = new Vector2(2, 2); + + m_crown = new SpriteObj("Crown_Sprite"); + m_crown.ForceDraw = true; + m_crown.Scale = new Vector2(0.7f, 0.7f); + m_crown.Rotation = -30; + m_crown.OutlineWidth = 2; + + m_dlcIcon = new SpriteObj("MedallionPiece5_Sprite"); + m_dlcIcon.Position = new Vector2(950, 310); + //m_dlcIcon.OutlineWidth = 2; + //m_dlcIcon.Scale = new Vector2(2, 2); + m_dlcIcon.ForceDraw = true; + m_dlcIcon.TextureColor = Color.Yellow; + base.LoadContent(); + } + + public override void OnEnter() + { + Game.HoursPlayedSinceLastSave = 0; + + Camera.Zoom = 1; + m_profileSelectKey.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_BACK_TO_MENU_OPTIONS_3_NEW"), Game.GameConfig.ProfileSlot); + //m_profileSelectKey.Text = "[Input:" + InputMapType.MENU_PROFILESELECT + "] " + LocaleBuilder.getResourceString("LOC_ID_BACK_TO_MENU_OPTIONS_3") + " (" + Game.GameConfig.ProfileSlot + ")"; + + // Setting initial data. + SoundManager.PlayMusic("TitleScreenSong", true, 1f); + Game.ScreenManager.Player.ForceInvincible = false; //TEDDY - DISABLE INVINCIBILITY WHEN YOU ENTER GAME PROPER. + + m_optionsEntered = false; + m_startNewLegacy = false; + m_heroIsDead = false; + m_startNewGamePlus = false; + m_loadStartingRoom = false; + + m_bg.TextureColor = Color.Red; + m_crown.Visible = false; + + m_randomSeagullSFX = CDGMath.RandomInt(1, 5); + m_startPressed = false; + Tween.By(m_godRay, 5, Quad.EaseInOut, "Y", "-0.23"); + m_logo.Opacity = 0; + m_logo.Position = new Vector2(1320 / 2, 720 / 2 - 50); + Tween.To(m_logo, 2, Linear.EaseNone, "Opacity", "1"); + Tween.To(m_logo, 3, Quad.EaseInOut, "Y", "360"); + + m_crown.Opacity = 0; + m_crown.Position = new Vector2(390, 250 - 50); + Tween.To(m_crown, 2, Linear.EaseNone, "Opacity", "1"); + Tween.By(m_crown, 3, Quad.EaseInOut, "Y", "50"); + + m_dlcIcon.Opacity = 0; + m_dlcIcon.Visible = false; + if (Game.PlayerStats.ChallengeLastBossBeaten == true) + m_dlcIcon.Visible = true; + m_dlcIcon.Position = new Vector2(898, 317 - 50); + Tween.To(m_dlcIcon, 2, Linear.EaseNone, "Opacity", "1"); + Tween.By(m_dlcIcon, 3, Quad.EaseInOut, "Y", "50"); + + Camera.Position = new Vector2(1320 / 2, 720 / 2); + + m_pressStartText.Text = "[Input:" + InputMapType.MENU_CONFIRM1 + "]"; + + // Setting up save data. + LoadSaveData(); + Game.PlayerStats.TutorialComplete = true; // Force this to true since you can't be in the title screen without going through the tutorial first. + + m_startNewLegacy = !Game.PlayerStats.CharacterFound; + m_heroIsDead = Game.PlayerStats.IsDead; + m_startNewGamePlus = Game.PlayerStats.LastbossBeaten; + m_loadStartingRoom = Game.PlayerStats.LoadStartingRoom; + + if (Game.PlayerStats.TimesCastleBeaten > 0) + { + m_crown.Visible = true; + m_bg.TextureColor = Color.White; + } + + InitializeStartingText(); + + UpdateCopyrightText(); + + base.OnEnter(); + } + + public void UpdateCopyrightText() + { + m_copyrightText.ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_copyrightText)); + m_copyrightText.Text = LocaleBuilder.getResourceString("LOC_ID_COPYRIGHT_GENERIC", true) + " " + string.Format(LocaleBuilder.getResourceString("LOC_ID_TRADEMARK_GENERIC", true), "Rogue Legacy"); + } + + public override void OnExit() + { + if (m_seagullCue != null && m_seagullCue.IsPlaying) + { + m_seagullCue.Stop(AudioStopOptions.Immediate); + m_seagullCue.Dispose(); + } + base.OnExit(); + } + + public void LoadSaveData() + { + SkillSystem.ResetAllTraits(); + Game.PlayerStats.Dispose(); + Game.PlayerStats = new PlayerStats(); + (ScreenManager as RCScreenManager).Player.Reset(); + (ScreenManager.Game as Game).SaveManager.LoadFiles(null, SaveType.PlayerData, SaveType.Lineage, SaveType.UpgradeData); + // Special circumstance where you should override player's current HP/MP + Game.ScreenManager.Player.CurrentHealth = Game.PlayerStats.CurrentHealth; + Game.ScreenManager.Player.CurrentMana = Game.PlayerStats.CurrentMana; + } + + public void InitializeStartingText() + { + m_pressStartText2.ChangeFontNoDefault(LocaleBuilder.GetLanguageFont(m_pressStartText)); + + if (m_startNewLegacy == false) + { + // You have an active character who is not dead. Therefore begin the game like normal. + if (m_heroIsDead == false) + { + if (Game.PlayerStats.TimesCastleBeaten == 1) + m_pressStartText2.Text = LocaleBuilder.getResourceString("LOC_ID_TITLE_SCREEN_2") + " +"; + else if (Game.PlayerStats.TimesCastleBeaten > 1) + m_pressStartText2.Text = LocaleBuilder.getResourceString("LOC_ID_TITLE_SCREEN_2") + " +" + Game.PlayerStats.TimesCastleBeaten; + else + m_pressStartText2.Text = LocaleBuilder.getResourceString("LOC_ID_TITLE_SCREEN_2"); + } + else // You have an active character but he died. Go to legacy screen. + { + if (Game.PlayerStats.TimesCastleBeaten == 1) + m_pressStartText2.Text = LocaleBuilder.getResourceString("LOC_ID_TITLE_SCREEN_3", true) + " +"; + else if (Game.PlayerStats.TimesCastleBeaten > 1) + m_pressStartText2.Text = LocaleBuilder.getResourceString("LOC_ID_TITLE_SCREEN_3", true) + " +" + Game.PlayerStats.TimesCastleBeaten; + else + m_pressStartText2.Text = LocaleBuilder.getResourceString("LOC_ID_TITLE_SCREEN_3", true); + } + } + else + { + // No character was found, and the castle was never beaten. Therefore you are starting a new game. + if (m_startNewGamePlus == false) + m_pressStartText2.Text = LocaleBuilder.getResourceString("LOC_ID_TITLE_SCREEN_4", true); + else // You've beaten the castle at least once, which means it's new game plus. + { + if (Game.PlayerStats.TimesCastleBeaten == 1) + m_pressStartText2.Text = LocaleBuilder.getResourceString("LOC_ID_TITLE_SCREEN_4", true) + " +"; + else + m_pressStartText2.Text = LocaleBuilder.getResourceString("LOC_ID_TITLE_SCREEN_4", true) + " +" + Game.PlayerStats.TimesCastleBeaten; + } + } + } + + public void StartPressed() + { + SoundManager.PlaySound("Game_Start"); + + if (m_startNewLegacy == false) + { + if (m_heroIsDead == false) // Loading a previous file. + { + if (m_loadStartingRoom == true) + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.StartingRoom, true); + else + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Level, true); + } + else // Selecting a new heir. + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Lineage, true); + } + else + { + Game.PlayerStats.CharacterFound = true; // Signifies that a new game is being started. + // Start a brand new game. + if (m_startNewGamePlus == true) // If start new game plus is true, erase these flags. + { + Game.PlayerStats.LastbossBeaten = false; + Game.PlayerStats.BlobBossBeaten = false; + Game.PlayerStats.EyeballBossBeaten = false; + Game.PlayerStats.FairyBossBeaten = false; + Game.PlayerStats.FireballBossBeaten = false; + Game.PlayerStats.FinalDoorOpened = false; + if ((ScreenManager.Game as Game).SaveManager.FileExists(SaveType.Map)) + { + (ScreenManager.Game as Game).SaveManager.ClearFiles(SaveType.Map, SaveType.MapData); + (ScreenManager.Game as Game).SaveManager.ClearBackupFiles(SaveType.Map, SaveType.MapData); + } + } + else + Game.PlayerStats.Gold = 0; + + // Default data that needs to be restarted when starting a new game. + //Game.PlayerStats.Gold = 0; + Game.PlayerStats.HeadPiece = (byte)CDGMath.RandomInt(1, PlayerPart.NumHeadPieces);// Necessary to change his headpiece so he doesn't look like the first dude. + Game.PlayerStats.EnemiesKilledInRun.Clear(); + + (ScreenManager.Game as Game).SaveManager.SaveFiles(SaveType.PlayerData, SaveType.Lineage, SaveType.UpgradeData); // Create new player, lineage, and upgrade data. + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.StartingRoom, true); + } + + SoundManager.StopMusic(0.2f); + } + + public override void Update(GameTime gameTime) + { + //m_castle.Position = new Vector2(InputSystem.InputManager.MouseX, InputSystem.InputManager.MouseY); + if (m_randomSeagullSFX > 0) + { + m_randomSeagullSFX -= (float)gameTime.ElapsedGameTime.TotalSeconds; + if (m_randomSeagullSFX <= 0) + { + if (m_seagullCue != null && m_seagullCue.IsPlaying) + { + m_seagullCue.Stop(AudioStopOptions.Immediate); + m_seagullCue.Dispose(); + } + m_seagullCue = SoundManager.PlaySound("Wind1"); + m_randomSeagullSFX = CDGMath.RandomInt(10, 15); + } + } + + float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds; + + //m_smallCloud1.Rotation += 0.03f; + //m_smallCloud2.Rotation += 0.02f; + //m_smallCloud3.Rotation += 0.05f; + //m_smallCloud4.Rotation -= 0.01f; + //m_smallCloud5.Rotation -= 0.03f; + + m_smallCloud1.Rotation += (1.8f * elapsedSeconds); + m_smallCloud2.Rotation += (1.2f * elapsedSeconds); + m_smallCloud3.Rotation += (3 * elapsedSeconds); + m_smallCloud4.Rotation -= (0.6f * elapsedSeconds); + m_smallCloud5.Rotation -= (1.8f * elapsedSeconds); + + + //m_largeCloud2.X += 0.04f; + m_largeCloud2.X += (2.4f * elapsedSeconds); + if (m_largeCloud2.Bounds.Left > 1320) + m_largeCloud2.X = 0 - m_largeCloud2.Width / 2; + + //m_largeCloud3.X -= 0.05f; + m_largeCloud3.X -= (3 * elapsedSeconds); + if (m_largeCloud3.Bounds.Right < 0) + m_largeCloud3.X = 1320 + m_largeCloud3.Width / 2; + + if (m_startPressed == false) + { + m_pressStartText.Opacity = (float)Math.Abs(Math.Sin((float)Game.TotalGameTime * 1)); + //if (m_pressStartText.Opacity < 0.5f) m_pressStartText.Opacity = 0.5f; + } + + // Gives it a glow effect by growing and shrinking. + m_godRay.LightSourceSize = 1 + ((float)Math.Abs(Math.Sin((float)Game.TotalGameTime * 0.5f)) * 0.5f); + + // Needed to refresh the save state in case the player entered the options screen and deleted his/her file. + if (m_optionsEntered == true && Game.ScreenManager.CurrentScreen == this) + { + m_optionsEntered = false; + // Recheck these buttons. + m_optionsKey.Text = "[Input:" + InputMapType.MENU_OPTIONS + "]"; + m_profileCardKey.Text = "[Input:" + InputMapType.MENU_PROFILECARD + "]"; + m_creditsKey.Text = "[Input:" + InputMapType.MENU_CREDITS + "]"; + m_profileSelectKey.Text = string.Format(LocaleBuilder.getString("LOC_ID_BACK_TO_MENU_OPTIONS_3_NEW", m_profileSelectKey), Game.GameConfig.ProfileSlot); + //m_profileSelectKey.Text = "[Input:" + InputMapType.MENU_PROFILESELECT + "] " + LocaleBuilder.getString("LOC_ID_BACK_TO_MENU_OPTIONS_3", m_profileSelectKey) + " (" + Game.GameConfig.ProfileSlot + ")"; + + // Recheck save data. This might not be needed any longer. Not sure. + //InitializeSaveData(); + } + + base.Update(gameTime); + } + + public override void HandleInput() + { + HandleAchievementInput(); + + //ChangeRay(); + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM1) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM2) || Game.GlobalInput.JustPressed(InputMapType.MENU_CONFIRM3)) + StartPressed(); + + if (m_startNewLegacy == false) + { + if (Game.GlobalInput.JustPressed(InputMapType.MENU_PROFILECARD)) + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.ProfileCard, false, null); + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_OPTIONS)) + { + m_optionsEntered = true; + List optionsData = new List(); + optionsData.Add(true); + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Options, false, optionsData); + } + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_CREDITS))// && InputManager.Pressed(Keys.LeftAlt, PlayerIndex.One) == false && InputManager.Pressed(Keys.RightAlt, PlayerIndex.One) == false) // Make sure not to load credits if alttabbing. + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.Credits, false, null); + + if (Game.GlobalInput.JustPressed(InputMapType.MENU_PROFILESELECT)) + (ScreenManager as RCScreenManager).DisplayScreen(ScreenType.ProfileSelect, false, null); + + base.HandleInput(); + } + + public void HandleAchievementInput() + { + if (InputManager.Pressed(Keys.LeftAlt, PlayerIndex.One) && InputManager.Pressed(Keys.CapsLock, PlayerIndex.One)) + { + if (InputManager.JustPressed(Keys.T, PlayerIndex.One)) + { + if (GameUtil.IsAchievementUnlocked("FEAR_OF_LIFE") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_DECISIONS") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_WEALTH") == true && + GameUtil.IsAchievementUnlocked("LOVE_OF_GOLD") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_NUDITY") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_THROWING_STUFF_OUT") == true && + GameUtil.IsAchievementUnlocked("LOVE_OF_MAGIC") == true && + GameUtil.IsAchievementUnlocked("LOVE_OF_CHANGE") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_EYES") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_GHOSTS") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_FIRE") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_SLIME") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_FATHERS") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_ANIMALS") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_TWINS") == true && + GameUtil.IsAchievementUnlocked("LOVE_OF_BOOKS") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_CHICKENS") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_GRAVITY") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_IMPERFECTIONS") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_SLEEP") == true && + GameUtil.IsAchievementUnlocked("LOVE_OF_CLOWNS") == true && + GameUtil.IsAchievementUnlocked("LOVE_OF_KNOWLEDGE") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_RELATIVES") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_CHEMICALS") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_BONES") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_BLINDNESS") == true && + GameUtil.IsAchievementUnlocked("FEAR_OF_SPACE") == true && + GameUtil.IsAchievementUnlocked("LOVE_OF_LAUGHING_AT_OTHERS") == true) + { + Console.WriteLine("UNLOCKED THANATOPHOBIA"); + GameUtil.UnlockAchievement("FEAR_OF_DYING"); + } + } + else if (InputManager.JustPressed(Keys.S, PlayerIndex.One)) + { + Console.WriteLine("UNLOCKED SOMNIPHOBIA"); + GameUtil.UnlockAchievement("FEAR_OF_SLEEP"); + } + } + } + + public void ChangeRay() + { + + //if (Keyboard.GetState().IsKeyDown(Keys.F1)) + // m_godRay.lightTexture = ScreenManager.Game.Content.Load("GameSpritesheets/flare"); + //if (Keyboard.GetState().IsKeyDown(Keys.F2)) + // m_godRay.lightTexture = ScreenManager.Game.Content.Load("GameSpritesheets/flare2"); + //if (Keyboard.GetState().IsKeyDown(Keys.F3)) + // m_godRay.lightTexture = ScreenManager.Game.Content.Load("GameSpritesheets/flare3"); + //if (Keyboard.GetState().IsKeyDown(Keys.F4)) + // m_godRay.lightTexture = ScreenManager.Game.Content.Load("GameSpritesheets/flare4"); + + if (Keyboard.GetState().IsKeyDown(Keys.Up)) + m_godRay.lightSource = new Vector2(m_godRay.lightSource.X, m_godRay.lightSource.Y - .01f); + if (Keyboard.GetState().IsKeyDown(Keys.Down)) + m_godRay.lightSource = new Vector2(m_godRay.lightSource.X, m_godRay.lightSource.Y + .01f); + if (Keyboard.GetState().IsKeyDown(Keys.Left)) + m_godRay.lightSource = new Vector2(m_godRay.lightSource.X - .01f, m_godRay.lightSource.Y); + if (Keyboard.GetState().IsKeyDown(Keys.Right)) + m_godRay.lightSource = new Vector2(m_godRay.lightSource.X + .01f, m_godRay.lightSource.Y); + + if (Keyboard.GetState().IsKeyDown(Keys.Y)) + m_godRay.Exposure += .01f; + if (Keyboard.GetState().IsKeyDown(Keys.H)) + m_godRay.Exposure -= .01f; + + if (Keyboard.GetState().IsKeyDown(Keys.U)) + m_godRay.LightSourceSize += .01f; + if (Keyboard.GetState().IsKeyDown(Keys.J)) + m_godRay.LightSourceSize -= .01f; + + if (Keyboard.GetState().IsKeyDown(Keys.I)) + m_godRay.Density += .01f; + if (Keyboard.GetState().IsKeyDown(Keys.K)) + m_godRay.Density -= .01f; + + if (Keyboard.GetState().IsKeyDown(Keys.O)) + m_godRay.Decay += .01f; + if (Keyboard.GetState().IsKeyDown(Keys.L)) + m_godRay.Decay -= .01f; + + if (Keyboard.GetState().IsKeyDown(Keys.P)) + m_godRay.Weight += .01f; + if (Keyboard.GetState().IsKeyDown(Keys.OemSemicolon)) + m_godRay.Weight -= .01f; + } + + public override void Draw(GameTime gameTime) + { + Camera.GraphicsDevice.SetRenderTarget(m_godRayTexture); + Camera.GraphicsDevice.Clear(Color.White); + Camera.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.LinearClamp, null, null); // Anything that is affected by the godray should be drawn here. + m_smallCloud1.DrawOutline(Camera); + m_smallCloud3.DrawOutline(Camera); + m_smallCloud4.DrawOutline(Camera); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + m_castle.DrawOutline(Camera); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + m_smallCloud2.DrawOutline(Camera); + m_smallCloud5.DrawOutline(Camera); + m_logo.DrawOutline(Camera); + m_dlcIcon.DrawOutline(Camera); + m_crown.DrawOutline(Camera); + + //m_largeCloud1.DrawOutline(Camera); + //m_largeCloud2.DrawOutline(Camera); + //m_largeCloud3.DrawOutline(Camera); + //m_largeCloud4.DrawOutline(Camera); + Camera.End(); + + m_ppm.Draw(gameTime, m_godRayTexture); + + //Anything not affected by god ray should get drawn here. + Camera.GraphicsDevice.SetRenderTarget(m_godRayTexture); + Camera.GraphicsDevice.Clear(Color.Black); + Camera.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, null, null); + m_bg.Draw(Camera); + m_smallCloud1.Draw(Camera); + m_smallCloud3.Draw(Camera); + m_smallCloud4.Draw(Camera); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + m_castle.Draw(Camera); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + m_smallCloud2.Draw(Camera); + m_smallCloud5.Draw(Camera); + + m_largeCloud1.Draw(Camera); + m_largeCloud2.Draw(Camera); + m_largeCloud3.Draw(Camera); + m_largeCloud4.Draw(Camera); + + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; + Camera.Draw(Game.GenericTexture, new Rectangle(-10, -10, 1400, 800), Color.Black * m_hardCoreModeOpacity); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp; + + m_logo.Draw(Camera); + m_crown.Draw(Camera); + m_copyrightText.Draw(Camera); + m_versionNumber.Draw(Camera); + + m_pressStartText2.Opacity = m_pressStartText.Opacity; + m_pressStartText.Draw(Camera); + m_pressStartText2.Draw(Camera); + + if (m_startNewLegacy == false) + m_profileCardKey.Draw(Camera); + m_creditsKey.Draw(Camera); + m_optionsKey.Draw(Camera); + m_profileSelectKey.Draw(Camera); + Camera.GraphicsDevice.SamplerStates[0] = SamplerState.PointWrap; + if (m_startNewLegacy == false) + m_profileCard.Draw(Camera); + m_dlcIcon.Draw(Camera); + m_optionsIcon.Draw(Camera); + m_creditsIcon.Draw(Camera); + Camera.End(); + + Camera.GraphicsDevice.SetRenderTarget((ScreenManager as RCScreenManager).RenderTarget); + Camera.GraphicsDevice.Clear(Color.Black); + + Camera.Begin(SpriteSortMode.Immediate, BlendState.Additive); + Camera.Draw(m_ppm.Scene, new Rectangle(0, 0, Camera.GraphicsDevice.Viewport.Width, Camera.GraphicsDevice.Viewport.Height), Color.White); + Camera.Draw(m_godRayTexture, new Rectangle(0, 0, Camera.GraphicsDevice.Viewport.Width, Camera.GraphicsDevice.Viewport.Height), Color.White); + Camera.End(); + + base.Draw(gameTime); + } + + public override void Dispose() + { + if (IsDisposed == false) + { + Console.WriteLine("Disposing Title Screen"); + m_godRayTexture.Dispose(); + m_godRayTexture = null; + + m_bg.Dispose(); + m_bg = null; + m_logo.Dispose(); + m_logo = null; + m_castle.Dispose(); + m_castle = null; + + m_smallCloud1.Dispose(); + m_smallCloud2.Dispose(); + m_smallCloud3.Dispose(); + m_smallCloud4.Dispose(); + m_smallCloud5.Dispose(); + m_smallCloud1 = null; + m_smallCloud2 = null; + m_smallCloud3 = null; + m_smallCloud4 = null; + m_smallCloud5 = null; + + m_largeCloud1.Dispose(); + m_largeCloud1 = null; + m_largeCloud2.Dispose(); + m_largeCloud2 = null; + m_largeCloud3.Dispose(); + m_largeCloud3 = null; + m_largeCloud4.Dispose(); + m_largeCloud4 = null; + + m_pressStartText.Dispose(); + m_pressStartText = null; + m_pressStartText2.Dispose(); + m_pressStartText2 = null; + m_copyrightText.Dispose(); + m_copyrightText = null; + m_versionNumber.Dispose(); + m_versionNumber = null; + m_titleText.Dispose(); + m_titleText = null; + + m_profileCard.Dispose(); + m_profileCard = null; + m_optionsIcon.Dispose(); + m_optionsIcon = null; + m_creditsIcon.Dispose(); + m_creditsIcon = null; + + m_profileCardKey.Dispose(); + m_profileCardKey = null; + m_optionsKey.Dispose(); + m_optionsKey = null; + m_creditsKey.Dispose(); + m_creditsKey = null; + m_crown.Dispose(); + m_crown = null; + m_profileSelectKey.Dispose(); + m_profileSelectKey = null; + + m_dlcIcon.Dispose(); + m_dlcIcon = null; + + m_seagullCue = null; + base.Dispose(); + } + } + + public override void RefreshTextObjs() + { + UpdateCopyrightText(); + m_profileSelectKey.Text = string.Format(LocaleBuilder.getResourceString("LOC_ID_BACK_TO_MENU_OPTIONS_3_NEW"), Game.GameConfig.ProfileSlot); + //m_profileSelectKey.Text = "[Input:" + InputMapType.MENU_PROFILESELECT + "] " + LocaleBuilder.getResourceString("LOC_ID_BACK_TO_MENU_OPTIONS_3") + " (" + Game.GameConfig.ProfileSlot + ")"; + InitializeStartingText(); // refreshes m_pressStartText2 + base.RefreshTextObjs(); + } + } +} diff --git a/RogueCastle/src/SkillBuilder.cs b/RogueCastle/src/SkillBuilder.cs new file mode 100644 index 0000000..7e84044 --- /dev/null +++ b/RogueCastle/src/SkillBuilder.cs @@ -0,0 +1,1398 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + class SkillBuilder + { + + public static SkillObj BuildSkill(SkillType skillType, SkillObj trait = null) + { + if (trait == null) + trait = new SkillObj("Icon_SwordLocked_Sprite"); + + switch (skillType) + { + case (SkillType.Null): + break; + case (SkillType.Filler): + trait.Name = "Filler"; // not localized + //trait.Description = "This is a filler trait used to link to other traits. This text should never be visible."; // not localized + trait.NameLocID = ""; + trait.DescLocID = ""; + break; + + #region Skills + + case (SkillType.Health_Up): + trait.Name = "Health Up"; + //trait.Description = "Improve your cardio workout. A better heart means better health."; + trait.NameLocID = "LOC_ID_SKILL_NAME_1"; + trait.DescLocID = "LOC_ID_SKILL_DESC_1"; + trait.PerLevelModifier = 10f; + trait.BaseCost = 50; + trait.Appreciation = 40; + trait.MaxLevel = 75; + trait.IconName = "Icon_Health_UpLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = " hp"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_14" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Invuln_Time_Up): + trait.Name = "Invuln Time Up"; + //trait.Description = "Strengthen your adrenal glands and be invulnerable like Bane. Let the games begin!"; + trait.NameLocID = "LOC_ID_SKILL_NAME_2"; + trait.DescLocID = "LOC_ID_SKILL_DESC_2"; + trait.PerLevelModifier = 0.1f; + trait.BaseCost = 750; + trait.Appreciation = 1700; + trait.MaxLevel = 5; + trait.IconName = "Icon_InvulnTimeUpLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = " sec"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_21" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Death_Dodge): + trait.Name = "Death Defy"; + //trait.Description = "Release your inner cat, and avoid death. Sometimes."; + trait.NameLocID = "LOC_ID_SKILL_NAME_3"; + trait.DescLocID = "LOC_ID_SKILL_DESC_3"; + trait.PerLevelModifier = 0.015f; + trait.BaseCost = 750; + trait.Appreciation = 1500; + trait.MaxLevel = 10; + trait.IconName = "Icon_DeathDefyLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = "%"; + switch (LocaleBuilder.languageType) + { + case(LanguageType.French): + trait.UnitLocIDs = new string[] { " %", "" }; + break; + default: + trait.UnitLocIDs = new string[] { "%", "" }; + break; + } + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Attack_Up): + trait.Name = "Attack Up"; + //trait.Description = "A proper gym will allow you to really strengthen your arms and butt muscles."; + trait.NameLocID = "LOC_ID_SKILL_NAME_4"; + trait.DescLocID = "LOC_ID_SKILL_DESC_4"; + trait.PerLevelModifier = 2f; + trait.BaseCost = 100; + trait.Appreciation = 85; + trait.MaxLevel = 75; + trait.IconName = "Icon_SwordLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = " str"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_16" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Down_Strike_Up): + trait.Name = "Down Strike Up"; + //trait.Description = "A pogo practice room has its benefits. Deal more damage with consecutive down strikes."; + trait.NameLocID = "LOC_ID_SKILL_NAME_5"; + trait.DescLocID = "LOC_ID_SKILL_DESC_5"; + trait.PerLevelModifier = 0.05f; + trait.BaseCost = 750; + trait.Appreciation = 1500; + trait.MaxLevel = 5; + trait.IconName = "Icon_Attack_UpLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = "%"; + switch (LocaleBuilder.languageType) + { + case (LanguageType.French): + trait.UnitLocIDs = new string[] { " %", "" }; + break; + default: + trait.UnitLocIDs = new string[] { "%", "" }; + break; + } + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Crit_Chance_Up): + trait.Name = "Crit Chance Up"; + //trait.Description = "Teaching yourself about the weaknesses of enemies allows you to strike with deadly efficiency."; + trait.NameLocID = "LOC_ID_SKILL_NAME_6"; + trait.DescLocID = "LOC_ID_SKILL_DESC_6"; + trait.PerLevelModifier = 0.02f; + trait.BaseCost = 150; + trait.Appreciation = 125; + trait.MaxLevel = 25; + trait.IconName = "Icon_Crit_Chance_UpLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = "%"; + switch (LocaleBuilder.languageType) + { + case (LanguageType.French): + trait.UnitLocIDs = new string[] { " %", "" }; + break; + default: + trait.UnitLocIDs = new string[] { "%", "" }; + break; + } + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Crit_Damage_Up): + trait.Name = "Crit Damage Up"; + //trait.Description = "Practice the deadly strikes to be even deadlier. Enemies will be so dead."; + trait.NameLocID = "LOC_ID_SKILL_NAME_7"; + trait.DescLocID = "LOC_ID_SKILL_DESC_7"; + trait.PerLevelModifier = 0.05f; + trait.BaseCost = 150; + trait.Appreciation = 125; + trait.MaxLevel = 25; + trait.IconName = "Icon_Crit_Damage_UpLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = "%"; + switch (LocaleBuilder.languageType) + { + case (LanguageType.French): + trait.UnitLocIDs = new string[] { " %", "" }; + break; + default: + trait.UnitLocIDs = new string[] { "%", "" }; + break; + } + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Magic_Damage_Up): + trait.Name = "Magic Damage Up"; + //trait.Description = "Learn the secrets of the universe, so you can use it to kill with spells better."; + trait.NameLocID = "LOC_ID_SKILL_NAME_8"; + trait.DescLocID = "LOC_ID_SKILL_DESC_8"; + trait.PerLevelModifier = 2f; + trait.BaseCost = 100; + trait.Appreciation = 85; + trait.MaxLevel = 75; + trait.IconName = "Icon_MagicDmgUpLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = " int"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_17" }; + trait.DisplayStat = false; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Mana_Up): + trait.Name = "Mana Up"; + //trait.Description = "Increase your mental fortitude in order to increase your mana pool. "; + trait.NameLocID = "LOC_ID_SKILL_NAME_9"; + trait.DescLocID = "LOC_ID_SKILL_DESC_9"; + trait.PerLevelModifier = 10f; + trait.BaseCost = 50; + trait.Appreciation = 40; + trait.MaxLevel = 75; + trait.IconName = "Icon_ManaUpLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = " mp"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_15" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Smithy): + trait.Name = "Smithy"; + //trait.Description = "Unlock the smithy and gain access to phat loot."; + trait.NameLocID = "LOC_ID_SKILL_NAME_10"; + trait.DescLocID = "LOC_ID_SKILL_DESC_10"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 50; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_SmithyLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = "0"; + trait.DisplayStat = false; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Enchanter): + trait.Name = "Enchantress"; + //trait.Description = "Unlock the enchantress and gain access to her magical runes and powers."; + trait.NameLocID = "LOC_ID_SKILL_NAME_11"; + trait.DescLocID = "LOC_ID_SKILL_DESC_11"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 50; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_EnchanterLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = "0"; + trait.DisplayStat = false; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Architect): + trait.Name = "Architect"; + //trait.Description = "Unlock the architect and gain the powers to lock down the castle."; + trait.NameLocID = "LOC_ID_SKILL_NAME_12"; + trait.DescLocID = "LOC_ID_SKILL_DESC_12"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 50; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_ArchitectLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = "0"; + trait.DisplayStat = false; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Equip_Up): + trait.Name = "Equip Up"; + //trait.Description = "Upgrading your carry capacity will allow you to wear better and heavier armor."; + trait.NameLocID = "LOC_ID_SKILL_NAME_13"; + trait.DescLocID = "LOC_ID_SKILL_DESC_13"; + trait.PerLevelModifier = 10f; + trait.BaseCost = 50; + trait.Appreciation = 40; + trait.MaxLevel = 50; + trait.IconName = "Icon_Equip_UpLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = " weight"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_13" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Armor_Up): + trait.Name = "Armor Up"; + //trait.Description = "Strengthen your innards through natural means to reduce incoming damage."; + trait.NameLocID = "LOC_ID_SKILL_NAME_14"; + trait.DescLocID = "LOC_ID_SKILL_DESC_14"; + trait.PerLevelModifier = 4f; + trait.BaseCost = 125; + trait.Appreciation = 105; + trait.MaxLevel = 50; + trait.IconName = "Icon_ShieldLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = " armor"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_20" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Gold_Gain_Up): + trait.Name = "Gold Gain Up"; + //trait.Description = "Improve your looting skills, and get more bang for your buck."; + trait.NameLocID = "LOC_ID_SKILL_NAME_15"; + trait.DescLocID = "LOC_ID_SKILL_DESC_15"; + trait.PerLevelModifier = 0.1f; + trait.BaseCost = 1000; + trait.Appreciation = 2150; + trait.MaxLevel = 5; + trait.IconName = "Icon_Gold_Gain_UpLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = "%"; + switch (LocaleBuilder.languageType) + { + case (LanguageType.French): + trait.UnitLocIDs = new string[] { " %", "" }; + break; + default: + trait.UnitLocIDs = new string[] { "%", "" }; + break; + } + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Prices_Down): + trait.Name = "Haggle"; + //trait.Description = "Lower Charon's toll by learning how to barter with death itself."; + trait.NameLocID = "LOC_ID_SKILL_NAME_16"; + trait.DescLocID = "LOC_ID_SKILL_DESC_16"; + trait.PerLevelModifier = 0.1f; + trait.BaseCost = 500; + trait.Appreciation = 1000; + trait.MaxLevel = 5; + trait.IconName = "Icon_HaggleLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = "%"; + switch (LocaleBuilder.languageType) + { + case (LanguageType.French): + trait.UnitLocIDs = new string[] { " %", "" }; + break; + default: + trait.UnitLocIDs = new string[] { "%", "" }; + break; + } + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Potion_Up): + trait.Name = "Potion Up"; + //trait.Description = "Gut cleansing leads to noticable improvements from both potions and meat."; + trait.NameLocID = "LOC_ID_SKILL_NAME_17"; + trait.DescLocID = "LOC_ID_SKILL_DESC_17"; + trait.PerLevelModifier = 0.01f; + trait.BaseCost = 750; + trait.Appreciation = 1750; + trait.MaxLevel = 5; + trait.IconName = "Icon_PotionUpLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = "% hp/mp"; + switch (LocaleBuilder.languageType) + { + case (LanguageType.French): + trait.UnitLocIDs = new string[] { " % ", "LOC_ID_SKILL_SCREEN_18" }; + break; + default: + trait.UnitLocIDs = new string[] { "% ", "LOC_ID_SKILL_SCREEN_18" }; + break; + } + trait.DisplayStat = false; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Randomize_Children): + trait.Name = "Randomize Children"; + //trait.Description = "Use the power of science to make a whole new batch of babies. Just... don't ask."; + trait.NameLocID = "LOC_ID_SKILL_NAME_18"; + trait.DescLocID = "LOC_ID_SKILL_DESC_18"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 5000; + trait.Appreciation = 5000; + trait.MaxLevel = 1; + trait.IconName = "Icon_RandomizeChildrenLocked_Sprite"; + //trait.InputDescription = "Press [Input:" + InputMapType.MENU_MAP + "] to randomize your children"; + //trait.InputDescLocIDs = new string[] { "LOC_ID_SKILL_INPUT_1", " [Input:" + InputMapType.MENU_MAP + "] ", "LOC_ID_SKILL_INPUT_2" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_18"; + trait.UnitOfMeasurement = "%"; + switch (LocaleBuilder.languageType) + { + case (LanguageType.French): + trait.UnitLocIDs = new string[] { " %", "" }; + break; + default: + trait.UnitLocIDs = new string[] { "%", "" }; + break; + } + trait.DisplayStat = false; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Lich_Unlock): + trait.Name = "Unlock Lich"; + //trait.Description = "Release the power of the Lich! A being of massive potential."; + trait.NameLocID = "LOC_ID_SKILL_NAME_19"; + trait.DescLocID = "LOC_ID_SKILL_DESC_19"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 850; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_LichUnlockLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = " hp"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_14" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Banker_Unlock): + trait.Name = "Unlock Miner"; + //trait.Description = "Unlock the skills of the Miner and raise your family fortune."; + trait.NameLocID = "LOC_ID_SKILL_NAME_20"; + trait.DescLocID = "LOC_ID_SKILL_DESC_20"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 400; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_SpelunkerUnlockLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = " hp"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_14" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Spellsword_Unlock): + trait.Name = "Unlock Spell Thief"; + //trait.Description = "Unlock the Spellthief, and become a martial mage."; + trait.NameLocID = "LOC_ID_SKILL_NAME_21"; + trait.DescLocID = "LOC_ID_SKILL_DESC_21"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 850; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_SpellswordUnlockLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = " hp"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_14" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Ninja_Unlock): + trait.Name = "Unlock Shinobi"; + //trait.Description = "Unlock the Shinobi, the fleetest of fighters."; + trait.NameLocID = "LOC_ID_SKILL_NAME_22"; + trait.DescLocID = "LOC_ID_SKILL_DESC_22"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 400; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_NinjaUnlockLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = " hp"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_14" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Mana_Cost_Down): + trait.Name = "Mana Cost Down"; + //trait.Description = "Practice your basics to reduce mana costs when casting spells."; + trait.NameLocID = "LOC_ID_SKILL_NAME_23"; + trait.DescLocID = "LOC_ID_SKILL_DESC_23"; + trait.PerLevelModifier = 0.05f; + trait.BaseCost = 750; + trait.Appreciation = 1700; + trait.MaxLevel = 5; + trait.IconName = "Icon_ManaCostDownLocked_Sprite"; + //trait.InputDescription = " "; + //trait.InputDescLocIDs = new string[] { "", " ", "" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_SPACE"; + trait.UnitOfMeasurement = "%"; + switch (LocaleBuilder.languageType) + { + case (LanguageType.French): + trait.UnitLocIDs = new string[] { " %", "" }; + break; + default: + trait.UnitLocIDs = new string[] { "%", "" }; + break; + } + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Knight_Up): + trait.Name = "Upgrade Knight"; + //trait.Description = "Turn your knights into Paladins. A ferocious forefront fighter."; + trait.NameLocID = "LOC_ID_SKILL_NAME_24"; + trait.DescLocID = "LOC_ID_SKILL_DESC_24"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 50; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_KnightUpLocked_Sprite"; + //trait.InputDescription = "Press [Input:" + InputMapType.PLAYER_BLOCK + "] to block all incoming damage."; + //trait.InputDescLocIDs = new string[] { "LOC_ID_SKILL_INPUT_1", " [Input:" + InputMapType.PLAYER_BLOCK + "] ", "LOC_ID_SKILL_INPUT_3" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_24"; + trait.UnitOfMeasurement = " hp"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_14" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Mage_Up): + trait.Name = "Upgrade Mage"; + //trait.Description = "Unlock the latent powers of the Mage and transform them into the all powerful Archmage"; + trait.NameLocID = "LOC_ID_SKILL_NAME_25"; + trait.DescLocID = "LOC_ID_SKILL_DESC_25"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 300; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_WizardUpLocked_Sprite"; + //trait.InputDescription = "Press [Input:" + InputMapType.PLAYER_BLOCK + "] to switch spells"; + //trait.InputDescLocIDs = new string[] { "LOC_ID_SKILL_INPUT_1", " [Input:" + InputMapType.PLAYER_BLOCK + "] ", "LOC_ID_SKILL_INPUT_4" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_25"; + trait.UnitOfMeasurement = " hp"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_14" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Assassin_Up): + trait.Name = "Upgrade Knave"; + //trait.Description = "Learn the dark arts, and turn the Knave into an Assassin"; + trait.NameLocID = "LOC_ID_SKILL_NAME_26"; + trait.DescLocID = "LOC_ID_SKILL_DESC_26"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 300; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_AssassinUpLocked_Sprite"; + //trait.InputDescription = "Press [Input:" + InputMapType.PLAYER_BLOCK + "] to turn to mist"; + //trait.InputDescLocIDs = new string[] { "LOC_ID_SKILL_INPUT_1", " [Input:" + InputMapType.PLAYER_BLOCK + "] ", "LOC_ID_SKILL_INPUT_5" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_26"; + trait.UnitOfMeasurement = " hp"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_14" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Banker_Up): + trait.Name = "Upgrade Miner"; + //trait.Description = "Earn your geology degree and go from Miner to Spelunker. Spiffy."; + trait.NameLocID = "LOC_ID_SKILL_NAME_27"; + trait.DescLocID = "LOC_ID_SKILL_DESC_27"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 1750; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_SpelunkerUpLocked_Sprite"; + //trait.InputDescription = "Press [Input:" + InputMapType.PLAYER_BLOCK + "] to turn on your headlamp"; + //trait.InputDescLocIDs = new string[] { "LOC_ID_SKILL_INPUT_1", " [Input:" + InputMapType.PLAYER_BLOCK + "] ", "LOC_ID_SKILL_INPUT_6" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_27"; + trait.UnitOfMeasurement = " hp"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_14" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Barbarian_Up): + trait.Name = "Upgrade Barbarian"; + //trait.Description = "Become a Barbarian King. The king of freemen. That makes no sense."; + trait.NameLocID = "LOC_ID_SKILL_NAME_28"; + trait.DescLocID = "LOC_ID_SKILL_DESC_28"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 300; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_BarbarianUpLocked_Sprite"; + //trait.InputDescription = "Press [Input:" + InputMapType.PLAYER_BLOCK + "] to cast an epic shout that knocks virtually everything away."; + //trait.InputDescLocIDs = new string[] { "LOC_ID_SKILL_INPUT_1", " [Input:" + InputMapType.PLAYER_BLOCK + "] ", "LOC_ID_SKILL_INPUT_7" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_28"; + trait.UnitOfMeasurement = " hp"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_14" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Lich_Up): + trait.Name = "Upgrade Lich"; + //trait.Description = "Royalize your all-powerful Liches, and turn them into Lich Kings."; + trait.NameLocID = "LOC_ID_SKILL_NAME_29"; + trait.DescLocID = "LOC_ID_SKILL_DESC_29"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 1500; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_LichUpLocked_Sprite"; + //trait.InputDescription = "Press [Input:" + InputMapType.PLAYER_BLOCK + "] to convert max hp into max mp"; + //trait.InputDescLocIDs = new string[] { "LOC_ID_SKILL_INPUT_1", " [Input:" + InputMapType.PLAYER_BLOCK + "] ", "LOC_ID_SKILL_INPUT_8" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_29"; + trait.UnitOfMeasurement = " hp"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_14" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.Ninja_Up): + trait.Name = "Upgrade Shinobi"; + //trait.Description = "Become the leader of your village, and turn your Shinobi into a Hokage. Believe it!"; + trait.NameLocID = "LOC_ID_SKILL_NAME_30"; + trait.DescLocID = "LOC_ID_SKILL_DESC_30"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 750; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_NinjaUpLocked_Sprite"; + //trait.InputDescription = "Press [Input:" + InputMapType.PLAYER_BLOCK + "] to flash"; + //trait.InputDescLocIDs = new string[] { "LOC_ID_SKILL_INPUT_1", " [Input:" + InputMapType.PLAYER_BLOCK + "] ", "LOC_ID_SKILL_INPUT_9" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_30"; + trait.UnitOfMeasurement = " hp"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_14" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + case (SkillType.SpellSword_Up): + trait.Name = "Upgrade Spell Thief"; + //trait.Description = "Ride the vortexes of magic, and turn your Spellthiefs into Spellswords."; + trait.NameLocID = "LOC_ID_SKILL_NAME_31"; + trait.DescLocID = "LOC_ID_SKILL_DESC_31"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 1500; + trait.Appreciation = 0; + trait.MaxLevel = 1; + trait.IconName = "Icon_SpellswordUpLocked_Sprite"; + //trait.InputDescription = "Press [Input:" + InputMapType.PLAYER_BLOCK + "] to cast empowered spells"; + //trait.InputDescLocIDs = new string[] { "LOC_ID_SKILL_INPUT_1", " [Input:" + InputMapType.PLAYER_BLOCK + "] ", "LOC_ID_SKILL_INPUT_10" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_31"; + trait.UnitOfMeasurement = " hp"; + trait.UnitLocIDs = new string[] { " ", "LOC_ID_SKILL_SCREEN_14" }; + trait.DisplayStat = true; + trait.StatType = TraitStatType.PlayerMaxHealth; + break; + + # endregion + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + case (SkillType.SuperSecret): + trait.Name = "Beastiality"; + //trait.Description = "Half man, half ******, all awesome."; + trait.NameLocID = "LOC_ID_SKILL_NAME_32"; + trait.DescLocID = "LOC_ID_SKILL_DESC_32"; + trait.PerLevelModifier = 10f; + trait.BaseCost = 5000;//7500;//50; + trait.Appreciation = 30; + trait.MaxLevel = 1; + trait.IconName = "Icon_Display_Boss_RoomsLocked_Sprite"; //Icon_SuperSecretLocked_Sprite + //trait.InputDescription = "Press [Input:" + InputMapType.PLAYER_JUMP1 + "] to awesome."; + //trait.InputDescLocIDs = new string[] { "LOC_ID_SKILL_INPUT_1", " [Input:" + InputMapType.PLAYER_JUMP1 + "] ", "LOC_ID_SKILL_INPUT_11" }; + trait.InputDescLocID = "LOC_ID_SKILL_INPUT_32"; + trait.UnitOfMeasurement = "hp"; + trait.UnitLocIDs = new string[] { "", "LOC_ID_SKILL_SCREEN_14" }; + trait.DisplayStat = true; + break; + + + + + + + + + + + case (SkillType.Quick_of_Breath): + trait.Name = "Quick of Breath"; + //trait.Description = "QUICK OF BREATH \nYou're a heavy breather. Bad for stalking, good for walking! \n\nIncrease your natural endurance regeneration."; + trait.NameLocID = "LOC_ID_SKILL_NAME_33"; + trait.DescLocID = "LOC_ID_SKILL_DESC_33"; + trait.PerLevelModifier = 1f; + trait.BaseCost = 1000; + trait.Appreciation = 500; + trait.MaxLevel = 5; + trait.IconName = "IconBootLocked_Sprite"; + break; + + + case (SkillType.Born_to_Run): + trait.Name = "Born to Run"; + //trait.Description = "You were infused with tiger blood at a young age. You have now been infused with the power to release tiger blood when stabbed. \nRunning drains less endurance."; + trait.NameLocID = "LOC_ID_SKILL_NAME_34"; + trait.DescLocID = "LOC_ID_SKILL_DESC_34"; + trait.Position = new Vector2(50, 100); + trait.PerLevelModifier = 0.01f; + trait.BaseCost = 700; + trait.Appreciation = 100; + trait.MaxLevel = 5; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Stout_Heart): + trait.Name = "Stout Heart"; + //trait.Description = "Your have viking ancestry. \n\nIncrease your starting endurance."; + trait.NameLocID = "LOC_ID_SKILL_NAME_35"; + trait.DescLocID = "LOC_ID_SKILL_DESC_35"; + trait.PerLevelModifier = 20f; + trait.BaseCost = 1000; + trait.Appreciation = 500; + trait.MaxLevel = 5; + trait.IconName = "IconBootLocked_Sprite"; + break; + + + + + case (SkillType.Out_the_Gate): + trait.Name = "Out the Gate"; + //trait.Description = "You're an early waker. If leveling was like waking up.\n Gain bonus HP and MP every time you level."; + trait.NameLocID = "LOC_ID_SKILL_NAME_36"; + trait.DescLocID = "LOC_ID_SKILL_DESC_36"; + trait.PerLevelModifier = 35f; + trait.BaseCost = 2500; + trait.Appreciation = 5000; + trait.MaxLevel = 2; + trait.IconName = "IconBootLocked_Sprite"; + break; + + + + + + + + + + + case (SkillType.Spell_Sword): + trait.Name = "Spellsword"; + //trait.Description = "You were born with absolute power in your fingertips. \nAll spells deal more damage."; + trait.NameLocID = "LOC_ID_SKILL_NAME_37"; + trait.DescLocID = "LOC_ID_SKILL_DESC_37"; + trait.Position = new Vector2(100, 200); + trait.PerLevelModifier = 5f; + trait.BaseCost = 700; + trait.Appreciation = 100; + trait.MaxLevel = 5; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Sorcerer): + trait.Name = "Sorcerer"; + //trait.Description = "You were born with arcane energy coarsing through your veins. Ow. \nSpells cost less to cast."; + trait.NameLocID = "LOC_ID_SKILL_NAME_38"; + trait.DescLocID = "LOC_ID_SKILL_DESC_38"; + trait.Position = new Vector2(100, 250); + trait.PerLevelModifier = 5f; + trait.BaseCost = 700; + trait.Appreciation = 100; + trait.MaxLevel = 5; + trait.IconName = "IconBootLocked_Sprite"; + break; + + + + + case (SkillType.Perfectionist): + trait.Name = "Perfectionist"; + //trait.Description = "OCD finally comes in handy. \nGain more gold."; + trait.NameLocID = "LOC_ID_SKILL_NAME_39"; + trait.DescLocID = "LOC_ID_SKILL_DESC_39"; + trait.Position = new Vector2(150, 50); + trait.PerLevelModifier = 1f; + trait.BaseCost = 1000; + trait.Appreciation = 100; + trait.MaxLevel = 5; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Well_Endowed): + trait.Name = "Well Endowed"; + //trait.Description = "By law, you are now the best man. \nGive birth to more children."; + trait.NameLocID = "LOC_ID_SKILL_NAME_40"; + trait.DescLocID = "LOC_ID_SKILL_DESC_40"; + trait.Position = new Vector2(150, 100); + trait.PerLevelModifier = 1f; + trait.BaseCost = 100; + trait.Appreciation = 100; + trait.MaxLevel = 2; + trait.IconName = "IconBootLocked_Sprite"; + break; + + + + + + + + case (SkillType.Treasure_Hunter): + trait.Name = "Treasure Hunter"; + //trait.Description = "Your parents said learning how to sift for gold was useless for a farmer. Whose laughing now? \n Display treasure rooms at the start of the game."; + trait.NameLocID = "LOC_ID_SKILL_NAME_41"; + trait.DescLocID = "LOC_ID_SKILL_DESC_41"; + trait.Position = new Vector2(150, 250); + trait.PerLevelModifier = 1f; + trait.BaseCost = 100; + trait.Appreciation = 100; + trait.MaxLevel = 2; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Mortar_Master): + trait.Name = "Mortar Master"; + //trait.Description = "War is hell. Luckily you were never in one. \n Fire more mortars."; + trait.NameLocID = "LOC_ID_SKILL_NAME_42"; + trait.DescLocID = "LOC_ID_SKILL_DESC_42"; + trait.Position = new Vector2(150, 300); + trait.PerLevelModifier = 1f; + trait.BaseCost = 1000; + trait.Appreciation = 100; + trait.MaxLevel = 3; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Explosive_Expert): + trait.Name = "Explosive Expert"; + //trait.Description = "As a child, you showed an affinity for blowing things up. \n Bombs have a larger radius."; + trait.NameLocID = "LOC_ID_SKILL_NAME_43"; + trait.DescLocID = "LOC_ID_SKILL_DESC_43"; + trait.Position = new Vector2(200, 50); + trait.PerLevelModifier = 5f; + trait.BaseCost = 1000; + trait.Appreciation = 100; + trait.MaxLevel = 3; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Icicle): + trait.Name = "Icicle"; + //trait.Description = "You're great grandfather was a snowman. He taught you nothing. \n Icicles pierce through more enemies."; + trait.NameLocID = "LOC_ID_SKILL_NAME_44"; + trait.DescLocID = "LOC_ID_SKILL_DESC_44"; + trait.Position = new Vector2(200, 100); + trait.PerLevelModifier = 1f; + trait.BaseCost = 1000; + trait.Appreciation = 100; + trait.MaxLevel = 3; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Guru): + trait.Name = "Guru"; + //trait.Description = "You are Zen-like. \n Regain endurance faster while still."; + trait.NameLocID = "LOC_ID_SKILL_NAME_45"; + trait.DescLocID = "LOC_ID_SKILL_DESC_45"; + trait.Position = new Vector2(50, 50); + trait.PerLevelModifier = 5f; + trait.BaseCost = 1000; + trait.Appreciation = 100; + trait.MaxLevel = 1; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Iron_Lung): + trait.Name = "Iron Lung"; + //trait.Description = "Generic SKILL. Increase total Endurance."; + trait.NameLocID = "LOC_ID_SKILL_NAME_46"; + trait.DescLocID = "LOC_ID_SKILL_DESC_46"; + trait.Position = new Vector2(50, 200); + trait.PerLevelModifier = 25f; + trait.BaseCost = 500; + trait.Appreciation = 100; + trait.MaxLevel = 50; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Sword_Master): + trait.Name = "Sword Master"; + //trait.Description = "You fight with finesse \n Attacks Drain X% less endurance."; + trait.NameLocID = "LOC_ID_SKILL_NAME_47"; + trait.DescLocID = "LOC_ID_SKILL_DESC_47"; + trait.Position = new Vector2(50, 150); + trait.PerLevelModifier = 0.1f; + trait.BaseCost = 1000; + trait.Appreciation = 100; + trait.MaxLevel = 2; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Tank): + trait.Name = "Tank"; + //trait.Description = "Generic SKILL. Increase Health"; + trait.NameLocID = "LOC_ID_SKILL_NAME_48"; + trait.DescLocID = "LOC_ID_SKILL_DESC_48"; + trait.Position = new Vector2(50, 200); + trait.PerLevelModifier = 25f; + trait.BaseCost = 500; + trait.Appreciation = 100; + trait.MaxLevel = 50; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Vampire): + trait.Name = "Vampire"; + //trait.Description = "You suck... Blood. \n Restore a small amount of life with every hit."; + trait.NameLocID = "LOC_ID_SKILL_NAME_49"; + trait.DescLocID = "LOC_ID_SKILL_DESC_49"; + trait.Position = new Vector2(50, 250); + trait.PerLevelModifier = 1f; + trait.BaseCost = 1000; + trait.Appreciation = 100; + trait.MaxLevel = 1; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Second_Chance): + trait.Name = "Second Chance"; + //trait.Description = "Come back to life, just like Jesus. But you're still not jesus. \n Revive once after dying."; + trait.NameLocID = "LOC_ID_SKILL_NAME_50"; + trait.DescLocID = "LOC_ID_SKILL_DESC_50"; + trait.Position = new Vector2(50, 300); + trait.PerLevelModifier = 0.25f; + trait.BaseCost = 1000; + trait.Appreciation = 100; + trait.MaxLevel = 1; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Peace_of_Mind): + trait.Name = "Peace of Mind"; + //trait.Description = "Clearing a room is like clearing your mind. I don't know how. \nRegain helath for every room fully cleared."; + trait.NameLocID = "LOC_ID_SKILL_NAME_51"; + trait.DescLocID = "LOC_ID_SKILL_DESC_51"; + trait.Position = new Vector2(50, 250); + trait.PerLevelModifier = 10f; + trait.BaseCost = 1000; + trait.Appreciation = 100; + trait.MaxLevel = 1; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Cartography_Ninja): + trait.Name = "Cartography Ninja"; + //trait.Description = "Cartography /n Each percentage of map revealed adds 0.1 damage."; + trait.NameLocID = "LOC_ID_SKILL_NAME_52"; + trait.DescLocID = "LOC_ID_SKILL_DESC_52"; + trait.Position = new Vector2(100, 50); + trait.PerLevelModifier = 1f; + trait.BaseCost = 700; + trait.Appreciation = 100; + trait.MaxLevel = 1; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Strong_Man): + trait.Name = "Strong Man"; + //trait.Description = "Generic SKILL. Increase Attack Damage."; + trait.NameLocID = "LOC_ID_SKILL_NAME_53"; + trait.DescLocID = "LOC_ID_SKILL_DESC_53"; + trait.Position = new Vector2(100, 50); + trait.PerLevelModifier = 2f; + trait.BaseCost = 700; + trait.Appreciation = 100; + trait.MaxLevel = 50; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Suicidalist): + trait.Name = "Suicidalist"; + //trait.Description = "You're a very, very sore loser. \n Deal massive damage to all enemies on screen upon death."; + trait.NameLocID = "LOC_ID_SKILL_NAME_54"; + trait.DescLocID = "LOC_ID_SKILL_DESC_54"; + trait.Position = new Vector2(100, 100); + trait.PerLevelModifier = 100f; + trait.BaseCost = 700; + trait.Appreciation = 100; + trait.MaxLevel = 1; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Crit_Barbarian): + trait.Name = "Crit Barbarian"; + //trait.Description = "You have learned that hitting the balls deals massive damage. \n Crits deal more damage."; + trait.NameLocID = "LOC_ID_SKILL_NAME_55"; + trait.DescLocID = "LOC_ID_SKILL_DESC_55"; + trait.Position = new Vector2(100, 150); + trait.PerLevelModifier = 0.1f; + trait.BaseCost = 700; + trait.Appreciation = 100; + trait.MaxLevel = 1; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Magician): + trait.Name = "Magician"; + //trait.Description = "GENERIC SKILL."; + trait.NameLocID = "LOC_ID_SKILL_NAME_56"; + trait.DescLocID = "LOC_ID_SKILL_DESC_56"; + trait.Position = new Vector2(100, 250); + trait.PerLevelModifier = 1f; + trait.BaseCost = 700; + trait.Appreciation = 100; + trait.MaxLevel = 50; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Keymaster): + trait.Name = "Keymaster"; + //trait.Description = "Oh. They were in my back pocket. \nGain 2 extra keys."; + trait.NameLocID = "LOC_ID_SKILL_NAME_57"; + trait.DescLocID = "LOC_ID_SKILL_DESC_57"; + trait.Position = new Vector2(100, 300); + trait.PerLevelModifier = 2f; + trait.BaseCost = 2000; + trait.Appreciation = 100; + trait.MaxLevel = 1; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.One_Time_Only): + trait.Name = "One Time Only"; + //trait.Description = "Like a pheonix you are reborn from your crappy ashes. \n Regain all HP and MP."; + trait.NameLocID = "LOC_ID_SKILL_NAME_58"; + trait.DescLocID = "LOC_ID_SKILL_DESC_58"; + trait.Position = new Vector2(150, 100); + trait.PerLevelModifier = 1f; + trait.BaseCost = 100; + trait.Appreciation = 100; + trait.MaxLevel = 1; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Cutting_Out_Early): + trait.Name = "Cutting Out Early"; + //trait.Description = "Retire, and invest your money wisely. End your game early, and gain a bonus to gold found."; + trait.NameLocID = "LOC_ID_SKILL_NAME_59"; + trait.DescLocID = "LOC_ID_SKILL_DESC_59"; + trait.Position = new Vector2(150, 100); + trait.PerLevelModifier = 0.25f; + trait.BaseCost = 100; + trait.Appreciation = 100; + trait.MaxLevel = 1; + trait.IconName = "IconBootLocked_Sprite"; + break; + + case (SkillType.Quaffer): + trait.Name = "Quaffer"; + //trait.Description = "CHUG CHUG CHUG! \n Drink potions instantly."; + trait.NameLocID = "LOC_ID_SKILL_NAME_60"; + trait.DescLocID = "LOC_ID_SKILL_DESC_60"; + trait.Position = new Vector2(150, 150); + trait.PerLevelModifier = 1f; + trait.BaseCost = 1000; + trait.Appreciation = 100; + trait.MaxLevel = 1; + trait.IconName = "IconBootLocked_Sprite"; + break; + } + + trait.TraitType = skillType; + return trait; + } + + public static SkillLinker GetSkillLinker(int xIndex, int yIndex) + { + SkillLinker link = new SkillLinker(); + + if (xIndex == 5 && yIndex == 9) + { + link.TopLink = new Vector2(5, 8); + link.BottomLink = new Vector2(6, 9); + link.LeftLink = new Vector2(4, 5); + link.RightLink = new Vector2(6, 5); + } + else if (xIndex == 8 && yIndex == 8) + { + link.TopLink = new Vector2(5, 9); + link.BottomLink = new Vector2(-1, -1); + link.LeftLink = new Vector2(2, 8); + link.RightLink = new Vector2(8, 7); + } + else if (xIndex == 3 && yIndex == 4) + { + link.TopLink = new Vector2(2, 3); + link.BottomLink = new Vector2(3, 6); + link.LeftLink = new Vector2(2, 4); + link.RightLink = new Vector2(5, 6); + } + else if (xIndex == 4 && yIndex == 6) + { + link.TopLink = new Vector2(3, 6); + link.BottomLink = new Vector2(4, 5); + link.LeftLink = new Vector2(1, 5); + link.RightLink = new Vector2(5, 8); + } + else if (xIndex == 2 && yIndex == 8) + { + link.TopLink = new Vector2(4, 5); + link.BottomLink = new Vector2(-1, -1); + link.LeftLink = new Vector2(2, 7); + link.RightLink = new Vector2(6, 9); + } + else if (xIndex == 2 && yIndex == 5) + { + link.TopLink = new Vector2(2, 4); + link.BottomLink = new Vector2(2, 6); + link.LeftLink = new Vector2(0, 5); + link.RightLink = new Vector2(3, 6); + } + else if (xIndex == 1 && yIndex == 5) + { + link.TopLink = new Vector2(0, 5); + link.BottomLink = new Vector2(-1, -1); + link.LeftLink = new Vector2(0, 6); + link.RightLink = new Vector2(4, 6); + } + else if (xIndex == 8 && yIndex == 5) + { + link.TopLink = new Vector2(8, 4); + link.BottomLink = new Vector2(7, 6); + link.LeftLink = new Vector2(-1, -1); + link.RightLink = new Vector2(-1, -1); + } + else if (xIndex == 2 && yIndex == 6) + { + link.TopLink = new Vector2(2, 5); + link.BottomLink = new Vector2(2, 7); + link.LeftLink = new Vector2(-1, -1); + link.RightLink = new Vector2(4, 5); + } + else if (xIndex == 5 && yIndex == 8) + { + link.TopLink = new Vector2(5, 7); + link.BottomLink = new Vector2(5, 9); + link.LeftLink = new Vector2(4, 6); + link.RightLink = new Vector2(6, 6); + } + else if (xIndex == 5 && yIndex == 6) + { + link.TopLink = new Vector2(-1, -1); + link.BottomLink = new Vector2(5, 7); + link.LeftLink = new Vector2(3, 4); + link.RightLink = new Vector2(8, 3); + } + else if (xIndex == 3 && yIndex == 6) + { + link.TopLink = new Vector2(3, 4); + link.BottomLink = new Vector2(4, 6); + link.LeftLink = new Vector2(2, 5); + link.RightLink = new Vector2(5, 7); + } + else if (xIndex == 7 && yIndex == 6) + { + link.TopLink = new Vector2(8, 5); + link.BottomLink = new Vector2(6, 6); + link.LeftLink = new Vector2(5, 7); + link.RightLink = new Vector2(-1, -1); + } + else if (xIndex == 6 && yIndex == 6) + { + link.TopLink = new Vector2(7, 6); + link.BottomLink = new Vector2(6, 5); + link.LeftLink = new Vector2(5, 8); + link.RightLink = new Vector2(8, 6); + } + else if (xIndex == 8 && yIndex == 6) + { + link.TopLink = new Vector2(-1, -1); + link.BottomLink = new Vector2(8, 7); + link.LeftLink = new Vector2(6, 6); + link.RightLink = new Vector2(9, 6); + } + else if (xIndex == 8 && yIndex == 4) + { + link.TopLink = new Vector2(8, 1); + link.BottomLink = new Vector2(8, 5); + link.LeftLink = new Vector2(8, 3); + link.RightLink = new Vector2(-1, -1); + } + else if (xIndex == 8 && yIndex == 7) + { + link.TopLink = new Vector2(8, 6); + link.BottomLink = new Vector2(-1, -1); + link.LeftLink = new Vector2(6, 9); + link.RightLink = new Vector2(-1, -1); + } + else if (xIndex == 2 && yIndex == 7) + { + link.TopLink = new Vector2(2, 6); + link.BottomLink = new Vector2(2, 7); + link.LeftLink = new Vector2(-1, -1); + link.RightLink = new Vector2(2, 8); + } + else if (xIndex == 8 && yIndex == 3) + { + link.TopLink = new Vector2(8, 2); + link.BottomLink = new Vector2(-1, -1); + link.LeftLink = new Vector2(5, 6); + link.RightLink = new Vector2(8, 4); + } + else if (xIndex == 8 && yIndex == 2) + { + link.TopLink = new Vector2(7, 2); + link.BottomLink = new Vector2(8, 3); + link.LeftLink = new Vector2(-1, -1); + link.RightLink = new Vector2(8, 1); + } + else if (xIndex == 9 && yIndex == 6) + { + link.TopLink = new Vector2(-1, -1); + link.BottomLink = new Vector2(-1, -1); + link.LeftLink = new Vector2(8, 6); + link.RightLink = new Vector2(-1, -1); + } + else if (xIndex == 2 && yIndex == 4) + { + link.TopLink = new Vector2(-1, -1); + link.BottomLink = new Vector2(2, 5); + link.LeftLink = new Vector2(-1, -1); + link.RightLink = new Vector2(3, 4); + } + else if (xIndex == 5 && yIndex == 7) + { + link.TopLink = new Vector2(5, 6); + link.BottomLink = new Vector2(5, 8); + link.LeftLink = new Vector2(3, 6); + link.RightLink = new Vector2(7, 6); + } + else if (xIndex == 4 && yIndex == 5) + { + link.TopLink = new Vector2(4, 6); + link.BottomLink = new Vector2(2, 8); + link.LeftLink = new Vector2(2, 6); + link.RightLink = new Vector2(5, 9); + } + else if (xIndex == 6 && yIndex == 5) + { + link.TopLink = new Vector2(6, 6); + link.BottomLink = new Vector2(-1, -1); + link.LeftLink = new Vector2(5, 9); + link.RightLink = new Vector2(-1, -1); + } + else if (xIndex == 2 && yIndex == 3) + { + link.TopLink = new Vector2(-1, -1); + link.BottomLink = new Vector2(3, 4); + link.LeftLink = new Vector2(-1, -1); + link.RightLink = new Vector2(-1, -1); + } + else if (xIndex == 7 && yIndex == 2) + { + link.TopLink = new Vector2(7, 1); + link.BottomLink = new Vector2(8, 2); + link.LeftLink = new Vector2(-1, -1); + link.RightLink = new Vector2(-1, -1); + } + else if (xIndex == 7 && yIndex == 1) + { + link.BottomLink = new Vector2(7, 2); + link.TopLink = new Vector2(-1, -1); + link.LeftLink = new Vector2(-1, -1); + link.RightLink = new Vector2(-1, -1); + } + else if (xIndex == 0 && yIndex == 5) + { + link.TopLink = new Vector2(-1, -1); + link.BottomLink = new Vector2(1, 5); + link.LeftLink = new Vector2(0, 6); + link.RightLink = new Vector2(2, 5); + } + + else if (xIndex == 0 && yIndex == 6) + { + link.TopLink = new Vector2(-1, -1); + link.BottomLink = new Vector2(-11, -1); + link.LeftLink = new Vector2(-1, -1); + link.RightLink = new Vector2(0, 5); + } + else if (xIndex == 6 && yIndex == 9) + { + link.TopLink = new Vector2(5, 9); + link.BottomLink = new Vector2(-1, -1); + link.LeftLink = new Vector2(2, 8); + link.RightLink = new Vector2(8, 7); + } + else if (xIndex == 8 && yIndex == 1) + { + link.TopLink = new Vector2(-1, -1); + link.BottomLink = new Vector2(8, 4); + link.LeftLink = new Vector2(8, 2); + link.RightLink = new Vector2(8, 0); + } + else if (xIndex == 8 && yIndex == 0) + { + link.TopLink = new Vector2(-1, -1); + link.BottomLink = new Vector2(-1, -1); + link.LeftLink = new Vector2(8, 1); + link.RightLink = new Vector2(-1, -1); + } + return link; + } + } +} diff --git a/RogueCastle/src/SkillSystem.cs b/RogueCastle/src/SkillSystem.cs new file mode 100644 index 0000000..df20ebc --- /dev/null +++ b/RogueCastle/src/SkillSystem.cs @@ -0,0 +1,326 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class SkillSystem + { + #region MANOR PIECE CONSTS + private const int Trait_ObservatoryTelescope = 0; + private const int Trait_ObservatoryBase = 1; + private const int Trait_RightHighTower = 2; + private const int Trait_RightHighUpper = 3; + private const int Trait_RightHighBase = 4; + private const int Trait_RightExtension = 5; + private const int Trait_RightBigRoof = 6; + private const int Trait_RightBigUpper = 7; + private const int Trait_RightWingRoof = 8; + private const int Trait_RightBigBase = 9; + private const int Trait_RightWingBase = 10; + private const int Trait_RightWingWindow = 11; + private const int Trait_LeftExtensionBase = 12; + private const int Trait_LeftFarRoof = 13; + private const int Trait_LeftFarBase = 14; + private const int Trait_LeftBigRoof = 15; + private const int Trait_LeftBigUpper2 = 16; + private const int Trait_LeftBigWindows = 17; + private const int Trait_LeftBigUpper = 18; + private const int Trait_LeftBigBase = 19; + private const int Trait_LeftWingRoof = 20; + private const int Trait_LeftWingBase = 21; + private const int Trait_LeftWingWindow = 22; + private const int Trait_GroundRoad = 23; + private const int Trait_MainRoof = 24; + private const int Trait_MainBase = 25; + private const int Trait_FrontWindowTop = 26; + private const int Trait_FrontWindowBottom = 27; + private const int Trait_LeftTree1 = 28; + private const int Trait_LeftTree2 = 29; + private const int Trait_RightTree1 = 30; + private const int TOTAL = 31; + #endregion + + private static SkillType StartingTrait = SkillType.Smithy; //SkillType.Health_Up;//SkillType.Smithy; + private static SkillObj m_blankTrait; // A blank trait used for dead traits that need to be removed later on. + + //Remember: m_skillTypeArray is compiled as follows int[rows,cols]. + private static SkillType[,] m_skillTypeArray = + { + { SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Randomize_Children, SkillType.Null, }, + { SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.SuperSecret, SkillType.Mana_Cost_Down, SkillType.Null, }, + { SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Invuln_Time_Up, SkillType.SpellSword_Up, SkillType.Null, }, + { SkillType.Null, SkillType.Null, SkillType.Down_Strike_Up, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Spellsword_Unlock, SkillType.Null, }, + { SkillType.Null, SkillType.Null, SkillType.Ninja_Up, SkillType.Armor_Up, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Potion_Up, SkillType.Null, }, + { SkillType.Lich_Up, SkillType.Lich_Unlock, SkillType.Prices_Down, SkillType.Null, SkillType.Attack_Up, SkillType.Null, SkillType.Magic_Damage_Up, SkillType.Null, SkillType.Assassin_Up, SkillType.Null, }, + { SkillType.Death_Dodge, SkillType.Null, SkillType.Ninja_Unlock, SkillType.Barbarian_Up, SkillType.Architect, SkillType.Equip_Up, SkillType.Enchanter, SkillType.Mage_Up, SkillType.Banker_Unlock, SkillType.Banker_Up, }, + { SkillType.Null, SkillType.Null, SkillType.Crit_Chance_Up, SkillType.Null, SkillType.Null, SkillType.Knight_Up, SkillType.Null, SkillType.Null, SkillType.Gold_Gain_Up, SkillType.Null, }, + { SkillType.Null, SkillType.Null, SkillType.Crit_Damage_Up, SkillType.Null, SkillType.Null, SkillType.Health_Up, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, }, + { SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Null, SkillType.Smithy, SkillType.Mana_Up, SkillType.Null, SkillType.Null, SkillType.Null, }, + }; + + private static Vector2[,] m_skillPositionArray = + { + { new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2(860, 125), new Vector2 (0,0), }, + { new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (655,-100), new Vector2(735, 95), new Vector2 (0,0), }, + { new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2(655, 50), new Vector2(655, 125), new Vector2 (0,0), }, + { new Vector2 (0,0), new Vector2 (0,0), new Vector2(365, 150), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2(655, 200), new Vector2 (0,0), }, + { new Vector2 (0,0), new Vector2 (0,0), new Vector2(185, 250), new Vector2(365, 250), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2(735, 200), new Vector2 (0,0), }, + { new Vector2(110, 360), new Vector2(110, 460), new Vector2(185, 360), new Vector2 (0,0), new Vector2(275, 555), new Vector2 (0,0), new Vector2(735, 555), new Vector2 (0,0), new Vector2(735, 280), new Vector2 (0,0), }, + { new Vector2(40, 410), new Vector2 (0,0), new Vector2(185, 555), new Vector2(275, 360), new Vector2(275, 460), new Vector2(505, 315), new Vector2(735, 460), new Vector2(735, 360), new Vector2(860, 460), new Vector2(938, 415), }, + { new Vector2 (0,0), new Vector2 (0,0), new Vector2(185, 680), new Vector2 (0,0), new Vector2 (0,0), new Vector2(505, 410), new Vector2 (0,0), new Vector2 (0,0), new Vector2(860, 680), new Vector2 (0,0), }, + { new Vector2 (0,0), new Vector2 (0,0), new Vector2(275, 680), new Vector2 (0,0), new Vector2 (0,0), new Vector2(505, 490), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), }, + { new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), new Vector2(505, 590), new Vector2(505, 680), new Vector2 (0,0), new Vector2 (0,0), new Vector2 (0,0), } + }; + + private static int[,] m_manorPieceArray = + { + { -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, }, + { -1, -1, -1, -1, -1, -1, -1, 2, 1, -1, }, + { -1, -1, -1, -1, -1, -1, -1, 2, 3, -1, }, + { -1, -1, 15, -1, -1, -1, -1, -1, 4, -1, }, + { -1, -1, 16, 17, -1, -1, -1, -1, 6, -1, }, + { 13, 14, 18, -1, 22, -1, 11, -1, 7, -1, }, + { 12, -1, 19, 20, 21, 25, 10, 9, 8, 5, }, + { -1, -1, 29, -1, -1, 27, -1, -1, 31, -1, }, + { -1, -1, 30, -1, -1, 28, -1, -1, -1, -1, }, + { -1, -1, -1, -1, -1, 26, 24, -1, -1, -1, } + + }; + + private static SkillLinker[,] m_skillLinkerArray; + + private static List m_skillArray; + + private static bool m_iconsVisible = true; + + public static void Initialize() + { + m_blankTrait = new SkillObj("Icon_Sword_Sprite"); + + if (m_skillTypeArray.Length != m_skillPositionArray.Length) + throw new Exception("Cannot create Trait System. The type array is not the same length as the position array."); + + // Loading all traits into the trait array. + m_skillArray = new List(); + + for (int i = 2; i < (int)SkillType.DIVIDER; i++) // The starting 2 traits are null and filler. + { + SkillObj skill = SkillBuilder.BuildSkill((SkillType)i); + skill.Position = GetSkillPosition(skill); + m_skillArray.Add(skill); + //Console.WriteLine(trait.Position); + } + + GetSkill(StartingTrait).Visible = true; // Set the starting trait to visible. + + m_skillLinkerArray = new SkillLinker[10, 10]; + + for (int i = 0; i < 10; i++) + { + for (int k = 0; k < 10; k++) + { + m_skillLinkerArray[i, k] = SkillBuilder.GetSkillLinker(i, k); + } + } + } + + public static void LevelUpTrait(SkillObj trait, bool giveGoldBonus) + { + Game.PlayerStats.CurrentLevel++; + trait.CurrentLevel++; + UpdateTraitSprite(trait); + + if (trait.TraitType == SkillType.Gold_Flat_Bonus && giveGoldBonus == true) + Game.PlayerStats.Gold += (int)trait.ModifierAmount; + + bool unlockAchievement = true; + foreach (SkillObj skill in SkillArray) + { + if (skill.CurrentLevel < 1) + { + unlockAchievement = false; + break; + } + } + + if (unlockAchievement == true) + GameUtil.UnlockAchievement("FEAR_OF_DECISIONS"); + + if (Game.PlayerStats.CurrentLevel >= 50) + GameUtil.UnlockAchievement("FEAR_OF_WEALTH"); + } + + public static void ResetAllTraits() + { + foreach (SkillObj skill in m_skillArray) + { + skill.CurrentLevel = 0; + skill.Visible = false; + } + GetSkill(StartingTrait).Visible = true; // Set the starting trait to visible. + Game.PlayerStats.CurrentLevel = 0; + } + + public static void UpdateAllTraitSprites() + { + foreach (SkillObj trait in m_skillArray) + { + UpdateTraitSprite(trait); + } + } + + public static void UpdateTraitSprite(SkillObj trait) + { + //if (trait.Visible == true) + { + string traitName = trait.IconName; + if (trait.CurrentLevel > 0 && trait.CurrentLevel < trait.MaxLevel) + traitName = traitName.Replace("Locked", ""); + else if (trait.CurrentLevel > 0 && trait.CurrentLevel >= trait.MaxLevel) + traitName = traitName.Replace("Locked", "Max"); + + trait.ChangeSprite(traitName); + } + } + + public static List GetAllConnectingTraits(SkillObj trait) + { + int cols = GetTypeArrayColumns(); + int rows = GetTypeArrayRows(); + + Vector2 traitIndex = GetTraitTypeIndex(trait); + SkillObj[] traitArray = new SkillObj[4]; // 0 = right, 1 = left, 2 = top, 3 = bottom. + + if (traitIndex.X + 1 < cols) // Right Trait + traitArray[0] = GetSkill((int)traitIndex.X + 1, (int)traitIndex.Y); + if (traitIndex.X - 1 >= 0) // Left Trait + traitArray[1] = GetSkill((int)traitIndex.X - 1, (int)traitIndex.Y); + if (traitIndex.Y - 1 >= 0) // Top Trait + traitArray[2] = GetSkill((int)traitIndex.X, (int)traitIndex.Y - 1); + if (traitIndex.Y + 1 < rows) // Bottom Trait + traitArray[3] = GetSkill((int)traitIndex.X, (int)traitIndex.Y + 1); + + List traitList = new List(); + foreach (SkillObj traitObj in traitArray) + { + if (traitObj != null) // && traitObj.traitType != TraitType.Filler) + traitList.Add(traitObj); + } + + return traitList; + } + + public static SkillObj GetSkill(SkillType skillType) + { + foreach (SkillObj traitToReturn in m_skillArray) + { + if (traitToReturn.TraitType == skillType) + return traitToReturn; + } + return m_blankTrait; + } + + public static SkillObj GetSkill(int indexX, int indexY) + { + return GetSkill(m_skillTypeArray[indexY, indexX]); + } + + // Returns the array index of a trait in the trait type array. + public static Vector2 GetTraitTypeIndex(SkillObj trait) + { + Vector2 traitIndex = new Vector2(-1, -1); + SkillType traitType = trait.TraitType; + for (int i = 0; i < m_skillTypeArray.GetLength(1); i++) + { + for (int k = 0; k < m_skillTypeArray.GetLength(0); k++) + { + if (m_skillTypeArray[k, i] == traitType) + traitIndex = new Vector2(i, k); + } + } + + return traitIndex; + } + + // Returns the position of a trait in the trait position array. + public static Vector2 GetSkillPosition(SkillObj skill) + { + Vector2 skillTypeIndex = GetTraitTypeIndex(skill); + return m_skillPositionArray[(int)skillTypeIndex.Y, (int)skillTypeIndex.X]; + } + + public static int GetTypeArrayRows() + { + return m_skillTypeArray.GetLength(0); + } + + public static int GetTypeArrayColumns() + { + return m_skillTypeArray.GetLength(1); + } + + + public static SkillObj[] GetSkillArray() + { + return m_skillArray.ToArray(); + } + + public static List SkillArray + { + get { return m_skillArray; } + } + + public static int GetManorPiece(SkillObj trait) + { + Vector2 traitPosition = GetTraitTypeIndex(trait); + return m_manorPieceArray[(int)traitPosition.Y, (int)traitPosition.X]; + } + + public static SkillLinker GetSkillLink(int x, int y) + { + return m_skillLinkerArray[x, y]; + } + + public static void HideAllIcons() + { + foreach (SkillObj skill in m_skillArray) + skill.Opacity = 0; + + m_iconsVisible = false; + } + + public static void ShowAllIcons() + { + foreach (SkillObj skill in m_skillArray) + skill.Opacity = 1; + + m_iconsVisible = true; + } + + public static bool IconsVisible + { + get { return m_iconsVisible; } + } + + public static void RefreshTextObjs() + { + for (int i = 2; i < (int)SkillType.DIVIDER; i++) // The starting 2 traits are null and filler. + { + SkillObj skill = m_skillArray[i - 2]; + SkillBuilder.BuildSkill((SkillType)i, skill); + } + } + } + + public struct SkillLinker + { + public Vector2 TopLink; + public Vector2 BottomLink; + public Vector2 LeftLink; + public Vector2 RightLink; + } +} \ No newline at end of file diff --git a/RogueCastle/src/SleepUtil.cs b/RogueCastle/src/SleepUtil.cs new file mode 100644 index 0000000..d3a8fda --- /dev/null +++ b/RogueCastle/src/SleepUtil.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; + +namespace RogueCastle +{ + public static class SleepUtil + { + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags); + + [FlagsAttribute] + enum EXECUTION_STATE : uint + { + ES_AWAYMODE_REQUIRED = 0x00000040, + ES_CONTINUOUS = 0x80000000, + ES_DISPLAY_REQUIRED = 0x00000002, + ES_SYSTEM_REQUIRED = 0x00000001 + } + + public static void DisableScreensaver() + { + if (Environment.OSVersion.Platform != PlatformID.Win32NT) + { + return; + } + + if (SleepUtil.SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS + | EXECUTION_STATE.ES_DISPLAY_REQUIRED + | EXECUTION_STATE.ES_SYSTEM_REQUIRED + | EXECUTION_STATE.ES_AWAYMODE_REQUIRED) == 0) //Away mode for Windows >= Vista + SleepUtil.SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS + | EXECUTION_STATE.ES_DISPLAY_REQUIRED + | EXECUTION_STATE.ES_SYSTEM_REQUIRED); + } + + public static void EnableScreensaver() + { + if (Environment.OSVersion.Platform != PlatformID.Win32NT) + { + return; + } + + SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS); + } + } + +} diff --git a/RogueCastle/src/Types/BonusRoomTypes.cs b/RogueCastle/src/Types/BonusRoomTypes.cs new file mode 100644 index 0000000..d0934d2 --- /dev/null +++ b/RogueCastle/src/Types/BonusRoomTypes.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + public class BonusRoomTypes + { + public const byte None = 0; + public const byte PickChest = 1; + public const byte SpecialItem = 2; + public const byte RandomTeleport = 3; + public const byte SpellSwap = 4; + public const byte VitaChamber = 5; + public const byte Diary = 6; + public const byte Portrait = 7; + public const byte CarnivalShoot1 = 8; + public const byte CarnivalShoot2 = 9; + public const byte Arena = 10; + public const byte Jukebox = 11; + } +} diff --git a/RogueCastle/src/Types/BossRoomTypes.cs b/RogueCastle/src/Types/BossRoomTypes.cs new file mode 100644 index 0000000..5a4535b --- /dev/null +++ b/RogueCastle/src/Types/BossRoomTypes.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + class BossRoomType + { + public const byte None = 0; + public const byte EyeballBossRoom = 1; + public const byte LastBossRoom = 2; + public const byte SkeletonBossRoom = 3; + public const byte KnightBossRoom = 4; + public const byte FairyBossRoom = 5; + public const byte FireballBossRoom = 6; + public const byte BlobBossRoom = 7; + } +} diff --git a/RogueCastle/src/Types/ChestConditionType.cs b/RogueCastle/src/Types/ChestConditionType.cs new file mode 100644 index 0000000..fd7b9a0 --- /dev/null +++ b/RogueCastle/src/Types/ChestConditionType.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + public class ChestConditionType + { + public const int None = 0; + public const int KillAllEnemies = 1; + public const int HealthBelow15 = 2; + public const int DontLook = 3; + public const int NoJumping = 4; + public const int NoSound = 5; + public const int NoFloor = 6; + public const int NoAttackingEnemies = 7; + public const int ReachIn5Seconds = 8; + public const int TakeNoDamage = 9; + public const int InvisibleChest = 10; + } +} \ No newline at end of file diff --git a/RogueCastle/src/Types/ChestType.cs b/RogueCastle/src/Types/ChestType.cs new file mode 100644 index 0000000..b04accb --- /dev/null +++ b/RogueCastle/src/Types/ChestType.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + public class ChestType + { + public const byte None = 0; + public const byte Brown = 1; + public const byte Silver = 2; + public const byte Gold = 3; + public const byte Fairy = 4; + public const byte Boss = 5; + } +} diff --git a/RogueCastle/src/Types/ClassType.cs b/RogueCastle/src/Types/ClassType.cs new file mode 100644 index 0000000..5c65980 --- /dev/null +++ b/RogueCastle/src/Types/ClassType.cs @@ -0,0 +1,281 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; + +namespace RogueCastle +{ + class ClassType + { + // These four classes start unlocked. + public const byte Knight = 0; + public const byte Wizard = 1; + public const byte Barbarian = 2; + public const byte Assassin = 3; + + // These four classes need to be unlocked via skill tree. + public const byte Ninja = 4; + public const byte Banker = 5; + public const byte SpellSword = 6; + public const byte Lich = 7; + + public const byte Knight2 = 8; + public const byte Wizard2 = 9; + public const byte Barbarian2 = 10; + public const byte Assassin2 = 11; + + public const byte Ninja2 = 12; + public const byte Banker2 = 13; + public const byte SpellSword2 = 14; + public const byte Lich2 = 15; + + public const byte TotalUniques = 8; + public const byte Total = 16; + + public const byte Dragon = 16; + public const byte Traitor = 17; + + public static string ToStringID(byte classType, bool isFemale) + { + switch (classType) + { + case (Knight): + return !isFemale ? "LOC_ID_CLASS_NAME_1_MALE" : "LOC_ID_CLASS_NAME_1_FEMALE"; // "Knight" + case (Knight2): + return !isFemale ? "LOC_ID_CLASS_NAME_2_MALE" : "LOC_ID_CLASS_NAME_2_FEMALE"; // "Paladin" + case (Assassin): + return !isFemale ? "LOC_ID_CLASS_NAME_3_MALE" : "LOC_ID_CLASS_NAME_3_FEMALE"; // "Knave" + case (Assassin2): + return !isFemale ? "LOC_ID_CLASS_NAME_4_MALE" : "LOC_ID_CLASS_NAME_4_FEMALE"; // "Assassin"; + case (Banker): + return !isFemale ? "LOC_ID_CLASS_NAME_5_MALE" : "LOC_ID_CLASS_NAME_5_FEMALE"; // "Miner" + case (Banker2): + return !isFemale ? "LOC_ID_CLASS_NAME_6_MALE" : "LOC_ID_CLASS_NAME_6_FEMALE"; // "Spelunker", "Spelunkette" + case (Wizard): + return !isFemale ? "LOC_ID_CLASS_NAME_7_MALE" : "LOC_ID_CLASS_NAME_7_FEMALE"; // "Mage" + case (Wizard2): + return !isFemale ? "LOC_ID_CLASS_NAME_8_MALE" : "LOC_ID_CLASS_NAME_8_FEMALE"; // "Archmage" + case (Barbarian): + return !isFemale ? "LOC_ID_CLASS_NAME_9_MALE" : "LOC_ID_CLASS_NAME_9_FEMALE"; // "Barbarian" + case (Barbarian2): + return !isFemale ? "LOC_ID_CLASS_NAME_10_MALE" : "LOC_ID_CLASS_NAME_10_FEMALE"; // "Barbarian King", "Barbarian Queen" + case (Ninja): + return "LOC_ID_CLASS_NAME_11"; // "Shinobi" + case (Ninja2): + return "LOC_ID_CLASS_NAME_12"; // "Hokage" + case (SpellSword): + return !isFemale ? "LOC_ID_CLASS_NAME_13_MALE" : "LOC_ID_CLASS_NAME_13_FEMALE"; // "Spellthief" + case (SpellSword2): + return !isFemale ? "LOC_ID_CLASS_NAME_14_MALE" : "LOC_ID_CLASS_NAME_14_FEMALE"; // "Spellsword" + case (Lich): + return "LOC_ID_CLASS_NAME_15"; // "Lich" + case (Lich2): + return !isFemale ? "LOC_ID_CLASS_NAME_16_MALE" : "LOC_ID_CLASS_NAME_16_FEMALE"; // "Lich King", "Lich Queen" + case (Dragon): + return !isFemale ? "LOC_ID_CLASS_NAME_17_MALE" : "LOC_ID_CLASS_NAME_17_FEMALE"; // "Dragon" + case (Traitor): + return !isFemale ? "LOC_ID_CLASS_NAME_18_MALE" : "LOC_ID_CLASS_NAME_18_FEMALE"; // "Traitor" + } + + return ""; + } + + public static string DescriptionID(byte classType) + { + switch (classType) + { + case (Knight): + return "LOC_ID_CLASS_DESC_1"; //"Your standard hero. Pretty good at everything.";//"Your average knight. No outstanding abilities or weaknesses."; + case (Knight2): + return "LOC_ID_CLASS_DESC_2"; //"Your standard hero. Pretty good at everything.\nSPECIAL: Guardian's Shield.";//"Your standard hero. Pretty good at everything. [Input:" + InputMapType.PLAYER_BLOCK + "] to block all incoming damage."; + case (Assassin): + return "LOC_ID_CLASS_DESC_3"; //"A risky hero. Low stats but can land devastating critical strikes.";//"75% HP, 25% Crit Chance and Crit Damage";//"35% Health and Manaa\n250% Strength and Intelligence";//"He is an assassin"; + case (Assassin2): + return "LOC_ID_CLASS_DESC_4"; //"A risky hero. Low stats but can land devastating critical strikes.\nSPECIAL: Mist Form."; //"A risky hero. He has low stats but can land devestating critical strikes. [Input:" + InputMapType.PLAYER_BLOCK + "] turns you into mist."; + case (Banker): + return "LOC_ID_CLASS_DESC_5"; //"A hero for hoarders. Very weak, but has a huge bonus to gold.";//"Super rich banker"; + case (Banker2): + return "LOC_ID_CLASS_DESC_6"; //"A hero for hoarders. Very weak, but has a huge bonus to gold.\nSPECIAL: Ordinary Headlamp.";//"Super rich banker";//"A hero for hoarders. Very weak, but has a huge bonus to gold. [Input:" + InputMapType.PLAYER_BLOCK + "] to toggle your headlamp.";//"Super rich banker"; + case (Wizard): + return "LOC_ID_CLASS_DESC_7"; //"A powerful spellcaster. Every kill gives you mana."; //"Everyone loves Magical Trevor"; + case (Wizard2): + return "LOC_ID_CLASS_DESC_8"; //"A powerful spellcaster. Every kill gives you mana.\nSPECIAL: Spell Cycle.";//"Very weak, but very intelligent, and every kill gives you mana. [Input:" + InputMapType.PLAYER_BLOCK + "] cycles spells."; + case (Barbarian): + return "LOC_ID_CLASS_DESC_9"; //"A walking tank. This hero can take a beating.";//"Conan the babarian"; + case (Barbarian2): + return "LOC_ID_CLASS_DESC_10"; //"A walking tank. This hero can take a beating.\nSPECIAL: Barbarian Shout."; + case (Ninja): + return "LOC_ID_CLASS_DESC_11"; //"A fast hero. Deal massive damage, but you cannot crit.";//I am a rogue"; + case (Ninja2): + return "LOC_ID_CLASS_DESC_12"; //"A fast hero. Deal massive damage, but you cannot crit.\nSPECIAL: Replacement Technique."; + case (SpellSword): + return "LOC_ID_CLASS_DESC_13"; //"A hero for experts. Hit enemies to restore mana."; + case (SpellSword2): + return "LOC_ID_CLASS_DESC_14"; //"A hero for experts. Hit enemies to restore mana.\nSPECIAL: Empowered Spell."; + case (Lich): + return "LOC_ID_CLASS_DESC_15"; //"Feed off the dead. Gain permanent life for every kill up to a cap. Extremely intelligent."; + case (Lich2): + return "LOC_ID_CLASS_DESC_16"; //"Feed off the dead. Gain permanent life for every kill up to a cap. Extremely intelligent.\nSPECIAL: HP Conversion."; + case (Dragon): + return "LOC_ID_CLASS_DESC_17"; //"You are a man-dragon"; + case (Traitor): + return "LOC_ID_CLASS_DESC_18"; //"Fountain text here"; + } + return ""; + } + + // Can't return Loc IDs because of all the inline values, just return string and assume calling function/screen will call this on language change refresh + public static string ProfileCardDescription(byte classType) + { + switch (classType) + { + case (Knight): + return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_1"); + case (Knight2): + return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_2"); + case (Assassin): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_3_NEW"), (PlayerEV.ASSASSIN_CRITCHANCE_MOD * 100), (PlayerEV.ASSASSIN_CRITDAMAGE_MOD * 100)); + //return "+" + (PlayerEV.ASSASSIN_CRITCHANCE_MOD * 100) + LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_3") + ", +" + (PlayerEV.ASSASSIN_CRITDAMAGE_MOD * 100) + LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_3b"); + case (Assassin2): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_4_NEW"), (PlayerEV.ASSASSIN_CRITCHANCE_MOD * 100), (PlayerEV.ASSASSIN_CRITDAMAGE_MOD * 100)); + //return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_4") + "\n+" + (PlayerEV.ASSASSIN_CRITCHANCE_MOD * 100) + LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_4b") + ", +" + (PlayerEV.ASSASSIN_CRITDAMAGE_MOD * 100) + LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_4c"); + case (Banker): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_5_NEW"), (PlayerEV.BANKER_GOLDGAIN_MOD * 100)); + //return "+" + (PlayerEV.BANKER_GOLDGAIN_MOD * 100) + LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_5"); + case (Banker2): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_6_NEW"), (PlayerEV.BANKER_GOLDGAIN_MOD * 100)); + //return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_6") + "\n+" + (PlayerEV.BANKER_GOLDGAIN_MOD * 100) + LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_6b"); + case (Wizard): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_7_NEW"), GameEV.MAGE_MANA_GAIN); + //return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_7") + " " + GameEV.MAGE_MANA_GAIN + " " + LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_7b"); + case (Wizard2): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_8_NEW"), GameEV.MAGE_MANA_GAIN); + //return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_8") + " " + GameEV.MAGE_MANA_GAIN + " " + LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_8b"); + case (Barbarian): + return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_9"); + case (Barbarian2): + return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_10"); + case (Ninja): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_11_NEW"), (PlayerEV.NINJA_MOVESPEED_MOD * 100)); + //return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_11") + "\n +" + (PlayerEV.NINJA_MOVESPEED_MOD * 100) + LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_11b"); + case (Ninja2): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_12_NEW"), (PlayerEV.NINJA_MOVESPEED_MOD * 100)); + //return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_12") + "\n +" + (PlayerEV.NINJA_MOVESPEED_MOD * 100) + LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_12b"); + case (SpellSword): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_13_NEW"), (GameEV.SPELLSWORD_ATTACK_MANA_CONVERSION * 100)); + //return (GameEV.SPELLSWORD_ATTACK_MANA_CONVERSION * 100) + LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_13"); + case (SpellSword2): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_14_NEW"), (GameEV.SPELLSWORD_ATTACK_MANA_CONVERSION * 100)); + //return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_14") + "\n" + (GameEV.SPELLSWORD_ATTACK_MANA_CONVERSION * 100) + LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_14b"); + case (Lich): + return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_15"); + case (Lich2): + return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_16"); + case (Dragon): + return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_17"); + case (Traitor): + return LocaleBuilder.getResourceString("LOC_ID_PROFILE_DESC_18"); + } + return ""; + } + + public static byte GetRandomClass() + { + List randomClassList = new List(); + + // Adding the classes that start unlocked. + randomClassList.Add(ClassType.Knight); + randomClassList.Add(ClassType.Wizard); + randomClassList.Add(ClassType.Barbarian); + randomClassList.Add(ClassType.Assassin); + + // Adding the classes that have been unlocked via skill tree. + if (SkillSystem.GetSkill(SkillType.Ninja_Unlock).ModifierAmount > 0) + randomClassList.Add(ClassType.Ninja); + if (SkillSystem.GetSkill(SkillType.Banker_Unlock).ModifierAmount > 0) + randomClassList.Add(ClassType.Banker); + if (SkillSystem.GetSkill(SkillType.Spellsword_Unlock).ModifierAmount > 0) + randomClassList.Add(ClassType.SpellSword); + if (SkillSystem.GetSkill(SkillType.Lich_Unlock).ModifierAmount > 0) + randomClassList.Add(ClassType.Lich); + if (SkillSystem.GetSkill(SkillType.SuperSecret).ModifierAmount > 0) + randomClassList.Add(ClassType.Dragon); + + if (Game.PlayerStats.ChallengeLastBossBeaten == true || Game.GameConfig.UnlockTraitor == 2) + randomClassList.Add(ClassType.Traitor); + + // After the list is made, randomly select a class from that list. + byte randClass = randomClassList[CDGMath.RandomInt(0, randomClassList.Count - 1)]; + + // Check to see if the upgrade for the class has been unlocked. If so, return the upgraded version of the class. + if (Upgraded(randClass) == true) + randClass += 8; + + return randClass; + } + + public static bool Upgraded(byte classType) + { + switch (classType) + { + case (ClassType.Knight): + return SkillSystem.GetSkill(SkillType.Knight_Up).ModifierAmount > 0; + case (ClassType.Wizard): + return SkillSystem.GetSkill(SkillType.Mage_Up).ModifierAmount > 0; + case (ClassType.Barbarian): + return SkillSystem.GetSkill(SkillType.Barbarian_Up).ModifierAmount > 0; + case (ClassType.Ninja): + return SkillSystem.GetSkill(SkillType.Ninja_Up).ModifierAmount > 0; + case (ClassType.Assassin): + return SkillSystem.GetSkill(SkillType.Assassin_Up).ModifierAmount > 0; + case (ClassType.Banker): + return SkillSystem.GetSkill(SkillType.Banker_Up).ModifierAmount > 0; + case (ClassType.SpellSword): + return SkillSystem.GetSkill(SkillType.SpellSword_Up).ModifierAmount > 0; + case (ClassType.Lich): + return SkillSystem.GetSkill(SkillType.Lich_Up).ModifierAmount > 0; + } + + return false; + } + + public static byte[] GetSpellList(byte classType) + { + switch (classType) + { + case (ClassType.Knight): + case (ClassType.Knight2): + return new byte[] { SpellType.Axe, SpellType.Dagger, SpellType.Boomerang, SpellType.DualBlades, SpellType.Close, SpellType.Bounce, }; + case (ClassType.Barbarian): + case (ClassType.Barbarian2): + return new byte[] { SpellType.Axe, SpellType.Dagger, SpellType.Boomerang, SpellType.DualBlades, SpellType.Close, }; + case (ClassType.Assassin): + case (ClassType.Assassin2): + return new byte[] { SpellType.Axe, SpellType.Dagger, SpellType.Translocator, SpellType.Boomerang, SpellType.DualBlades, SpellType.Bounce, }; + case (ClassType.Banker): + case (ClassType.Banker2): + return new byte[] { SpellType.Axe, SpellType.Dagger, SpellType.Boomerang, SpellType.DualBlades, SpellType.DamageShield, SpellType.Bounce, }; + case (ClassType.Lich): + case (ClassType.Lich2): + return new byte[] { SpellType.Nuke, SpellType.DamageShield, SpellType.Bounce, }; + case (ClassType.SpellSword): + case (ClassType.SpellSword2): + return new byte[] { SpellType.Axe, SpellType.Dagger, SpellType.Boomerang, SpellType.DualBlades, SpellType.Close, SpellType.DamageShield, }; + case (ClassType.Wizard): + case (ClassType.Wizard2): + return new byte[] { SpellType.Axe, SpellType.Dagger, SpellType.TimeStop, SpellType.Boomerang, SpellType.DualBlades, SpellType.Close, SpellType.DamageShield, SpellType.Bounce, }; + case (ClassType.Ninja): + case (ClassType.Ninja2): + return new byte[] { SpellType.Axe, SpellType.Dagger, SpellType.Translocator, SpellType.Boomerang, SpellType.DualBlades, SpellType.Close, SpellType.Bounce, }; + case (ClassType.Dragon): + return new byte[] { SpellType.DragonFire, }; + case (ClassType.Traitor): + return new byte[] { SpellType.RapidDagger }; + } + + return null; + } + } + +} diff --git a/RogueCastle/src/Types/EnemyType.cs b/RogueCastle/src/Types/EnemyType.cs new file mode 100644 index 0000000..2a614d3 --- /dev/null +++ b/RogueCastle/src/Types/EnemyType.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + class EnemyType + { + public const byte None = 0; + public const byte BallAndChain = 1; + public const byte Blob = 2; + public const byte BouncySpike = 3; + public const byte Eagle = 4; + public const byte EarthWizard = 5; + public const byte Eyeball = 6; + public const byte Fairy = 7; + public const byte Fireball = 8; + public const byte FireWizard = 9; + public const byte Horse = 10; + public const byte IceWizard = 11; + public const byte Knight = 12; + public const byte Ninja = 13; + public const byte ShieldKnight = 14; + public const byte Skeleton = 15; + public const byte SwordKnight = 16; + public const byte Turret = 17; + public const byte Wall = 18; + public const byte Wolf = 19; + public const byte Zombie = 20; + public const byte SpikeTrap = 21; + public const byte Plant = 22; + public const byte Energon = 23; + public const byte Spark = 24; + public const byte SkeletonArcher = 25; + public const byte Chicken = 26; + public const byte Platform = 27; + public const byte HomingTurret = 28; + public const byte LastBoss = 29; + public const byte Dummy = 30; + public const byte Starburst = 31; + public const byte Portrait = 32; + public const byte Mimic = 33; + + public const byte Total = 34; + } +} diff --git a/RogueCastle/src/Types/EquipmentType.cs b/RogueCastle/src/Types/EquipmentType.cs new file mode 100644 index 0000000..97fb778 --- /dev/null +++ b/RogueCastle/src/Types/EquipmentType.cs @@ -0,0 +1,487 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class EquipmentCategoryType + { + public const int Sword = 0; + public const int Helm = 1; + public const int Chest = 2; + public const int Limbs = 3; + public const int Cape = 4; + + public const int Total = 5; + + // English-only string needed by BlacksmithScreen for sprite name generation + public static string ToStringEN(int equipmentType) + { + switch (equipmentType) + { + case (Sword): + return "Sword"; + case (Cape): + return "Cape"; + case (Limbs): + return "Limbs"; + case (Helm): + return "Helm"; + case (Chest): + return "Chest"; + } + return "None"; + } + + public static string ToStringID(int equipmentType) + { + switch (equipmentType) + { + case (Sword): + return "LOC_ID_EQUIPMENT_CAT_1"; + case (Cape): + return "LOC_ID_EQUIPMENT_CAT_2"; + case (Limbs): + return "LOC_ID_EQUIPMENT_CAT_3"; + case (Helm): + return "LOC_ID_EQUIPMENT_CAT_4"; + case (Chest): + return "LOC_ID_EQUIPMENT_CAT_5"; + } + return "LOC_ID_EQUIPMENT_CAT_6"; + } + + public static string ToStringID2(int equipmentType) // Sigh, my horrid architecture caused this. + { + switch (equipmentType) + { + case (Sword): + return "LOC_ID_EQUIPMENT_CAT2_1"; + case (Cape): + return "LOC_ID_EQUIPMENT_CAT2_2"; + case (Limbs): + return "LOC_ID_EQUIPMENT_CAT2_3"; + case (Helm): + return "LOC_ID_EQUIPMENT_CAT2_4"; + case (Chest): + return "LOC_ID_EQUIPMENT_CAT2_5"; + } + return "LOC_ID_EQUIPMENT_CAT2_6"; + } + } + + public class EquipmentState + { + public const int NotFound = 0; + public const int FoundButNotSeen = 1; + public const int FoundAndSeen = 2; + public const int Purchased = 3; + //public const int PurchasedAndEquipped = 4; + } + + public class EquipmentAbilityType + { + public const int DoubleJump = 0; + public const int Dash = 1; + public const int Vampirism = 2; + public const int Flight = 3; + public const int ManaGain = 4; + public const int DamageReturn = 5; + public const int GoldGain = 6; + public const int MovementSpeed = 7; + public const int RoomLevelUp = 8; + public const int RoomLevelDown = 9; + public const int ManaHPGain = 10; + + public const int Total = 11; + + // Special rune gained only through locking the castle. + public const int ArchitectFee = 20; + + // Special rune gained only through beating the castle at least once. + public const int NewGamePlusGoldBonus = 21; + + //public static string ToString(int type) + //{ + // return ""; + //} + + public static string ToStringID(int type) + { + switch (type) + { + case (DoubleJump): + return "LOC_ID_EQUIPMENT_ABILITY_1"; + case (Dash): + return "LOC_ID_EQUIPMENT_ABILITY_2"; + case (Vampirism): + return "LOC_ID_EQUIPMENT_ABILITY_3"; + case (Flight): + return "LOC_ID_EQUIPMENT_ABILITY_4"; + case (ManaGain): + return "LOC_ID_EQUIPMENT_ABILITY_5"; + case (ManaHPGain): + return "LOC_ID_EQUIPMENT_ABILITY_6"; + case (DamageReturn): + return "LOC_ID_EQUIPMENT_ABILITY_7"; + case (GoldGain): + return "LOC_ID_EQUIPMENT_ABILITY_8"; + case (MovementSpeed): + return "LOC_ID_EQUIPMENT_ABILITY_9"; + case (RoomLevelUp): + return "LOC_ID_EQUIPMENT_ABILITY_10"; + case (RoomLevelDown): + return "LOC_ID_EQUIPMENT_ABILITY_11"; + case (ArchitectFee): + return "LOC_ID_EQUIPMENT_ABILITY_12"; + case(NewGamePlusGoldBonus): + return "LOC_ID_EQUIPMENT_ABILITY_13"; + } + + return ""; + } + + public static string ToStringID2(int type) + { + switch (type) + { + case (DoubleJump): + return "LOC_ID_EQUIPMENT_ABILITY2_1"; + case (Dash): + return "LOC_ID_EQUIPMENT_ABILITY2_2"; + case (Vampirism): + return "LOC_ID_EQUIPMENT_ABILITY2_3"; + case (Flight): + return "LOC_ID_EQUIPMENT_ABILITY2_4"; + case (ManaGain): + return "LOC_ID_EQUIPMENT_ABILITY2_5"; + case (ManaHPGain): + return "LOC_ID_EQUIPMENT_ABILITY2_6"; + case (DamageReturn): + return "LOC_ID_EQUIPMENT_ABILITY2_7"; + case (GoldGain): + return "LOC_ID_EQUIPMENT_ABILITY2_8"; + case (MovementSpeed): + return "LOC_ID_EQUIPMENT_ABILITY2_9"; + case (RoomLevelUp): + return "LOC_ID_EQUIPMENT_ABILITY2_10"; + case (RoomLevelDown): + return "LOC_ID_EQUIPMENT_ABILITY2_11"; + case (ArchitectFee): + return "LOC_ID_EQUIPMENT_ABILITY2_12"; + case (NewGamePlusGoldBonus): + return "LOC_ID_EQUIPMENT_ABILITY2_13"; + } + + return ""; + } + + public static string DescriptionID(int type) + { + switch (type) + { + case (DoubleJump): + return "LOC_ID_EQUIPMENT_DESC_1"; + case (Dash): + return "LOC_ID_EQUIPMENT_DESC_2"; + case (Vampirism): + return "LOC_ID_EQUIPMENT_DESC_3"; + case (Flight): + return "LOC_ID_EQUIPMENT_DESC_4"; + case (ManaGain): + return "LOC_ID_EQUIPMENT_DESC_5"; + case (ManaHPGain): + return "LOC_ID_EQUIPMENT_DESC_6"; + case (DamageReturn): + return "LOC_ID_EQUIPMENT_DESC_7"; + case (GoldGain): + return "LOC_ID_EQUIPMENT_DESC_8"; + case (MovementSpeed): + return "LOC_ID_EQUIPMENT_DESC_9"; + case (RoomLevelUp): + return "LOC_ID_EQUIPMENT_DESC_10"; + case (RoomLevelDown): + return "LOC_ID_EQUIPMENT_DESC_11"; + } + + return ""; + } + + // Returns localized string. This is safe because calling function LoadBackCardStats() + // is refreshed on language change. + public static string ShortDescription(int type, float amount) + { + switch (type) + { + case (DoubleJump): + if (amount > 1) + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_1_NEW_A"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_1") + " " + amount + " " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_1b"); + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_1_NEW_B"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_1") + " " + amount + " " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_1c"); + case (Dash): + if (amount > 1) + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_2_NEW_A"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_2") + " " + amount + " " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_2b"); + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_2_NEW_B"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_2") + " " + amount + " " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_2c"); + case (Vampirism): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_3_NEW"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_3") + " " + amount + " " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_3b"); + case (Flight): + if (amount > 1) + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_4_NEW_A"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_4") + " " + amount + " " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_4b"); + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_4_NEW_B"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_4") + " " + amount + " " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_4c"); + case (ManaGain): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_5_NEW"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_5") + " " + amount + " " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_5b"); + case (ManaHPGain): + return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_6"); + case (DamageReturn): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_7_NEW"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_7") + " " + amount + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_7b"); + case (GoldGain): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_8_NEW"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_8") + " " + amount + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_8b"); + case (MovementSpeed): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_9_NEW"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_9") + " " + amount + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_9b"); + case (ArchitectFee): + return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_10"); + case (NewGamePlusGoldBonus): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_11_NEW"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_11") + " " + amount + "%"; + case (RoomLevelUp): + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_12_NEW"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_12") + " " + (int)((amount / LevelEV.ROOM_LEVEL_MOD) * LevelEV.ENEMY_LEVEL_FAKE_MULTIPLIER) + " " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_12b"); + case (RoomLevelDown): + if (amount > 1) + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_13_NEW_A"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_13") + " " + amount + " " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_13b"); + return string.Format(LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_13_NEW_B"), amount); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_13") + " " + amount + " " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_SHORT_13c"); + } + + return ""; + } + + // Returns localized string. This is safe because calling function UpdateEquipmentDataText() + // is refreshed on language change. + public static string Instructions(int type) + { + switch (type) + { + case (DoubleJump): + return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_1_NEW"); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_1") + " [Input:" + InputMapType.PLAYER_JUMP1 + "] " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_1b"); + //return "[Input:" + InputMapType.PLAYER_JUMP1 + "] " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_1b"); + case (Dash): + return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_2_NEW"); + //return "[Input:" + InputMapType.PLAYER_DASHLEFT + "] " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_2") + " [Input:" + InputMapType.PLAYER_DASHRIGHT + "] " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_2b"); + //return "[Input:" + InputMapType.PLAYER_DASHLEFT + "] or [Input:" + InputMapType.PLAYER_DASHRIGHT + "] to blah blah blah"; + case (Vampirism): + return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_3"); + case (Flight): + return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_4_NEW"); + //return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_4") + " [Input:" + InputMapType.PLAYER_JUMP1 + "] " + LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_4b"); + case (ManaGain): + return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_5"); + case (ManaHPGain): + return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_6"); + case (DamageReturn): + return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_7"); + case (GoldGain): + return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_8"); + case (MovementSpeed): + return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_9"); + case (RoomLevelUp): + return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_10"); + case (RoomLevelDown): + return LocaleBuilder.getResourceString("LOC_ID_EQUIPMENT_INST_11"); + } + + return ""; + } + + public static string Icon(int type) + { + switch (type) + { + case (DoubleJump): + return "EnchantressUI_DoubleJumpIcon_Sprite"; + case (Dash): + return "EnchantressUI_DashIcon_Sprite"; + case (Vampirism): + return "EnchantressUI_VampirismIcon_Sprite"; + case (Flight): + return "EnchantressUI_FlightIcon_Sprite"; + case (ManaGain): + return "EnchantressUI_ManaGainIcon_Sprite"; + case (ManaHPGain): + return "EnchantressUI_BalanceIcon_Sprite"; + case (DamageReturn): + return "EnchantressUI_DamageReturnIcon_Sprite"; + case (GoldGain): + return "Icon_Gold_Gain_Up_Sprite"; + case (MovementSpeed): + return "EnchantressUI_SpeedUpIcon_Sprite"; + case (RoomLevelUp): + return "EnchantressUI_CurseIcon_Sprite"; + case (RoomLevelDown): + return "EnchantressUI_BlessingIcon_Sprite"; + } + + return ""; + } + + } + + public class EquipmentBaseType + { + public const int Bronze = 0; + public const int Silver = 1; + public const int Gold = 2; + public const int Imperial = 3; + public const int Royal = 4; + + public const int Knight = 5; + public const int Earthen = 6; + public const int Sky = 7; + public const int Dragon = 8; + public const int Eternal = 9; + + public const int Blood = 10; + public const int Amethyst = 11; + public const int Spike = 12; + public const int Holy = 13; + public const int Dark = 14; + + public const int Total = 15; + + public static string ToStringID(int equipmentBaseType) + { + switch (equipmentBaseType) + { + case (Bronze): + return "LOC_ID_EQUIPMENT_BASE_1"; + case (Silver): + return "LOC_ID_EQUIPMENT_BASE_2"; + case (Gold): + return "LOC_ID_EQUIPMENT_BASE_3"; + case (Imperial): + return "LOC_ID_EQUIPMENT_BASE_4"; + case (Royal): + return "LOC_ID_EQUIPMENT_BASE_5"; + case (Knight): + return "LOC_ID_EQUIPMENT_BASE_6"; + case (Earthen): + return "LOC_ID_EQUIPMENT_BASE_7"; + case (Sky): + return "LOC_ID_EQUIPMENT_BASE_8"; + case (Dragon): + return "LOC_ID_EQUIPMENT_BASE_9"; + case (Eternal): + return "LOC_ID_EQUIPMENT_BASE_10"; + case (Amethyst): + return "LOC_ID_EQUIPMENT_BASE_11"; + case (Blood): + return "LOC_ID_EQUIPMENT_BASE_12"; + case (Spike): + return "LOC_ID_EQUIPMENT_BASE_13"; + case (Holy): + return "LOC_ID_EQUIPMENT_BASE_14"; + case (Dark): + return "LOC_ID_EQUIPMENT_BASE_15"; + } + return ""; + } + } + + public class EquipmentData + { + public int BonusDamage; + public int BonusMagic; + public int Weight; + public int BonusMana; + public int BonusHealth; + public int BonusArmor; + public int Cost = 9999; + public Color FirstColour = Color.White; + public Color SecondColour = Color.White; + public Vector2[] SecondaryAttribute = null; + public byte ChestColourRequirement = 0; + public byte LevelRequirement = 0; + + public void Dispose() + { + if (SecondaryAttribute != null) + Array.Clear(SecondaryAttribute, 0, SecondaryAttribute.Length); + SecondaryAttribute = null; + } + } + + public class EquipmentSecondaryDataType + { + public const int None = 0; + public const int CritChance = 1; + public const int CritDamage = 2; + public const int GoldBonus = 3; + public const int DamageReturn = 4; + public const int XpBonus = 5; + // Anything above this line will be displayed as a percent. + public const int AirAttack = 6; + public const int Vampirism = 7; + public const int ManaDrain = 8; + public const int DoubleJump = 9; + public const int MoveSpeed = 10; + public const int AirDash = 11; + public const int Block = 12; + public const int Float = 13; + public const int AttackProjectiles = 14; + public const int Flight = 15; + + public const int Total = 16; + + public static string ToStringID(int equipmentSecondaryDataType) + { + switch (equipmentSecondaryDataType) + { + case (CritChance): + return "LOC_ID_EQUIPMENT_SEC_1"; + case (CritDamage): + return "LOC_ID_EQUIPMENT_SEC_2"; + case (Vampirism): + return "LOC_ID_EQUIPMENT_SEC_3"; + case (GoldBonus): + return "LOC_ID_EQUIPMENT_SEC_4"; + case (ManaDrain): + return "LOC_ID_EQUIPMENT_SEC_5"; + case (XpBonus): + return "LOC_ID_EQUIPMENT_SEC_6"; + case (AirAttack): + return "LOC_ID_EQUIPMENT_SEC_7"; + case (DoubleJump): + return "LOC_ID_EQUIPMENT_SEC_8"; + case (DamageReturn): + return "LOC_ID_EQUIPMENT_SEC_9"; + case (AirDash): + return "LOC_ID_EQUIPMENT_SEC_10"; + case (Block): + return "LOC_ID_EQUIPMENT_SEC_11"; + case (Float): + return "LOC_ID_EQUIPMENT_SEC_12"; + case (AttackProjectiles): + return "LOC_ID_EQUIPMENT_SEC_13"; + case (Flight): + return "LOC_ID_EQUIPMENT_SEC_14"; + case (MoveSpeed): + return "LOC_ID_EQUIPMENT_SEC_15"; + } + return "LOC_ID_EQUIPMENT_SEC_16"; + } + } +} diff --git a/RogueCastle/src/Types/FamilyTreeNode.cs b/RogueCastle/src/Types/FamilyTreeNode.cs new file mode 100644 index 0000000..c15de66 --- /dev/null +++ b/RogueCastle/src/Types/FamilyTreeNode.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public struct FamilyTreeNode + { + public string Name; + public byte Age; + public byte ChildAge; + public byte Class; + public byte HeadPiece; + public byte ChestPiece; + public byte ShoulderPiece; + public int NumEnemiesBeaten; + public bool BeatenABoss; + public bool IsFemale; + public Vector2 Traits; + private string m_romanNumeral; + public string RomanNumeral + { + get + { + if (m_romanNumeral == null) + m_romanNumeral = ""; + return m_romanNumeral; + } + set { m_romanNumeral = value; } + } + } +} diff --git a/RogueCastle/src/Types/GameTypes.cs b/RogueCastle/src/Types/GameTypes.cs new file mode 100644 index 0000000..55b4cca --- /dev/null +++ b/RogueCastle/src/Types/GameTypes.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + public class GameTypes + { + public enum EnemyDifficulty + { + BASIC, + ADVANCED, + EXPERT, + MINIBOSS + } + + public enum DoorType + { + NULL, + OPEN, + LOCKED, + BLOCKED + } + + public enum LevelType + { + NONE, + CASTLE, + GARDEN, + DUNGEON, + TOWER + } + + public enum WeaponType + { + NONE, + DAGGER, + SWORD, + SPEAR, + AXE, + } + + public enum ArmorType + { + NONE, + HEAD, + BODY, + RING, + FOOT, + HAND, + ALL + } + + public enum EquipmentType + { + NONE, + WEAPON, + ARMOR + } + + public enum StatType + { + STRENGTH = 0, + HEALTH = 1, + ENDURANCE = 2, + EQUIPLOAD = 3, + } + + public enum SkillType + { + STRENGTH = 0, + HEALTH, + DEFENSE, + } + + // CollisionType represents the type of object you are colliding with. + public const int CollisionType_NULL = 0; + public const int CollisionType_WALL = 1; + public const int CollisionType_PLAYER= 2; + public const int CollisionType_ENEMY = 3; + public const int CollisionType_ENEMYWALL = 4; // An enemy that you cannot walk through while invincible. + public const int CollisionType_WALL_FOR_PLAYER = 5; + public const int CollisionType_WALL_FOR_ENEMY = 6; + public const int CollisionType_PLAYER_TRIGGER = 7; + public const int CollisionType_ENEMY_TRIGGER = 8; + public const int CollisionType_GLOBAL_TRIGGER = 9; + public const int CollisionType_GLOBAL_DAMAGE_WALL = 10; + + public const int LogicSetType_NULL = 0; + public const int LogicSetType_NONATTACK = 1; + public const int LogicSetType_ATTACK = 2; + public const int LogicSetType_CD = 3; + } +} diff --git a/RogueCastle/src/Types/GetItemType.cs b/RogueCastle/src/Types/GetItemType.cs new file mode 100644 index 0000000..c4f3df8 --- /dev/null +++ b/RogueCastle/src/Types/GetItemType.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + class GetItemType + { + public const byte None = 0; + public const byte Blueprint = 1; + public const byte Rune = 2; + public const byte StatDrop = 3; + public const byte Spell = 4; + public const byte SpecialItem = 5; + public const byte TripStatDrop = 6; + public const byte FountainPiece = 7; + } +} diff --git a/RogueCastle/src/Types/InputMapType.cs b/RogueCastle/src/Types/InputMapType.cs new file mode 100644 index 0000000..73562d0 --- /dev/null +++ b/RogueCastle/src/Types/InputMapType.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + class InputMapType + { + // Menu Input + public const byte MENU_CONFIRM1 = 0; + public const byte MENU_CONFIRM2 = 1; + public const byte MENU_CANCEL1 = 2; + public const byte MENU_CANCEL2 = 3; + public const byte MENU_OPTIONS = 4; + public const byte MENU_ROGUEMODE = 5; + public const byte MENU_CREDITS = 6; + public const byte MENU_PROFILECARD = 7; + public const byte MENU_PAUSE = 8; + public const byte MENU_MAP = 9; + + // Player Input + public const byte PLAYER_JUMP1 = 10; + public const byte PLAYER_JUMP2 = 11; + public const byte PLAYER_ATTACK = 12; + public const byte PLAYER_BLOCK = 13; + public const byte PLAYER_DASHLEFT = 14; + public const byte PLAYER_DASHRIGHT = 15; + public const byte PLAYER_UP1 = 16; + public const byte PLAYER_UP2 = 17; + public const byte PLAYER_DOWN1 = 18; + public const byte PLAYER_DOWN2 = 19; + public const byte PLAYER_LEFT1 = 20; + public const byte PLAYER_LEFT2 = 21; + public const byte PLAYER_RIGHT1 = 22; + public const byte PLAYER_RIGHT2 = 23; + public const byte PLAYER_SPELL1 = 24; + + public const byte MENU_PROFILESELECT = 25; + public const byte MENU_DELETEPROFILE = 26; + + public const byte MENU_CONFIRM3 = 27; + public const byte MENU_CANCEL3 = 28; + + public const byte Total = 29; + } +} diff --git a/RogueCastle/src/Types/ItemDropType.cs b/RogueCastle/src/Types/ItemDropType.cs new file mode 100644 index 0000000..0380c92 --- /dev/null +++ b/RogueCastle/src/Types/ItemDropType.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + public class ItemDropType + { + public const int None = 0; + public const int Coin = 1; + public const int Health = 2; + public const int Mana = 3; + public const int Stat_Strength = 4; + public const int Stat_Magic = 5; + public const int Stat_Defense = 6; + public const int Stat_MaxHealth = 7; + public const int Stat_MaxMana = 8; + public const int Stat_Weight = 9; + public const int MoneyBag = 10; + public const int Diamond = 11; + public const int Blueprint = 12; + public const int Redprint = 13; + public const int TripStatDrop = 14; + public const int BigDiamond = 20; + + public const int FountainPiece1 = 15; + public const int FountainPiece2 = 16; + public const int FountainPiece3 = 17; + public const int FountainPiece4 = 18; + public const int FountainPiece5 = 19; + + public const int CoinAmount = 10; + public const int MoneyBagAmount = 100; + public const int DiamondAmount = 1000; + public const int BigDiamondAmount = 10000; + } +} diff --git a/RogueCastle/src/Types/LanguageType.cs b/RogueCastle/src/Types/LanguageType.cs new file mode 100644 index 0000000..7bc28e2 --- /dev/null +++ b/RogueCastle/src/Types/LanguageType.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + public enum LanguageType + { + English, + French, + German, + Russian, + Portuguese_Brazil, + Spanish_Spain, + Polish, + Chinese_Simp, + MAX, + } +} diff --git a/RogueCastle/src/Types/LineageTypes.cs b/RogueCastle/src/Types/LineageTypes.cs new file mode 100644 index 0000000..067986d --- /dev/null +++ b/RogueCastle/src/Types/LineageTypes.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public struct PlayerLineageData + { + public string Name; + public byte Spell; + public byte Class; + public byte Age; + public byte ChildAge; + public bool IsFemale; + + private string m_romanNumeral; + public string RomanNumeral + { + get + { + if (m_romanNumeral == null) + m_romanNumeral = ""; + return m_romanNumeral; + } + set { m_romanNumeral = value; } + } + + public byte HeadPiece; + public byte ChestPiece; + public byte ShoulderPiece; + public Vector2 Traits; + } +} diff --git a/RogueCastle/src/Types/OrbType.cs b/RogueCastle/src/Types/OrbType.cs new file mode 100644 index 0000000..fcd0d86 --- /dev/null +++ b/RogueCastle/src/Types/OrbType.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + class OrbType + { + public const int RED = 0; + public const int BLUE = 1; + public const int GREEN = 2; + public const int YELLOW = 3; + } +} diff --git a/RogueCastle/src/Types/PlayerPart.cs b/RogueCastle/src/Types/PlayerPart.cs new file mode 100644 index 0000000..da4d1c6 --- /dev/null +++ b/RogueCastle/src/Types/PlayerPart.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class PlayerPart + { + public const int None = -1; + public const int Wings = 0; + public const int Cape = 1; + public const int Legs = 2; + public const int ShoulderB = 3; + public const int Chest = 4; + public const int Boobs = 5; + public const int Arms = 6; + public const int Hair = 7; + public const int Neck = 8; + public const int ShoulderA = 9; + public const int Sword1 = 10; + public const int Sword2 = 11; + public const int Head = 12; + public const int Bowtie = 13; + public const int Glasses = 14; + public const int Extra = 15; + public const int Light = 16; + + public const int NumHeadPieces = 5; + public const int NumChestPieces = 5; + public const int NumShoulderPieces = 5; + + public const int DragonHelm = 6; + public const int IntroHelm = 7; + + public static Vector3 GetPartIndices(int category) + { + switch (category) + { + case (EquipmentCategoryType.Cape): + return new Vector3(PlayerPart.Cape, PlayerPart.Neck, PlayerPart.None); + case (EquipmentCategoryType.Chest): + return new Vector3(PlayerPart.Chest, PlayerPart.ShoulderB, PlayerPart.ShoulderA); + case (EquipmentCategoryType.Helm): + return new Vector3(PlayerPart.Head, PlayerPart.Hair, PlayerPart.None); + case (EquipmentCategoryType.Limbs): + return new Vector3(PlayerPart.Arms, PlayerPart.Legs, PlayerPart.None); + case (EquipmentCategoryType.Sword): + return new Vector3(PlayerPart.Sword1, PlayerPart.Sword2, PlayerPart.None); + } + return new Vector3(-1, -1, -1); + } + } +} diff --git a/RogueCastle/src/Types/RoomType.cs b/RogueCastle/src/Types/RoomType.cs new file mode 100644 index 0000000..b265d34 --- /dev/null +++ b/RogueCastle/src/Types/RoomType.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + public class RoomType + { + public const int Normal = 0; + public const int Boss = 1; + public const int Secret = 2; + public const int Bonus = 3; + public const int Linker = 4; + public const int Starting = 5; + public const int BossEntrance = 6; + public const int Test = 7; + public const int CastleEntrance = 8; + public const int Tutorial = 9; + public const int Compass = 10; + } +} diff --git a/RogueCastle/src/Types/ScreenType.cs b/RogueCastle/src/Types/ScreenType.cs new file mode 100644 index 0000000..9f8de8a --- /dev/null +++ b/RogueCastle/src/Types/ScreenType.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + public class ScreenType + { + public const int Num_Screens = 32; + + public const int Null = 0; + public const int CDGSplash = 1; + public const int MiscSplash = 2; + public const int Title = 3; + public const int Options = 4; + public const int Level = 5; + public const int Skill = 6; + public const int GameOver = 7; + public const int LevelUp = 8; + public const int Lineage = 9; + public const int Blacksmith = 10; + public const int Enchantress = 11; + public const int GetItem = 12; + public const int Dialogue = 13; + public const int Map = 14; + public const int StartingRoom = 15; + public const int Pause = 16; + public const int ProfileCard = 17; + public const int Credits = 18; + public const int SkillUnlock = 19; + public const int DiaryEntry = 20; + public const int DeathDefy = 21; + public const int Text = 22; + public const int TutorialRoom = 23; + public const int Ending = 24; + public const int DiaryFlashback = 25; + public const int GameOverBoss = 26; + + public const int TitleWhite = 27; + public const int DemoStart = 28; + public const int DemoEnd = 29; + + public const int BlitWorks = 30; + + public const int ProfileSelect = 31; + public const int Loading = 32; + } +} diff --git a/RogueCastle/src/Types/SkillType.cs b/RogueCastle/src/Types/SkillType.cs new file mode 100644 index 0000000..634be22 --- /dev/null +++ b/RogueCastle/src/Types/SkillType.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + public enum SkillType + { + Null = 0, + Filler, + Health_Up, // Done + Invuln_Time_Up, // Done + Death_Dodge, // Done + + Attack_Up, // Done + Down_Strike_Up, // Done + Crit_Chance_Up, // Done + Crit_Damage_Up, // Done + + Magic_Damage_Up, // Done + Mana_Up, // Done + Mana_Cost_Down, // Done + + Smithy, // Done + Enchanter, // Done + Architect, //Done + + Equip_Up, // Done + Armor_Up, // Done + + Gold_Gain_Up, // Done + Prices_Down, + + Potion_Up, // Done + Randomize_Children, + + Lich_Unlock, + Banker_Unlock, + Spellsword_Unlock, + Ninja_Unlock, + + Knight_Up, + Mage_Up, + Assassin_Up, + Banker_Up, + Barbarian_Up, + Lich_Up, + Ninja_Up, + SpellSword_Up, + + SuperSecret, + + + DIVIDER, // NO LONGER USED // This separates the traits from the skills. + Attack_Speed_Up, // Done + Invuln_Attack_Up, // Done + Health_Up_Final, + Equip_Up_Final, + Damage_Up_Final, + Mana_Up_Final, + XP_Gain_Up, // Done + Gold_Flat_Bonus, // Done + Mana_Regen_Up, + Run, + Block, + Cartographer, + Env_Damage_Down, + Gold_Loss_Down, + Vampire_Up, + + Stout_Heart, // Done + Quick_of_Breath, // Done + Born_to_Run, // Done + Out_the_Gate, // Done HP portion only since MP isn't implemented yet. + Perfectionist, // Done + + Guru, + Iron_Lung, + Sword_Master, + Tank, + Vampire, + Second_Chance, + Peace_of_Mind, + Cartography_Ninja, + Strong_Man, + Suicidalist, + Crit_Barbarian, + Magician, + Keymaster, + One_Time_Only, + Cutting_Out_Early, + Quaffer, + + Spell_Sword, + Sorcerer, + + Well_Endowed, + Treasure_Hunter, + Mortar_Master, + Explosive_Expert, + Icicle, + ENDER, + } + + public class TraitState + { + public const byte Invisible = 0; + public const byte Purchasable = 1; + public const byte Purchased = 2; + public const byte MaxedOut = 3; + } + + class TraitStatType + { + public const int PlayerMaxHealth = 0; // A dummy variable used for property in TraitObj called StatType that is no longer used. + + public static float GetTraitStat(SkillType traitType) + { + switch (traitType) + { + case (SkillType.Health_Up_Final): + case (SkillType.Health_Up): + return Game.ScreenManager.Player.MaxHealth; + case (SkillType.Invuln_Time_Up): + return Game.ScreenManager.Player.InvincibilityTime; + case (SkillType.Death_Dodge): + return SkillSystem.GetSkill(SkillType.Death_Dodge).ModifierAmount * 100; + case (SkillType.Damage_Up_Final): + case (SkillType.Attack_Up): + return Game.ScreenManager.Player.Damage; + case (SkillType.Crit_Chance_Up): + return Game.ScreenManager.Player.TotalCritChance; + case (SkillType.Crit_Damage_Up): + return Game.ScreenManager.Player.TotalCriticalDamage * 100; + case (SkillType.Mana_Up_Final): + case (SkillType.Mana_Up): + return Game.ScreenManager.Player.MaxMana; + case (SkillType.Mana_Regen_Up): + return Game.ScreenManager.Player.ManaGain; + case (SkillType.Equip_Up_Final): + case (SkillType.Equip_Up): + return Game.ScreenManager.Player.MaxWeight; + case (SkillType.Armor_Up): + return Game.ScreenManager.Player.TotalArmor; + case (SkillType.Gold_Gain_Up): + return Game.ScreenManager.Player.TotalGoldBonus; + case (SkillType.XP_Gain_Up): + return Game.ScreenManager.Player.TotalXPBonus; + case (SkillType.Mana_Cost_Down): + return SkillSystem.GetSkill(SkillType.Mana_Cost_Down).ModifierAmount * 100; //Game.ScreenManager.Player.TotalXPBonus; + case (SkillType.Attack_Speed_Up): + return SkillSystem.GetSkill(SkillType.Attack_Speed_Up).ModifierAmount * 10; + case (SkillType.Magic_Damage_Up): + return Game.ScreenManager.Player.TotalMagicDamage; + case (SkillType.Potion_Up): + return (GameEV.ITEM_HEALTHDROP_AMOUNT + SkillSystem.GetSkill(SkillType.Potion_Up).ModifierAmount) * 100; + case (SkillType.Prices_Down): + return SkillSystem.GetSkill(SkillType.Prices_Down).ModifierAmount * 100; + case (SkillType.Down_Strike_Up): + return SkillSystem.GetSkill(SkillType.Down_Strike_Up).ModifierAmount * 100; + } + + return -1; + } + } +} diff --git a/RogueCastle/src/Types/SkillUnlockType.cs b/RogueCastle/src/Types/SkillUnlockType.cs new file mode 100644 index 0000000..f1eeb6c --- /dev/null +++ b/RogueCastle/src/Types/SkillUnlockType.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + class SkillUnlockType + { + public const byte None = 0; + public const byte Blacksmith = 1; + public const byte Enchantress = 2; + public const byte Architect = 3; + public const byte Ninja = 4; + public const byte Banker = 5; + public const byte SpellSword = 6; + public const byte Lich = 7; + + public const byte KnightUp = 8; + public const byte WizardUp = 9; + public const byte BarbarianUp = 10; + public const byte NinjaUp = 11; + public const byte AssassinUp = 12; + public const byte BankerUp = 13; + public const byte SpellSwordUp = 14; + public const byte LichUp = 15; + + public const byte Dragon = 16; + public const byte Traitor = 17; + + public static string DescriptionID(byte unlockType) + { + switch (unlockType) + { + case (Blacksmith): + return "LOC_ID_SKILL_UNLOCK_1"; + case (Enchantress): + return "LOC_ID_SKILL_UNLOCK_2"; + case (Architect): + return "LOC_ID_SKILL_UNLOCK_3"; + case (Ninja): + return "LOC_ID_SKILL_UNLOCK_4"; + case (Banker): + return "LOC_ID_SKILL_UNLOCK_5"; + case (SpellSword): + return "LOC_ID_SKILL_UNLOCK_6"; + case (Lich): + return "LOC_ID_SKILL_UNLOCK_7"; + case (KnightUp): + return "LOC_ID_SKILL_UNLOCK_8"; + case (WizardUp): + return "LOC_ID_SKILL_UNLOCK_9"; + case (BarbarianUp): + return "LOC_ID_SKILL_UNLOCK_10"; + case (NinjaUp): + return "LOC_ID_SKILL_UNLOCK_11"; + case (AssassinUp): + return "LOC_ID_SKILL_UNLOCK_12"; + case (BankerUp): + return "LOC_ID_SKILL_UNLOCK_13"; + case (SpellSwordUp): + return "LOC_ID_SKILL_UNLOCK_14"; + case (LichUp): + return "LOC_ID_SKILL_UNLOCK_15"; + case(Dragon): + return "LOC_ID_SKILL_UNLOCK_16"; + case (Traitor): + return "LOC_ID_SKILL_UNLOCK_17"; + } + + return ""; + } + } + +} diff --git a/RogueCastle/src/Types/SpecialItemType.cs b/RogueCastle/src/Types/SpecialItemType.cs new file mode 100644 index 0000000..6ffb880 --- /dev/null +++ b/RogueCastle/src/Types/SpecialItemType.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RogueCastle +{ + class SpecialItemType + { + public const byte None = 0; + public const byte FreeEntrance = 1; // Done + public const byte LoseCoins = 2; // Done + public const byte Revive = 3; // Done + public const byte SpikeImmunity = 4; // Done + public const byte GoldPerKill = 5; // Done + public const byte Compass = 6; // Done + + public const byte Total = 7; + + public const byte Glasses = 8; // Done. Don't include glasses on the list because it needs to be hard coded in. + + public const byte EyeballToken = 9; + public const byte SkullToken = 10; + public const byte FireballToken = 11; + public const byte BlobToken = 12; + public const byte LastBossToken = 13; + + public static string ToStringID(byte itemType) + { + switch (itemType) + { + case (Revive): + return "LOC_ID_SPECIAL_ITEM_TYPE_1"; + case (SpikeImmunity): + return "LOC_ID_SPECIAL_ITEM_TYPE_2"; + case (LoseCoins): + return "LOC_ID_SPECIAL_ITEM_TYPE_3"; + case (FreeEntrance): + return "LOC_ID_SPECIAL_ITEM_TYPE_4"; + case (Compass): + return "LOC_ID_SPECIAL_ITEM_TYPE_5"; + case (GoldPerKill): + return "LOC_ID_SPECIAL_ITEM_TYPE_6"; + case (Glasses): + return "LOC_ID_SPECIAL_ITEM_TYPE_7"; + case (EyeballToken): + return "LOC_ID_SPECIAL_ITEM_TYPE_8"; + case (SkullToken): + return "LOC_ID_SPECIAL_ITEM_TYPE_9"; + case (FireballToken): + return "LOC_ID_SPECIAL_ITEM_TYPE_10"; + case (BlobToken): + return "LOC_ID_SPECIAL_ITEM_TYPE_11"; + case (LastBossToken): + return "LOC_ID_SPECIAL_ITEM_TYPE_12"; + } + return ""; + } + + public static string SpriteName(byte itemType) + { + switch (itemType) + { + case (Revive): + return "BonusRoomRingIcon_Sprite"; + case (SpikeImmunity): + return "BonusRoomBootsIcon_Sprite"; + case (LoseCoins): + return "BonusRoomHedgehogIcon_Sprite"; + case(FreeEntrance): + return "BonusRoomObolIcon_Sprite"; + case (Compass): + return "BonusRoomCompassIcon_Sprite"; + case (GoldPerKill): + return "BonusRoomBlessingIcon_Sprite"; + case(Glasses): + return "BonusRoomGlassesIcon_Sprite"; + case (EyeballToken): + return "ChallengeIcon_Eyeball_Sprite"; + case (SkullToken): + return "ChallengeIcon_Skull_Sprite"; + case (FireballToken): + return "ChallengeIcon_Fireball_Sprite"; + case (BlobToken): + return "ChallengeIcon_Blob_Sprite"; + case (LastBossToken): + return "ChallengeIcon_LastBoss_Sprite"; + } + return ""; + } + } +} diff --git a/RogueCastle/src/Types/SpellType.cs b/RogueCastle/src/Types/SpellType.cs new file mode 100644 index 0000000..35c0ab4 --- /dev/null +++ b/RogueCastle/src/Types/SpellType.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + class SpellType + { + public const byte None = 0; + public const byte Dagger = 1; // DONE + public const byte Axe = 2; // DONE + public const byte TimeBomb = 3; // + public const byte TimeStop = 4; // DONE - Just needs art. + public const byte Nuke = 5; // DONE - Needs art. + public const byte Translocator = 6; // DONE - Just needs effect. + public const byte Displacer = 7; // DONE - But buggy. + public const byte Boomerang = 8; // DONE + public const byte DualBlades = 9; // DONE + public const byte Close = 10; // DONE + public const byte DamageShield = 11; // DONE + public const byte Bounce = 12; // DONE + public const byte DragonFire = 13; // Special spell for the dragon. + public const byte RapidDagger = 14; + public const byte DragonFireNeo = 15; + public const byte Total = 16; + + public const byte Laser = 100; // DONE - Needs art. // Disabled for now. + public const byte Shout = 20; // Special spell for the barbarian. + + public static string ToStringID(byte spellType) + { + switch (spellType) + { + case (Dagger): + return "LOC_ID_SPELL_TYPE_1"; + case (Axe): + return "LOC_ID_SPELL_TYPE_2"; + case (TimeBomb): + return "LOC_ID_SPELL_TYPE_3"; + case (TimeStop): + return "LOC_ID_SPELL_TYPE_4"; + case (Nuke): + return "LOC_ID_SPELL_TYPE_5"; + case (Translocator): + return "LOC_ID_SPELL_TYPE_6"; + case (Displacer): + return "LOC_ID_SPELL_TYPE_7"; + case (Boomerang): + return "LOC_ID_SPELL_TYPE_8"; + case (DualBlades): + return "LOC_ID_SPELL_TYPE_9"; + case (Close): + return "LOC_ID_SPELL_TYPE_10"; + case (DamageShield): + return "LOC_ID_SPELL_TYPE_11"; + case (Bounce): + return "LOC_ID_SPELL_TYPE_12"; + case (Laser): + return "LOC_ID_SPELL_TYPE_13"; + case (DragonFire): + case (DragonFireNeo): + return "LOC_ID_SPELL_TYPE_14"; + case (RapidDagger): + return "LOC_ID_SPELL_TYPE_15"; + } + return ""; + } + + public static string DescriptionID(byte spellType) + { + switch (spellType) + { + case (Dagger): + return "LOC_ID_SPELL_DESC_1"; + case (Axe): + return "LOC_ID_SPELL_DESC_2"; + case (TimeBomb): + return "LOC_ID_SPELL_DESC_3"; + case (TimeStop): + return "LOC_ID_SPELL_DESC_4"; + case (Nuke): + return "LOC_ID_SPELL_DESC_5"; + case (Translocator): + return "LOC_ID_SPELL_DESC_6"; + case (Displacer): + return "LOC_ID_SPELL_DESC_7"; + case (Boomerang): + return "LOC_ID_SPELL_DESC_8"; + case (DualBlades): + return "LOC_ID_SPELL_DESC_9"; + case (Close): + return "LOC_ID_SPELL_DESC_10"; + case (DamageShield): + return "LOC_ID_SPELL_DESC_11"; + case (Bounce): + return "LOC_ID_SPELL_DESC_12"; + case (Laser): + return "LOC_ID_SPELL_DESC_13"; + case (DragonFire): + case (DragonFireNeo): + return "LOC_ID_SPELL_DESC_14"; + case (RapidDagger): + return "LOC_ID_SPELL_DESC_15"; + } + return ""; + } + + public static string Icon(byte spellType) + { + switch (spellType) + { + case (Dagger): + return "DaggerIcon_Sprite"; + case (Axe): + return "AxeIcon_Sprite"; + case (TimeBomb): + return "TimeBombIcon_Sprite"; + case (TimeStop): + return "TimeStopIcon_Sprite"; + case (Nuke): + return "NukeIcon_Sprite"; + case (Translocator): + return "TranslocatorIcon_Sprite"; + case (Displacer): + return "DisplacerIcon_Sprite"; + case (Boomerang): + return "BoomerangIcon_Sprite"; + case (DualBlades): + return "DualBladesIcon_Sprite"; + case (Close): + return "CloseIcon_Sprite"; + case (DamageShield): + return "DamageShieldIcon_Sprite"; + case (Bounce): + return "BounceIcon_Sprite"; + case (Laser): + return "DaggerIcon_Sprite"; + case (DragonFire): + case (DragonFireNeo): + return "DragonFireIcon_Sprite"; + case (RapidDagger): + return "RapidDaggerIcon_Sprite"; + } + return "DaggerIcon_Sprite"; + } + + public static Vector3 GetNext3Spells() + { + byte[] spellArray = ClassType.GetSpellList(ClassType.Wizard2); + List spellList = new List(); + foreach (byte spell in spellArray) + spellList.Add(spell); + int spellIndex = spellList.IndexOf(Game.PlayerStats.Spell); + spellList.Clear(); + spellList = null; + + byte[] wizardSpells = new byte[3]; + for (int i = 0; i < 3; i++) + { + wizardSpells[i] = spellArray[spellIndex]; + spellIndex++; + if (spellIndex >= spellArray.Length) + spellIndex = 0; + } + + return new Vector3(wizardSpells[0], wizardSpells[1], wizardSpells[2]); + } + } +} diff --git a/RogueCastle/src/Types/TraitType.cs b/RogueCastle/src/Types/TraitType.cs new file mode 100644 index 0000000..711481c --- /dev/null +++ b/RogueCastle/src/Types/TraitType.cs @@ -0,0 +1,499 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using DS2DEngine; + +namespace RogueCastle +{ + public class TraitType + { + public const byte None = 0; + public const byte ColorBlind = 1; // Done + public const byte Gay = 2; // Done + public const byte NearSighted = 3; // Done + public const byte FarSighted = 4; // Done + public const byte Dyslexia = 5; // Done + public const byte Gigantism = 6; // Done + public const byte Dwarfism = 7; // Done + public const byte Baldness = 8; // Done + public const byte Endomorph = 9; // Done + public const byte Ectomorph = 10; // Done + public const byte Alzheimers = 11; // Done + public const byte Dextrocardia = 12; // Done + public const byte Tourettes = 13; // Done + public const byte Hyperactive = 14; // Done + public const byte OCD = 15; // Done + public const byte Hypergonadism = 16; // Done + public const byte Hypogonadism = 17; // Done + public const byte StereoBlind = 18; // Done + public const byte IBS = 19; // Done + public const byte Vertigo = 20; // Done + public const byte TunnelVision = 21; // Done + public const byte Ambilevous = 22; // Done + public const byte PAD = 23; // Done + public const byte Alektorophobia = 24; // Done + public const byte Hypochondriac = 25; // Done + public const byte Dementia = 26; // Done + public const byte Hypermobility = 27; // Done + public const byte EideticMemory = 28; // Done + public const byte Nostalgic = 29; // Done + public const byte CIP = 30; // Done + public const byte Savant = 31; // Done + public const byte TheOne = 32; // Done + public const byte NoFurniture = 33; // Done + public const byte PlatformsOpen = 34; // Done + public const byte Glaucoma = 35; // Done + public const byte Clonus = 36; // Done + public const byte Prosopagnosia = 37; // Done + + public const byte Total = 38; + + public const byte Adopted = 100; + + public static byte Rarity(byte traitType) + { + switch (traitType) + { + case (ColorBlind): + return 2; + case (Gay): + return 1; + case (NearSighted): + return 2; + case (FarSighted): + return 3; + case (Dyslexia): + return 3; + case (Gigantism): + return 1; + case (Dwarfism): + return 1; + case (Baldness): + return 1; + case (Endomorph): + return 1; + case (Ectomorph): + return 2; + case (Alzheimers): + return 3; + case (Dextrocardia): + return 2; + case (Tourettes): + return 1; + case (Hyperactive): + return 1; + case (OCD): + return 1; + case (Hypergonadism): + return 1; + case (Hypogonadism): + return 3; + case (StereoBlind): + return 1; + case (IBS): + return 2; + case (Vertigo): + return 3; + case (TunnelVision): + return 2; + case (Ambilevous): + return 2; + case (PAD): + return 2; + case (Alektorophobia): + return 2; + case (Hypochondriac): + return 3; + case (Dementia): + return 3; + case (Hypermobility): + return 2; + case (EideticMemory): + return 2; + case (Nostalgic): + return 3; + case (CIP): + return 3; + case (Savant): + return 2; + case (TheOne): + return 3; + case (NoFurniture): + return 2; + case (PlatformsOpen): + return 2; + case (Glaucoma): + return 2; + case(Clonus): + return 2; + case(Prosopagnosia): + return 2; + } + return 0; + } + + public static string ToStringID(byte traitType) + { + switch (traitType) + { + case (ColorBlind): + return "LOC_ID_TRAIT_TYPE_1"; + case (Gay): + return "LOC_ID_TRAIT_TYPE_2"; + case (NearSighted): + return "LOC_ID_TRAIT_TYPE_3"; + case (FarSighted): + return "LOC_ID_TRAIT_TYPE_4"; + case (Dyslexia): + return "LOC_ID_TRAIT_TYPE_5"; + case (Gigantism): + return "LOC_ID_TRAIT_TYPE_6"; + case (Dwarfism): + return "LOC_ID_TRAIT_TYPE_7"; + case (Baldness): + return "LOC_ID_TRAIT_TYPE_8"; + case (Endomorph): + return "LOC_ID_TRAIT_TYPE_9"; + case (Ectomorph): + return "LOC_ID_TRAIT_TYPE_10"; + case (Alzheimers): + return "LOC_ID_TRAIT_TYPE_11"; + case (Dextrocardia): + return "LOC_ID_TRAIT_TYPE_12"; + case (Tourettes): + return "LOC_ID_TRAIT_TYPE_13"; + case (Hyperactive): + return "LOC_ID_TRAIT_TYPE_14"; + case (OCD): + return "LOC_ID_TRAIT_TYPE_15"; + case (Hypergonadism): + return "LOC_ID_TRAIT_TYPE_16"; + case (Hypogonadism): + return "LOC_ID_TRAIT_TYPE_17"; + case (StereoBlind): + return "LOC_ID_TRAIT_TYPE_18"; + case (IBS): + return "LOC_ID_TRAIT_TYPE_19"; + case (Vertigo): + return "LOC_ID_TRAIT_TYPE_20"; + case (TunnelVision): + return "LOC_ID_TRAIT_TYPE_21"; + case (Ambilevous): + return "LOC_ID_TRAIT_TYPE_22"; + case (PAD): + return "LOC_ID_TRAIT_TYPE_23"; + case (Alektorophobia): + return "LOC_ID_TRAIT_TYPE_24"; + case (Hypochondriac): + return "LOC_ID_TRAIT_TYPE_25"; + case (Dementia): + return "LOC_ID_TRAIT_TYPE_26"; + case (Hypermobility): + return "LOC_ID_TRAIT_TYPE_27"; + case (EideticMemory): + return "LOC_ID_TRAIT_TYPE_28"; + case (Nostalgic): + return "LOC_ID_TRAIT_TYPE_29"; + case (CIP): + return "LOC_ID_TRAIT_TYPE_30"; + case (Savant): + return "LOC_ID_TRAIT_TYPE_31"; + case (TheOne): + return "LOC_ID_TRAIT_TYPE_32"; + case(NoFurniture): + return "LOC_ID_TRAIT_TYPE_33"; + case (PlatformsOpen): + return "LOC_ID_TRAIT_TYPE_34"; + case (Glaucoma): + return "LOC_ID_TRAIT_TYPE_35"; + case(Clonus): + return "LOC_ID_TRAIT_TYPE_36"; + case(Prosopagnosia): + return "LOC_ID_TRAIT_TYPE_37"; + } + return "NULL"; + } + + public static string DescriptionID(byte traitType, bool isFemale) + { + switch (traitType) + { + case (ColorBlind): + return "LOC_ID_TRAIT_DESC_1"; + case (Gay): + if (isFemale == true) + return "LOC_ID_TRAIT_DESC_2"; + else + return "LOC_ID_TRAIT_DESC_2b"; + case (NearSighted): + return "LOC_ID_TRAIT_DESC_3"; + case (FarSighted): + return "LOC_ID_TRAIT_DESC_4"; + case (Dyslexia): + return "LOC_ID_TRAIT_DESC_5"; + case (Gigantism): + return "LOC_ID_TRAIT_DESC_6"; + case (Dwarfism): + return "LOC_ID_TRAIT_DESC_7"; + case (Baldness): + return "LOC_ID_TRAIT_DESC_8"; + case (Endomorph): + return "LOC_ID_TRAIT_DESC_9"; + case (Ectomorph): + return "LOC_ID_TRAIT_DESC_10"; + case (Alzheimers): + return "LOC_ID_TRAIT_DESC_11"; + case (Dextrocardia): + return "LOC_ID_TRAIT_DESC_12"; + case (Tourettes): + return "LOC_ID_TRAIT_DESC_13"; + case (Hyperactive): + return "LOC_ID_TRAIT_DESC_14"; + case (OCD): + return "LOC_ID_TRAIT_DESC_15"; + case (Hypergonadism): + return "LOC_ID_TRAIT_DESC_16"; + case (Hypogonadism): + return "LOC_ID_TRAIT_DESC_17"; + case (StereoBlind): + return "LOC_ID_TRAIT_DESC_18"; + case (IBS): + return "LOC_ID_TRAIT_DESC_19"; + case (Vertigo): + return "LOC_ID_TRAIT_DESC_20"; + case (TunnelVision): + return "LOC_ID_TRAIT_DESC_21"; + case (Ambilevous): + return "LOC_ID_TRAIT_DESC_22"; + case (PAD): + return "LOC_ID_TRAIT_DESC_23"; + case (Alektorophobia): + return "LOC_ID_TRAIT_DESC_24"; + case (Hypochondriac): + return "LOC_ID_TRAIT_DESC_25"; + case (Dementia): + return "LOC_ID_TRAIT_DESC_26"; + case (Hypermobility): + return "LOC_ID_TRAIT_DESC_27"; + case (EideticMemory): + return "LOC_ID_TRAIT_DESC_28"; + case (Nostalgic): + return "LOC_ID_TRAIT_DESC_29"; + case (CIP): + return "LOC_ID_TRAIT_DESC_30"; + case (Savant): + return "LOC_ID_TRAIT_DESC_31"; + case (TheOne): + return "LOC_ID_TRAIT_DESC_32"; + case (NoFurniture): + return "LOC_ID_TRAIT_DESC_33"; + case (PlatformsOpen): + return "LOC_ID_TRAIT_DESC_34"; + case (Glaucoma): + return "LOC_ID_TRAIT_DESC_35"; + case(Clonus): + return "LOC_ID_TRAIT_DESC_36"; + case(Prosopagnosia): + return "LOC_ID_TRAIT_DESC_37"; + } + return "NULL"; + } + + public static string ProfileCardDescriptionID(byte traitType) + { + switch (traitType) + { + case (ColorBlind): + return "LOC_ID_TRAIT_PROF_1"; + case (Gay): + if (Game.PlayerStats.IsFemale == true) + return "LOC_ID_TRAIT_PROF_2"; + else + return "LOC_ID_TRAIT_PROF_2b"; + case (NearSighted): + return "LOC_ID_TRAIT_PROF_3"; + case (FarSighted): + return "LOC_ID_TRAIT_PROF_4"; + case (Dyslexia): + return "LOC_ID_TRAIT_PROF_5"; + case (Gigantism): + return "LOC_ID_TRAIT_PROF_6"; + case (Dwarfism): + return "LOC_ID_TRAIT_PROF_7"; + case (Baldness): + return "LOC_ID_TRAIT_PROF_8"; + case (Endomorph): + return "LOC_ID_TRAIT_PROF_9"; + case (Ectomorph): + return "LOC_ID_TRAIT_PROF_10"; + case (Alzheimers): + return "LOC_ID_TRAIT_PROF_11"; + case (Dextrocardia): + return "LOC_ID_TRAIT_PROF_12"; + case (Tourettes): + return "LOC_ID_TRAIT_PROF_13"; + case (Hyperactive): + return "LOC_ID_TRAIT_PROF_14"; + case (OCD): + return "LOC_ID_TRAIT_PROF_15"; + case (Hypergonadism): + return "LOC_ID_TRAIT_PROF_16"; + case (Hypogonadism): + return "LOC_ID_TRAIT_PROF_17"; + case (StereoBlind): + return "LOC_ID_TRAIT_PROF_18"; + case (IBS): + return "LOC_ID_TRAIT_PROF_19"; + case (Vertigo): + return "LOC_ID_TRAIT_PROF_20"; + case (TunnelVision): + return "LOC_ID_TRAIT_PROF_21"; + case (Ambilevous): + return "LOC_ID_TRAIT_PROF_22"; + case (PAD): + return "LOC_ID_TRAIT_PROF_23"; + case (Alektorophobia): + return "LOC_ID_TRAIT_PROF_24"; + case (Hypochondriac): + return "LOC_ID_TRAIT_PROF_25"; + case (Dementia): + return "LOC_ID_TRAIT_PROF_26"; + case (Hypermobility): + return "LOC_ID_TRAIT_PROF_27"; + case (EideticMemory): + return "LOC_ID_TRAIT_PROF_28"; + case (Nostalgic): + return "LOC_ID_TRAIT_PROF_29"; + case (CIP): + return "LOC_ID_TRAIT_PROF_30"; + case (Savant): + return "LOC_ID_TRAIT_PROF_31"; + case (TheOne): + return "LOC_ID_TRAIT_PROF_32"; + case (NoFurniture): + return "LOC_ID_TRAIT_PROF_33"; + case (PlatformsOpen): + return "LOC_ID_TRAIT_PROF_34"; + case (Glaucoma): + return "LOC_ID_TRAIT_PROF_35"; + case (Clonus): + return "LOC_ID_TRAIT_DESC_36"; + case (Prosopagnosia): + return "LOC_ID_TRAIT_DESC_37"; + } + return "NULL"; + } + + public static Vector2 CreateRandomTraits() + { + Vector2 traitsToReturn = Vector2.Zero; + + int numTraits = 0; + int maxTraits = 2;//3; //The maximum number of traits a player can have. + int baseChanceForTrait = 94;//60;//100; //90; //The Base chance of the player getting at least 1 trait. + int dropRateChanceForTrait = 39;//45;//40; //The percent chance of getting a consecutive trait. + int minChanceForTrait = 1; //Minimum chance for the player to get a trait. + int traitChance = CDGMath.RandomInt(0, 100); + + // Start by getting the number of traits this lineage has. + for (int i = 0; i < maxTraits; i++) + { + if (traitChance < baseChanceForTrait) + numTraits++; + + baseChanceForTrait -= dropRateChanceForTrait; + if (baseChanceForTrait < minChanceForTrait) + baseChanceForTrait = minChanceForTrait; + } + + int[] rarityParams = new int[] { 48, 37, 15 }; //Sets odds of being rarity 1,2, or 3. The higher, the rarer. + byte rarity = 0; + int totalChance = 0; + int chance = CDGMath.RandomInt(0, 100); + List traitList = new List(); + + if (numTraits > 0) + { + // Calculate the rarity for trait 1. + for (int k = 0; k < 3; k++) + { + totalChance += rarityParams[k]; + if (chance <= totalChance) + { + rarity = (byte)(k + 1); + break; + } + } + + // Find all traits of the equivalent rarity for trait 1. + for (byte i = 0; i < TraitType.Total; i++) + { + if (rarity == TraitType.Rarity(i)) + traitList.Add(i); + } + + // Set trait 1's trait. + traitsToReturn.X = traitList[CDGMath.RandomInt(0, traitList.Count - 1)]; + } + + if (numTraits > 1) + { + rarity = 0; + totalChance = 0; + chance = CDGMath.RandomInt(0, 100); + traitList.Clear(); + + // Calculate the rarity for trait 2. + for (int k = 0; k < 3; k++) + { + totalChance += rarityParams[k]; + if (chance <= totalChance) + { + rarity = (byte)(k + 1); + break; + } + } + + // Find all traits of the equivalent rarity for trait 2. + for (byte i = 0; i < TraitType.Total; i++) + { + if (rarity == TraitType.Rarity(i)) + traitList.Add(i); + } + + // Set trait 2's trait. + do + { + traitsToReturn.Y = traitList[CDGMath.RandomInt(0, traitList.Count - 1)]; + } while (traitsToReturn.Y == traitsToReturn.X || TraitConflict(traitsToReturn) == true); + } + + return traitsToReturn; + } + + // Calculates whether there is a conflict between two traits. + public static bool TraitConflict(Vector2 traits) + { + bool conflict = false; + + if ((traits.X == TraitType.Hypergonadism && traits.Y == TraitType.Hypogonadism) || (traits.X == TraitType.Hypogonadism && traits.Y == TraitType.Hypergonadism)) + conflict = true; + + if ((traits.X == TraitType.Endomorph && traits.Y == TraitType.Ectomorph) || (traits.X == TraitType.Ectomorph && traits.Y == TraitType.Endomorph)) + conflict = true; + + if ((traits.X == TraitType.Gigantism && traits.Y == TraitType.Dwarfism) || (traits.X == TraitType.Dwarfism && traits.Y == TraitType.Gigantism)) + conflict = true; + + if ((traits.X == TraitType.NearSighted && traits.Y == TraitType.FarSighted) || (traits.X == TraitType.FarSighted && traits.Y == TraitType.NearSighted)) + conflict = true; + + if ((traits.X == TraitType.ColorBlind && traits.Y == TraitType.Nostalgic) || (traits.X == TraitType.Nostalgic && traits.Y == TraitType.ColorBlind)) + conflict = true; + + return conflict; + } + } +} diff --git a/RogueCastle/src/VirtualScreen.cs b/RogueCastle/src/VirtualScreen.cs new file mode 100644 index 0000000..ced423a --- /dev/null +++ b/RogueCastle/src/VirtualScreen.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; +using SpriteSystem; +using DS2DEngine; + +namespace RogueCastle +{ + class VirtualScreen + { + public readonly int VirtualWidth; + public readonly int VirtualHeight; + public readonly float VirtualAspectRatio; + + private GraphicsDevice graphicsDevice; + private RenderTarget2D screen; + + public VirtualScreen(int virtualWidth, int virtualHeight, GraphicsDevice graphicsDevice) + { + VirtualWidth = virtualWidth; + VirtualHeight = virtualHeight; + VirtualAspectRatio = (float)(virtualWidth) / (float)(virtualHeight); + + this.graphicsDevice = graphicsDevice; + //screen = new RenderTarget2D(graphicsDevice, virtualWidth, virtualHeight, false, graphicsDevice.PresentationParameters.BackBufferFormat, graphicsDevice.PresentationParameters.DepthStencilFormat, graphicsDevice.PresentationParameters.MultiSampleCount, RenderTargetUsage.DiscardContents); + screen = new RenderTarget2D(graphicsDevice, virtualWidth, virtualHeight, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + } + + public void ReinitializeRTs(GraphicsDevice graphicsDevice) + { + this.graphicsDevice = graphicsDevice; + if (screen.IsDisposed == false) + { + screen.Dispose(); + screen = null; + } + //screen = new RenderTarget2D(graphicsDevice, VirtualWidth, VirtualHeight, false, graphicsDevice.PresentationParameters.BackBufferFormat, graphicsDevice.PresentationParameters.DepthStencilFormat, graphicsDevice.PresentationParameters.MultiSampleCount, RenderTargetUsage.DiscardContents); + screen = new RenderTarget2D(graphicsDevice, VirtualWidth, VirtualHeight, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + + } + + private bool areaIsDirty = true; + + public void PhysicalResolutionChanged() + { + areaIsDirty = true; + } + + private Rectangle area; + + public void Update() + { + if (!areaIsDirty) + { + return; + } + + areaIsDirty = false; + var physicalWidth = graphicsDevice.Viewport.Width; + var physicalHeight = graphicsDevice.Viewport.Height; + var physicalAspectRatio = graphicsDevice.Viewport.AspectRatio; + + // This 'if' was commented out during Switch development, flibit added it back + if ((int)(physicalAspectRatio * 10) == (int)(VirtualAspectRatio * 10)) + { + area = new Rectangle(0, 0, physicalWidth, physicalHeight); + return; + } + + if (VirtualAspectRatio > physicalAspectRatio) + { + var scaling = (float)physicalWidth / (float)VirtualWidth; + var width = (float)(VirtualWidth) * scaling; + var height = (float)(VirtualHeight) * scaling; + var borderSize = (int)((physicalHeight - height) / 2); + area = new Rectangle(0, borderSize, (int)width, (int)height); + } + else + { + var scaling = (float)physicalHeight / (float)VirtualHeight; + var width = (float)(VirtualWidth) * scaling; + var height = (float)(VirtualHeight) * scaling; + var borderSize = (int)((physicalWidth - width) / 2); + area = new Rectangle(borderSize, 0, (int)width, (int)height); + } + } + + public void RecreateGraphics() + { + Console.WriteLine("GraphicsDevice Virtualization failed"); + + GraphicsDevice newDevice = (Game.ScreenManager.Game as Game).graphics.GraphicsDevice; + Game.ScreenManager.ReinitializeCamera(newDevice); + SpriteLibrary.ClearLibrary(); + (Game.ScreenManager.Game as Game).LoadAllSpriteFonts(); + (Game.ScreenManager.Game as Game).LoadAllEffects(); + (Game.ScreenManager.Game as Game).LoadAllSpritesheets(); + + if (Game.GenericTexture.IsDisposed == false) + Game.GenericTexture.Dispose(); + Game.GenericTexture = new Texture2D(newDevice, 1, 1); + Game.GenericTexture.SetData(new Color[] { Color.White }); + + Game.ScreenManager.ReinitializeContent(null, null); + } + + public void BeginCapture() + { + // XNA failed to properly reinitialize GraphicsDevice in virtualization. Time to recreate graphics device. + if (graphicsDevice.IsDisposed) + RecreateGraphics(); + + graphicsDevice.SetRenderTarget(screen); + } + + public void EndCapture() + { + graphicsDevice.SetRenderTarget(null); + } + + public void Draw(SpriteBatch spriteBatch) + { + if ((Game.ScreenManager.CurrentScreen is SkillScreen == false) && (Game.ScreenManager.CurrentScreen is LineageScreen == false) && + (Game.ScreenManager.CurrentScreen is SkillUnlockScreen == false) && (Game.ScreenManager.GetLevelScreen() != null) && + (Game.PlayerStats.Traits.X == TraitType.Vertigo || Game.PlayerStats.Traits.Y == TraitType.Vertigo) && Game.PlayerStats.SpecialItem != SpecialItemType.Glasses) + spriteBatch.Draw(screen, area, null, Color.White, 0, Vector2.Zero, SpriteEffects.FlipVertically, 0); + else + spriteBatch.Draw(screen, area, null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0); + } + + public RenderTarget2D RenderTarget + { + get { return screen; } + } + + } +} diff --git a/RogueCastle/src/WordBuilder.cs b/RogueCastle/src/WordBuilder.cs new file mode 100644 index 0000000..c49413c --- /dev/null +++ b/RogueCastle/src/WordBuilder.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DS2DEngine; + +namespace RogueCastle +{ + public class WordBuilder + { + private static string[] intro = { "Sir Skunky the Knight\n" }; //{ "So it continues... ", "Once more, ", "As constant as the passage of time, ", "The story grows stale, and " }; + private static string[] middle = { "Gigantism - You are larger\n" };//{ "an old hero's journey draws to a close, ", "another hero arises ", "the fated journey of another hero begins ", "another fool appears " }; + private static string[] end = { "Dextrocardia - HP/MP pools are swapped\n" };//{ "as the consuming darkness creeps ever closer.", "as the allure of defeating the castle grows.", "and the evil that plagues the world remains.", "because this game is too damn hard." }; + + public static string BuildDungeonNameLocID(GameTypes.LevelType levelType) + { + switch (levelType) + { + case GameTypes.LevelType.CASTLE: + return "LOC_ID_DUNGEON_NAME_1"; //"Castle Hamson"; //"The Keep"; //TEDDY - CHANGING NAME + case GameTypes.LevelType.DUNGEON: + return "LOC_ID_DUNGEON_NAME_2"; //"The Land of Darkness"; //"The Dungeon"; //TEDDY - CHANGING NAME + case GameTypes.LevelType.GARDEN: + return "LOC_ID_DUNGEON_NAME_3"; //"Forest Abkhazia";//"The Dungeon"; //TEDDY - CHANGING NAME + case GameTypes.LevelType.TOWER: + return "LOC_ID_DUNGEON_NAME_4"; //"The Maya";//"The Tower"; //TEDDY - CHANGING NAME + } + + return ""; + } + + // This doesn't seem to be used so no need for localization --Dave + public static void RandomIntro(TextObj textObj, int wordWrap = 0) + { + textObj.Text = intro[CDGMath.RandomInt(0, intro.Length - 1)] + middle[CDGMath.RandomInt(0, middle.Length - 1)] + end[CDGMath.RandomInt(0, end.Length - 1)]; + if (wordWrap > 0) + textObj.WordWrap(wordWrap); + } + } +} diff --git a/RogueCastle/src/XMLCompiler.cs b/RogueCastle/src/XMLCompiler.cs new file mode 100644 index 0000000..cd2409b --- /dev/null +++ b/RogueCastle/src/XMLCompiler.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; +using DS2DEngine; +using Microsoft.Xna.Framework; + +namespace RogueCastle +{ + public class XMLCompiler + { + public static void CompileEnemies(List enemyDataList, string filePath) + { + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Indent = true; + settings.ConformanceLevel = ConformanceLevel.Fragment; + XmlWriter writer = XmlWriter.Create(System.IO.Path.Combine(filePath, "EnemyList.xml"), settings); + + string xmlStringtest = ""; + writer.WriteStartElement("xml"); + + foreach (EnemyEditorData enemyDataObj in enemyDataList) + { + xmlStringtest += "\n"; + writer.WriteStartElement("EnemyObj"); + writer.WriteAttributeString("Type", enemyDataObj.Type.ToString()); + writer.WriteAttributeString("SpriteName", enemyDataObj.SpriteName); + + writer.WriteAttributeString("BasicScaleX", enemyDataObj.BasicScale.X.ToString()); + writer.WriteAttributeString("BasicScaleY", enemyDataObj.BasicScale.Y.ToString()); + + writer.WriteAttributeString("AdvancedScaleX", enemyDataObj.AdvancedScale.X.ToString()); + writer.WriteAttributeString("AdvancedScaleY", enemyDataObj.AdvancedScale.Y.ToString()); + + writer.WriteAttributeString("ExpertScaleX", enemyDataObj.ExpertScale.X.ToString()); + writer.WriteAttributeString("ExpertScaleY", enemyDataObj.ExpertScale.Y.ToString()); + + writer.WriteAttributeString("MinibossScaleX", enemyDataObj.MinibossScale.X.ToString()); + writer.WriteAttributeString("MinibossScaleY", enemyDataObj.MinibossScale.Y.ToString()); + + writer.WriteEndElement(); + xmlStringtest += "\n"; + } + writer.WriteEndElement(); + // Console.WriteLine(xmlStringtest); + writer.Flush(); + writer.Close(); + + } + } + + public struct EnemyEditorData + { + public byte Type; + public string SpriteName; + public Vector2 BasicScale; + public Vector2 AdvancedScale; + public Vector2 ExpertScale; + public Vector2 MinibossScale; + + public EnemyEditorData(byte enemyType) + { + EnemyObj enemyBasic = EnemyBuilder.BuildEnemy(enemyType, null, null, null, GameTypes.EnemyDifficulty.BASIC); + EnemyObj enemyAdvanced = EnemyBuilder.BuildEnemy(enemyType, null, null, null, GameTypes.EnemyDifficulty.ADVANCED); + EnemyObj enemyExpert = EnemyBuilder.BuildEnemy(enemyType, null, null, null, GameTypes.EnemyDifficulty.EXPERT); + EnemyObj enemyMiniboss = EnemyBuilder.BuildEnemy(enemyType, null, null, null, GameTypes.EnemyDifficulty.MINIBOSS); + + Type = enemyType; + SpriteName = enemyBasic.SpriteName; + BasicScale = enemyBasic.Scale; + AdvancedScale = enemyAdvanced.Scale; + ExpertScale = enemyExpert.Scale; + MinibossScale = enemyMiniboss.Scale; + } + } + +} diff --git a/RogueLegacy.sln b/RogueLegacy.sln new file mode 100644 index 0000000..5ac0d78 --- /dev/null +++ b/RogueLegacy.sln @@ -0,0 +1,47 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RogueCastle", "RogueCastle\RogueCastle.csproj", "{4526354A-4053-41F2-9124-FFC831A7FED1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DS2DEngine", "DS2DEngine\DS2DEngine.csproj", "{050AF89B-5F49-455E-93C1-BFE7FF9506D2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpriteSystem", "SpriteSystem\SpriteSystem.csproj", "{92C40872-2B5C-4894-AABB-602547E1DFC3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tweener", "Tweener\Tweener.csproj", "{D9583122-AC6D-41EB-8292-04BDD0519D7C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InputSystem", "InputSystem\InputSystem.csproj", "{4EFA1C2F-A065-4520-A8AC-A71EA1751C54}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FNA", "..\FNA\FNA.NetFramework.csproj", "{35253CE1-C864-4CD3-8249-4D1319748E8F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {050AF89B-5F49-455E-93C1-BFE7FF9506D2}.Debug|x64.ActiveCfg = Debug|x64 + {050AF89B-5F49-455E-93C1-BFE7FF9506D2}.Debug|x64.Build.0 = Debug|x64 + {050AF89B-5F49-455E-93C1-BFE7FF9506D2}.Release|x64.ActiveCfg = Release|x64 + {050AF89B-5F49-455E-93C1-BFE7FF9506D2}.Release|x64.Build.0 = Release|x64 + {35253CE1-C864-4CD3-8249-4D1319748E8F}.Debug|x64.ActiveCfg = Debug|x64 + {35253CE1-C864-4CD3-8249-4D1319748E8F}.Debug|x64.Build.0 = Debug|x64 + {35253CE1-C864-4CD3-8249-4D1319748E8F}.Release|x64.ActiveCfg = Release|x64 + {35253CE1-C864-4CD3-8249-4D1319748E8F}.Release|x64.Build.0 = Release|x64 + {4526354A-4053-41F2-9124-FFC831A7FED1}.Debug|x64.ActiveCfg = Debug|x64 + {4526354A-4053-41F2-9124-FFC831A7FED1}.Debug|x64.Build.0 = Debug|x64 + {4526354A-4053-41F2-9124-FFC831A7FED1}.Release|x64.ActiveCfg = Release|x64 + {4526354A-4053-41F2-9124-FFC831A7FED1}.Release|x64.Build.0 = Release|x64 + {4EFA1C2F-A065-4520-A8AC-A71EA1751C54}.Debug|x64.ActiveCfg = Debug|x64 + {4EFA1C2F-A065-4520-A8AC-A71EA1751C54}.Debug|x64.Build.0 = Debug|x64 + {4EFA1C2F-A065-4520-A8AC-A71EA1751C54}.Release|x64.ActiveCfg = Release|x64 + {4EFA1C2F-A065-4520-A8AC-A71EA1751C54}.Release|x64.Build.0 = Release|x64 + {92C40872-2B5C-4894-AABB-602547E1DFC3}.Debug|x64.ActiveCfg = Debug|x64 + {92C40872-2B5C-4894-AABB-602547E1DFC3}.Debug|x64.Build.0 = Debug|x64 + {92C40872-2B5C-4894-AABB-602547E1DFC3}.Release|x64.ActiveCfg = Release|x64 + {92C40872-2B5C-4894-AABB-602547E1DFC3}.Release|x64.Build.0 = Release|x64 + {D9583122-AC6D-41EB-8292-04BDD0519D7C}.Debug|x64.ActiveCfg = Debug|x64 + {D9583122-AC6D-41EB-8292-04BDD0519D7C}.Debug|x64.Build.0 = Debug|x64 + {D9583122-AC6D-41EB-8292-04BDD0519D7C}.Release|x64.ActiveCfg = Release|x64 + {D9583122-AC6D-41EB-8292-04BDD0519D7C}.Release|x64.Build.0 = Release|x64 + EndGlobalSection +EndGlobal diff --git a/SpriteSystem/SpriteLibrary.cs b/SpriteSystem/SpriteLibrary.cs new file mode 100644 index 0000000..8fe83c0 --- /dev/null +++ b/SpriteSystem/SpriteLibrary.cs @@ -0,0 +1,515 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; +using System.Xml.Linq; +using System.IO; +using System.Globalization; + +namespace SpriteSystem +{ + public class SpriteLibrary + { + //SpritesheetData items contain all the spritesheet data for a particular object in a spritesheet, NOT the data for all objects in a spritesheet. + + private static Dictionary _spriteDict; // string is name of graphic (groupName). SpritesheetData holds a list of info for each item index. + private static Dictionary _textureDict; // string is name of graphics (groupName). + private static Dictionary> _charDataDict; + + private static HashSet m_loadedPathesList; + + public SpriteLibrary() + { + } + + public static void Init() + { + _spriteDict = new Dictionary(); + _textureDict = new Dictionary(); + _charDataDict = new Dictionary>(); + m_loadedPathesList = new HashSet(); + } + + public static List LoadSpritesheet(ContentManager content, string spritesheetName, bool returnCharDataNames) + { + // flibit added this + spritesheetName = spritesheetName.Replace('\\', '/'); + + if (m_loadedPathesList.Contains(spritesheetName)) + { + Console.WriteLine("Spritesheet: " + spritesheetName + " already loaded in the Sprite Library."); + return null; + } + m_loadedPathesList.Add(spritesheetName); + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true; + settings.IgnoreWhitespace = true; + Texture2D newTexture2D = content.Load(spritesheetName); + XmlReader reader = XmlReader.Create(content.RootDirectory + Path.DirectorySeparatorChar + spritesheetName + ".xml", settings); + return ParseData(reader, newTexture2D, returnCharDataNames, spritesheetName); + } + + /// + /// Overloaded method that stores the spritesheet via full string path, as opposed to a content manager. + /// + /// The graphics device that you want to be used to draw this spritesheet. + /// The full string path of the spritesheet. + /// If true, returns a list of all CharData names. If false, returns all Sprite names. + /// If true, premultiplies alpha for the image. + public static List LoadSpritesheet(GraphicsDevice graphicsDevice, string fullSpritePath, bool returnCharDataNames, bool premultiplyAlpha = false) + { + // flibit added this + fullSpritePath = fullSpritePath.Replace('\\', '/'); + + if (m_loadedPathesList.Contains(fullSpritePath)) + { + Console.WriteLine("Spritesheet Path: " + fullSpritePath + " already loaded in the Sprite Library."); + return null; + } + m_loadedPathesList.Add(fullSpritePath); + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true; + settings.IgnoreWhitespace = true; + + FileStream fs = new FileStream(fullSpritePath, FileMode.Open, FileAccess.Read); + Texture2D newTexture2D = Texture2D.FromStream(graphicsDevice, fs); + fs.Close(); + + if (newTexture2D == null) + throw new Exception("File not found at path: " + fullSpritePath); + + if (premultiplyAlpha) + { + Color[] data = new Color[newTexture2D.Width * newTexture2D.Height]; + newTexture2D.GetData(data); + for (int i = 0; i < data.Length; i += 1) + { + data[i] = Color.FromNonPremultiplied(data[i].ToVector4()); + } + newTexture2D.SetData(data); + } + + string xmlPath = fullSpritePath.Substring(0, fullSpritePath.Length - 4) + ".xml"; + XmlReader reader = XmlReader.Create(xmlPath, settings); + + return ParseData(reader, newTexture2D, returnCharDataNames, fullSpritePath); + } + + private static List ParseData(XmlReader reader, Texture2D newTexture2D, bool returnCharDataNames, string spritesheetName) + { + List namesList = new List(); + // flibit didn't like this! + // CultureInfo ci = (CultureInfo)CultureInfo.CurrentCulture.Clone(); + // ci.NumberFormat.CurrencyDecimalSeparator = "."; + CultureInfo ci = CultureInfo.InvariantCulture; + + string lastFrameName = ""; + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + if (reader.Name == "instance") + { + reader.MoveToAttribute("name"); + string name = reader.Value; + if (returnCharDataNames == false && namesList.Contains(name) == false) + namesList.Add(name); + reader.MoveToAttribute("index"); + int index = int.Parse(reader.Value, NumberStyles.Any, ci); + reader.MoveToAttribute("posX"); + int posX = int.Parse(reader.Value, NumberStyles.Any, ci); + reader.MoveToAttribute("posY"); + int posY = int.Parse(reader.Value, NumberStyles.Any, ci); + reader.MoveToAttribute("anchorX"); + int anchorX = (int)float.Parse(reader.Value, NumberStyles.Any, ci); + reader.MoveToAttribute("anchorY"); + int anchorY = (int)float.Parse(reader.Value, NumberStyles.Any, ci); + reader.MoveToAttribute("width"); + int width = (int)float.Parse(reader.Value, NumberStyles.Any, ci); + reader.MoveToAttribute("height"); + int height = (int)float.Parse(reader.Value, NumberStyles.Any, ci); + + if (_textureDict.ContainsKey(name) == false) // If the texture dictionary does not have this image, create a new one. + { + _textureDict.Add(name, newTexture2D); + } + + if (_spriteDict.ContainsKey(name) == false) // If the sprite dictionary does not have this image's data, create a new one. + { + SpritesheetObj newSpriteSheet = new SpritesheetObj(name, spritesheetName); + newSpriteSheet.AddImageData(index, posX, posY, anchorX, anchorY, width, height); + _spriteDict.Add(name, newSpriteSheet); + } + else + { + SpritesheetObj spritesheetToAddDataTo = _spriteDict[name]; + spritesheetToAddDataTo.AddImageData(index, posX, posY, anchorX, anchorY, width, height); + } + } + else if (reader.Name == "animation") + { + reader.MoveToAttribute("name"); + string name = reader.Value; + lastFrameName = name; // This variable is used so that the rectangle nodes know which animation frame they're tied to. + reader.MoveToAttribute("index"); + int index = int.Parse(reader.Value, NumberStyles.Any, ci); + reader.MoveToAttribute("duration"); + int duration = int.Parse(reader.Value, NumberStyles.Any, ci); + reader.MoveToAttribute("frame"); + int frame = int.Parse(reader.Value, NumberStyles.Any, ci); + reader.MoveToAttribute("label"); + string label = reader.Value; + + if (_spriteDict.ContainsKey(name) == true) + { + SpritesheetObj spritesheetToAddDataTo = _spriteDict[name]; + spritesheetToAddDataTo.AddFrameData(frame, index, duration, label); + } + else + throw new Exception("Attempting to add frame data to non-existent sprite called: " + name); + } + else if (reader.Name == "rectangle") + { + reader.MoveToAttribute("x"); + int x = int.Parse(reader.Value, NumberStyles.Any, ci); + //int x = (int)float.Parse(reader.Value); + reader.MoveToAttribute("y"); + int y = int.Parse(reader.Value, NumberStyles.Any, ci); + //int y = (int)float.Parse(reader.Value); + reader.MoveToAttribute("width"); + int width = int.Parse(reader.Value, NumberStyles.Any, ci); + //int width = (int)float.Parse(reader.Value); + reader.MoveToAttribute("height"); + //int height = int.Parse(reader.Value); + int height = (int)float.Parse(reader.Value, NumberStyles.Any, ci); + reader.MoveToAttribute("rotation"); + float rotation = float.Parse(reader.Value, NumberStyles.Any, ci); + reader.MoveToAttribute("type"); + int type = int.Parse(reader.Value, NumberStyles.Any, ci); + //int type = (int)float.Parse(reader.Value); + + if (_spriteDict.ContainsKey(lastFrameName) == true) + { + SpritesheetObj spritesheetToAddDataTo = _spriteDict[lastFrameName]; + spritesheetToAddDataTo.AddHitboxToLastFrameData(x, y, width, height, rotation, type); + } + else + throw new Exception("Attempting to add hitbox data to non-existent sprite called: " + lastFrameName); + + } + else if (reader.Name == "container") + { + reader.MoveToAttribute("name"); + string parentName = reader.Value; + if (returnCharDataNames == true && namesList.Contains(parentName) == false) + namesList.Add(parentName); + reader.MoveToAttribute("child"); + string childName = reader.Value; + reader.MoveToAttribute("childX"); + int childX = (int)float.Parse(reader.Value, NumberStyles.Any, ci); + reader.MoveToAttribute("childY"); + int childY = (int)float.Parse(reader.Value, NumberStyles.Any, ci); + + AddCharacterData(parentName, childName, childX, childY); + } + } + } + + foreach (KeyValuePair pair in _spriteDict) + { + pair.Value.SortImageData(); + } + + return namesList; + } + + private static void AddCharacterData(string parent, string child, int childX, int childY) + { + if (_charDataDict.ContainsKey(parent) == false) + { + List newCharList = new List(); + CharacterData newCharData = new CharacterData(); + newCharData.Child = child; + newCharData.ChildX = childX; + newCharData.ChildY = childY; + newCharList.Add(newCharData); + _charDataDict.Add(parent, newCharList); + } + else + { + List oldCharList = _charDataDict[parent]; + CharacterData newCharData = new CharacterData(); + newCharData.Child = child; + newCharData.ChildX = childX; + newCharData.ChildY = childY; + oldCharList.Add(newCharData); + } + } + + public static bool ContainsSprite(string spriteName) + { + return _spriteDict.ContainsKey(spriteName); + } + + public static bool ContainsCharacter(string charDataName) + { + return _charDataDict.ContainsKey(charDataName); + } + + public static void ClearLibrary() + { + // Creating a copy of m_loadedPathesList first because m_loadedPathesList is modified when calling ClearSpritesheet(). + List spritesheetNamesList = new List(); + foreach (string name in m_loadedPathesList) + spritesheetNamesList.Add(name); + + foreach (string spritesheetName in spritesheetNamesList) + ClearSpritesheet(spritesheetName); + + foreach (KeyValuePair entry in _spriteDict) + { + if (entry.Value.IsDisposed == false) + entry.Value.Dispose(); + } + _spriteDict.Clear(); + + foreach (KeyValuePair entry in _textureDict) + { + if (entry.Value.IsDisposed == false) + entry.Value.Dispose(); + } + _textureDict.Clear(); + _charDataDict.Clear(); + m_loadedPathesList.Clear(); + } + + // Clears an item from the Sprite Library. The actual texture will not be disposed unless all items that reference that texture are removed. + public static void ClearItem(string name) + { + if (_spriteDict.ContainsKey(name)) + { + _spriteDict[name].Dispose(); + _spriteDict.Remove(name); + } + + // Check to see if other SpritesheetObjs reference the texture of the object just removed. + //If yes, do not remove texture. + //If no, remove and dispose texture. + bool removeTexture = true; + Texture2D textureCheck = null; + if (_textureDict.ContainsKey(name)) + textureCheck = _textureDict[name]; + + foreach (KeyValuePair pair in _spriteDict) + { + if (_textureDict[pair.Value.SpritesheetObjName] == textureCheck) + { + removeTexture = false; + break; + } + } + + if (removeTexture == true && textureCheck != null) + { + Texture2D textureToDispose = _textureDict[name]; + _textureDict.Remove(name); + textureToDispose.Dispose(); + } + + if (_charDataDict.ContainsKey(name)) + _charDataDict.Remove(name); + } + + //Unlike clear item, clear spritesheet will remove every single texture and SpritesheetObj that was loaded from a spritesheet name + public static void ClearSpritesheet(string spritesheetName) + { + // flibit added this + spritesheetName = spritesheetName.Replace('\\', '/'); + + if (m_loadedPathesList.Contains(spritesheetName)) + { + List spritesheetObjsToRemove = new List(); + Texture2D textureToDispose = null; + + foreach (KeyValuePair pair in _spriteDict) + { + if (pair.Value.SpritesheetName == spritesheetName) + { + spritesheetObjsToRemove.Add(pair.Value.SpritesheetObjName); + if (textureToDispose == null) + textureToDispose = _textureDict[pair.Value.SpritesheetObjName]; + } + } + + List charDataToRemove = new List(); + foreach (string objName in spritesheetObjsToRemove) + { + if (_spriteDict.ContainsKey(objName)) // These look ups may not be necessary. + { + _spriteDict[objName].Dispose(); + _spriteDict.Remove(objName); + } + + if (_textureDict.ContainsKey(objName)) + _textureDict.Remove(objName); + + //Check to see if any children of a characterdata object uses these sprites. If so, remove that characterdata entry. + foreach (KeyValuePair> pair in _charDataDict) + { + foreach (CharacterData data in pair.Value) + { + if (data.Child == objName) + { + charDataToRemove.Add(pair.Key); + break; + } + } + } + } + + foreach (string charDataName in charDataToRemove) + { + _charDataDict.Remove(charDataName); + } + + if (textureToDispose != null && textureToDispose.IsDisposed == false) + textureToDispose.Dispose(); + + m_loadedPathesList.Remove(spritesheetName); + } + else + Console.WriteLine("Could not clear Spritesheet: " + spritesheetName + " from the Sprite Library as it does not exist."); + } + + public static FrameData GetFrameData(string name, int index) + { + return _spriteDict[name].FrmData(index); + } + + public static List GetFrameDataList(string name) + { + return _spriteDict[name].FrmDataList(); + } + + public static int GetFrameCount(string name) + { + return _spriteDict[name].FrameCount(); + } + + public static ImageData GetImageData(string name, int index) + { + return _spriteDict[name].ImgData(index); + } + + public static List GetImageDataList(string name) + { + return _spriteDict[name].ImgDataList(); + } + + public static Texture2D GetSprite(string name) + { + return _textureDict[name]; + } + + public static string GetSpritesheetName(string name) + { + return _spriteDict[name].SpritesheetName; + } + + public static Vector2 GetSSPos(string name, int index) + { + return _spriteDict[name].SSPos(index); + } + + public static Vector2 GetAnchor(string name, int index) + { + return _spriteDict[name].Anchor(index); + } + + public static int GetWidth(string name, int index) + { + return _spriteDict[name].Width(index); + } + + public static int GetHeight(string name, int index) + { + return _spriteDict[name].Height(index); + } + + public static List GetCharData(string name) + { + return _charDataDict[name]; + } + + public static List GetAllSpriteNames() + { + return new List(_spriteDict.Keys); + } + + public static List GetAllSpriteNames(string filePath) + { + List listToReturn = new List(); + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true; + settings.IgnoreWhitespace = true; + string xmlPath = filePath.Substring(0, filePath.Length - 4) + ".xml"; + XmlReader reader = XmlReader.Create(xmlPath, settings); + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + if (reader.Name == "instance") + { + reader.MoveToAttribute("name"); + string name = reader.Value; + if (listToReturn.Contains(name) == false) + listToReturn.Add(name); + } + } + } + return listToReturn; + } + + public static List GetAllCharDataNames() + { + return new List(_charDataDict.Keys); + } + + public static List GetAllCharDataNames(string filePath) + { + List listToReturn = new List(); + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true; + settings.IgnoreWhitespace = true; + string xmlPath = filePath.Substring(0, filePath.Length - 4) + ".xml"; + XmlReader reader = XmlReader.Create(xmlPath, settings); + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + if (reader.Name == "container") + { + reader.MoveToAttribute("name"); + string name = reader.Value; + if (listToReturn.Contains(name) == false) + listToReturn.Add(name); + } + } + } + return listToReturn; + } + + public static int NumItems + { + get { return _charDataDict.Count; } + } + } +} diff --git a/SpriteSystem/SpriteSystem.csproj b/SpriteSystem/SpriteSystem.csproj new file mode 100644 index 0000000..506d4bb --- /dev/null +++ b/SpriteSystem/SpriteSystem.csproj @@ -0,0 +1,14 @@ + + + + Library + net40 + + + + + {35253CE1-C864-4CD3-8249-4D1319748E8F} + FNA + + + diff --git a/SpriteSystem/SpritesheetObj.cs b/SpriteSystem/SpritesheetObj.cs new file mode 100644 index 0000000..499d620 --- /dev/null +++ b/SpriteSystem/SpritesheetObj.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; + +namespace SpriteSystem +{ + public class SpritesheetObj + { + private string _spritesheetObjName; + private string _spritesheetName; + private List _imageDataList; + private List _frameDataList; + private bool m_isDisposed = false; + + public SpritesheetObj(string objName, string spritesheetName) + { + _spritesheetObjName = objName; + _spritesheetName = spritesheetName; + _imageDataList = new List(); + _frameDataList = new List(); + + } + + public void AddImageData(int index, int posX, int posY, int anchorX, int anchorY, int width, int height) + { + ImageData newImageData = new ImageData(); + newImageData.Index = index; + newImageData.SSPos.X = posX; + newImageData.SSPos.Y = posY; + newImageData.Anchor.X = anchorX; + newImageData.Anchor.Y = anchorY; + newImageData.Width = width; + newImageData.Height = height; + _imageDataList.Add(newImageData); + } + + public void SortImageData() + { + _imageDataList.Sort(ImageDataComparator); + } + + private int ImageDataComparator(ImageData id1, ImageData id2) + { + if (id1.Index > id2.Index) + return 1; + else if (id1.Index < id2.Index) + return -1; + else return 0; + } + + public void AddFrameData(int frame, int index, int duration, string label) + { + if (duration < 1) + throw new Exception("Frame data cannot have a duration of 0 frames"); + + FrameData newFrameData = new FrameData(); + newFrameData.hitboxList = new List(); + newFrameData.Frame = frame; + newFrameData.Index = index; + newFrameData.Duration = duration; + newFrameData.Label = label; + _frameDataList.Add(newFrameData); + } + + //Adds a hitbox to the hitboxlist in the last FrameData object created by calling AddFrameData(). + public void AddHitboxToLastFrameData(int x, int y, int width, int height, float rotation, int type) + { + Hitbox newHitbox = new Hitbox(); + newHitbox.X = x; + newHitbox.Y = y; + newHitbox.Width = width; + newHitbox.Height = height; + newHitbox.Rotation = rotation; + newHitbox.Type = type; + + _frameDataList[_frameDataList.Count - 1].hitboxList.Add(newHitbox); + } + + public FrameData FrmData(int index) + { return _frameDataList[index]; } + + public int FrameCount() + { return _frameDataList.Count; } + + public ImageData ImgData(int index) + { return _imageDataList[index]; } + + public Vector2 SSPos(int index) + { return _imageDataList[index].SSPos; } + + public Vector2 Anchor(int index) + { return _imageDataList[index].Anchor; } + + public int Width(int index) + { return _imageDataList[index].Width; } + + public int Height(int index) + { return _imageDataList[index].Height; } + + public List ImgDataList() + { return _imageDataList; } + + public List FrmDataList() + { return _frameDataList; } + + public string SpritesheetObjName + { + get { return _spritesheetObjName; } + } + + public string SpritesheetName + { + get { return _spritesheetName; } + } + + public bool IsDisposed + { + get { return m_isDisposed; } + } + + public void Dispose() + { + if (m_isDisposed == false) + { + m_isDisposed = true; + _imageDataList.Clear(); + _imageDataList = null; + foreach (FrameData fd in _frameDataList) + { + fd.Dispose(); + } + _frameDataList.Clear(); + _frameDataList = null; + + } + } + } + + public struct ImageData + { + public Vector2 SSPos; // Spritesheet Position + public Vector2 Anchor; + public int Index; + public int Width; + public int Height; + } + + public class FrameData + { + public int Frame; + public int Index; + public int Duration; + public List hitboxList; + public string Label; + + public void Dispose() + { + hitboxList.Clear(); + hitboxList = null; + } + } + + public struct CharacterData + { + public string Child; + public int ChildX; + public int ChildY; + } + + public struct Hitbox + { + public int X; + public int Y; + public int Width; + public int Height; + public float Rotation; + public int Type; + } +} diff --git a/Tweener/Ease.cs b/Tweener/Ease.cs new file mode 100644 index 0000000..51f78f3 --- /dev/null +++ b/Tweener/Ease.cs @@ -0,0 +1,265 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Tweener.Ease +{ + public class Back + { +// public static float EaseIn(float t, float b, float c, float d, float s) + public static float EaseIn(float t, float b, float c, float d) + { + float s = 1.70158f; + return c * (t /= d) * t * ((s + 1) * t - s) + b; + } + + public static float EaseInLarge(float t, float b, float c, float d) + { + float s = 1.70158f * 3; + return c * (t /= d) * t * ((s + 1) * t - s) + b; + } + + public static float EaseOut(float t, float b, float c, float d) + { + float s = 1.70158f; + return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; + } + + public static float EaseOutLarge(float t, float b, float c, float d) + { + float s = 1.70158f * 3; + return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; + } + + public static float EaseInOut(float t, float b, float c, float d) + { + float s = 1.70158f; + if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525f))+1)*t - s)) + b; + return c/2*((t-=2)*t*(((s*=(1.525f))+1)*t + s) + 2) + b; + } + + public static float EaseInOutLarge(float t, float b, float c, float d) + { + float s = 1.70158f * 3; + if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525f)) + 1) * t - s)) + b; + return c / 2 * ((t -= 2) * t * (((s *= (1.525f)) + 1) * t + s) + 2) + b; + } + } + + public class Bounce + { + public static float EaseOut(float t, float b, float c, float d) + { + if ((t/=d) < (1/2.75f)) { + return c*(7.5625f*t*t) + b; + } else if (t < (2/2.75f)) { + return c*(7.5625f*(t-=(1.5f/2.75f))*t + .75f) + b; + } else if (t < (2.5f/2.75f)) { + return c*(7.5625f*(t-=(2.25f/2.75f))*t + .9375f) + b; + } else { + return c*(7.5625f*(t-=(2.625f/2.75f))*t + .984375f) + b; + } + } + + public static float EaseIn(float t, float b, float c, float d) + { + return c - EaseOut(d-t, 0, c, d) + b; + } + + public static float EaseInOut(float t, float b, float c, float d) + { + if (t < d/2) return EaseIn(t*2, 0, c, d) * .5f + b; + else return EaseOut(t*2-d, 0, c, d) * .5f + c*.5f + b; + } + } + + public class Circ + { + public static float EaseIn(float t, float b, float c, float d) + { + return -c * (float)(Math.Sqrt(1 - (t/=d)*t) - 1) + b; + } + + public static float EaseOut(float t, float b, float c, float d) + { + return c * (float)Math.Sqrt(1 - (t = t / d - 1) * t) + b; + } + + public static float EaseInOut(float t, float b, float c, float d) + { + if ((t /= d / 2) < 1) return -c / 2 * (float)(Math.Sqrt(1 - t * t) - 1) + b; + return c / 2 * (float)(Math.Sqrt(1 - (t -= 2) * t) + 1) + b; + } + } + + public class Cubic + { + public static float EaseIn(float t, float b, float c, float d) + { + return c*(t/=d)*t*t + b; + } + + public static float EaseOut(float t, float b, float c, float d) + { + return c*((t=t/d-1)*t*t + 1) + b; + } + + public static float EaseInOut(float t, float b, float c, float d) + { + if ((t/=d/2) < 1) return c/2*t*t*t + b; + return c/2*((t-=2)*t*t + 2) + b; + } + } + + public class Elastic + { + public static float EaseIn(float t, float b, float c, float d, float a, float p) + { + float s; + if (t == 0) return b; if ((t /= d) == 1) return b + c; if (p == 0) p = d * .3f; + if (a == 0 || a < Math.Abs(c)) { a = c; s = p / 4; } + else s = (float)(p / (2 * Math.PI) * Math.Asin(c / a)); + return (float)(-(a * Math.Pow(2, 10 * (t -= 1)) * Math.Sin((t * d - s) * (2 * Math.PI) / p)) + b); + } + + public static float EaseOut(float t, float b, float c, float d, float a, float p) + { + float s; + if (t == 0) return b; if ((t /= d) == 1) return b + c; if (p == 0) p = d * .3f; + if (a == 0 || a < Math.Abs(c)) { a = c; s = p / 4; } + else s = (float)(p / (2 * Math.PI) * Math.Asin(c / a)); + return (float)(a * Math.Pow(2, -10 * t) * Math.Sin((t * d - s) * (2 * Math.PI) / p) + c + b); + } + + public static float EaseInOut(float t, float b, float c, float d, float a, float p) + { + float s; + if (t == 0) return b; if ((t /= d / 2) == 2) return b + c; if (p == 0) p = d * (.3f * 1.5f); + if (a == 0 || a < Math.Abs(c)) { a = c; s = p / 4; } + else s = (float)(p / (2 * Math.PI) * Math.Asin(c / a)); + if (t < 1) return (float)(-.5f * (a * Math.Pow(2, 10 * (t -= 1)) * Math.Sin((t * d - s) * (2 * Math.PI) / p)) + b); + return (float)(a * Math.Pow(2, -10 * (t -= 1)) * Math.Sin((t * d - s) * (2 * Math.PI) / p) * .5f + c + b); + } + } + + public class Expo + { + public static float EaseIn(float t, float b, float c, float d) + { + return (t==0) ? b : (float)(c * Math.Pow(2, 10 * (t/d - 1)) + b); + } + + public static float EaseOut(float t, float b, float c, float d) + { + return (t==d) ? b+c : (float)(c * (-Math.Pow(2, -10 * t/d) + 1) + b); + } + + public static float EaseInOut(float t, float b, float c, float d) + { + if (t==0) return b; + if (t==d) return b+c; + if ((t/=d/2) < 1) return (float)(c/2 * Math.Pow(2, 10 * (t - 1)) + b); + return (float)(c/2 * (-Math.Pow(2, -10 * --t) + 2) + b); + } + } + + //t is time, b is beginning position, c is the total change in position (NOT DELTACHANGE), and d is the total duration of the tween + public class Linear + { + public static float EaseNone(float t, float b, float c, float d) + { + return c*t/d + b; + } + + public static float EaseIn(float t, float b, float c, float d) + { + return c*t/d + b; + } + + public static float EaseOut(float t, float b, float c, float d) + { + return c*t/d + b; + } + + public static float EaseInOut(float t, float b, float c, float d) + { + return c*t/d + b; + } + } + + public class Quad + { + public static float EaseIn(float t, float b, float c, float d) + { + return c*(t/=d)*t + b; + } + + public static float EaseOut(float t, float b, float c, float d) + { + return -c *(t/=d)*(t-2) + b; + } + + public static float EaseInOut(float t, float b, float c, float d) + { + if ((t/=d/2) < 1) return c/2*t*t + b; + return -c/2 * ((--t)*(t-2) - 1) + b; + } + } + + public class Quart + { + public static float EaseIn(float t, float b, float c, float d) + { + return c*(t/=d)*t*t*t + b; + } + + public static float EaseOut(float t, float b, float c, float d) + { + return -c * ((t=t/d-1)*t*t*t - 1) + b; + } + + public static float EaseInOut(float t, float b, float c, float d) + { + if ((t/=d/2) < 1) return c/2*t*t*t*t + b; + return -c/2 * ((t-=2)*t*t*t - 2) + b; + } + } + + public class Quint + { + public static float EaseIn(float t, float b, float c, float d) + { + return c*(t/=d)*t*t*t*t + b; + } + + public static float EaseOut(float t, float b, float c, float d) + { + return c*((t=t/d-1)*t*t*t*t + 1) + b; + } + + public static float EaseInOut(float t, float b, float c, float d) + { + if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; + return c/2*((t-=2)*t*t*t*t + 2) + b; + } + } + + public class Sine + { + public static float EaseIn(float t, float b, float c, float d) + { + return (float)(-c * Math.Cos(t/d * (Math.PI/2)) + c + b); + } + + public static float EaseOut(float t, float b, float c, float d) + { + return (float)(c * Math.Sin(t/d * (Math.PI/2)) + b); + } + + public static float EaseInOut(float t, float b, float c, float d) + { + return (float)(-c/2 * (Math.Cos(Math.PI*t/d) - 1) + b); + } + } +} diff --git a/Tweener/Tween.cs b/Tweener/Tween.cs new file mode 100644 index 0000000..e329c44 --- /dev/null +++ b/Tweener/Tween.cs @@ -0,0 +1,305 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; +using System.Globalization; + +namespace Tweener +{ + public delegate float Easing(float t, float b, float c, float d); + + public sealed class Tween // Sealed means it can't be inherited from. + { + //private static volatile Tweener _singleton; // For multithreading. Volatile to ensure threads don't try to access the singleton's methods before it has been initialized. + //private static object _syncRoot = new Object(); // Blank object used to lock the singleton during instantiation to ensure multiple threads don't try to initialize it at once. + private static Stack _inactiveTweenPool; + private static LinkedList _activeTweenPool; + private static Stack _tweensToDispose; + + private static int _activeTweenCount; + private static int _inactiveTweenCount; + + public static CultureInfo ParserCI; + private static int m_poolSize = 0; + + public static void Initialize(int poolSize) + { + _inactiveTweenPool = new Stack(); + _activeTweenPool = new LinkedList(); + _tweensToDispose = new Stack(); + + for (int i = 0; i < poolSize; i++) + { + _inactiveTweenPool.Push(new TweenObject()); + } + + _inactiveTweenCount = poolSize; + m_poolSize = poolSize; + // flibit didn't like this! + // ParserCI = (CultureInfo)CultureInfo.CurrentCulture.Clone(); + // ParserCI.NumberFormat.CurrencyDecimalSeparator = "."; + ParserCI = CultureInfo.InvariantCulture; + } + + public static TweenObject By(object tweenObject, float duration, Easing ease, params string[] properties) + { + if (properties.Length % 2 != 0) + throw new Exception("TweenTo parameters must be submitted as follows - , "); + + TweenObject checkedOutTween = CheckOutTween(); + checkedOutTween.SetValues(tweenObject, duration, ease, false, properties); + return checkedOutTween; + } + + public static TweenObject To(object tweenObject, float duration, Easing ease, params string[] properties) + { + if (properties.Length % 2 != 0) + throw new Exception("TweenTo parameters must be submitted as follows - , "); + + TweenObject checkedOutTween = CheckOutTween(); + checkedOutTween.SetValues(tweenObject, duration, ease, true, properties); + return checkedOutTween; + } + + /// + /// A convenience function to add an endhandler to the last tween made + /// so that you do not have to hold a reference to the tween every time. + /// + public static void AddEndHandlerToLastTween(object methodObject, string functionName, params object[] args) + { + TweenObject lastTween = _activeTweenPool.Last.Value; + lastTween.EndHandler(methodObject, functionName, args); + } + + /// + /// A convenience function to add an endhandler to the last tween made + /// so that you do not have to hold a reference to the tween every time. + /// + public static void AddEndHandlerToLastTween(Type methodType, string functionName, params object[] args) + { + TweenObject lastTween = _activeTweenPool.Last.Value; + lastTween.EndHandler(methodType, functionName, args); + } + + public static TweenObject RunFunction(float delay, object methodObject, string functionName, params object[] args) + { + TweenObject toReturn = Tween.To(methodObject, delay, Tweener.Ease.Linear.EaseNone); + Tween.AddEndHandlerToLastTween(methodObject, functionName, args); + return toReturn; + } + + public static TweenObject RunFunction(float delay, Type methodType, string functionName, params object[] args) + { + TweenObject toReturn = Tween.To(methodType, delay, Tweener.Ease.Linear.EaseNone); + Tween.AddEndHandlerToLastTween(methodType, functionName, args); + return toReturn; + } + + /// + /// If an active tween is found in the _activeTweenPool it is updated. + /// If an inactive tween is found in the _activeTweenPool it is disposed (cleaned up and sent back into the _inactiveTweenPool). + /// + public static void Update(GameTime gameTime) + { + int numOfDisposableTweens = 0; + float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds; + foreach (TweenObject tween in _activeTweenPool) + { + if (tween.Active == true) + tween.Update(elapsedTime); + else + { + numOfDisposableTweens++; + _tweensToDispose.Push(tween); + } + } + + if (numOfDisposableTweens > 0) + { + foreach (TweenObject tween in _tweensToDispose) + { + Dispose(tween); + } + _tweensToDispose.Clear(); + } + } + + public static TweenObject Contains(object obj) + { + foreach (TweenObject tweenObj in _activeTweenPool) + { + if (obj == tweenObj.TweenedObject) + return tweenObj; + } + return null; + } + + public static void StopAllContaining(object obj, bool runEndHandler) + { + foreach (TweenObject tweenObj in _activeTweenPool) + { + if (obj == tweenObj.TweenedObject) + tweenObj.StopTween(runEndHandler); + } + } + + public static void StopAllContaining(Type type, bool runEndHandler) + { + foreach (TweenObject tweenObj in _activeTweenPool) + { + if (tweenObj.TweenedObject != null && tweenObj.TweenedObject.GetType() == type) + tweenObj.StopTween(runEndHandler); + } + } + + public static void StopAll(bool runEndHandler) + { + foreach (TweenObject tween in _activeTweenPool) + { + tween.StopTween(runEndHandler); + } + } + + public static void PauseAll() + { + foreach (TweenObject tween in _activeTweenPool) + { + tween.PauseTween(); + } + } + + public static void ResumeAll() + { + foreach (TweenObject tween in _activeTweenPool) + { + tween.ResumeTween(); + } + } + + public static void PauseAllContaining(object obj) + { + foreach (TweenObject tween in _activeTweenPool) + { + if (tween.TweenedObject == obj) + tween.PauseTween(); + } + } + + public static void ResumeAllContaining(object obj) + { + foreach (TweenObject tween in _activeTweenPool) + { + if (tween.TweenedObject == obj) + tween.ResumeTween(); + } + } + + public static void PauseAllContaining(Type type) + { + foreach (TweenObject tween in _activeTweenPool) + { + if (tween.TweenedObject != null && tween.TweenedObject.GetType() == type) + tween.PauseTween(); + } + } + + public static void ResumeAllContaining(Type type) + { + foreach (TweenObject tween in _activeTweenPool) + { + if (tween.TweenedObject != null && tween.TweenedObject.GetType() == type) + tween.ResumeTween(); + } + } + + private static TweenObject CheckOutTween() + { + if (_inactiveTweenCount < 1) + throw new Exception("TweenManager resource pool ran out of tweens."); + + TweenObject tweenToReturn = _inactiveTweenPool.Pop(); + _activeTweenPool.AddLast(tweenToReturn); + + if (tweenToReturn.CheckedOut == true) + throw new Exception("Checked out tween already checked out. There is an error in your Tween CheckIn()/CheckOut() code."); + + tweenToReturn.CheckedOut = true; + _activeTweenCount++; + _inactiveTweenCount--; + return tweenToReturn; + } + + private static void CheckInTween(TweenObject tween) + { + if (tween.CheckedOut == true) + { + tween.CheckedOut = false; + _inactiveTweenPool.Push(tween); + _activeTweenPool.Remove(tween); + + _activeTweenCount--; + _inactiveTweenCount++; + } + else + throw new Exception("Checking in an already checked in tween. There is an error in your Tween CheckIn()/CheckOut() code."); + } + + public static void Dispose(TweenObject tween) + { + //Tweens endhandler is called here so that it isn't called during the Update method, effectively modifying the collection in Update(). + tween.RunEndHandler(); + tween.Dispose(); + CheckInTween(tween); + } + + public static void DisposeAll() + { + foreach (TweenObject tween in _activeTweenPool) + { + tween.Dispose(); + } + _activeTweenPool.Clear(); + _inactiveTweenPool.Clear(); + // _singleton = null; + } + + public static int PoolSize + { + get { return m_poolSize;} + } + + public static int ActiveTweens + { + get { return _activeTweenCount; } + } + + public static int AvailableTweens + { + get { return _inactiveTweenCount; } + } + + /*public static Tweener Instance + { + get + { + if (_singleton == null) + { + lock (_syncRoot) + { + if (_singleton == null) + _singleton = new Tweener(); + } + } + + return _singleton; + } + }*/ + + public static float EaseNone(float t, float b, float c, float d) + { + return c * t / d + b; + } + } + +} diff --git a/Tweener/TweenObject.cs b/Tweener/TweenObject.cs new file mode 100644 index 0000000..ab72972 --- /dev/null +++ b/Tweener/TweenObject.cs @@ -0,0 +1,296 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using Microsoft.Xna.Framework; +using System.Globalization; + +namespace Tweener +{ + public class TweenObject + { + private string[] _propertiesList; + private object _tweenObject; + private PropertyInfo _propertyInfo; // Create an property info instance so that a new one isn't constantly created. + private object _methodObject; + private object[] _methodArgs; + private MethodInfo _methodInfo; + private float _duration = 0; + private float _elapsedTime = 0; + private float[] _initialValues; + private bool _tweenTo; + private Easing _ease; + private bool _runEndHandler; + private bool _paused; + private bool m_isType; // Flag to determine if the tweenedObject passed in is a Type or not. (For static classes) + + private bool _active; + public bool CheckedOut; + + public bool UseTicks = false; + private float m_delayTime = 0; + private float m_elapsedDelayTime = 0; + + public TweenObject() + { + _runEndHandler = false; + _paused = false; + } + + public void SetValues(object tweenObject, float duration, Easing ease, bool tweenTo, string[] properties) + { + if (tweenObject is Type) + m_isType = true; + else + m_isType = false; + + _tweenObject = tweenObject; + _propertiesList = properties; + _duration = duration; + _ease = ease; + _active = true; + _tweenTo = tweenTo; + _elapsedTime = 0; + + _initialValues = new float[_propertiesList.Length / 2]; + + int counter = 0; // Counter is used to go up in the array by 1, since the for loop goes up by 2. + for (int i = 0; i < _propertiesList.Length; i = i + 2) + { + if (properties[i] != "delay") + { + if (m_isType == true) + _propertyInfo = (_tweenObject as Type).GetProperty(_propertiesList[i]); + else + _propertyInfo = _tweenObject.GetType().GetProperty(_propertiesList[i]); + + if (_propertyInfo == null) + throw new Exception("Property " + _propertiesList[i] + " not found on object " + _tweenObject.GetType().ToString()); + _initialValues[counter] = Convert.ToSingle(_propertyInfo.GetValue(_tweenObject, null)); + //Console.WriteLine("test " + counter + " " + _initialValues[counter]); + counter++; + } + else + { + m_delayTime = float.Parse(_propertiesList[i + 1], NumberStyles.Any, Tween.ParserCI); + m_elapsedDelayTime = 0; + } + } + } + + //public void Update(GameTime gameTime) + public void Update(float elapsedTime) + { + //float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds; + + if (_paused == false) + { + if (m_elapsedDelayTime > m_delayTime) // Adds a special "delay" keycode so that tweens can be delayed before running. + { + if (_elapsedTime < _duration) // Means tween is still running. + { + int counter = 0; + for (int i = 0; i < _propertiesList.Length - 1; i = i + 2) + { + if (_propertiesList[i] != "delay") + { + if (m_isType == true) + _propertyInfo = (_tweenObject as Type).GetProperty(_propertiesList[i]); + else + _propertyInfo = _tweenObject.GetType().GetProperty(_propertiesList[i]); + + float value; + if (_tweenTo == true) + value = _ease(_elapsedTime, _initialValues[counter], float.Parse(_propertiesList[i + 1], NumberStyles.Any, Tween.ParserCI) - _initialValues[counter], _duration); + else + value = _ease(_elapsedTime, _initialValues[counter], float.Parse(_propertiesList[i + 1], NumberStyles.Any, Tween.ParserCI), _duration); + if (_propertyInfo.PropertyType == typeof(int)) + _propertyInfo.SetValue(_tweenObject, (int)value, null); + else + _propertyInfo.SetValue(_tweenObject, value, null); + counter++; + } + //Console.WriteLine(_elapsedTime); + } + if (UseTicks == true) + _elapsedTime++; + else + _elapsedTime += elapsedTime; + } + else + { + this.Complete(); + } + } + else + m_elapsedDelayTime += elapsedTime; + } + } + + /// + /// Sets the endhandler for the tween. + /// The method MUST be public, otherwise it will not be invoked at the end of the tween. + /// + public void EndHandler(object methodObject, string functionName, params object[] args) + { + if (methodObject == null) + throw new Exception("methodObject cannot be null"); + + // Type array used to find endhandler that is overloaded. + Type[] typeArray = new Type[args.Length]; + for (int i = 0; i < args.Length; i++) + { + Type argType = args[i] as Type; + if (argType != null) + { + typeArray[i] = argType; + args[i] = null; + } + else + typeArray[i] = args[i].GetType(); + } + + _methodInfo = methodObject.GetType().GetMethod(functionName, typeArray); + + if (_methodInfo == null) + throw new Exception("Function " + functionName + " not found in class " + methodObject.GetType().ToString()); + + _methodObject = methodObject; + _methodArgs = args; + _runEndHandler = true; + } + + // Used for static methods. + public void EndHandler(Type objectType, string functionName, params object[] args) + { + // Type array used to find endhandler that is overloaded. + Type[] typeArray = new Type[args.Length]; + for (int i = 0; i < args.Length; i++) + { + Type argType = args[i] as Type; + if (argType != null) + { + typeArray[i] = argType; + args[i] = null; + } + else + typeArray[i] = args[i].GetType(); + } + + _methodInfo = objectType.GetMethod(functionName, typeArray); + + if (_methodInfo == null) + throw new Exception("Function " + functionName + " not found in class " + objectType.GetType().ToString()); + + _methodObject = null; + _methodArgs = args; + _runEndHandler = true; + } + + public void Complete() + { + int counter = 0; + for (int i = 0; i < _propertiesList.Length - 1; i = i + 2) + { + if (_propertiesList[i] != "delay") + { + if (m_isType == true) + _propertyInfo = (_tweenObject as Type).GetProperty(_propertiesList[i]); + else + _propertyInfo = _tweenObject.GetType().GetProperty(_propertiesList[i]); + + float value; + if (_tweenTo == true) + value = float.Parse(_propertiesList[i + 1], NumberStyles.Any, Tween.ParserCI); + else + value = _initialValues[counter] + float.Parse(_propertiesList[i + 1], NumberStyles.Any, Tween.ParserCI); + _elapsedTime = _duration; + + if (_propertyInfo.PropertyType == typeof(int)) + _propertyInfo.SetValue(_tweenObject, (int)value, null); + else + _propertyInfo.SetValue(_tweenObject, value, null); + counter++; + } + } + + //Console.WriteLine("Tween complete"); + _active = false; + } + + public void RunEndHandler() + { + // Run the tween's end handler. + if (_runEndHandler == true) + { + if (_methodInfo != null) + _methodInfo.Invoke(_methodObject, _methodArgs); + } + } + + public void StopTween(bool runEndHandler) + { + _runEndHandler = runEndHandler; + _active = false; // The tween will be garbage collected on the next update. + } + + public void PauseTween() + { + _paused = true; + } + + public void ResumeTween() + { + _paused = false; + } + + public void Dispose() + { + _tweenObject = null; + _propertyInfo = null; + _methodObject = null; + _methodInfo = null; + if (_methodArgs != null) + Array.Clear(_methodArgs, 0, _methodArgs.Length); + _methodArgs = null; + if (_propertiesList != null) + Array.Clear(_propertiesList, 0,_propertiesList.Length); + _propertiesList = null; + if (_initialValues != null) + Array.Clear(_initialValues, 0, _initialValues.Length); + _initialValues = null; + _active = false; + _elapsedTime = 0; + _duration = 0; + _tweenTo = false; + _ease = new Easing(Ease.Linear.EaseNone); + _runEndHandler = false; + _paused = false; + UseTicks = false; + m_delayTime = 0; + m_elapsedDelayTime = 0; + } + + public bool Active + { + get { return _active; } + } + + public bool Paused + { + get { return _paused; } + } + + public object TweenedObject + { + get { return _tweenObject; } + } + + public bool IsType + { + get { return m_isType; } + } + } +} diff --git a/Tweener/Tweener.csproj b/Tweener/Tweener.csproj new file mode 100644 index 0000000..506d4bb --- /dev/null +++ b/Tweener/Tweener.csproj @@ -0,0 +1,14 @@ + + + + Library + net40 + + + + + {35253CE1-C864-4CD3-8249-4D1319748E8F} + FNA + + +