1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-25 06:35:30 +00:00

Merge branch 'master' into spellcreation

This commit is contained in:
scrawl 2012-10-23 10:38:53 +02:00
commit 33361e6539
60 changed files with 3199 additions and 525 deletions

View File

@ -306,7 +306,7 @@ endif()
# Compiler settings
if (CMAKE_COMPILER_IS_GNUCC)
add_definitions (-Wall -Wextra -Wno-unused-parameter -Wno-reorder)
add_definitions (-Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++0x -pedantic)
# Silence warnings in OGRE headers. Remove once OGRE got fixed!
add_definitions (-Wno-ignored-qualifiers)

View File

@ -1,5 +1,7 @@
set(ESMTOOL
esmtool.cpp
labels.hpp
labels.cpp
record.hpp
record.cpp
)

View File

@ -13,7 +13,7 @@
#include "record.hpp"
#define ESMTOOL_VERSION 1.1
#define ESMTOOL_VERSION 1.2
// Create a local alias for brevity
namespace bpo = boost::program_options;
@ -57,6 +57,8 @@ struct Arguments
std::string encoding;
std::string filename;
std::string outname;
std::vector<std::string> types;
ESMData data;
ESM::ESMReader reader;
@ -70,7 +72,12 @@ bool parseOptions (int argc, char** argv, Arguments &info)
desc.add_options()
("help,h", "print help message.")
("version,v", "print version information and quit.")
("raw,r", "Show an unformattet list of all records and subrecords.")
("raw,r", "Show an unformatted list of all records and subrecords.")
// The intention is that this option would interact better
// with other modes including clone, dump, and raw.
("type,t", bpo::value< std::vector<std::string> >(),
"Show only records of this type (four character record code). May "
"be specified multiple times. Only affects dump mode.")
("quiet,q", "Supress all record information. Useful for speed tests.")
("loadcells,C", "Browse through contents of all cells.")
@ -122,6 +129,9 @@ bool parseOptions (int argc, char** argv, Arguments &info)
return false;
}
if (variables.count("type") > 0)
info.types = variables["type"].as< std::vector<std::string> >();
info.mode = variables["mode"].as<std::string>();
if (!(info.mode == "dump" || info.mode == "clone" || info.mode == "comp"))
{
@ -306,14 +316,23 @@ int load(Arguments& info)
uint32_t flags;
esm.getRecHeader(flags);
// Is the user interested in this record type?
bool interested = true;
if (info.types.size() > 0)
{
std::vector<std::string>::iterator match;
match = std::find(info.types.begin(), info.types.end(),
n.toString());
if (match == info.types.end()) interested = false;
}
std::string id = esm.getHNOString("NAME");
if(!quiet)
if(!quiet && interested)
std::cout << "\nRecord: " << n.toString()
<< " '" << id << "'\n";
EsmTool::RecordBase *record =
EsmTool::RecordBase::create(n.val);
EsmTool::RecordBase *record = EsmTool::RecordBase::create(n);
if (record == 0) {
if (std::find(skipped.begin(), skipped.end(), n.val) == skipped.end())
@ -326,18 +345,16 @@ int load(Arguments& info)
if (quiet) break;
std::cout << " Skipping\n";
} else {
if (record->getType() == ESM::REC_GMST) {
if (record->getType().val == ESM::REC_GMST) {
// preset id for GameSetting record
record->cast<ESM::GameSetting>()->get().mId = id;
}
record->setId(id);
record->setFlags((int) flags);
record->load(esm);
if (!quiet) {
record->print();
}
if (!quiet && interested) record->print();
if (record->getType() == ESM::REC_CELL && loadCells) {
if (record->getType().val == ESM::REC_CELL && loadCells) {
loadCell(record->cast<ESM::Cell>()->get(), esm, info);
}
@ -434,7 +451,7 @@ int clone(Arguments& info)
{
EsmTool::RecordBase *record = *it;
name.val = record->getType();
name.val = record->getType().val;
esm.startRecord(name.toString(), record->getFlags());

881
apps/esmtool/labels.cpp Normal file
View File

@ -0,0 +1,881 @@
#include "labels.hpp"
#include <components/esm/loadbody.hpp>
#include <components/esm/loadcell.hpp>
#include <components/esm/loadcont.hpp>
#include <components/esm/loadcrea.hpp>
#include <components/esm/loadlevlist.hpp>
#include <components/esm/loadligh.hpp>
#include <components/esm/loadmgef.hpp>
#include <components/esm/loadnpc.hpp>
#include <components/esm/loadrace.hpp>
#include <components/esm/loadspel.hpp>
#include <components/esm/loadweap.hpp>
#include <components/esm/aipackage.hpp>
#include <iostream>
#include <boost/format.hpp>
std::string bodyPartLabel(char idx)
{
const char *bodyPartLabels[] = {
"Head",
"Hair",
"Neck",
"Cuirass",
"Groin",
"Skirt",
"Right Hand",
"Left Hand",
"Right Wrist",
"Left Wrist",
"Shield",
"Right Forearm",
"Left Forearm",
"Right Upperarm",
"Left Upperarm",
"Right Foot",
"Left Foot",
"Right Ankle",
"Left Ankle",
"Right Knee",
"Left Knee",
"Right Leg",
"Left Leg",
"Right Shoulder",
"Left Shoulder",
"Weapon",
"Tail"
};
if ((int)idx >= 0 && (int)(idx) <= 26)
return bodyPartLabels[(int)(idx)];
else
return "Invalid";
}
std::string meshPartLabel(char idx)
{
const char *meshPartLabels[] = {
"Head",
"Hair",
"Neck",
"Chest",
"Groin",
"Hand",
"Wrist",
"Forearm",
"Upperarm",
"Foot",
"Ankle",
"Knee",
"Upper Leg",
"Clavicle",
"Tail"
};
if ((int)(idx) >= 0 && (int)(idx) <= ESM::BodyPart::MP_Tail)
return meshPartLabels[(int)(idx)];
else
return "Invalid";
}
std::string meshTypeLabel(char idx)
{
const char *meshTypeLabels[] = {
"Skin",
"Clothing",
"Armor"
};
if ((int)(idx) >= 0 && (int)(idx) <= ESM::BodyPart::MT_Armor)
return meshTypeLabels[(int)(idx)];
else
return "Invalid";
}
std::string clothingTypeLabel(int idx)
{
const char *clothingTypeLabels[] = {
"Pants",
"Shoes",
"Shirt",
"Belt",
"Robe",
"Right Glove",
"Left Glove",
"Skirt",
"Ring",
"Amulet"
};
if (idx >= 0 && idx <= 9)
return clothingTypeLabels[idx];
else
return "Invalid";
}
std::string armorTypeLabel(int idx)
{
const char *armorTypeLabels[] = {
"Helmet",
"Cuirass",
"Left Pauldron",
"Right Pauldron",
"Greaves",
"Boots",
"Left Gauntlet",
"Right Gauntlet",
"Shield",
"Left Bracer",
"Right Bracer"
};
if (idx >= 0 && idx <= 10)
return armorTypeLabels[idx];
else
return "Invalid";
}
std::string dialogTypeLabel(int idx)
{
const char *dialogTypeLabels[] = {
"Topic",
"Voice",
"Greeting",
"Persuasion",
"Journal"
};
if (idx >= 0 && idx <= 4)
return dialogTypeLabels[idx];
else if (idx == -1)
return "Deleted";
else
return "Invalid";
}
std::string questStatusLabel(int idx)
{
const char *questStatusLabels[] = {
"None",
"Name",
"Finished",
"Restart",
"Deleted"
};
if (idx >= 0 && idx <= 4)
return questStatusLabels[idx];
else
return "Invalid";
}
std::string creatureTypeLabel(int idx)
{
const char *creatureTypeLabels[] = {
"Creature",
"Daedra",
"Undead",
"Humanoid",
};
if (idx >= 0 && idx <= 3)
return creatureTypeLabels[idx];
else
return "Invalid";
}
std::string soundTypeLabel(int idx)
{
const char *soundTypeLabels[] = {
"Left Foot",
"Right Foot",
"Swim Left",
"Swim Right",
"Moan",
"Roar",
"Scream",
"Land"
};
if (idx >= 0 && idx <= 7)
return soundTypeLabels[idx];
else
return "Invalid";
}
std::string weaponTypeLabel(int idx)
{
const char *weaponTypeLabels[] = {
"Short Blade One Hand",
"Long Blade One Hand",
"Long Blade Two Hand",
"Blunt One Hand",
"Blunt Two Close",
"Blunt Two Wide",
"Spear Two Wide",
"Axe One Hand",
"Axe Two Hand",
"Marksman Bow",
"Marksman Crossbow",
"Marksman Thrown",
"Arrow",
"Bolt"
};
if (idx >= 0 && idx <= 13)
return weaponTypeLabels[idx];
else
return "Invalid";
}
std::string aiTypeLabel(int type)
{
if (type == ESM::AI_Wander) return "Wander";
else if (type == ESM::AI_Travel) return "Travel";
else if (type == ESM::AI_Follow) return "Follow";
else if (type == ESM::AI_Escort) return "Escort";
else if (type == ESM::AI_Activate) return "Activate";
else return "Invalid";
}
std::string magicEffectLabel(int idx)
{
const char* magicEffectLabels [] = {
"Water Breathing",
"Swift Swim",
"Water Walking",
"Shield",
"Fire Shield",
"Lightning Shield",
"Frost Shield",
"Burden",
"Feather",
"Jump",
"Levitate",
"SlowFall",
"Lock",
"Open",
"Fire Damage",
"Shock Damage",
"Frost Damage",
"Drain Attribute",
"Drain Health",
"Drain Magicka",
"Drain Fatigue",
"Drain Skill",
"Damage Attribute",
"Damage Health",
"Damage Magicka",
"Damage Fatigue",
"Damage Skill",
"Poison",
"Weakness to Fire",
"Weakness to Frost",
"Weakness to Shock",
"Weakness to Magicka",
"Weakness to Common Disease",
"Weakness to Blight Disease",
"Weakness to Corprus Disease",
"Weakness to Poison",
"Weakness to Normal Weapons",
"Disintegrate Weapon",
"Disintegrate Armor",
"Invisibility",
"Chameleon",
"Light",
"Sanctuary",
"Night Eye",
"Charm",
"Paralyze",
"Silence",
"Blind",
"Sound",
"Calm Humanoid",
"Calm Creature",
"Frenzy Humanoid",
"Frenzy Creature",
"Demoralize Humanoid",
"Demoralize Creature",
"Rally Humanoid",
"Rally Creature",
"Dispel",
"Soultrap",
"Telekinesis",
"Mark",
"Recall",
"Divine Intervention",
"Almsivi Intervention",
"Detect Animal",
"Detect Enchantment",
"Detect Key",
"Spell Absorption",
"Reflect",
"Cure Common Disease",
"Cure Blight Disease",
"Cure Corprus Disease",
"Cure Poison",
"Cure Paralyzation",
"Restore Attribute",
"Restore Health",
"Restore Magicka",
"Restore Fatigue",
"Restore Skill",
"Fortify Attribute",
"Fortify Health",
"Fortify Magicka",
"Fortify Fatigue",
"Fortify Skill",
"Fortify Maximum Magicka",
"Absorb Attribute",
"Absorb Health",
"Absorb Magicka",
"Absorb Fatigue",
"Absorb Skill",
"Resist Fire",
"Resist Frost",
"Resist Shock",
"Resist Magicka",
"Resist Common Disease",
"Resist Blight Disease",
"Resist Corprus Disease",
"Resist Poison",
"Resist Normal Weapons",
"Resist Paralysis",
"Remove Curse",
"Turn Undead",
"Summon Scamp",
"Summon Clannfear",
"Summon Daedroth",
"Summon Dremora",
"Summon Ancestral Ghost",
"Summon Skeletal Minion",
"Summon Bonewalker",
"Summon Greater Bonewalker",
"Summon Bonelord",
"Summon Winged Twilight",
"Summon Hunger",
"Summon Golden Saint",
"Summon Flame Atronach",
"Summon Frost Atronach",
"Summon Storm Atronach",
"Fortify Attack",
"Command Creature",
"Command Humanoid",
"Bound Dagger",
"Bound Longsword",
"Bound Mace",
"Bound Battle Axe",
"Bound Spear",
"Bound Longbow",
"EXTRA SPELL",
"Bound Cuirass",
"Bound Helm",
"Bound Boots",
"Bound Shield",
"Bound Gloves",
"Corprus",
"Vampirism",
"Summon Centurion Sphere",
"Sun Damage",
"Stunted Magicka",
"Summon Fabricant",
"sEffectSummonCreature01",
"sEffectSummonCreature02",
"sEffectSummonCreature03",
"sEffectSummonCreature04",
"sEffectSummonCreature05"
};
if (idx >= 0 && idx <= 143)
return magicEffectLabels[idx];
else
return "Invalid";
}
std::string attributeLabel(int idx)
{
const char* attributeLabels [] = {
"Strength",
"Intelligence",
"Willpower",
"Agility",
"Speed",
"Endurance",
"Personality",
"Luck"
};
if (idx >= 0 && idx <= 7)
return attributeLabels[idx];
else
return "Invalid";
}
std::string spellTypeLabel(int idx)
{
const char* spellTypeLabels [] = {
"Spells",
"Abilities",
"Blight Disease",
"Disease",
"Curse",
"Powers"
};
if (idx >= 0 && idx <= 5)
return spellTypeLabels[idx];
else
return "Invalid";
}
std::string specializationLabel(int idx)
{
const char* specializationLabels [] = {
"Combat",
"Magic",
"Stealth"
};
if (idx >= 0 && idx <= 2)
return specializationLabels[idx];
else
return "Invalid";
}
std::string skillLabel(int idx)
{
const char* skillLabels [] = {
"Block",
"Armorer",
"Medium Armor",
"Heavy Armor",
"Blunt Weapon",
"Long Blade",
"Axe",
"Spear",
"Athletics",
"Enchant",
"Destruction",
"Alteration",
"Illusion",
"Conjuration",
"Mysticism",
"Restoration",
"Alchemy",
"Unarmored",
"Security",
"Sneak",
"Acrobatics",
"Light Armor",
"Short Blade",
"Marksman",
"Mercantile",
"Speechcraft",
"Hand-to-hand"
};
if (idx >= 0 && idx <= 27)
return skillLabels[idx];
else
return "Invalid";
}
std::string apparatusTypeLabel(int idx)
{
const char* apparatusTypeLabels [] = {
"Mortar",
"Alembic",
"Calcinator",
"Retort",
};
if (idx >= 0 && idx <= 3)
return apparatusTypeLabels[idx];
else
return "Invalid";
}
std::string rangeTypeLabel(int idx)
{
const char* rangeTypeLabels [] = {
"Self",
"Touch",
"Target"
};
if (idx >= 0 && idx <= 3)
return rangeTypeLabels[idx];
else
return "Invalid";
}
std::string schoolLabel(int idx)
{
const char* schoolLabels [] = {
"Alteration",
"Conjuration",
"Destruction",
"Illusion",
"Mysticism",
"Restoration"
};
if (idx >= 0 && idx <= 5)
return schoolLabels[idx];
else
return "Invalid";
}
std::string enchantTypeLabel(int idx)
{
const char* enchantTypeLabels [] = {
"Cast Once",
"Cast When Strikes",
"Cast When Used",
"Constant Effect"
};
if (idx >= 0 && idx <= 3)
return enchantTypeLabels[idx];
else
return "Invalid";
}
std::string ruleFunction(int idx)
{
std::string ruleFunctions[] = {
"Reaction Low",
"Reaction High",
"Rank Requirement",
"NPC? Reputation",
"Health Percent",
"Player Reputation",
"NPC Level",
"Player Health Percent",
"Player Magicka",
"Player Fatigue",
"Player Attribute Strength",
"Player Skill Block",
"Player Skill Armorer",
"Player Skill Medium Armor",
"Player Skill Heavy Armor",
"Player Skill Blunt Weapon",
"Player Skill Long Blade",
"Player Skill Axe",
"Player Skill Spear",
"Player Skill Athletics",
"Player Skill Enchant",
"Player Skill Destruction",
"Player Skill Alteration",
"Player Skill Illusion",
"Player Skill Conjuration",
"Player Skill Mysticism",
"Player SKill Restoration",
"Player Skill Alchemy",
"Player Skill Unarmored",
"Player Skill Security",
"Player Skill Sneak",
"Player Skill Acrobatics",
"Player Skill Light Armor",
"Player Skill Short Blade",
"Player Skill Marksman",
"Player Skill Mercantile",
"Player Skill Speechcraft",
"Player Skill Hand to Hand",
"Player Gender",
"Player Expelled from Faction",
"Player Diseased (Common)",
"Player Diseased (Blight)",
"Player Clothing Modifier",
"Player Crime Level",
"Player Same Sex",
"Player Same Race",
"Player Same Faction",
"Faction Rank Difference",
"Player Detected",
"Alarmed",
"Choice Selected",
"Player Attribute Intelligence",
"Player Attribute Willpower",
"Player Attribute Agility",
"Player Attribute Speed",
"Player Attribute Endurance",
"Player Attribute Personality",
"Player Attribute Luck",
"Player Diseased (Corprus)",
"Weather",
"Player is a Vampire",
"Player Level",
"Attacked",
"NPC Talked to Player",
"Player Health",
"Creature Target",
"Friend Hit",
"Fight",
"Hello",
"Alarm",
"Flee",
"Should Attack",
//Unkown but causes NPCs to growl and roar.
"UNKNOWN 72"
};
if (idx >= 0 && idx <= 72)
return ruleFunctions[idx];
else
return "Invalid";
}
// The "unused flag bits" should probably be defined alongside the
// defined bits in the ESM component. The names of the flag bits are
// very inconsistent.
std::string bodyPartFlags(int flags)
{
std::string properties = "";
if (flags == 0) properties += "[None] ";
if (flags & ESM::BodyPart::BPF_Female) properties += "Female ";
if (flags & ESM::BodyPart::BPF_Playable) properties += "Playable ";
int unused = (0xFFFFFFFF ^
(ESM::BodyPart::BPF_Female|
ESM::BodyPart::BPF_Playable));
if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;
}
std::string cellFlags(int flags)
{
std::string properties = "";
if (flags == 0) properties += "[None] ";
if (flags & ESM::Cell::HasWater) properties += "HasWater ";
if (flags & ESM::Cell::Interior) properties += "Interior ";
if (flags & ESM::Cell::NoSleep) properties += "NoSleep ";
if (flags & ESM::Cell::QuasiEx) properties += "QuasiEx ";
// This used value is not in the ESM component.
if (flags & 0x00000040) properties += "Unknown ";
int unused = (0xFFFFFFFF ^
(ESM::Cell::HasWater|
ESM::Cell::Interior|
ESM::Cell::NoSleep|
ESM::Cell::QuasiEx|
0x00000040));
if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;
}
std::string containerFlags(int flags)
{
std::string properties = "";
if (flags == 0) properties += "[None] ";
if (flags & ESM::Container::Unknown) properties += "Unknown ";
if (flags & ESM::Container::Organic) properties += "Organic ";
if (flags & ESM::Container::Respawn) properties += "Respawn ";
int unused = (0xFFFFFFFF ^
(ESM::Container::Unknown|
ESM::Container::Organic|
ESM::Container::Respawn));
if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;
}
std::string creatureFlags(int flags)
{
std::string properties = "";
if (flags == 0) properties += "[None] ";
if (flags & ESM::Creature::None) properties += "All ";
if (flags & ESM::Creature::Walks) properties += "Walks ";
if (flags & ESM::Creature::Swims) properties += "Swims ";
if (flags & ESM::Creature::Flies) properties += "Flies ";
if (flags & ESM::Creature::Biped) properties += "Biped ";
if (flags & ESM::Creature::Respawn) properties += "Respawn ";
if (flags & ESM::Creature::Weapon) properties += "Weapon ";
if (flags & ESM::Creature::Skeleton) properties += "Skeleton ";
if (flags & ESM::Creature::Metal) properties += "Metal ";
if (flags & ESM::Creature::Essential) properties += "Essential ";
int unused = (0xFFFFFFFF ^
(ESM::Creature::None|
ESM::Creature::Walks|
ESM::Creature::Swims|
ESM::Creature::Flies|
ESM::Creature::Biped|
ESM::Creature::Respawn|
ESM::Creature::Weapon|
ESM::Creature::Skeleton|
ESM::Creature::Metal|
ESM::Creature::Essential));
if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;
}
std::string landFlags(int flags)
{
std::string properties = "";
// The ESM component says that this first four bits are used, but
// only the first three bits are used as far as I can tell.
// There's also no enumeration of the bit in the ESM component.
if (flags == 0) properties += "[None] ";
if (flags & 0x00000001) properties += "Unknown1 ";
if (flags & 0x00000004) properties += "Unknown3 ";
if (flags & 0x00000002) properties += "Unknown2 ";
if (flags & 0xFFFFFFF8) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;
}
std::string leveledListFlags(int flags)
{
std::string properties = "";
if (flags == 0) properties += "[None] ";
if (flags & ESM::LeveledListBase::AllLevels) properties += "AllLevels ";
// This flag apparently not present on creature lists...
if (flags & ESM::LeveledListBase::Each) properties += "Each ";
int unused = (0xFFFFFFFF ^
(ESM::LeveledListBase::AllLevels|
ESM::LeveledListBase::Each));
if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;
}
std::string lightFlags(int flags)
{
std::string properties = "";
if (flags == 0) properties += "[None] ";
if (flags & ESM::Light::Dynamic) properties += "Dynamic ";
if (flags & ESM::Light::Fire) properties += "Fire ";
if (flags & ESM::Light::Carry) properties += "Carry ";
if (flags & ESM::Light::Flicker) properties += "Flicker ";
if (flags & ESM::Light::FlickerSlow) properties += "FlickerSlow ";
if (flags & ESM::Light::Pulse) properties += "Pulse ";
if (flags & ESM::Light::PulseSlow) properties += "PulseSlow ";
if (flags & ESM::Light::Negative) properties += "Negative ";
if (flags & ESM::Light::OffDefault) properties += "OffDefault ";
int unused = (0xFFFFFFFF ^
(ESM::Light::Dynamic|
ESM::Light::Fire|
ESM::Light::Carry|
ESM::Light::Flicker|
ESM::Light::FlickerSlow|
ESM::Light::Pulse|
ESM::Light::PulseSlow|
ESM::Light::Negative|
ESM::Light::OffDefault));
if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;
}
std::string magicEffectFlags(int flags)
{
std::string properties = "";
if (flags == 0) properties += "[None] ";
// Enchanting & SpellMaking occur on the same list of effects.
// "EXTRA SPELL" appears in the construction set under both the
// spell making and enchanting tabs as an allowed effect. Since
// most of the effects without this flags are defective in various
// ways, it's still very unclear what these flag bits are.
if (flags & ESM::MagicEffect::SpellMaking) properties += "SpellMaking ";
if (flags & ESM::MagicEffect::Enchanting) properties += "Enchanting ";
if (flags & 0x00000040) properties += "RangeNoSelf ";
if (flags & 0x00000080) properties += "RangeTouch ";
if (flags & 0x00000100) properties += "RangeTarget ";
if (flags & 0x00001000) properties += "Unknown2 ";
if (flags & 0x00000001) properties += "AffectSkill ";
if (flags & 0x00000002) properties += "AffectAttribute ";
if (flags & ESM::MagicEffect::NoDuration) properties += "NoDuration ";
if (flags & 0x00000008) properties += "NoMagnitude ";
if (flags & 0x00000010) properties += "Negative ";
if (flags & 0x00000020) properties += "Unknown1 ";
// ESM componet says 0x800 is negative, but none of the magic
// effects have this flags set.
if (flags & ESM::MagicEffect::Negative) properties += "Unused ";
// Since only Chameleon has this flag it could be anything
// that uniquely distinguishes Chameleon.
if (flags & 0x00002000) properties += "Chameleon ";
if (flags & 0x00004000) properties += "Bound ";
if (flags & 0x00008000) properties += "Summon ";
// Calm, Demoralize, Frenzy, Lock, Open, Rally, Soultrap, Turn Unded
if (flags & 0x00010000) properties += "Unknown3 ";
if (flags & 0x00020000) properties += "Absorb ";
if (flags & 0xFFFC0000) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;
}
std::string npcFlags(int flags)
{
std::string properties = "";
if (flags == 0) properties += "[None] ";
// Mythicmods and the ESM component differ. Mythicmods says
// 0x8=None and 0x10=AutoCalc, while our code defines 0x8 as
// AutoCalc. The former seems to be correct. All Bethesda
// records have bit 0x8 set. A suspiciously large portion of
// females have autocalc turned off.
if (flags & ESM::NPC::Autocalc) properties += "Unknown ";
if (flags & 0x00000010) properties += "Autocalc ";
if (flags & ESM::NPC::Female) properties += "Female ";
if (flags & ESM::NPC::Respawn) properties += "Respawn ";
if (flags & ESM::NPC::Essential) properties += "Essential ";
// These two flags do not appear on any NPCs and may have been
// confused with the flags for creatures.
if (flags & ESM::NPC::Skeleton) properties += "Skeleton ";
if (flags & ESM::NPC::Metal) properties += "Metal ";
// Whether corpses persist is a bit that is unaccounted for,
// however the only unknown bit occurs on ALL records, and
// relatively few NPCs have this bit set.
int unused = (0xFFFFFFFF ^
(ESM::NPC::Autocalc|
0x00000010|
ESM::NPC::Female|
ESM::NPC::Respawn|
ESM::NPC::Essential|
ESM::NPC::Skeleton|
ESM::NPC::Metal));
if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;
}
std::string raceFlags(int flags)
{
std::string properties = "";
if (flags == 0) properties += "[None] ";
// All races have the playable flag set in Bethesda files.
if (flags & ESM::Race::Playable) properties += "Playable ";
if (flags & ESM::Race::Beast) properties += "Beast ";
int unused = (0xFFFFFFFF ^
(ESM::Race::Playable|
ESM::Race::Beast));
if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;
}
std::string spellFlags(int flags)
{
std::string properties = "";
if (flags == 0) properties += "[None] ";
if (flags & ESM::Spell::F_Autocalc) properties += "Autocalc ";
if (flags & ESM::Spell::F_PCStart) properties += "PCStart ";
if (flags & ESM::Spell::F_Always) properties += "Always ";
int unused = (0xFFFFFFFF ^
(ESM::Spell::F_Autocalc|
ESM::Spell::F_PCStart|
ESM::Spell::F_Always));
if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;
}
std::string weaponFlags(int flags)
{
std::string properties = "";
if (flags == 0) properties += "[None] ";
// The interpretation of the flags are still unclear to me.
// Apparently you can't be Silver without being Magical? Many of
// the "Magical" weapons don't have enchantments of any sort.
if (flags & ESM::Weapon::Magical) properties += "Magical ";
if (flags & ESM::Weapon::Silver) properties += "Silver ";
int unused = (0xFFFFFFFF ^
(ESM::Weapon::Magical|
ESM::Weapon::Silver));
if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;
}

64
apps/esmtool/labels.hpp Normal file
View File

@ -0,0 +1,64 @@
#ifndef OPENMW_ESMTOOL_LABELS_H
#define OPENMW_ESMTOOL_LABELS_H
#include <string>
std::string bodyPartLabel(char idx);
std::string meshPartLabel(char idx);
std::string meshTypeLabel(char idx);
std::string clothingTypeLabel(int idx);
std::string armorTypeLabel(int idx);
std::string dialogTypeLabel(int idx);
std::string questStatusLabel(int idx);
std::string creatureTypeLabel(int idx);
std::string soundTypeLabel(int idx);
std::string weaponTypeLabel(int idx);
// This function's a bit different because the types are record types,
// not consecutive values.
std::string aiTypeLabel(int type);
// This one's also a bit different, because it enumerates dialog
// select rule functions, not types. Structurally, it still converts
// indexes to strings for display.
std::string ruleFunction(int idx);
// The labels below here can all be loaded from GMSTs, but are not
// currently because among other things, that requires loading the
// GMSTs before dumping any of the records.
// If the data format supported ordered lists of GMSTs (post 1.0), the
// lists could define the valid values, their localization strings,
// and the indexes for referencing the types in other records in the
// database. Then a single label function could work for all types.
std::string magicEffectLabel(int idx);
std::string attributeLabel(int idx);
std::string spellTypeLabel(int idx);
std::string specializationLabel(int idx);
std::string skillLabel(int idx);
std::string apparatusTypeLabel(int idx);
std::string rangeTypeLabel(int idx);
std::string schoolLabel(int idx);
std::string enchantTypeLabel(int idx);
// The are the flag functions that convert a bitmask into a list of
// human readble strings representing the set bits.
std::string bodyPartFlags(int flags);
std::string cellFlags(int flags);
std::string containerFlags(int flags);
std::string creatureFlags(int flags);
std::string landFlags(int flags);
std::string leveledListFlags(int flags);
std::string lightFlags(int flags);
std::string magicEffectFlags(int flags);
std::string npcFlags(int flags);
std::string raceFlags(int flags);
std::string spellFlags(int flags);
std::string weaponFlags(int flags);
// Missing flags functions:
// aiServicesFlags, possibly more
#endif

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@ namespace EsmTool
protected:
std::string mId;
int mFlags;
int mType;
ESM::NAME mType;
public:
RecordBase () {}
@ -42,7 +42,7 @@ namespace EsmTool
mFlags = flags;
}
int getType() const {
ESM::NAME getType() const {
return mType;
}
@ -50,7 +50,7 @@ namespace EsmTool
virtual void save(ESM::ESMWriter &esm) = 0;
virtual void print() = 0;
static RecordBase *create(int type);
static RecordBase *create(ESM::NAME type);
// just make it a bit shorter
template <class T>

View File

@ -24,6 +24,6 @@ public slots:
};
Q_DECLARE_METATYPE(QVector<QPersistentModelIndex>);
Q_DECLARE_METATYPE(QVector<QPersistentModelIndex>)
#endif
#endif

View File

@ -78,7 +78,7 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(std::string filename) {
multistrmap::iterator it;
if((it = map.find(key)) == map.end()) {
map.insert( std::make_pair<std::string, std::vector<std::string> > (key, std::vector<std::string>() ) );
map.insert( std::make_pair (key, std::vector<std::string>() ) );
}
map[key].push_back(value);
}
@ -115,7 +115,7 @@ MwIniImporter::multistrmap MwIniImporter::loadCfgFile(std::string filename) {
multistrmap::iterator it;
if((it = map.find(key)) == map.end()) {
map.insert( std::make_pair<std::string, std::vector<std::string> > (key, std::vector<std::string>() ) );
map.insert( std::make_pair (key, std::vector<std::string>() ) );
}
map[key].push_back(value);
}
@ -152,12 +152,12 @@ void MwIniImporter::mergeFallback(multistrmap &cfg, multistrmap &ini) {
}
}
}
};
}
void MwIniImporter::insertMultistrmap(multistrmap &cfg, std::string key, std::string value) {
multistrmap::iterator it = cfg.find(key);
if(it == cfg.end()) {
cfg.insert(std::make_pair<std::string, std::vector<std::string> >(key, std::vector<std::string>() ));
cfg.insert(std::make_pair (key, std::vector<std::string>() ));
}
cfg[key].push_back(value);
}

