From 673b10207948598535444ae1afbb153f824a4298 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 3 Jul 2014 12:17:24 +0200 Subject: [PATCH 01/49] increased version number --- CMakeLists.txt | 2 +- readme.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9de8efeb5..cb9a54a6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/) message(STATUS "Configuring OpenMW...") set(OPENMW_VERSION_MAJOR 0) -set(OPENMW_VERSION_MINOR 30) +set(OPENMW_VERSION_MINOR 31) set(OPENMW_VERSION_RELEASE 0) set(OPENMW_VERSION_COMMITHASH "") diff --git a/readme.txt b/readme.txt index 92cb35f31..90f223a64 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ OpenMW: A reimplementation of The Elder Scrolls III: Morrowind OpenMW is an attempt at recreating the engine for the popular role-playing game Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. -Version: 0.30.0 +Version: 0.31.0 License: GPL (see GPL3.txt for more information) Website: http://www.openmw.org From 6ba4a5335cdbdcbd8683989fb4fcf86c53fd0f2b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 4 Jul 2014 08:58:54 +0200 Subject: [PATCH 02/49] updated changelog --- readme.txt | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) diff --git a/readme.txt b/readme.txt index 90f223a64..bafca48a4 100644 --- a/readme.txt +++ b/readme.txt @@ -96,6 +96,188 @@ Allowed options: CHANGELOG +0.31.0 + +Bug #245: Cloud direction and weather systems differ from Morrowind +Bug #275: Local Map does not always show objects that span multiple cells +Bug #538: Update CenterOnCell (COC) function behavior +Bug #618: Local and World Map Textures are sometimes Black +Bug #640: Water behaviour at night +Bug #668: OpenMW doesn't support non-latin paths on Windows +Bug #746: OpenMW doesn't check if the background music was already played +Bug #747: Door is stuck if cell is left before animation finishes +Bug #772: Disabled statics are visible on map +Bug #829: OpenMW uses up all available vram, when playing for extended time +Bug #869: Dead bodies don't collide with anything +Bug #894: Various character creation issues +Bug #897/#1369: opencs Segmentation Fault after "new" or "load" +Bug #899: Various jumping issues +Bug #952: Reflection effects are one frame delayed +Bug #993: Able to interact with world during Wait/Rest dialog +Bug #995: Dropped items can be placed inside the wall +Bug #1008: Corpses always face up upon reentering the cell +Bug #1035: Random colour patterns appearing in automap +Bug #1037: Footstep volume issues +Bug #1047: Creation of wrong links in dialogue window +Bug #1129: Summoned creature time life duration seems infinite +Bug #1134: Crimes can be committed against hostile NPCs +Bug #1136: Creature run speed formula is incorrect +Bug #1150: Weakness to Fire doesn't apply to Fire Damage in the same spell +Bug #1155: NPCs killing each other +Bug #1166: Bittercup script still does not work +Bug #1178: .bsa file names are case sensitive. +Bug #1179: Crash after trying to load game after being killed +Bug #1180: Changing footstep sound location +Bug #1196: Jumping not disabled when showing messageboxes +Bug #1202: "strange" keys are not shown in binding menu, and are not saved either, but works +Bug #1217: Container content changes based on the current position of the mouse +Bug #1234: Loading/saving issues with dynamic records +Bug #1277: Text pasted into the console appears twice +Bug #1284: Crash on New Game +Bug #1303: It's possible to skip the chargen +Bug #1304: Slaughterfish should not detect the player unless the player is in the water +Bug #1311: Editor: deleting Record Filter line does not reset the filter +Bug #1324: ERROR: ESM Error: String table overflow when loading Animated Morrowind.esp +Bug #1328: Editor: Bogus Filter created when dragging multiple records to filter bar of non-applicable table +Bug #1331: Walking/running sound persist after killing NPC`s that are walking/running. +Bug #1334: Previously equipped items not shown as unequipped after attempting to sell them. +Bug #1335: Actors ignore vertical axis when deciding to attack +Bug #1338: Unknown toggle option for shadows +Bug #1339: "Ashlands Region" is visible when beginning new game during "Loading Area" process +Bug #1340: Guards prompt Player with punishment options after resisting arrest with another guard. +Bug #1348: Regression: Bug #1098 has returned with a vengeance +Bug #1349: [TR] TR_Data mesh tr_ex_imp_gatejamb01 cannot be activated +Bug #1352: Disabling an ESX file does not disable dependent ESX files +Bug #1355: CppCat Checks OpenMW +Bug #1356: Incorrect voice type filtering for sleep interrupts +Bug #1357: Restarting the game clears saves +Bug #1360: Seyda Neen silk rider dialog problem +Bug #1361: Some lights don't work +Bug #1364: It is difficult to bind "Mouse 1" to an action in the options menu +Bug #1370: Animation compilation mod does not work properly +Bug #1371: SL_Pick01.nif from third party fails to load in openmw, but works in Vanilla +Bug #1373: When stealing in front of Sellus Gravius cannot exit the dialog +Bug #1378: Installs to /usr/local are not working +Bug #1380: Loading a save file fail if one of the content files is disabled +Bug #1382: "getHExact() size mismatch" crash on loading official plugin "Siege at Firemoth.esp" +Bug #1386: Arkngthand door will not open +Bug #1388: Segfault when modifying View Distance in Menu options +Bug #1389: Crash when loading a save after dying +Bug #1390: Apostrophe characters not displayed [French version] +Bug #1391: Custom made icon background texture for magical weapons and stuff isn't scaled properly on GUI. +Bug #1393: Coin icon during the level up dialogue are off of the background +Bug #1394: Alt+F4 doesn't work on Win version +Bug #1395: Changing rings switches only the last one put on +Bug #1396: Pauldron parts aren't showing when the robe is equipped +Bug #1402: Dialogue of some shrines have wrong button orientation +Bug #1403: Items are floating in the air when they're dropped onto dead bodies. +Bug #1404: Forearms are not rendered on Argonian females +Bug #1407: Alchemy allows making potions from two of the same item +Bug #1408: "Max sale" button gives you all the items AND all the trader's gold +Bug #1409: Rest "Until Healed" broken for characters with stunted magicka. +Bug #1412: Empty travel window opens while playing through start game +Bug #1413: Save game ignores missing writing permission +Bug #1414: The Underground 2 ESM Error +Bug #1416: Not all splash screens in the Splash directory are used +Bug #1417: Loading saved game does not terminate +Bug #1419: Skyrim: Home of the Nords error +Bug #1422: ClearInfoActor +Bug #1423: ForceGreeting closes existing dialogue windows +Bug #1425: Cannot load save game +Bug #1426: Read skill books aren't stored in savegame +Bug #1427: Useless items can be set under hotkeys +Bug #1429: Text variables in journal +Bug #1432: When attacking friendly NPC, the crime is reported and bounty is raised after each swing +Bug #1435: Stealing priceless items is without punishment +Bug #1437: Door marker at Jobasha's Rare Books is spawning PC in the air +Bug #1440: Topic selection menu should be wider +Bug #1441: Dropping items on the rug makes them inaccessible +Bug #1442: When dropping and taking some looted items, bystanders consider that as a crime +Bug #1444: Arrows and bolts are not dropped where the cursor points +Bug #1445: Security trainers offering acrobatics instead +Bug #1447: Character dash not displayed, French edition +Bug #1448: When the player is killed by the guard while having a bounty on his head, the guard dialogue opens over and over instead of loading dialogue +Bug #1454: Script error in SkipTutorial +Bug #1456: Bad lighting when using certain Morrowind.ini generated by MGE +Bug #1457: Heart of Lorkan comes after you when attacking it +Bug #1458: Modified Keybindings are not remembered +Bug #1459: Dura Gra-Bol doesn't respond to PC attack +Bug #1462: Interior cells not loaded with Morrowind Patch active +Bug #1469: Item tooltip should show the base value, not real value +Bug #1477: Death count is not stored in savegame +Bug #1478: AiActivate does not trigger activate scripts +Bug #1481: Weapon not rendered when partially submerged in water +Bug #1483: Enemies are attacking even while dying +Bug #1486: ESM Error: Don't know what to do with INFO +Bug #1490: Arrows shot at PC can end up in inventory +Bug #1492: Monsters respawn on top of one another +Bug #1493: Dialogue box opens with follower NPC even if NPC is dead +Bug #1494: Paralysed cliffracers remain airbourne +Bug #1495: Dialogue box opens with follower NPC even the game is paused +Bug #1496: GUI messages are not cleared when loading another saved game +Bug #1499: Underwater sound sometimes plays when transitioning from interior. +Bug #1500: Targetted spells and water. +Bug #1502: Console error message on info refusal +Bug #1507: Bloodmoon MQ The Ritual of Beasts: Can't remove the arrow +Bug #1508: Bloodmoon: Fort Frostmoth, cant talk with Carnius Magius +Bug #1516: PositionCell doesn't move actors to current cell +Bug #1518: ForceGreeting broken for explicit references +Bug #1522: Crash after attempting to play non-music file +Bug #1523: World map empty after loading interior save +Bug #1524: Arrows in waiting/resting dialog act like minimum and maximum buttons +Bug #1525: Werewolf: Killed NPC's don't fill werewolfs hunger for blood +Bug #1527: Werewolf: Detect life detects wrong type of actor +Bug #1529: OpenMW crash during "the shrine of the dead" mission (tribunal) +Bug #1530: Selected text in the console has the same color as the background +Bug #1539: Barilzar's Mazed Band: Tribunal +Bug #1542: Looping taunts from NPC`s after death: Tribunal +Bug #1543: OpenCS crash when using drag&drop in script editor +Bug #1547: Bamz-Amschend: Centurion Archers combat problem +Bug #1548: The Missing Hand: Tribunal +Bug #1549: The Mad God: Tribunal, Dome of Serlyn +Bug #1557: A bounty is calculated from actual item cost +Bug #1562: Invisible terrain on top of Red Mountain +Bug #1564: Cave of the hidden music: Bloodmoon +Bug #1567: Editor: Deleting of referenceables does not work +Bug #1568: Picking up a stack of items and holding the enter key and moving your mouse around paints a bunch of garbage on screen. +Bug #1574: Solstheim: Drauger cant inflict damage on player +Bug #1578: Solstheim: Bonewolf running animation not working +Bug #1585: Particle effects on PC are stopped when paralyzed +Bug #1589: Tribunal: Crimson Plague quest does not update when Gedna Relvel is killed +Bug #1590: Failed to save game: compile error +Bug #1598: Segfault when making Drain/Fortify Skill spells +Bug #1599: Unable to switch to fullscreen +Bug #1613: Morrowind Rebirth duplicate objects / vanilla objects not removed +Feature #32: Periodic Cleanup/Refill +Feature #41: Precipitation and weather particles +Feature #568: Editor: Configuration setup +Feature #649: Editor: Threaded loading +Feature #930: Editor: Cell record saving +Feature #934: Editor: Body part table +Feature #935: Editor: Enchantment effect table +Feature #1162: Dialogue merging +Feature #1174: Saved Game: add missing creature state +Feature #1177: Saved Game: fog of war state +Feature #1312: Editor: Combat/Magic/Stealth values for creatures are not displayed +Feature #1314: Make NPCs and creatures fight each other +Feature #1315: Crime: Murder +Feature #1321: Sneak skill enhancements +Feature #1323: Handle restocking items +Feature #1332: Saved Game: levelled creatures +Feature #1347: modFactionReaction script instruction +Feature #1362: Animated main menu support +Feature #1433: Store walk/run toggle +Feature #1449: Use names instead of numbers for saved game files and folders +Feature #1453: Adding Delete button to the load menu +Feature #1460: Enable Journal screen while in dialogue +Feature #1480: Play Battle music when in combat +Feature #1501: Followers unable to fast travel with you +Feature #1520: Disposition and distance-based aggression/ShouldAttack +Feature #1595: Editor: Object rendering in cells +Task #940: Move license to locations where applicable +Task #1333: Remove cmake git tag reading +Task #1566: Editor: Object rendering refactoring + 0.30.0 Bug #416: Extreme shaking can occur during cell transitions while moving From f27e3067a39a2ba005ae621fdb6a77ff9a045ea1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 4 Jul 2014 23:19:40 +0200 Subject: [PATCH 03/49] Use explicit C locale in Misc::StringUtils (Fixes #1216) --- components/misc/stringops.cpp | 55 +---------------------------------- components/misc/stringops.hpp | 32 ++++++-------------- 2 files changed, 10 insertions(+), 77 deletions(-) diff --git a/components/misc/stringops.cpp b/components/misc/stringops.cpp index 0bc8e290a..0f801e554 100644 --- a/components/misc/stringops.cpp +++ b/components/misc/stringops.cpp @@ -12,59 +12,6 @@ namespace Misc { -bool begins(const char* str1, const char* str2) -{ - while(*str2) - { - if(*str1 == 0 || *str1 != *str2) return false; - - str1++; - str2++; - } - return true; -} - -bool ends(const char* str1, const char* str2) -{ - int len1 = strlen(str1); - int len2 = strlen(str2); - - if(len1 < len2) return false; - - return strcmp(str2, str1+len1-len2) == 0; -} - -// True if the given chars match, case insensitive -static bool icmp(char a, char b) -{ - if(a >= 'A' && a <= 'Z') - a += 'a' - 'A'; - if(b >= 'A' && b <= 'Z') - b += 'a' - 'A'; - - return a == b; -} - -bool ibegins(const char* str1, const char* str2) -{ - while(*str2) - { - if(*str1 == 0 || !icmp(*str1,*str2)) return false; - - str1++; - str2++; - } - return true; -} - -bool iends(const char* str1, const char* str2) -{ - int len1 = strlen(str1); - int len2 = strlen(str2); - - if(len1 < len2) return false; - - return strcasecmp(str2, str1+len1-len2) == 0; -} +std::locale StringUtils::mLocale = std::locale::classic(); } diff --git a/components/misc/stringops.hpp b/components/misc/stringops.hpp index d41463cfc..04dedb072 100644 --- a/components/misc/stringops.hpp +++ b/components/misc/stringops.hpp @@ -4,15 +4,18 @@ #include #include #include +#include namespace Misc { class StringUtils { + + static std::locale mLocale; struct ci { - bool operator()(int x, int y) const { - return std::tolower(x) < std::tolower(y); + bool operator()(char x, char y) const { + return std::tolower(x, StringUtils::mLocale) < std::tolower(y, StringUtils::mLocale); } }; @@ -28,7 +31,7 @@ public: std::string::const_iterator xit = x.begin(); std::string::const_iterator yit = y.begin(); for (; xit != x.end(); ++xit, ++yit) { - if (std::tolower(*xit) != std::tolower(*yit)) { + if (std::tolower(*xit, mLocale) != std::tolower(*yit, mLocale)) { return false; } } @@ -42,7 +45,7 @@ public: for(;xit != x.end() && yit != y.end() && len > 0;++xit,++yit,--len) { int res = *xit - *yit; - if(res != 0 && std::tolower(*xit) != std::tolower(*yit)) + if(res != 0 && std::tolower(*xit, mLocale) != std::tolower(*yit, mLocale)) return (res > 0) ? 1 : -1; } if(len > 0) @@ -57,12 +60,8 @@ public: /// Transforms input string to lower case w/o copy static std::string &toLower(std::string &inout) { - std::transform( - inout.begin(), - inout.end(), - inout.begin(), - (int (*)(int)) std::tolower - ); + for (unsigned int i=0; i Date: Sat, 5 Jul 2014 07:24:30 +0200 Subject: [PATCH 04/49] Fix travis --- .../components/misc/test_stringops.cpp | 65 ------------------- 1 file changed, 65 deletions(-) diff --git a/apps/openmw_test_suite/components/misc/test_stringops.cpp b/apps/openmw_test_suite/components/misc/test_stringops.cpp index 44587c445..55fe0e0c2 100644 --- a/apps/openmw_test_suite/components/misc/test_stringops.cpp +++ b/apps/openmw_test_suite/components/misc/test_stringops.cpp @@ -12,68 +12,3 @@ struct StringOpsTest : public ::testing::Test { } }; - -TEST_F(StringOpsTest, begins_matching) -{ - ASSERT_TRUE(Misc::begins("abc", "a")); - ASSERT_TRUE(Misc::begins("abc", "ab")); - ASSERT_TRUE(Misc::begins("abc", "abc")); - ASSERT_TRUE(Misc::begins("abcd", "abc")); -} - -TEST_F(StringOpsTest, begins_not_matching) -{ - ASSERT_FALSE(Misc::begins("abc", "b")); - ASSERT_FALSE(Misc::begins("abc", "bc")); - ASSERT_FALSE(Misc::begins("abc", "bcd")); - ASSERT_FALSE(Misc::begins("abc", "abcd")); -} - -TEST_F(StringOpsTest, ibegins_matching) -{ - ASSERT_TRUE(Misc::ibegins("Abc", "a")); - ASSERT_TRUE(Misc::ibegins("aBc", "ab")); - ASSERT_TRUE(Misc::ibegins("abC", "abc")); - ASSERT_TRUE(Misc::ibegins("abcD", "abc")); -} - -TEST_F(StringOpsTest, ibegins_not_matching) -{ - ASSERT_FALSE(Misc::ibegins("abc", "b")); - ASSERT_FALSE(Misc::ibegins("abc", "bc")); - ASSERT_FALSE(Misc::ibegins("abc", "bcd")); - ASSERT_FALSE(Misc::ibegins("abc", "abcd")); -} - -TEST_F(StringOpsTest, ends_matching) -{ - ASSERT_TRUE(Misc::ends("abc", "c")); - ASSERT_TRUE(Misc::ends("abc", "bc")); - ASSERT_TRUE(Misc::ends("abc", "abc")); - ASSERT_TRUE(Misc::ends("abcd", "abcd")); -} - -TEST_F(StringOpsTest, ends_not_matching) -{ - ASSERT_FALSE(Misc::ends("abc", "b")); - ASSERT_FALSE(Misc::ends("abc", "ab")); - ASSERT_FALSE(Misc::ends("abc", "bcd")); - ASSERT_FALSE(Misc::ends("abc", "abcd")); -} - -TEST_F(StringOpsTest, iends_matching) -{ - ASSERT_TRUE(Misc::iends("Abc", "c")); - ASSERT_TRUE(Misc::iends("aBc", "bc")); - ASSERT_TRUE(Misc::iends("abC", "abc")); - ASSERT_TRUE(Misc::iends("abcD", "abcd")); -} - -TEST_F(StringOpsTest, iends_not_matching) -{ - ASSERT_FALSE(Misc::iends("abc", "b")); - ASSERT_FALSE(Misc::iends("abc", "ab")); - ASSERT_FALSE(Misc::iends("abc", "bcd")); - ASSERT_FALSE(Misc::iends("abc", "abcd")); -} - From 05cb22f5b79acabf181ef540d57a2de8d8d7ce6c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 7 Jul 2014 10:36:29 +0200 Subject: [PATCH 05/49] updated changelog --- readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.txt b/readme.txt index bafca48a4..23fe99f71 100644 --- a/readme.txt +++ b/readme.txt @@ -130,6 +130,7 @@ Bug #1179: Crash after trying to load game after being killed Bug #1180: Changing footstep sound location Bug #1196: Jumping not disabled when showing messageboxes Bug #1202: "strange" keys are not shown in binding menu, and are not saved either, but works +Bug #1216: Broken dialog topics in russian Morrowind Bug #1217: Container content changes based on the current position of the mouse Bug #1234: Loading/saving issues with dynamic records Bug #1277: Text pasted into the console appears twice From 0295673869888ee3075b12e7e9681c5e1f167f71 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 7 Jul 2014 23:37:59 +0200 Subject: [PATCH 06/49] Reset item model when reference is reset (Fixes #1628) This caused crashes when the window was resized after the reference no longer exists (e.g. when a savegame is loaded) --- apps/openmw/mwgui/companionwindow.cpp | 5 +++++ apps/openmw/mwgui/companionwindow.hpp | 2 ++ apps/openmw/mwgui/container.cpp | 6 ++++++ apps/openmw/mwgui/container.hpp | 2 ++ apps/openmw/mwgui/tradewindow.cpp | 6 ++++++ apps/openmw/mwgui/tradewindow.hpp | 1 + 6 files changed, 22 insertions(+) diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp index d0ac3e7c3..8d199e727 100644 --- a/apps/openmw/mwgui/companionwindow.cpp +++ b/apps/openmw/mwgui/companionwindow.cpp @@ -153,6 +153,11 @@ void CompanionWindow::onReferenceUnavailable() MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Companion); } +void CompanionWindow::resetReference() +{ + ReferenceInterface::resetReference(); + mItemView->setModel(NULL); +} } diff --git a/apps/openmw/mwgui/companionwindow.hpp b/apps/openmw/mwgui/companionwindow.hpp index 006d0a3c3..dc460e2fc 100644 --- a/apps/openmw/mwgui/companionwindow.hpp +++ b/apps/openmw/mwgui/companionwindow.hpp @@ -20,6 +20,8 @@ namespace MWGui virtual void exit(); + virtual void resetReference(); + void open(const MWWorld::Ptr& npc); void onFrame (); diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 011feb4d3..8da3def5f 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -258,6 +258,12 @@ namespace MWGui onTakeAllButtonClicked(mTakeButton); } + void ContainerWindow::resetReference() + { + ReferenceInterface::resetReference(); + mItemView->setModel(NULL); + } + void ContainerWindow::close() { WindowBase::close(); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 5446a4ab7..79951f70e 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -54,6 +54,8 @@ namespace MWGui void open(const MWWorld::Ptr& container, bool loot=false); virtual void close(); + virtual void resetReference(); + virtual void exit(); private: diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index c0a51311f..19187cde1 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -531,4 +531,10 @@ namespace MWGui sellerStats.setLastRestockTime(MWBase::Environment::get().getWorld()->getTimeStamp()); } } + + void TradeWindow::resetReference() + { + ReferenceInterface::resetReference(); + mItemView->setModel(NULL); + } } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index cc70f1ae9..b487a8870 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -37,6 +37,7 @@ namespace MWGui virtual void exit(); + virtual void resetReference(); private: ItemView* mItemView; From 4a844ef79bbbfe23d9a9c2220aa0675a187bf7d1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 5 Jul 2014 18:24:55 +0200 Subject: [PATCH 07/49] Fix compile error for OPENMW_USE_FFMPEG=0 --- apps/openmw/mwrender/videoplayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index 03e74697c..409e27388 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -1088,7 +1088,7 @@ public: void close() { } - bool update(Ogre::MaterialPtr &mat, Ogre::Rectangle2D *rect, int screen_width, int screen_height) + bool update() { return false; } }; From ef9eb8351498118c32888345c68688cec30df5db Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 3 Jul 2014 20:28:52 +0200 Subject: [PATCH 08/49] Fix initializing CharacterController with fists or spell equipped --- apps/openmw/mwmechanics/character.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 2c5d68ceb..6549442ed 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -570,10 +570,14 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim if (cls.hasInventoryStore(mPtr)) { getActiveWeapon(cls.getCreatureStats(mPtr), cls.getInventoryStore(mPtr), &mWeaponType); - if(mWeaponType != WeapType_None && mWeaponType != WeapType_Spell && mWeaponType != WeapType_HandToHand) + if (mWeaponType != WeapType_None) { - getWeaponGroup(mWeaponType, mCurrentWeapon); mUpperBodyState = UpperCharState_WeapEquiped; + getWeaponGroup(mWeaponType, mCurrentWeapon); + } + + if(mWeaponType != WeapType_None && mWeaponType != WeapType_Spell && mWeaponType != WeapType_HandToHand) + { mAnimation->showWeapons(true); mAnimation->setWeaponGroup(mCurrentWeapon); } From 3042a9da7331e7908faaea50112c6e59ffbcd19c Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 3 Jul 2014 19:37:12 +0200 Subject: [PATCH 09/49] Cancel queued view mode switch when switching view mode (Fixes #1618) --- apps/openmw/mwrender/camera.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 9e683cc15..4580bae70 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -149,6 +149,8 @@ namespace MWRender mViewModeToggleQueued = true; return; } + else + mViewModeToggleQueued = false; mFirstPersonView = !mFirstPersonView; processViewChange(); From 05d92f0a7b3df74c48bfc4d89870a8c3f4f2e4d8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 8 Jul 2014 08:07:13 +0200 Subject: [PATCH 10/49] updated changelog --- readme.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/readme.txt b/readme.txt index 23fe99f71..a02cc4ebc 100644 --- a/readme.txt +++ b/readme.txt @@ -249,6 +249,8 @@ Bug #1590: Failed to save game: compile error Bug #1598: Segfault when making Drain/Fortify Skill spells Bug #1599: Unable to switch to fullscreen Bug #1613: Morrowind Rebirth duplicate objects / vanilla objects not removed +Bug #1618: Death notice fails to show up +Bug #1628: Alt+Tab Segfault Feature #32: Periodic Cleanup/Refill Feature #41: Precipitation and weather particles Feature #568: Editor: Configuration setup From 563c2e57309d33d2ef6156045b4202344b0540c9 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 15 Jul 2014 10:39:11 +0200 Subject: [PATCH 11/49] be a bit more relaxed about allowing - in names (Fixes #1593) --- components/compiler/scanner.cpp | 19 +++++++++++++------ components/compiler/scanner.hpp | 2 ++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index 46e50a2e9..dd8fb431b 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -343,17 +343,13 @@ namespace Compiler } else if (!(c=='"' && name.empty())) { - if (!(std::isalpha (c) || std::isdigit (c) || c=='_' || c=='`' || - /// \todo add an option to disable the following hack. Also, find out who is - /// responsible for allowing it in the first place and meet up with that person in - /// a dark alley. - (c=='-' && !name.empty() && std::isalpha (mStream.peek())))) + if (!isStringCharacter (c)) { putback (c); break; } - if (first && std::isdigit (c)) + if (first && (std::isdigit (c) || c=='`' || c=='-')) error = true; } @@ -499,6 +495,17 @@ namespace Compiler return true; } + bool Scanner::isStringCharacter (char c, bool lookAhead) + { + return std::isalpha (c) || std::isdigit (c) || c=='_' || + /// \todo disable this when doing more stricter compiling + c=='`' || + /// \todo disable this when doing more stricter compiling. Also, find out who is + /// responsible for allowing it in the first place and meet up with that person in + /// a dark alley. + (c=='-' && (!lookAhead || isStringCharacter (mStream.peek(), false))); + } + bool Scanner::isWhitespace (char c) { return c==' ' || c=='\t'; diff --git a/components/compiler/scanner.hpp b/components/compiler/scanner.hpp index 344ae0582..7f6609f76 100644 --- a/components/compiler/scanner.hpp +++ b/components/compiler/scanner.hpp @@ -92,6 +92,8 @@ namespace Compiler bool scanSpecial (char c, Parser& parser, bool& cont); + bool isStringCharacter (char c, bool lookAhead = true); + static bool isWhitespace (char c); public: From 8241ee59c3e0a9519200f9af64acabc18291bf85 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 15 Jul 2014 12:59:02 +0200 Subject: [PATCH 12/49] modified GlobalScripts data structures to accommodate targeted script data --- apps/openmw/mwscript/globalscripts.cpp | 60 +++++++++++++------------- apps/openmw/mwscript/globalscripts.hpp | 11 ++++- 2 files changed, 40 insertions(+), 31 deletions(-) diff --git a/apps/openmw/mwscript/globalscripts.cpp b/apps/openmw/mwscript/globalscripts.cpp index 8e118e2f8..411a0ec13 100644 --- a/apps/openmw/mwscript/globalscripts.cpp +++ b/apps/openmw/mwscript/globalscripts.cpp @@ -15,6 +15,9 @@ namespace MWScript { + GlobalScriptDesc::GlobalScriptDesc() : mRunning (false) {} + + GlobalScripts::GlobalScripts (const MWWorld::ESMStore& store) : mStore (store) { @@ -23,53 +26,53 @@ namespace MWScript void GlobalScripts::addScript (const std::string& name) { - std::map >::iterator iter = + std::map::iterator iter = mScripts.find (::Misc::StringUtils::lowerCase (name)); if (iter==mScripts.end()) { if (const ESM::Script *script = mStore.get().find (name)) { - Locals locals; - - locals.configure (*script); + GlobalScriptDesc desc; + desc.mRunning = true; + desc.mLocals.configure (*script); - mScripts.insert (std::make_pair (name, std::make_pair (true, locals))); + mScripts.insert (std::make_pair (name, desc)); } } else - iter->second.first = true; + iter->second.mRunning = true; } void GlobalScripts::removeScript (const std::string& name) { - std::map >::iterator iter = + std::map::iterator iter = mScripts.find (::Misc::StringUtils::lowerCase (name)); if (iter!=mScripts.end()) - iter->second.first = false; + iter->second.mRunning = false; } bool GlobalScripts::isRunning (const std::string& name) const { - std::map >::const_iterator iter = + std::map::const_iterator iter = mScripts.find (::Misc::StringUtils::lowerCase (name)); if (iter==mScripts.end()) return false; - return iter->second.first; + return iter->second.mRunning; } void GlobalScripts::run() { - for (std::map >::iterator iter (mScripts.begin()); + for (std::map::iterator iter (mScripts.begin()); iter!=mScripts.end(); ++iter) { - if (iter->second.first) + if (iter->second.mRunning) { MWScript::InterpreterContext interpreterContext ( - &iter->second.second, MWWorld::Ptr()); + &iter->second.mLocals, MWWorld::Ptr()); MWBase::Environment::get().getScriptManager()->run (iter->first, interpreterContext); } } @@ -99,16 +102,16 @@ namespace MWScript void GlobalScripts::write (ESM::ESMWriter& writer, Loading::Listener& progress) const { - for (std::map >::const_iterator iter (mScripts.begin()); + for (std::map::const_iterator iter (mScripts.begin()); iter!=mScripts.end(); ++iter) { ESM::GlobalScript script; script.mId = iter->first; - iter->second.second.write (script.mLocals, iter->first); + iter->second.mLocals.write (script.mLocals, iter->first); - script.mRunning = iter->second.first ? 1 : 0; + script.mRunning = iter->second.mRunning ? 1 : 0; writer.startRecord (ESM::REC_GSCR); script.save (writer); @@ -124,25 +127,24 @@ namespace MWScript ESM::GlobalScript script; script.load (reader); - std::map >::iterator iter = + std::map::iterator iter = mScripts.find (script.mId); if (iter==mScripts.end()) { if (const ESM::Script *scriptRecord = mStore.get().search (script.mId)) { - std::pair data (false, Locals()); + GlobalScriptDesc desc; + desc.mLocals.configure (*scriptRecord); - data.second.configure (*scriptRecord); - - iter = mScripts.insert (std::make_pair (script.mId, data)).first; + iter = mScripts.insert (std::make_pair (script.mId, desc)).first; } else // script does not exist anymore return true; } - iter->second.first = script.mRunning!=0; - iter->second.second.read (script.mLocals, script.mId); + iter->second.mRunning = script.mRunning!=0; + iter->second.mLocals.read (script.mLocals, script.mId); return true; } @@ -153,21 +155,19 @@ namespace MWScript Locals& GlobalScripts::getLocals (const std::string& name) { std::string name2 = ::Misc::StringUtils::lowerCase (name); - std::map >::iterator iter = - mScripts.find (name2); + std::map::iterator iter = mScripts.find (name2); if (iter==mScripts.end()) { if (const ESM::Script *script = mStore.get().find (name)) { - Locals locals; - - locals.configure (*script); + GlobalScriptDesc desc; + desc.mLocals.configure (*script); - iter = mScripts.insert (std::make_pair (name, std::make_pair (false, locals))).first; + iter = mScripts.insert (std::make_pair (name, desc)).first; } } - return iter->second.second; + return iter->second.mLocals; } } diff --git a/apps/openmw/mwscript/globalscripts.hpp b/apps/openmw/mwscript/globalscripts.hpp index 97584a5b8..9ad9361b6 100644 --- a/apps/openmw/mwscript/globalscripts.hpp +++ b/apps/openmw/mwscript/globalscripts.hpp @@ -26,10 +26,19 @@ namespace MWWorld namespace MWScript { + struct GlobalScriptDesc + { + bool mRunning; + Locals mLocals; + std::string mId; // ID used to start targeted script (empty if not a targeted script) + + GlobalScriptDesc(); + }; + class GlobalScripts { const MWWorld::ESMStore& mStore; - std::map > mScripts; // running, local variables + std::map mScripts; public: From e9377ad5c41abdfaecb6e12c79d91750cd0cfd12 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 15 Jul 2014 13:05:38 +0200 Subject: [PATCH 13/49] include targeted script data in saved games --- apps/openmw/mwscript/globalscripts.cpp | 3 +++ components/esm/globalscript.cpp | 4 ++++ components/esm/globalscript.hpp | 1 + 3 files changed, 8 insertions(+) diff --git a/apps/openmw/mwscript/globalscripts.cpp b/apps/openmw/mwscript/globalscripts.cpp index 411a0ec13..3335f4415 100644 --- a/apps/openmw/mwscript/globalscripts.cpp +++ b/apps/openmw/mwscript/globalscripts.cpp @@ -113,6 +113,8 @@ namespace MWScript script.mRunning = iter->second.mRunning ? 1 : 0; + script.mTargetId = iter->second.mId; + writer.startRecord (ESM::REC_GSCR); script.save (writer); writer.endRecord (ESM::REC_GSCR); @@ -145,6 +147,7 @@ namespace MWScript iter->second.mRunning = script.mRunning!=0; iter->second.mLocals.read (script.mLocals, script.mId); + iter->second.mId = script.mTargetId; return true; } diff --git a/components/esm/globalscript.cpp b/components/esm/globalscript.cpp index dcbd91140..467fe54a1 100644 --- a/components/esm/globalscript.cpp +++ b/components/esm/globalscript.cpp @@ -12,6 +12,8 @@ void ESM::GlobalScript::load (ESMReader &esm) mRunning = 0; esm.getHNOT (mRunning, "RUN_"); + + mTargetId = esm.getHNOString ("TARG"); } void ESM::GlobalScript::save (ESMWriter &esm) const @@ -22,4 +24,6 @@ void ESM::GlobalScript::save (ESMWriter &esm) const if (mRunning) esm.writeHNT ("RUN_", mRunning); + + esm.writeHNOString ("TARG", mTargetId); } \ No newline at end of file diff --git a/components/esm/globalscript.hpp b/components/esm/globalscript.hpp index 4fb8b7c48..43c859e09 100644 --- a/components/esm/globalscript.hpp +++ b/components/esm/globalscript.hpp @@ -15,6 +15,7 @@ namespace ESM std::string mId; Locals mLocals; int mRunning; + std::string mTargetId; // for targeted scripts void load (ESMReader &esm); void save (ESMWriter &esm) const; From 75ab8de3d200e24b934a86727f65f37cd787fe25 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 15 Jul 2014 13:26:04 +0200 Subject: [PATCH 14/49] added opcode for running scripts with explicit references (targeted scripts) --- apps/openmw/mwscript/globalscripts.cpp | 8 ++++-- apps/openmw/mwscript/globalscripts.hpp | 2 +- apps/openmw/mwscript/interpretercontext.cpp | 4 +-- apps/openmw/mwscript/interpretercontext.hpp | 2 +- components/interpreter/context.hpp | 2 +- components/interpreter/docs/vmformat.txt | 3 ++- components/interpreter/installopcodes.cpp | 1 + components/interpreter/scriptopcodes.hpp | 28 ++++++++++++++++----- 8 files changed, 36 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwscript/globalscripts.cpp b/apps/openmw/mwscript/globalscripts.cpp index 3335f4415..83c6560f0 100644 --- a/apps/openmw/mwscript/globalscripts.cpp +++ b/apps/openmw/mwscript/globalscripts.cpp @@ -24,7 +24,7 @@ namespace MWScript addStartup(); } - void GlobalScripts::addScript (const std::string& name) + void GlobalScripts::addScript (const std::string& name, const std::string& targetId) { std::map::iterator iter = mScripts.find (::Misc::StringUtils::lowerCase (name)); @@ -36,12 +36,16 @@ namespace MWScript GlobalScriptDesc desc; desc.mRunning = true; desc.mLocals.configure (*script); + desc.mId = targetId; mScripts.insert (std::make_pair (name, desc)); } } - else + else if (!iter->second.mRunning) + { iter->second.mRunning = true; + iter->second.mId = targetId; + } } void GlobalScripts::removeScript (const std::string& name) diff --git a/apps/openmw/mwscript/globalscripts.hpp b/apps/openmw/mwscript/globalscripts.hpp index 9ad9361b6..55c2e9321 100644 --- a/apps/openmw/mwscript/globalscripts.hpp +++ b/apps/openmw/mwscript/globalscripts.hpp @@ -44,7 +44,7 @@ namespace MWScript GlobalScripts (const MWWorld::ESMStore& store); - void addScript (const std::string& name); + void addScript (const std::string& name, const std::string& targetId = ""); void removeScript (const std::string& name); diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 028f83a61..0b474510d 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -366,9 +366,9 @@ namespace MWScript return MWBase::Environment::get().getScriptManager()->getGlobalScripts().isRunning (name); } - void InterpreterContext::startScript (const std::string& name) + void InterpreterContext::startScript (const std::string& name, const std::string& targetId) { - MWBase::Environment::get().getScriptManager()->getGlobalScripts().addScript (name); + MWBase::Environment::get().getScriptManager()->getGlobalScripts().addScript (name, targetId); } void InterpreterContext::stopScript (const std::string& name) diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 99026392e..0f4eefeeb 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -113,7 +113,7 @@ namespace MWScript virtual bool isScriptRunning (const std::string& name) const; - virtual void startScript (const std::string& name); + virtual void startScript (const std::string& name, const std::string& targetId = ""); virtual void stopScript (const std::string& name); diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index 97e4fad4f..25a3ab30d 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -81,7 +81,7 @@ namespace Interpreter virtual bool isScriptRunning (const std::string& name) const = 0; - virtual void startScript (const std::string& name) = 0; + virtual void startScript (const std::string& name, const std::string& targetId = "") = 0; virtual void stopScript (const std::string& name) = 0; diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index 990762268..5d1eba088 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -133,5 +133,6 @@ op 67: store stack[0] in member float stack[2] of global script with ID stack[1] op 68: replace stack[0] with member short stack[1] of global script with ID stack[0] op 69: replace stack[0] with member short stack[1] of global script with ID stack[0] op 70: replace stack[0] with member short stack[1] of global script with ID stack[0] -opcodes 71-33554431 unused +op 71: explicit reference (target) = stack[0]; pop; start script stack[0] and pop +opcodes 72-33554431 unused opcodes 33554432-67108863 reserved for extensions diff --git a/components/interpreter/installopcodes.cpp b/components/interpreter/installopcodes.cpp index 721cde3d8..d705a109c 100644 --- a/components/interpreter/installopcodes.cpp +++ b/components/interpreter/installopcodes.cpp @@ -113,6 +113,7 @@ namespace Interpreter interpreter.installSegment5 (46, new OpScriptRunning); interpreter.installSegment5 (47, new OpStartScript); interpreter.installSegment5 (48, new OpStopScript); + interpreter.installSegment5 (71, new OpStartScriptExplicit); // spacial interpreter.installSegment5 (49, new OpGetDistance); diff --git a/components/interpreter/scriptopcodes.hpp b/components/interpreter/scriptopcodes.hpp index 56502d510..c98bcd23e 100644 --- a/components/interpreter/scriptopcodes.hpp +++ b/components/interpreter/scriptopcodes.hpp @@ -10,36 +10,52 @@ namespace Interpreter class OpScriptRunning : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime[0].mInteger = runtime.getContext().isScriptRunning (name); - } + } }; class OpStartScript : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); runtime.getContext().startScript (name); - } + } + }; + + class OpStartScriptExplicit : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + std::string targetId = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + std::string name = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + runtime.getContext().startScript (name, targetId); + } }; class OpStopScript : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); runtime.getContext().stopScript (name); - } + } }; } From e8322da6631ecf49a6761210df1e9f89ac26725a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 17 Jul 2014 08:35:28 +0200 Subject: [PATCH 15/49] added support for targeted scripts to script compiler --- components/compiler/generator.cpp | 15 +++++++++++---- components/compiler/generator.hpp | 2 +- components/compiler/lineparser.cpp | 14 +++++++------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index c67e51e57..235b163ad 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -300,9 +300,9 @@ namespace code.push_back (Compiler::Generator::segment5 (46)); } - void opStartScript (Compiler::Generator::CodeContainer& code) + void opStartScript (Compiler::Generator::CodeContainer& code, bool targeted) { - code.push_back (Compiler::Generator::segment5 (47)); + code.push_back (Compiler::Generator::segment5 (targeted ? 71 : 47)); } void opStopScript (Compiler::Generator::CodeContainer& code) @@ -830,9 +830,16 @@ namespace Compiler opScriptRunning (code); } - void startScript (CodeContainer& code) + void startScript (CodeContainer& code, Literals& literals, const std::string& id) { - opStartScript (code); + if (id.empty()) + opStartScript (code, false); + else + { + int index = literals.addString (id); + opPushInt (code, index); + opStartScript (code, true); + } } void stopScript (CodeContainer& code) diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index b51116122..2619033c8 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -113,7 +113,7 @@ namespace Compiler void scriptRunning (CodeContainer& code); - void startScript (CodeContainer& code); + void startScript (CodeContainer& code, Literals& literals, const std::string& id); void stopScript (CodeContainer& code); diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index f7d2726e3..b1b831bc2 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -262,6 +262,13 @@ namespace Compiler Generator::disable (mCode, mLiterals, mExplicit); mState = PotentialEndState; return true; + + case Scanner::K_startscript: + + mExprParser.parseArguments ("c", scanner, mCode); + Generator::startScript (mCode, mLiterals, mExplicit); + mState = EndState; + return true; } // check for custom extensions @@ -361,13 +368,6 @@ namespace Compiler mState = EndState; return true; - case Scanner::K_startscript: - - mExprParser.parseArguments ("c", scanner, mCode); - Generator::startScript (mCode); - mState = EndState; - return true; - case Scanner::K_stopscript: mExprParser.parseArguments ("c", scanner, mCode); From dba6a9ebff4ba8c3ad8b4d2cee94a5b3bf3d7212 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 17 Jul 2014 09:15:41 +0200 Subject: [PATCH 16/49] run targeted scripts with an implicit reference based on the ID given --- apps/openmw/mwscript/globalscripts.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/globalscripts.cpp b/apps/openmw/mwscript/globalscripts.cpp index 83c6560f0..332431b16 100644 --- a/apps/openmw/mwscript/globalscripts.cpp +++ b/apps/openmw/mwscript/globalscripts.cpp @@ -75,8 +75,15 @@ namespace MWScript { if (iter->second.mRunning) { + MWWorld::Ptr ptr; + + if (!iter->second.mId.empty()) + ptr = MWBase::Environment::get().getWorld()->getPtr ( + iter->second.mId, false); + MWScript::InterpreterContext interpreterContext ( - &iter->second.mLocals, MWWorld::Ptr()); + &iter->second.mLocals, ptr); + MWBase::Environment::get().getScriptManager()->run (iter->first, interpreterContext); } } From 35b27ea8cb480e07ddffb24e91e7255f79d4de87 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 17 Jul 2014 11:29:04 +0200 Subject: [PATCH 17/49] ignore stray string argument after GetDisabled --- components/compiler/exprparser.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index e54b2e2a8..d0cda0ec2 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -386,6 +386,9 @@ namespace Compiler mExplicit.clear(); mRefOp = false; + std::vector ignore; + parseArguments ("x", scanner, ignore); + mNextOperand = false; return true; } @@ -527,6 +530,9 @@ namespace Compiler Generator::getDisabled (mCode, mLiterals, ""); mOperands.push_back ('l'); + std::vector ignore; + parseArguments ("x", scanner, ignore); + mNextOperand = false; return true; } From 27c84d6cb7130204334af3575edabfe589337762 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 17 Jul 2014 13:36:55 +0200 Subject: [PATCH 18/49] the reference for a targeted script is now determined when needed instead of at the start of the script execution --- apps/openmw/mwscript/globalscripts.cpp | 6 +-- apps/openmw/mwscript/interpretercontext.cpp | 49 +++++++++++++-------- apps/openmw/mwscript/interpretercontext.hpp | 19 ++++++-- components/interpreter/context.hpp | 2 + 4 files changed, 49 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwscript/globalscripts.cpp b/apps/openmw/mwscript/globalscripts.cpp index 332431b16..0c94f503b 100644 --- a/apps/openmw/mwscript/globalscripts.cpp +++ b/apps/openmw/mwscript/globalscripts.cpp @@ -77,12 +77,8 @@ namespace MWScript { MWWorld::Ptr ptr; - if (!iter->second.mId.empty()) - ptr = MWBase::Environment::get().getWorld()->getPtr ( - iter->second.mId, false); - MWScript::InterpreterContext interpreterContext ( - &iter->second.mLocals, ptr); + &iter->second.mLocals, MWWorld::Ptr(), iter->second.mId); MWBase::Environment::get().getScriptManager()->run (iter->first, interpreterContext); } diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 0b474510d..c64b4c0d3 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -22,7 +22,7 @@ namespace MWScript { - MWWorld::Ptr InterpreterContext::getReference ( + MWWorld::Ptr InterpreterContext::getReferenceImp ( const std::string& id, bool activeOnly, bool doThrow) { if (!id.empty()) @@ -31,6 +31,10 @@ namespace MWScript } else { + if (mReference.isEmpty() && !mTargetId.empty()) + mReference = + MWBase::Environment::get().getWorld()->searchPtr (mTargetId, false); + if (mReference.isEmpty() && doThrow) throw std::runtime_error ("no implicit reference"); @@ -38,7 +42,7 @@ namespace MWScript } } - const MWWorld::Ptr InterpreterContext::getReference ( + const MWWorld::Ptr InterpreterContext::getReferenceImp ( const std::string& id, bool activeOnly, bool doThrow) const { if (!id.empty()) @@ -47,6 +51,10 @@ namespace MWScript } else { + if (mReference.isEmpty() && !mTargetId.empty()) + mReference = + MWBase::Environment::get().getWorld()->searchPtr (mTargetId, false); + if (mReference.isEmpty() && doThrow) throw std::runtime_error ("no implicit reference"); @@ -64,7 +72,7 @@ namespace MWScript } else { - const MWWorld::Ptr ptr = getReference (id, false); + const MWWorld::Ptr ptr = getReferenceImp (id, false); id = ptr.getClass().getScript (ptr); @@ -84,7 +92,7 @@ namespace MWScript } else { - const MWWorld::Ptr ptr = getReference (id, false); + const MWWorld::Ptr ptr = getReferenceImp (id, false); id = ptr.getClass().getScript (ptr); @@ -96,9 +104,9 @@ namespace MWScript } InterpreterContext::InterpreterContext ( - MWScript::Locals *locals, MWWorld::Ptr reference) + MWScript::Locals *locals, MWWorld::Ptr reference, const std::string& targetId) : mLocals (locals), mReference (reference), - mActivationHandled (false) + mActivationHandled (false), mTargetId (targetId) {} int InterpreterContext::getLocalShort (int index) const @@ -236,34 +244,34 @@ namespace MWScript std::string InterpreterContext::getNPCName() const { - ESM::NPC npc = *mReference.get()->mBase; + ESM::NPC npc = *getReferenceImp().get()->mBase; return npc.mName; } std::string InterpreterContext::getNPCRace() const { - ESM::NPC npc = *mReference.get()->mBase; + ESM::NPC npc = *getReferenceImp().get()->mBase; const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npc.mRace); return race->mName; } std::string InterpreterContext::getNPCClass() const { - ESM::NPC npc = *mReference.get()->mBase; + ESM::NPC npc = *getReferenceImp().get()->mBase; const ESM::Class* class_ = MWBase::Environment::get().getWorld()->getStore().get().find(npc.mClass); return class_->mName; } std::string InterpreterContext::getNPCFaction() const { - ESM::NPC npc = *mReference.get()->mBase; + ESM::NPC npc = *getReferenceImp().get()->mBase; const ESM::Faction* faction = MWBase::Environment::get().getWorld()->getStore().get().find(npc.mFaction); return faction->mName; } std::string InterpreterContext::getNPCRank() const { - std::map ranks = mReference.getClass().getNpcStats (mReference).getFactionRanks(); + std::map ranks = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks(); std::map::const_iterator it = ranks.begin(); MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -299,7 +307,7 @@ namespace MWScript MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); - std::string factionId = mReference.getClass().getNpcStats (mReference).getFactionRanks().begin()->first; + std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first; std::map ranks = player.getClass().getNpcStats (player).getFactionRanks(); std::map::const_iterator it = ranks.find(factionId); @@ -326,7 +334,7 @@ namespace MWScript MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); - std::string factionId = mReference.getClass().getNpcStats (mReference).getFactionRanks().begin()->first; + std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first; std::map ranks = player.getClass().getNpcStats (player).getFactionRanks(); std::map::const_iterator it = ranks.find(factionId); @@ -383,7 +391,7 @@ namespace MWScript MWWorld::Ptr ref2; if (id.empty()) - ref2 = getReference("", true, true); + ref2 = getReferenceImp(); else ref2 = MWBase::Environment::get().getWorld()->searchPtr(id, true); @@ -448,19 +456,19 @@ namespace MWScript bool InterpreterContext::isDisabled (const std::string& id) const { - const MWWorld::Ptr ref = getReference (id, false); + const MWWorld::Ptr ref = getReferenceImp (id, false); return !ref.getRefData().isEnabled(); } void InterpreterContext::enable (const std::string& id) { - MWWorld::Ptr ref = getReference (id, false); + MWWorld::Ptr ref = getReferenceImp (id, false); MWBase::Environment::get().getWorld()->enable (ref); } void InterpreterContext::disable (const std::string& id) { - MWWorld::Ptr ref = getReference (id, false); + MWWorld::Ptr ref = getReferenceImp (id, false); MWBase::Environment::get().getWorld()->disable (ref); } @@ -542,6 +550,11 @@ namespace MWScript MWWorld::Ptr InterpreterContext::getReference(bool required) { - return getReference ("", true, required); + return getReferenceImp ("", true, required); + } + + std::string InterpreterContext::getTargetId() const + { + return mTargetId; } } diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 0f4eefeeb..f897282e2 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -27,14 +27,22 @@ namespace MWScript class InterpreterContext : public Interpreter::Context { Locals *mLocals; - MWWorld::Ptr mReference; + mutable MWWorld::Ptr mReference; MWWorld::Ptr mActivated; bool mActivationHandled; - MWWorld::Ptr getReference (const std::string& id, bool activeOnly, bool doThrow=true); + std::string mTargetId; - const MWWorld::Ptr getReference (const std::string& id, bool activeOnly, bool doThrow=true) const; + /// If \a id is empty, a reference the script is run from is returned or in case + /// of a non-local script the reference derived from the target ID. + MWWorld::Ptr getReferenceImp (const std::string& id = "", bool activeOnly = false, + bool doThrow=true); + + /// If \a id is empty, a reference the script is run from is returned or in case + /// of a non-local script the reference derived from the target ID. + const MWWorld::Ptr getReferenceImp (const std::string& id = "", + bool activeOnly = false, bool doThrow=true) const; const Locals& getMemberLocals (std::string& id, bool global) const; ///< \a id is changed to the respective script ID, if \a id wasn't a script ID before @@ -44,7 +52,8 @@ namespace MWScript public: - InterpreterContext (MWScript::Locals *locals, MWWorld::Ptr reference); + InterpreterContext (MWScript::Locals *locals, MWWorld::Ptr reference, + const std::string& targetId = ""); ///< The ownership of \a locals is not transferred. 0-pointer allowed. virtual int getLocalShort (int index) const; @@ -158,6 +167,8 @@ namespace MWScript MWWorld::Ptr getReference(bool required=true); ///< Reference, that the script is running from (can be empty) + + virtual std::string getTargetId() const; }; } diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index 25a3ab30d..881687366 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -108,6 +108,8 @@ namespace Interpreter virtual void setMemberFloat (const std::string& id, const std::string& name, float value, bool global) = 0; + + virtual std::string getTargetId() const = 0; }; } From 8952154488789989e7721678c1bfc5672590a1ff Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 17 Jul 2014 13:37:57 +0200 Subject: [PATCH 19/49] inherit target ID when starting a script from another script --- components/interpreter/scriptopcodes.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/interpreter/scriptopcodes.hpp b/components/interpreter/scriptopcodes.hpp index c98bcd23e..976390eb5 100644 --- a/components/interpreter/scriptopcodes.hpp +++ b/components/interpreter/scriptopcodes.hpp @@ -26,7 +26,7 @@ namespace Interpreter { std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - runtime.getContext().startScript (name); + runtime.getContext().startScript (name, runtime.getContext().getTargetId()); } }; From 4fb897f2f8ea61f3f40a133c9a908d0db8092863 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 18 Jul 2014 09:56:58 +0200 Subject: [PATCH 20/49] added missing getId functions to classes derived from MWWorld::Class --- apps/openmw/mwclass/activator.cpp | 5 +++++ apps/openmw/mwclass/activator.hpp | 3 +++ apps/openmw/mwclass/apparatus.cpp | 5 +++++ apps/openmw/mwclass/apparatus.hpp | 3 +++ apps/openmw/mwclass/armor.cpp | 5 +++++ apps/openmw/mwclass/armor.hpp | 3 +++ apps/openmw/mwclass/book.cpp | 5 +++++ apps/openmw/mwclass/book.hpp | 3 +++ apps/openmw/mwclass/clothing.cpp | 5 +++++ apps/openmw/mwclass/clothing.hpp | 3 +++ apps/openmw/mwclass/container.cpp | 5 +++++ apps/openmw/mwclass/container.hpp | 3 +++ apps/openmw/mwclass/creaturelevlist.cpp | 5 +++++ apps/openmw/mwclass/creaturelevlist.hpp | 3 +++ apps/openmw/mwclass/door.cpp | 5 +++++ apps/openmw/mwclass/door.hpp | 3 +++ apps/openmw/mwclass/itemlevlist.cpp | 5 +++++ apps/openmw/mwclass/itemlevlist.hpp | 3 +++ apps/openmw/mwclass/light.cpp | 5 +++++ apps/openmw/mwclass/light.hpp | 3 +++ apps/openmw/mwclass/lockpick.cpp | 5 +++++ apps/openmw/mwclass/lockpick.hpp | 3 +++ apps/openmw/mwclass/misc.cpp | 5 +++++ apps/openmw/mwclass/misc.hpp | 3 +++ apps/openmw/mwclass/potion.cpp | 5 +++++ apps/openmw/mwclass/potion.hpp | 3 +++ apps/openmw/mwclass/probe.cpp | 5 +++++ apps/openmw/mwclass/probe.hpp | 3 +++ apps/openmw/mwclass/repair.cpp | 5 +++++ apps/openmw/mwclass/repair.hpp | 3 +++ apps/openmw/mwclass/static.cpp | 5 +++++ apps/openmw/mwclass/static.hpp | 3 +++ 32 files changed, 128 insertions(+) diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 043aadd35..0585ced51 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -25,6 +25,11 @@ namespace MWClass { + std::string Activator::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index 1e772ef4f..3e4bc3de4 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -13,6 +13,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index d61ba038a..32f2e0bb7 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -21,6 +21,11 @@ namespace MWClass { + std::string Apparatus::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + void Apparatus::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index 17b8b9254..5cdda8f26 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -13,6 +13,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual float getWeight (const MWWorld::Ptr& ptr) const; virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index b29bf36b2..79766e9ec 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -25,6 +25,11 @@ namespace MWClass { + std::string Armor::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + void Armor::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index e9164f920..8b7804c63 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -12,6 +12,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual float getWeight (const MWWorld::Ptr& ptr) const; virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 0adee57e3..91b570783 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -22,6 +22,11 @@ namespace MWClass { + std::string Book::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + void Book::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index b60ef41d6..49d21e8bf 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -12,6 +12,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index dc98e323e..1a9a497d7 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -22,6 +22,11 @@ namespace MWClass { + std::string Clothing::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + void Clothing::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index 052928238..99ce61ece 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -12,6 +12,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 53add4274..044d67536 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -43,6 +43,11 @@ namespace namespace MWClass { + std::string Container::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + void Container::ensureCustomData (const MWWorld::Ptr& ptr) const { if (!ptr.getRefData().getCustomData()) diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 9fc013e45..e926a71fe 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -15,6 +15,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering diff --git a/apps/openmw/mwclass/creaturelevlist.cpp b/apps/openmw/mwclass/creaturelevlist.cpp index 784304804..754780b1d 100644 --- a/apps/openmw/mwclass/creaturelevlist.cpp +++ b/apps/openmw/mwclass/creaturelevlist.cpp @@ -27,6 +27,11 @@ namespace namespace MWClass { + std::string CreatureLevList::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + std::string CreatureLevList::getName (const MWWorld::Ptr& ptr) const { return ""; diff --git a/apps/openmw/mwclass/creaturelevlist.hpp b/apps/openmw/mwclass/creaturelevlist.hpp index 6c51a3189..7016524eb 100644 --- a/apps/openmw/mwclass/creaturelevlist.hpp +++ b/apps/openmw/mwclass/creaturelevlist.hpp @@ -11,6 +11,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 677ad462e..889268a9a 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -42,6 +42,11 @@ namespace namespace MWClass { + std::string Door::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + void Door::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index 12b360aa8..23e11d336 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -16,6 +16,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering diff --git a/apps/openmw/mwclass/itemlevlist.cpp b/apps/openmw/mwclass/itemlevlist.cpp index 6ed9ab2e5..d31080bb2 100644 --- a/apps/openmw/mwclass/itemlevlist.cpp +++ b/apps/openmw/mwclass/itemlevlist.cpp @@ -5,6 +5,11 @@ namespace MWClass { + std::string ItemLevList::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + std::string ItemLevList::getName (const MWWorld::Ptr& ptr) const { return ""; diff --git a/apps/openmw/mwclass/itemlevlist.hpp b/apps/openmw/mwclass/itemlevlist.hpp index 0b71b072c..2b507135f 100644 --- a/apps/openmw/mwclass/itemlevlist.hpp +++ b/apps/openmw/mwclass/itemlevlist.hpp @@ -9,6 +9,9 @@ namespace MWClass { public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 8a2c20f69..6178984cf 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -47,6 +47,11 @@ namespace namespace MWClass { + std::string Light::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + void Light::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 5568e1727..584039336 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -14,6 +14,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index bc6855129..9cce5694d 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -22,6 +22,11 @@ namespace MWClass { + std::string Lockpick::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + void Lockpick::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index 8f5a699d9..d4bdf3fa6 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -12,6 +12,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 1044fb01d..7bd2f9b67 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -38,6 +38,11 @@ bool isGold (const MWWorld::Ptr& ptr) namespace MWClass { + std::string Miscellaneous::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index 16e9ca10b..53a8e050b 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -12,6 +12,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 440121d35..b0b15193d 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -24,6 +24,11 @@ namespace MWClass { + std::string Potion::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index 0f0578ca0..4c407d161 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -12,6 +12,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index ed8625eec..030426dee 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -22,6 +22,11 @@ namespace MWClass { + std::string Probe::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + void Probe::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index a959e6c42..047cb8ed4 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -12,6 +12,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index d7a080534..f62d5f6cf 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -21,6 +21,11 @@ namespace MWClass { + std::string Repair::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + void Repair::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index 28ca5ad4c..17730d6ec 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -12,6 +12,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index 8768bde06..c241935ab 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -12,6 +12,11 @@ namespace MWClass { + std::string Static::getId (const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mId; + } + void Static::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { MWWorld::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/static.hpp b/apps/openmw/mwclass/static.hpp index e36b3d142..2ac2e8682 100644 --- a/apps/openmw/mwclass/static.hpp +++ b/apps/openmw/mwclass/static.hpp @@ -12,6 +12,9 @@ namespace MWClass public: + /// Return ID of \a ptr + virtual std::string getId (const MWWorld::Ptr& ptr) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering From 6a3ff211b18cbf5505dfb6f06a554aac4cf8355d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 18 Jul 2014 09:57:47 +0200 Subject: [PATCH 21/49] automatically get target ID at InterpreterContext construction, if a reference is available --- apps/openmw/mwscript/interpretercontext.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index c64b4c0d3..e1dc6273c 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -107,7 +107,13 @@ namespace MWScript MWScript::Locals *locals, MWWorld::Ptr reference, const std::string& targetId) : mLocals (locals), mReference (reference), mActivationHandled (false), mTargetId (targetId) - {} + { + // If we run on a reference (local script, dialogue script or console with object + // selected), store the ID of that reference store it so it can be inherited by + // targeted scripts started from this one. + if (targetId.empty() && !reference.isEmpty()) + mTargetId = reference.getClass().getId (reference); + } int InterpreterContext::getLocalShort (int index) const { From e33ee52b917c2e9a295b89b20c6cd117db32a439 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 18 Jul 2014 12:29:20 +0200 Subject: [PATCH 22/49] make stray names in the begin line a warning instead of an error --- components/compiler/fileparser.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/compiler/fileparser.cpp b/components/compiler/fileparser.cpp index 185af4a51..e90e9a8f6 100644 --- a/components/compiler/fileparser.cpp +++ b/components/compiler/fileparser.cpp @@ -51,6 +51,12 @@ namespace Compiler /// \todo allow this workaround to be disabled for newer scripts } + if (mState==BeginCompleteState) + { + reportWarning ("Stray string (" + name + ") after begin statement", loc); + return true; + } + return Parser::parseName (name, loc, scanner); } From d87630b41a0c5dc5deada97c2b3f363361f9554f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 Jul 2014 09:34:10 +0200 Subject: [PATCH 23/49] blacklisting for scripts in OpenMW --- apps/openmw/engine.cpp | 14 ++++++++++++- apps/openmw/engine.hpp | 6 ++++++ apps/openmw/main.cpp | 20 ++++++++++++++----- apps/openmw/mwscript/scriptmanagerimp.cpp | 24 ++++++++++++++++++----- apps/openmw/mwscript/scriptmanagerimp.hpp | 4 +++- files/openmw.cfg | 1 + files/openmw.cfg.local | 1 + 7 files changed, 58 insertions(+), 12 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index f8b4c9856..66eae5f5d 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -180,6 +180,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) , mEncoder(NULL) , mActivationDistanceOverride(-1) , mGrab(true) + , mScriptBlacklistUse (true) { std::srand ( std::time(NULL) ); @@ -406,7 +407,8 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) mScriptContext->setExtensions (&mExtensions); mEnvironment.setScriptManager (new MWScript::ScriptManager (MWBase::Environment::get().getWorld()->getStore(), - mVerboseScripts, *mScriptContext, mWarningsMode)); + mVerboseScripts, *mScriptContext, mWarningsMode, + mScriptBlacklistUse ? mScriptBlacklist : std::vector())); // Create game mechanics system MWMechanics::MechanicsManager* mechanics = new MWMechanics::MechanicsManager; @@ -565,3 +567,13 @@ void OMW::Engine::setWarningsMode (int mode) { mWarningsMode = mode; } + +void OMW::Engine::setScriptBlacklist (const std::vector& list) +{ + mScriptBlacklist = list; +} + +void OMW::Engine::setScriptBlacklistUse (bool use) +{ + mScriptBlacklistUse = use; +} \ No newline at end of file diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index e0f51d0dc..203379a93 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -89,6 +89,8 @@ namespace OMW Files::Collections mFileCollections; bool mFSStrict; Translation::Storage mTranslationDataStorage; + std::vector mScriptBlacklist; + bool mScriptBlacklistUse; // not implemented Engine (const Engine&); @@ -181,6 +183,10 @@ namespace OMW void setWarningsMode (int mode); + void setScriptBlacklist (const std::vector& list); + + void setScriptBlacklistUse (bool use); + private: Files::ConfigurationManager& mCfgMgr; }; diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index adde408b9..8cdab74d8 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -144,6 +144,12 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat "\t1 - show warning but consider script as correctly compiled anyway\n" "\t2 - treat warnings as errors") + ("script-blacklist", bpo::value()->default_value(StringsVector(), "") + ->multitoken(), "ignore the specified script (if the use of the blacklist is enabled)") + + ("script-blacklist-use", bpo::value()->implicit_value(true) + ->default_value(true), "enable script blacklisting") + ("skip-menu", bpo::value()->implicit_value(true) ->default_value(false), "skip main menu on game startup") @@ -241,15 +247,19 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat engine.setCell(variables["start"].as()); engine.setSkipMenu (variables["skip-menu"].as()); - // other settings - engine.setSoundUsage(!variables["no-sound"].as()); - engine.setScriptsVerbosity(variables["script-verbose"].as()); + // scripts engine.setCompileAll(variables["script-all"].as()); - engine.setFallbackValues(variables["fallback"].as().mMap); + engine.setScriptsVerbosity(variables["script-verbose"].as()); engine.setScriptConsoleMode (variables["script-console"].as()); engine.setStartupScript (variables["script-run"].as()); - engine.setActivationDistanceOverride (variables["activate-dist"].as()); engine.setWarningsMode (variables["script-warn"].as()); + engine.setScriptBlacklist (variables["script-blacklist"].as()); + engine.setScriptBlacklistUse (variables["script-blacklist-use"].as()); + + // other settings + engine.setSoundUsage(!variables["no-sound"].as()); + engine.setFallbackValues(variables["fallback"].as().mMap); + engine.setActivationDistanceOverride (variables["activate-dist"].as()); return true; } diff --git a/apps/openmw/mwscript/scriptmanagerimp.cpp b/apps/openmw/mwscript/scriptmanagerimp.cpp index 7b858dacf..781c16299 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.cpp +++ b/apps/openmw/mwscript/scriptmanagerimp.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -22,12 +23,19 @@ namespace MWScript { ScriptManager::ScriptManager (const MWWorld::ESMStore& store, bool verbose, - Compiler::Context& compilerContext, int warningsMode) + Compiler::Context& compilerContext, int warningsMode, + const std::vector& scriptBlacklist) : mErrorHandler (std::cerr), mStore (store), mVerbose (verbose), mCompilerContext (compilerContext), mParser (mErrorHandler, mCompilerContext), mOpcodesInstalled (false), mGlobalScripts (store) { mErrorHandler.setWarningsMode (warningsMode); + + mScriptBlacklist.resize (scriptBlacklist.size()); + + std::transform (scriptBlacklist.begin(), scriptBlacklist.end(), + mScriptBlacklist.begin(), Misc::StringUtils::lowerCase); + std::sort (mScriptBlacklist.begin(), mScriptBlacklist.end()); } bool ScriptManager::compile (const std::string& name) @@ -133,11 +141,17 @@ namespace MWScript int success = 0; const MWWorld::Store& scripts = mStore.get(); - MWWorld::Store::iterator it = scripts.begin(); - for (; it != scripts.end(); ++it, ++count) - if (compile (it->mId)) - ++success; + for (MWWorld::Store::iterator iter = scripts.begin(); + iter != scripts.end(); ++iter) + if (!std::binary_search (mScriptBlacklist.begin(), mScriptBlacklist.end(), + Misc::StringUtils::lowerCase (iter->mId))) + { + ++count; + + if (compile (iter->mId)) + ++success; + } return std::make_pair (count, success); } diff --git a/apps/openmw/mwscript/scriptmanagerimp.hpp b/apps/openmw/mwscript/scriptmanagerimp.hpp index da3abc60b..4edc09eca 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.hpp +++ b/apps/openmw/mwscript/scriptmanagerimp.hpp @@ -48,11 +48,13 @@ namespace MWScript ScriptCollection mScripts; GlobalScripts mGlobalScripts; std::map mOtherLocals; + std::vector mScriptBlacklist; public: ScriptManager (const MWWorld::ESMStore& store, bool verbose, - Compiler::Context& compilerContext, int warningsMode); + Compiler::Context& compilerContext, int warningsMode, + const std::vector& scriptBlacklist); virtual void run (const std::string& name, Interpreter::Context& interpreterContext); ///< Run the script with the given name (compile first, if not compiled yet) diff --git a/files/openmw.cfg b/files/openmw.cfg index b67b79a96..4ebe287d5 100644 --- a/files/openmw.cfg +++ b/files/openmw.cfg @@ -2,3 +2,4 @@ data="?global?data" data="?mw?Data Files" data-local="?userdata?data" resources=${OPENMW_RESOURCE_FILES} +script-blacklist=Museum diff --git a/files/openmw.cfg.local b/files/openmw.cfg.local index 6a578542d..4ae51382e 100644 --- a/files/openmw.cfg.local +++ b/files/openmw.cfg.local @@ -3,3 +3,4 @@ data="?mw?Data Files" data=./data data-local="?userdata?data" resources=./resources +script-blacklist=Museum From a9f9dec923927934c3adc9772b963cedd28e3874 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 Jul 2014 12:15:21 +0200 Subject: [PATCH 24/49] consider script blacklist in OpenCS verifier --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/editor.cpp | 10 +++++++- apps/opencs/model/doc/blacklist.cpp | 31 +++++++++++++++++++++++ apps/opencs/model/doc/blacklist.hpp | 25 ++++++++++++++++++ apps/opencs/model/doc/document.cpp | 14 ++++++++-- apps/opencs/model/doc/document.hpp | 7 ++++- apps/opencs/model/doc/documentmanager.cpp | 7 ++++- apps/opencs/model/doc/documentmanager.hpp | 3 +++ apps/opencs/model/tools/scriptcheck.cpp | 21 ++++++++++----- apps/opencs/model/tools/scriptcheck.hpp | 9 +++++-- apps/opencs/model/tools/tools.cpp | 6 +++-- apps/opencs/model/tools/tools.hpp | 4 ++- 12 files changed, 122 insertions(+), 17 deletions(-) create mode 100644 apps/opencs/model/doc/blacklist.cpp create mode 100644 apps/opencs/model/doc/blacklist.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index c03cc3138..e1e467889 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -9,7 +9,7 @@ opencs_units (model/doc ) opencs_units_noqt (model/doc - stage savingstate savingstages + stage savingstate savingstages blacklist ) opencs_hdrs_noqt (model/doc diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index b3513a7f1..44d66b236 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -86,7 +86,11 @@ std::pair > CS::Editor::readConfi ("encoding", boost::program_options::value()->default_value("win1252")) ("resources", boost::program_options::value()->default_value("resources")) ("fallback-archive", boost::program_options::value >()-> - default_value(std::vector(), "fallback-archive")->multitoken()); + default_value(std::vector(), "fallback-archive")->multitoken()) + ("script-blacklist", boost::program_options::value >()->default_value(std::vector(), "") + ->multitoken(), "exclude specified script from the verifier (if the use of the blacklist is enabled)") + ("script-blacklist-use", boost::program_options::value()->implicit_value(true) + ->default_value(true), "enable script blacklisting"); boost::program_options::notify(variables); @@ -97,6 +101,10 @@ std::pair > CS::Editor::readConfi mDocumentManager.setResourceDir (mResources = variables["resources"].as()); + if (variables["script-blacklist-use"].as()) + mDocumentManager.setBlacklistedScripts ( + variables["script-blacklist"].as >()); + mFsStrict = variables["fs-strict"].as(); Files::PathContainer dataDirs, dataLocal; diff --git a/apps/opencs/model/doc/blacklist.cpp b/apps/opencs/model/doc/blacklist.cpp new file mode 100644 index 000000000..9b37a4302 --- /dev/null +++ b/apps/opencs/model/doc/blacklist.cpp @@ -0,0 +1,31 @@ + +#include "blacklist.hpp" + +#include + +#include + +bool CSMDoc::Blacklist::isBlacklisted (const CSMWorld::UniversalId& id) const +{ + std::map >::const_iterator iter = + mIds.find (id.getType()); + + if (iter==mIds.end()) + return false; + + return std::binary_search (iter->second.begin(), iter->second.end(), + Misc::StringUtils::lowerCase (id.getId())); +} + +void CSMDoc::Blacklist::add (CSMWorld::UniversalId::Type type, + const std::vector& ids) +{ + std::vector& list = mIds[type]; + + int size = list.size(); + + list.resize (size+ids.size()); + + std::transform (ids.begin(), ids.end(), list.begin()+size, Misc::StringUtils::lowerCase); + std::sort (list.begin(), list.end()); +} \ No newline at end of file diff --git a/apps/opencs/model/doc/blacklist.hpp b/apps/opencs/model/doc/blacklist.hpp new file mode 100644 index 000000000..9bf7f1d86 --- /dev/null +++ b/apps/opencs/model/doc/blacklist.hpp @@ -0,0 +1,25 @@ +#ifndef CSM_DOC_BLACKLIST_H +#define CSM_DOC_BLACKLIST_H + +#include +#include +#include + +#include "../world/universalid.hpp" + +namespace CSMDoc +{ + /// \brief ID blacklist sorted by UniversalId type + class Blacklist + { + std::map > mIds; + + public: + + bool isBlacklisted (const CSMWorld::UniversalId& id) const; + + void add (CSMWorld::UniversalId::Type type, const std::vector& ids); + }; +} + +#endif diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 23a47b313..c608757e0 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2205,9 +2205,10 @@ void CSMDoc::Document::createBase() CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, bool new_, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, - ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager) + ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager, + const std::vector& blacklistedScripts) : mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager), - mTools (mData), mResDir(resDir), + mTools (*this), mResDir(resDir), mProjectPath ((configuration.getUserDataPath() / "projects") / (savePath.filename().string() + ".project")), mSaving (*this, mProjectPath, encoding) @@ -2239,6 +2240,8 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, createBase(); } + mBlacklist.add (CSMWorld::UniversalId::Type_Script, blacklistedScripts); + addOptionalGmsts(); addOptionalGlobals(); @@ -2358,6 +2361,13 @@ CSMTools::ReportModel *CSMDoc::Document::getReport (const CSMWorld::UniversalId& return mTools.getReport (id); } +bool CSMDoc::Document::isBlacklisted (const CSMWorld::UniversalId& id) + const +{ + return mBlacklist.isBlacklisted (id); +} + + void CSMDoc::Document::progress (int current, int max, int type) { emit progress (current, max, type, 1, this); diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index d092b47c8..d0e94d5e0 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -17,6 +17,7 @@ #include "state.hpp" #include "saving.hpp" +#include "blacklist.hpp" class QAbstractItemModel; @@ -52,6 +53,7 @@ namespace CSMDoc boost::filesystem::path mProjectPath; Saving mSaving; boost::filesystem::path mResDir; + Blacklist mBlacklist; // It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is // using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late. @@ -78,7 +80,8 @@ namespace CSMDoc Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, bool new_, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, - ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager); + ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager, + const std::vector& blacklistedScripts); ~Document(); @@ -110,6 +113,8 @@ namespace CSMDoc CSMTools::ReportModel *getReport (const CSMWorld::UniversalId& id); ///< The ownership of the returned report is not transferred. + bool isBlacklisted (const CSMWorld::UniversalId& id) const; + signals: void stateChanged (int state, CSMDoc::Document *document); diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 6953db0ed..9b807225c 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -52,7 +52,7 @@ CSMDoc::DocumentManager::~DocumentManager() void CSMDoc::DocumentManager::addDocument (const std::vector& files, const boost::filesystem::path& savePath, bool new_) { - Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager); + Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts); mDocuments.push_back (document); @@ -85,6 +85,11 @@ void CSMDoc::DocumentManager::setEncoding (ToUTF8::FromType encoding) mEncoding = encoding; } +void CSMDoc::DocumentManager::setBlacklistedScripts (const std::vector& scriptIds) +{ + mBlacklistedScripts = scriptIds; +} + void CSMDoc::DocumentManager::listResources() { mResourcesManager.listResources(); diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index cebae6f6d..c545b9a9f 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -34,6 +34,7 @@ namespace CSMDoc Loader mLoader; ToUTF8::FromType mEncoding; CSMWorld::ResourcesManager mResourcesManager; + std::vector mBlacklistedScripts; DocumentManager (const DocumentManager&); DocumentManager& operator= (const DocumentManager&); @@ -53,6 +54,8 @@ namespace CSMDoc void setEncoding (ToUTF8::FromType encoding); + void setBlacklistedScripts (const std::vector& scriptIds); + /// Ask OGRE for a list of available resources. void listResources(); diff --git a/apps/opencs/model/tools/scriptcheck.cpp b/apps/opencs/model/tools/scriptcheck.cpp index b989e22a2..d2c647bda 100644 --- a/apps/opencs/model/tools/scriptcheck.cpp +++ b/apps/opencs/model/tools/scriptcheck.cpp @@ -7,6 +7,8 @@ #include #include +#include "../doc/document.hpp" + #include "../world/data.hpp" void CSMTools::ScriptCheckStage::report (const std::string& message, const Compiler::TokenLoc& loc, @@ -37,8 +39,8 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, Type type) (type==ErrorMessage ? "error: " : "warning: ") + message)); } -CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMWorld::Data& data) -: mData (data), mContext (data), mMessages (0) +CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document) +: mDocument (document), mContext (document.getData()), mMessages (0) { /// \todo add an option to configure warning mode setWarningsMode (0); @@ -53,18 +55,25 @@ int CSMTools::ScriptCheckStage::setup() mMessages = 0; mId.clear(); - return mData.getScripts().getSize(); + return mDocument.getData().getScripts().getSize(); } void CSMTools::ScriptCheckStage::perform (int stage, Messages& messages) { + mId = mDocument.getData().getScripts().getId (stage); + + if (mDocument.isBlacklisted ( + CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Script, mId))) + return; + mMessages = &messages; - mId = mData.getScripts().getId (stage); try { - mFile = mData.getScripts().getRecord (stage).get().mId; - std::istringstream input (mData.getScripts().getRecord (stage).get().mScriptText); + const CSMWorld::Data& data = mDocument.getData(); + + mFile = data.getScripts().getRecord (stage).get().mId; + std::istringstream input (data.getScripts().getRecord (stage).get().mScriptText); Compiler::Scanner scanner (*this, input, mContext.getExtensions()); diff --git a/apps/opencs/model/tools/scriptcheck.hpp b/apps/opencs/model/tools/scriptcheck.hpp index ecf8d61b7..75f11b9d4 100644 --- a/apps/opencs/model/tools/scriptcheck.hpp +++ b/apps/opencs/model/tools/scriptcheck.hpp @@ -8,12 +8,17 @@ #include "../world/scriptcontext.hpp" +namespace CSMDoc +{ + class Document; +} + namespace CSMTools { /// \brief VerifyStage: make sure that scripts compile class ScriptCheckStage : public CSMDoc::Stage, private Compiler::ErrorHandler { - const CSMWorld::Data& mData; + const CSMDoc::Document& mDocument; Compiler::Extensions mExtensions; CSMWorld::ScriptContext mContext; std::string mId; @@ -28,7 +33,7 @@ namespace CSMTools public: - ScriptCheckStage (const CSMWorld::Data& data); + ScriptCheckStage (const CSMDoc::Document& document); virtual int setup(); ///< \return number of steps diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 2f93db48e..fcf98868a 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -5,6 +5,7 @@ #include "../doc/state.hpp" #include "../doc/operation.hpp" +#include "../doc/document.hpp" #include "../world/data.hpp" #include "../world/universalid.hpp" @@ -80,13 +81,14 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier() mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions())); - mVerifier->appendStage (new ScriptCheckStage (mData)); + mVerifier->appendStage (new ScriptCheckStage (mDocument)); } return mVerifier; } -CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0), mNextReportNumber (0) +CSMTools::Tools::Tools (CSMDoc::Document& document) +: mDocument (document), mData (document.getData()), mVerifier (0), mNextReportNumber (0) { // index 0: load error log mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 3394d3f62..4d677142d 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -14,6 +14,7 @@ namespace CSMWorld namespace CSMDoc { class Operation; + class Document; } namespace CSMTools @@ -24,6 +25,7 @@ namespace CSMTools { Q_OBJECT + CSMDoc::Document& mDocument; CSMWorld::Data& mData; CSMDoc::Operation *mVerifier; std::map mReports; @@ -44,7 +46,7 @@ namespace CSMTools public: - Tools (CSMWorld::Data& data); + Tools (CSMDoc::Document& document); virtual ~Tools(); From 11a2c767cc474a3a8c1f3b831d5a67b7e7449c72 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 Jul 2014 12:50:29 +0200 Subject: [PATCH 25/49] some argument parsing cleanup --- components/compiler/exprparser.cpp | 30 +++++++++++++++++++----------- components/compiler/extensions.hpp | 2 +- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index d0cda0ec2..6e29626b1 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -777,11 +777,22 @@ namespace Compiler ++optionalCount; } } + else if (*iter=='X') + { + parser.reset(); + + parser.setOptional (true); + + scanner.scan (parser); + + if (optional && parser.isEmpty()) + break; + } else { parser.reset(); - if (optional || *iter == 'X') + if (optional) parser.setOptional (true); scanner.scan (parser); @@ -789,20 +800,17 @@ namespace Compiler if (optional && parser.isEmpty()) break; - if (*iter != 'X') - { - std::vector tmp; + std::vector tmp; - char type = parser.append (tmp); + char type = parser.append (tmp); - if (type!=*iter) - Generator::convert (tmp, type, *iter); + if (type!=*iter) + Generator::convert (tmp, type, *iter); - stack.push (tmp); + stack.push (tmp); - if (optional) - ++optionalCount; - } + if (optional) + ++optionalCount; } } diff --git a/components/compiler/extensions.hpp b/components/compiler/extensions.hpp index d229751de..aa62fd0eb 100644 --- a/components/compiler/extensions.hpp +++ b/components/compiler/extensions.hpp @@ -21,7 +21,7 @@ namespace Compiler s - Short
S - String, case preserved
x - Optional, ignored string argument - X - Optional, ignored integer argument + X - Optional, ignored float argument **/ typedef std::string ScriptArgs; From aa8c0bccb4b8c304bcdef0cbdda0f808aa31d437 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 23 Jul 2014 09:44:29 +0200 Subject: [PATCH 26/49] added new argument type: z (optional, any) --- components/CMakeLists.txt | 2 +- components/compiler/discardparser.cpp | 70 +++++++++++++++++++++++++++ components/compiler/discardparser.hpp | 45 +++++++++++++++++ components/compiler/exprparser.cpp | 14 +++++- components/compiler/extensions.hpp | 3 +- 5 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 components/compiler/discardparser.cpp create mode 100644 components/compiler/discardparser.hpp diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index b8ebb84b1..a9bd376a9 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -58,7 +58,7 @@ add_component_dir (compiler context controlparser errorhandler exception exprparser extensions fileparser generator lineparser literals locals output parser scanner scriptparser skipparser streamerrorhandler stringparser tokenloc nullerrorhandler opcodes extensions0 declarationparser - quickfileparser + quickfileparser discardparser ) add_component_dir (interpreter diff --git a/components/compiler/discardparser.cpp b/components/compiler/discardparser.cpp new file mode 100644 index 000000000..6028968bb --- /dev/null +++ b/components/compiler/discardparser.cpp @@ -0,0 +1,70 @@ + +#include "discardparser.hpp" + +#include "scanner.hpp" + +namespace Compiler +{ + DiscardParser::DiscardParser (ErrorHandler& errorHandler, const Context& context) + : Parser (errorHandler, context), mState (StartState) + { + + } + + bool DiscardParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner) + { + if (mState==StartState || mState==CommaState || mState==MinusState) + { + start(); + return false; + } + + return Parser::parseInt (value, loc, scanner); + } + + bool DiscardParser::parseFloat (float value, const TokenLoc& loc, Scanner& scanner) + { + if (mState==StartState || mState==CommaState || mState==MinusState) + { + start(); + return false; + } + + return Parser::parseFloat (value, loc, scanner); + } + + bool DiscardParser::parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner) + { + if (mState==StartState || mState==CommaState) + { + start(); + return false; + } + + return Parser::parseName (name, loc, scanner); + } + + bool DiscardParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) + { + if (code==Scanner::S_comma && mState==StartState) + { + mState = CommaState; + return true; + } + + if (code==Scanner::S_minus && (mState==StartState || mState==CommaState)) + { + mState = MinusState; + return true; + } + + return Parser::parseSpecial (code, loc, scanner); + } + + void DiscardParser::reset() + { + mState = StartState; + Parser::reset(); + } +} diff --git a/components/compiler/discardparser.hpp b/components/compiler/discardparser.hpp new file mode 100644 index 000000000..bee8a87bb --- /dev/null +++ b/components/compiler/discardparser.hpp @@ -0,0 +1,45 @@ +#ifndef COMPILER_DISCARDPARSER_H_INCLUDED +#define COMPILER_DISCARDPARSER_H_INCLUDED + +#include "parser.hpp" + +namespace Compiler +{ + /// \brief Parse a single optional numeric value or string and discard it + class DiscardParser : public Parser + { + enum State + { + StartState, CommaState, MinusState + }; + + State mState; + + public: + + DiscardParser (ErrorHandler& errorHandler, const Context& context); + + virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner); + ///< Handle an int token. + /// \return fetch another token? + + virtual bool parseFloat (float value, const TokenLoc& loc, Scanner& scanner); + ///< Handle a float token. + /// \return fetch another token? + + virtual bool parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner); + ///< Handle a name token. + /// \return fetch another token? + + virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner); + ///< Handle a special character token. + /// \return fetch another token? + + virtual void reset(); + ///< Reset parser to clean state. + }; +} + +#endif + diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 6e29626b1..d94f6c436 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -16,6 +16,7 @@ #include "stringparser.hpp" #include "extensions.hpp" #include "context.hpp" +#include "discardparser.hpp" namespace Compiler { @@ -743,6 +744,7 @@ namespace Compiler ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true); StringParser stringParser (getErrorHandler(), getContext(), mLiterals); + DiscardParser discardParser (getErrorHandler(), getContext()); std::stack > stack; @@ -785,7 +787,17 @@ namespace Compiler scanner.scan (parser); - if (optional && parser.isEmpty()) + if (parser.isEmpty()) + break; + } + else if (*iter=='z') + { + discardParser.reset(); + discardParser.setOptional (true); + + scanner.scan (discardParser); + + if (discardParser.isEmpty()) break; } else diff --git a/components/compiler/extensions.hpp b/components/compiler/extensions.hpp index aa62fd0eb..a15218d99 100644 --- a/components/compiler/extensions.hpp +++ b/components/compiler/extensions.hpp @@ -21,7 +21,8 @@ namespace Compiler s - Short
S - String, case preserved
x - Optional, ignored string argument - X - Optional, ignored float argument + X - Optional, ignored numeric expression + z - Optional, ignored string or numeric argument **/ typedef std::string ScriptArgs; From 19f4c46fe4eac193e0423dca48803f7b48af301e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 23 Jul 2014 12:33:35 +0200 Subject: [PATCH 27/49] alllow (and ignore) explicit references for StopScript and ScriptRunning --- components/compiler/exprparser.cpp | 15 +++++++++++++++ components/compiler/lineparser.cpp | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index d94f6c436..6dcca08df 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -408,6 +408,21 @@ namespace Compiler mNextOperand = false; return true; } + else if (keyword==Scanner::K_scriptrunning) + { + start(); + + mTokenLoc = loc; + parseArguments ("c", scanner); + + Generator::scriptRunning (mCode); + mOperands.push_back ('l'); + + mExplicit.clear(); + mRefOp = false; + mNextOperand = false; + return true; + } // check for custom extensions if (const Extensions *extensions = getContext().getExtensions()) diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index b1b831bc2..cdbfaa04a 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -269,6 +269,13 @@ namespace Compiler Generator::startScript (mCode, mLiterals, mExplicit); mState = EndState; return true; + + case Scanner::K_stopscript: + + mExprParser.parseArguments ("c", scanner, mCode); + Generator::stopScript (mCode); + mState = EndState; + return true; } // check for custom extensions From f55084463b47cb3bee1d420f7badee83de0f710f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 23 Jul 2014 12:35:15 +0200 Subject: [PATCH 28/49] added MockChangeScript to script blacklist --- files/openmw.cfg | 1 + files/openmw.cfg.local | 1 + 2 files changed, 2 insertions(+) diff --git a/files/openmw.cfg b/files/openmw.cfg index 4ebe287d5..de1f22e50 100644 --- a/files/openmw.cfg +++ b/files/openmw.cfg @@ -3,3 +3,4 @@ data="?mw?Data Files" data-local="?userdata?data" resources=${OPENMW_RESOURCE_FILES} script-blacklist=Museum +script-blacklist=MockChangeScript \ No newline at end of file diff --git a/files/openmw.cfg.local b/files/openmw.cfg.local index 4ae51382e..b2970fb19 100644 --- a/files/openmw.cfg.local +++ b/files/openmw.cfg.local @@ -4,3 +4,4 @@ data=./data data-local="?userdata?data" resources=./resources script-blacklist=Museum +script-blacklist=MockChangeScript From 2e355df8b31a60a1c72b0b837c895caf0b0c8714 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 Jul 2014 07:59:50 +0200 Subject: [PATCH 29/49] removed function ScriptManager::getLocalIndex (was redundant and was also depending on precompiled scripts) --- apps/openmw/mwbase/scriptmanager.hpp | 8 +-- apps/openmw/mwscript/interpretercontext.cpp | 60 ++++++++++++--------- apps/openmw/mwscript/interpretercontext.hpp | 4 ++ apps/openmw/mwscript/scriptmanagerimp.cpp | 42 --------------- apps/openmw/mwscript/scriptmanagerimp.hpp | 5 -- components/compiler/locals.hpp | 6 ++- 6 files changed, 45 insertions(+), 80 deletions(-) diff --git a/apps/openmw/mwbase/scriptmanager.hpp b/apps/openmw/mwbase/scriptmanager.hpp index ae146e064..1a9eee456 100644 --- a/apps/openmw/mwbase/scriptmanager.hpp +++ b/apps/openmw/mwbase/scriptmanager.hpp @@ -50,13 +50,7 @@ namespace MWBase ///< Return locals for script \a name. virtual MWScript::GlobalScripts& getGlobalScripts() = 0; - - virtual int getLocalIndex (const std::string& scriptId, const std::string& variable, - char type) = 0; - ///< Return index of the variable of the given name and type in the given script. Will - /// throw an exception, if there is no such script or variable or the type does not match. - - }; + }; } #endif diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index e1dc6273c..121b07e34 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -3,8 +3,12 @@ #include #include +#include #include + +#include + #include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" @@ -103,6 +107,32 @@ namespace MWScript } } + int InterpreterContext::findLocalVariableIndex (const std::string& scriptId, + const std::string& name, char type) const + { + int index = MWBase::Environment::get().getScriptManager()->getLocals (scriptId). + search (type, name); + + if (index!=-1) + return index; + + std::ostringstream stream; + + stream << "Failed to access "; + + switch (type) + { + case 's': stream << "short"; break; + case 'l': stream << "long"; break; + case 'f': stream << "float"; break; + } + + stream << " member variable " << name << " in script " << scriptId; + + throw std::runtime_error (stream.str().c_str()); + } + + InterpreterContext::InterpreterContext ( MWScript::Locals *locals, MWWorld::Ptr reference, const std::string& targetId) : mLocals (locals), mReference (reference), @@ -485,10 +515,7 @@ namespace MWScript const Locals& locals = getMemberLocals (scriptId, global); - int index = MWBase::Environment::get().getScriptManager()->getLocalIndex ( - scriptId, name, 's'); - - return locals.mShorts[index]; + return locals.mShorts[findLocalVariableIndex (scriptId, name, 's')]; } int InterpreterContext::getMemberLong (const std::string& id, const std::string& name, @@ -498,10 +525,7 @@ namespace MWScript const Locals& locals = getMemberLocals (scriptId, global); - int index = MWBase::Environment::get().getScriptManager()->getLocalIndex ( - scriptId, name, 'l'); - - return locals.mLongs[index]; + return locals.mLongs[findLocalVariableIndex (scriptId, name, 'l')]; } float InterpreterContext::getMemberFloat (const std::string& id, const std::string& name, @@ -511,10 +535,7 @@ namespace MWScript const Locals& locals = getMemberLocals (scriptId, global); - int index = MWBase::Environment::get().getScriptManager()->getLocalIndex ( - scriptId, name, 'f'); - - return locals.mFloats[index]; + return locals.mFloats[findLocalVariableIndex (scriptId, name, 'f')]; } void InterpreterContext::setMemberShort (const std::string& id, const std::string& name, @@ -524,10 +545,7 @@ namespace MWScript Locals& locals = getMemberLocals (scriptId, global); - int index = - MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's'); - - locals.mShorts[index] = value; + locals.mShorts[findLocalVariableIndex (scriptId, name, 's')] = value; } void InterpreterContext::setMemberLong (const std::string& id, const std::string& name, int value, bool global) @@ -536,10 +554,7 @@ namespace MWScript Locals& locals = getMemberLocals (scriptId, global); - int index = - MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l'); - - locals.mLongs[index] = value; + locals.mLongs[findLocalVariableIndex (scriptId, name, 'l')] = value; } void InterpreterContext::setMemberFloat (const std::string& id, const std::string& name, float value, bool global) @@ -548,10 +563,7 @@ namespace MWScript Locals& locals = getMemberLocals (scriptId, global); - int index = - MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f'); - - locals.mFloats[index] = value; + locals.mFloats[findLocalVariableIndex (scriptId, name, 'f')] = value; } MWWorld::Ptr InterpreterContext::getReference(bool required) diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index f897282e2..bc43f3e44 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -50,6 +50,10 @@ namespace MWScript Locals& getMemberLocals (std::string& id, bool global); ///< \a id is changed to the respective script ID, if \a id wasn't a script ID before + /// Throws an exception if local variable can't be found. + int findLocalVariableIndex (const std::string& scriptId, const std::string& name, + char type) const; + public: InterpreterContext (MWScript::Locals *locals, MWWorld::Ptr reference, diff --git a/apps/openmw/mwscript/scriptmanagerimp.cpp b/apps/openmw/mwscript/scriptmanagerimp.cpp index 781c16299..289fd9a70 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.cpp +++ b/apps/openmw/mwscript/scriptmanagerimp.cpp @@ -196,46 +196,4 @@ namespace MWScript { return mGlobalScripts; } - - int ScriptManager::getLocalIndex (const std::string& scriptId, const std::string& variable, - char type) - { - const ESM::Script *script = mStore.get().find (scriptId); - - int offset = 0; - int size = 0; - - switch (type) - { - case 's': - - offset = 0; - size = script->mData.mNumShorts; - break; - - case 'l': - - offset = script->mData.mNumShorts; - size = script->mData.mNumLongs; - break; - - case 'f': - - offset = script->mData.mNumShorts+script->mData.mNumLongs; - size = script->mData.mNumFloats; - break; - - default: - - throw std::runtime_error ("invalid variable type"); - } - - std::string variable2 = Misc::StringUtils::lowerCase (variable); - - for (int i=0; imVarNames.at (i+offset))==variable2) - return i; - - throw std::runtime_error ("unable to access local variable " + variable + " of " + scriptId); - } } diff --git a/apps/openmw/mwscript/scriptmanagerimp.hpp b/apps/openmw/mwscript/scriptmanagerimp.hpp index 4edc09eca..7b1121aca 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.hpp +++ b/apps/openmw/mwscript/scriptmanagerimp.hpp @@ -71,11 +71,6 @@ namespace MWScript ///< Return locals for script \a name. virtual GlobalScripts& getGlobalScripts(); - - virtual int getLocalIndex (const std::string& scriptId, const std::string& variable, - char type); - ///< 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. }; } diff --git a/components/compiler/locals.hpp b/components/compiler/locals.hpp index d5bf05253..cf7899b5c 100644 --- a/components/compiler/locals.hpp +++ b/components/compiler/locals.hpp @@ -17,8 +17,6 @@ namespace Compiler int searchIndex (char type, const std::string& name) const; - bool search (char type, const std::string& name) const; - std::vector& get (char type); public: @@ -29,6 +27,10 @@ namespace Compiler int getIndex (const std::string& name) const; ///< return index for local variable \a name (-1: does not exist). + /// Return index for local variable \a name of type \a type (-1: variable does not + /// exit). + bool search (char type, const std::string& name) const; + const std::vector& get (char type) const; void write (std::ostream& localFile) const; From 9f69db0d69538add19a714391e825c01a7254da2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 Jul 2014 08:12:53 +0200 Subject: [PATCH 30/49] added missing const to ScriptManager::getLocals --- apps/openmw/mwbase/scriptmanager.hpp | 2 +- apps/openmw/mwscript/scriptmanagerimp.cpp | 2 +- apps/openmw/mwscript/scriptmanagerimp.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwbase/scriptmanager.hpp b/apps/openmw/mwbase/scriptmanager.hpp index 1a9eee456..7bdeba132 100644 --- a/apps/openmw/mwbase/scriptmanager.hpp +++ b/apps/openmw/mwbase/scriptmanager.hpp @@ -46,7 +46,7 @@ namespace MWBase ///< Compile all scripts /// \return count, success - virtual Compiler::Locals& getLocals (const std::string& name) = 0; + virtual const Compiler::Locals& getLocals (const std::string& name) = 0; ///< Return locals for script \a name. virtual MWScript::GlobalScripts& getGlobalScripts() = 0; diff --git a/apps/openmw/mwscript/scriptmanagerimp.cpp b/apps/openmw/mwscript/scriptmanagerimp.cpp index 289fd9a70..5af214268 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.cpp +++ b/apps/openmw/mwscript/scriptmanagerimp.cpp @@ -156,7 +156,7 @@ namespace MWScript return std::make_pair (count, success); } - Compiler::Locals& ScriptManager::getLocals (const std::string& name) + const Compiler::Locals& ScriptManager::getLocals (const std::string& name) { std::string name2 = Misc::StringUtils::lowerCase (name); diff --git a/apps/openmw/mwscript/scriptmanagerimp.hpp b/apps/openmw/mwscript/scriptmanagerimp.hpp index 7b1121aca..6026f6aba 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.hpp +++ b/apps/openmw/mwscript/scriptmanagerimp.hpp @@ -67,7 +67,7 @@ namespace MWScript ///< Compile all scripts /// \return count, success - virtual Compiler::Locals& getLocals (const std::string& name); + virtual const Compiler::Locals& getLocals (const std::string& name); ///< Return locals for script \a name. virtual GlobalScripts& getGlobalScripts(); From f6b502b195f508e12db8491a0c29b0db72820081 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 Jul 2014 09:05:17 +0200 Subject: [PATCH 31/49] rewrote dialgoue filter access to local variables --- apps/openmw/mwdialogue/filter.cpp | 52 ++++++++++++------------------- 1 file changed, 20 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index 08cdb1d00..b7f91613a 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -1,11 +1,14 @@ #include "filter.hpp" +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/journal.hpp" #include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/dialoguemanager.hpp" +#include "../mwbase/scriptmanager.hpp" #include "../mwworld/class.hpp" #include "../mwworld/inventorystore.hpp" @@ -187,33 +190,28 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c if (scriptName.empty()) return false; // no script - const ESM::Script *script = - MWBase::Environment::get().getWorld()->getStore().get().find (scriptName); + std::string name = Misc::StringUtils::lowerCase (select.getName()); - std::string name = select.getName(); + const Compiler::Locals& localDefs = + MWBase::Environment::get().getScriptManager()->getLocals (scriptName); - int i = 0; + char type = localDefs.getType (name); - for (; i (script->mVarNames.size()); ++i) - if (Misc::StringUtils::ciEqual(script->mVarNames[i], name)) - break; + if (type==' ') + return false; // script does not have a variable of this name. - if (i>=static_cast (script->mVarNames.size())) - return false; // script does not have a variable of this name + int index = localDefs.getIndex (name); const MWScript::Locals& locals = mActor.getRefData().getLocals(); - if (imData.mNumShorts) - return select.selectCompare (static_cast (locals.mShorts[i])); - - i -= script->mData.mNumShorts; - - if (imData.mNumLongs) - return select.selectCompare (locals.mLongs[i]); - - i -= script->mData.mNumLongs; + switch (type) + { + case 's': return select.selectCompare (static_cast (locals.mShorts[index])); + case 'l': return select.selectCompare (locals.mLongs[index]); + case 'f': return select.selectCompare (locals.mFloats[index]); + } - return select.selectCompare (locals.mFloats.at (i)); + throw std::logic_error ("unknown local variable type in dialogue filter"); } case SelectWrapper::Function_PcHealthPercent: @@ -453,20 +451,10 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co // This actor has no attached script, so there is no local variable return true; - const ESM::Script *script = - MWBase::Environment::get().getWorld()->getStore().get().find (scriptName); - - std::string name = select.getName(); - - int i = 0; - for (; i < static_cast (script->mVarNames.size()); ++i) - if (Misc::StringUtils::ciEqual(script->mVarNames[i], name)) - break; - - if (i >= static_cast (script->mVarNames.size())) - return true; // script does not have a variable of this name + const Compiler::Locals& localDefs = + MWBase::Environment::get().getScriptManager()->getLocals (scriptName); - return false; + return localDefs.getIndex (Misc::StringUtils::lowerCase (select.getName()))==-1; } case SelectWrapper::Function_SameGender: From 87c54adb2460fa1028aae89c3a7cca52a154ebbe Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 Jul 2014 09:26:30 +0200 Subject: [PATCH 32/49] some cleanup --- apps/openmw/mwscript/locals.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwscript/locals.cpp b/apps/openmw/mwscript/locals.cpp index 57584ac30..6a8a857d8 100644 --- a/apps/openmw/mwscript/locals.cpp +++ b/apps/openmw/mwscript/locals.cpp @@ -29,7 +29,7 @@ namespace MWScript int Locals::getIntVar(const std::string &script, const std::string &var) { - Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script); + const Compiler::Locals& locals = MWBase::Environment::get().getScriptManager()->getLocals(script); int index = locals.getIndex(var); char type = locals.getType(var); if(index != -1) @@ -53,7 +53,7 @@ namespace MWScript bool Locals::setVarByInt(const std::string& script, const std::string& var, int val) { - Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script); + const Compiler::Locals& locals = MWBase::Environment::get().getScriptManager()->getLocals(script); int index = locals.getIndex(var); char type = locals.getType(var); if(index != -1) From a3c4000198b1b970d52275ff8cdb67515158fc6a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 Jul 2014 09:36:02 +0200 Subject: [PATCH 33/49] moved call to Globalscripts::addStartup out of the constructor because at the time of construction the environment may not be set up yet to perform this operation --- apps/openmw/engine.cpp | 2 ++ apps/openmw/mwscript/globalscripts.cpp | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 66eae5f5d..6a48789a5 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -421,6 +421,8 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) mOgre->getRoot()->addFrameListener (this); // scripts + mEnvironment.getScriptManager()->getGlobalScripts().addStartup(); + if (mCompileAll) { std::pair result = MWBase::Environment::get().getScriptManager()->compileAll(); diff --git a/apps/openmw/mwscript/globalscripts.cpp b/apps/openmw/mwscript/globalscripts.cpp index 0c94f503b..8270c4e6b 100644 --- a/apps/openmw/mwscript/globalscripts.cpp +++ b/apps/openmw/mwscript/globalscripts.cpp @@ -20,9 +20,7 @@ namespace MWScript GlobalScripts::GlobalScripts (const MWWorld::ESMStore& store) : mStore (store) - { - addStartup(); - } + {} void GlobalScripts::addScript (const std::string& name, const std::string& targetId) { From 1ca0cc4988caccd1ccc848dce3a2b2c8a200b606 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 Jul 2014 09:37:21 +0200 Subject: [PATCH 34/49] rewrote MWScript::Locals::configure to be independent of precompiled script data --- apps/openmw/mwscript/locals.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwscript/locals.cpp b/apps/openmw/mwscript/locals.cpp index 6a8a857d8..a1ee48ae6 100644 --- a/apps/openmw/mwscript/locals.cpp +++ b/apps/openmw/mwscript/locals.cpp @@ -14,12 +14,15 @@ namespace MWScript { void Locals::configure (const ESM::Script& script) { + const Compiler::Locals& locals = + MWBase::Environment::get().getScriptManager()->getLocals (script.mId); + mShorts.clear(); - mShorts.resize (script.mData.mNumShorts, 0); + mShorts.resize (locals.get ('s').size(), 0); mLongs.clear(); - mLongs.resize (script.mData.mNumLongs, 0); + mLongs.resize (locals.get ('l').size(), 0); mFloats.clear(); - mFloats.resize (script.mData.mNumFloats, 0); + mFloats.resize (locals.get ('f').size(), 0); } bool Locals::isEmpty() const From acb728195f84f199bfa5bdd704d79819e6439f60 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 Jul 2014 10:37:34 +0200 Subject: [PATCH 35/49] improved documentation of ESM::Script member variables --- components/esm/loadscpt.hpp | 38 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/components/esm/loadscpt.hpp b/components/esm/loadscpt.hpp index d5200d4c1..38160e7f4 100644 --- a/components/esm/loadscpt.hpp +++ b/components/esm/loadscpt.hpp @@ -23,29 +23,8 @@ public: struct SCHDstruct { - /* Script name. - - NOTE: You should handle the name "Main" (case insensitive) with - care. With tribunal, modders got the ability to add 'start - scripts' to their mods, which is a script that is run at - startup and which runs throughout the game (I think.) - - However, before Tribunal, there was only one startup script, - called "Main". If mods wanted to make their own start scripts, - they had to overwrite Main. This is obviously problem if - multiple mods to this at the same time. - - Although most mods have switched to using Trib-style startup - scripts, some legacy mods might still overwrite Main, and this - can cause problems if several mods do it. I think the best - course of action is to NEVER overwrite main, but instead add - each with a separate unique name and add them to the start - script list. But there might be other problems with this - approach though. - */ - - // These describe the sizes we need to allocate for the script - // data. + /// Data from script-precompling in the editor. + /// \warning Do not use them. OpenCS currently does not precompile scripts. int mNumShorts, mNumLongs, mNumFloats, mScriptDataSize, mStringTableSize; }; // 52 bytes @@ -53,9 +32,16 @@ public: SCHDstruct mData; - std::vector mVarNames; // Variable names - std::vector mScriptData; // Compiled bytecode - std::string mScriptText; // Uncompiled script + /// Variable names generated by script-precompiling in the editor. + /// \warning Do not use this field. OpenCS currently does not precompile scripts. + std::vector mVarNames; + + /// Bytecode generated from script-precompiling in the editor. + /// \warning Do not use this field. OpenCS currently does not precompile scripts. + std::vector mScriptData; + + /// Script source code + std::string mScriptText; void load(ESMReader &esm); void save(ESMWriter &esm) const; From 5e543ac8065cbeaa7625ab838176d3e76ea6d2f4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 Jul 2014 11:53:30 +0200 Subject: [PATCH 36/49] added script doortestwarp to blacklist --- files/openmw.cfg | 3 ++- files/openmw.cfg.local | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/files/openmw.cfg b/files/openmw.cfg index de1f22e50..e105b6304 100644 --- a/files/openmw.cfg +++ b/files/openmw.cfg @@ -3,4 +3,5 @@ data="?mw?Data Files" data-local="?userdata?data" resources=${OPENMW_RESOURCE_FILES} script-blacklist=Museum -script-blacklist=MockChangeScript \ No newline at end of file +script-blacklist=MockChangeScript +script-blacklist=doortestwarp diff --git a/files/openmw.cfg.local b/files/openmw.cfg.local index b2970fb19..9d86174d9 100644 --- a/files/openmw.cfg.local +++ b/files/openmw.cfg.local @@ -5,3 +5,4 @@ data-local="?userdata?data" resources=./resources script-blacklist=Museum script-blacklist=MockChangeScript +script-blacklist=doortestwarp From d0654f3adefc86a82641a7435e4b84682e606600 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 Jul 2014 12:17:15 +0200 Subject: [PATCH 37/49] move starting of startup scripts from engine startup to new game start; also restart all startup scripts on saved game load --- apps/openmw/engine.cpp | 2 -- apps/openmw/mwstate/statemanagerimp.cpp | 5 +++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 6a48789a5..66eae5f5d 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -421,8 +421,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) mOgre->getRoot()->addFrameListener (this); // scripts - mEnvironment.getScriptManager()->getGlobalScripts().addStartup(); - if (mCompileAll) { std::pair result = MWBase::Environment::get().getScriptManager()->compileAll(); diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index a3604cc66..b69e6b908 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -139,6 +139,9 @@ void MWState::StateManager::newGame (bool bypass) else MWBase::Environment::get().getWorld()->setGlobalInt ("chargenstate", -1); + + MWBase::Environment::get().getScriptManager()->getGlobalScripts().addStartup(); + mState = State_Running; } @@ -401,6 +404,8 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl // Use detectWorldSpaceChange=false, otherwise some of the data we just loaded would be cleared again MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition(), false); + MWBase::Environment::get().getScriptManager()->getGlobalScripts().addStartup(); + // Do not trigger erroneous cellChanged events MWBase::Environment::get().getWorld()->markCellAsUnchanged(); } From af54bb96237e17066ed81ce56712fbada9353372 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 Jul 2014 12:23:18 +0200 Subject: [PATCH 38/49] removed some redundancies; some more general cleanup --- apps/openmw/mwstate/statemanagerimp.cpp | 7 ++----- apps/openmw/mwworld/worldimp.cpp | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index b69e6b908..96f14d7e9 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -132,16 +132,13 @@ void MWState::StateManager::newGame (bool bypass) { cleanup(); - MWBase::Environment::get().getWorld()->startNewGame (bypass); - if (!bypass) MWBase::Environment::get().getWindowManager()->setNewGame (true); - else - MWBase::Environment::get().getWorld()->setGlobalInt ("chargenstate", -1); - MWBase::Environment::get().getScriptManager()->getGlobalScripts().addStartup(); + MWBase::Environment::get().getWorld()->startNewGame (bypass); + mState = State_Running; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 386834882..98025b00e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -211,9 +211,9 @@ namespace MWWorld // set new game mark mGlobalVariables["chargenstate"].setInteger (1); mGlobalVariables["pcrace"].setInteger (3); - - MWBase::Environment::get().getScriptManager()->getGlobalScripts().addStartup(); } + else + mGlobalVariables["chargenstate"].setInteger (-1); if (bypass && !mStartCell.empty()) { From 6a745c014fec66622bdda9759c3c6e181067d5e7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 27 Jul 2014 11:51:53 +0200 Subject: [PATCH 39/49] workaround for incorrect argument order for PositionCell instruction --- components/compiler/errorhandler.cpp | 30 +++++++++++++++++++++++----- components/compiler/errorhandler.hpp | 21 +++++++++++++++++++ components/compiler/lineparser.cpp | 27 +++++++++++++++++++++++-- 3 files changed, 71 insertions(+), 7 deletions(-) diff --git a/components/compiler/errorhandler.cpp b/components/compiler/errorhandler.cpp index fe58836cc..bcd30ef2d 100644 --- a/components/compiler/errorhandler.cpp +++ b/components/compiler/errorhandler.cpp @@ -3,11 +3,8 @@ namespace Compiler { - // constructor - - ErrorHandler::ErrorHandler() : mWarnings (0), mErrors (0), mWarningsMode (1) {} - - // destructor + ErrorHandler::ErrorHandler() + : mWarnings (0), mErrors (0), mWarningsMode (1), mDowngradeErrors (false) {} ErrorHandler::~ErrorHandler() {} @@ -49,6 +46,12 @@ namespace Compiler void ErrorHandler::error (const std::string& message, const TokenLoc& loc) { + if (mDowngradeErrors) + { + warning (message, loc); + return; + } + ++mErrors; report (message, loc, ErrorMessage); } @@ -72,4 +75,21 @@ namespace Compiler { mWarningsMode = mode; } + + void ErrorHandler::downgradeErrors (bool downgrade) + { + mDowngradeErrors = downgrade; + } + + + ErrorDowngrade::ErrorDowngrade (ErrorHandler& handler) : mHandler (handler) + { + mHandler.downgradeErrors (true); + } + + ErrorDowngrade::~ErrorDowngrade() + { + mHandler.downgradeErrors (false); + } + } diff --git a/components/compiler/errorhandler.hpp b/components/compiler/errorhandler.hpp index e5922a6be..c92e7bb8d 100644 --- a/components/compiler/errorhandler.hpp +++ b/components/compiler/errorhandler.hpp @@ -17,6 +17,7 @@ namespace Compiler int mWarnings; int mErrors; int mWarningsMode; + bool mDowngradeErrors; protected: @@ -66,6 +67,26 @@ namespace Compiler void setWarningsMode (int mode); ///< // 0 ignore, 1 rate as warning, 2 rate as error + + /// Treat errors as warnings. + void downgradeErrors (bool downgrade); + }; + + class ErrorDowngrade + { + ErrorHandler& mHandler; + + /// not implemented + ErrorDowngrade (const ErrorDowngrade&); + + /// not implemented + ErrorDowngrade& operator= (const ErrorDowngrade&); + + public: + + ErrorDowngrade (ErrorHandler& handler); + + ~ErrorDowngrade(); }; } diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index cdbfaa04a..2226f5845 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -11,6 +11,7 @@ #include "generator.hpp" #include "extensions.hpp" #include "declarationparser.hpp" +#include "exception.hpp" namespace Compiler { @@ -292,9 +293,31 @@ namespace Compiler mExplicit.clear(); } - int optionals = mExprParser.parseArguments (argumentType, scanner, mCode); + int optionals = 0; + + try + { + ErrorDowngrade errorDowngrade (getErrorHandler()); + std::vector code; + optionals = mExprParser.parseArguments (argumentType, scanner, code); + mCode.insert (mCode.begin(), code.begin(), code.end()); + extensions->generateInstructionCode (keyword, mCode, mLiterals, + mExplicit, optionals); + } + catch (const SourceException& exception) + { + // Ignore argument exceptions for positioncell. + /// \todo add option to disable this + if (Misc::StringUtils::lowerCase (loc.mLiteral)=="positioncell") + { + SkipParser skip (getErrorHandler(), getContext()); + scanner.scan (skip); + return false; + } + + throw; + } - extensions->generateInstructionCode (keyword, mCode, mLiterals, mExplicit, optionals); mState = EndState; return true; } From 2abc4e42c8610d97901db3c863c50cabfa15c0a2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 27 Jul 2014 20:49:57 +0200 Subject: [PATCH 40/49] end parsing of line after parsing a declaration --- components/compiler/lineparser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 2226f5845..0a3629912 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -386,7 +386,7 @@ namespace Compiler if (declaration.parseKeyword (keyword, loc, scanner)) scanner.scan (declaration); - return true; + return false; } case Scanner::K_set: mState = SetState; return true; From 17bd094afd9fabc19dc3a86a6a542996805db2c8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 27 Jul 2014 20:55:54 +0200 Subject: [PATCH 41/49] allow a few more stray arguments --- components/compiler/extensions0.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index ef4fe4fbd..3945b73cc 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -59,7 +59,7 @@ namespace Compiler extensions.registerInstruction ("modfight", "l", opcodeModFight, opcodeModFightExplicit); extensions.registerInstruction ("modflee", "l", opcodeModFlee, opcodeModFleeExplicit); extensions.registerInstruction ("modalarm", "l", opcodeModAlarm, opcodeModAlarmExplicit); - extensions.registerInstruction ("toggleai", "", opcodeToggleAI, opcodeToggleAI); + extensions.registerInstruction ("toggleai", "X", opcodeToggleAI, opcodeToggleAI); extensions.registerInstruction ("tai", "", opcodeToggleAI, opcodeToggleAI); extensions.registerInstruction("startcombat", "c", opcodeStartCombat, opcodeStartCombatExplicit); extensions.registerInstruction("stopcombat", "x", opcodeStopCombat, opcodeStopCombatExplicit); @@ -113,12 +113,12 @@ namespace Compiler { void registerExtensions (Extensions& extensions) { - extensions.registerInstruction ("additem", "cl", opcodeAddItem, opcodeAddItemExplicit); + extensions.registerInstruction ("additem", "clxx", opcodeAddItem, opcodeAddItemExplicit); extensions.registerFunction ("getitemcount", 'l', "c", opcodeGetItemCount, opcodeGetItemCountExplicit); extensions.registerInstruction ("removeitem", "cl", opcodeRemoveItem, opcodeRemoveItemExplicit); - extensions.registerInstruction ("equip", "c", opcodeEquip, opcodeEquipExplicit); + extensions.registerInstruction ("equip", "cX", opcodeEquip, opcodeEquipExplicit); extensions.registerFunction ("getarmortype", 'l', "l", opcodeGetArmorType, opcodeGetArmorTypeExplicit); extensions.registerFunction ("hasitemequipped", 'l', "c", opcodeHasItemEquipped, opcodeHasItemEquippedExplicit); extensions.registerFunction ("hassoulgem", 'l', "c", opcodeHasSoulGem, opcodeHasSoulGemExplicit); @@ -163,7 +163,7 @@ namespace Compiler { void registerExtensions (Extensions& extensions) { - extensions.registerInstruction ("journal", "cl", opcodeJournal); + extensions.registerInstruction ("journal", "clxxX", opcodeJournal); extensions.registerInstruction ("setjournalindex", "cl", opcodeSetJournalIndex); extensions.registerFunction ("getjournalindex", 'l', "c", opcodeGetJournalIndex); extensions.registerInstruction ("addtopic", "S" , opcodeAddTopic); @@ -406,7 +406,7 @@ namespace Compiler extensions.registerInstruction ("setpccrimelevel", "f", opcodeSetPCCrimeLevel); extensions.registerInstruction ("modpccrimelevel", "f", opcodeModPCCrimeLevel); - extensions.registerInstruction ("addspell", "cxX", opcodeAddSpell, opcodeAddSpellExplicit); + extensions.registerInstruction ("addspell", "cz", opcodeAddSpell, opcodeAddSpellExplicit); extensions.registerInstruction ("removespell", "c", opcodeRemoveSpell, opcodeRemoveSpellExplicit); extensions.registerInstruction ("removespelleffects", "c", opcodeRemoveSpellEffects, From b4ba18afe7ba0c4a91a24d99d21f6ff9439e896f Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Sun, 27 Jul 2014 23:36:40 +0200 Subject: [PATCH 42/49] Include revision number in the "version" command line option (Closes #1711) --- apps/openmw/main.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index adde408b9..0aa763407 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -184,6 +184,14 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat if (variables.count ("version")) { std::cout << "OpenMW version " << OPENMW_VERSION << std::endl; + + std::string rev = OPENMW_VERSION_COMMITHASH; + std::string tag = OPENMW_VERSION_TAGHASH; + if (!rev.empty() && !tag.empty()) + { + rev = rev.substr(0, 10); + std::cout << "Revision " << rev << std::endl; + } run = false; } From ad50b926f5a667fed85b2ef4a6b44ccad091eeb8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 28 Jul 2014 09:01:44 +0200 Subject: [PATCH 43/49] reducing some stray arguments again --- components/compiler/extensions0.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 3945b73cc..0181fae96 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -59,7 +59,7 @@ namespace Compiler extensions.registerInstruction ("modfight", "l", opcodeModFight, opcodeModFightExplicit); extensions.registerInstruction ("modflee", "l", opcodeModFlee, opcodeModFleeExplicit); extensions.registerInstruction ("modalarm", "l", opcodeModAlarm, opcodeModAlarmExplicit); - extensions.registerInstruction ("toggleai", "X", opcodeToggleAI, opcodeToggleAI); + extensions.registerInstruction ("toggleai", "", opcodeToggleAI, opcodeToggleAI); extensions.registerInstruction ("tai", "", opcodeToggleAI, opcodeToggleAI); extensions.registerInstruction("startcombat", "c", opcodeStartCombat, opcodeStartCombatExplicit); extensions.registerInstruction("stopcombat", "x", opcodeStopCombat, opcodeStopCombatExplicit); @@ -113,7 +113,7 @@ namespace Compiler { void registerExtensions (Extensions& extensions) { - extensions.registerInstruction ("additem", "clxx", opcodeAddItem, opcodeAddItemExplicit); + extensions.registerInstruction ("additem", "cl", opcodeAddItem, opcodeAddItemExplicit); extensions.registerFunction ("getitemcount", 'l', "c", opcodeGetItemCount, opcodeGetItemCountExplicit); extensions.registerInstruction ("removeitem", "cl", opcodeRemoveItem, @@ -163,7 +163,7 @@ namespace Compiler { void registerExtensions (Extensions& extensions) { - extensions.registerInstruction ("journal", "clxxX", opcodeJournal); + extensions.registerInstruction ("journal", "cl", opcodeJournal); extensions.registerInstruction ("setjournalindex", "cl", opcodeSetJournalIndex); extensions.registerFunction ("getjournalindex", 'l', "c", opcodeGetJournalIndex); extensions.registerInstruction ("addtopic", "S" , opcodeAddTopic); From b56cb7e5eec16a5b59102df953db9ee7e86b2a16 Mon Sep 17 00:00:00 2001 From: bogglez Date: Mon, 28 Jul 2014 17:46:41 +0200 Subject: [PATCH 44/49] Remove defunct option for building without FFmpeg - Added REQUIRED to find_package(FFmpeg) - Removed USE_FFMPEG option from CMakeLists.txt - Always use FFmpeg for sound input - Removed SOUND_DEFINE from CMakeLists.txt - Removed #else branch from videoplayer.cpp with dummy VideoState code (FFmpeg is now guaranteed to exist and the code was incomplete) - Remove #ifdef OPENMW_USE_FFMPEG in ffmpeg_decoder.cpp, it is guaranteed to be used - Remove #ifdef OPENMW_USE_FFMPEG from soundmanagerimp.cpp, it is guaranteed to be used --- CMakeLists.txt | 33 +++---------------------- apps/openmw/CMakeLists.txt | 1 - apps/openmw/mwrender/videoplayer.cpp | 23 ----------------- apps/openmw/mwsound/ffmpeg_decoder.cpp | 5 ---- apps/openmw/mwsound/soundmanagerimp.cpp | 5 ---- 5 files changed, 4 insertions(+), 63 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee3850ddb..2f5e21c61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,9 +74,6 @@ option(BUILD_OPENCS "build OpenMW Construction Set" ON) option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF) option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest ang GMock frameworks" OFF) -# Sound source selection -option(USE_FFMPEG "use ffmpeg for sound" ON) - # OS X deployment option(OPENMW_OSX_DEPLOYMENT OFF) @@ -138,32 +135,10 @@ set(OPENMW_LIBS ${OENGINE_ALL}) set(OPENMW_LIBS_HEADER) # Sound setup -set(GOT_SOUND_INPUT 0) -set(SOUND_INPUT_INCLUDES "") -set(SOUND_INPUT_LIBRARY "") -set(SOUND_DEFINE "") -if (USE_FFMPEG) - set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE) - find_package(FFmpeg) - if (FFMPEG_FOUND) - set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${FFMPEG_INCLUDE_DIRS}) - set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES}) - set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_FFMPEG) - set(GOT_SOUND_INPUT 1) - endif (FFMPEG_FOUND) -endif (USE_FFMPEG) - -if (NOT GOT_SOUND_INPUT) - message(WARNING "--------------------") - message(WARNING "Failed to find any sound input packages") - message(WARNING "--------------------") -endif (NOT GOT_SOUND_INPUT) - -if (NOT FFMPEG_FOUND) - message(WARNING "--------------------") - message(WARNING "FFmpeg not found, video playback will be disabled") - message(WARNING "--------------------") -endif (NOT FFMPEG_FOUND) +set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE) +find_package(FFmpeg REQUIRED) +set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIRS}) +set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES}) # TinyXML option(USE_SYSTEM_TINYXML "Use system TinyXML library instead of internal." OFF) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 0dda1131b..c5ff2a83c 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -99,7 +99,6 @@ add_executable(openmw # Sound stuff - here so CMake doesn't stupidly recompile EVERYTHING # when we change the backend. include_directories(${SOUND_INPUT_INCLUDES} ${BULLET_INCLUDE_DIRS}) -add_definitions(${SOUND_DEFINE}) target_link_libraries(openmw ${OGRE_LIBRARIES} diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index 409e27388..2d05f2770 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -26,8 +26,6 @@ typedef SSIZE_T ssize_t; namespace MWRender { -#ifdef OPENMW_USE_FFMPEG - extern "C" { #include @@ -1073,27 +1071,6 @@ void VideoState::deinit() } } -#else // defined OPENMW_USE_FFMPEG - -class VideoState -{ -public: - VideoState() { } - - void init(const std::string& resourceName) - { - throw std::runtime_error("FFmpeg not supported, cannot play \""+resourceName+"\""); - } - void deinit() { } - - void close() { } - - bool update() - { return false; } -}; - -#endif // defined OPENMW_USE_FFMPEG - VideoPlayer::VideoPlayer() : mState(NULL) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index 10a782b96..982d0c5ff 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -1,6 +1,3 @@ -#ifdef OPENMW_USE_FFMPEG - - #include "ffmpeg_decoder.hpp" // auto_ptr @@ -375,5 +372,3 @@ FFmpeg_Decoder::~FFmpeg_Decoder() } } - -#endif diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index ba7b4f3ba..453a19905 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -17,15 +17,10 @@ #include "openal_output.hpp" #define SOUND_OUT "OpenAL" -/* Set up the sound manager to use FFMPEG for input. - * The OPENMW_USE_x macros are set in CMakeLists.txt. -*/ -#ifdef OPENMW_USE_FFMPEG #include "ffmpeg_decoder.hpp" #ifndef SOUND_IN #define SOUND_IN "FFmpeg" #endif -#endif namespace MWSound From 0032426817376061cb6d68624e900933c6e734c9 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 28 Jul 2014 20:39:37 +0200 Subject: [PATCH 45/49] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index 5c757f957..2c8d86f49 100644 --- a/credits.txt +++ b/credits.txt @@ -72,6 +72,7 @@ Sandy Carter (bwrsandman) Sebastian Wick (swick) Sergey Shambir sir_herrbatka +Stefan Galowicz (bogglez) Sylvain Thesnieres (Garvek) Thomas Luppi (Digmaster) Tom Mason (wheybags) From c006393178a359a95a3f089e8e2b734ee6020fff Mon Sep 17 00:00:00 2001 From: bogglez Date: Mon, 28 Jul 2014 21:52:34 +0200 Subject: [PATCH 46/49] Fix http://bugs.openmw.org/issues/768 Changes application_name in configuration manager to OpenMW instead of openmw, if on windows. This shouldn't break anything since Windows uses case-insensitive filesystems. Strictly speaking the installation directory must be OpenMW now though (not sure whether this is the case) --- components/files/configurationmanager.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index 58d75d1fd..942f47d4e 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -16,13 +16,19 @@ namespace Files static const char* const openmwCfgFile = "openmw.cfg"; +#if defined(_WIN32) || defined(__WINDOWS__) +static const char* const applicationName = "OpenMW"; +#else +static const char* const applicationName = "openmw"; +#endif + const char* const mwToken = "?mw?"; const char* const localToken = "?local?"; const char* const userDataToken = "?userdata?"; const char* const globalToken = "?global?"; ConfigurationManager::ConfigurationManager() - : mFixedPath("openmw") + : mFixedPath(applicationName) { setupTokensMapping(); From 20efeea5d9ed9590c3c8a0f703a7dbf37e5dc6df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=9Aciubid=C5=82o?= Date: Mon, 28 Jul 2014 20:39:13 +0100 Subject: [PATCH 47/49] AI tell their greatings even when player is moving (like morrowind). Greating reset distance was greatly inflated comparing with morrowind. --- apps/openmw/mwmechanics/aiwander.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index b97554e2a..f1a815d30 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -454,9 +454,7 @@ namespace MWMechanics if (!mSaidGreeting) { // TODO: check if actor is aware / has line of sight - if (playerDistSqr <= helloDistance*helloDistance - // Only play a greeting if the player is not moving - && Ogre::Vector3(player.getClass().getMovementSettings(player).mPosition).squaredLength() == 0) + if (playerDistSqr <= helloDistance*helloDistance) { mSaidGreeting = true; MWBase::Environment::get().getDialogueManager()->say(actor, "hello"); @@ -467,7 +465,7 @@ namespace MWMechanics static float fGreetDistanceReset = MWBase::Environment::get().getWorld()->getStore() .get().find("fGreetDistanceReset")->getFloat(); - if (playerDistSqr >= fGreetDistanceReset*fGreetDistanceReset * iGreetDistanceMultiplier*iGreetDistanceMultiplier) + if (playerDistSqr >= fGreetDistanceReset*fGreetDistanceReset) mSaidGreeting = false; } From d47bfbe69c9c4ac81d4140445c0451a3dd96eec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=9Aciubid=C5=82o?= Date: Mon, 28 Jul 2014 23:16:24 +0100 Subject: [PATCH 48/49] Implement AI greeting states. Greeting consist of 3 phases: - none - default one, greeting state can only change to "in progress" when near enough and some time passes - in progress - NPC says his greating and rotates toward player, state can only change to "done" after some time - done - rotation is stoped, after idling can go away from player, state can only change to "none" when player and NPC are faraway --- apps/openmw/mwmechanics/aiwander.cpp | 37 +++++++++++++++------------- apps/openmw/mwmechanics/aiwander.hpp | 7 +++++- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index f1a815d30..519cc8a61 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -43,7 +43,7 @@ namespace MWMechanics mReaction = 0; mRotate = false; mTargetAngle = 0; - mSaidGreeting = false; + mSaidGreeting = Greet_None; mHasReturnPosition = false; mReturnPosition = Ogre::Vector3(0,0,0); @@ -407,7 +407,7 @@ namespace MWMechanics } // Allow interrupting a walking actor to trigger a greeting - if(mIdleNow || (mWalking && !mObstacleCheck.isNormalState() && mDistance)) + if(mIdleNow || mWalking) { // Play a random voice greeting if the player gets too close int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified(); @@ -421,8 +421,18 @@ namespace MWMechanics Ogre::Vector3 playerPos(player.getRefData().getPosition().pos); Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos); float playerDistSqr = playerPos.squaredDistance(actorPos); - - if(playerDistSqr <= helloDistance*helloDistance) + + if (mSaidGreeting == Greet_None) + { + // TODO: check if actor is aware / has line of sight + if (playerDistSqr <= helloDistance*helloDistance) + { + mSaidGreeting = Greet_InProgress; + MWBase::Environment::get().getDialogueManager()->say(actor, "hello"); + } + } + + if(mSaidGreeting == Greet_InProgress) { if(mWalking) { @@ -449,29 +459,22 @@ namespace MWMechanics mRotate = true; } } + + mSaidGreeting = Greet_Done; } - - if (!mSaidGreeting) - { - // TODO: check if actor is aware / has line of sight - if (playerDistSqr <= helloDistance*helloDistance) - { - mSaidGreeting = true; - MWBase::Environment::get().getDialogueManager()->say(actor, "hello"); - } - } - else + + if (mSaidGreeting == MWMechanics::AiWander::Greet_Done) { static float fGreetDistanceReset = MWBase::Environment::get().getWorld()->getStore() .get().find("fGreetDistanceReset")->getFloat(); if (playerDistSqr >= fGreetDistanceReset*fGreetDistanceReset) - mSaidGreeting = false; + mSaidGreeting = Greet_None; } // Check if idle animation finished // FIXME: don't stay forever - if(!checkIdle(actor, mPlayedIdle) && playerDistSqr > helloDistance*helloDistance) + if(!checkIdle(actor, mPlayedIdle) && (playerDistSqr > helloDistance*helloDistance || mSaidGreeting == MWMechanics::AiWander::Greet_Done)) { mPlayedIdle = 0; mIdleNow = false; diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 7abd19e27..fdfd6f42e 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -62,7 +62,12 @@ namespace MWMechanics std::vector mIdle; bool mRepeat; - bool mSaidGreeting; + enum GreetingState { + Greet_None, + Greet_InProgress, + Greet_Done + }; + GreetingState mSaidGreeting; bool mHasReturnPosition; // NOTE: Could be removed if mReturnPosition was initialized to actor position, // if we had the actor in the AiWander constructor... From bd3729a6cbbf2067b6c1f46a37c749ddc8f18daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=9Aciubid=C5=82o?= Date: Mon, 28 Jul 2014 23:41:37 +0100 Subject: [PATCH 49/49] Add grace periods for player greeting. Add delay for NPC greating. NPC ignores greeted player after some time. Fixes bug 1503. --- apps/openmw/mwmechanics/aiwander.cpp | 23 ++++++++++++++++++----- apps/openmw/mwmechanics/aiwander.hpp | 1 + 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 519cc8a61..27dad88cd 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -22,6 +22,9 @@ namespace MWMechanics { static const int COUNT_BEFORE_RESET = 200; // TODO: maybe no longer needed static const float DOOR_CHECK_INTERVAL = 1.5f; + static const float REACTION_INTERVAL = 0.25f; + static const int GREETING_SHOULD_START = 4; //how many reaction intervals should pass before NPC can greet player + static const int GREETING_SHOULD_END = 10; AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector& idle, bool repeat): mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat) @@ -44,6 +47,7 @@ namespace MWMechanics mRotate = false; mTargetAngle = 0; mSaidGreeting = Greet_None; + greetingTimer = 0; mHasReturnPosition = false; mReturnPosition = Ogre::Vector3(0,0,0); @@ -221,14 +225,14 @@ namespace MWMechanics } mReaction += duration; - if(mReaction < 0.25f) // FIXME: hard coded constant + if(mReaction < REACTION_INTERVAL) { return false; } else mReaction = 0; - // NOTE: everything below get updated every 0.25 seconds + // NOTE: everything below get updated every REACTION_INTERVAL seconds MWBase::World *world = MWBase::Environment::get().getWorld(); if(mDuration) @@ -424,16 +428,22 @@ namespace MWMechanics if (mSaidGreeting == Greet_None) { - // TODO: check if actor is aware / has line of sight if (playerDistSqr <= helloDistance*helloDistance) + greetingTimer++; + + // TODO: check if actor is aware / has line of sight + if (greetingTimer >= GREETING_SHOULD_START) { mSaidGreeting = Greet_InProgress; MWBase::Environment::get().getDialogueManager()->say(actor, "hello"); + greetingTimer = 0; } } if(mSaidGreeting == Greet_InProgress) { + greetingTimer++; + if(mWalking) { stopWalking(actor); @@ -460,7 +470,11 @@ namespace MWMechanics } } - mSaidGreeting = Greet_Done; + if (greetingTimer >= GREETING_SHOULD_END) + { + mSaidGreeting = Greet_Done; + greetingTimer = 0; + } } if (mSaidGreeting == MWMechanics::AiWander::Greet_Done) @@ -473,7 +487,6 @@ namespace MWMechanics } // Check if idle animation finished - // FIXME: don't stay forever if(!checkIdle(actor, mPlayedIdle) && (playerDistSqr > helloDistance*helloDistance || mSaidGreeting == MWMechanics::AiWander::Greet_Done)) { mPlayedIdle = 0; diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index fdfd6f42e..9b579b24a 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -68,6 +68,7 @@ namespace MWMechanics Greet_Done }; GreetingState mSaidGreeting; + int greetingTimer; bool mHasReturnPosition; // NOTE: Could be removed if mReturnPosition was initialized to actor position, // if we had the actor in the AiWander constructor...