1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-26 09:35:28 +00:00

Merge remote-tracking branch 'scrawl/master'

This commit is contained in:
Marc Zinnschlag 2014-01-07 10:17:33 +01:00
commit 72a81a2381
16 changed files with 300 additions and 60 deletions

View File

@ -74,7 +74,7 @@ add_openmw_dir (mwmechanics
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
aiescort aiactivate aicombat repair enchanting pathfinding security spellsuccess spellcasting
disease
disease pickpocket
)
add_openmw_dir (mwbase

View File

@ -88,6 +88,9 @@ namespace MWBase
virtual int countDeaths (const std::string& id) const = 0;
///< Return the number of deaths for actors with the given ID.
/// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check!
virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) = 0;
enum PersuasionType
{
PT_Admire,

View File

@ -613,7 +613,7 @@ namespace MWClass
// 'ptr' is losing health. Play a 'hit' voiced dialog entry if not already saying
// something, alert the character controller, scripts, etc.
MWBase::Environment::get().getDialogueManager()->say(ptr, "thief");
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
if(object.isEmpty())
{

View File

@ -6,10 +6,13 @@
#include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/dialoguemanager.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "../mwmechanics/pickpocket.hpp"
#include "countdialog.hpp"
#include "tradewindow.hpp"
#include "inventorywindow.hpp"
@ -123,6 +126,7 @@ namespace MWGui
, mSelectedItem(-1)
, mModel(NULL)
, mSortModel(NULL)
, mPickpocketDetected(false)
{
getWidget(mDisposeCorpseButton, "DisposeCorpseButton");
getWidget(mTakeButton, "TakeButton");
@ -171,6 +175,9 @@ namespace MWGui
void ContainerWindow::dragItem(MyGUI::Widget* sender, int count)
{
if (!onTakeItem(mModel->getItem(mSelectedItem), count))
return;
mDragAndDrop->startDrag(mSelectedItem, mSortModel, mModel, mItemView, count);
}
@ -208,6 +215,7 @@ namespace MWGui
void ContainerWindow::open(const MWWorld::Ptr& container, bool loot)
{
mPickpocketDetected = false;
mPtr = container;
if (mPtr.getTypeName() == typeid(ESM::NPC).name() && !loot)
@ -230,6 +238,28 @@ namespace MWGui
setTitle(MWWorld::Class::get(container).getName(container));
}
void ContainerWindow::close()
{
WindowBase::close();
// Make sure we were actually closed, rather than just temporarily hidden (e.g. console or main menu opened)
if (!MWBase::Environment::get().getWindowManager()->containsMode(GM_Container)
&& !mPickpocketDetected // If it was already detected while taking an item, no need to check now
)
{
MWMechanics::Pickpocket pickpocket(MWBase::Environment::get().getWorld()->getPlayer().getPlayer(),
mPtr);
if (pickpocket.finish())
{
// TODO: crime
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
MWBase::Environment::get().getDialogueManager()->say(mPtr, "Thief");
mPickpocketDetected = true;
return;
}
}
}
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
{
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
@ -255,8 +285,13 @@ namespace MWGui
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
}
playerModel->copyItem(mModel->getItem(i), mModel->getItem(i).mCount);
mModel->removeItem(mModel->getItem(i), mModel->getItem(i).mCount);
const ItemStack& item = mModel->getItem(i);
if (!onTakeItem(item, item.mCount))
break;
playerModel->copyItem(item, item.mCount);
mModel->removeItem(item, item.mCount);
}
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
@ -283,4 +318,22 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
}
bool ContainerWindow::onTakeItem(const ItemStack &item, int count)
{
if (dynamic_cast<PickpocketItemModel*>(mModel))
{
MWMechanics::Pickpocket pickpocket(MWBase::Environment::get().getWorld()->getPlayer().getPlayer(),
mPtr);
if (pickpocket.pick(item.mBase, count))
{
// TODO: crime
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
MWBase::Environment::get().getDialogueManager()->say(mPtr, "Thief");
mPickpocketDetected = true;
return false;
}
}
return true;
}
}

View File