View File

@ -30,7 +30,7 @@ add_openmw_dir (mwgui
formatting inventorywindow container hud countdialog tradewindow settingswindow
confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog
enchantingdialog
enchantingdialog trainingwindow travelwindow
)
add_openmw_dir (mwdialogue
@ -62,7 +62,7 @@ add_openmw_dir (mwclass
add_openmw_dir (mwmechanics
mechanicsmanagerimp stat creaturestats magiceffects movement actors drawstate spells
activespells npcstats aipackage aisequence
activespells npcstats aipackage aisequence alchemy
)
add_openmw_dir (mwbase

View File

@ -163,9 +163,8 @@ void OMW::Engine::loadBSA()
std::cout << "Data dir " << dataDirectory << std::endl;
Bsa::addDir(dataDirectory, mFSStrict);
// Workaround: Mygui does not find textures in non-BSA subfolders, _unless_ they are explicitely added like this
// For splash screens, this is OK to do, but eventually we will need an investigation why this is necessary
Bsa::addDir(dataDirectory + "/Splash", mFSStrict);
// Workaround until resource listing capabilities are added to DirArchive, we need those to list available splash screens
addResourcesDirectory (dataDirectory);
}
}
@ -424,21 +423,10 @@ void OMW::Engine::activate()
if (handle.empty())
return;
// the faced handle is not updated immediately, so on a cell change it might
// point to an object that doesn't exist anymore
// therefore, we are catching the "Unknown Ogre handle" exception that occurs in this case
MWWorld::Ptr ptr;
try
{
ptr = MWBase::Environment::get().getWorld()->getPtrViaHandle (handle);
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaHandle (handle);
if (ptr.isEmpty())
return;
}
catch (std::runtime_error&)
{
if (ptr.isEmpty())
return;
}
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);

