mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-25 06:35:30 +00:00
Merge remote-tracking branch 'scrawl/armorrating' into next
This commit is contained in:
commit
6ef754c451
@ -82,7 +82,7 @@ namespace MWBase
|
||||
|
||||
virtual int getDerivedDisposition(const MWWorld::Ptr& ptr) = 0;
|
||||
///< Calculate the diposition of an NPC toward the player.
|
||||
|
||||
|
||||
virtual int countDeaths (const std::string& id) const = 0;
|
||||
///< Return the number of deaths for actors with the given ID.
|
||||
|
||||
|
@ -191,6 +191,12 @@ namespace MWClass
|
||||
return info;
|
||||
}
|
||||
|
||||
float Creature::getArmorRating (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
/// \todo add Shield magic effect magnitude here, controlled by a GMST (Vanilla vs MCP behaviour)
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
float Creature::getCapacity (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
|
||||
@ -203,9 +209,9 @@ namespace MWClass
|
||||
|
||||
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
|
||||
|
||||
weight -= stats.getMagicEffects().get (MWMechanics::EffectKey (8)).mMagnitude; // feather
|
||||
weight -= stats.getMagicEffects().get (MWMechanics::EffectKey (ESM::MagicEffect::Feather)).mMagnitude;
|
||||
|
||||
weight += stats.getMagicEffects().get (MWMechanics::EffectKey (7)).mMagnitude; // burden
|
||||
weight += stats.getMagicEffects().get (MWMechanics::EffectKey (ESM::MagicEffect::Burden)).mMagnitude;
|
||||
|
||||
if (weight<0)
|
||||
weight = 0;
|
||||
|
@ -54,6 +54,9 @@ namespace MWClass
|
||||
///< Returns total weight of objects inside this object (including modifications from magic
|
||||
/// effects). Throws an exception, if the object can't hold other objects.
|
||||
|
||||
virtual float getArmorRating (const MWWorld::Ptr& ptr) const;
|
||||
///< @return combined armor rating of this actor
|
||||
|
||||
virtual bool isEssential (const MWWorld::Ptr& ptr) const;
|
||||
///< Is \a ptr essential? (i.e. may losing \a ptr make the game unwinnable)
|
||||
|
||||
|
@ -471,9 +471,9 @@ namespace MWClass
|
||||
|
||||
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
|
||||
|
||||
weight -= stats.getMagicEffects().get (MWMechanics::EffectKey (8)).mMagnitude; // feather
|
||||
weight -= stats.getMagicEffects().get (MWMechanics::EffectKey (ESM::MagicEffect::Feather)).mMagnitude;
|
||||
|
||||
weight += stats.getMagicEffects().get (MWMechanics::EffectKey (7)).mMagnitude; // burden
|
||||
weight += stats.getMagicEffects().get (MWMechanics::EffectKey (ESM::MagicEffect::Burden)).mMagnitude;
|
||||
|
||||
if (weight<0)
|
||||
weight = 0;
|
||||
@ -505,6 +505,55 @@ namespace MWClass
|
||||
stats.useSkill (skill, *class_, usageType);
|
||||
}
|
||||
|
||||
float Npc::getArmorRating (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore(ptr);
|
||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
|
||||
int ratings[MWWorld::InventoryStore::Slots];
|
||||
|
||||
int iBaseArmorSkill = gmst.find("iBaseArmorSkill")->getInt();
|
||||
float fUnarmoredBase1 = gmst.find("fUnarmoredBase1")->getFloat();
|
||||
float fUnarmoredBase2 = gmst.find("fUnarmoredBase2")->getFloat();
|
||||
int unarmoredSkill = MWWorld::Class::get(ptr).getNpcStats(ptr).getSkill(ESM::Skill::Unarmored).getModified();
|
||||
|
||||
for (int i = 0; i < MWWorld::InventoryStore::Slots; ++i)
|
||||
{
|
||||
MWWorld::ContainerStoreIterator it = invStore.getSlot(i);
|
||||
if (it == invStore.end() || it->getTypeName() != typeid(ESM::Armor).name())
|
||||
{
|
||||
// unarmored
|
||||
ratings[i] = (fUnarmoredBase1 * unarmoredSkill) * (fUnarmoredBase2 * unarmoredSkill);
|
||||
}
|
||||
else
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Armor> *ref =
|
||||
it->get<ESM::Armor>();
|
||||
|
||||
int armorSkillType = MWWorld::Class::get(*it).getEquipmentSkill(*it);
|
||||
int armorSkill = MWWorld::Class::get(ptr).getNpcStats(ptr).getSkill(armorSkillType).getModified();
|
||||
|
||||
if (ref->mBase->mData.mWeight == 0)
|
||||
ratings[i] = ref->mBase->mData.mArmor;
|
||||
else
|
||||
ratings[i] = ref->mBase->mData.mArmor * armorSkill / iBaseArmorSkill;
|
||||
}
|
||||
}
|
||||
|
||||
float shield = MWWorld::Class::get(ptr).getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Shield).mMagnitude;
|
||||
|
||||
return ratings[MWWorld::InventoryStore::Slot_Cuirass] * 0.3
|
||||
+ (ratings[MWWorld::InventoryStore::Slot_CarriedLeft] + ratings[MWWorld::InventoryStore::Slot_Helmet]
|
||||
+ ratings[MWWorld::InventoryStore::Slot_Greaves] + ratings[MWWorld::InventoryStore::Slot_Boots]
|
||||
+ ratings[MWWorld::InventoryStore::Slot_LeftPauldron] + ratings[MWWorld::InventoryStore::Slot_RightPauldron]
|
||||
) * 0.1
|
||||
+ (ratings[MWWorld::InventoryStore::Slot_LeftGauntlet] + MWWorld::InventoryStore::Slot_RightGauntlet)
|
||||
* 0.05
|
||||
+ shield;
|
||||
}
|
||||
|
||||
|
||||
void Npc::adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const
|
||||
{
|
||||
y = 0;
|
||||
|
@ -104,6 +104,9 @@ namespace MWClass
|
||||
///< Returns total weight of objects inside this object (including modifications from magic
|
||||
/// effects). Throws an exception, if the object can't hold other objects.
|
||||
|
||||
virtual float getArmorRating (const MWWorld::Ptr& ptr) const;
|
||||
///< @return combined armor rating of this actor
|
||||
|
||||
virtual bool apply (const MWWorld::Ptr& ptr, const std::string& id,
|
||||
const MWWorld::Ptr& actor) const;
|
||||
///< Apply \a id on \a ptr.
|
||||
|
@ -459,7 +459,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
|
||||
case SelectWrapper::Function_PcCorprus:
|
||||
|
||||
return MWWorld::Class::get (player).getCreatureStats (player).
|
||||
getMagicEffects().get (132).mMagnitude!=0;
|
||||
getMagicEffects().get (ESM::MagicEffect::Corprus).mMagnitude!=0;
|
||||
|
||||
case SelectWrapper::Function_PcExpelled:
|
||||
{
|
||||
|
@ -683,12 +683,18 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
|
||||
// transfer everything into the player's inventory
|
||||
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
|
||||
|
||||
std::vector<MWWorld::Ptr> equippedItems = getEquippedItems();
|
||||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWWorld::ContainerStore& playerStore = MWWorld::Class::get(player).getContainerStore(player);
|
||||
|
||||
int i=0;
|
||||
for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter)
|
||||
{
|
||||
if (std::find(equippedItems.begin(), equippedItems.end(), *iter) != equippedItems.end()
|
||||
&& !mDisplayEquippedItems)
|
||||
continue;
|
||||
|
||||
playerStore.add(*iter);
|
||||
|
||||
if (i==0)
|
||||
@ -698,11 +704,11 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
|
||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||
}
|
||||
|
||||
iter->getRefData().setCount(0);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
containerStore.clear();
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
@ -50,6 +51,7 @@ namespace MWGui
|
||||
getWidget(mFilterMisc, "MiscButton");
|
||||
getWidget(mLeftPane, "LeftPane");
|
||||
getWidget(mRightPane, "RightPane");
|
||||
getWidget(mArmorRating, "ArmorRating");
|
||||
|
||||
mAvatar->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onAvatarClicked);
|
||||
|
||||
@ -288,6 +290,9 @@ namespace MWGui
|
||||
mPreview.update (size.width, size.height);
|
||||
mAvatarImage->setSize(MyGUI::IntSize(std::max(mAvatar->getSize().width, 512), std::max(mAvatar->getSize().height, 1024)));
|
||||
mAvatarImage->setImageTexture("CharacterPreview");
|
||||
|
||||
mArmorRating->setCaptionWithReplacing ("#{sArmor}: "
|
||||
+ boost::lexical_cast<std::string>(static_cast<int>(MWWorld::Class::get(mPtr).getArmorRating(mPtr))));
|
||||
}
|
||||
|
||||
void InventoryWindow::pickUpObject (MWWorld::Ptr object)
|
||||
|
@ -159,7 +159,7 @@ namespace MWGui
|
||||
|
||||
float hourlyHealthDelta = stats.getAttribute(ESM::Attribute::Endurance).getModified() * 0.1;
|
||||
|
||||
bool stunted = (stats.getMagicEffects().get(MWMechanics::EffectKey(136)).mMagnitude > 0);
|
||||
bool stunted = (stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0);
|
||||
float fRestMagicMult = store.get<ESM::GameSetting>().find("fRestMagicMult")->getFloat();
|
||||
float hourlyMagickaDelta = fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified();
|
||||
|
||||
|
@ -71,7 +71,7 @@ namespace MWMechanics
|
||||
int endurance = creatureStats.getAttribute(5).getBase();
|
||||
|
||||
double magickaFactor =
|
||||
creatureStats.getMagicEffects().get (EffectKey (84)).mMagnitude * 0.1 + 0.5;
|
||||
creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::FortifyMaximumMagicka)).mMagnitude * 0.1 + 0.5;
|
||||
|
||||
DynamicStat<float> health = creatureStats.getHealth();
|
||||
health.setBase (static_cast<int> (0.5 * (strength + endurance)) + creatureStats.getLevelHealthBonus ());
|
||||
@ -92,8 +92,7 @@ namespace MWMechanics
|
||||
|
||||
if (duration == 3600)
|
||||
{
|
||||
// stunted magicka
|
||||
bool stunted = stats.getMagicEffects ().get(MWMechanics::EffectKey(136)).mMagnitude > 0;
|
||||
bool stunted = stats.getMagicEffects ().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0;
|
||||
|
||||
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
|
||||
|
||||
@ -140,9 +139,9 @@ namespace MWMechanics
|
||||
for (int i=0; i<8; ++i)
|
||||
{
|
||||
int modifier =
|
||||
creatureStats.getMagicEffects().get (EffectKey (79, i)).mMagnitude;
|
||||
creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::FortifyAttribute, i)).mMagnitude;
|
||||
|
||||
modifier -= creatureStats.getMagicEffects().get (EffectKey (17, i)).mMagnitude;
|
||||
modifier -= creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::DrainAttribute, i)).mMagnitude;
|
||||
|
||||
creatureStats.getAttribute(i).setModifier (modifier);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "mechanicsmanagerimp.hpp"
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
@ -215,19 +215,22 @@ namespace MWScript
|
||||
std::string InterpreterContext::getNPCRace() const
|
||||
{
|
||||
ESM::NPC npc = *mReference.get<ESM::NPC>()->mBase;
|
||||
return npc.mRace;
|
||||
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npc.mRace);
|
||||
return race->mName;
|
||||
}
|
||||
|
||||
std::string InterpreterContext::getNPCClass() const
|
||||
{
|
||||
ESM::NPC npc = *mReference.get<ESM::NPC>()->mBase;
|
||||
return npc.mClass;
|
||||
const ESM::Class* class_ = MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(npc.mClass);
|
||||
return class_->mName;
|
||||
}
|
||||
|
||||
std::string InterpreterContext::getNPCFaction() const
|
||||
{
|
||||
ESM::NPC npc = *mReference.get<ESM::NPC>()->mBase;
|
||||
return npc.mFaction;
|
||||
const ESM::Faction* faction = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(npc.mFaction);
|
||||
return faction->mName;
|
||||
}
|
||||
|
||||
std::string InterpreterContext::getNPCRank() const
|
||||
|
@ -89,7 +89,7 @@ namespace MWScript
|
||||
virtual std::string getNPCClass() const;
|
||||
|
||||
virtual std::string getNPCFaction() const;
|
||||
|
||||
|
||||
virtual std::string getNPCRank() const;
|
||||
|
||||
virtual std::string getPCName() const;
|
||||
|
@ -167,11 +167,16 @@ namespace MWWorld
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Class::hasDetected (const MWWorld::Ptr& ptr, const MWWorld::Ptr& ptr2) const
|
||||
bool Class::hasDetected (const MWWorld::Ptr& ptr, const MWWorld::Ptr& ptr2) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float Class::getArmorRating (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
throw std::runtime_error("Class does not support armor rating");
|
||||
}
|
||||
|
||||
const Class& Class::get (const std::string& key)
|
||||
{
|
||||
std::map<std::string, boost::shared_ptr<Class> >::const_iterator iter = sClasses.find (key);
|
||||
|
@ -215,6 +215,9 @@ namespace MWWorld
|
||||
///< Return the down sound ID of \a ptr or throw an exception, if class does not support ID retrieval
|
||||
/// (default implementation: throw an exception)
|
||||
|
||||
virtual float getArmorRating (const MWWorld::Ptr& ptr) const;
|
||||
///< @return combined armor rating of this actor
|
||||
|
||||
virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of inventory icon.
|
||||
|
||||
|
@ -1259,7 +1259,7 @@ namespace MWWorld
|
||||
World::isFlying(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
const MWWorld::Class &cls = MWWorld::Class::get(ptr);
|
||||
if(cls.isActor() && cls.getCreatureStats(ptr).getMagicEffects().get(MWMechanics::EffectKey(10/*levitate*/)).mMagnitude > 0)
|
||||
if(cls.isActor() && cls.getCreatureStats(ptr).getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Levitate)).mMagnitude > 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -66,6 +66,158 @@ struct MagicEffect
|
||||
|
||||
void load(ESMReader &esm);
|
||||
void save(ESMWriter &esm);
|
||||
|
||||
|
||||
enum Effects
|
||||
{
|
||||
WaterBreathing = 0,
|
||||
SwiftSwim = 1,
|
||||
WaterWalking = 2,
|
||||
Shield = 3,
|
||||
FireShield = 4,
|
||||
LightningShield = 5,
|
||||
FrostShield = 6,
|
||||
Burden = 7,
|
||||
Feather = 8,
|
||||
Jump = 9,
|
||||
Levitate = 10,
|
||||
SlowFall = 11,
|
||||
Lock = 12,
|
||||
Open = 13,
|
||||
FireDamage = 14,
|
||||
ShockDamage = 15,
|
||||
FrostDamage = 16,
|
||||
DrainAttribute = 17,
|
||||
DrainHealth = 18,
|
||||
DrainMagicka = 19,
|
||||
DrainFatigue = 20,
|
||||
DrainSkill = 21,
|
||||
DamageAttribute = 22,
|
||||
DamageHealth = 23,
|
||||
DamageMagicka = 24,
|
||||
DamageFatigue = 25,
|
||||
DamageSkill = 26,
|
||||
Poison = 27,
|
||||
WeaknessToFire = 28,
|
||||
WeaknessToFrost = 29,
|
||||
WeaknessToShock = 30,
|
||||
WeaknessToMagicka = 31,
|
||||
WeaknessToCommonDisease = 32,
|
||||
WeaknessToBlightDisease = 33,
|
||||
WeaknessToCorprusDisease = 34,
|
||||
WeaknessToPoison = 35,
|
||||
WeaknessToNormalWeapons = 36,
|
||||
DisintegrateWeapon = 37,
|
||||
DisintegrateArmor = 38,
|
||||
Invisibility = 39,
|
||||
Chameleon = 40,
|
||||
Light = 41,
|
||||
Sanctuary = 42,
|
||||
NightEye = 43,
|
||||
Charm = 44,
|
||||
Paralyze = 45,
|
||||
Silence = 46,
|
||||
Blind = 47,
|
||||
Sound = 48,
|
||||
CalmHumanoid = 49,
|
||||
CalmCreature = 50,
|
||||
FrenzyHumanoid = 51,
|
||||
FrenzyCreature = 52,
|
||||
DemoralizeHumanoid = 53,
|
||||
DemoralizeCreature = 54,
|
||||
RallyHumanoid = 55,
|
||||
RallyCreature = 56,
|
||||
Dispel = 57,
|
||||
Soultrap = 58,
|
||||
Telekinesis = 59,
|
||||
Mark = 60,
|
||||
Recall = 61,
|
||||
DivineIntervention = 62,
|
||||
AlmsiviIntervention = 63,
|
||||
DetectAnimal = 64,
|
||||
DetectEnchantment = 65,
|
||||
DetectKey = 66,
|
||||
SpellAbsorption = 67,
|
||||
Reflect = 68,
|
||||
CureCommonDisease = 69,
|
||||
CureBlightDisease = 70,
|
||||
CureCorprusDisease = 71,
|
||||
CurePoison = 72,
|
||||
CureParalyzation = 73,
|
||||
RestoreAttribute = 74,
|
||||
RestoreHealth = 75,
|
||||
RestoreMagicka = 76,
|
||||
RestoreFatigue = 77,
|
||||
RestoreSkill = 78,
|
||||
FortifyAttribute = 79,
|
||||
FortifyHealth = 80,
|
||||
FortifyMagicka= 81,
|
||||
FortifyFatigue = 82,
|
||||
FortifySkill = 83,
|
||||
FortifyMaximumMagicka = 84,
|
||||
AbsorbAttribute = 85,
|
||||
AbsorbHealth = 86,
|
||||
AbsorbMagicka = 87,
|
||||
AbsorbFatigue = 88,
|
||||
AbsorbSkill = 89,
|
||||
ResistFire = 90,
|
||||
ResistFrost = 91,
|
||||
ResistShock = 92,
|
||||
ResistMagicka = 93,
|
||||
ResistCommonDisease = 94,
|
||||
ResistBlightDisease = 95,
|
||||
ResistCorprusDisease = 96,
|
||||
ResistPoison = 97,
|
||||
ResistNormalWeapons = 98,
|
||||
ResistParalysis = 99,
|
||||
RemoveCurse = 100,
|
||||
TurnUndead = 101,
|
||||
SummonScamp = 102,
|
||||
SummonClannfear = 103,
|
||||
SummonDaedroth = 104,
|
||||
SummonDremora = 105,
|
||||
SummonAncestralGhost = 106,
|
||||
SummonSkeletalMinion = 107,
|
||||
SummonBonewalker = 108,
|
||||
SummonGreaterBonewalker = 109,
|
||||
SummonBonelord = 110,
|
||||
SummonWingedTwilight = 111,
|
||||
SummonHunger = 112,
|
||||
SummonGoldenSaint = 113,
|
||||
SummonFlameAtronach = 114,
|
||||
SummonFrostAtronach = 115,
|
||||
SummonStormAtronach = 116,
|
||||
FortifyAttack = 117,
|
||||
CommandCreature = 118,
|
||||
CommandHumanoid = 119,
|
||||
BoundDagger = 120,
|
||||
BoundLongsword = 121,
|
||||
BoundMace = 122,
|
||||
BoundBattleAxe = 123,
|
||||
BoundSpear = 124,
|
||||
BoundLongbow = 125,
|
||||
ExtraSpell = 126,
|
||||
BoundCuirass = 127,
|
||||
BoundHelm = 128,
|
||||
BoundBoots = 129,
|
||||
BoundShield = 130,
|
||||
BoundGloves = 131,
|
||||
Corprus = 132,
|
||||
Vampirism = 133,
|
||||
SummonCenturionSphere = 134,
|
||||
SunDamage = 135,
|
||||
StuntedMagicka = 136,
|
||||
|
||||
// Tribunal only
|
||||
SummonFabricant = 137,
|
||||
|
||||
// Bloodmoon only
|
||||
SummonWolf = 138,
|
||||
SummonBear = 139,
|
||||
SummonBonewolf = 140,
|
||||
SummonCreature04 = 141,
|
||||
SummonCreature05 = 142
|
||||
};
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
@ -17,7 +17,6 @@
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="ProgressText" position="0 150 212 24" align="HCenter Bottom" name="ArmorRating">
|
||||
<Property key="Caption" value="Armor Rating"/>
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
Loading…
x
Reference in New Issue
Block a user