@ -52,10 +52,13 @@ namespace MWGui
ContainerWindow(DragAndDrop* dragAndDrop);
void open(const MWWorld::Ptr& container, bool loot=false);
virtual void close();
private:
DragAndDrop* mDragAndDrop;
bool mPickpocketDetected;
MWGui::ItemView* mItemView;
SortFilterItemModel* mSortModel;
ItemModel* mModel;
@ -73,6 +76,9 @@ namespace MWGui
void onTakeAllButtonClicked(MyGUI::Widget* _sender);
void onDisposeCorpseButtonClicked(MyGUI::Widget* sender);
/// @return is taking the item allowed?
bool onTakeItem(const ItemStack& item, int count);
virtual void onReferenceUnavailable();
};
}

View File

@ -158,50 +158,49 @@ namespace MWMechanics
calculateDynamicStats (ptr);
calculateCreatureStatModifiers (ptr, duration);
if(!MWBase::Environment::get().getWindowManager()->isGuiMode())
// AI
if(MWBase::Environment::get().getMechanicsManager()->isAIActive())
{
// AI
if(MWBase::Environment::get().getMechanicsManager()->isAIActive())
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
//engage combat or not?
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
if(ptr != player && !creatureStats.isHostile())
{
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
//engage combat or not?
if(ptr != MWBase::Environment::get().getWorld()->getPlayer().getPlayer() && !creatureStats.isHostile())
ESM::Position playerpos = player.getRefData().getPosition();
ESM::Position actorpos = ptr.getRefData().getPosition();
float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0])
+(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1])
+(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2]));
float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified();
float disp = 100; //creatures don't have disposition, so set it to 100 by default
if(ptr.getTypeName() == typeid(ESM::NPC).name())
{
ESM::Position playerpos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition();
ESM::Position actorpos = ptr.getRefData().getPosition();
float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0])
+(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1])
+(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2]));
float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified();
float disp = 100; //creatures don't have disposition, so set it to 100 by default
if(ptr.getTypeName() == typeid(ESM::NPC).name())
{
disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(ptr);
}
bool LOS = MWBase::Environment::get().getWorld()->getLOS(ptr,MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
if( ( (fight == 100 )
|| (fight >= 95 && d <= 3000)
|| (fight >= 90 && d <= 2000)
|| (fight >= 80 && d <= 1000)
|| (fight >= 80 && disp <= 40)
|| (fight >= 70 && disp <= 35 && d <= 1000)
|| (fight >= 60 && disp <= 30 && d <= 1000)
|| (fight >= 50 && disp == 0)
|| (fight >= 40 && disp <= 10 && d <= 500) )
&& LOS
)
{
creatureStats.getAiSequence().stack(AiCombat("player"));
creatureStats.setHostile(true);
}
disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(ptr);
}
bool LOS = MWBase::Environment::get().getWorld()->getLOS(ptr,player)
&& MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr);
if( ( (fight == 100 )
|| (fight >= 95 && d <= 3000)
|| (fight >= 90 && d <= 2000)
|| (fight >= 80 && d <= 1000)
|| (fight >= 80 && disp <= 40)
|| (fight >= 70 && disp <= 35 && d <= 1000)
|| (fight >= 60 && disp <= 30 && d <= 1000)
|| (fight >= 50 && disp == 0)
|| (fight >= 40 && disp <= 10 && d <= 500) )
&& LOS
)
{
creatureStats.getAiSequence().stack(AiCombat("player"));
creatureStats.setHostile(true);
}
creatureStats.getAiSequence().execute (ptr,duration);
}
// fatigue restoration
calculateRestoration(ptr, duration);
creatureStats.getAiSequence().execute (ptr,duration);
}
// fatigue restoration
calculateRestoration(ptr, duration);
}
void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused)

View File

