antag definitions + servant background
This commit is contained in:
@@ -169,7 +169,7 @@ public sealed partial class AntagSelectionSystem
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (def.PrefRoles.Count == 0)
|
if (def.PrefRoles.Count == 0)
|
||||||
return false;
|
return true; //CP14 - If definition dont have PrefRoles, everyone can be this antag
|
||||||
|
|
||||||
var pref = (HumanoidCharacterProfile) _pref.GetPreferences(session.UserId).SelectedCharacter;
|
var pref = (HumanoidCharacterProfile) _pref.GetPreferences(session.UserId).SelectedCharacter;
|
||||||
return pref.AntagPreferences.Any(p => def.PrefRoles.Contains(p));
|
return pref.AntagPreferences.Any(p => def.PrefRoles.Contains(p));
|
||||||
|
|||||||
@@ -393,7 +393,7 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
|
|||||||
|
|
||||||
if (!antagEnt.HasValue)
|
if (!antagEnt.HasValue)
|
||||||
{
|
{
|
||||||
var getEntEv = new AntagSelectEntityEvent(session, ent);
|
var getEntEv = new AntagSelectEntityEvent(session, ent, def); //CP14 def added
|
||||||
RaiseLocalEvent(ent, ref getEntEv, true);
|
RaiseLocalEvent(ent, ref getEntEv, true);
|
||||||
antagEnt = getEntEv.Entity;
|
antagEnt = getEntEv.Entity;
|
||||||
}
|
}
|
||||||
@@ -416,7 +416,7 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
|
|||||||
// Therefore any component subscribing to this has to make sure both subscriptions return the same value
|
// Therefore any component subscribing to this has to make sure both subscriptions return the same value
|
||||||
// or the ghost role raffle location preview will be wrong.
|
// or the ghost role raffle location preview will be wrong.
|
||||||
|
|
||||||
var getPosEv = new AntagSelectLocationEvent(session, ent);
|
var getPosEv = new AntagSelectLocationEvent(session, ent, def); //CP14 def added
|
||||||
RaiseLocalEvent(ent, ref getPosEv, true);
|
RaiseLocalEvent(ent, ref getPosEv, true);
|
||||||
if (getPosEv.Handled)
|
if (getPosEv.Handled)
|
||||||
{
|
{
|
||||||
@@ -603,7 +603,7 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
|
|||||||
/// Only raised if the selected player's current entity is invalid.
|
/// Only raised if the selected player's current entity is invalid.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public record struct AntagSelectEntityEvent(ICommonSession? Session, Entity<AntagSelectionComponent> GameRule)
|
public record struct AntagSelectEntityEvent(ICommonSession? Session, Entity<AntagSelectionComponent> GameRule, AntagSelectionDefinition? Def = null) //CP14 Definition added
|
||||||
{
|
{
|
||||||
public readonly ICommonSession? Session = Session;
|
public readonly ICommonSession? Session = Session;
|
||||||
|
|
||||||
@@ -616,7 +616,7 @@ public record struct AntagSelectEntityEvent(ICommonSession? Session, Entity<Anta
|
|||||||
/// Event raised on a game rule entity to determine the location for the antagonist.
|
/// Event raised on a game rule entity to determine the location for the antagonist.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public record struct AntagSelectLocationEvent(ICommonSession? Session, Entity<AntagSelectionComponent> GameRule)
|
public record struct AntagSelectLocationEvent(ICommonSession? Session, Entity<AntagSelectionComponent> GameRule, AntagSelectionDefinition? Def = null) //CP14 Definition added
|
||||||
{
|
{
|
||||||
public readonly ICommonSession? Session = Session;
|
public readonly ICommonSession? Session = Session;
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,12 @@ public sealed partial class AntagSelectionComponent : Component
|
|||||||
[DataDefinition]
|
[DataDefinition]
|
||||||
public partial struct AntagSelectionDefinition()
|
public partial struct AntagSelectionDefinition()
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// CP14 - unique keys that allow you to separate logic in AfterAntagEntitySelectedEvent, depending on the key
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public string DefinitionKey = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of antagonist roles that are used for selecting which players will be antagonists.
|
/// A list of antagonist roles that are used for selecting which players will be antagonists.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,23 +1,84 @@
|
|||||||
using Content.Server._CP14.GameTicking.Rules.Components;
|
using Content.Server._CP14.GameTicking.Rules.Components;
|
||||||
|
using Content.Server.Antag;
|
||||||
using Content.Server.GameTicking.Rules;
|
using Content.Server.GameTicking.Rules;
|
||||||
using Content.Shared.GameTicking.Components;
|
using Content.Shared.GameTicking.Components;
|
||||||
|
using Content.Shared.Objectives.Systems;
|
||||||
|
using Content.Shared.Players;
|
||||||
|
|
||||||
namespace Content.Server._CP14.GameTicking.Rules;
|
namespace Content.Server._CP14.GameTicking.Rules;
|
||||||
|
|
||||||
public sealed class CP14LurkerHuntRule : GameRuleSystem<CP14LurkerHuntRuleComponent>
|
public sealed class CP14LurkerHuntRule : GameRuleSystem<CP14LurkerHuntRuleComponent>
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly SharedObjectivesSystem _objectives = default!;
|
||||||
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||||
|
|
||||||
|
private const string LurkerDefinitionKey = "Lurker";
|
||||||
|
private const string HunterDefinitionKey = "Hunter";
|
||||||
|
private const string VictimDefinitionKey = "Victim";
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<CP14LurkerHuntRuleComponent, AfterAntagEntitySelectedEvent>(AfterRoleSelected);
|
||||||
|
SubscribeLocalEvent<CP14LurkerHuntRuleComponent, AntagSelectLocationEvent>(OnAntagSelectLocation);
|
||||||
|
SubscribeLocalEvent<CP14LurkerHuntRuleComponent, AntagSelectEntityEvent>(OnAntagSelectEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAntagSelectEntity(Entity<CP14LurkerHuntRuleComponent> ent, ref AntagSelectEntityEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (args.Def is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (args.Def.Value.DefinitionKey == LurkerDefinitionKey)
|
||||||
|
{
|
||||||
|
args.Entity = Spawn(ent.Comp.LurkerProto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAntagSelectLocation(Entity<CP14LurkerHuntRuleComponent> ent, ref AntagSelectLocationEvent args)
|
||||||
|
{
|
||||||
|
if (args.Def is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//Spawn lurker on random position on the map
|
||||||
|
if (args.Def.Value.DefinitionKey == LurkerDefinitionKey && TryFindRandomTile(out _, out _, out _, out var coords))
|
||||||
|
{
|
||||||
|
args.Coordinates.Add(_transform.ToMapCoordinates(coords));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AfterRoleSelected(Entity<CP14LurkerHuntRuleComponent> ent, ref AfterAntagEntitySelectedEvent args)
|
||||||
|
{
|
||||||
|
if (args.Session is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var mind = args.Session.GetMind();
|
||||||
|
|
||||||
|
if (mind is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (args.Def.DefinitionKey)
|
||||||
|
{
|
||||||
|
case LurkerDefinitionKey:
|
||||||
|
ent.Comp.Lurker = mind;
|
||||||
|
break;
|
||||||
|
case VictimDefinitionKey:
|
||||||
|
ent.Comp.Victims.Add(mind.Value);
|
||||||
|
break;
|
||||||
|
case HunterDefinitionKey:
|
||||||
|
ent.Comp.Hunters.Add(mind.Value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void Added(EntityUid uid, CP14LurkerHuntRuleComponent component, GameRuleComponent gameRule, GameRuleAddedEvent args)
|
protected override void Added(EntityUid uid, CP14LurkerHuntRuleComponent component, GameRuleComponent gameRule, GameRuleAddedEvent args)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Started(EntityUid uid,
|
protected override void Started(EntityUid uid,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Content.Shared._CP14.Procedural.Prototypes;
|
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Server._CP14.GameTicking.Rules.Components;
|
namespace Content.Server._CP14.GameTicking.Rules.Components;
|
||||||
@@ -6,4 +5,15 @@ namespace Content.Server._CP14.GameTicking.Rules.Components;
|
|||||||
[RegisterComponent, Access(typeof(CP14LurkerHuntRule))]
|
[RegisterComponent, Access(typeof(CP14LurkerHuntRule))]
|
||||||
public sealed partial class CP14LurkerHuntRuleComponent : Component
|
public sealed partial class CP14LurkerHuntRuleComponent : Component
|
||||||
{
|
{
|
||||||
|
[DataField]
|
||||||
|
public EntProtoId LurkerProto = "CP14MobLurker";
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public EntityUid? Lurker;
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public HashSet<EntityUid> Hunters = new();
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public HashSet<EntityUid> Victims = new();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared._CP14.Background;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
public sealed partial class CP14BackgroundMerkasServantComponent : Component
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
cp14-bloodmoon-raising = The moon in the sky is stained with blood. The next night will be terrible.
|
|
||||||
cp14-bloodmoon-start = The blood moon shines in full force, enslaving minds.
|
|
||||||
cp14-bloodmoon-end = The blood moon sets over the horizon, losing its power.
|
|
||||||
|
|
||||||
cp14-bloodmoon-curse-removed = The curse of the blood moon is dispelled.
|
|
||||||
cp14-bloodmoon-curse-examined = [color=red]The aura of the blood moon hovers around this creature. Be careful, for his mind is unstable.[/color]
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
cp14-lurker-briefing = In the past, you made a pact with Darkness for power and influence. Now it demands its payment. You must reap the harvest from those chosen by Lady Darkness. Use your Lurker form, to turn pitiful mortals into obedient servants of darkness.
|
||||||
|
cp14-lurker-victim-briefing = Shadows gather around you. Whispers call your name in the darkness. Dark entities are out hunting, and you are their prey. What has attracted their attention, that Darkness itself reaches out to embrace you?
|
||||||
|
cp14-lurker-hunter-briefing = Your duty as a servant of Merkas has brought you to these lands, where Darkness has set its sights on mortals. Protect the people by destroying the cursed creatures lurking in the darkness.
|
||||||
@@ -21,4 +21,9 @@ cp14-trait-snoring-name = Loud snoring
|
|||||||
cp14-trait-snoring-desc = It is simply impossible to sleep next to you because you snore terribly loudly at everything.
|
cp14-trait-snoring-desc = It is simply impossible to sleep next to you because you snore terribly loudly at everything.
|
||||||
|
|
||||||
cp14-trait-mana-wasting-name = Magical mediocrity.
|
cp14-trait-mana-wasting-name = Magical mediocrity.
|
||||||
cp14-trait-mana-wasting-desc = Fate has decreed that magic is just an empty sound for you. You are unable to store or use magical energy.
|
cp14-trait-mana-wasting-desc = Fate has decreed that magic is just an empty sound for you. You are unable to store or use magical energy.
|
||||||
|
|
||||||
|
# Backgrounds
|
||||||
|
|
||||||
|
cp14-trait-bg-merkas-servant-name = Servant of the Light Merkas
|
||||||
|
cp14-trait-bg-merkas-servant-desc = Your past is closely tied to serving Merkas, the god of light, and his dogma is still strong in your mind. You feel compelled to help those in need, banish darkness, and bring light to the hearts of those around you.
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
cp14-bloodmoon-raising = Луна на небосводе обагривается кровью. Следующая ночь будет ужасной.
|
|
||||||
cp14-bloodmoon-start = Кровавая луна сияет в полную силу, порабощая разумы.
|
|
||||||
cp14-bloodmoon-end = Кровавая луна заходит за горизонт, теряя свою силу.
|
|
||||||
|
|
||||||
cp14-bloodmoon-curse-removed = Проклятье кровавой луны развеивается.
|
|
||||||
cp14-bloodmoon-curse-examined = [color=red]Аура кровавой луны витает вокруг этого существа. Будьте осторожны, ибо его разум нестабилен.[/color]
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
cp14-lurker-briefing = прошлом вы заключили контракт с Тьмой ради силы и власти. Теперь она требует свою плату. Вы должны собрать жатву с тех, кого укажет госпожа Тьма. Используйте свой теневой облик Таящегося, чтобы обратить жалких смертных в покорных слуг тьмы.
|
||||||
|
cp14-lurker-victim-briefing = Тени сгущаются рядом с вами. В темноте слышны шепоты, зовущие по имени. Темные сущности выходят на охоту, и их цель — вы. Чем вы привлекли их внимание, что сама Тьма протягивает к вам свои объятия?
|
||||||
|
cp14-lurker-hunter-briefing = Ваш долг служителя Меркаса привел вас в эти земли, где Тьма устроила свою охоту на смертных. Защитите людей, уничтожив проклятых созданий, таящихся во мраке.
|
||||||
@@ -21,4 +21,9 @@ cp14-trait-snoring-name = Громкий храп
|
|||||||
cp14-trait-snoring-desc = Спать рядом с вами просто невозможно, потому что во все вы жутко громко храпите.
|
cp14-trait-snoring-desc = Спать рядом с вами просто невозможно, потому что во все вы жутко громко храпите.
|
||||||
|
|
||||||
cp14-trait-mana-wasting-name = Магическая бездарность
|
cp14-trait-mana-wasting-name = Магическая бездарность
|
||||||
cp14-trait-mana-wasting-desc = Судьба распорядилась так, что магия для вас - лишь пустой звук. Вы не способны ни накапливать, ни использовать магическую энергию.
|
cp14-trait-mana-wasting-desc = Судьба распорядилась так, что магия для вас - лишь пустой звук. Вы не способны ни накапливать, ни использовать магическую энергию.
|
||||||
|
|
||||||
|
# Backgrounds
|
||||||
|
|
||||||
|
cp14-trait-bg-merkas-servant-name = Служитель светлого Меркаса
|
||||||
|
cp14-trait-bg-merkas-servant-desc = Ваше прошлое тесно связано с служением Меркасу - богу света, и его догмы все еще сильны в вашем сознании. Вы считаете себя должным помогать нуждающимся, изгонять тьму и нести свет в сердца окружающих.
|
||||||
@@ -21,3 +21,23 @@
|
|||||||
- state: green
|
- state: green
|
||||||
- sprite: _CP14/Mobs/Pets/rat.rsi
|
- sprite: _CP14/Mobs/Pets/rat.rsi
|
||||||
state: rat
|
state: rat
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
categories: [ HideSpawnMenu, Spawner ]
|
||||||
|
parent: BaseAntagSpawner
|
||||||
|
id: CP14SpawnPointLurker
|
||||||
|
components:
|
||||||
|
- type: GhostRole
|
||||||
|
name: cp14-ghost-role-information-name-lurker
|
||||||
|
description: cp14-ghost-role-information-description-lurker
|
||||||
|
rules: cp14-ghost-role-information-rules-demiplane #TODO
|
||||||
|
mindRoles:
|
||||||
|
- CP14MindRoleDemiplaneAntag
|
||||||
|
raffle:
|
||||||
|
settings: default
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Markers/jobs.rsi
|
||||||
|
layers:
|
||||||
|
- state: green
|
||||||
|
- sprite: _CP14/Mobs/Monster/lurker.rsi
|
||||||
|
state: live
|
||||||
@@ -5,6 +5,38 @@
|
|||||||
- type: CP14StationAdditionalModifierRule
|
- type: CP14StationAdditionalModifierRule
|
||||||
modifiers:
|
modifiers:
|
||||||
- Geodes
|
- Geodes
|
||||||
- Geodes
|
- type: CP14LurkerHuntRule
|
||||||
- Geodes
|
- type: GameRule
|
||||||
- Geodes
|
minPlayers: 7
|
||||||
|
- type: AntagSelection
|
||||||
|
selectionTime: PrePlayerSpawn
|
||||||
|
definitions:
|
||||||
|
- definitionKey: Lurker
|
||||||
|
spawnerPrototype: CP14SpawnPointLurker
|
||||||
|
min: 1
|
||||||
|
max: 1
|
||||||
|
blacklist:
|
||||||
|
components:
|
||||||
|
- CP14BackgroundMerkasServant
|
||||||
|
briefing:
|
||||||
|
text: cp14-lurker-briefing
|
||||||
|
- definitionKey: Victim
|
||||||
|
lateJoinAdditional: true
|
||||||
|
min: 1
|
||||||
|
max: 3
|
||||||
|
playerRatio: 3
|
||||||
|
blacklist:
|
||||||
|
components:
|
||||||
|
- CP14BackgroundMerkasServant
|
||||||
|
briefing:
|
||||||
|
text: cp14-lurker-victim-briefing
|
||||||
|
- definitionKey: Hunter
|
||||||
|
lateJoinAdditional: true
|
||||||
|
min: 1
|
||||||
|
max: 3
|
||||||
|
playerRatio: 3
|
||||||
|
whitelist:
|
||||||
|
components:
|
||||||
|
- CP14BackgroundMerkasServant
|
||||||
|
briefing:
|
||||||
|
text: cp14-lurker-hunter-briefing
|
||||||
8
Resources/Prototypes/_CP14/Traits/backgrounds.yml
Normal file
8
Resources/Prototypes/_CP14/Traits/backgrounds.yml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
- type: trait
|
||||||
|
id: CP14BackgroundMerkasServant
|
||||||
|
name: cp14-trait-bg-merkas-servant-name
|
||||||
|
description: cp14-trait-bg-merkas-servant-desc
|
||||||
|
category: CP14Background
|
||||||
|
cost: 1
|
||||||
|
components:
|
||||||
|
- type: CP14BackgroundMerkasServant
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
- type: traitCategory
|
- type: traitCategory
|
||||||
id: CP14PhysicalTraits
|
id: CP14PhysicalTraits
|
||||||
name: cp14-trait-category-physical
|
name: cp14-trait-category-physical
|
||||||
maxTraitPoints: 1
|
maxTraitPoints: 2
|
||||||
|
|
||||||
- type: traitCategory
|
- type: traitCategory
|
||||||
id: CP14Background
|
id: CP14Background
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
description: cp14-trait-blindness-desc
|
description: cp14-trait-blindness-desc
|
||||||
#traitGear: WhiteCane
|
#traitGear: WhiteCane
|
||||||
category: CP14PhysicalTraits
|
category: CP14PhysicalTraits
|
||||||
cost: -2
|
cost: 2
|
||||||
whitelist:
|
whitelist:
|
||||||
components:
|
components:
|
||||||
- Blindable
|
- Blindable
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
name: cp14-trait-mana-wasting-name
|
name: cp14-trait-mana-wasting-name
|
||||||
description: cp14-trait-mana-wasting-desc
|
description: cp14-trait-mana-wasting-desc
|
||||||
category: CP14PhysicalTraits
|
category: CP14PhysicalTraits
|
||||||
cost: -2
|
cost: 2
|
||||||
whitelist:
|
whitelist:
|
||||||
components:
|
components:
|
||||||
- CP14MagicEnergyContainer
|
- CP14MagicEnergyContainer
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
description: cp14-trait-poor-vision-desc
|
description: cp14-trait-poor-vision-desc
|
||||||
#traitGear: ClothingEyesGlasses
|
#traitGear: ClothingEyesGlasses
|
||||||
category: CP14PhysicalTraits
|
category: CP14PhysicalTraits
|
||||||
cost: -1
|
cost: 1
|
||||||
whitelist:
|
whitelist:
|
||||||
components:
|
components:
|
||||||
- Blindable
|
- Blindable
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
name: cp14-trait-narcolepsy-name
|
name: cp14-trait-narcolepsy-name
|
||||||
description: cp14-trait-narcolepsy-desc
|
description: cp14-trait-narcolepsy-desc
|
||||||
category: CP14PhysicalTraits
|
category: CP14PhysicalTraits
|
||||||
cost: -1
|
cost: 1
|
||||||
components:
|
components:
|
||||||
- type: Narcolepsy
|
- type: Narcolepsy
|
||||||
timeBetweenIncidents: 300, 600
|
timeBetweenIncidents: 300, 600
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
id: CP14Muted
|
id: CP14Muted
|
||||||
name: cp14-trait-muted-name
|
name: cp14-trait-muted-name
|
||||||
description: cp14-trait-muted-desc
|
description: cp14-trait-muted-desc
|
||||||
cost: -1
|
cost: 1
|
||||||
category: CP14PhysicalTraits
|
category: CP14PhysicalTraits
|
||||||
components:
|
components:
|
||||||
- type: Muted
|
- type: Muted
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
id: CP14PainNumbness
|
id: CP14PainNumbness
|
||||||
name: trait-painnumbness-name
|
name: trait-painnumbness-name
|
||||||
description: trait-painnumbness-desc
|
description: trait-painnumbness-desc
|
||||||
cost: -1
|
cost: 1
|
||||||
category: CP14PhysicalTraits
|
category: CP14PhysicalTraits
|
||||||
components:
|
components:
|
||||||
- type: PainNumbness
|
- type: PainNumbness
|
||||||
|
|||||||
Reference in New Issue
Block a user