mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-20 03:16:26 -05:00
Added credits screen.
This commit is contained in:
parent
6b40c30b5c
commit
842153c241
@ -7,6 +7,7 @@
|
|||||||
Narrow,
|
Narrow,
|
||||||
Cancel,
|
Cancel,
|
||||||
Tall,
|
Tall,
|
||||||
|
Short,
|
||||||
// Game UI
|
// Game UI
|
||||||
Skill,
|
Skill,
|
||||||
Run,
|
Run,
|
||||||
|
@ -22,6 +22,7 @@ namespace OpenDiablo2.Common.Enums
|
|||||||
public enum eSceneType
|
public enum eSceneType
|
||||||
{
|
{
|
||||||
MainMenu,
|
MainMenu,
|
||||||
|
Credits,
|
||||||
SelectHeroClass,
|
SelectHeroClass,
|
||||||
SelectCharacter,
|
SelectCharacter,
|
||||||
Game
|
Game
|
||||||
|
@ -13,6 +13,7 @@ namespace OpenDiablo2.Common.Models
|
|||||||
public bool Toggleable { get; internal set; } = false;
|
public bool Toggleable { get; internal set; } = false;
|
||||||
public int BaseFrame { get; internal set; } = 0;
|
public int BaseFrame { get; internal set; } = 0;
|
||||||
public int DisabledFrame { get; internal set; } = -1;
|
public int DisabledFrame { get; internal set; } = -1;
|
||||||
|
public string FontPath { get; internal set; } = ResourcePaths.FontExocet10;
|
||||||
|
|
||||||
public bool IsDarkenedWhenDisabled => DisabledFrame == -1;
|
public bool IsDarkenedWhenDisabled => DisabledFrame == -1;
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ namespace OpenDiablo2.Common.Models
|
|||||||
{eButtonType.Medium, new ButtonLayout{ XSegments = 1, ResourceName=ResourcePaths.MediumButtonBlank, PaletteName = Palettes.Units } },
|
{eButtonType.Medium, new ButtonLayout{ XSegments = 1, ResourceName=ResourcePaths.MediumButtonBlank, PaletteName = Palettes.Units } },
|
||||||
{eButtonType.Narrow, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.NarrowButtonBlank,PaletteName = Palettes.Units } },
|
{eButtonType.Narrow, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.NarrowButtonBlank,PaletteName = Palettes.Units } },
|
||||||
{eButtonType.Tall, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.TallButtonBlank, PaletteName = Palettes.Units } },
|
{eButtonType.Tall, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.TallButtonBlank, PaletteName = Palettes.Units } },
|
||||||
|
{eButtonType.Short, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.ShortButtonBlank, PaletteName = Palettes.Units, FontPath = ResourcePaths.FontExocet10 } },
|
||||||
{eButtonType.Cancel, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.CancelButton,PaletteName = Palettes.Units } },
|
{eButtonType.Cancel, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.CancelButton,PaletteName = Palettes.Units } },
|
||||||
// Minipanel
|
// Minipanel
|
||||||
{eButtonType.MinipanelCharacter, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 0 } },
|
{eButtonType.MinipanelCharacter, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 0 } },
|
||||||
|
@ -30,6 +30,9 @@ namespace OpenDiablo2.Common
|
|||||||
public const string Diablo2LogoBlackLeft = @"data\global\ui\FrontEnd\D2logoBlackLeft.DC6";
|
public const string Diablo2LogoBlackLeft = @"data\global\ui\FrontEnd\D2logoBlackLeft.DC6";
|
||||||
public const string Diablo2LogoBlackRight = @"data\global\ui\FrontEnd\D2logoBlackRight.DC6";
|
public const string Diablo2LogoBlackRight = @"data\global\ui\FrontEnd\D2logoBlackRight.DC6";
|
||||||
|
|
||||||
|
// --- Credits ---
|
||||||
|
public const string CreditsBackground = @"data\global\ui\CharSelect\creditsbckgexpand.dc6";
|
||||||
|
public const string CreditsText = @"data\local\ui\eng\ExpansionCredits.txt";
|
||||||
// --- Character Select Screen ---
|
// --- Character Select Screen ---
|
||||||
public const string CharacterSelectBackground = @"data\global\ui\FrontEnd\charactercreationscreenEXP.dc6";
|
public const string CharacterSelectBackground = @"data\global\ui\FrontEnd\charactercreationscreenEXP.dc6";
|
||||||
public const string CharacterSelectCampfire = @"data\global\ui\FrontEnd\fire.DC6";
|
public const string CharacterSelectCampfire = @"data\global\ui\FrontEnd\fire.DC6";
|
||||||
@ -117,6 +120,7 @@ namespace OpenDiablo2.Common
|
|||||||
public const string MediumButtonBlank = @"data\global\ui\FrontEnd\MediumButtonBlank.dc6";
|
public const string MediumButtonBlank = @"data\global\ui\FrontEnd\MediumButtonBlank.dc6";
|
||||||
public const string CancelButton = @"data\global\ui\FrontEnd\CancelButtonBlank.dc6";
|
public const string CancelButton = @"data\global\ui\FrontEnd\CancelButtonBlank.dc6";
|
||||||
public const string NarrowButtonBlank = @"data\global\ui\FrontEnd\NarrowButtonBlank.dc6";
|
public const string NarrowButtonBlank = @"data\global\ui\FrontEnd\NarrowButtonBlank.dc6";
|
||||||
|
public const string ShortButtonBlank = @"data\global\ui\CharSelect\ShortButtonBlank.dc6";
|
||||||
public const string TextBox2 = @"data\global\ui\FrontEnd\textbox2.dc6";
|
public const string TextBox2 = @"data\global\ui\FrontEnd\textbox2.dc6";
|
||||||
public const string TallButtonBlank = @"data\global\ui\CharSelect\TallButtonBlank.dc6";
|
public const string TallButtonBlank = @"data\global\ui\CharSelect\TallButtonBlank.dc6";
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ namespace OpenDiablo2.Core.UI
|
|||||||
this.mouseInfoProvider = mouseInfoProvider;
|
this.mouseInfoProvider = mouseInfoProvider;
|
||||||
this.musicProvider = soundProvider;
|
this.musicProvider = soundProvider;
|
||||||
|
|
||||||
font = renderWindow.LoadFont(ResourcePaths.FontExocet10, Palettes.Units);
|
font = renderWindow.LoadFont(buttonLayout.FontPath, Palettes.Units);
|
||||||
label = renderWindow.CreateLabel(font);
|
label = renderWindow.CreateLabel(font);
|
||||||
|
|
||||||
sprite = renderWindow.LoadSprite(buttonLayout.ResourceName, buttonLayout.PaletteName, true);
|
sprite = renderWindow.LoadSprite(buttonLayout.ResourceName, buttonLayout.PaletteName, true);
|
||||||
|
@ -45,7 +45,7 @@ namespace OpenDiablo2.SDL2_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string text;
|
private string text = string.Empty;
|
||||||
public string Text
|
public string Text
|
||||||
{
|
{
|
||||||
get => text;
|
get => text;
|
||||||
|
185
OpenDiablo2.Scenes/Credits.cs
Normal file
185
OpenDiablo2.Scenes/Credits.cs
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
using OpenDiablo2.Common;
|
||||||
|
using OpenDiablo2.Common.Attributes;
|
||||||
|
using OpenDiablo2.Common.Enums;
|
||||||
|
using OpenDiablo2.Common.Interfaces;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace OpenDiablo2.Scenes
|
||||||
|
{
|
||||||
|
[Scene(eSceneType.Credits)]
|
||||||
|
public sealed class Credits : IScene
|
||||||
|
{
|
||||||
|
private class LabelItem
|
||||||
|
{
|
||||||
|
public ILabel Label { get; set; }
|
||||||
|
public bool IsHeading { get; set; }
|
||||||
|
public bool Avaiable { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private const float secondsPerCycle = (40f / 1000f);
|
||||||
|
|
||||||
|
private readonly IRenderWindow renderWindow;
|
||||||
|
private readonly ISceneManager sceneManager;
|
||||||
|
private readonly IMPQProvider mpqProvider;
|
||||||
|
|
||||||
|
private bool doneWithCredits = false;
|
||||||
|
private int cyclesTillNextLine = 0;
|
||||||
|
private float cycleTime = 0f;
|
||||||
|
private IFont textFont;
|
||||||
|
private ISprite backgroundSprite;
|
||||||
|
private IButton btnExit;
|
||||||
|
private Stack<string> creditsText;
|
||||||
|
private List<LabelItem> fontLabels = new List<LabelItem>();
|
||||||
|
|
||||||
|
public Credits(
|
||||||
|
IRenderWindow renderWindow,
|
||||||
|
ISceneManager sceneManager,
|
||||||
|
IMPQProvider mpqProvider,
|
||||||
|
Func<eButtonType, IButton> createButton
|
||||||
|
)
|
||||||
|
{
|
||||||
|
this.renderWindow = renderWindow;
|
||||||
|
this.sceneManager = sceneManager;
|
||||||
|
this.mpqProvider = mpqProvider;
|
||||||
|
|
||||||
|
backgroundSprite = renderWindow.LoadSprite(ResourcePaths.CreditsBackground, Palettes.Sky);
|
||||||
|
|
||||||
|
btnExit = createButton(eButtonType.Medium);
|
||||||
|
btnExit.Text = "Exit".ToUpper();
|
||||||
|
btnExit.Location = new Point(20, 550);
|
||||||
|
btnExit.OnActivate = OnActivateClicked;
|
||||||
|
|
||||||
|
textFont = renderWindow.LoadFont(ResourcePaths.FontFormal10, Palettes.Static);
|
||||||
|
|
||||||
|
creditsText = new Stack<string>((
|
||||||
|
File.ReadAllLines(Path.Combine(Path.GetDirectoryName(Environment.GetCommandLineArgs().First()), "credits.txt"))
|
||||||
|
.Concat(mpqProvider.GetTextFile(ResourcePaths.CreditsText))
|
||||||
|
).Reverse());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnActivateClicked()
|
||||||
|
=> sceneManager.ChangeScene(eSceneType.MainMenu);
|
||||||
|
|
||||||
|
private void AddNextItem()
|
||||||
|
{
|
||||||
|
if (!creditsText.Any())
|
||||||
|
{
|
||||||
|
doneWithCredits = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var text = creditsText.Pop().Trim();
|
||||||
|
if (text.Trim().Length == 0)
|
||||||
|
{
|
||||||
|
cyclesTillNextLine = 18;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var isHeading = text.StartsWith("*");
|
||||||
|
var isNextHeading = creditsText.Any() && creditsText.Peek().StartsWith("*");
|
||||||
|
var isNextSpace = creditsText.Any() && creditsText.Peek().Trim().Length == 0;
|
||||||
|
var label = GetNewFontLabel(isHeading);
|
||||||
|
label.Text = isHeading ? text.Substring(1) : text;
|
||||||
|
var isDoubled = false;
|
||||||
|
if (!isHeading && !isNextHeading && !isNextSpace)
|
||||||
|
{
|
||||||
|
isDoubled = true;
|
||||||
|
|
||||||
|
// Gotta go side by side
|
||||||
|
label.Location = new Point(390 - label.TextArea.Width, 605);
|
||||||
|
|
||||||
|
var text2 = creditsText.Pop().Trim();
|
||||||
|
isNextHeading = creditsText.Any() && creditsText.Peek().StartsWith("*");
|
||||||
|
var label2 = GetNewFontLabel(isHeading);
|
||||||
|
label2.Text = text2;
|
||||||
|
|
||||||
|
label2.Location = new Point(410, 605);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
label.Location = new Point(400 - (label.TextArea.Width / 2), 605);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isHeading && isNextHeading)
|
||||||
|
cyclesTillNextLine = 40;
|
||||||
|
else if (isNextHeading)
|
||||||
|
cyclesTillNextLine = isDoubled ? 40 : 70;
|
||||||
|
else if (isHeading)
|
||||||
|
cyclesTillNextLine = 40;
|
||||||
|
else
|
||||||
|
cyclesTillNextLine = 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Render()
|
||||||
|
{
|
||||||
|
renderWindow.Draw(backgroundSprite, 4, 3, 0);
|
||||||
|
btnExit.Render();
|
||||||
|
foreach (var label in fontLabels.Where(x => !x.Avaiable).Select(x => x.Label))
|
||||||
|
renderWindow.Draw(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(long ms)
|
||||||
|
{
|
||||||
|
|
||||||
|
cycleTime += (ms / 1000f);
|
||||||
|
while (cycleTime >= secondsPerCycle)
|
||||||
|
{
|
||||||
|
cycleTime -= secondsPerCycle;
|
||||||
|
if (!doneWithCredits && (--cyclesTillNextLine <= 0))
|
||||||
|
AddNextItem();
|
||||||
|
|
||||||
|
foreach (var fontLabel in fontLabels.Where(x => !x.Avaiable))
|
||||||
|
{
|
||||||
|
if (fontLabel.Label.Location.Y - 1 <= -15)
|
||||||
|
{
|
||||||
|
fontLabel.Avaiable = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fontLabel.Label.Location = new Point(fontLabel.Label.Location.X, fontLabel.Label.Location.Y - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btnExit.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ILabel GetNewFontLabel(bool isHeading)
|
||||||
|
{
|
||||||
|
var labelItem = fontLabels.FirstOrDefault(x => x.Avaiable && x.IsHeading == isHeading);
|
||||||
|
if (labelItem != null)
|
||||||
|
{
|
||||||
|
labelItem.Avaiable = false;
|
||||||
|
return labelItem.Label;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newLabelItem = new LabelItem
|
||||||
|
{
|
||||||
|
Avaiable = false,
|
||||||
|
IsHeading = isHeading,
|
||||||
|
Label = renderWindow.CreateLabel(textFont)
|
||||||
|
};
|
||||||
|
|
||||||
|
newLabelItem.Label.TextColor = isHeading
|
||||||
|
? Color.FromArgb(255, 88, 82)
|
||||||
|
: Color.FromArgb(198, 178, 150);
|
||||||
|
|
||||||
|
fontLabels.Add(newLabelItem);
|
||||||
|
return newLabelItem.Label;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
backgroundSprite?.Dispose();
|
||||||
|
|
||||||
|
foreach (var labelItem in fontLabels)
|
||||||
|
labelItem.Label.Dispose();
|
||||||
|
|
||||||
|
textFont.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -34,7 +34,7 @@ namespace OpenDiablo2.Scenes
|
|||||||
private readonly ISprite backgroundSprite, diabloLogoLeft, diabloLogoRight, diabloLogoLeftBlack, diabloLogoRightBlack;
|
private readonly ISprite backgroundSprite, diabloLogoLeft, diabloLogoRight, diabloLogoLeftBlack, diabloLogoRightBlack;
|
||||||
private readonly IFont labelFont;
|
private readonly IFont labelFont;
|
||||||
private readonly ILabel versionLabel, urlLabel;
|
private readonly ILabel versionLabel, urlLabel;
|
||||||
private readonly IButton btnSinglePlayer, btnExit, btnWebsite;
|
private readonly IButton btnSinglePlayer, btnExit, btnWebsite, btnCredits;
|
||||||
|
|
||||||
public MainMenu(
|
public MainMenu(
|
||||||
IRenderWindow renderWindow,
|
IRenderWindow renderWindow,
|
||||||
@ -42,8 +42,7 @@ namespace OpenDiablo2.Scenes
|
|||||||
IResourceManager resourceManager,
|
IResourceManager resourceManager,
|
||||||
ISoundProvider soundProvider,
|
ISoundProvider soundProvider,
|
||||||
IMPQProvider mpqProvider,
|
IMPQProvider mpqProvider,
|
||||||
Func<eButtonType, IButton> createButton,
|
Func<eButtonType, IButton> createButton
|
||||||
Func<eSceneType, IScene> getScene // Temporary until SDL load functions are sped up
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.renderWindow = renderWindow;
|
this.renderWindow = renderWindow;
|
||||||
@ -64,7 +63,7 @@ namespace OpenDiablo2.Scenes
|
|||||||
|
|
||||||
btnWebsite = createButton(eButtonType.Wide);
|
btnWebsite = createButton(eButtonType.Wide);
|
||||||
btnWebsite.Text = "Visit Github".ToUpper();
|
btnWebsite.Text = "Visit Github".ToUpper();
|
||||||
btnWebsite.Location = new Point(264, 460);
|
btnWebsite.Location = new Point(264, 330);
|
||||||
btnWebsite.OnActivate = OnVisitWebsiteClicked;
|
btnWebsite.OnActivate = OnVisitWebsiteClicked;
|
||||||
|
|
||||||
btnExit = createButton(eButtonType.Wide);
|
btnExit = createButton(eButtonType.Wide);
|
||||||
@ -72,8 +71,13 @@ namespace OpenDiablo2.Scenes
|
|||||||
btnExit.Location = new Point(264, 500);
|
btnExit.Location = new Point(264, 500);
|
||||||
btnExit.OnActivate = OnExitClicked;
|
btnExit.OnActivate = OnExitClicked;
|
||||||
|
|
||||||
|
btnCredits = createButton(eButtonType.Short);
|
||||||
|
btnCredits.Text = "Credits".ToUpper(); /* TODO: We apparently need a 'half font' option... */
|
||||||
|
btnCredits.Location = new Point(264, 470);
|
||||||
|
btnCredits.OnActivate = OnCreditsClicked;
|
||||||
|
|
||||||
labelFont = renderWindow.LoadFont(ResourcePaths.Font16, Palettes.Static);
|
labelFont = renderWindow.LoadFont(ResourcePaths.Font16, Palettes.Static);
|
||||||
versionLabel = renderWindow.CreateLabel(labelFont, new Point(50, 555), "v0.01 Pre-Alpha");
|
versionLabel = renderWindow.CreateLabel(labelFont, new Point(50, 555), "v0.02 Pre-Alpha");
|
||||||
urlLabel = renderWindow.CreateLabel(labelFont, new Point(50, 569), "https://github.com/essial/OpenDiablo2/");
|
urlLabel = renderWindow.CreateLabel(labelFont, new Point(50, 569), "https://github.com/essial/OpenDiablo2/");
|
||||||
urlLabel.TextColor = Color.Magenta;
|
urlLabel.TextColor = Color.Magenta;
|
||||||
|
|
||||||
@ -81,6 +85,9 @@ namespace OpenDiablo2.Scenes
|
|||||||
soundProvider.PlaySong();
|
soundProvider.PlaySong();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnCreditsClicked()
|
||||||
|
=> sceneManager.ChangeScene(eSceneType.Credits);
|
||||||
|
|
||||||
private void OnVisitWebsiteClicked()
|
private void OnVisitWebsiteClicked()
|
||||||
=> System.Diagnostics.Process.Start("https://github.com/essial/OpenDiablo2/");
|
=> System.Diagnostics.Process.Start("https://github.com/essial/OpenDiablo2/");
|
||||||
|
|
||||||
@ -103,6 +110,7 @@ namespace OpenDiablo2.Scenes
|
|||||||
btnSinglePlayer.Render();
|
btnSinglePlayer.Render();
|
||||||
btnWebsite.Render();
|
btnWebsite.Render();
|
||||||
btnExit.Render();
|
btnExit.Render();
|
||||||
|
btnCredits.Render();
|
||||||
|
|
||||||
//wideButton.Location = new Point(264, 290);
|
//wideButton.Location = new Point(264, 290);
|
||||||
//renderWindow.Draw(wideButton, 2, 1, 0);
|
//renderWindow.Draw(wideButton, 2, 1, 0);
|
||||||
@ -118,6 +126,7 @@ namespace OpenDiablo2.Scenes
|
|||||||
btnSinglePlayer.Update();
|
btnSinglePlayer.Update();
|
||||||
btnWebsite.Update();
|
btnWebsite.Update();
|
||||||
btnExit.Update();
|
btnExit.Update();
|
||||||
|
btnCredits.Update();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="AutofacModule.cs" />
|
<Compile Include="AutofacModule.cs" />
|
||||||
|
<Compile Include="Credits.cs" />
|
||||||
<Compile Include="Game.cs" />
|
<Compile Include="Game.cs" />
|
||||||
<Compile Include="MainMenu.cs" />
|
<Compile Include="MainMenu.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
@ -135,5 +135,10 @@
|
|||||||
<Install>false</Install>
|
<Install>false</Install>
|
||||||
</BootstrapperPackage>
|
</BootstrapperPackage>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="credits.txt">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
16
OpenDiablo2/credits.txt
Normal file
16
OpenDiablo2/credits.txt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
*OpenDiablo2
|
||||||
|
An open source re-implementation of Diablo 2 in C#
|
||||||
|
|
||||||
|
THIS GAME IS NEITHER DEVELOPED BY, NOR ENDORSED
|
||||||
|
|
||||||
|
BY BLIZZARD OR ITS PARENT COMPANY ACTIVISION.
|
||||||
|
|
||||||
|
*Developers:
|
||||||
|
erexo
|
||||||
|
essial
|
||||||
|
grazz
|
||||||
|
Mirey
|
||||||
|
nicholasdechiara
|
||||||
|
wtfblub
|
||||||
|
|
||||||
|
*----- Original Diablo2 Credits -----
|
Loading…
Reference in New Issue
Block a user