@ -12,6 +12,8 @@
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include <OgreSceneNode.h>
#include "spellcasting.hpp"
namespace MWMechanics
@ -725,4 +727,74 @@ namespace MWMechanics
{
return mAI;
}
bool MechanicsManager::awarenessCheck(const MWWorld::Ptr &ptr, const MWWorld::Ptr &observer)
{
const MWWorld::Store<ESM::GameSetting>& store = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
float invisibility = stats.getMagicEffects().get(ESM::MagicEffect::Invisibility).mMagnitude;
if (invisibility > 0)
return false;
float sneakTerm = 0;
if (ptr.getClass().getStance(ptr, MWWorld::Class::Sneak)
&& !MWBase::Environment::get().getWorld()->isSwimming(ptr)
&& MWBase::Environment::get().getWorld()->isOnGround(ptr))
{
static float fSneakSkillMult = store.find("fSneakSkillMult")->getFloat();
static float fSneakBootMult = store.find("fSneakBootMult")->getFloat();
float sneak = 0;
if (ptr.getClass().isNpc())
sneak = ptr.getClass().getNpcStats(ptr).getSkill(ESM::Skill::Sneak).getModified();
int agility = stats.getAttribute(ESM::Attribute::Agility).getModified();
int luck = stats.getAttribute(ESM::Attribute::Luck).getModified();
float bootWeight = 0;
if (ptr.getClass().isNpc())
{
MWWorld::InventoryStore& inv = ptr.getClass().getInventoryStore(ptr);
MWWorld::ContainerStoreIterator it = inv.getSlot(MWWorld::InventoryStore::Slot_Boots);
if (it != inv.end())
bootWeight = it->getClass().getWeight(*it);
}
sneakTerm = fSneakSkillMult * sneak + 0.2 * agility + 0.1 * luck + bootWeight * fSneakBootMult;
}
static float fSneakDistBase = store.find("fSneakDistanceBase")->getFloat();
static float fSneakDistMult = store.find("fSneakDistanceMultiplier")->getFloat();
Ogre::Vector3 pos1 (ptr.getRefData().getPosition().pos);
Ogre::Vector3 pos2 (observer.getRefData().getPosition().pos);
float distTerm = fSneakDistBase + fSneakDistMult * pos1.distance(pos2);
float chameleon = stats.getMagicEffects().get(ESM::MagicEffect::Chameleon).mMagnitude;
float x = sneakTerm * distTerm * stats.getFatigueTerm() + chameleon + invisibility;
CreatureStats& observerStats = observer.getClass().getCreatureStats(observer);
int obsAgility = observerStats.getAttribute(ESM::Attribute::Agility).getModified();
int obsLuck = observerStats.getAttribute(ESM::Attribute::Luck).getModified();
float obsBlind = observerStats.getMagicEffects().get(ESM::MagicEffect::Blind).mMagnitude;
int obsSneak = 0;
if (observer.getClass().isNpc())
obsSneak = observer.getClass().getNpcStats(observer).getSkill(ESM::Skill::Sneak).getModified();
float obsTerm = obsSneak + 0.2 * obsAgility + 0.1 * obsLuck - obsBlind;
// is ptr behind the observer?
static float fSneakNoViewMult = store.find("fSneakNoViewMult")->getFloat();
static float fSneakViewMult = store.find("fSneakViewMult")->getFloat();
float y = 0;
Ogre::Vector3 vec = pos1 - pos2;
Ogre::Radian angle = observer.getRefData().getBaseNode()->getOrientation().yAxis().angleBetween(vec);
if (angle < Ogre::Degree(90))
y = obsTerm * observerStats.getFatigueTerm() * fSneakNoViewMult;
else
y = obsTerm * observerStats.getFatigueTerm() * fSneakViewMult;
float target = x - y;
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
return (roll >= target);
}
}

View File

@ -98,6 +98,9 @@ namespace MWMechanics
void toLower(std::string npcFaction);
///< Perform a persuasion action on NPC
/// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check!
virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer);
virtual void forceStateUpdate(const MWWorld::Ptr &ptr);
virtual void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number);

View File