View File

@ -68,7 +68,7 @@ void validate(boost::any &v, std::vector<std::string> const &tokens, FallbackMap
if((mapIt = map->mMap.find(key)) == map->mMap.end())
{
map->mMap.insert(std::make_pair<std::string,std::string>(key,value));
map->mMap.insert(std::make_pair (key,value));
}
}
}

View File

@ -37,7 +37,7 @@ namespace MWBase
Play_Normal = 0, /* tracked, non-looping, multi-instance, environment */
Play_Loop = 1<<0, /* Sound will continually loop until explicitly stopped */
Play_NoEnv = 1<<1, /* Do not apply environment effects (eg, underwater filters) */
Play_NoTrack = 1<<2, /* (3D only) Play the sound at the given object's position
Play_NoTrack = 1<<2 /* (3D only) Play the sound at the given object's position
* but do not keep it updated (the sound will not move with
* the object and will not stop when the object is deleted. */
};

View File

@ -42,6 +42,7 @@ namespace MWGui
class Console;
class SpellWindow;
class TradeWindow;
class TravelWindow;
class SpellBuyingWindow;
class ConfirmationDialog;
class CountDialog;
@ -108,6 +109,7 @@ namespace MWBase
virtual MWGui::ConfirmationDialog* getConfirmationDialog() = 0;
virtual MWGui::TradeWindow* getTradeWindow() = 0;
virtual MWGui::SpellBuyingWindow* getSpellBuyingWindow() = 0;
virtual MWGui::TravelWindow* getTravelWindow() = 0;
virtual MWGui::SpellWindow* getSpellWindow() = 0;
virtual MWGui::Console* getConsole() = 0;
@ -230,6 +232,7 @@ namespace MWBase
virtual void startSpellMaking(MWWorld::Ptr actor) = 0;
virtual void startEnchanting(MWWorld::Ptr actor) = 0;
virtual void startTraining(MWWorld::Ptr actor) = 0;
};
}

View File

@ -143,6 +143,9 @@ namespace MWBase
virtual MWWorld::Ptr getPtrViaHandle (const std::string& handle) = 0;
///< Return a pointer to a liveCellRef with the given Ogre handle.
virtual MWWorld::Ptr searchPtrViaHandle (const std::string& handle) = 0;
///< Return a pointer to a liveCellRef with the given Ogre handle or Ptr() if not found
/// \todo enable reference in the OGRE scene
virtual void enable (const MWWorld::Ptr& ptr) = 0;

View File

@ -795,12 +795,18 @@ namespace MWDialogue
|| services & ESM::NPC::Misc)
windowServices |= MWGui::DialogueWindow::Service_Trade;
if( !mActor.get<ESM::NPC>()->base->mTransport.empty())
windowServices |= MWGui::DialogueWindow::Service_Travel;
if (services & ESM::NPC::Spells)
windowServices |= MWGui::DialogueWindow::Service_BuySpells;
if (services & ESM::NPC::Spellmaking)
windowServices |= MWGui::DialogueWindow::Service_CreateSpells;
if (services & ESM::NPC::Training)
windowServices |= MWGui::DialogueWindow::Service_Training;
if (services & ESM::NPC::Enchanting)
windowServices |= MWGui::DialogueWindow::Service_Enchant;

View File

