mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-04 03:40:14 +00:00
Merge branch 'master' into spellcreation
This commit is contained in:
commit
33361e6539
@ -306,7 +306,7 @@ endif()
|
|||||||
|
|
||||||
# Compiler settings
|
# Compiler settings
|
||||||
if (CMAKE_COMPILER_IS_GNUCC)
|
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!
|
# Silence warnings in OGRE headers. Remove once OGRE got fixed!
|
||||||
add_definitions (-Wno-ignored-qualifiers)
|
add_definitions (-Wno-ignored-qualifiers)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
set(ESMTOOL
|
set(ESMTOOL
|
||||||
esmtool.cpp
|
esmtool.cpp
|
||||||
|
labels.hpp
|
||||||
|
labels.cpp
|
||||||
record.hpp
|
record.hpp
|
||||||
record.cpp
|
record.cpp
|
||||||
)
|
)
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include "record.hpp"
|
#include "record.hpp"
|
||||||
|
|
||||||
#define ESMTOOL_VERSION 1.1
|
#define ESMTOOL_VERSION 1.2
|
||||||
|
|
||||||
// Create a local alias for brevity
|
// Create a local alias for brevity
|
||||||
namespace bpo = boost::program_options;
|
namespace bpo = boost::program_options;
|
||||||
@ -57,6 +57,8 @@ struct Arguments
|
|||||||
std::string encoding;
|
std::string encoding;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
std::string outname;
|
std::string outname;
|
||||||
|
|
||||||
|
std::vector<std::string> types;
|
||||||
|
|
||||||
ESMData data;
|
ESMData data;
|
||||||
ESM::ESMReader reader;
|
ESM::ESMReader reader;
|
||||||
@ -70,7 +72,12 @@ bool parseOptions (int argc, char** argv, Arguments &info)
|
|||||||
desc.add_options()
|
desc.add_options()
|
||||||
("help,h", "print help message.")
|
("help,h", "print help message.")
|
||||||
("version,v", "print version information and quit.")
|
("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.")
|
("quiet,q", "Supress all record information. Useful for speed tests.")
|
||||||
("loadcells,C", "Browse through contents of all cells.")
|
("loadcells,C", "Browse through contents of all cells.")
|
||||||
|
|
||||||
@ -122,6 +129,9 @@ bool parseOptions (int argc, char** argv, Arguments &info)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (variables.count("type") > 0)
|
||||||
|
info.types = variables["type"].as< std::vector<std::string> >();
|
||||||
|
|
||||||
info.mode = variables["mode"].as<std::string>();
|
info.mode = variables["mode"].as<std::string>();
|
||||||
if (!(info.mode == "dump" || info.mode == "clone" || info.mode == "comp"))
|
if (!(info.mode == "dump" || info.mode == "clone" || info.mode == "comp"))
|
||||||
{
|
{
|
||||||
@ -306,14 +316,23 @@ int load(Arguments& info)
|
|||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
esm.getRecHeader(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");
|
std::string id = esm.getHNOString("NAME");
|
||||||
|
|
||||||
if(!quiet)
|
if(!quiet && interested)
|
||||||
std::cout << "\nRecord: " << n.toString()
|
std::cout << "\nRecord: " << n.toString()
|
||||||
<< " '" << id << "'\n";
|
<< " '" << id << "'\n";
|
||||||
|
|
||||||
EsmTool::RecordBase *record =
|
EsmTool::RecordBase *record = EsmTool::RecordBase::create(n);
|
||||||
EsmTool::RecordBase::create(n.val);
|
|
||||||
|
|
||||||
if (record == 0) {
|
if (record == 0) {
|
||||||
if (std::find(skipped.begin(), skipped.end(), n.val) == skipped.end())
|
if (std::find(skipped.begin(), skipped.end(), n.val) == skipped.end())
|
||||||
@ -326,18 +345,16 @@ int load(Arguments& info)
|
|||||||
if (quiet) break;
|
if (quiet) break;
|
||||||
std::cout << " Skipping\n";
|
std::cout << " Skipping\n";
|
||||||
} else {
|
} else {
|
||||||
if (record->getType() == ESM::REC_GMST) {
|
if (record->getType().val == ESM::REC_GMST) {
|
||||||
// preset id for GameSetting record
|
// preset id for GameSetting record
|
||||||
record->cast<ESM::GameSetting>()->get().mId = id;
|
record->cast<ESM::GameSetting>()->get().mId = id;
|
||||||
}
|
}
|
||||||
record->setId(id);
|
record->setId(id);
|
||||||
record->setFlags((int) flags);
|
record->setFlags((int) flags);
|
||||||
record->load(esm);
|
record->load(esm);
|
||||||
if (!quiet) {
|
if (!quiet && interested) record->print();
|
||||||
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);
|
loadCell(record->cast<ESM::Cell>()->get(), esm, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +451,7 @@ int clone(Arguments& info)
|
|||||||
{
|
{
|
||||||
EsmTool::RecordBase *record = *it;
|
EsmTool::RecordBase *record = *it;
|
||||||
|
|
||||||
name.val = record->getType();
|
name.val = record->getType().val;
|
||||||
|
|
||||||
esm.startRecord(name.toString(), record->getFlags());
|
esm.startRecord(name.toString(), record->getFlags());
|
||||||
|
|
||||||
|
881
apps/esmtool/labels.cpp
Normal file
881
apps/esmtool/labels.cpp
Normal 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
64
apps/esmtool/labels.hpp
Normal 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
@ -20,7 +20,7 @@ namespace EsmTool
|
|||||||
protected:
|
protected:
|
||||||
std::string mId;
|
std::string mId;
|
||||||
int mFlags;
|
int mFlags;
|
||||||
int mType;
|
ESM::NAME mType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RecordBase () {}
|
RecordBase () {}
|
||||||
@ -42,7 +42,7 @@ namespace EsmTool
|
|||||||
mFlags = flags;
|
mFlags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getType() const {
|
ESM::NAME getType() const {
|
||||||
return mType;
|
return mType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ namespace EsmTool
|
|||||||
virtual void save(ESM::ESMWriter &esm) = 0;
|
virtual void save(ESM::ESMWriter &esm) = 0;
|
||||||
virtual void print() = 0;
|
virtual void print() = 0;
|
||||||
|
|
||||||
static RecordBase *create(int type);
|
static RecordBase *create(ESM::NAME type);
|
||||||
|
|
||||||
// just make it a bit shorter
|
// just make it a bit shorter
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -24,6 +24,6 @@ public slots:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(QVector<QPersistentModelIndex>);
|
Q_DECLARE_METATYPE(QVector<QPersistentModelIndex>)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -78,7 +78,7 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(std::string filename) {
|
|||||||
|
|
||||||
multistrmap::iterator it;
|
multistrmap::iterator it;
|
||||||
if((it = map.find(key)) == map.end()) {
|
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);
|
map[key].push_back(value);
|
||||||
}
|
}
|
||||||
@ -115,7 +115,7 @@ MwIniImporter::multistrmap MwIniImporter::loadCfgFile(std::string filename) {
|
|||||||
|
|
||||||
multistrmap::iterator it;
|
multistrmap::iterator it;
|
||||||
if((it = map.find(key)) == map.end()) {
|
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);
|
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) {
|
void MwIniImporter::insertMultistrmap(multistrmap &cfg, std::string key, std::string value) {
|
||||||
multistrmap::iterator it = cfg.find(key);
|
multistrmap::iterator it = cfg.find(key);
|
||||||
if(it == cfg.end()) {
|
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);
|
cfg[key].push_back(value);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ add_openmw_dir (mwgui
|
|||||||
formatting inventorywindow container hud countdialog tradewindow settingswindow
|
formatting inventorywindow container hud countdialog tradewindow settingswindow
|
||||||
confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
|
confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
|
||||||
itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog
|
itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog
|
||||||
enchantingdialog
|
enchantingdialog trainingwindow travelwindow
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwdialogue
|
add_openmw_dir (mwdialogue
|
||||||
@ -62,7 +62,7 @@ add_openmw_dir (mwclass
|
|||||||
|
|
||||||
add_openmw_dir (mwmechanics
|
add_openmw_dir (mwmechanics
|
||||||
mechanicsmanagerimp stat creaturestats magiceffects movement actors drawstate spells
|
mechanicsmanagerimp stat creaturestats magiceffects movement actors drawstate spells
|
||||||
activespells npcstats aipackage aisequence
|
activespells npcstats aipackage aisequence alchemy
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwbase
|
add_openmw_dir (mwbase
|
||||||
|
@ -163,9 +163,8 @@ void OMW::Engine::loadBSA()
|
|||||||
std::cout << "Data dir " << dataDirectory << std::endl;
|
std::cout << "Data dir " << dataDirectory << std::endl;
|
||||||
Bsa::addDir(dataDirectory, mFSStrict);
|
Bsa::addDir(dataDirectory, mFSStrict);
|
||||||
|
|
||||||
// Workaround: Mygui does not find textures in non-BSA subfolders, _unless_ they are explicitely added like this
|
// Workaround until resource listing capabilities are added to DirArchive, we need those to list available splash screens
|
||||||
// For splash screens, this is OK to do, but eventually we will need an investigation why this is necessary
|
addResourcesDirectory (dataDirectory);
|
||||||
Bsa::addDir(dataDirectory + "/Splash", mFSStrict);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,21 +423,10 @@ void OMW::Engine::activate()
|
|||||||
if (handle.empty())
|
if (handle.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// the faced handle is not updated immediately, so on a cell change it might
|
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaHandle (handle);
|
||||||
// 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);
|
|
||||||
|
|
||||||
if (ptr.isEmpty())
|
if (ptr.isEmpty())
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (std::runtime_error&)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);
|
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);
|
||||||
|
|
||||||
|
@ -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())
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ namespace MWBase
|
|||||||
Play_Normal = 0, /* tracked, non-looping, multi-instance, environment */
|
Play_Normal = 0, /* tracked, non-looping, multi-instance, environment */
|
||||||
Play_Loop = 1<<0, /* Sound will continually loop until explicitly stopped */
|
Play_Loop = 1<<0, /* Sound will continually loop until explicitly stopped */
|
||||||
Play_NoEnv = 1<<1, /* Do not apply environment effects (eg, underwater filters) */
|
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
|
* but do not keep it updated (the sound will not move with
|
||||||
* the object and will not stop when the object is deleted. */
|
* the object and will not stop when the object is deleted. */
|
||||||
};
|
};
|
||||||
|
@ -42,6 +42,7 @@ namespace MWGui
|
|||||||
class Console;
|
class Console;
|
||||||
class SpellWindow;
|
class SpellWindow;
|
||||||
class TradeWindow;
|
class TradeWindow;
|
||||||
|
class TravelWindow;
|
||||||
class SpellBuyingWindow;
|
class SpellBuyingWindow;
|
||||||
class ConfirmationDialog;
|
class ConfirmationDialog;
|
||||||
class CountDialog;
|
class CountDialog;
|
||||||
@ -108,6 +109,7 @@ namespace MWBase
|
|||||||
virtual MWGui::ConfirmationDialog* getConfirmationDialog() = 0;
|
virtual MWGui::ConfirmationDialog* getConfirmationDialog() = 0;
|
||||||
virtual MWGui::TradeWindow* getTradeWindow() = 0;
|
virtual MWGui::TradeWindow* getTradeWindow() = 0;
|
||||||
virtual MWGui::SpellBuyingWindow* getSpellBuyingWindow() = 0;
|
virtual MWGui::SpellBuyingWindow* getSpellBuyingWindow() = 0;
|
||||||
|
virtual MWGui::TravelWindow* getTravelWindow() = 0;
|
||||||
virtual MWGui::SpellWindow* getSpellWindow() = 0;
|
virtual MWGui::SpellWindow* getSpellWindow() = 0;
|
||||||
virtual MWGui::Console* getConsole() = 0;
|
virtual MWGui::Console* getConsole() = 0;
|
||||||
|
|
||||||
@ -230,6 +232,7 @@ namespace MWBase
|
|||||||
|
|
||||||
virtual void startSpellMaking(MWWorld::Ptr actor) = 0;
|
virtual void startSpellMaking(MWWorld::Ptr actor) = 0;
|
||||||
virtual void startEnchanting(MWWorld::Ptr actor) = 0;
|
virtual void startEnchanting(MWWorld::Ptr actor) = 0;
|
||||||
|
virtual void startTraining(MWWorld::Ptr actor) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,6 +143,9 @@ namespace MWBase
|
|||||||
virtual MWWorld::Ptr getPtrViaHandle (const std::string& handle) = 0;
|
virtual MWWorld::Ptr getPtrViaHandle (const std::string& handle) = 0;
|
||||||
///< Return a pointer to a liveCellRef with the given Ogre handle.
|
///< 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
|
/// \todo enable reference in the OGRE scene
|
||||||
virtual void enable (const MWWorld::Ptr& ptr) = 0;
|
virtual void enable (const MWWorld::Ptr& ptr) = 0;
|
||||||
|
|
||||||
|
@ -795,12 +795,18 @@ namespace MWDialogue
|
|||||||
|| services & ESM::NPC::Misc)
|
|| services & ESM::NPC::Misc)
|
||||||
windowServices |= MWGui::DialogueWindow::Service_Trade;
|
windowServices |= MWGui::DialogueWindow::Service_Trade;
|
||||||
|
|
||||||
|
if( !mActor.get<ESM::NPC>()->base->mTransport.empty())
|
||||||
|
windowServices |= MWGui::DialogueWindow::Service_Travel;
|
||||||
|
|
||||||
if (services & ESM::NPC::Spells)
|
if (services & ESM::NPC::Spells)
|
||||||
windowServices |= MWGui::DialogueWindow::Service_BuySpells;
|
windowServices |= MWGui::DialogueWindow::Service_BuySpells;
|
||||||
|
|
||||||
if (services & ESM::NPC::Spellmaking)
|
if (services & ESM::NPC::Spellmaking)
|
||||||
windowServices |= MWGui::DialogueWindow::Service_CreateSpells;
|
windowServices |= MWGui::DialogueWindow::Service_CreateSpells;
|
||||||
|
|
||||||
|
if (services & ESM::NPC::Training)
|
||||||
|
windowServices |= MWGui::DialogueWindow::Service_Training;
|
||||||
|
|
||||||
if (services & ESM::NPC::Enchanting)
|
if (services & ESM::NPC::Enchanting)
|
||||||
windowServices |= MWGui::DialogueWindow::Service_Enchant;
|
windowServices |= MWGui::DialogueWindow::Service_Enchant;
|
||||||
|
|
||||||
|
@ -28,25 +28,25 @@ namespace MWGui
|
|||||||
{
|
{
|
||||||
AlchemyWindow::AlchemyWindow(MWBase::WindowManager& parWindowManager)
|
AlchemyWindow::AlchemyWindow(MWBase::WindowManager& parWindowManager)
|
||||||
: WindowBase("openmw_alchemy_window.layout", parWindowManager)
|
: WindowBase("openmw_alchemy_window.layout", parWindowManager)
|
||||||
, ContainerBase(0)
|
, ContainerBase(0), mApparatus (4), mIngredients (4)
|
||||||
{
|
{
|
||||||
getWidget(mCreateButton, "CreateButton");
|
getWidget(mCreateButton, "CreateButton");
|
||||||
getWidget(mCancelButton, "CancelButton");
|
getWidget(mCancelButton, "CancelButton");
|
||||||
getWidget(mIngredient1, "Ingredient1");
|
getWidget(mIngredients[0], "Ingredient1");
|
||||||
getWidget(mIngredient2, "Ingredient2");
|
getWidget(mIngredients[1], "Ingredient2");
|
||||||
getWidget(mIngredient3, "Ingredient3");
|
getWidget(mIngredients[2], "Ingredient3");
|
||||||
getWidget(mIngredient4, "Ingredient4");
|
getWidget(mIngredients[3], "Ingredient4");
|
||||||
getWidget(mApparatus1, "Apparatus1");
|
getWidget(mApparatus[0], "Apparatus1");
|
||||||
getWidget(mApparatus2, "Apparatus2");
|
getWidget(mApparatus[1], "Apparatus2");
|
||||||
getWidget(mApparatus3, "Apparatus3");
|
getWidget(mApparatus[2], "Apparatus3");
|
||||||
getWidget(mApparatus4, "Apparatus4");
|
getWidget(mApparatus[3], "Apparatus4");
|
||||||
getWidget(mEffectsBox, "CreatedEffects");
|
getWidget(mEffectsBox, "CreatedEffects");
|
||||||
getWidget(mNameEdit, "NameEdit");
|
getWidget(mNameEdit, "NameEdit");
|
||||||
|
|
||||||
mIngredient1->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
|
mIngredients[0]->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
|
||||||
mIngredient2->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
|
mIngredients[1]->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
|
||||||
mIngredient3->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
|
mIngredients[2]->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
|
||||||
mIngredient4->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
|
mIngredients[3]->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
|
||||||
|
|
||||||
mCreateButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCreateButtonClicked);
|
mCreateButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCreateButtonClicked);
|
||||||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCancelButtonClicked);
|
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCancelButtonClicked);
|
||||||
@ -62,157 +62,52 @@ namespace MWGui
|
|||||||
|
|
||||||
void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender)
|
void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
|
mAlchemy.clear();
|
||||||
|
|
||||||
mWindowManager.removeGuiMode(GM_Alchemy);
|
mWindowManager.removeGuiMode(GM_Alchemy);
|
||||||
mWindowManager.removeGuiMode(GM_Inventory);
|
mWindowManager.removeGuiMode(GM_Inventory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender)
|
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)
|
// check if mortar & pestle is available (always needed)
|
||||||
/// \todo check albemic, calcinator, retort (sometimes needed)
|
if (result == MWMechanics::Alchemy::Result_NoMortarAndPestle)
|
||||||
if (!mApparatus1->isUserString("ToolTipType"))
|
|
||||||
{
|
{
|
||||||
mWindowManager.messageBox("#{sNotifyMessage45}", std::vector<std::string>());
|
mWindowManager.messageBox("#{sNotifyMessage45}", std::vector<std::string>());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure 2 or more ingredients were selected
|
// make sure 2 or more ingredients were selected
|
||||||
int numIngreds = 0;
|
if (result == MWMechanics::Alchemy::Result_LessThanTwoIngredients)
|
||||||
if (mIngredient1->isUserString("ToolTipType"))
|
|
||||||
++numIngreds;
|
|
||||||
if (mIngredient2->isUserString("ToolTipType"))
|
|
||||||
++numIngreds;
|
|
||||||
if (mIngredient3->isUserString("ToolTipType"))
|
|
||||||
++numIngreds;
|
|
||||||
if (mIngredient4->isUserString("ToolTipType"))
|
|
||||||
++numIngreds;
|
|
||||||
if (numIngreds < 2)
|
|
||||||
{
|
{
|
||||||
mWindowManager.messageBox("#{sNotifyMessage6a}", std::vector<std::string>());
|
mWindowManager.messageBox("#{sNotifyMessage6a}", std::vector<std::string>());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure a name was entered
|
if (result == MWMechanics::Alchemy::Result_NoEffects)
|
||||||
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())
|
|
||||||
{
|
{
|
||||||
mWindowManager.messageBox("#{sNotifyMessage8}", std::vector<std::string>());
|
mWindowManager.messageBox("#{sNotifyMessage8}", std::vector<std::string>());
|
||||||
MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f);
|
MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f);
|
||||||
return;
|
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>());
|
mWindowManager.messageBox("#{sPotionSuccess}", std::vector<std::string>());
|
||||||
MWBase::Environment::get().getSoundManager()->playSound("potion success", 1.f, 1.f);
|
MWBase::Environment::get().getSoundManager()->playSound("potion success", 1.f, 1.f);
|
||||||
}
|
}
|
||||||
else
|
else if (result == MWMechanics::Alchemy::Result_RandomFailure)
|
||||||
{
|
{
|
||||||
// potion failed
|
// potion failed
|
||||||
mWindowManager.messageBox("#{sNotifyMessage8}", std::vector<std::string>());
|
mWindowManager.messageBox("#{sNotifyMessage8}", std::vector<std::string>());
|
||||||
@ -220,155 +115,53 @@ namespace MWGui
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reduce count of the ingredients
|
// reduce count of the ingredients
|
||||||
if (mIngredient1->isUserString("ToolTipType"))
|
for (int i=0; i<4; ++i)
|
||||||
{
|
if (mIngredients[i]->isUserString("ToolTipType"))
|
||||||
MWWorld::Ptr ingred = *mIngredient1->getUserData<MWWorld::Ptr>();
|
{
|
||||||
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
|
MWWorld::Ptr ingred = *mIngredients[i]->getUserData<MWWorld::Ptr>();
|
||||||
if (ingred.getRefData().getCount() == 0)
|
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
|
||||||
removeIngredient(mIngredient1);
|
if (ingred.getRefData().getCount() == 0)
|
||||||
}
|
removeIngredient(mIngredients[i]);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlchemyWindow::open()
|
void AlchemyWindow::open()
|
||||||
{
|
{
|
||||||
openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
|
openContainer (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); // this sets mPtr
|
||||||
setFilter(ContainerBase::Filter_Ingredients);
|
setFilter (ContainerBase::Filter_Ingredients);
|
||||||
|
|
||||||
// pick the best available apparatus
|
mAlchemy.setAlchemist (mPtr);
|
||||||
MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
|
|
||||||
|
|
||||||
MWWorld::Ptr bestAlbemic;
|
int index = 0;
|
||||||
MWWorld::Ptr bestMortarPestle;
|
|
||||||
MWWorld::Ptr bestCalcinator;
|
|
||||||
MWWorld::Ptr bestRetort;
|
|
||||||
|
|
||||||
for (MWWorld::ContainerStoreIterator it(store.begin(MWWorld::ContainerStore::Type_Apparatus));
|
for (MWMechanics::Alchemy::TToolsIterator iter (mAlchemy.beginTools());
|
||||||
it != store.end(); ++it)
|
iter!=mAlchemy.endTools() && index<static_cast<int> (mApparatus.size()); ++iter, ++index)
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Apparatus>* ref = it->get<ESM::Apparatus>();
|
if (!iter->isEmpty())
|
||||||
if (ref->base->mData.mType == ESM::Apparatus::Albemic
|
{
|
||||||
&& (bestAlbemic.isEmpty() || ref->base->mData.mQuality > bestAlbemic.get<ESM::Apparatus>()->base->mData.mQuality))
|
mApparatus.at (index)->setUserString ("ToolTipType", "ItemPtr");
|
||||||
bestAlbemic = *it;
|
mApparatus.at (index)->setUserData (*iter);
|
||||||
else if (ref->base->mData.mType == ESM::Apparatus::MortarPestle
|
mApparatus.at (index)->setImageTexture (getIconPath (*iter));
|
||||||
&& (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 (!bestMortarPestle.isEmpty())
|
update();
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender)
|
void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
removeIngredient(_sender);
|
removeIngredient(_sender);
|
||||||
drawItems();
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlchemyWindow::onSelectedItemImpl(MWWorld::Ptr item)
|
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
|
if (res != -1)
|
||||||
// (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"))
|
|
||||||
{
|
{
|
||||||
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();
|
update();
|
||||||
|
|
||||||
std::string sound = MWWorld::Class::get(item).getUpSoundId(item);
|
std::string sound = MWWorld::Class::get(item).getUpSoundId(item);
|
||||||
@ -380,54 +173,40 @@ namespace MWGui
|
|||||||
{
|
{
|
||||||
std::vector<MWWorld::Ptr> ignore;
|
std::vector<MWWorld::Ptr> ignore;
|
||||||
// don't show ingredients that are currently selected in the "available ingredients" box.
|
// don't show ingredients that are currently selected in the "available ingredients" box.
|
||||||
if (mIngredient1->isUserString("ToolTipType"))
|
for (int i=0; i<4; ++i)
|
||||||
ignore.push_back(*mIngredient1->getUserData<MWWorld::Ptr>());
|
if (mIngredients[i]->isUserString("ToolTipType"))
|
||||||
if (mIngredient2->isUserString("ToolTipType"))
|
ignore.push_back(*mIngredients[i]->getUserData<MWWorld::Ptr>());
|
||||||
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>());
|
|
||||||
|
|
||||||
return ignore;
|
return ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlchemyWindow::update()
|
void AlchemyWindow::update()
|
||||||
{
|
{
|
||||||
Widgets::SpellEffectList effects;
|
MWMechanics::Alchemy::TIngredientsIterator it = mAlchemy.beginIngredients ();
|
||||||
|
|
||||||
for (int i=0; i<4; ++i)
|
for (int i=0; i<4; ++i)
|
||||||
{
|
{
|
||||||
MyGUI::ImageBox* ingredient;
|
MyGUI::ImageBox* ingredient = mIngredients[i];
|
||||||
if (i==0)
|
|
||||||
ingredient = mIngredient1;
|
|
||||||
else if (i==1)
|
|
||||||
ingredient = mIngredient2;
|
|
||||||
else if (i==2)
|
|
||||||
ingredient = mIngredient3;
|
|
||||||
else if (i==3)
|
|
||||||
ingredient = mIngredient4;
|
|
||||||
|
|
||||||
if (!ingredient->isUserString("ToolTipType"))
|
MWWorld::Ptr item;
|
||||||
continue;
|
if (it != mAlchemy.endIngredients ())
|
||||||
|
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
if (ref->base->mData.mEffectID[i] < 0)
|
item = *it;
|
||||||
continue;
|
++it;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update ingredient count labels
|
|
||||||
if (ingredient->getChildCount())
|
if (ingredient->getChildCount())
|
||||||
MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0));
|
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"));
|
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->setTextAlign(MyGUI::Align::Right);
|
||||||
text->setNeedMouseFocus(false);
|
text->setNeedMouseFocus(false);
|
||||||
@ -436,49 +215,15 @@ namespace MWGui
|
|||||||
text->setCaption(getCountString(ingredient->getUserData<MWWorld::Ptr>()->getRefData().getCount()));
|
text->setCaption(getCountString(ingredient->getUserData<MWWorld::Ptr>()->getRefData().getCount()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// now remove effects that are only present once
|
drawItems();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
std::vector<ESM::ENAMstruct> effects;
|
||||||
it = effects.erase(it);
|
ESM::EffectList list;
|
||||||
else
|
list.mList = effects;
|
||||||
++it;
|
for (MWMechanics::Alchemy::TEffectsIterator it = mAlchemy.beginEffects (); it != mAlchemy.endEffects (); ++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)
|
|
||||||
{
|
{
|
||||||
bool found = false;
|
list.mList.push_back(*it);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mEffects = effects;
|
|
||||||
|
|
||||||
while (mEffectsBox->getChildCount())
|
while (mEffectsBox->getChildCount())
|
||||||
MyGUI::Gui::getInstance().destroyWidget(mEffectsBox->getChildAt(0));
|
MyGUI::Gui::getInstance().destroyWidget(mEffectsBox->getChildAt(0));
|
||||||
@ -487,7 +232,9 @@ namespace MWGui
|
|||||||
Widgets::MWEffectListPtr effectsWidget = mEffectsBox->createWidget<Widgets::MWEffectList>
|
Widgets::MWEffectListPtr effectsWidget = mEffectsBox->createWidget<Widgets::MWEffectList>
|
||||||
("MW_StatName", coord, MyGUI::Align::Left | MyGUI::Align::Top);
|
("MW_StatName", coord, MyGUI::Align::Left | MyGUI::Align::Top);
|
||||||
effectsWidget->setWindowManager(&mWindowManager);
|
effectsWidget->setWindowManager(&mWindowManager);
|
||||||
effectsWidget->setEffectList(effects);
|
|
||||||
|
Widgets::SpellEffectList _list = Widgets::MWEffectList::effectListFromESM(&list);
|
||||||
|
effectsWidget->setEffectList(_list);
|
||||||
|
|
||||||
std::vector<MyGUI::WidgetPtr> effectItems;
|
std::vector<MyGUI::WidgetPtr> effectItems;
|
||||||
effectsWidget->createEffectWidgets(effectItems, mEffectsBox, coord, false, 0);
|
effectsWidget->createEffectWidgets(effectItems, mEffectsBox, coord, false, 0);
|
||||||
@ -496,9 +243,10 @@ namespace MWGui
|
|||||||
|
|
||||||
void AlchemyWindow::removeIngredient(MyGUI::Widget* ingredient)
|
void AlchemyWindow::removeIngredient(MyGUI::Widget* ingredient)
|
||||||
{
|
{
|
||||||
ingredient->clearUserStrings();
|
for (int i=0; i<4; ++i)
|
||||||
static_cast<MyGUI::ImageBox*>(ingredient)->setImageTexture("");
|
if (mIngredients[i] == ingredient)
|
||||||
if (ingredient->getChildCount())
|
mAlchemy.removeIngredient (i);
|
||||||
MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0));
|
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
#ifndef MWGUI_ALCHEMY_H
|
#ifndef MWGUI_ALCHEMY_H
|
||||||
#define MWGUI_ALCHEMY_H
|
#define MWGUI_ALCHEMY_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../mwmechanics/alchemy.hpp"
|
||||||
|
|
||||||
#include "window_base.hpp"
|
#include "window_base.hpp"
|
||||||
#include "container.hpp"
|
#include "container.hpp"
|
||||||
#include "widgets.hpp"
|
#include "widgets.hpp"
|
||||||
@ -18,22 +22,10 @@ namespace MWGui
|
|||||||
MyGUI::Button* mCreateButton;
|
MyGUI::Button* mCreateButton;
|
||||||
MyGUI::Button* mCancelButton;
|
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::Widget* mEffectsBox;
|
||||||
|
|
||||||
MyGUI::EditBox* mNameEdit;
|
MyGUI::EditBox* mNameEdit;
|
||||||
|
|
||||||
Widgets::SpellEffectList mEffects; // effects of created potion
|
|
||||||
|
|
||||||
void onCancelButtonClicked(MyGUI::Widget* _sender);
|
void onCancelButtonClicked(MyGUI::Widget* _sender);
|
||||||
void onCreateButtonClicked(MyGUI::Widget* _sender);
|
void onCreateButtonClicked(MyGUI::Widget* _sender);
|
||||||
void onIngredientSelected(MyGUI::Widget* _sender);
|
void onIngredientSelected(MyGUI::Widget* _sender);
|
||||||
@ -46,6 +38,13 @@ namespace MWGui
|
|||||||
virtual void onReferenceUnavailable() { ; }
|
virtual void onReferenceUnavailable() { ; }
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
MWMechanics::Alchemy mAlchemy;
|
||||||
|
|
||||||
|
std::vector<MyGUI::ImageBox *> mApparatus;
|
||||||
|
std::vector<MyGUI::ImageBox *> mIngredients;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,16 @@
|
|||||||
using namespace MWGui;
|
using namespace MWGui;
|
||||||
using namespace Widgets;
|
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)
|
BirthDialog::BirthDialog(MWBase::WindowManager& parWindowManager)
|
||||||
: WindowBase("openmw_chargen_birth.layout", 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 it = store.birthSigns.list.begin();
|
||||||
ESMS::RecListT<ESM::BirthSign>::MapType::const_iterator end = store.birthSigns.list.end();
|
ESMS::RecListT<ESM::BirthSign>::MapType::const_iterator end = store.birthSigns.list.end();
|
||||||
int index = 0;
|
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;
|
std::string id = it->first;
|
||||||
mBirthList->addItem(birth.mName, it->first);
|
const ESM::BirthSign* sign = &it->second;
|
||||||
if (boost::iequals(it->first, mCurrentBirthId))
|
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);
|
mBirthList->setIndexSelected(index);
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "tradewindow.hpp"
|
#include "tradewindow.hpp"
|
||||||
#include "spellbuyingwindow.hpp"
|
#include "spellbuyingwindow.hpp"
|
||||||
#include "inventorywindow.hpp"
|
#include "inventorywindow.hpp"
|
||||||
|
#include "travelwindow.hpp"
|
||||||
|
|
||||||
using namespace MWGui;
|
using namespace MWGui;
|
||||||
using namespace Widgets;
|
using namespace Widgets;
|
||||||
@ -137,6 +138,11 @@ void DialogueWindow::onSelectTopic(std::string topic)
|
|||||||
mWindowManager.pushGuiMode(GM_SpellBuying);
|
mWindowManager.pushGuiMode(GM_SpellBuying);
|
||||||
mWindowManager.getSpellBuyingWindow()->startSpellBuying(mPtr);
|
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())
|
else if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sSpellMakingMenuTitle")->getString())
|
||||||
{
|
{
|
||||||
mWindowManager.pushGuiMode(GM_SpellCreation);
|
mWindowManager.pushGuiMode(GM_SpellCreation);
|
||||||
@ -147,6 +153,11 @@ void DialogueWindow::onSelectTopic(std::string topic)
|
|||||||
mWindowManager.pushGuiMode(GM_Enchanting);
|
mWindowManager.pushGuiMode(GM_Enchanting);
|
||||||
mWindowManager.startEnchanting (mPtr);
|
mWindowManager.startEnchanting (mPtr);
|
||||||
}
|
}
|
||||||
|
else if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sServiceTrainingTitle")->getString())
|
||||||
|
{
|
||||||
|
mWindowManager.pushGuiMode(GM_Training);
|
||||||
|
mWindowManager.startTraining (mPtr);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(topic));
|
MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(topic));
|
||||||
}
|
}
|
||||||
@ -175,12 +186,18 @@ void DialogueWindow::setKeywords(std::list<std::string> keyWords)
|
|||||||
if (mServices & Service_BuySpells)
|
if (mServices & Service_BuySpells)
|
||||||
mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sSpells")->getString());
|
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)
|
if (mServices & Service_CreateSpells)
|
||||||
mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sSpellmakingMenuTitle")->getString());
|
mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sSpellmakingMenuTitle")->getString());
|
||||||
|
|
||||||
if (mServices & Service_Enchant)
|
if (mServices & Service_Enchant)
|
||||||
mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sEnchanting")->getString());
|
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)
|
if (anyService)
|
||||||
mTopicsList->addSeparator();
|
mTopicsList->addSeparator();
|
||||||
|
|
||||||
|
@ -48,7 +48,6 @@ namespace MWGui
|
|||||||
void askQuestion(std::string question);
|
void askQuestion(std::string question);
|
||||||
void goodbye();
|
void goodbye();
|
||||||
|
|
||||||
// various service button visibilities, depending if the npc/creature talked to has these services
|
|
||||||
// make sure to call these before setKeywords()
|
// make sure to call these before setKeywords()
|
||||||
void setServices(int services) { mServices = services; }
|
void setServices(int services) { mServices = services; }
|
||||||
|
|
||||||
@ -57,7 +56,9 @@ namespace MWGui
|
|||||||
Service_Trade = 0x01,
|
Service_Trade = 0x01,
|
||||||
Service_BuySpells = 0x02,
|
Service_BuySpells = 0x02,
|
||||||
Service_CreateSpells = 0x04,
|
Service_CreateSpells = 0x04,
|
||||||
Service_Enchant = 0x08
|
Service_Enchant = 0x08,
|
||||||
|
Service_Training = 0x10,
|
||||||
|
Service_Travel = 0x20
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -76,10 +77,6 @@ namespace MWGui
|
|||||||
*/
|
*/
|
||||||
std::string parseText(std::string text);
|
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;
|
int mServices;
|
||||||
|
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
|
@ -245,15 +245,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle();
|
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle();
|
||||||
MWWorld::Ptr object;
|
MWWorld::Ptr object = MWBase::Environment::get().getWorld()->searchPtrViaHandle(handle);
|
||||||
try
|
|
||||||
{
|
|
||||||
object = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle);
|
|
||||||
}
|
|
||||||
catch (std::exception& /* e */)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == GM_Console)
|
if (mode == GM_Console)
|
||||||
MWBase::Environment::get().getWindowManager()->getConsole()->setSelectedObject(object);
|
MWBase::Environment::get().getWindowManager()->getConsole()->setSelectedObject(object);
|
||||||
|
@ -6,10 +6,13 @@
|
|||||||
#include <OgreCompositorChain.h>
|
#include <OgreCompositorChain.h>
|
||||||
#include <OgreMaterial.h>
|
#include <OgreMaterial.h>
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
|
#include <openengine/ogre/fader.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/inputmanager.hpp"
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
@ -106,6 +109,7 @@ namespace MWGui
|
|||||||
|
|
||||||
if (mTimer.getMilliseconds () > mLastRenderTime + (1.f/loadingScreenFps) * 1000.f)
|
if (mTimer.getMilliseconds () > mLastRenderTime + (1.f/loadingScreenFps) * 1000.f)
|
||||||
{
|
{
|
||||||
|
float dt = mTimer.getMilliseconds () - mLastRenderTime;
|
||||||
mLastRenderTime = mTimer.getMilliseconds ();
|
mLastRenderTime = mTimer.getMilliseconds ();
|
||||||
|
|
||||||
if (mFirstLoad && mTimer.getMilliseconds () > mLastWallpaperChangeTime + 3000*1)
|
if (mFirstLoad && mTimer.getMilliseconds () > mLastWallpaperChangeTime + 3000*1)
|
||||||
@ -151,6 +155,8 @@ namespace MWGui
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWorld ()->getFader ()->update (dt);
|
||||||
|
|
||||||
mWindow->update();
|
mWindow->update();
|
||||||
|
|
||||||
if (!hasCompositor)
|
if (!hasCompositor)
|
||||||
@ -207,20 +213,22 @@ namespace MWGui
|
|||||||
|
|
||||||
void LoadingScreen::changeWallpaper ()
|
void LoadingScreen::changeWallpaper ()
|
||||||
{
|
{
|
||||||
/// \todo use a directory listing here
|
|
||||||
std::vector<std::string> splash;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,10 @@ namespace MWGui
|
|||||||
GM_Rest,
|
GM_Rest,
|
||||||
GM_RestBed,
|
GM_RestBed,
|
||||||
GM_SpellBuying,
|
GM_SpellBuying,
|
||||||
|
GM_Travel,
|
||||||
GM_SpellCreation,
|
GM_SpellCreation,
|
||||||
GM_Enchanting,
|
GM_Enchanting,
|
||||||
|
GM_Training,
|
||||||
|
|
||||||
GM_Levelup,
|
GM_Levelup,
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ namespace MWGui
|
|||||||
|
|
||||||
MyGUI::Button* toAdd =
|
MyGUI::Button* toAdd =
|
||||||
mSpellsView->createWidget<MyGUI::Button>(
|
mSpellsView->createWidget<MyGUI::Button>(
|
||||||
(price>mWindowManager.getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SpellText",
|
(price>mWindowManager.getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton",
|
||||||
0,
|
0,
|
||||||
mCurrentY,
|
mCurrentY,
|
||||||
200,
|
200,
|
||||||
|
@ -79,14 +79,10 @@ void ToolTips::onFrame(float frameDuration)
|
|||||||
|| (mWindowManager->getMode() == GM_Inventory)))
|
|| (mWindowManager->getMode() == GM_Inventory)))
|
||||||
{
|
{
|
||||||
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle();
|
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle();
|
||||||
try
|
|
||||||
{
|
mFocusObject = MWBase::Environment::get().getWorld()->searchPtrViaHandle(handle);
|
||||||
mFocusObject = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle);
|
if (mFocusObject.isEmpty ())
|
||||||
}
|
|
||||||
catch (std::exception /* & e */)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
MyGUI::IntSize tooltipSize = getToolTipViaPtr(true);
|
MyGUI::IntSize tooltipSize = getToolTipViaPtr(true);
|
||||||
|
|
||||||
|
159
apps/openmw/mwgui/trainingwindow.cpp
Normal file
159
apps/openmw/mwgui/trainingwindow.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
36
apps/openmw/mwgui/trainingwindow.hpp
Normal file
36
apps/openmw/mwgui/trainingwindow.hpp
Normal 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
|
187
apps/openmw/mwgui/travelwindow.cpp
Normal file
187
apps/openmw/mwgui/travelwindow.cpp
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
55
apps/openmw/mwgui/travelwindow.hpp
Normal file
55
apps/openmw/mwgui/travelwindow.hpp
Normal 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
|
@ -38,6 +38,7 @@
|
|||||||
#include "countdialog.hpp"
|
#include "countdialog.hpp"
|
||||||
#include "tradewindow.hpp"
|
#include "tradewindow.hpp"
|
||||||
#include "spellbuyingwindow.hpp"
|
#include "spellbuyingwindow.hpp"
|
||||||
|
#include "travelwindow.hpp"
|
||||||
#include "settingswindow.hpp"
|
#include "settingswindow.hpp"
|
||||||
#include "confirmationdialog.hpp"
|
#include "confirmationdialog.hpp"
|
||||||
#include "alchemywindow.hpp"
|
#include "alchemywindow.hpp"
|
||||||
@ -48,6 +49,7 @@
|
|||||||
#include "waitdialog.hpp"
|
#include "waitdialog.hpp"
|
||||||
#include "spellcreationdialog.hpp"
|
#include "spellcreationdialog.hpp"
|
||||||
#include "enchantingdialog.hpp"
|
#include "enchantingdialog.hpp"
|
||||||
|
#include "trainingwindow.hpp"
|
||||||
|
|
||||||
using namespace MWGui;
|
using namespace MWGui;
|
||||||
|
|
||||||
@ -69,6 +71,7 @@ WindowManager::WindowManager(
|
|||||||
, mCountDialog(NULL)
|
, mCountDialog(NULL)
|
||||||
, mTradeWindow(NULL)
|
, mTradeWindow(NULL)
|
||||||
, mSpellBuyingWindow(NULL)
|
, mSpellBuyingWindow(NULL)
|
||||||
|
, mTravelWindow(NULL)
|
||||||
, mSettingsWindow(NULL)
|
, mSettingsWindow(NULL)
|
||||||
, mConfirmationDialog(NULL)
|
, mConfirmationDialog(NULL)
|
||||||
, mAlchemyWindow(NULL)
|
, mAlchemyWindow(NULL)
|
||||||
@ -79,6 +82,7 @@ WindowManager::WindowManager(
|
|||||||
, mWaitDialog(NULL)
|
, mWaitDialog(NULL)
|
||||||
, mSpellCreationDialog(NULL)
|
, mSpellCreationDialog(NULL)
|
||||||
, mEnchantingDialog(NULL)
|
, mEnchantingDialog(NULL)
|
||||||
|
, mTrainingWindow(NULL)
|
||||||
, mPlayerClass()
|
, mPlayerClass()
|
||||||
, mPlayerName()
|
, mPlayerName()
|
||||||
, mPlayerRaceId()
|
, mPlayerRaceId()
|
||||||
@ -145,6 +149,7 @@ WindowManager::WindowManager(
|
|||||||
mInventoryWindow = new InventoryWindow(*this,mDragAndDrop);
|
mInventoryWindow = new InventoryWindow(*this,mDragAndDrop);
|
||||||
mTradeWindow = new TradeWindow(*this);
|
mTradeWindow = new TradeWindow(*this);
|
||||||
mSpellBuyingWindow = new SpellBuyingWindow(*this);
|
mSpellBuyingWindow = new SpellBuyingWindow(*this);
|
||||||
|
mTravelWindow = new TravelWindow(*this);
|
||||||
mDialogueWindow = new DialogueWindow(*this);
|
mDialogueWindow = new DialogueWindow(*this);
|
||||||
mContainerWindow = new ContainerWindow(*this,mDragAndDrop);
|
mContainerWindow = new ContainerWindow(*this,mDragAndDrop);
|
||||||
mHud = new HUD(w,h, mShowFPSLevel, mDragAndDrop);
|
mHud = new HUD(w,h, mShowFPSLevel, mDragAndDrop);
|
||||||
@ -161,6 +166,7 @@ WindowManager::WindowManager(
|
|||||||
mWaitDialog = new WaitDialog(*this);
|
mWaitDialog = new WaitDialog(*this);
|
||||||
mSpellCreationDialog = new SpellCreationDialog(*this);
|
mSpellCreationDialog = new SpellCreationDialog(*this);
|
||||||
mEnchantingDialog = new EnchantingDialog(*this);
|
mEnchantingDialog = new EnchantingDialog(*this);
|
||||||
|
mTrainingWindow = new TrainingWindow(*this);
|
||||||
|
|
||||||
mLoadingScreen = new LoadingScreen(mOgre->getScene (), mOgre->getWindow (), *this);
|
mLoadingScreen = new LoadingScreen(mOgre->getScene (), mOgre->getWindow (), *this);
|
||||||
mLoadingScreen->onResChange (w,h);
|
mLoadingScreen->onResChange (w,h);
|
||||||
@ -209,6 +215,7 @@ WindowManager::~WindowManager()
|
|||||||
delete mScrollWindow;
|
delete mScrollWindow;
|
||||||
delete mTradeWindow;
|
delete mTradeWindow;
|
||||||
delete mSpellBuyingWindow;
|
delete mSpellBuyingWindow;
|
||||||
|
delete mTravelWindow;
|
||||||
delete mSettingsWindow;
|
delete mSettingsWindow;
|
||||||
delete mConfirmationDialog;
|
delete mConfirmationDialog;
|
||||||
delete mAlchemyWindow;
|
delete mAlchemyWindow;
|
||||||
@ -218,6 +225,7 @@ WindowManager::~WindowManager()
|
|||||||
delete mWaitDialog;
|
delete mWaitDialog;
|
||||||
delete mSpellCreationDialog;
|
delete mSpellCreationDialog;
|
||||||
delete mEnchantingDialog;
|
delete mEnchantingDialog;
|
||||||
|
delete mTrainingWindow;
|
||||||
|
|
||||||
cleanupGarbage();
|
cleanupGarbage();
|
||||||
|
|
||||||
@ -261,6 +269,7 @@ void WindowManager::updateVisible()
|
|||||||
mBookWindow->setVisible(false);
|
mBookWindow->setVisible(false);
|
||||||
mTradeWindow->setVisible(false);
|
mTradeWindow->setVisible(false);
|
||||||
mSpellBuyingWindow->setVisible(false);
|
mSpellBuyingWindow->setVisible(false);
|
||||||
|
mTravelWindow->setVisible(false);
|
||||||
mSettingsWindow->setVisible(false);
|
mSettingsWindow->setVisible(false);
|
||||||
mAlchemyWindow->setVisible(false);
|
mAlchemyWindow->setVisible(false);
|
||||||
mSpellWindow->setVisible(false);
|
mSpellWindow->setVisible(false);
|
||||||
@ -269,6 +278,7 @@ void WindowManager::updateVisible()
|
|||||||
mWaitDialog->setVisible(false);
|
mWaitDialog->setVisible(false);
|
||||||
mSpellCreationDialog->setVisible(false);
|
mSpellCreationDialog->setVisible(false);
|
||||||
mEnchantingDialog->setVisible(false);
|
mEnchantingDialog->setVisible(false);
|
||||||
|
mTrainingWindow->setVisible(false);
|
||||||
|
|
||||||
mHud->setVisible(true);
|
mHud->setVisible(true);
|
||||||
|
|
||||||
@ -369,12 +379,18 @@ void WindowManager::updateVisible()
|
|||||||
case GM_SpellBuying:
|
case GM_SpellBuying:
|
||||||
mSpellBuyingWindow->setVisible(true);
|
mSpellBuyingWindow->setVisible(true);
|
||||||
break;
|
break;
|
||||||
|
case GM_Travel:
|
||||||
|
mTravelWindow->setVisible(true);
|
||||||
|
break;
|
||||||
case GM_SpellCreation:
|
case GM_SpellCreation:
|
||||||
mSpellCreationDialog->setVisible(true);
|
mSpellCreationDialog->setVisible(true);
|
||||||
break;
|
break;
|
||||||
case GM_Enchanting:
|
case GM_Enchanting:
|
||||||
mEnchantingDialog->setVisible(true);
|
mEnchantingDialog->setVisible(true);
|
||||||
break;
|
break;
|
||||||
|
case GM_Training:
|
||||||
|
mTrainingWindow->setVisible(true);
|
||||||
|
break;
|
||||||
case GM_InterMessageBox:
|
case GM_InterMessageBox:
|
||||||
break;
|
break;
|
||||||
case GM_Journal:
|
case GM_Journal:
|
||||||
@ -574,6 +590,9 @@ void WindowManager::onFrame (float frameDuration)
|
|||||||
|
|
||||||
mHud->onFrame(frameDuration);
|
mHud->onFrame(frameDuration);
|
||||||
|
|
||||||
|
mTrainingWindow->onFrame (frameDuration);
|
||||||
|
|
||||||
|
mTrainingWindow->checkReferenceAvailable();
|
||||||
mDialogueWindow->checkReferenceAvailable();
|
mDialogueWindow->checkReferenceAvailable();
|
||||||
mTradeWindow->checkReferenceAvailable();
|
mTradeWindow->checkReferenceAvailable();
|
||||||
mSpellBuyingWindow->checkReferenceAvailable();
|
mSpellBuyingWindow->checkReferenceAvailable();
|
||||||
@ -862,6 +881,7 @@ MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; }
|
|||||||
MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; }
|
MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; }
|
||||||
MWGui::TradeWindow* WindowManager::getTradeWindow() { return mTradeWindow; }
|
MWGui::TradeWindow* WindowManager::getTradeWindow() { return mTradeWindow; }
|
||||||
MWGui::SpellBuyingWindow* WindowManager::getSpellBuyingWindow() { return mSpellBuyingWindow; }
|
MWGui::SpellBuyingWindow* WindowManager::getSpellBuyingWindow() { return mSpellBuyingWindow; }
|
||||||
|
MWGui::TravelWindow* WindowManager::getTravelWindow() { return mTravelWindow; }
|
||||||
MWGui::SpellWindow* WindowManager::getSpellWindow() { return mSpellWindow; }
|
MWGui::SpellWindow* WindowManager::getSpellWindow() { return mSpellWindow; }
|
||||||
MWGui::Console* WindowManager::getConsole() { return mConsole; }
|
MWGui::Console* WindowManager::getConsole() { return mConsole; }
|
||||||
|
|
||||||
@ -993,3 +1013,8 @@ void WindowManager::startEnchanting (MWWorld::Ptr actor)
|
|||||||
{
|
{
|
||||||
mEnchantingDialog->startEnchanting (actor);
|
mEnchantingDialog->startEnchanting (actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WindowManager::startTraining(MWWorld::Ptr actor)
|
||||||
|
{
|
||||||
|
mTrainingWindow->startTraining(actor);
|
||||||
|
}
|
||||||
|
@ -66,6 +66,7 @@ namespace MWGui
|
|||||||
class WaitDialog;
|
class WaitDialog;
|
||||||
class SpellCreationDialog;
|
class SpellCreationDialog;
|
||||||
class EnchantingDialog;
|
class EnchantingDialog;
|
||||||
|
class TrainingWindow;
|
||||||
|
|
||||||
class WindowManager : public MWBase::WindowManager
|
class WindowManager : public MWBase::WindowManager
|
||||||
{
|
{
|
||||||
@ -113,6 +114,7 @@ namespace MWGui
|
|||||||
virtual MWGui::ConfirmationDialog* getConfirmationDialog();
|
virtual MWGui::ConfirmationDialog* getConfirmationDialog();
|
||||||
virtual MWGui::TradeWindow* getTradeWindow();
|
virtual MWGui::TradeWindow* getTradeWindow();
|
||||||
virtual MWGui::SpellBuyingWindow* getSpellBuyingWindow();
|
virtual MWGui::SpellBuyingWindow* getSpellBuyingWindow();
|
||||||
|
virtual MWGui::TravelWindow* getTravelWindow();
|
||||||
virtual MWGui::SpellWindow* getSpellWindow();
|
virtual MWGui::SpellWindow* getSpellWindow();
|
||||||
virtual MWGui::Console* getConsole();
|
virtual MWGui::Console* getConsole();
|
||||||
|
|
||||||
@ -215,6 +217,7 @@ namespace MWGui
|
|||||||
|
|
||||||
virtual void startSpellMaking(MWWorld::Ptr actor);
|
virtual void startSpellMaking(MWWorld::Ptr actor);
|
||||||
virtual void startEnchanting(MWWorld::Ptr actor);
|
virtual void startEnchanting(MWWorld::Ptr actor);
|
||||||
|
virtual void startTraining(MWWorld::Ptr actor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OEngine::GUI::MyGUIManager *mGuiManager;
|
OEngine::GUI::MyGUIManager *mGuiManager;
|
||||||
@ -235,6 +238,7 @@ namespace MWGui
|
|||||||
CountDialog* mCountDialog;
|
CountDialog* mCountDialog;
|
||||||
TradeWindow* mTradeWindow;
|
TradeWindow* mTradeWindow;
|
||||||
SpellBuyingWindow* mSpellBuyingWindow;
|
SpellBuyingWindow* mSpellBuyingWindow;
|
||||||
|
TravelWindow* mTravelWindow;
|
||||||
SettingsWindow* mSettingsWindow;
|
SettingsWindow* mSettingsWindow;
|
||||||
ConfirmationDialog* mConfirmationDialog;
|
ConfirmationDialog* mConfirmationDialog;
|
||||||
AlchemyWindow* mAlchemyWindow;
|
AlchemyWindow* mAlchemyWindow;
|
||||||
@ -245,6 +249,7 @@ namespace MWGui
|
|||||||
WaitDialog* mWaitDialog;
|
WaitDialog* mWaitDialog;
|
||||||
SpellCreationDialog* mSpellCreationDialog;
|
SpellCreationDialog* mSpellCreationDialog;
|
||||||
EnchantingDialog* mEnchantingDialog;
|
EnchantingDialog* mEnchantingDialog;
|
||||||
|
TrainingWindow* mTrainingWindow;
|
||||||
|
|
||||||
CharacterCreation* mCharGen;
|
CharacterCreation* mCharGen;
|
||||||
|
|
||||||
|
@ -118,18 +118,14 @@ namespace MWMechanics
|
|||||||
+ fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified ());
|
+ fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr)
|
void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
|
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
|
||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
for (int i=0; i<5; ++i)
|
for (int i=0; i<8; ++i)
|
||||||
{
|
{
|
||||||
int modifier =
|
int modifier =
|
||||||
creatureStats.getMagicEffects().get (EffectKey (79, i)).mMagnitude;
|
creatureStats.getMagicEffects().get (EffectKey (79, i)).mMagnitude;
|
||||||
|
490
apps/openmw/mwmechanics/alchemy.cpp
Normal file
490
apps/openmw/mwmechanics/alchemy.cpp
Normal 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;
|
||||||
|
}
|
121
apps/openmw/mwmechanics/alchemy.hpp
Normal file
121
apps/openmw/mwmechanics/alchemy.hpp
Normal 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
|
||||||
|
|
@ -8,7 +8,7 @@ namespace MWMechanics
|
|||||||
{
|
{
|
||||||
DrawState_Weapon = 0,
|
DrawState_Weapon = 0,
|
||||||
DrawState_Spell = 1,
|
DrawState_Spell = 1,
|
||||||
DrawState_Nothing = 2,
|
DrawState_Nothing = 2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ namespace MWRender
|
|||||||
{
|
{
|
||||||
Ogre::Image image;
|
Ogre::Image image;
|
||||||
|
|
||||||
Ogre::uchar data[mWidth * mHeight * 3];
|
std::vector<Ogre::uchar> data (mWidth * mHeight * 3);
|
||||||
|
|
||||||
for (int x = mMinX; x <= mMaxX; ++x)
|
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");
|
//image.save (mCacheDir + "/GlobalMap.png");
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ namespace Ogre
|
|||||||
class Entity;
|
class Entity;
|
||||||
class Vector3;
|
class Vector3;
|
||||||
struct RenderTargetEvent;
|
struct RenderTargetEvent;
|
||||||
};
|
}
|
||||||
|
|
||||||
namespace MWRender {
|
namespace MWRender {
|
||||||
|
|
||||||
|
@ -74,6 +74,6 @@ namespace MWScript
|
|||||||
///< Return index of the variable of the given name and type in the given script. Will
|
///< 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.
|
/// throw an exception, if there is no such script or variable or the type does not match.
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -54,6 +54,6 @@ namespace MWSound
|
|||||||
#ifndef DEFAULT_DECODER
|
#ifndef DEFAULT_DECODER
|
||||||
#define DEFAULT_DECODER (::MWSound::FFmpeg_Decoder)
|
#define DEFAULT_DECODER (::MWSound::FFmpeg_Decoder)
|
||||||
#endif
|
#endif
|
||||||
};
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -52,6 +52,6 @@ namespace MWSound
|
|||||||
#ifndef DEFAULT_DECODER
|
#ifndef DEFAULT_DECODER
|
||||||
#define DEFAULT_DECODER (::MWSound::MpgSnd_Decoder)
|
#define DEFAULT_DECODER (::MWSound::MpgSnd_Decoder)
|
||||||
#endif
|
#endif
|
||||||
};
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -66,6 +66,6 @@ namespace MWSound
|
|||||||
#ifndef DEFAULT_OUTPUT
|
#ifndef DEFAULT_OUTPUT
|
||||||
#define DEFAULT_OUTPUT (::MWSound::OpenAL_Output)
|
#define DEFAULT_OUTPUT (::MWSound::OpenAL_Output)
|
||||||
#endif
|
#endif
|
||||||
};
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,7 +26,7 @@ namespace MWSound
|
|||||||
|
|
||||||
enum Environment {
|
enum Environment {
|
||||||
Env_Normal,
|
Env_Normal,
|
||||||
Env_Underwater,
|
Env_Underwater
|
||||||
};
|
};
|
||||||
|
|
||||||
class SoundManager : public MWBase::SoundManager
|
class SoundManager : public MWBase::SoundManager
|
||||||
|
@ -326,6 +326,14 @@ namespace MWWorld
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ptr World::getPtrViaHandle (const std::string& handle)
|
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)
|
if (mPlayer->getPlayer().getRefData().getHandle()==handle)
|
||||||
return mPlayer->getPlayer();
|
return mPlayer->getPlayer();
|
||||||
@ -339,7 +347,7 @@ namespace MWWorld
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::runtime_error ("unknown Ogre handle: " + handle);
|
return MWWorld::Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::enable (const Ptr& reference)
|
void World::enable (const Ptr& reference)
|
||||||
@ -864,12 +872,13 @@ namespace MWWorld
|
|||||||
mWeatherManager->update (duration);
|
mWeatherManager->update (duration);
|
||||||
|
|
||||||
// inform the GUI about focused object
|
// inform the GUI about focused object
|
||||||
try
|
MWWorld::Ptr object = searchPtrViaHandle(mFacedHandle);
|
||||||
{
|
|
||||||
MWWorld::Ptr object = getPtrViaHandle(mFacedHandle);
|
|
||||||
MWBase::Environment::get().getWindowManager()->setFocusObject(object);
|
|
||||||
|
|
||||||
// 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::SceneNode* node = object.getRefData().getBaseNode();
|
||||||
Ogre::AxisAlignedBox bounds;
|
Ogre::AxisAlignedBox bounds;
|
||||||
int i;
|
int i;
|
||||||
@ -885,11 +894,6 @@ namespace MWWorld
|
|||||||
screenCoords[0], screenCoords[1], screenCoords[2], screenCoords[3]);
|
screenCoords[0], screenCoords[1], screenCoords[2], screenCoords[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::runtime_error&)
|
|
||||||
{
|
|
||||||
MWWorld::Ptr null;
|
|
||||||
MWBase::Environment::get().getWindowManager()->setFocusObject(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mRendering->occlusionQuerySupported())
|
if (!mRendering->occlusionQuerySupported())
|
||||||
{
|
{
|
||||||
|
@ -163,6 +163,9 @@ namespace MWWorld
|
|||||||
virtual Ptr getPtrViaHandle (const std::string& handle);
|
virtual Ptr getPtrViaHandle (const std::string& handle);
|
||||||
///< Return a pointer to a liveCellRef with the given Ogre 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 enable (const Ptr& ptr);
|
||||||
|
|
||||||
virtual void disable (const Ptr& ptr);
|
virtual void disable (const Ptr& ptr);
|
||||||
|
@ -375,7 +375,7 @@ void addBSA(const std::string& name, const std::string& group)
|
|||||||
{
|
{
|
||||||
insertBSAFactory();
|
insertBSAFactory();
|
||||||
ResourceGroupManager::getSingleton().
|
ResourceGroupManager::getSingleton().
|
||||||
addResourceLocation(name, "BSA", group);
|
addResourceLocation(name, "BSA", group, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addDir(const std::string& name, const bool& fs, const std::string& group)
|
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();
|
insertDirFactory();
|
||||||
|
|
||||||
ResourceGroupManager::getSingleton().
|
ResourceGroupManager::getSingleton().
|
||||||
addResourceLocation(name, "Dir", group);
|
addResourceLocation(name, "Dir", group, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,6 @@ namespace ESM
|
|||||||
{
|
{
|
||||||
// These are probabilities
|
// These are probabilities
|
||||||
char mHello, mU1, mFight, mFlee, mAlarm, mU2, mU3, mU4;
|
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
|
int mServices; // See the Services enum
|
||||||
}; // 12 bytes
|
}; // 12 bytes
|
||||||
|
|
||||||
@ -60,7 +58,7 @@ namespace ESM
|
|||||||
AI_Travel = 0x545f4941,
|
AI_Travel = 0x545f4941,
|
||||||
AI_Follow = 0x465f4941,
|
AI_Follow = 0x465f4941,
|
||||||
AI_Escort = 0x455f4941,
|
AI_Escort = 0x455f4941,
|
||||||
AI_Activate = 0x415f4941,
|
AI_Activate = 0x415f4941
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \note Used for storaging packages in a single container
|
/// \note Used for storaging packages in a single container
|
||||||
|
@ -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)
|
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);
|
startSubRecord(name);
|
||||||
writeHString(data);
|
writeHString(data);
|
||||||
|
|
||||||
if (data.size() < size)
|
if (static_cast<int> (data.size()) < size)
|
||||||
{
|
{
|
||||||
for (int i = data.size(); i < size; ++i)
|
for (int i = data.size(); i < size; ++i)
|
||||||
write("\0",1);
|
write("\0",1);
|
||||||
|
@ -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.
|
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.
|
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.
|
CasterLinked = 0x20000, // Must quench if caster is dead, or not an NPC/creature. Not allowed in containter/door trap spells.
|
||||||
|
|
||||||
SpellMaking = 0x0200,
|
SpellMaking = 0x0200,
|
||||||
Enchanting = 0x0400,
|
Enchanting = 0x0400,
|
||||||
Negative = 0x0800 // A harmful effect. Will determine whether
|
Negative = 0x0800 // A harmful effect. Will determine whether
|
||||||
|
@ -331,7 +331,7 @@ namespace ESMS
|
|||||||
// Find land for the given coordinates. Return null if no mData.
|
// Find land for the given coordinates. Return null if no mData.
|
||||||
Land *search(int x, int y) const
|
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() )
|
if ( itr == lands.end() )
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -350,7 +350,7 @@ namespace ESMS
|
|||||||
land->load(esm);
|
land->load(esm);
|
||||||
|
|
||||||
// Store the structure
|
// Store the structure
|
||||||
lands[std::make_pair<int, int>(land->mX, land->mY)] = land;
|
lands[std::make_pair (land->mX, land->mY)] = land;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ Alexander Olofsson (Ace)
|
|||||||
Artem Kotsynyak (greye)
|
Artem Kotsynyak (greye)
|
||||||
athile
|
athile
|
||||||
BrotherBrick
|
BrotherBrick
|
||||||
|
Cory F. Cohen (cfcohen)
|
||||||
Cris Mihalache (Mirceam)
|
Cris Mihalache (Mirceam)
|
||||||
Douglas Diniz (Dgdiniz)
|
Douglas Diniz (Dgdiniz)
|
||||||
Eli2
|
Eli2
|
||||||
|
@ -157,10 +157,15 @@
|
|||||||
shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart)
|
shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if UNDERWATER
|
#if (UNDERWATER) || (FOG)
|
||||||
shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix)
|
shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix)
|
||||||
shUniform(float, waterLevel) @shSharedParameter(waterLevel)
|
|
||||||
shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position)
|
shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERWATER
|
||||||
|
|
||||||
|
shUniform(float, waterLevel) @shSharedParameter(waterLevel)
|
||||||
|
|
||||||
shUniform(float4, lightDirectionWS0) @shAutoConstant(lightDirectionWS0, light_position, 0)
|
shUniform(float4, lightDirectionWS0) @shAutoConstant(lightDirectionWS0, light_position, 0)
|
||||||
|
|
||||||
shSampler2D(causticMap)
|
shSampler2D(causticMap)
|
||||||
@ -211,8 +216,12 @@
|
|||||||
|
|
||||||
|
|
||||||
float3 caustics = float3(1,1,1);
|
float3 caustics = float3(1,1,1);
|
||||||
#if UNDERWATER
|
|
||||||
|
#if (UNDERWATER) || (FOG)
|
||||||
float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePositionPassthrough,1)).xyz;
|
float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePositionPassthrough,1)).xyz;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERWATER
|
||||||
float3 waterEyePos = float3(1,1,1);
|
float3 waterEyePos = float3(1,1,1);
|
||||||
// NOTE: this calculation would be wrong for non-uniform scaling
|
// NOTE: this calculation would be wrong for non-uniform scaling
|
||||||
float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0));
|
float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0));
|
||||||
|
@ -187,11 +187,13 @@
|
|||||||
shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart)
|
shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (UNDERWATER) || (FOG)
|
||||||
|
shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix)
|
||||||
|
shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if UNDERWATER
|
#if UNDERWATER
|
||||||
shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix)
|
|
||||||
shUniform(float, waterLevel) @shSharedParameter(waterLevel)
|
shUniform(float, waterLevel) @shSharedParameter(waterLevel)
|
||||||
shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position)
|
|
||||||
shUniform(float4, lightDirectionWS0) @shAutoConstant(lightDirectionWS0, light_position, 0)
|
shUniform(float4, lightDirectionWS0) @shAutoConstant(lightDirectionWS0, light_position, 0)
|
||||||
|
|
||||||
shSampler2D(causticMap)
|
shSampler2D(causticMap)
|
||||||
@ -222,9 +224,12 @@
|
|||||||
|
|
||||||
|
|
||||||
float3 caustics = float3(1,1,1);
|
float3 caustics = float3(1,1,1);
|
||||||
|
#if (UNDERWATER) || (FOG)
|
||||||
|
float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePosition,1)).xyz;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if UNDERWATER
|
#if UNDERWATER
|
||||||
|
|
||||||
float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePosition,1)).xyz;
|
|
||||||
float3 waterEyePos = float3(1,1,1);
|
float3 waterEyePos = float3(1,1,1);
|
||||||
// NOTE: this calculation would be wrong for non-uniform scaling
|
// NOTE: this calculation would be wrong for non-uniform scaling
|
||||||
float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0));
|
float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0));
|
||||||
@ -373,7 +378,6 @@
|
|||||||
|
|
||||||
shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz);
|
shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz);
|
||||||
|
|
||||||
|
|
||||||
#if MRT
|
#if MRT
|
||||||
shOutputColour(1) = float4(depth / far,1,1,1);
|
shOutputColour(1) = float4(depth / far,1,1,1);
|
||||||
#endif
|
#endif
|
||||||
|
@ -78,6 +78,8 @@ set(MYGUI_FILES
|
|||||||
openmw_spellcreation_dialog.layout
|
openmw_spellcreation_dialog.layout
|
||||||
openmw_edit_effect.layout
|
openmw_edit_effect.layout
|
||||||
openmw_enchanting_dialog.layout
|
openmw_enchanting_dialog.layout
|
||||||
|
openmw_trainingwindow.layout
|
||||||
|
openmw_travel_window.layout
|
||||||
smallbars.png
|
smallbars.png
|
||||||
VeraMono.ttf
|
VeraMono.ttf
|
||||||
markers.png
|
markers.png
|
||||||
|
30
files/mygui/openmw_trainingwindow.layout
Normal file
30
files/mygui/openmw_trainingwindow.layout
Normal 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>
|
35
files/mygui/openmw_travel_window.layout
Normal file
35
files/mygui/openmw_travel_window.layout
Normal 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>
|
@ -1,5 +1,4 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Version=${OPENMW_VERSION}
|
|
||||||
Type=Application
|
Type=Application
|
||||||
Name=OpenMW Launcher
|
Name=OpenMW Launcher
|
||||||
GenericName=Role Playing Game
|
GenericName=Role Playing Game
|
||||||
|
@ -16,7 +16,7 @@ namespace Physic
|
|||||||
pEng = eng;
|
pEng = eng;
|
||||||
tr.setIdentity();
|
tr.setIdentity();
|
||||||
pName = name;
|
pName = name;
|
||||||
};
|
}
|
||||||
|
|
||||||
void CMotionState::getWorldTransform(btTransform &worldTrans) const
|
void CMotionState::getWorldTransform(btTransform &worldTrans) const
|
||||||
{
|
{
|
||||||
|
@ -626,4 +626,4 @@ namespace Physic
|
|||||||
|
|
||||||
shape->Shape->getAabb(trans, min, max);
|
shape->Shape->getAabb(trans, min, max);
|
||||||
}
|
}
|
||||||
}};
|
}}
|
||||||
|
@ -40,7 +40,7 @@ Fader::Fader(Ogre::SceneManager* sceneMgr)
|
|||||||
Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
|
Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
|
||||||
node->attachObject(mRectangle);
|
node->attachObject(mRectangle);
|
||||||
mRectangle->setVisible(false);
|
mRectangle->setVisible(false);
|
||||||
mRectangle->setVisibilityFlags (0x01);
|
mRectangle->setVisibilityFlags (2048);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fader::~Fader()
|
Fader::~Fader()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user