@ -0,0 +1,67 @@
#include "pickpocket.hpp"
#include "../mwworld/class.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "npcstats.hpp"
namespace MWMechanics
{
Pickpocket::Pickpocket(const MWWorld::Ptr &thief, const MWWorld::Ptr &victim)
: mThief(thief)
, mVictim(victim)
{
}
float Pickpocket::getChanceModifier(const MWWorld::Ptr &ptr, float add)
{
NpcStats& stats = ptr.getClass().getNpcStats(ptr);
float agility = stats.getAttribute(ESM::Attribute::Agility).getModified();
float luck = stats.getAttribute(ESM::Attribute::Luck).getModified();
float sneak = stats.getSkill(ESM::Skill::Sneak).getModified();
return (add + 0.2 * agility + 0.1 * luck + sneak) * stats.getFatigueTerm();
}
bool Pickpocket::getDetected(float valueTerm)
{
float x = getChanceModifier(mThief);
float y = getChanceModifier(mVictim, valueTerm);
float t = 2*x - y;
NpcStats& pcStats = mThief.getClass().getNpcStats(mThief);
float pcSneak = pcStats.getSkill(ESM::Skill::Sneak).getModified();
int iPickMinChance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("iPickMinChance")->getInt();
int iPickMaxChance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("iPickMaxChance")->getInt();
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
if (t < pcSneak / iPickMinChance)
{
return (roll > int(pcSneak / iPickMinChance));
}
else
{
t = std::min(float(iPickMaxChance), t);
return (roll > int(t));
}
}
bool Pickpocket::pick(MWWorld::Ptr item, int count)
{
float stackValue = item.getClass().getValue(item) * count;
float fPickPocketMod = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fPickPocketMod")->getFloat();
float valueTerm = 10 * fPickPocketMod * stackValue;
return getDetected(valueTerm);
}
bool Pickpocket::finish()
{
return getDetected(0.f);
}
}

View File

@ -0,0 +1,30 @@
#ifndef OPENMW_MECHANICS_PICKPOCKET_H
#define OPENMW_MECHANICS_PICKPOCKET_H
#include "../mwworld/ptr.hpp"
namespace MWMechanics
{
class Pickpocket
{
public:
Pickpocket (const MWWorld::Ptr& thief, const MWWorld::Ptr& victim);
/// Steal some items
/// @return Was the thief detected?
bool pick (MWWorld::Ptr item, int count);
/// End the pickpocketing process
/// @return Was the thief detected?
bool finish ();
private:
bool getDetected(float valueTerm);
float getChanceModifier(const MWWorld::Ptr& ptr, float add=0);
MWWorld::Ptr mThief;
MWWorld::Ptr mVictim;
};
}
#endif

View File

@ -231,6 +231,7 @@ namespace MWMechanics
{
float mProgress;
public:
SkillValue() : mProgress(0) {}
float getProgress() const { return mProgress; }
void setProgress(float progress) { mProgress = progress; }
};

View File

@ -358,19 +358,21 @@ namespace MWScript
};
template<class R>
class OpGetDetected : public Interpreter::Opcode1
class OpGetDetected : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr observer = R()(runtime);
std::string actorID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
Interpreter::Type_Integer value = false; // TODO replace with implementation
MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPtr(actorID, true);
std::cout << "AiGetDetected: " << actorID << ", " << value << std::endl;
Interpreter::Type_Integer value =
MWBase::Environment::get().getWorld()->getLOS(observer, actor) &&
MWBase::Environment::get().getMechanicsManager()->awarenessCheck(actor, observer);
runtime.push (value);
}
@ -432,8 +434,8 @@ namespace MWScript
new OpGetAiPackageDone<ExplicitRef>);
interpreter.installSegment5 (Compiler::Ai::opcodeGetCurrentAiPackage, new OpGetCurrentAIPackage<ImplicitRef>);
interpreter.installSegment5 (Compiler::Ai::opcodeGetCurrentAiPackageExplicit, new OpGetCurrentAIPackage<ExplicitRef>);
interpreter.installSegment3 (Compiler::Ai::opcodeGetDetected, new OpGetDetected<ImplicitRef>);
interpreter.installSegment3 (Compiler::Ai::opcodeGetDetectedExplicit, new OpGetDetected<ExplicitRef>);
interpreter.installSegment5 (Compiler::Ai::opcodeGetDetected, new OpGetDetected<ImplicitRef>);
interpreter.installSegment5 (Compiler::Ai::opcodeGetDetectedExplicit, new OpGetDetected<ExplicitRef>);
interpreter.installSegment5 (Compiler::Ai::opcodeGetLineOfSight, new OpGetLineOfSight<ImplicitRef>);
interpreter.installSegment5 (Compiler::Ai::opcodeGetLineOfSightExplicit, new OpGetLineOfSight<ExplicitRef>);
interpreter.installSegment5 (Compiler::Ai::opcodeToggleAI, new OpToggleAI<ImplicitRef>);