@ -28,25 +28,25 @@ namespace MWGui
{
AlchemyWindow::AlchemyWindow(MWBase::WindowManager& parWindowManager)
: WindowBase("openmw_alchemy_window.layout", parWindowManager)
, ContainerBase(0)
, ContainerBase(0), mApparatus (4), mIngredients (4)
{
getWidget(mCreateButton, "CreateButton");
getWidget(mCancelButton, "CancelButton");
getWidget(mIngredient1, "Ingredient1");
getWidget(mIngredient2, "Ingredient2");
getWidget(mIngredient3, "Ingredient3");
getWidget(mIngredient4, "Ingredient4");
getWidget(mApparatus1, "Apparatus1");
getWidget(mApparatus2, "Apparatus2");
getWidget(mApparatus3, "Apparatus3");
getWidget(mApparatus4, "Apparatus4");
getWidget(mIngredients[0], "Ingredient1");
getWidget(mIngredients[1], "Ingredient2");
getWidget(mIngredients[2], "Ingredient3");
getWidget(mIngredients[3], "Ingredient4");
getWidget(mApparatus[0], "Apparatus1");
getWidget(mApparatus[1], "Apparatus2");
getWidget(mApparatus[2], "Apparatus3");
getWidget(mApparatus[3], "Apparatus4");
getWidget(mEffectsBox, "CreatedEffects");
getWidget(mNameEdit, "NameEdit");
mIngredient1->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
mIngredient2->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
mIngredient3->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
mIngredient4->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
mIngredients[0]->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
mIngredients[1]->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
mIngredients[2]->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
mIngredients[3]->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
mCreateButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCreateButtonClicked);
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCancelButtonClicked);
@ -62,157 +62,52 @@ namespace MWGui
void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender)
{
mAlchemy.clear();
mWindowManager.removeGuiMode(GM_Alchemy);
mWindowManager.removeGuiMode(GM_Inventory);
}
void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender)
{
std::string name = mNameEdit->getCaption();
boost::algorithm::trim(name);
MWMechanics::Alchemy::Result result = mAlchemy.create (mNameEdit->getCaption ());
if (result == MWMechanics::Alchemy::Result_NoName)
{
mWindowManager.messageBox("#{sNotifyMessage37}", std::vector<std::string>());
return;
}
// check if mortar & pestle is available (always needed)
/// \todo check albemic, calcinator, retort (sometimes needed)
if (!mApparatus1->isUserString("ToolTipType"))
if (result == MWMechanics::Alchemy::Result_NoMortarAndPestle)
{
mWindowManager.messageBox("#{sNotifyMessage45}", std::vector<std::string>());
return;
}
// make sure 2 or more ingredients were selected
int numIngreds = 0;
if (mIngredient1->isUserString("ToolTipType"))
++numIngreds;
if (mIngredient2->isUserString("ToolTipType"))
++numIngreds;
if (mIngredient3->isUserString("ToolTipType"))
++numIngreds;
if (mIngredient4->isUserString("ToolTipType"))
++numIngreds;
if (numIngreds < 2)
if (result == MWMechanics::Alchemy::Result_LessThanTwoIngredients)
{
mWindowManager.messageBox("#{sNotifyMessage6a}", std::vector<std::string>());
return;
}
// make sure a name was entered
std::string name = mNameEdit->getCaption();
boost::algorithm::trim(name);
if (name == "")
{
mWindowManager.messageBox("#{sNotifyMessage37}", std::vector<std::string>());
return;
}
// if there are no created effects, the potion will always fail (but the ingredients won't be destroyed)
if (mEffects.empty())
if (result == MWMechanics::Alchemy::Result_NoEffects)
{
mWindowManager.messageBox("#{sNotifyMessage8}", std::vector<std::string>());
MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f);
return;
}
if (rand() % 2 == 0) /// \todo
if (result == MWMechanics::Alchemy::Result_Success)
{
ESM::Potion newPotion;
newPotion.mName = mNameEdit->getCaption();
ESM::EffectList effects;
for (unsigned int i=0; i<4; ++i)
{
if (mEffects.size() >= i+1)
{
ESM::ENAMstruct effect;
effect.mEffectID = mEffects[i].mEffectID;
effect.mArea = 0;
effect.mRange = ESM::RT_Self;
effect.mSkill = mEffects[i].mSkill;
effect.mAttribute = mEffects[i].mAttribute;
effect.mMagnMin = 1; /// \todo
effect.mMagnMax = 10; /// \todo
effect.mDuration = 60; /// \todo
effects.mList.push_back(effect);
}
}
// UESP Wiki / Morrowind:Alchemy
// "The weight of a potion is an average of the weight of the ingredients, rounded down."
// note by scrawl: not rounding down here, I can't imagine a created potion to
// have 0 weight when using ingredients with 0.1 weight respectively
float weight = 0;
if (mIngredient1->isUserString("ToolTipType"))
weight += mIngredient1->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>()->base->mData.mWeight;
if (mIngredient2->isUserString("ToolTipType"))
weight += mIngredient2->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>()->base->mData.mWeight;
if (mIngredient3->isUserString("ToolTipType"))
weight += mIngredient3->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>()->base->mData.mWeight;
if (mIngredient4->isUserString("ToolTipType"))
weight += mIngredient4->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>()->base->mData.mWeight;
newPotion.mData.mWeight = weight / float(numIngreds);
newPotion.mData.mValue = 100; /// \todo
newPotion.mEffects = effects;
// pick a random mesh and icon
std::vector<std::string> names;
/// \todo is the mesh/icon dependent on alchemy skill?
names.push_back("standard");
names.push_back("bargain");
names.push_back("cheap");
names.push_back("fresh");
names.push_back("exclusive");
names.push_back("quality");
int random = rand() % names.size();
newPotion.mModel = "m\\misc_potion_" + names[random ] + "_01.nif";
newPotion.mIcon = "m\\tx_potion_" + names[random ] + "_01.dds";
// check if a similiar potion record exists already
bool found = false;
std::string objectId;
typedef std::map<std::string, ESM::Potion> PotionMap;
PotionMap potions = MWBase::Environment::get().getWorld()->getStore().potions.list;
for (PotionMap::const_iterator it = potions.begin(); it != potions.end(); ++it)
{
if (found) break;
if (it->second.mData.mValue == newPotion.mData.mValue
&& it->second.mData.mWeight == newPotion.mData.mWeight
&& it->second.mName == newPotion.mName
&& it->second.mEffects.mList.size() == newPotion.mEffects.mList.size())
{
// check effects
for (unsigned int i=0; i < it->second.mEffects.mList.size(); ++i)
{
const ESM::ENAMstruct& a = it->second.mEffects.mList[i];
const ESM::ENAMstruct& b = newPotion.mEffects.mList[i];
if (a.mEffectID == b.mEffectID
&& a.mArea == b.mArea
&& a.mRange == b.mRange
&& a.mSkill == b.mSkill
&& a.mAttribute == b.mAttribute
&& a.mMagnMin == b.mMagnMin
&& a.mMagnMax == b.mMagnMax
&& a.mDuration == b.mDuration)
{
found = true;
objectId = it->first;
break;
}
}
}
}
if (!found)
{
std::pair<std::string, const ESM::Potion*> result = MWBase::Environment::get().getWorld()->createRecord(newPotion);
objectId = result.first;
}
// create a reference and add it to player inventory
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), objectId);
MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
ref.getPtr().getRefData().setCount(1);
store.add(ref.getPtr());
mWindowManager.messageBox("#{sPotionSuccess}", std::vector<std::string>());
MWBase::Environment::get().getSoundManager()->playSound("potion success", 1.f, 1.f);
}
else
else if (result == MWMechanics::Alchemy::Result_RandomFailure)
{
// potion failed
mWindowManager.messageBox("#{sNotifyMessage8}", std::vector<std::string>());
@ -220,155 +115,53 @@ namespace MWGui
}
// reduce count of the ingredients
if (mIngredient1->isUserString("ToolTipType"))
{
MWWorld::Ptr ingred = *mIngredient1->getUserData<MWWorld::Ptr>();
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
if (ingred.getRefData().getCount() == 0)
removeIngredient(mIngredient1);
}
if (mIngredient2->isUserString("ToolTipType"))
{
MWWorld::Ptr ingred = *mIngredient2->getUserData<MWWorld::Ptr>();
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
if (ingred.getRefData().getCount() == 0)
removeIngredient(mIngredient2);
}
if (mIngredient3->isUserString("ToolTipType"))
{
MWWorld::Ptr ingred = *mIngredient3->getUserData<MWWorld::Ptr>();
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
if (ingred.getRefData().getCount() == 0)
removeIngredient(mIngredient3);
}
if (mIngredient4->isUserString("ToolTipType"))
{
MWWorld::Ptr ingred = *mIngredient4->getUserData<MWWorld::Ptr>();
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
if (ingred.getRefData().getCount() == 0)
removeIngredient(mIngredient4);
for (int i=0; i<4; ++i)
if (mIngredients[i]->isUserString("ToolTipType"))
{
MWWorld::Ptr ingred = *mIngredients[i]->getUserData<MWWorld::Ptr>();
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
if (ingred.getRefData().getCount() == 0)
removeIngredient(mIngredients[i]);
}
update();
}
void AlchemyWindow::open()
{
openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
setFilter(ContainerBase::Filter_Ingredients);
openContainer (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); // this sets mPtr
setFilter (ContainerBase::Filter_Ingredients);
// pick the best available apparatus
MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
mAlchemy.setAlchemist (mPtr);
MWWorld::Ptr bestAlbemic;
MWWorld::Ptr bestMortarPestle;
MWWorld::Ptr bestCalcinator;
MWWorld::Ptr bestRetort;
int index = 0;
for (MWWorld::ContainerStoreIterator it(store.begin(MWWorld::ContainerStore::Type_Apparatus));
it != store.end(); ++it)
for (MWMechanics::Alchemy::TToolsIterator iter (mAlchemy.beginTools());
iter!=mAlchemy.endTools() && index<static_cast<int> (mApparatus.size()); ++iter, ++index)
{
MWWorld::LiveCellRef<ESM::Apparatus>* ref = it->get<ESM::Apparatus>();
if (ref->base->mData.mType == ESM::Apparatus::Albemic
&& (bestAlbemic.isEmpty() || ref->base->mData.mQuality > bestAlbemic.get<ESM::Apparatus>()->base->mData.mQuality))
bestAlbemic = *it;
else if (ref->base->mData.mType == ESM::Apparatus::MortarPestle
&& (bestMortarPestle.isEmpty() || ref->base->mData.mQuality > bestMortarPestle.get<ESM::Apparatus>()->base->mData.mQuality))
bestMortarPestle = *it;
else if (ref->base->mData.mType == ESM::Apparatus::Calcinator
&& (bestCalcinator.isEmpty() || ref->base->mData.mQuality > bestCalcinator.get<ESM::Apparatus>()->base->mData.mQuality))
bestCalcinator = *it;
else if (ref->base->mData.mType == ESM::Apparatus::Retort
&& (bestRetort.isEmpty() || ref->base->mData.mQuality > bestRetort.get<ESM::Apparatus>()->base->mData.mQuality))
bestRetort = *it;
if (!iter->isEmpty())
{
mApparatus.at (index)->setUserString ("ToolTipType", "ItemPtr");
mApparatus.at (index)->setUserData (*iter);
mApparatus.at (index)->setImageTexture (getIconPath (*iter));
}
}
if (!bestMortarPestle.isEmpty())
{
mApparatus1->setUserString("ToolTipType", "ItemPtr");
mApparatus1->setUserData(bestMortarPestle);
mApparatus1->setImageTexture(getIconPath(bestMortarPestle));
}
if (!bestAlbemic.isEmpty())
{
mApparatus2->setUserString("ToolTipType", "ItemPtr");
mApparatus2->setUserData(bestAlbemic);
mApparatus2->setImageTexture(getIconPath(bestAlbemic));
}
if (!bestCalcinator.isEmpty())
{
mApparatus3->setUserString("ToolTipType", "ItemPtr");
mApparatus3->setUserData(bestCalcinator);
mApparatus3->setImageTexture(getIconPath(bestCalcinator));
}
if (!bestRetort.isEmpty())
{
mApparatus4->setUserString("ToolTipType", "ItemPtr");
mApparatus4->setUserData(bestRetort);
mApparatus4->setImageTexture(getIconPath(bestRetort));
}
update();
}
void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender)
{
removeIngredient(_sender);
drawItems();
update();
}
void AlchemyWindow::onSelectedItemImpl(MWWorld::Ptr item)
{
MyGUI::ImageBox* add = NULL;
int res = mAlchemy.addIngredient(item);
// don't allow to add an ingredient that is already added
// (which could happen if two similiar ingredients don't stack because of script / owner)
bool alreadyAdded = false;
std::string name = MWWorld::Class::get(item).getName(item);
if (mIngredient1->isUserString("ToolTipType"))
if (res != -1)
{
MWWorld::Ptr item2 = *mIngredient1->getUserData<MWWorld::Ptr>();
std::string name2 = MWWorld::Class::get(item2).getName(item2);
if (name == name2)
alreadyAdded = true;
}
if (mIngredient2->isUserString("ToolTipType"))
{
MWWorld::Ptr item2 = *mIngredient2->getUserData<MWWorld::Ptr>();
std::string name2 = MWWorld::Class::get(item2).getName(item2);
if (name == name2)
alreadyAdded = true;
}
if (mIngredient3->isUserString("ToolTipType"))
{
MWWorld::Ptr item2 = *mIngredient3->getUserData<MWWorld::Ptr>();
std::string name2 = MWWorld::Class::get(item2).getName(item2);
if (name == name2)
alreadyAdded = true;
}
if (mIngredient4->isUserString("ToolTipType"))
{
MWWorld::Ptr item2 = *mIngredient4->getUserData<MWWorld::Ptr>();
std::string name2 = MWWorld::Class::get(item2).getName(item2);
if (name == name2)
alreadyAdded = true;
}
if (alreadyAdded)
return;
if (!mIngredient1->isUserString("ToolTipType"))
add = mIngredient1;
if (add == NULL && !mIngredient2->isUserString("ToolTipType"))
add = mIngredient2;
if (add == NULL && !mIngredient3->isUserString("ToolTipType"))
add = mIngredient3;
if (add == NULL && !mIngredient4->isUserString("ToolTipType"))
add = mIngredient4;
if (add != NULL)
{
add->setUserString("ToolTipType", "ItemPtr");
add->setUserData(item);
add->setImageTexture(getIconPath(item));
drawItems();
update();
std::string sound = MWWorld::Class::get(item).getUpSoundId(item);
@ -380,54 +173,40 @@ namespace MWGui
{
std::vector<MWWorld::Ptr> ignore;
// don't show ingredients that are currently selected in the "available ingredients" box.
if (mIngredient1->isUserString("ToolTipType"))
ignore.push_back(*mIngredient1->getUserData<MWWorld::Ptr>());
if (mIngredient2->isUserString("ToolTipType"))
ignore.push_back(*mIngredient2->getUserData<MWWorld::Ptr>());
if (mIngredient3->isUserString("ToolTipType"))
ignore.push_back(*mIngredient3->getUserData<MWWorld::Ptr>());
if (mIngredient4->isUserString("ToolTipType"))
ignore.push_back(*mIngredient4->getUserData<MWWorld::Ptr>());
for (int i=0; i<4; ++i)
if (mIngredients[i]->isUserString("ToolTipType"))
ignore.push_back(*mIngredients[i]->getUserData<MWWorld::Ptr>());
return ignore;
}
void AlchemyWindow::update()
{
Widgets::SpellEffectList effects;
MWMechanics::Alchemy::TIngredientsIterator it = mAlchemy.beginIngredients ();
for (int i=0; i<4; ++i)
{
MyGUI::ImageBox* ingredient;
if (i==0)
ingredient = mIngredient1;
else if (i==1)
ingredient = mIngredient2;
else if (i==2)
ingredient = mIngredient3;
else if (i==3)
ingredient = mIngredient4;
MyGUI::ImageBox* ingredient = mIngredients[i];
if (!ingredient->isUserString("ToolTipType"))
continue;
// add the effects of this ingredient to list of effects
MWWorld::LiveCellRef<ESM::Ingredient>* ref = ingredient->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>();
for (int i=0; i<4; ++i)
MWWorld::Ptr item;
if (it != mAlchemy.endIngredients ())
{
if (ref->base->mData.mEffectID[i] < 0)
continue;
MWGui::Widgets::SpellEffectParams params;
params.mEffectID = ref->base->mData.mEffectID[i];
params.mAttribute = ref->base->mData.mAttributes[i];
params.mSkill = ref->base->mData.mSkills[i];
effects.push_back(params);
item = *it;
++it;
}
// update ingredient count labels
if (ingredient->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0));
ingredient->setImageTexture("");
ingredient->clearUserStrings ();
if (item.isEmpty ())
continue;
ingredient->setUserString("ToolTipType", "ItemPtr");
ingredient->setUserData(item);
ingredient->setImageTexture(getIconPath(item));
MyGUI::TextBox* text = ingredient->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label"));
text->setTextAlign(MyGUI::Align::Right);
text->setNeedMouseFocus(false);
@ -436,49 +215,15 @@ namespace MWGui
text->setCaption(getCountString(ingredient->getUserData<MWWorld::Ptr>()->getRefData().getCount()));
}
// now remove effects that are only present once
Widgets::SpellEffectList::iterator it = effects.begin();
while (it != effects.end())
{
Widgets::SpellEffectList::iterator next = it;
++next;
bool found = false;
for (; next != effects.end(); ++next)
{
if (*next == *it)
found = true;
}
drawItems();
if (!found)
it = effects.erase(it);
else
++it;
}
// now remove duplicates, and don't allow more than 4 effects
Widgets::SpellEffectList old = effects;
effects.clear();
int i=0;
for (Widgets::SpellEffectList::iterator it = old.begin();
it != old.end(); ++it)
std::vector<ESM::ENAMstruct> effects;
ESM::EffectList list;
list.mList = effects;
for (MWMechanics::Alchemy::TEffectsIterator it = mAlchemy.beginEffects (); it != mAlchemy.endEffects (); ++it)
{
bool found = false;
for (Widgets::SpellEffectList::iterator it2 = effects.begin();
it2 != effects.end(); ++it2)
{
// MW considers all "foritfy attribute" effects as the same effect. See the
// "Can't create multi-state boost potions" discussion on http://www.uesp.net/wiki/Morrowind_talk:Alchemy
// thus, we are only checking effectID here and not attribute or skill
if (it2->mEffectID == it->mEffectID)
found = true;
}
if (!found && i<4)
{
++i;
effects.push_back(*it);
}
list.mList.push_back(*it);
}
mEffects = effects;
while (mEffectsBox->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mEffectsBox->getChildAt(0));
@ -487,7 +232,9 @@ namespace MWGui
Widgets::MWEffectListPtr effectsWidget = mEffectsBox->createWidget<Widgets::MWEffectList>
("MW_StatName", coord, MyGUI::Align::Left | MyGUI::Align::Top);
effectsWidget->setWindowManager(&mWindowManager);
effectsWidget->setEffectList(effects);
Widgets::SpellEffectList _list = Widgets::MWEffectList::effectListFromESM(&list);
effectsWidget->setEffectList(_list);
std::vector<MyGUI::WidgetPtr> effectItems;
effectsWidget->createEffectWidgets(effectItems, mEffectsBox, coord, false, 0);
@ -496,9 +243,10 @@ namespace MWGui
void AlchemyWindow::removeIngredient(MyGUI::Widget* ingredient)
{
ingredient->clearUserStrings();
static_cast<MyGUI::ImageBox*>(ingredient)->setImageTexture("");
if (ingredient->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0));
for (int i=0; i<4; ++i)
if (mIngredients[i] == ingredient)
mAlchemy.removeIngredient (i);
update();
}
}

View File

@ -1,6 +1,10 @@
#ifndef MWGUI_ALCHEMY_H
#define MWGUI_ALCHEMY_H
#include <vector>
#include "../mwmechanics/alchemy.hpp"
#include "window_base.hpp"
#include "container.hpp"
#include "widgets.hpp"
@ -18,22 +22,10 @@ namespace MWGui
MyGUI::Button* mCreateButton;
MyGUI::Button* mCancelButton;
MyGUI::ImageBox* mIngredient1;
MyGUI::ImageBox* mIngredient2;
MyGUI::ImageBox* mIngredient3;
MyGUI::ImageBox* mIngredient4;
MyGUI::ImageBox* mApparatus1;
MyGUI::ImageBox* mApparatus2;
MyGUI::ImageBox* mApparatus3;
MyGUI::ImageBox* mApparatus4;
MyGUI::Widget* mEffectsBox;
MyGUI::EditBox* mNameEdit;
Widgets::SpellEffectList mEffects; // effects of created potion
void onCancelButtonClicked(MyGUI::Widget* _sender);
void onCreateButtonClicked(MyGUI::Widget* _sender);
void onIngredientSelected(MyGUI::Widget* _sender);
@ -46,6 +38,13 @@ namespace MWGui
virtual void onReferenceUnavailable() { ; }
void update();
private:
MWMechanics::Alchemy mAlchemy;
std::vector<MyGUI::ImageBox *> mApparatus;
std::vector<MyGUI::ImageBox *> mIngredients;
};
}

View File

@ -14,6 +14,16 @@
using namespace MWGui;
using namespace Widgets;
namespace
{
bool sortBirthSigns(const std::pair<std::string, const ESM::BirthSign*>& left, const std::pair<std::string, const ESM::BirthSign*>& right)
{
return left.second->mName.compare (right.second->mName) < 0;
}
}
BirthDialog::BirthDialog(MWBase::WindowManager& parWindowManager)
: WindowBase("openmw_chargen_birth.layout", parWindowManager)
{
@ -115,11 +125,21 @@ void BirthDialog::updateBirths()
ESMS::RecListT<ESM::BirthSign>::MapType::const_iterator it = store.birthSigns.list.begin();
ESMS::RecListT<ESM::BirthSign>::MapType::const_iterator end = store.birthSigns.list.end();
int index = 0;
for (; it != end; ++it)
// sort by name
std::vector < std::pair<std::string, const ESM::BirthSign*> > birthSigns;
for (; it!=end; ++it)
{
const ESM::BirthSign &birth = it->second;
mBirthList->addItem(birth.mName, it->first);
if (boost::iequals(it->first, mCurrentBirthId))
std::string id = it->first;
const ESM::BirthSign* sign = &it->second;
birthSigns.push_back(std::make_pair(id, sign));
}
std::sort(birthSigns.begin(), birthSigns.end(), sortBirthSigns);
for (std::vector < std::pair<std::string, const ESM::BirthSign*> >::const_iterator it2 = birthSigns.begin(); it2 != birthSigns.end(); ++it2)
{
mBirthList->addItem(it2->second->mName, it2->first);
if (boost::iequals(it2->first, mCurrentBirthId))
mBirthList->setIndexSelected(index);
++index;
}

View File

@ -19,6 +19,7 @@
#include "tradewindow.hpp"
#include "spellbuyingwindow.hpp"
#include "inventorywindow.hpp"
#include "travelwindow.hpp"
using namespace MWGui;
using namespace Widgets;
@ -137,6 +138,11 @@ void DialogueWindow::onSelectTopic(std::string topic)
mWindowManager.pushGuiMode(GM_SpellBuying);
mWindowManager.getSpellBuyingWindow()->startSpellBuying(mPtr);
}
else if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sTravel")->getString())
{
mWindowManager.pushGuiMode(GM_Travel);
mWindowManager.getTravelWindow()->startTravel(mPtr);
}
else if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sSpellMakingMenuTitle")->getString())
{
mWindowManager.pushGuiMode(GM_SpellCreation);
@ -147,6 +153,11 @@ void DialogueWindow::onSelectTopic(std::string topic)
mWindowManager.pushGuiMode(GM_Enchanting);
mWindowManager.startEnchanting (mPtr);
}
else if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sServiceTrainingTitle")->getString())
{
mWindowManager.pushGuiMode(GM_Training);
mWindowManager.startTraining (mPtr);
}
else
MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(topic));
}
@ -175,12 +186,18 @@ void DialogueWindow::setKeywords(std::list<std::string> keyWords)
if (mServices & Service_BuySpells)
mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sSpells")->getString());
if (mServices & Service_Travel)
mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sTravel")->getString());
if (mServices & Service_CreateSpells)
mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sSpellmakingMenuTitle")->getString());
if (mServices & Service_Enchant)
mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sEnchanting")->getString());
if (mServices & Service_Training)
mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sServiceTrainingTitle")->getString());
if (anyService)
mTopicsList->addSeparator();

View File

@ -48,7 +48,6 @@ namespace MWGui
void askQuestion(std::string question);
void goodbye();
// various service button visibilities, depending if the npc/creature talked to has these services
// make sure to call these before setKeywords()
void setServices(int services) { mServices = services; }
@ -57,7 +56,9 @@ namespace MWGui
Service_Trade = 0x01,
Service_BuySpells = 0x02,
Service_CreateSpells = 0x04,
Service_Enchant = 0x08
Service_Enchant = 0x08,
Service_Training = 0x10,
Service_Travel = 0x20
};
protected:
@ -76,10 +77,6 @@ namespace MWGui
*/
std::string parseText(std::string text);
// various service button visibilities, depending if the npc/creature talked to has these services
bool mShowTrade;
bool mShowSpells;
int mServices;
bool mEnabled;

View File

@ -245,15 +245,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender)
return;
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle();
MWWorld::Ptr object;
try
{
object = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle);
}
catch (std::exception& /* e */)
{
return;
}
MWWorld::Ptr object = MWBase::Environment::get().getWorld()->searchPtrViaHandle(handle);
if (mode == GM_Console)
MWBase::Environment::get().getWindowManager()->getConsole()->setSelectedObject(object);

View File

@ -6,10 +6,13 @@
#include <OgreCompositorChain.h>
#include <OgreMaterial.h>
#include <boost/algorithm/string.hpp>
#include <openengine/ogre/fader.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/inputmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
@ -106,6 +109,7 @@ namespace MWGui
if (mTimer.getMilliseconds () > mLastRenderTime + (1.f/loadingScreenFps) * 1000.f)
{
float dt = mTimer.getMilliseconds () - mLastRenderTime;
mLastRenderTime = mTimer.getMilliseconds ();
if (mFirstLoad && mTimer.getMilliseconds () > mLastWallpaperChangeTime + 3000*1)
@ -151,6 +155,8 @@ namespace MWGui
}
}
MWBase::Environment::get().getWorld ()->getFader ()->update (dt);
mWindow->update();
if (!hasCompositor)
@ -207,20 +213,22 @@ namespace MWGui
void LoadingScreen::changeWallpaper ()
{
/// \todo use a directory listing here
std::vector<std::string> splash;
splash.push_back ("Splash_Bonelord.tga");
splash.push_back ("Splash_ClannDaddy.tga");
splash.push_back ("Splash_Clannfear.tga");
splash.push_back ("Splash_Daedroth.tga");
splash.push_back ("Splash_Hunger.tga");
splash.push_back ("Splash_KwamaWarrior.tga");
splash.push_back ("Splash_Netch.tga");
splash.push_back ("Splash_NixHound.tga");
splash.push_back ("Splash_Siltstriker.tga");
splash.push_back ("Splash_Skeleton.tga");
splash.push_back ("Splash_SphereCenturion.tga");
mBackgroundImage->setImageTexture (splash[rand() % splash.size()]);
Ogre::StringVectorPtr resources = Ogre::ResourceGroupManager::getSingleton ().listResourceNames ("General", false);
for (Ogre::StringVector::const_iterator it = resources->begin(); it != resources->end(); ++it)
{
if (it->size() < 6)
continue;
std::string start = it->substr(0, 6);
boost::to_lower(start);
if (start == "splash")
splash.push_back (*it);
}
std::string randomSplash = splash[rand() % splash.size()];
Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton ().load (randomSplash, "General");
mBackgroundImage->setImageTexture (randomSplash);
}
}

View File

@ -22,8 +22,10 @@ namespace MWGui
GM_Rest,
GM_RestBed,
GM_SpellBuying,
GM_Travel,
GM_SpellCreation,
GM_Enchanting,
GM_Training,
GM_Levelup,

View File

@ -54,7 +54,7 @@ namespace MWGui
MyGUI::Button* toAdd =
mSpellsView->createWidget<MyGUI::Button>(
(price>mWindowManager.getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SpellText",
(price>mWindowManager.getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton",
0,
mCurrentY,
200,

View File

@ -79,14 +79,10 @@ void ToolTips::onFrame(float frameDuration)
|| (mWindowManager->getMode() == GM_Inventory)))
{
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle();
try
{
mFocusObject = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle);
}
catch (std::exception /* & e */)
{
mFocusObject = MWBase::Environment::get().getWorld()->searchPtrViaHandle(handle);
if (mFocusObject.isEmpty ())
return;
}
MyGUI::IntSize tooltipSize = getToolTipViaPtr(true);

View File

@ -0,0 +1,159 @@
#include "trainingwindow.hpp"
#include <boost/lexical_cast.hpp>
#include <openengine/ogre/fader.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "inventorywindow.hpp"
#include "tradewindow.hpp"
#include "tooltips.hpp"
namespace MWGui
{
TrainingWindow::TrainingWindow(MWBase::WindowManager &parWindowManager)
: WindowBase("openmw_trainingwindow.layout", parWindowManager)
, mFadeTimeRemaining(0)
{
getWidget(mTrainingOptions, "TrainingOptions");
getWidget(mCancelButton, "CancelButton");
getWidget(mPlayerGold, "PlayerGold");
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TrainingWindow::onCancelButtonClicked);
}
void TrainingWindow::open()
{
center();
}
void TrainingWindow::startTraining (MWWorld::Ptr actor)
{
mPtr = actor;
mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast<std::string>(mWindowManager.getInventoryWindow()->getPlayerGold()));
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(actor).getNpcStats (actor);
// NPC can train you in his best 3 skills
std::vector< std::pair<int, int> > bestSkills;
bestSkills.push_back (std::make_pair(-1, -1));
bestSkills.push_back (std::make_pair(-1, -1));
bestSkills.push_back (std::make_pair(-1, -1));
for (int i=0; i<ESM::Skill::Length; ++i)
{
int value = npcStats.getSkill (i).getBase ();
for (int j=0; j<3; ++j)
{
if (value > bestSkills[j].second)
{
if (j<2)
{
bestSkills[j+1] = bestSkills[j];
}
bestSkills[j] = std::make_pair(i, value);
break;
}
}
}
MyGUI::EnumeratorWidgetPtr widgets = mTrainingOptions->getEnumerator ();
MyGUI::Gui::getInstance ().destroyWidgets (widgets);
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ();
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
for (int i=0; i<3; ++i)
{
/// \todo mercantile skill
int price = pcStats.getSkill (bestSkills[i].first).getBase() * MWBase::Environment::get().getWorld ()->getStore ().gameSettings.find("iTrainingMod")->getInt ();
std::string skin = (price > mWindowManager.getInventoryWindow ()->getPlayerGold ()) ? "SandTextGreyedOut" : "SandTextButton";
MyGUI::Button* button = mTrainingOptions->createWidget<MyGUI::Button>(skin,
MyGUI::IntCoord(5, 5+i*18, mTrainingOptions->getWidth()-10, 18), MyGUI::Align::Default);
button->setUserData(bestSkills[i].first);
button->eventMouseButtonClick += MyGUI::newDelegate(this, &TrainingWindow::onTrainingSelected);
button->setCaptionWithReplacing("#{" + ESM::Skill::sSkillNameIds[bestSkills[i].first] + "} - " + boost::lexical_cast<std::string>(price));
button->setSize(button->getTextSize ().width+12, button->getSize().height);
ToolTips::createSkillToolTip (button, bestSkills[i].first);
}
center();
}
void TrainingWindow::onReferenceUnavailable ()
{
mWindowManager.removeGuiMode(GM_Training);
}
void TrainingWindow::onCancelButtonClicked (MyGUI::Widget *sender)
{
mWindowManager.removeGuiMode (GM_Training);
}
void TrainingWindow::onTrainingSelected (MyGUI::Widget *sender)
{
int skillId = *sender->getUserData<int>();
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ();
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
/// \todo mercantile skill
int price = pcStats.getSkill (skillId).getBase() * MWBase::Environment::get().getWorld ()->getStore ().gameSettings.find("iTrainingMod")->getInt ();
if (mWindowManager.getInventoryWindow()->getPlayerGold()<price)
return;
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(mPtr).getNpcStats (mPtr);
if (npcStats.getSkill (skillId).getBase () <= pcStats.getSkill (skillId).getBase ())
{
mWindowManager.messageBox ("#{sServiceTrainingWords}", std::vector<std::string>());
return;
}
// increase skill
MWWorld::LiveCellRef<ESM::NPC> *playerRef = player.get<ESM::NPC>();
const ESM::Class *class_ = MWBase::Environment::get().getWorld()->getStore().classes.find (
playerRef->base->mClass);
pcStats.increaseSkill (skillId, *class_, true);
// remove gold
mWindowManager.getTradeWindow()->addOrRemoveGold(-price);
// go back to game mode
mWindowManager.removeGuiMode (GM_Training);
mWindowManager.removeGuiMode (GM_Dialogue);
// advance time
MWBase::Environment::get().getWorld ()->advanceTime (2);
MWBase::Environment::get().getWorld ()->getFader()->fadeOut(0.25);
mFadeTimeRemaining = 0.5;
}
void TrainingWindow::onFrame(float dt)
{
if (mFadeTimeRemaining <= 0)
return;
mFadeTimeRemaining -= dt;
if (mFadeTimeRemaining <= 0)
MWBase::Environment::get().getWorld ()->getFader()->fadeIn(0.25);
}
}

View File

@ -0,0 +1,36 @@
#ifndef MWGUI_TRAININGWINDOW_H
#define MWGUI_TRAININGWINDOW_H
#include "window_base.hpp"
#include "referenceinterface.hpp"
namespace MWGui
{
class TrainingWindow : public WindowBase, public ReferenceInterface
{
public:
TrainingWindow(MWBase::WindowManager& parWindowManager);
virtual void open();
void startTraining(MWWorld::Ptr actor);
void onFrame(float dt);
protected:
virtual void onReferenceUnavailable ();
void onCancelButtonClicked (MyGUI::Widget* sender);
void onTrainingSelected(MyGUI::Widget* sender);
MyGUI::Widget* mTrainingOptions;
MyGUI::Button* mCancelButton;
MyGUI::TextBox* mPlayerGold;
float mFadeTimeRemaining;
};
}
#endif

View File