View File

@ -79,13 +79,13 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(const Ptr& itemPtr,
{
const MWWorld::ContainerStoreIterator& retVal = MWWorld::ContainerStore::add(itemPtr, count, actorPtr, setOwner);
// Auto-equip items if an armor/clothing item is added, but not for the player nor werewolves
// Auto-equip items if an armor/clothing or weapon item is added, but not for the player nor werewolves
if ((actorPtr.getRefData().getHandle() != "player")
&& !(MWWorld::Class::get(actorPtr).getNpcStats(actorPtr).isWerewolf())
&& !actorPtr.getClass().getCreatureStats(actorPtr).isDead())
{
std::string type = itemPtr.getTypeName();
if ((type == typeid(ESM::Armor).name()) || (type == typeid(ESM::Clothing).name()))
if ((type == typeid(ESM::Armor).name()) || (type == typeid(ESM::Clothing).name()) || (type == typeid(ESM::Weapon).name()))
autoEquip(actorPtr);
}
@ -185,7 +185,10 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
// Only autoEquip if we are the original owner of the item.
// This stops merchants from auto equipping anything you sell to them.
if (!Misc::StringUtils::ciEqual(test.getCellRef().mOwner, actor.getCellRef().mRefID))
// ...unless this is a companion, he should always equip items given to him.
if (!Misc::StringUtils::ciEqual(test.getCellRef().mOwner, actor.getCellRef().mRefID) &&
(actor.getClass().getScript(actor).empty() ||
!actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion")))
continue;
int testSkill = MWWorld::Class::get (test).getEquipmentSkill (test);

View File

@ -1840,13 +1840,6 @@ namespace MWWorld
bool World::getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc)
{
// This is a placeholder! Needs to go into an NPC awareness check function (see
// https://wiki.openmw.org/index.php?title=Research:NPC_AI_Behaviour#NPC_Awareness_Check )
if (targetNpc.getClass().getCreatureStats(targetNpc).getMagicEffects().get(ESM::MagicEffect::Invisibility).mMagnitude)
return false;
if (targetNpc.getClass().getCreatureStats(targetNpc).getMagicEffects().get(ESM::MagicEffect::Chameleon).mMagnitude > 100)
return false;
Ogre::Vector3 halfExt1 = mPhysEngine->getCharacter(npc.getRefData().getHandle())->getHalfExtents();
float* pos1 = npc.getRefData().getPosition().pos;
Ogre::Vector3 halfExt2 = mPhysEngine->getCharacter(targetNpc.getRefData().getHandle())->getHalfExtents();

View File

@ -1209,20 +1209,27 @@ ObjectScenePtr Loader::createObjects(Ogre::Entity *parent, const std::string &bo
if(isskinned)
{
// Apparently both are allowed. Sigh.
// This could also mean that filters are supposed to work on the actual node
// hierarchy, rather than just trishapes, and the 'tri ' should be omitted?
std::string filter = "@shape=tri "+bonename;
std::string filter2 = "@shape="+bonename;
Misc::StringUtils::toLower(filter);
Misc::StringUtils::toLower(filter2);
for(size_t i = 0;i < scene->mEntities.size();i++)
{
Ogre::Entity *entity = scene->mEntities[i];
if(entity->hasSkeleton())
{
if(entity == scene->mSkelBase ||
entity->getMesh()->getName().find(filter) != std::string::npos)
entity->getMesh()->getName().find(filter) != std::string::npos
|| entity->getMesh()->getName().find(filter2) != std::string::npos)
parentNode->attachObject(entity);
}
else
{
if(entity->getMesh()->getName().find(filter) == std::string::npos)
if(entity->getMesh()->getName().find(filter) == std::string::npos
|| entity->getMesh()->getName().find(filter2) == std::string::npos)
entity->detachFromParent();
}
}

View File

@ -3,6 +3,7 @@
<MyGUI type="Layout">
<Widget type="Window" skin="MW_Window" layer="Windows" position="0 0 600 300" name="_Main">
<Property key="MinSize" value="245 145"/>
<Property key="Visible" value="false"/>
<!-- Items -->
<Widget type="ItemView" skin="MW_ItemView" position="5 5 575 225" name="ItemView" align="Left Top Stretch">