@ -0,0 +1,187 @@
#include "travelwindow.hpp"
#include <algorithm>
#include <boost/lexical_cast.hpp>
#include <libs/openengine/ogre/fader.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/manualref.hpp"
#include "../mwmechanics/spells.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "inventorywindow.hpp"
#include "tradewindow.hpp"
namespace MWGui
{
const int TravelWindow::sLineHeight = 18;
TravelWindow::TravelWindow(MWBase::WindowManager& parWindowManager) :
WindowBase("openmw_travel_window.layout", parWindowManager)
, mCurrentY(0)
, mLastPos(0)
{
setCoord(0, 0, 450, 300);
getWidget(mCancelButton, "CancelButton");
getWidget(mPlayerGold, "PlayerGold");
getWidget(mSelect, "Select");
getWidget(mDestinations, "Travel");
getWidget(mDestinationsView, "DestinationsView");
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TravelWindow::onCancelButtonClicked);
mDestinations->setCoord(450/2-mDestinations->getTextSize().width/2,
mDestinations->getTop(),
mDestinations->getTextSize().width,
mDestinations->getHeight());
mSelect->setCoord(8,
mSelect->getTop(),
mSelect->getTextSize().width,
mSelect->getHeight());
}
void TravelWindow::addDestination(const std::string& travelId,ESM::Position pos,bool interior)
{
int price = 0;
if(interior)
{
price = MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fMagesGuildTravel")->getFloat();
}
else
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
ESM::Position PlayerPos = player.getRefData().getPosition();
float d = sqrt( pow(pos.pos[0] - PlayerPos.pos[0],2) + pow(pos.pos[1] - PlayerPos.pos[1],2) + pow(pos.pos[2] - PlayerPos.pos[2],2) );
price = d/MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fTravelMult")->getFloat();
}
MyGUI::Button* toAdd = mDestinationsView->createWidget<MyGUI::Button>((price>mWindowManager.getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton", 0, mCurrentY, 200, sLineHeight, MyGUI::Align::Default);
mCurrentY += sLineHeight;
/// \todo price adjustment depending on merchantile skill
if(interior)
toAdd->setUserString("interior","y");
else
toAdd->setUserString("interior","n");
std::ostringstream oss;
oss << price;
toAdd->setUserString("price",oss.str());
toAdd->setCaptionWithReplacing(travelId+" - "+boost::lexical_cast<std::string>(price)+"#{sgp}");
toAdd->setSize(toAdd->getTextSize().width,sLineHeight);
toAdd->eventMouseWheel += MyGUI::newDelegate(this, &TravelWindow::onMouseWheel);
toAdd->setUserString("Destination", travelId);
toAdd->setUserData(pos);
toAdd->eventMouseButtonClick += MyGUI::newDelegate(this, &TravelWindow::onTravelButtonClick);
mDestinationsWidgetMap.insert(std::make_pair (toAdd, travelId));
}
void TravelWindow::clearDestinations()
{
mDestinationsView->setViewOffset(MyGUI::IntPoint(0,0));
mCurrentY = 0;
while (mDestinationsView->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mDestinationsView->getChildAt(0));
mDestinationsWidgetMap.clear();
}
void TravelWindow::startTravel(const MWWorld::Ptr& actor)
{
center();
mPtr = actor;
clearDestinations();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
for(unsigned int i = 0;i<mPtr.get<ESM::NPC>()->base->mTransport.size();i++)
{
std::string cellname = mPtr.get<ESM::NPC>()->base->mTransport[i].mCellName;
bool interior = true;
int x,y;
MWBase::Environment::get().getWorld()->positionToIndex(mPtr.get<ESM::NPC>()->base->mTransport[i].mPos.pos[0],
mPtr.get<ESM::NPC>()->base->mTransport[i].mPos.pos[1],x,y);
if(cellname == "") {cellname = MWBase::Environment::get().getWorld()->getExterior(x,y)->cell->mName; interior= false;}
addDestination(cellname,mPtr.get<ESM::NPC>()->base->mTransport[i].mPos,interior);
}
updateLabels();
mDestinationsView->setCanvasSize (MyGUI::IntSize(mDestinationsView->getWidth(), std::max(mDestinationsView->getHeight(), mCurrentY)));
}
void TravelWindow::onTravelButtonClick(MyGUI::Widget* _sender)
{
std::istringstream iss(_sender->getUserString("price"));
int price;
iss >> price;
if (mWindowManager.getInventoryWindow()->getPlayerGold()<price)
return;
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(1);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
ESM::Position pos = *_sender->getUserData<ESM::Position>();
std::string cellname = _sender->getUserString("Destination");
int x,y;
bool interior = _sender->getUserString("interior") == "y";
MWBase::Environment::get().getWorld()->positionToIndex(pos.pos[0],pos.pos[1],x,y);
MWWorld::CellStore* cell;
if(interior) cell = MWBase::Environment::get().getWorld()->getInterior(cellname);
else
{
cell = MWBase::Environment::get().getWorld()->getExterior(x,y);
ESM::Position PlayerPos = player.getRefData().getPosition();
float d = sqrt( pow(pos.pos[0] - PlayerPos.pos[0],2) + pow(pos.pos[1] - PlayerPos.pos[1],2) + pow(pos.pos[2] - PlayerPos.pos[2],2) );
int time = int(d /MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fTravelTimeMult")->getFloat());
for(int i = 0;i < time;i++)
{
MWBase::Environment::get().getMechanicsManager ()->restoreDynamicStats ();
}
MWBase::Environment::get().getWorld()->advanceTime(time);
}
MWBase::Environment::get().getWorld()->moveObject(player,*cell,pos.pos[0],pos.pos[1],pos.pos[2]);
mWindowManager.removeGuiMode(GM_Travel);
mWindowManager.removeGuiMode(GM_Dialogue);
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0);
MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(1);
}
void TravelWindow::onCancelButtonClicked(MyGUI::Widget* _sender)
{
mWindowManager.removeGuiMode(GM_Travel);
}
void TravelWindow::updateLabels()
{
mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast<std::string>(mWindowManager.getInventoryWindow()->getPlayerGold()));
mPlayerGold->setCoord(8,
mPlayerGold->getTop(),
mPlayerGold->getTextSize().width,
mPlayerGold->getHeight());
}
void TravelWindow::onReferenceUnavailable()
{
mWindowManager.removeGuiMode(GM_Travel);
mWindowManager.removeGuiMode(GM_Dialogue);
}
void TravelWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{
if (mDestinationsView->getViewOffset().top + _rel*0.3 > 0)
mDestinationsView->setViewOffset(MyGUI::IntPoint(0, 0));
else
mDestinationsView->setViewOffset(MyGUI::IntPoint(0, mDestinationsView->getViewOffset().top + _rel*0.3));
}
}

View File

@ -0,0 +1,55 @@
#ifndef MWGUI_TravelWINDOW_H
#define MWGUI_TravelWINDOW_H
#include "container.hpp"
#include "window_base.hpp"
#include "../mwworld/ptr.hpp"
namespace MyGUI
{
class Gui;
class Widget;
}
namespace MWGui
{
class WindowManager;
}
namespace MWGui
{
class TravelWindow : public ReferenceInterface, public WindowBase
{
public:
TravelWindow(MWBase::WindowManager& parWindowManager);
void startTravel(const MWWorld::Ptr& actor);
protected:
MyGUI::Button* mCancelButton;
MyGUI::TextBox* mPlayerGold;
MyGUI::TextBox* mDestinations;
MyGUI::TextBox* mSelect;
MyGUI::ScrollView* mDestinationsView;
std::map<MyGUI::Widget*, std::string> mDestinationsWidgetMap;
void onCancelButtonClicked(MyGUI::Widget* _sender);
void onTravelButtonClick(MyGUI::Widget* _sender);
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
void addDestination(const std::string& destinationID,ESM::Position pos,bool interior);
void clearDestinations();
int mLastPos,mCurrentY;
static const int sLineHeight;
void updateLabels();
virtual void onReferenceUnavailable();
};
}
#endif

View File

@ -38,6 +38,7 @@
#include "countdialog.hpp"
#include "tradewindow.hpp"
#include "spellbuyingwindow.hpp"
#include "travelwindow.hpp"
#include "settingswindow.hpp"
#include "confirmationdialog.hpp"
#include "alchemywindow.hpp"
@ -48,6 +49,7 @@
#include "waitdialog.hpp"
#include "spellcreationdialog.hpp"
#include "enchantingdialog.hpp"
#include "trainingwindow.hpp"
using namespace MWGui;
@ -69,6 +71,7 @@ WindowManager::WindowManager(
, mCountDialog(NULL)
, mTradeWindow(NULL)
, mSpellBuyingWindow(NULL)
, mTravelWindow(NULL)
, mSettingsWindow(NULL)
, mConfirmationDialog(NULL)
, mAlchemyWindow(NULL)
@ -79,6 +82,7 @@ WindowManager::WindowManager(
, mWaitDialog(NULL)
, mSpellCreationDialog(NULL)
, mEnchantingDialog(NULL)
, mTrainingWindow(NULL)
, mPlayerClass()
, mPlayerName()
, mPlayerRaceId()
@ -145,6 +149,7 @@ WindowManager::WindowManager(
mInventoryWindow = new InventoryWindow(*this,mDragAndDrop);
mTradeWindow = new TradeWindow(*this);
mSpellBuyingWindow = new SpellBuyingWindow(*this);
mTravelWindow = new TravelWindow(*this);
mDialogueWindow = new DialogueWindow(*this);
mContainerWindow = new ContainerWindow(*this,mDragAndDrop);
mHud = new HUD(w,h, mShowFPSLevel, mDragAndDrop);
@ -161,6 +166,7 @@ WindowManager::WindowManager(
mWaitDialog = new WaitDialog(*this);
mSpellCreationDialog = new SpellCreationDialog(*this);
mEnchantingDialog = new EnchantingDialog(*this);
mTrainingWindow = new TrainingWindow(*this);
mLoadingScreen = new LoadingScreen(mOgre->getScene (), mOgre->getWindow (), *this);
mLoadingScreen->onResChange (w,h);
@ -209,6 +215,7 @@ WindowManager::~WindowManager()
delete mScrollWindow;
delete mTradeWindow;
delete mSpellBuyingWindow;
delete mTravelWindow;
delete mSettingsWindow;
delete mConfirmationDialog;
delete mAlchemyWindow;
@ -218,6 +225,7 @@ WindowManager::~WindowManager()
delete mWaitDialog;
delete mSpellCreationDialog;
delete mEnchantingDialog;
delete mTrainingWindow;
cleanupGarbage();
@ -261,6 +269,7 @@ void WindowManager::updateVisible()
mBookWindow->setVisible(false);
mTradeWindow->setVisible(false);
mSpellBuyingWindow->setVisible(false);
mTravelWindow->setVisible(false);
mSettingsWindow->setVisible(false);
mAlchemyWindow->setVisible(false);
mSpellWindow->setVisible(false);
@ -269,6 +278,7 @@ void WindowManager::updateVisible()
mWaitDialog->setVisible(false);
mSpellCreationDialog->setVisible(false);
mEnchantingDialog->setVisible(false);
mTrainingWindow->setVisible(false);
mHud->setVisible(true);
@ -369,12 +379,18 @@ void WindowManager::updateVisible()
case GM_SpellBuying:
mSpellBuyingWindow->setVisible(true);
break;
case GM_Travel:
mTravelWindow->setVisible(true);
break;
case GM_SpellCreation:
mSpellCreationDialog->setVisible(true);
break;
case GM_Enchanting:
mEnchantingDialog->setVisible(true);
break;
case GM_Training:
mTrainingWindow->setVisible(true);
break;
case GM_InterMessageBox:
break;
case GM_Journal:
@ -574,6 +590,9 @@ void WindowManager::onFrame (float frameDuration)
mHud->onFrame(frameDuration);
mTrainingWindow->onFrame (frameDuration);
mTrainingWindow->checkReferenceAvailable();
mDialogueWindow->checkReferenceAvailable();
mTradeWindow->checkReferenceAvailable();
mSpellBuyingWindow->checkReferenceAvailable();
@ -862,6 +881,7 @@ MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; }
MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; }
MWGui::TradeWindow* WindowManager::getTradeWindow() { return mTradeWindow; }
MWGui::SpellBuyingWindow* WindowManager::getSpellBuyingWindow() { return mSpellBuyingWindow; }
MWGui::TravelWindow* WindowManager::getTravelWindow() { return mTravelWindow; }
MWGui::SpellWindow* WindowManager::getSpellWindow() { return mSpellWindow; }
MWGui::Console* WindowManager::getConsole() { return mConsole; }
@ -993,3 +1013,8 @@ void WindowManager::startEnchanting (MWWorld::Ptr actor)
{
mEnchantingDialog->startEnchanting (actor);
}
void WindowManager::startTraining(MWWorld::Ptr actor)
{
mTrainingWindow->startTraining(actor);
}

View File

@ -66,6 +66,7 @@ namespace MWGui
class WaitDialog;
class SpellCreationDialog;
class EnchantingDialog;
class TrainingWindow;
class WindowManager : public MWBase::WindowManager
{
@ -113,6 +114,7 @@ namespace MWGui
virtual MWGui::ConfirmationDialog* getConfirmationDialog();
virtual MWGui::TradeWindow* getTradeWindow();
virtual MWGui::SpellBuyingWindow* getSpellBuyingWindow();
virtual MWGui::TravelWindow* getTravelWindow();
virtual MWGui::SpellWindow* getSpellWindow();
virtual MWGui::Console* getConsole();
@ -215,6 +217,7 @@ namespace MWGui
virtual void startSpellMaking(MWWorld::Ptr actor);
virtual void startEnchanting(MWWorld::Ptr actor);
virtual void startTraining(MWWorld::Ptr actor);
private:
OEngine::GUI::MyGUIManager *mGuiManager;
@ -235,6 +238,7 @@ namespace MWGui
CountDialog* mCountDialog;
TradeWindow* mTradeWindow;
SpellBuyingWindow* mSpellBuyingWindow;
TravelWindow* mTravelWindow;
SettingsWindow* mSettingsWindow;
ConfirmationDialog* mConfirmationDialog;
AlchemyWindow* mAlchemyWindow;
@ -245,6 +249,7 @@ namespace MWGui
WaitDialog* mWaitDialog;
SpellCreationDialog* mSpellCreationDialog;
EnchantingDialog* mEnchantingDialog;
TrainingWindow* mTrainingWindow;
CharacterCreation* mCharGen;

View File

@ -118,18 +118,14 @@ namespace MWMechanics
+ fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified ());
}
}
}
void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr)
{
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
// attributes
for (int i=0; i<5; ++i)
for (int i=0; i<8; ++i)
{
int modifier =
creatureStats.getMagicEffects().get (EffectKey (79, i)).mMagnitude;

View File

@ -0,0 +1,490 @@
#include "alchemy.hpp"
#include <cassert>
#include <cstdlib>
#include <algorithm>
#include <stdexcept>
#include <components/esm/loadskil.hpp>
#include <components/esm/loadappa.hpp>
#include <components/esm/loadgmst.hpp>
#include <components/esm/loadmgef.hpp>
#include <components/esm_store/store.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwworld/manualref.hpp"
#include "magiceffects.hpp"
#include "creaturestats.hpp"
#include "npcstats.hpp"
std::set<MWMechanics::EffectKey> MWMechanics::Alchemy::listEffects() const
{
std::set<EffectKey> effects;
for (TIngredientsIterator iter (mIngredients.begin()); iter!=mIngredients.end(); ++iter)
{
if (!iter->isEmpty())
{
const MWWorld::LiveCellRef<ESM::Ingredient> *ingredient = iter->get<ESM::Ingredient>();
for (int i=0; i<4; ++i)
if (ingredient->base->mData.mEffectID[i]!=-1)
effects.insert (EffectKey (
ingredient->base->mData.mEffectID[i], ingredient->base->mData.mSkills[i]!=-1 ?
ingredient->base->mData.mSkills[i] : ingredient->base->mData.mAttributes[i]));
}
}
return effects;
}
void MWMechanics::Alchemy::filterEffects (std::set<EffectKey>& effects) const
{
std::set<EffectKey>::iterator iter = effects.begin();
while (iter!=effects.end())
{
bool remove = false;
const EffectKey& key = *iter;
{ // dodge pointless g++ warning
for (TIngredientsIterator iter (mIngredients.begin()); iter!=mIngredients.end(); ++iter)
{
bool found = false;
if (iter->isEmpty())
continue;
const MWWorld::LiveCellRef<ESM::Ingredient> *ingredient = iter->get<ESM::Ingredient>();
for (int i=0; i<4; ++i)
if (key.mId==ingredient->base->mData.mEffectID[i] &&
(key.mArg==ingredient->base->mData.mSkills[i] ||
key.mArg==ingredient->base->mData.mAttributes[i]))
{
found = true;
break;
}
if (!found)
{
remove = true;
break;
}
}
}
if (remove)
effects.erase (iter++);
else
++iter;
}
}
void MWMechanics::Alchemy::applyTools (int flags, float& value) const
{
bool magnitude = !(flags & ESM::MagicEffect::NoMagnitude);
bool duration = !(flags & ESM::MagicEffect::NoDuration);
bool negative = flags & (ESM::MagicEffect::Negative | ESM::MagicEffect::Harmful);
int tool = negative ? ESM::Apparatus::Retort : ESM::Apparatus::Albemic;
int setup = 0;
if (!mTools[tool].isEmpty() && !mTools[ESM::Apparatus::Calcinator].isEmpty())
setup = 1;
else if (!mTools[tool].isEmpty())
setup = 2;
else if (!mTools[ESM::Apparatus::Calcinator].isEmpty())
setup = 3;
else
return;
float toolQuality = setup==1 || setup==2 ? mTools[tool].get<ESM::Apparatus>()->base->mData.mQuality : 0;
float calcinatorQuality = setup==1 || setup==3 ?
mTools[ESM::Apparatus::Calcinator].get<ESM::Apparatus>()->base->mData.mQuality : 0;
float quality = 1;
switch (setup)
{
case 1:
quality = negative ? 2 * toolQuality + 3 * calcinatorQuality :
(magnitude && duration ?
2 * toolQuality + calcinatorQuality : 2/3.0 * (toolQuality + calcinatorQuality) + 0.5);
break;
case 2:
quality = negative ? 1+toolQuality : (magnitude && duration ? toolQuality : toolQuality + 0.5);
break;
case 3:
quality = magnitude && duration ? calcinatorQuality : calcinatorQuality + 0.5;
break;
}
if (setup==3 || !negative)
{
value += quality;
}
else
{
if (quality==0)
throw std::runtime_error ("invalid derived alchemy apparatus quality");
value /= quality;
}
}
void MWMechanics::Alchemy::updateEffects()
{
mEffects.clear();
mValue = 0;
if (countIngredients()<2 || mAlchemist.isEmpty() || mTools[ESM::Apparatus::MortarPestle].isEmpty())
return;
// find effects
std::set<EffectKey> effects (listEffects());
filterEffects (effects);
// general alchemy factor
float x = getChance();
x *= mTools[ESM::Apparatus::MortarPestle].get<ESM::Apparatus>()->base->mData.mQuality;
x *= MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fPotionStrengthMult")->getFloat();
// value
mValue = static_cast<int> (
x * MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("iAlchemyMod")->getFloat());
// build quantified effect list
for (std::set<EffectKey>::const_iterator iter (effects.begin()); iter!=effects.end(); ++iter)
{
const ESM::MagicEffect *magicEffect =
MWBase::Environment::get().getWorld()->getStore().magicEffects.find (iter->mId);
if (magicEffect->mData.mBaseCost<=0)
throw std::runtime_error ("invalid base cost for magic effect " + iter->mId);
float fPotionT1MagMul =
MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fPotionT1MagMult")->getFloat();
if (fPotionT1MagMul<=0)
throw std::runtime_error ("invalid gmst: fPotionT1MagMul");
float fPotionT1DurMult =
MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fPotionT1DurMult")->getFloat();
if (fPotionT1DurMult<=0)
throw std::runtime_error ("invalid gmst: fPotionT1DurMult");
float magnitude = magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude ?
1 : (x / fPotionT1MagMul) / magicEffect->mData.mBaseCost;
float duration = magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration ?
1 : (x / fPotionT1DurMult) / magicEffect->mData.mBaseCost;
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude))
applyTools (magicEffect->mData.mFlags, magnitude);
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
applyTools (magicEffect->mData.mFlags, duration);
duration = static_cast<int> (duration+0.5);
magnitude = static_cast<int> (magnitude+0.5);
if (magnitude>0 && duration>0)
{
ESM::ENAMstruct effect;
effect.mEffectID = iter->mId;
effect.mSkill = effect.mAttribute = iter->mArg; // somewhat hack-ish, but should work
effect.mRange = 0;
effect.mArea = 0;
effect.mDuration = duration;
effect.mMagnMin = effect.mMagnMax = magnitude;
mEffects.push_back (effect);
}
}
}
const ESM::Potion *MWMechanics::Alchemy::getRecord() const
{
for (ESMS::RecListWithIDT<ESM::Potion>::MapType::const_iterator iter (
MWBase::Environment::get().getWorld()->getStore().potions.list.begin());
iter!=MWBase::Environment::get().getWorld()->getStore().potions.list.end(); ++iter)
{
if (iter->second.mEffects.mList.size()!=mEffects.size())
continue;
bool mismatch = false;
for (int i=0; i<static_cast<int> (iter->second.mEffects.mList.size()); ++iter)
{
const ESM::ENAMstruct& first = iter->second.mEffects.mList[i];
const ESM::ENAMstruct& second = mEffects[i];
if (first.mEffectID!=second.mEffectID ||
first.mArea!=second.mArea ||
first.mRange!=second.mRange ||
first.mSkill!=second.mSkill ||
first.mAttribute!=second.mAttribute ||
first.mMagnMin!=second.mMagnMin ||
first.mMagnMax!=second.mMagnMax ||
first.mDuration!=second.mDuration)
{
mismatch = true;
break;
}
}
if (!mismatch)
return &iter->second;
}
return 0;
}
void MWMechanics::Alchemy::removeIngredients()
{
bool needsUpdate = false;
for (TIngredientsContainer::iterator iter (mIngredients.begin()); iter!=mIngredients.end(); ++iter)
if (!iter->isEmpty())
{
iter->getRefData().setCount (iter->getRefData().getCount()-1);
if (iter->getRefData().getCount()<1)
{
needsUpdate = true;
*iter = MWWorld::Ptr();
}
}
if (needsUpdate)
updateEffects();
}
void MWMechanics::Alchemy::addPotion (const std::string& name)
{
const ESM::Potion *record = getRecord();
if (!record)
{
ESM::Potion newRecord;
newRecord.mData.mWeight = 0;
for (TIngredientsIterator iter (beginIngredients()); iter!=endIngredients(); ++iter)
if (!iter->isEmpty())
newRecord.mData.mWeight += iter->get<ESM::Ingredient>()->base->mData.mWeight;
newRecord.mData.mWeight /= countIngredients();
newRecord.mData.mValue = mValue;
newRecord.mData.mAutoCalc = 0;
newRecord.mName = name;
int index = static_cast<int> (std::rand()/static_cast<double> (RAND_MAX)*6);
assert (index>=0 && index<6);
static const char *name[] = { "standard", "bargain", "cheap", "fresh", "exclusive", "quality" };
newRecord.mModel = "m\\misc_potion_" + std::string (name[index]) + "_01.nif";
newRecord.mIcon = "m\\tx_potion_" + std::string (name[index]) + "_01.dds";
newRecord.mEffects.mList = mEffects;
record = MWBase::Environment::get().getWorld()->createRecord (newRecord).second;
}
MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), record->mId);
MWWorld::Class::get (mAlchemist).getContainerStore (mAlchemist).add (ref.getPtr());
}
void MWMechanics::Alchemy::increaseSkill()
{
MWWorld::Class::get (mAlchemist).skillUsageSucceeded (mAlchemist, ESM::Skill::Alchemy, 0);
}
float MWMechanics::Alchemy::getChance() const
{
const CreatureStats& creatureStats = MWWorld::Class::get (mAlchemist).getCreatureStats (mAlchemist);
const NpcStats& npcStats = MWWorld::Class::get (mAlchemist).getNpcStats (mAlchemist);
return
(npcStats.getSkill (ESM::Skill::Alchemy).getModified() +
0.1 * creatureStats.getAttribute (1).getModified()
+ 0.1 * creatureStats.getAttribute (7).getModified());
}
int MWMechanics::Alchemy::countIngredients() const
{
int ingredients = 0;
for (TIngredientsIterator iter (beginIngredients()); iter!=endIngredients(); ++iter)
if (!iter->isEmpty())
++ingredients;
return ingredients;
}
void MWMechanics::Alchemy::setAlchemist (const MWWorld::Ptr& npc)
{
mAlchemist = npc;
mIngredients.resize (4);
std::fill (mIngredients.begin(), mIngredients.end(), MWWorld::Ptr());
mTools.resize (4);
std::fill (mTools.begin(), mTools.end(), MWWorld::Ptr());
mEffects.clear();
MWWorld::ContainerStore& store = MWWorld::Class::get (npc).getContainerStore (npc);
for (MWWorld::ContainerStoreIterator iter (store.begin (MWWorld::ContainerStore::Type_Apparatus));
iter!=store.end(); ++iter)
{
MWWorld::LiveCellRef<ESM::Apparatus>* ref = iter->get<ESM::Apparatus>();
int type = ref->base->mData.mType;
if (type<0 || type>=static_cast<int> (mTools.size()))
throw std::runtime_error ("invalid apparatus type");
if (!mTools[type].isEmpty())
if (ref->base->mData.mQuality<=mTools[type].get<ESM::Apparatus>()->base->mData.mQuality)
continue;
mTools[type] = *iter;
}
}
MWMechanics::Alchemy::TToolsIterator MWMechanics::Alchemy::beginTools() const
{
return mTools.begin();
}
MWMechanics::Alchemy::TToolsIterator MWMechanics::Alchemy::endTools() const
{
return mTools.end();
}
MWMechanics::Alchemy::TIngredientsIterator MWMechanics::Alchemy::beginIngredients() const
{
return mIngredients.begin();
}
MWMechanics::Alchemy::TIngredientsIterator MWMechanics::Alchemy::endIngredients() const
{
return mIngredients.end();
}
void MWMechanics::Alchemy::clear()
{
mAlchemist = MWWorld::Ptr();
mTools.clear();
mIngredients.clear();
mEffects.clear();
}
int MWMechanics::Alchemy::addIngredient (const MWWorld::Ptr& ingredient)
{
// find a free slot
int slot = -1;
for (int i=0; i<static_cast<int> (mIngredients.size()); ++i)
if (mIngredients[i].isEmpty())
{
slot = i;
break;
}
if (slot==-1)
return -1;
for (TIngredientsIterator iter (mIngredients.begin()); iter!=mIngredients.end(); ++iter)
if (!iter->isEmpty() && ingredient.get<ESM::Ingredient>()==iter->get<ESM::Ingredient>())
return -1;
mIngredients[slot] = ingredient;
updateEffects();
return slot;
}
void MWMechanics::Alchemy::removeIngredient (int index)
{
if (index>=0 && index<static_cast<int> (mIngredients.size()))
{
mIngredients[index] = MWWorld::Ptr();
updateEffects();
}
}
MWMechanics::Alchemy::TEffectsIterator MWMechanics::Alchemy::beginEffects() const
{
return mEffects.begin();
}
MWMechanics::Alchemy::TEffectsIterator MWMechanics::Alchemy::endEffects() const
{
return mEffects.end();
}
std::string MWMechanics::Alchemy::getPotionName() const
{
if (const ESM::Potion *potion = getRecord())
return potion->mName;
return "";
}
MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& name)
{
if (mTools[ESM::Apparatus::MortarPestle].isEmpty())
return Result_NoMortarAndPestle;
if (countIngredients()<2)
return Result_LessThanTwoIngredients;
if (name.empty() && getPotionName().empty())
return Result_NoName;
if (beginEffects()==endEffects())
return Result_NoEffects;
if (getChance()<std::rand()/static_cast<double> (RAND_MAX)*100)
{
removeIngredients();
return Result_RandomFailure;
}
addPotion (name);
removeIngredients();
increaseSkill();
return Result_Success;
}

View File

@ -0,0 +1,121 @@
#ifndef GAME_MWMECHANICS_ALCHEMY_H
#define GAME_MWMECHANICS_ALCHEMY_H
#include <vector>
#include <set>
#include <components/esm/effectlist.hpp>
#include "../mwworld/ptr.hpp"
namespace MWMechanics
{
struct EffectKey;
/// \brief Potion creation via alchemy skill
class Alchemy
{
public:
typedef std::vector<MWWorld::Ptr> TToolsContainer;
typedef TToolsContainer::const_iterator TToolsIterator;
typedef std::vector<MWWorld::Ptr> TIngredientsContainer;
typedef TIngredientsContainer::const_iterator TIngredientsIterator;
typedef std::vector<ESM::ENAMstruct> TEffectsContainer;
typedef TEffectsContainer::const_iterator TEffectsIterator;
enum Result
{
Result_Success,
Result_NoMortarAndPestle,
Result_LessThanTwoIngredients,
Result_NoName,
Result_NoEffects,
Result_RandomFailure
};
private:
MWWorld::Ptr mAlchemist;
TToolsContainer mTools;
TIngredientsContainer mIngredients;
TEffectsContainer mEffects;
int mValue;
std::set<EffectKey> listEffects() const;
///< List all effects of all used ingredients.
void filterEffects (std::set<EffectKey>& effects) const;
///< Filter out effects not shared by all ingredients.
void applyTools (int flags, float& value) const;
void updateEffects();
const ESM::Potion *getRecord() const;
///< Return existing recrod for created potion (may return 0)
void removeIngredients();
///< Remove selected ingredients from alchemist's inventory, cleanup selected ingredients and
/// update effect list accordingly.
void addPotion (const std::string& name);
///< Add a potion to the alchemist's inventory.
void increaseSkill();
///< Increase alchemist's skill.
float getChance() const;
///< Return chance of success.
int countIngredients() const;
public:
void setAlchemist (const MWWorld::Ptr& npc);
///< Set alchemist and configure alchemy setup accordingly. \a npc may be empty to indicate that
/// there is no alchemist (alchemy session has ended).
TToolsIterator beginTools() const;
///< \attention Iterates over tool slots, not over tools. Some of the slots may be empty.
TToolsIterator endTools() const;
TIngredientsIterator beginIngredients() const;
///< \attention Iterates over ingredient slots, not over ingredients. Some of the slots may be empty.
TIngredientsIterator endIngredients() const;
void clear();
///< Remove alchemist, tools and ingredients.
int addIngredient (const MWWorld::Ptr& ingredient);
///< Add ingredient into the next free slot.
///
/// \return Slot index or -1, if adding failed because of no free slot or the ingredient type being
/// listed already.
void removeIngredient (int index);
///< Remove ingredient from slot (calling this function on an empty slot is a no-op).
TEffectsIterator beginEffects() const;
TEffectsIterator endEffects() const;
std::string getPotionName() const;
///< Return the name of the potion that would be created when calling create (if a record for such
/// a potion already exists) or return an empty string.
Result create (const std::string& name);
///< Try to create a potion from the ingredients, place it in the inventory of the alchemist and
/// adjust the skills of the alchemist accordingly.
/// \param name must not be an empty string, unless there is already a potion record (
/// getPotionName() does not return an empty string).
};
}
#endif

View File

@ -8,7 +8,7 @@ namespace MWMechanics
{
DrawState_Weapon = 0,
DrawState_Spell = 1,
DrawState_Nothing = 2,
DrawState_Nothing = 2
};
}

View File

@ -53,7 +53,7 @@ namespace MWRender
{
Ogre::Image image;
Ogre::uchar data[mWidth * mHeight * 3];
std::vector<Ogre::uchar> data (mWidth * mHeight * 3);
for (int x = mMinX; x <= mMaxX; ++x)
{
@ -150,7 +150,7 @@ namespace MWRender
}
}
image.loadDynamicImage (data, mWidth, mHeight, Ogre::PF_B8G8R8);
image.loadDynamicImage (&data[0], mWidth, mHeight, Ogre::PF_B8G8R8);
//image.save (mCacheDir + "/GlobalMap.png");

View File

@ -23,7 +23,7 @@ namespace Ogre
class Entity;
class Vector3;
struct RenderTargetEvent;
};
}
namespace MWRender {

View File

@ -74,6 +74,6 @@ namespace MWScript
///< Return index of the variable of the given name and type in the given script. Will
/// throw an exception, if there is no such script or variable or the type does not match.
};
};
}
#endif

View File

@ -54,6 +54,6 @@ namespace MWSound
#ifndef DEFAULT_DECODER
#define DEFAULT_DECODER (::MWSound::FFmpeg_Decoder)
#endif
};
}
#endif

View File

@ -52,6 +52,6 @@ namespace MWSound
#ifndef DEFAULT_DECODER
#define DEFAULT_DECODER (::MWSound::MpgSnd_Decoder)
#endif
};
}
#endif

View File

@ -66,6 +66,6 @@ namespace MWSound
#ifndef DEFAULT_OUTPUT
#define DEFAULT_OUTPUT (::MWSound::OpenAL_Output)
#endif
};
}
#endif

View File

@ -26,7 +26,7 @@ namespace MWSound
enum Environment {
Env_Normal,
Env_Underwater,
Env_Underwater
};
class SoundManager : public MWBase::SoundManager

View File

@ -326,6 +326,14 @@ namespace MWWorld
}
Ptr World::getPtrViaHandle (const std::string& handle)
{
Ptr res = searchPtrViaHandle (handle);
if (res.isEmpty ())
throw std::runtime_error ("unknown Ogre handle: " + handle);
return res;
}
Ptr World::searchPtrViaHandle (const std::string& handle)
{
if (mPlayer->getPlayer().getRefData().getHandle()==handle)
return mPlayer->getPlayer();
@ -339,7 +347,7 @@ namespace MWWorld
return ptr;
}
throw std::runtime_error ("unknown Ogre handle: " + handle);
return MWWorld::Ptr();
}
void World::enable (const Ptr& reference)
@ -864,12 +872,13 @@ namespace MWWorld
mWeatherManager->update (duration);
// inform the GUI about focused object
try
{
MWWorld::Ptr object = getPtrViaHandle(mFacedHandle);
MWBase::Environment::get().getWindowManager()->setFocusObject(object);
MWWorld::Ptr object = searchPtrViaHandle(mFacedHandle);
// retrieve object dimensions so we know where to place the floating label
MWBase::Environment::get().getWindowManager()->setFocusObject(object);
// retrieve object dimensions so we know where to place the floating label
if (!object.isEmpty ())
{
Ogre::SceneNode* node = object.getRefData().getBaseNode();
Ogre::AxisAlignedBox bounds;
int i;
@ -885,11 +894,6 @@ namespace MWWorld
screenCoords[0], screenCoords[1], screenCoords[2], screenCoords[3]);
}
}
catch (std::runtime_error&)
{
MWWorld::Ptr null;
MWBase::Environment::get().getWindowManager()->setFocusObject(null);
}
if (!mRendering->occlusionQuerySupported())
{

View File

@ -163,6 +163,9 @@ namespace MWWorld
virtual Ptr getPtrViaHandle (const std::string& handle);
///< Return a pointer to a liveCellRef with the given Ogre handle.
virtual Ptr searchPtrViaHandle (const std::string& handle);
///< Return a pointer to a liveCellRef with the given Ogre handle or Ptr() if not found
virtual void enable (const Ptr& ptr);
virtual void disable (const Ptr& ptr);

View File

@ -375,7 +375,7 @@ void addBSA(const std::string& name, const std::string& group)
{
insertBSAFactory();
ResourceGroupManager::getSingleton().
addResourceLocation(name, "BSA", group);
addResourceLocation(name, "BSA", group, true);
}
void addDir(const std::string& name, const bool& fs, const std::string& group)
@ -384,7 +384,7 @@ void addDir(const std::string& name, const bool& fs, const std::string& group)
insertDirFactory();
ResourceGroupManager::getSingleton().
addResourceLocation(name, "Dir", group);
addResourceLocation(name, "Dir", group, true);
}
}

View File

@ -18,8 +18,6 @@ namespace ESM
{
// These are probabilities
char mHello, mU1, mFight, mFlee, mAlarm, mU2, mU3, mU4;
// The last u's might be the skills that this NPC can train you
// in?
int mServices; // See the Services enum
}; // 12 bytes
@ -60,7 +58,7 @@ namespace ESM
AI_Travel = 0x545f4941,
AI_Follow = 0x465f4941,
AI_Escort = 0x455f4941,
AI_Activate = 0x415f4941,
AI_Activate = 0x415f4941
};
/// \note Used for storaging packages in a single container

View File

@ -138,11 +138,11 @@ void ESMWriter::writeHNString(const std::string& name, const std::string& data)
void ESMWriter::writeHNString(const std::string& name, const std::string& data, int size)
{
assert(data.size() <= size);
assert(static_cast<int> (data.size()) <= size);
startSubRecord(name);
writeHString(data);
if (data.size() < size)
if (static_cast<int> (data.size()) < size)
{
for (int i = data.size(); i < size; ++i)
write("\0",1);

View File

@ -26,7 +26,6 @@ struct MagicEffect
NonRecastable = 0x4000, // Does not land if parent spell is already affecting target. Shows "you cannot re-cast" message for self target.
Unreflectable = 0x10000, // Cannot be reflected, the effect always lands normally.
CasterLinked = 0x20000, // Must quench if caster is dead, or not an NPC/creature. Not allowed in containter/door trap spells.
SpellMaking = 0x0200,
Enchanting = 0x0400,
Negative = 0x0800 // A harmful effect. Will determine whether

View File

@ -331,7 +331,7 @@ namespace ESMS
// Find land for the given coordinates. Return null if no mData.
Land *search(int x, int y) const
{
LandMap::const_iterator itr = lands.find(std::make_pair<int, int>(x, y));
LandMap::const_iterator itr = lands.find(std::make_pair (x, y));
if ( itr == lands.end() )
{
return NULL;
@ -350,7 +350,7 @@ namespace ESMS
land->load(esm);
// Store the structure
lands[std::make_pair<int, int>(land->mX, land->mY)] = land;
lands[std::make_pair (land->mX, land->mY)] = land;
}
};

View File

@ -16,6 +16,7 @@ Alexander Olofsson (Ace)
Artem Kotsynyak (greye)
athile
BrotherBrick
Cory F. Cohen (cfcohen)
Cris Mihalache (Mirceam)
Douglas Diniz (Dgdiniz)
Eli2

View File

@ -157,10 +157,15 @@
shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart)
#endif
#if UNDERWATER
#if (UNDERWATER) || (FOG)
shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix)
shUniform(float, waterLevel) @shSharedParameter(waterLevel)
shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position)
#endif
#if UNDERWATER
shUniform(float, waterLevel) @shSharedParameter(waterLevel)
shUniform(float4, lightDirectionWS0) @shAutoConstant(lightDirectionWS0, light_position, 0)
shSampler2D(causticMap)
@ -211,8 +216,12 @@
float3 caustics = float3(1,1,1);
#if UNDERWATER
#if (UNDERWATER) || (FOG)
float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePositionPassthrough,1)).xyz;
#endif
#if UNDERWATER
float3 waterEyePos = float3(1,1,1);
// NOTE: this calculation would be wrong for non-uniform scaling
float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0));

View File

@ -187,11 +187,13 @@
shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart)
#endif
#if (UNDERWATER) || (FOG)
shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix)
shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position)
#endif
#if UNDERWATER
shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix)
shUniform(float, waterLevel) @shSharedParameter(waterLevel)
shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position)
shUniform(float4, lightDirectionWS0) @shAutoConstant(lightDirectionWS0, light_position, 0)
shSampler2D(causticMap)
@ -222,9 +224,12 @@
float3 caustics = float3(1,1,1);
#if (UNDERWATER) || (FOG)
float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePosition,1)).xyz;
#endif
#if UNDERWATER
float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePosition,1)).xyz;
float3 waterEyePos = float3(1,1,1);
// NOTE: this calculation would be wrong for non-uniform scaling
float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0));
@ -373,7 +378,6 @@
shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz);
#if MRT
shOutputColour(1) = float4(depth / far,1,1,1);
#endif

View File

@ -78,6 +78,8 @@ set(MYGUI_FILES
openmw_spellcreation_dialog.layout
openmw_edit_effect.layout
openmw_enchanting_dialog.layout
openmw_trainingwindow.layout
openmw_travel_window.layout
smallbars.png
VeraMono.ttf
markers.png

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout">
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 319 200" name="_Main">
<Widget type="TextBox" skin="NormalText" position="0 5 319 24" name="Select" align="Right Top">
<Property key="TextAlign" value="Center"/>
<Property key="Caption" value="#{sServiceTrainingTitle}"/>
</Widget>
<Widget type="TextBox" skin="SandText" position="5 30 319 24" name="Travel" align="Right Top">
<Property key="TextAlign" value="Left"/>
<Property key="Caption" value="#{sTrainingServiceTitle}"/>
</Widget>
<Widget type="Widget" skin="MW_Box" position="6 54 299 100" align="Left Top" name="TrainingOptions">
</Widget>
<Widget type="TextBox" skin="SandText" position="8 161 200 24" name="PlayerGold" align="Right Top">
<Property key="TextAlign" value="Left"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" position="244 161 60 24" name="CancelButton" align="Right Top">
<Property key="ExpandDirection" value="Left"/>
<Property key="Caption" value="#{sCancel}"/>
</Widget>
</Widget>
</MyGUI>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout">
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 450 300" name="_Main">
<Property key="Visible" value="false"/>
<Widget type="TextBox" skin="SandText" position="8 10 24 24" name="Select" align="Right Top">
<Property key="TextAlign" value="Right"/>
<Property key="Caption" value="#{sTravelServiceTitle}"/>
</Widget>
<Widget type="TextBox" skin="SandText" position="0 0 24 24" name="Travel" align="Right Top">
<Property key="TextAlign" value="Right"/>
<Property key="Caption" value="#D8C09A#{sTravel}"/>
</Widget>
<Widget type="Widget" skin="MW_Box" position="6 31 430 225" align="ALIGN_LEFT ALIGN_STRETCH">
<Widget type="ScrollView" skin="MW_ScrollView" position="4 4 422 217" align="ALIGN_LEFT ALIGN_TOP ALIGN_STRETCH" name="DestinationsView">
<Property key="CanvasAlign" value="Left"/>
</Widget>
</Widget>
<Widget type="TextBox" skin="SandText" position="8 255 24 24" name="PlayerGold" align="Right Top">
<Property key="TextAlign" value="Right"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" position="375 260 60 24" name="CancelButton" align="Right Top">
<Property key="ExpandDirection" value="Left"/>
<Property key="Caption" value="#{sOK}"/>
</Widget>
</Widget>
</MyGUI>

View File

@ -1,5 +1,4 @@
[Desktop Entry]
Version=${OPENMW_VERSION}
Type=Application
Name=OpenMW Launcher
GenericName=Role Playing Game

View File

@ -16,7 +16,7 @@ namespace Physic
pEng = eng;
tr.setIdentity();
pName = name;
};
}
void CMotionState::getWorldTransform(btTransform &worldTrans) const
{

View File

@ -626,4 +626,4 @@ namespace Physic
shape->Shape->getAabb(trans, min, max);
}
}};
}}

View File

@ -40,7 +40,7 @@ Fader::Fader(Ogre::SceneManager* sceneMgr)
Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
node->attachObject(mRectangle);
mRectangle->setVisible(false);
mRectangle->setVisibilityFlags (0x01);
mRectangle->setVisibilityFlags (2048);
}
Fader::~Fader()