From 8837046d9c47f765cf404fd1eb92d1836acad340 Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Sun, 28 Jan 2018 22:49:49 -0600 Subject: [PATCH 01/16] Adding panel for advanced settings.cfg options --- apps/launcher/CMakeLists.txt | 4 + apps/launcher/advancedpage.cpp | 89 ++++++ apps/launcher/advancedpage.hpp | 32 ++ apps/launcher/maindialog.cpp | 17 +- apps/launcher/maindialog.hpp | 2 + .../icons/tango/48x48/emblem-system.png | Bin 0 -> 3423 bytes files/launcher/launcher.qrc | 3 +- files/ui/advancedpage.ui | 286 ++++++++++++++++++ files/ui/mainwindow.ui | 4 +- 9 files changed, 430 insertions(+), 7 deletions(-) create mode 100644 apps/launcher/advancedpage.cpp create mode 100644 apps/launcher/advancedpage.hpp create mode 100644 files/launcher/icons/tango/48x48/emblem-system.png create mode 100644 files/ui/advancedpage.ui diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index aac076404..aec8c2533 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -6,6 +6,7 @@ set(LAUNCHER playpage.cpp textslotmsgbox.cpp settingspage.cpp + advancedpage.cpp utils/profilescombobox.cpp utils/textinputdialog.cpp @@ -21,6 +22,7 @@ set(LAUNCHER_HEADER playpage.hpp textslotmsgbox.hpp settingspage.hpp + advancedpage.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp @@ -35,6 +37,7 @@ set(LAUNCHER_HEADER_MOC playpage.hpp textslotmsgbox.hpp settingspage.hpp + advancedpage.hpp utils/textinputdialog.hpp utils/profilescombobox.hpp @@ -49,6 +52,7 @@ set(LAUNCHER_UI ${CMAKE_SOURCE_DIR}/files/ui/playpage.ui ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui ${CMAKE_SOURCE_DIR}/files/ui/settingspage.ui + ${CMAKE_SOURCE_DIR}/files/ui/advancedpage.ui ) source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER}) diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp new file mode 100644 index 000000000..da142ff26 --- /dev/null +++ b/apps/launcher/advancedpage.cpp @@ -0,0 +1,89 @@ +#include "advancedpage.hpp" + +#include + +Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg, Settings::Manager &engineSettings, QWidget *parent) + : QWidget(parent) + , mCfgMgr(cfg) + , mEngineSettings(engineSettings) +{ + setObjectName ("AdvancedPage"); + setupUi(this); + + loadSettings(); +} + +bool Launcher::AdvancedPage::loadSettings() +{ + // Game Settings + loadSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game"); + loadSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game"); + loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game"); + loadSettingBool(showEffectDurationCheckBox, "show effect duration", "Game"); + loadSettingBool(showMeleeInfoCheckBox, "show enchant chance", "Game"); + loadSettingBool(showMeleeInfoCheckBox, "show melee info", "Game"); + loadSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game"); + + // Expected values are (0, 1, 2, 3) + int showOwnedIndex = mEngineSettings.getInt("show owned", "Game"); + // Match the index with the option. Will default to 0 if invalid. + if (showOwnedIndex >= 0 && showOwnedIndex <= 3) + showOwnedComboBox->setCurrentIndex(showOwnedIndex); + + // Input Settings + loadSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input"); + loadSettingBool(grabCursorCheckBox, "grab cursor", "Input"); + loadSettingBool(toggleSneakCheckBox, "toggle sneak", "Input"); + + // Other Settings + loadSettingBool(timePlayedCheckbox, "timeplayed", "Saves"); + + QString screenshotFormatString = QString::fromStdString(mEngineSettings.getString("screenshot format", "General")).toUpper(); + if (screenshotFormatComboBox->findText(screenshotFormatString) == -1) + screenshotFormatComboBox->addItem(screenshotFormatString); + screenshotFormatComboBox->setCurrentText(screenshotFormatString); + + return true; +} + +void Launcher::AdvancedPage::saveSettings() +{ + // Ensure we only set the new settings if they changed. This is to avoid cluttering the + // user settings file (which by definition should only contain settings the user has touched) + + // Game Settings + saveSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game"); + saveSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game"); + saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game"); + saveSettingBool(showEffectDurationCheckBox, "show effect duration", "Game"); + saveSettingBool(showMeleeInfoCheckBox, "show enchant chance", "Game"); + saveSettingBool(showMeleeInfoCheckBox, "show melee info", "Game"); + saveSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game"); + + int showOwnedCurrentIndex = showOwnedComboBox->currentIndex(); + if (showOwnedCurrentIndex != mEngineSettings.getInt("show owned", "Game")) + mEngineSettings.setInt("show owned", "Game", showOwnedCurrentIndex); + + // Input Settings + saveSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input"); + saveSettingBool(grabCursorCheckBox, "grab cursor", "Input"); + saveSettingBool(toggleSneakCheckBox, "toggle sneak", "Input"); + + // Other Settings + saveSettingBool(timePlayedCheckbox, "timeplayed", "Saves"); + + std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString(); + if (screenshotFormatString != mEngineSettings.getString("screenshot format", "General")) + mEngineSettings.setString("screenshot format", "General", screenshotFormatString); +} + +void Launcher::AdvancedPage::loadSettingBool(QCheckBox *checkbox, const std::string &setting, const std::string &group) { + if (mEngineSettings.getBool(setting, group)) + checkbox->setCheckState(Qt::Checked); +} + +void Launcher::AdvancedPage::saveSettingBool(QCheckBox *checkbox, const std::string &setting, const std::string &group) { + bool cValue = checkbox->checkState(); + if (cValue != mEngineSettings.getBool(setting, group)) + mEngineSettings.setBool(setting, group, cValue); +} \ No newline at end of file diff --git a/apps/launcher/advancedpage.hpp b/apps/launcher/advancedpage.hpp new file mode 100644 index 000000000..a8361c98e --- /dev/null +++ b/apps/launcher/advancedpage.hpp @@ -0,0 +1,32 @@ +#ifndef ADVANCEDPAGE_H +#define ADVANCEDPAGE_H + +#include + +#include "ui_advancedpage.h" + +#include + +namespace Files { struct ConfigurationManager; } + +namespace Launcher +{ + class AdvancedPage : public QWidget, private Ui::AdvancedPage + { + Q_OBJECT + + public: + AdvancedPage(Files::ConfigurationManager &cfg, Settings::Manager &engineSettings, QWidget *parent = 0); + + bool loadSettings(); + void saveSettings(); + + private: + Files::ConfigurationManager &mCfgMgr; + Settings::Manager &mEngineSettings; + + void loadSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group); + void saveSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group); + }; +} +#endif diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 31da90d2f..1a210ccc5 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -2,9 +2,7 @@ #include -#include #include -#include #include #include #include @@ -12,8 +10,6 @@ #include #include #include -#include -#include #include @@ -21,6 +17,7 @@ #include "graphicspage.hpp" #include "datafilespage.hpp" #include "settingspage.hpp" +#include "advancedpage.hpp" using namespace Process; @@ -104,6 +101,12 @@ void Launcher::MainDialog::createIcons() settingsButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom); settingsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + QListWidgetItem *advancedButton = new QListWidgetItem(iconWidget); + advancedButton->setIcon(QIcon::fromTheme("emblem-system")); + advancedButton->setText(tr("Advanced")); + advancedButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom); + advancedButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + connect(iconWidget, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), this, SLOT(changePage(QListWidgetItem*,QListWidgetItem*))); @@ -116,6 +119,7 @@ void Launcher::MainDialog::createPages() mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this); mGraphicsPage = new GraphicsPage(mCfgMgr, mEngineSettings, this); mSettingsPage = new SettingsPage(mCfgMgr, mGameSettings, mLauncherSettings, this); + mAdvancedPage = new AdvancedPage(mCfgMgr, mEngineSettings, this); // Set the combobox of the play page to imitate the combobox on the datafilespage mPlayPage->setProfilesModel(mDataFilesPage->profilesModel()); @@ -126,6 +130,7 @@ void Launcher::MainDialog::createPages() pagesWidget->addWidget(mDataFilesPage); pagesWidget->addWidget(mGraphicsPage); pagesWidget->addWidget(mSettingsPage); + pagesWidget->addWidget(mAdvancedPage); // Select the first page iconWidget->setCurrentItem(iconWidget->item(0), QItemSelectionModel::Select); @@ -245,6 +250,9 @@ bool Launcher::MainDialog::reloadSettings() if (!mGraphicsPage->loadSettings()) return false; + if (!mAdvancedPage->loadSettings()) + return false; + return true; } @@ -483,6 +491,7 @@ bool Launcher::MainDialog::writeSettings() mDataFilesPage->saveSettings(); mGraphicsPage->saveSettings(); mSettingsPage->saveSettings(); + mAdvancedPage->saveSettings(); QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); QDir dir(userPath); diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index 8d0d61b8f..6d3871b7c 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -30,6 +30,7 @@ namespace Launcher class DataFilesPage; class UnshieldThread; class SettingsPage; + class AdvancedPage; enum FirstRunDialogResult { @@ -88,6 +89,7 @@ namespace Launcher GraphicsPage *mGraphicsPage; DataFilesPage *mDataFilesPage; SettingsPage *mSettingsPage; + AdvancedPage *mAdvancedPage; Process::ProcessInvoker *mGameInvoker; Process::ProcessInvoker *mWizardInvoker; diff --git a/files/launcher/icons/tango/48x48/emblem-system.png b/files/launcher/icons/tango/48x48/emblem-system.png new file mode 100644 index 0000000000000000000000000000000000000000..9a765247cac594055fb1b80c2c164680070cc9f6 GIT binary patch literal 3423 zcmV-l4WROgP)b)L-ur1ltjd#20I+m9nxVfI<2&)NPDZmA#Q`vVej4t$G~A<0IKF!tb=FynELr)RpWyY55WLwh`9n}jRrQJ34(Rlon!Pd)Y2*aZI%t*NQ$SB~TS z#I|jX5CTGoNhzJ+oHNE)^P`+gew2f`jS%v}&Ye58a5xM}l0XPi`}_OV&d$y)03N9T z=}`^_0L{(K8i3kJB!X-k8-{_3pjlE@Lx1GHZGpSNB=AujZy%RWf`(8Ly{z@stQfhIAiRInI2}0NwHY$ z0Ap;)T)5^WfHC%CMN$5X5OO^hi~Vq>&r(V^M5EC%LI`A82Bj3TEQ1h&>gs9^;Jc-s zZE9*-q-om!)YjG>Q&qK#F}7(owpm|iV`Jl6p-|{heSLiy=NuO5yK z>n+_KhcWg&Ns{&wLVotrOD_d0Dk|VO4k)FdltR-qeER99W=~H~+_vps131&r(D1*W zdG^b){LkCAZ7W-~Y84$G9>$q7XC@{lCSGBT{r(#Xh{a+*DK9Vom+jlPmzkysN-0!T zMR#|1?$)ha2_eMGLWmkl=`p|G|M-d(EBuQWFQ%21l`u^cgb+xQlz)y=iqX+g^!4?b z*REaTLWuu1P4lRtC)(6ty(-sD~{v9w(Tin+`W4jXV0F!UsF>v@AcPTw;tvVkfx@li%&lJ z;kzH%>?ZB2_aJeT~8N! z-gU<4=qNfmIwma3+6zFGVx%((0D$)P_CG%N+;bZ#rF9DyERemKWj1enz3zqfu9d={ z2_dj;8>dd4%9y74Dr2mBCcZiC1D0jI*45QTIp@$cZB}m=!n>X=^mMVGDW$k^;|46t zx^n2yq4Tq`%}D?uUfe0bK{ zY1R;GZf@2r%WB=RV@Jg2^G(S_h46}^K+`m&(`j74e%2<%)Ud&K=XXZMmYN zLQ+)~ob!?)WZO0rMSy9L@`9Y;61wO6gNVi20#V$gHlecB0X! zFB*+1b#-;%oKJ&ychy`jhZ84GjG3l6pD~u1?X5D#mX(#2T|aQ(K$))V`HjqLLI}8P z&bDogkB=jjN+FR*@ZsU%Tr!#LY-niMCc9n%uxsDGeR41ugd|Cddk}FqAQ#+Q4!HOG z`uc3n`LE{!KRMs6BS(&WIy^l5d?*w`Hk+LS?}m|k-`yWVp%B91usnbMe7UWyZ2|Bg zjYbqjG0V%#VOdt*BLMQAE>;e>HOt+*cMZpJF3knrZI)%V4i6980KhrVn_F6V&9W>Q zh5=pIkxVAtDxeB@aHua=Rn>7pOU1bh?#&oN2pERp02q510RYAf!{9;)>aB$eL#gn- z<2Y_ql;;J=vTWG4ozEujV)eq$wEdTtms0?>4?|A~Sr7;WRPP%v6yVlcg$cy6EC8_c z0yyWo<2b(0KKqQ<)YQmTRaJ;YBA}EOEyBDaIOkZrc(MQb_3OIW9%cN2%ZWx9iKtJ#xjgnX__I*OgIz>^Q6+*1zoIe(g zMvdjmm#dpMZ`RyN3Plh?pePDXoH&u;oUeNK-FNTI1|N&XwpCYGpWU}_pTEDqzi8MH zLJ$lF(bCdl%d&jYw(ZY^5I2Mnp9AP+jE#E*Ol!@}%~~RnSS`!)r2_{J_*GRc`X+=B z&@>HSe)*-{($dmvn&w8vSi01>jIo8XEO+nSySGx3BqS1vqA~CD`H)VharNre%MA?; zn@f#XvY310jW=?Pu`XGb|Ipvx4*=5&FV_siz_Mk_=*Ep3mnn+UefaR;7Bofmyj+=!PML|3s&j}%ZSBeps!&i&hZ1&W(YuC0dU%oszQ!SrPr?Fwf z2CcTXcIo-^=Pw;Oa^wrn`R|1gUr|aI5<;Dk@-E*0d0ECr+hOsI06c`}glJyMO=wn$gkGHMv}l z`+Pn*8jT_l2q2kEVqjok+V1OJ#Gz0KgM)((fJ=lpwL?V)=X~<+U7#SJC#Kgpm@RU+iR8-*V)vE^Q{O{V^ z+rOBJZ%zjqA;iDmyLV3+8ym}~)xzqraOc!@9f?E&qobp^fB!yoUC;0GrEGF8SeAul z%a*BL!l5X%bK!)OTiQ?2}<4bekCJG62`~Jv2^KDITDFH z6N|-u{;dQwHa5QE_xty3-n`kD%jKqd{b4|h-E#{yuK*zgbX~_Y&phL&l>QTA>^t8` zKvPrG6OttT>#kk90F_k8W$`CSpFX+oA|tY5$0M=3pX`t<3d>$Ri+ z#+Xb9`Oo_L`d}~^%!iIELen%@mIa^B2U(Vju7y(YLI@~|f=DESnwlEiyLZpYX0xcS zu7;|rc@gP!8VeULl&Y$#mi6}b{-PM?OlkDbg%B$jEm|abvj!mqnx^5#jT`)vPd-6q zWu^JlQ&0J8YHE2lqQE`#y6N%p#~+7jn&|KE=UrW0*@1z9 z+qZAu{@Jl($BrwC@*BV3zjkP7XkJ}ioicf_LVJ6=VHn09#@HvtIA=Z7H#IdKk3=G` zz4+pb{=vaP=i>L{;^}nemm&^8Vm;2J$v?SUAS=JU#Y6PK~WUtg%@5>Na-vg??N+t$|B0RRfV4neO`0F*KIhwa<9`;y6I zezAu_A?Uh}%a<=-K6>=%+b;0r)$)k2_U+rZWcBLRClZN7?D+BH=O=$}0dNW-ORa%C zJOK6R(WAe5_0?Cew6wJJrBW#gfHo<>YqERgoR3UQOe|CsC7$z-4? zNG%-CCZA=Y6@70Ab`PZ3;5m4Bq z0s(~!tyJh03Mdrf!q2%q(*Ik)1Mt}dxc05v{{b)@Ww8q+=<@&o002ovPDHLkV1mVP BtH=NV literal 0 HcmV?d00001 diff --git a/files/launcher/launcher.qrc b/files/launcher/launcher.qrc index 4f55fccd5..ddcc26e59 100644 --- a/files/launcher/launcher.qrc +++ b/files/launcher/launcher.qrc @@ -9,8 +9,9 @@ icons/tango/index.theme - icons/tango/48x48/video-display.png + icons/tango/48x48/emblem-system.png icons/tango/48x48/preferences-system.png + icons/tango/48x48/video-display.png icons/tango/16x16/document-new.png icons/tango/16x16/edit-copy.png icons/tango/16x16/edit-delete.png diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui new file mode 100644 index 000000000..426cce0f8 --- /dev/null +++ b/files/ui/advancedpage.ui @@ -0,0 +1,286 @@ + + + AdvancedPage + + + + 0 + 0 + 434 + 373 + + + + + + + <html><head/><body><p>These settings are not available in the game. <span style=" font-weight:600;">Use at your own risk!</span></p></body></html> + + + + + + + true + + + + + 0 + 0 + 393 + 437 + + + + + + + Game + + + + + + <html><head/><body><p>If this setting is true, the player is allowed to loot actors (e.g. summoned creatures) during death animation, if they are not in combat. However disposing corpses during death animation is not recommended - death counter may not be incremented, and this behaviour can break quests. This is how original Morrowind behaves.</p><p>If this setting is false, player has to wait until end of death animation in all cases. This case is more safe, but makes using of summoned creatures exploit (looting summoned Dremoras and Golden Saints for expensive weapons) a lot harder.</p></body></html> + + + Can loot during death animation + + + + + + + <html><head/><body><p>Makes player followers and escorters start combat with enemies who have started combat with them or the player. Otherwise they wait for the enemies or the player to do an attack first.</p></body></html> + + + Followers attack on sight + + + + + + + <html><head/><body><p>Prevents merchants from equipping items that are sold to them.</p></body></html> + + + Prevent merchant equipping + + + + + + + <html><head/><body><p>Show the remaining duration of magic effects and lights if this setting is true. The remaining duration is displayed in the tooltip by hovering over the magical effect. </p><p>The default value is false.</p></body></html> + + + Show effect duration + + + + + + + <html><head/><body><p>Whether or not the chance of success will be displayed in the enchanting menu.</p><p>The default value is false.</p></body></html> + + + Show enchant chance + + + + + + + <html><head/><body><p>If this setting is true, melee weapons reach and speed will be showed on item tooltip.</p><p>The default value is false.</p></body></html> + + + Show melee info + + + + + + + <html><head/><body><p>If this setting is true, damage bonus of arrows and bolts will be showed on item tooltip.</p><p>The default value is false.</p></body></html> + + + Show projectile damage + + + + + + + <html><head/><body><p>Enable visual clues for items owned by NPCs when the crosshair is on the object.</p><p>The default value is Off.</p></body></html> + + + + -1 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Show owned: + + + + + + + + Off + + + + + Tool Tip Only + + + + + Crosshair Only + + + + + Tooltip and Crosshair + + + + + + + + + + + + + + Input + + + + + + <html><head/><body><p>Allow zooming in and out using the middle mouse wheel in third person view. This feature may not work correctly if the mouse wheel is bound to other actions, and may be triggered accidentally in some cases, so is disabled by default.</p></body></html> + + + Allow third person zoom + + + + + + + <html><head/><body><p>OpenMW will capture control of the cursor if this setting is true.</p><p>In “look mode”, OpenMW will center the cursor regardless of the value of this setting (since the cursor/crosshair is always centered in the OpenMW window). However, in GUI mode, this setting determines the behavior when the cursor is moved outside the OpenMW window. If true, the cursor movement stops at the edge of the window preventing access to other applications. If false, the cursor is allowed to move freely on the desktop.</p><p>This setting does not apply to the screen where escape has been pressed, where the cursor is never captured. Regardless of this setting “Alt-Tab” or some other operating system dependent key sequence can be used to allow the operating system to regain control of the mouse cursor. This setting interacts with the minimize on focus loss setting by affecting what counts as a focus loss. Specifically on a two-screen configuration it may be more convenient to access the second screen with setting disabled.</p><p>Note for developers: it’s desirable to have this setting disabled when running the game in a debugger, to prevent the mouse cursor from becoming unusable when the game pauses on a breakpoint.</p></body></html> + + + Grab cursor + + + + + + + <html><head/><body><p>This setting causes the behavior of the sneak key (bound to Ctrl by default) to toggle sneaking on and off rather than requiring the key to be held down while sneaking. Players that spend significant time sneaking may find the character easier to control with this option enabled. </p></body></html> + + + Toggle sneak + + + + + + + + + + Other + + + + + + <html><head/><body><p>This setting determines whether the amount of the time the player has spent playing will be displayed for each saved game in the Load menu.</p></body></html> + + + Add "Time Played" to saves + + + + + + + <html><head/><body><p>Specify the format for screen shots taken by pressing the screen shot key (bound to F12 by default). This setting should be the file extension commonly associated with the desired format. The formats supported will be determined at compilation, but “jpg”, “png”, and “tga” should be allowed.</p></body></html> + + + + -1 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Screenshot Format + + + + + + + + JPG + + + + + PNG + + + + + TGA + + + + + + + + + + + + + + + + + + + diff --git a/files/ui/mainwindow.ui b/files/ui/mainwindow.ui index 45578ef9e..13e8593e0 100644 --- a/files/ui/mainwindow.ui +++ b/files/ui/mainwindow.ui @@ -6,13 +6,13 @@ 0 0 - 635 + 720 565 - 635 + 720 565 From 04f79c34a2d68ffd1d81cc1b016757cf7c15f060 Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Sun, 28 Jan 2018 23:31:40 -0600 Subject: [PATCH 02/16] Fixing typo "Tooltip" -> "Tool Tip" --- files/ui/advancedpage.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index 426cce0f8..39bb58758 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -156,7 +156,7 @@ - Tooltip and Crosshair + Tool Tip and Crosshair From 8b178447818a585454234791f059ec7d63f2f3ee Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Mon, 29 Jan 2018 21:14:31 -0600 Subject: [PATCH 03/16] Replacing Qt5-only method with Qt4-compatible code --- apps/launcher/advancedpage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index da142ff26..779556df7 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -41,7 +41,7 @@ bool Launcher::AdvancedPage::loadSettings() QString screenshotFormatString = QString::fromStdString(mEngineSettings.getString("screenshot format", "General")).toUpper(); if (screenshotFormatComboBox->findText(screenshotFormatString) == -1) screenshotFormatComboBox->addItem(screenshotFormatString); - screenshotFormatComboBox->setCurrentText(screenshotFormatString); + screenshotFormatComboBox->setCurrentIndex(screenshotFormatComboBox->findText(screenshotFormatString)); return true; } From 88ae0772cf1be1dd252c20b6ccaec98d36d3c30f Mon Sep 17 00:00:00 2001 From: David Cernat Date: Tue, 30 Jan 2018 22:51:35 +0200 Subject: [PATCH 04/16] [Server] Initialize new processors and fix issues with RecordDynamic --- apps/openmw-mp/Script/ScriptFunctions.hpp | 1 + apps/openmw-mp/processors/ProcessorInitializer.cpp | 14 ++++++++++++++ .../processors/player/ProcessorRecordDynamic.hpp | 10 +++++----- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/apps/openmw-mp/Script/ScriptFunctions.hpp b/apps/openmw-mp/Script/ScriptFunctions.hpp index fd151a329..caaf3d593 100644 --- a/apps/openmw-mp/Script/ScriptFunctions.hpp +++ b/apps/openmw-mp/Script/ScriptFunctions.hpp @@ -163,6 +163,7 @@ public: {"OnPlayerMap", Function()}, {"OnPlayerInteraction", Function()}, {"OnPlayerRest", Function()}, + {"OnRecordDynamic", Function()}, {"OnCellLoad", Function()}, {"OnCellUnload", Function()}, {"OnCellDeletion", Function()}, diff --git a/apps/openmw-mp/processors/ProcessorInitializer.cpp b/apps/openmw-mp/processors/ProcessorInitializer.cpp index c2cad7ecf..ee5fd14c7 100644 --- a/apps/openmw-mp/processors/ProcessorInitializer.cpp +++ b/apps/openmw-mp/processors/ProcessorInitializer.cpp @@ -11,6 +11,7 @@ #include "player/ProcessorChatMsg.hpp" #include "player/ProcessorGUIMessageBox.hpp" #include "player/ProcessorGameWeather.hpp" +#include "player/ProcessorRecordDynamic.hpp" #include "player/ProcessorPlayerCharGen.hpp" #include "player/ProcessorPlayerAnimFlags.hpp" #include "player/ProcessorPlayerAnimPlay.hpp" @@ -28,10 +29,13 @@ #include "player/ProcessorPlayerInventory.hpp" #include "player/ProcessorPlayerJournal.hpp" #include "player/ProcessorPlayerKillCount.hpp" +#include "player/ProcessorPlayerInteraction.hpp" #include "player/ProcessorPlayerLevel.hpp" #include "player/ProcessorPlayerMap.hpp" +#include "player/ProcessorPlayerMiscellaneous.hpp" #include "player/ProcessorPlayerPosition.hpp" #include "player/ProcessorPlayerQuickKeys.hpp" +#include "player/ProcessorPlayerReputation.hpp" #include "player/ProcessorPlayerRest.hpp" #include "player/ProcessorPlayerResurrect.hpp" #include "player/ProcessorPlayerShapeshift.hpp" @@ -50,6 +54,7 @@ #include "actor/ProcessorActorCellChange.hpp" #include "actor/ProcessorActorDeath.hpp" #include "actor/ProcessorActorEquipment.hpp" +#include "actor/ProcessorActorInteraction.hpp" #include "actor/ProcessorActorStatsDynamic.hpp" #include "actor/ProcessorActorPosition.hpp" #include "actor/ProcessorActorSpeech.hpp" @@ -70,7 +75,9 @@ #include "world/ProcessorScriptLocalShort.hpp" #include "world/ProcessorScriptLocalFloat.hpp" #include "world/ProcessorScriptMemberShort.hpp" +#include "world/ProcessorScriptMemberFloat.hpp" #include "world/ProcessorScriptGlobalShort.hpp" +#include "world/ProcessorScriptGlobalFloat.hpp" #include "world/ProcessorVideoPlay.hpp" @@ -81,6 +88,7 @@ void ProcessorInitializer() PlayerProcessor::AddProcessor(new ProcessorChatMsg()); PlayerProcessor::AddProcessor(new ProcessorGUIMessageBox()); PlayerProcessor::AddProcessor(new ProcessorGameWeather()); + PlayerProcessor::AddProcessor(new ProcessorRecordDynamic()); PlayerProcessor::AddProcessor(new ProcessorPlayerCharGen()); PlayerProcessor::AddProcessor(new ProcessorPlayerAnimFlags()); PlayerProcessor::AddProcessor(new ProcessorPlayerAnimPlay()); @@ -98,10 +106,13 @@ void ProcessorInitializer() PlayerProcessor::AddProcessor(new ProcessorPlayerInventory()); PlayerProcessor::AddProcessor(new ProcessorPlayerJournal()); PlayerProcessor::AddProcessor(new ProcessorPlayerKillCount()); + PlayerProcessor::AddProcessor(new ProcessorPlayerInteraction()); PlayerProcessor::AddProcessor(new ProcessorPlayerLevel()); PlayerProcessor::AddProcessor(new ProcessorPlayerMap()); + PlayerProcessor::AddProcessor(new ProcessorPlayerMiscellaneous()); PlayerProcessor::AddProcessor(new ProcessorPlayerPosition()); PlayerProcessor::AddProcessor(new ProcessorPlayerQuickKeys()); + PlayerProcessor::AddProcessor(new ProcessorPlayerReputation()); PlayerProcessor::AddProcessor(new ProcessorPlayerRest()); PlayerProcessor::AddProcessor(new ProcessorPlayerResurrect()); PlayerProcessor::AddProcessor(new ProcessorPlayerShapeshift()); @@ -119,6 +130,7 @@ void ProcessorInitializer() ActorProcessor::AddProcessor(new ProcessorActorCellChange()); ActorProcessor::AddProcessor(new ProcessorActorDeath()); ActorProcessor::AddProcessor(new ProcessorActorEquipment()); + ActorProcessor::AddProcessor(new ProcessorActorInteraction()); ActorProcessor::AddProcessor(new ProcessorActorPosition()); ActorProcessor::AddProcessor(new ProcessorActorSpeech()); ActorProcessor::AddProcessor(new ProcessorActorStatsDynamic()); @@ -140,6 +152,8 @@ void ProcessorInitializer() WorldProcessor::AddProcessor(new ProcessorScriptLocalShort()); WorldProcessor::AddProcessor(new ProcessorScriptLocalFloat()); WorldProcessor::AddProcessor(new ProcessorScriptMemberShort()); + WorldProcessor::AddProcessor(new ProcessorScriptMemberFloat()); WorldProcessor::AddProcessor(new ProcessorScriptGlobalShort()); + WorldProcessor::AddProcessor(new ProcessorScriptGlobalFloat()); WorldProcessor::AddProcessor(new ProcessorVideoPlay()); } diff --git a/apps/openmw-mp/processors/player/ProcessorRecordDynamic.hpp b/apps/openmw-mp/processors/player/ProcessorRecordDynamic.hpp index 790e286c9..4acb7b0a8 100644 --- a/apps/openmw-mp/processors/player/ProcessorRecordDynamic.hpp +++ b/apps/openmw-mp/processors/player/ProcessorRecordDynamic.hpp @@ -1,14 +1,14 @@ -#ifndef OPENMW_PROCESSORPLAYERRECORDDYNAMIC_HPP -#define OPENMW_PROCESSORPLAYERRECORDDYNAMIC_HPP +#ifndef OPENMW_PROCESSORRECORDDYNAMIC_HPP +#define OPENMW_PROCESSORRECORDDYNAMIC_HPP #include "../PlayerProcessor.hpp" namespace mwmp { - class ProcessorPlayerRecordDynamic : public PlayerProcessor + class ProcessorRecordDynamic : public PlayerProcessor { public: - ProcessorPlayerRecordDynamic() + ProcessorRecordDynamic() { BPP_INIT(ID_RECORD_DYNAMIC) } @@ -22,4 +22,4 @@ namespace mwmp }; } -#endif //OPENMW_PROCESSORPLAYERRECORDDYNAMIC_HPP +#endif //OPENMW_PROCESSORRECORDDYNAMIC_HPP From 989f6e6b517ef0ff550ac457f97a9401c0b9cff0 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Tue, 30 Jan 2018 22:55:29 +0200 Subject: [PATCH 05/16] [General] Implement PlayerReputation packet --- apps/openmw-mp/Script/Functions/Quests.cpp | 25 ++++++++++++++ apps/openmw-mp/Script/Functions/Quests.hpp | 34 ++++++++++++++++++- apps/openmw/mwmp/LocalPlayer.cpp | 23 +++++++++++++ apps/openmw/mwmp/LocalPlayer.hpp | 2 ++ .../player/ProcessorPlayerReputation.hpp | 12 ++----- .../Packets/Player/PacketPlayerReputation.cpp | 2 +- 6 files changed, 87 insertions(+), 11 deletions(-) diff --git a/apps/openmw-mp/Script/Functions/Quests.cpp b/apps/openmw-mp/Script/Functions/Quests.cpp index 7c85ec956..d9d3606f9 100644 --- a/apps/openmw-mp/Script/Functions/Quests.cpp +++ b/apps/openmw-mp/Script/Functions/Quests.cpp @@ -79,6 +79,14 @@ void QuestFunctions::AddKill(unsigned short pid, const char* refId, int number) player->killChanges.kills.push_back(kill); } +void QuestFunctions::SetReputation(unsigned short pid, int value) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + player->npcStats.mReputation = value; +} + const char *QuestFunctions::GetJournalItemQuest(unsigned short pid, unsigned int i) noexcept { Player *player; @@ -133,6 +141,14 @@ int QuestFunctions::GetKillNumber(unsigned short pid, unsigned int i) noexcept return player->killChanges.kills.at(i).number; } +int QuestFunctions::GetReputation(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + return player->npcStats.mReputation; +} + void QuestFunctions::SendJournalChanges(unsigned short pid, bool toOthers) noexcept { Player *player; @@ -150,3 +166,12 @@ void QuestFunctions::SendKillChanges(unsigned short pid, bool toOthers) noexcept mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_KILL_COUNT)->setPlayer(player); mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_KILL_COUNT)->Send(toOthers); } + +void QuestFunctions::SendReputation(unsigned short pid, bool toOthers) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_REPUTATION)->setPlayer(player); + mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_REPUTATION)->Send(toOthers); +} diff --git a/apps/openmw-mp/Script/Functions/Quests.hpp b/apps/openmw-mp/Script/Functions/Quests.hpp index 3ce431dda..d140137de 100644 --- a/apps/openmw-mp/Script/Functions/Quests.hpp +++ b/apps/openmw-mp/Script/Functions/Quests.hpp @@ -12,6 +12,8 @@ {"AddJournalIndex", QuestFunctions::AddJournalIndex},\ {"AddKill", QuestFunctions::AddKill},\ \ + {"SetReputation", QuestFunctions::SetReputation},\ + \ {"GetJournalItemQuest", QuestFunctions::GetJournalItemQuest},\ {"GetJournalItemIndex", QuestFunctions::GetJournalItemIndex},\ {"GetJournalItemType", QuestFunctions::GetJournalItemType},\ @@ -19,8 +21,11 @@ {"GetKillRefId", QuestFunctions::GetKillRefId},\ {"GetKillNumber", QuestFunctions::GetKillNumber},\ \ + {"GetReputation", QuestFunctions::GetReputation},\ + \ {"SendJournalChanges", QuestFunctions::SendJournalChanges},\ - {"SendKillChanges", QuestFunctions::SendKillChanges} + {"SendKillChanges", QuestFunctions::SendKillChanges},\ + {"SendReputation", QuestFunctions::SendReputation} class QuestFunctions { @@ -93,6 +98,15 @@ public: */ static void AddKill(unsigned short pid, const char* refId, int number) noexcept; + /** + * \brief Set the reputation of a certain player. + * + * \param pid The player ID. + * \param value The reputation. + * \return void + */ + static void SetReputation(unsigned short pid, int value) noexcept; + /** * \brief Get the quest at a certain index in a player's latest journal changes. * @@ -149,6 +163,14 @@ public: */ static int GetKillNumber(unsigned short pid, unsigned int i) noexcept; + /** + * \brief Get the a certain player's reputation. + * + * \param pid The player ID. + * \return The reputation. + */ + static int GetReputation(unsigned short pid) noexcept; + /** * \brief Send a PlayerJournal packet with a player's recorded journal changes. * @@ -169,6 +191,16 @@ public: */ static void SendKillChanges(unsigned short pid, bool toOthers = false) noexcept; + /** + * \brief Send a PlayerReputation packet with a player's recorded reputation. + * + * \param pid The player ID whose reputation should be used. + * \param toOthers Whether this packet should be sent only to other players or + * only to the player it is about. + * \return void + */ + static void SendReputation(unsigned short pid, bool toOthers) noexcept; + private: }; diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index 56a426807..a6528c8ec 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -105,6 +105,7 @@ void LocalPlayer::update() updateSkills(); updateLevel(); updateBounty(); + updateReputation(); } } @@ -328,6 +329,19 @@ void LocalPlayer::updateBounty(bool forceUpdate) } } +void LocalPlayer::updateReputation(bool forceUpdate) +{ + MWWorld::Ptr ptrPlayer = getPlayerPtr(); + const MWMechanics::NpcStats &ptrNpcStats = ptrPlayer.getClass().getNpcStats(ptrPlayer); + + if (ptrNpcStats.getReputation() != npcStats.mReputation || forceUpdate) + { + npcStats.mReputation = ptrNpcStats.getReputation(); + getNetworking()->getPlayerPacket(ID_PLAYER_REPUTATION)->setPlayer(this); + getNetworking()->getPlayerPacket(ID_PLAYER_REPUTATION)->Send(); + } +} + void LocalPlayer::updatePosition(bool forceUpdate) { MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -928,6 +942,15 @@ void LocalPlayer::setBounty() ptrNpcStats->setBounty(npcStats.mBounty); } +void LocalPlayer::setReputation() +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + MWWorld::Ptr ptrPlayer = world->getPlayerPtr(); + + MWMechanics::NpcStats *ptrNpcStats = &ptrPlayer.getClass().getNpcStats(ptrPlayer); + ptrNpcStats->setReputation(npcStats.mReputation); +} + void LocalPlayer::setPosition() { MWBase::World *world = MWBase::Environment::get().getWorld(); diff --git a/apps/openmw/mwmp/LocalPlayer.hpp b/apps/openmw/mwmp/LocalPlayer.hpp index 1900b07b4..3f3da26ef 100644 --- a/apps/openmw/mwmp/LocalPlayer.hpp +++ b/apps/openmw/mwmp/LocalPlayer.hpp @@ -30,6 +30,7 @@ namespace mwmp void updateSkills(bool forceUpdate = false); void updateLevel(bool forceUpdate = false); void updateBounty(bool forceUpdate = false); + void updateReputation(bool forceUpdate = false); void updatePosition(bool forceUpdate = false); void updateCell(bool forceUpdate = false); void updateChar(); @@ -56,6 +57,7 @@ namespace mwmp void setSkills(); void setLevel(); void setBounty(); + void setReputation(); void setPosition(); void setCell(); void setClass(); diff --git a/apps/openmw/mwmp/processors/player/ProcessorPlayerReputation.hpp b/apps/openmw/mwmp/processors/player/ProcessorPlayerReputation.hpp index 4bdf7ee8b..ae932fa5c 100644 --- a/apps/openmw/mwmp/processors/player/ProcessorPlayerReputation.hpp +++ b/apps/openmw/mwmp/processors/player/ProcessorPlayerReputation.hpp @@ -16,19 +16,13 @@ namespace mwmp virtual void Do(PlayerPacket &packet, BasePlayer *player) { - if (isLocal()) + if (isRequest()) { - //if (isRequest()) - // static_cast(player)->updateReputation(true); - //else - // static_cast(player)->setReputation(); + static_cast(player)->updateReputation(true); } else if (player != 0) { - MWWorld::Ptr ptrPlayer = static_cast(player)->getPtr(); - MWMechanics::NpcStats *ptrNpcStats = &ptrPlayer.getClass().getNpcStats(ptrPlayer); - - ptrNpcStats->setReputation(player->npcStats.mReputation); + static_cast(player)->setReputation(); } } }; diff --git a/components/openmw-mp/Packets/Player/PacketPlayerReputation.cpp b/components/openmw-mp/Packets/Player/PacketPlayerReputation.cpp index 291846ef9..25f058a98 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerReputation.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerReputation.cpp @@ -12,5 +12,5 @@ void PacketPlayerReputation::Packet(RakNet::BitStream *bs, bool send) { PlayerPacket::Packet(bs, send); - // Placeholder + RW(player->npcStats.mReputation, send); } From b1b8e3156253f45c8f1eeaf81bbe537df765ad74 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Tue, 30 Jan 2018 22:05:16 +0000 Subject: [PATCH 06/16] Use unique_ptr over new/delete (Fixes #4305) --- apps/openmw/mwworld/worldimp.cpp | 36 +++++++++++++------------------- apps/openmw/mwworld/worldimp.hpp | 11 +++++----- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index d8f801420..02e0737ee 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -148,16 +148,16 @@ namespace MWWorld ToUTF8::Utf8Encoder* encoder, const std::map& fallbackMap, int activationDistanceOverride, const std::string& startCell, const std::string& startupScript, const std::string& resourcePath, const std::string& userDataPath) - : mResourceSystem(resourceSystem), mFallback(fallbackMap), mPlayer (0), mLocalScripts (mStore), + : mResourceSystem(resourceSystem), mFallback(fallbackMap), mLocalScripts (mStore), mSky (true), mCells (mStore, mEsm), mGodMode(false), mScriptsEnabled(true), mContentFiles (contentFiles), mUserDataPath(userDataPath), mActivationDistanceOverride (activationDistanceOverride), mStartupScript(startupScript), mStartCell (startCell), mDistanceToFacedObject(-1), mTeleportEnabled(true), mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0), mSpellPreloadTimer(0.f) { - mPhysics = new MWPhysics::PhysicsSystem(resourceSystem, rootNode); - mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem, workQueue, &mFallback, resourcePath); - mProjectileManager.reset(new ProjectileManager(mRendering->getLightRoot(), resourceSystem, mRendering, mPhysics)); + mPhysics.reset(new MWPhysics::PhysicsSystem(resourceSystem, rootNode)); + mRendering.reset(new MWRender::RenderingManager(viewer, rootNode, resourceSystem, workQueue, &mFallback, resourcePath)); + mProjectileManager.reset(new ProjectileManager(mRendering->getLightRoot(), resourceSystem, mRendering.get(), mPhysics.get())); mRendering->preloadCommonAssets(); @@ -189,9 +189,9 @@ namespace MWWorld mSwimHeightScale = mStore.get().find("fSwimHeightScale")->getFloat(); - mWeatherManager = new MWWorld::WeatherManager(*mRendering, mFallback, mStore); + mWeatherManager.reset(new MWWorld::WeatherManager(*mRendering, mFallback, mStore)); - mWorldScene = new Scene(*mRendering, mPhysics); + mWorldScene.reset(new Scene(*mRendering.get(), mPhysics.get())); } void World::fillGlobalVariables() @@ -224,8 +224,8 @@ namespace MWWorld // we don't want old weather to persist on a new game // Note that if reset later, the initial ChangeWeather that the chargen script calls will be lost. - delete mWeatherManager; - mWeatherManager = new MWWorld::WeatherManager(*mRendering, mFallback, mStore); + mWeatherManager.reset(); + mWeatherManager.reset(new MWWorld::WeatherManager(*mRendering.get(), mFallback, mStore)); if (!bypass) { @@ -492,12 +492,6 @@ namespace MWWorld { // Must be cleared before mRendering is destroyed mProjectileManager->clear(); - delete mWeatherManager; - delete mWorldScene; - delete mRendering; - delete mPhysics; - - delete mPlayer; } const ESM::Cell *World::getExterior (const std::string& cellName) const @@ -2214,7 +2208,7 @@ namespace MWWorld { const ESM::NPC *player = mStore.get().find("player"); if (!mPlayer) - mPlayer = new MWWorld::Player(player); + mPlayer.reset(new MWWorld::Player(player)); else { // Remove the old CharacterController @@ -3478,17 +3472,17 @@ namespace MWWorld if (MWMechanics::isSummoningEffect(it->mEffectID)) { - preload(mWorldScene, mStore, "VFX_Summon_Start"); - preload(mWorldScene, mStore, MWMechanics::getSummonedCreature(it->mEffectID)); + preload(mWorldScene.get(), mStore, "VFX_Summon_Start"); + preload(mWorldScene.get(), mStore, MWMechanics::getSummonedCreature(it->mEffectID)); } - preload(mWorldScene, mStore, effect->mCasting); - preload(mWorldScene, mStore, effect->mHit); + preload(mWorldScene.get(), mStore, effect->mCasting); + preload(mWorldScene.get(), mStore, effect->mHit); if (it->mArea > 0) - preload(mWorldScene, mStore, effect->mArea); + preload(mWorldScene.get(), mStore, effect->mArea); if (it->mRange == ESM::RT_Target) - preload(mWorldScene, mStore, effect->mBolt); + preload(mWorldScene.get(), mStore, effect->mBolt); } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 7af7b2968..02b3756d5 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -74,17 +74,11 @@ namespace MWWorld Resource::ResourceSystem* mResourceSystem; Fallback::Map mFallback; - MWRender::RenderingManager* mRendering; - MWWorld::WeatherManager* mWeatherManager; - - MWWorld::Scene *mWorldScene; - MWWorld::Player *mPlayer; std::vector mEsm; MWWorld::ESMStore mStore; LocalScripts mLocalScripts; MWWorld::Globals mGlobalVariables; - MWPhysics::PhysicsSystem *mPhysics; bool mSky; ESM::Variant* mGameHour; @@ -98,6 +92,11 @@ namespace MWWorld std::string mCurrentWorldSpace; + std::unique_ptr mPlayer; + std::unique_ptr mPhysics; + std::unique_ptr mRendering; + std::unique_ptr mWorldScene; + std::unique_ptr mWeatherManager; std::shared_ptr mProjectileManager; bool mGodMode; From 66078bfea74d8c56b9953490efcbb9e516598c22 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Wed, 31 Jan 2018 04:50:29 +0200 Subject: [PATCH 07/16] [General] Implement Mark location sync as part of PlayerMiscellaneous --- apps/openmw-mp/Script/Functions/Mechanics.cpp | 97 +++++++++++++ apps/openmw-mp/Script/Functions/Mechanics.hpp | 130 +++++++++++++++++- apps/openmw/mwmechanics/spellcasting.cpp | 11 ++ apps/openmw/mwmp/CellController.cpp | 1 - apps/openmw/mwmp/LocalPlayer.cpp | 18 +++ apps/openmw/mwmp/LocalPlayer.hpp | 6 +- .../player/ProcessorPlayerMiscellaneous.hpp | 4 +- components/openmw-mp/Base/BasePlayer.hpp | 10 ++ .../Player/PacketPlayerMiscellaneous.cpp | 12 +- 9 files changed, 279 insertions(+), 10 deletions(-) diff --git a/apps/openmw-mp/Script/Functions/Mechanics.cpp b/apps/openmw-mp/Script/Functions/Mechanics.cpp index bf499045a..127efe473 100644 --- a/apps/openmw-mp/Script/Functions/Mechanics.cpp +++ b/apps/openmw-mp/Script/Functions/Mechanics.cpp @@ -9,6 +9,65 @@ #include using namespace std; +static std::string tempCellDescription; + +unsigned char MechanicsFunctions::GetMiscellaneousChangeType(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + return player->miscellaneousChangeType; +} + +const char *MechanicsFunctions::GetMarkCell(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + tempCellDescription = player->cell.getDescription().c_str(); + return tempCellDescription.c_str(); +} + +double MechanicsFunctions::GetMarkPosX(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0.0f); + + return player->markPosition.pos[0]; +} + +double MechanicsFunctions::GetMarkPosY(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0.0f); + + return player->markPosition.pos[1]; +} + +double MechanicsFunctions::GetMarkPosZ(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0.0f); + + return player->markPosition.pos[2]; +} + +double MechanicsFunctions::GetMarkRotX(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0.0f); + + return player->markPosition.rot[0]; +} + +double MechanicsFunctions::GetMarkRotZ(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0.0f); + + return player->markPosition.rot[2]; +} + bool MechanicsFunctions::IsWerewolf(unsigned short pid) noexcept { Player *player; @@ -17,6 +76,33 @@ bool MechanicsFunctions::IsWerewolf(unsigned short pid) noexcept return player->isWerewolf; } +void MechanicsFunctions::SetMarkCell(unsigned short pid, const char *cellDescription) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + player->markCell = Utils::getCellFromDescription(cellDescription); +} + +void MechanicsFunctions::SetMarkPos(unsigned short pid, double x, double y, double z) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + player->markPosition.pos[0] = x; + player->markPosition.pos[1] = y; + player->markPosition.pos[2] = z; +} + +void MechanicsFunctions::SetMarkRot(unsigned short pid, double x, double z) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + player->markPosition.rot[0] = x; + player->markPosition.rot[2] = z; +} + void MechanicsFunctions::SetWerewolfState(unsigned short pid, bool isWerewolf) { Player *player; @@ -25,6 +111,17 @@ void MechanicsFunctions::SetWerewolfState(unsigned short pid, bool isWerewolf) player->isWerewolf = isWerewolf; } +void MechanicsFunctions::SendMarkLocation(unsigned short pid) +{ + Player *player; + GET_PLAYER(pid, player, ); + + player->miscellaneousChangeType = mwmp::MISCELLANEOUS_CHANGE_TYPE::MARK_LOCATION; + + mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_MISCELLANEOUS)->setPlayer(player); + mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_MISCELLANEOUS)->Send(false); +} + void MechanicsFunctions::SendShapeshift(unsigned short pid) { Player *player; diff --git a/apps/openmw-mp/Script/Functions/Mechanics.hpp b/apps/openmw-mp/Script/Functions/Mechanics.hpp index 308793430..d2c4f0ee0 100644 --- a/apps/openmw-mp/Script/Functions/Mechanics.hpp +++ b/apps/openmw-mp/Script/Functions/Mechanics.hpp @@ -4,19 +4,89 @@ #include "../Types.hpp" #define MECHANICSAPI \ - {"IsWerewolf", MechanicsFunctions::IsWerewolf},\ + {"GetMiscellaneousChangeType", MechanicsFunctions::GetMiscellaneousChangeType},\ \ - {"SetWerewolfState", MechanicsFunctions::SetWerewolfState},\ + {"GetMarkCell", MechanicsFunctions::GetMarkCell},\ + {"GetMarkPosX", MechanicsFunctions::GetMarkPosX},\ + {"GetMarkPosY", MechanicsFunctions::GetMarkPosY},\ + {"GetMarkPosZ", MechanicsFunctions::GetMarkPosZ},\ + {"GetMarkRotX", MechanicsFunctions::GetMarkRotX},\ + {"GetMarkRotZ", MechanicsFunctions::GetMarkRotZ},\ \ - {"SendShapeshift", MechanicsFunctions::SendShapeshift},\ + {"IsWerewolf", MechanicsFunctions::IsWerewolf},\ \ - {"Jail", MechanicsFunctions::Jail},\ - {"Resurrect", MechanicsFunctions::Resurrect} + {"SetMarkCell", MechanicsFunctions::SetMarkCell},\ + {"SetMarkPos", MechanicsFunctions::SetMarkPos},\ + {"SetMarkRot", MechanicsFunctions::SetMarkRot},\ + \ + {"SetWerewolfState", MechanicsFunctions::SetWerewolfState},\ + \ + {"SendMarkLocation", MechanicsFunctions::SendMarkLocation},\ + {"SendShapeshift", MechanicsFunctions::SendShapeshift},\ + \ + {"Jail", MechanicsFunctions::Jail},\ + {"Resurrect", MechanicsFunctions::Resurrect} class MechanicsFunctions { public: + /** + * \brief Get the type of a PlayerMiscellaneous packet. + * + * \param pid The player ID. + * \return The type. + */ + static unsigned char GetMiscellaneousChangeType(unsigned short pid) noexcept; + + /** + * \brief Get the cell description of a player's Mark cell. + * + * \param pid The player ID. + * \return The cell description. + */ + static const char *GetMarkCell(unsigned short pid) noexcept; + + /** + * \brief Get the X position of a player's Mark. + * + * \param pid The player ID. + * \return The X position. + */ + static double GetMarkPosX(unsigned short pid) noexcept; + + /** + * \brief Get the Y position of a player's Mark. + * + * \param pid The player ID. + * \return The Y position. + */ + static double GetMarkPosY(unsigned short pid) noexcept; + + /** + * \brief Get the Z position of a player's Mark. + * + * \param pid The player ID. + * \return The Z position. + */ + static double GetMarkPosZ(unsigned short pid) noexcept; + + /** + * \brief Get the X rotation of a player's Mark. + * + * \param pid The player ID. + * \return The X rotation. + */ + static double GetMarkRotX(unsigned short pid) noexcept; + + /** + * \brief Get the Z rotation of a player's Mark. + * + * \param pid The player ID. + * \return The X rotation. + */ + static double GetMarkRotZ(unsigned short pid) noexcept; + /** * \brief Check whether a player is a werewolf. * @@ -27,6 +97,48 @@ public: */ static bool IsWerewolf(unsigned short pid) noexcept; + /** + * \brief Set the Mark cell of a player. + * + * This changes the Mark cell recorded for that player in the server memory, but does not by itself + * send a packet. + * + * The cell is determined to be an exterior cell if it fits the pattern of a number followed + * by a comma followed by another number. + * + * \param pid The player ID. + * \param cellDescription The cell description. + * \return void + */ + static void SetMarkCell(unsigned short pid, const char *cellDescription) noexcept; + + /** + * \brief Set the Mark position of a player. + * + * This changes the Mark positional coordinates recorded for that player in the server memory, but + * does not by itself send a packet. + * + * \param pid The player ID. + * \param x The X position. + * \param y The Y position. + * \param z The Z position. + * \return void + */ + static void SetMarkPos(unsigned short pid, double x, double y, double z) noexcept; + + /** + * \brief Set the Mark rotation of a player. + * + * This changes the Mark positional coordinates recorded for that player in the server memory, but + * does not by itself send a packet. + * + * \param pid The player ID. + * \param x The X rotation. + * \param z The Z rotation. + * \return void + */ + static void SetMarkRot(unsigned short pid, double x, double z) noexcept; + /** * \brief Set the werewolf state of a player. * @@ -39,6 +151,14 @@ public: */ static void SetWerewolfState(unsigned short pid, bool isWerewolf); + /** + * \brief Send a PlayerMiscellaneous packet with a Mark location to a player. + * + * \param pid The player ID. + * \return void + */ + static void SendMarkLocation(unsigned short pid); + /** * \brief Send a PlayerShapeshift packet about a player. * diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 27c83249e..381a1047c 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -755,6 +755,17 @@ namespace MWMechanics { MWBase::Environment::get().getWorld()->getPlayer().markPosition( target.getCell(), target.getRefData().getPosition()); + + /* + Start of tes3mp addition + + Send a PlayerMiscellaneous packet with the player's new mark location + */ + mwmp::Main::get().getLocalPlayer()->sendMarkLocation(*target.getCell()->getCell(), target.getRefData().getPosition()); + /* + End of tes3mp addition + */ + return true; } else if (effectId == ESM::MagicEffect::Recall) diff --git a/apps/openmw/mwmp/CellController.cpp b/apps/openmw/mwmp/CellController.cpp index 83aa32bae..eb89f7b45 100644 --- a/apps/openmw/mwmp/CellController.cpp +++ b/apps/openmw/mwmp/CellController.cpp @@ -364,7 +364,6 @@ void CellController::openContainer(const MWWorld::Ptr &container) /*if (::Misc::StringUtils::ciEqual(name, "gold_001")) cont.remove("gold_001", count, container);*/ } - } void CellController::closeContainer(const MWWorld::Ptr &container) diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index a6528c8ec..781c8d7dd 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -1269,6 +1269,14 @@ void LocalPlayer::setShapeshift() MWBase::Environment::get().getMechanicsManager()->setWerewolf(ptrPlayer, isWerewolf); } +void LocalPlayer::setMarkLocation() +{ + MWWorld::CellStore *ptrCellStore = Main::get().getCellController()->getCellStore(markCell); + + if (ptrCellStore) + MWBase::Environment::get().getWorld()->getPlayer().markPosition(ptrCellStore, markPosition); +} + void LocalPlayer::sendClass() { MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -1555,6 +1563,16 @@ void LocalPlayer::sendShapeshift(bool werewolfState) getNetworking()->getPlayerPacket(ID_PLAYER_SHAPESHIFT)->Send(); } +void LocalPlayer::sendMarkLocation(const ESM::Cell& newMarkCell, const ESM::Position& newMarkPosition) +{ + miscellaneousChangeType = mwmp::MISCELLANEOUS_CHANGE_TYPE::MARK_LOCATION; + markCell = newMarkCell; + markPosition = newMarkPosition; + + getNetworking()->getPlayerPacket(ID_PLAYER_MISCELLANEOUS)->setPlayer(this); + getNetworking()->getPlayerPacket(ID_PLAYER_MISCELLANEOUS)->Send(); +} + void LocalPlayer::clearCellStates() { cellStateChanges.cellStates.clear(); diff --git a/apps/openmw/mwmp/LocalPlayer.hpp b/apps/openmw/mwmp/LocalPlayer.hpp index 3f3da26ef..7f92de89b 100644 --- a/apps/openmw/mwmp/LocalPlayer.hpp +++ b/apps/openmw/mwmp/LocalPlayer.hpp @@ -70,15 +70,16 @@ namespace mwmp void setBooks(); void setMapExplored(); void setShapeshift(); + void setMarkLocation(); void sendClass(); void sendInventory(); void sendSpellbook(); void sendCellStates(); void sendSpellAddition(std::string id); - void sendSpellAddition(const ESM::Spell &spell); + void sendSpellAddition(const ESM::Spell& spell); void sendSpellRemoval(std::string id); - void sendSpellRemoval(const ESM::Spell &spell); + void sendSpellRemoval(const ESM::Spell& spell); void sendQuickKey(unsigned short slot, int type, const std::string& itemId = ""); void sendJournalEntry(const std::string& quest, int index, const MWWorld::Ptr& actor); void sendJournalIndex(const std::string& quest, int index); @@ -89,6 +90,7 @@ namespace mwmp void sendKill(const std::string& refId, int number); void sendBook(const std::string& bookId); void sendShapeshift(bool isWerewolf); + void sendMarkLocation(const ESM::Cell& newMarkCell, const ESM::Position& newMarkPosition); void clearCellStates(); void clearCurrentContainer(); diff --git a/apps/openmw/mwmp/processors/player/ProcessorPlayerMiscellaneous.hpp b/apps/openmw/mwmp/processors/player/ProcessorPlayerMiscellaneous.hpp index f6e06b08b..4dcc8a5be 100644 --- a/apps/openmw/mwmp/processors/player/ProcessorPlayerMiscellaneous.hpp +++ b/apps/openmw/mwmp/processors/player/ProcessorPlayerMiscellaneous.hpp @@ -23,7 +23,9 @@ namespace mwmp if (!isRequest()) { LocalPlayer &localPlayer = static_cast(*player); - //localPlayer.setMiscellaneous(); + + if (player->miscellaneousChangeType == mwmp::MISCELLANEOUS_CHANGE_TYPE::MARK_LOCATION) + localPlayer.setMarkLocation(); } } }; diff --git a/components/openmw-mp/Base/BasePlayer.hpp b/components/openmw-mp/Base/BasePlayer.hpp index 480eb9351..15939ee00 100644 --- a/components/openmw-mp/Base/BasePlayer.hpp +++ b/components/openmw-mp/Base/BasePlayer.hpp @@ -184,6 +184,12 @@ namespace mwmp TRIBUNAL_TEMPLE }; + enum MISCELLANEOUS_CHANGE_TYPE + { + MARK_LOCATION = 0, + SELECTED_SPELL + }; + class BasePlayer { public: @@ -292,6 +298,10 @@ namespace mwmp std::string jailEndText; unsigned int resurrectType; + unsigned int miscellaneousChangeType; + + ESM::Cell markCell; + ESM::Position markPosition; bool diedSinceArrestAttempt; bool isReceivingQuickKeys; diff --git a/components/openmw-mp/Packets/Player/PacketPlayerMiscellaneous.cpp b/components/openmw-mp/Packets/Player/PacketPlayerMiscellaneous.cpp index 6a6aa40f8..cffb6a446 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerMiscellaneous.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerMiscellaneous.cpp @@ -12,5 +12,15 @@ void PacketPlayerMiscellaneous::Packet(RakNet::BitStream *bs, bool send) { PlayerPacket::Packet(bs, send); - // Placeholder + RW(player->miscellaneousChangeType, send); + + if (player->miscellaneousChangeType == mwmp::MISCELLANEOUS_CHANGE_TYPE::MARK_LOCATION) + { + RW(player->markCell.mData, send, 1); + RW(player->markCell.mName, send, 1); + + RW(player->markPosition.pos, send); + RW(player->markPosition.rot[0], send); + RW(player->markPosition.rot[2], send); + } } From ce5670e57e9e167a4cf94351b22ee43a4f2d6ecf Mon Sep 17 00:00:00 2001 From: David Cernat Date: Wed, 31 Jan 2018 18:51:30 +0200 Subject: [PATCH 08/16] [Client] Ignore invalid object refIds from ObjectPlace packets --- apps/openmw/mwmp/WorldEvent.cpp | 37 ++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwmp/WorldEvent.cpp b/apps/openmw/mwmp/WorldEvent.cpp index 5ad38bf87..6f2a84031 100644 --- a/apps/openmw/mwmp/WorldEvent.cpp +++ b/apps/openmw/mwmp/WorldEvent.cpp @@ -174,26 +174,35 @@ void WorldEvent::placeObjects(MWWorld::CellStore* cellStore) // Only create this object if it doesn't already exist if (!ptrFound) { - MWWorld::ManualRef ref(world->getStore(), worldObject.refId, 1); - MWWorld::Ptr newPtr = ref.getPtr(); + try + { + MWWorld::ManualRef ref(world->getStore(), worldObject.refId, 1); - if (worldObject.count > 1) - newPtr.getRefData().setCount(worldObject.count); + MWWorld::Ptr newPtr = ref.getPtr(); - if (worldObject.charge > -1) - newPtr.getCellRef().setCharge(worldObject.charge); + if (worldObject.count > 1) + newPtr.getRefData().setCount(worldObject.count); - if (worldObject.enchantmentCharge > -1) - newPtr.getCellRef().setEnchantmentCharge(worldObject.enchantmentCharge); + if (worldObject.charge > -1) + newPtr.getCellRef().setCharge(worldObject.charge); - newPtr.getCellRef().setGoldValue(worldObject.goldValue); - newPtr = world->placeObject(newPtr, cellStore, worldObject.position); + if (worldObject.enchantmentCharge > -1) + newPtr.getCellRef().setEnchantmentCharge(worldObject.enchantmentCharge); - // Because gold automatically gets replaced with a new object, make sure we set the mpNum at the end - newPtr.getCellRef().setMpNum(worldObject.mpNum); + newPtr.getCellRef().setGoldValue(worldObject.goldValue); + newPtr = world->placeObject(newPtr, cellStore, worldObject.position); + + // Because gold automatically gets replaced with a new object, make sure we set the mpNum at the end + newPtr.getCellRef().setMpNum(worldObject.mpNum); - if (guid == Main::get().getLocalPlayer()->guid && worldObject.droppedByPlayer) - world->PCDropped(newPtr); + if (guid == Main::get().getLocalPlayer()->guid && worldObject.droppedByPlayer) + world->PCDropped(newPtr); + + } + catch (std::exception&) + { + LOG_APPEND(Log::LOG_INFO, "-- Ignored placement of invalid object"); + } } else LOG_APPEND(Log::LOG_VERBOSE, "-- Object already existed!"); From aa448523f8c0affc25df21eb993a8e327b391878 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Wed, 31 Jan 2018 23:23:52 +0200 Subject: [PATCH 09/16] [Client] Clean up WorldEvent::runConsoleCommands() slightly --- apps/openmw/mwmp/WorldEvent.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwmp/WorldEvent.cpp b/apps/openmw/mwmp/WorldEvent.cpp index 6f2a84031..c62aed004 100644 --- a/apps/openmw/mwmp/WorldEvent.cpp +++ b/apps/openmw/mwmp/WorldEvent.cpp @@ -485,24 +485,20 @@ void WorldEvent::runConsoleCommands(MWWorld::CellStore* cellStore) if (worldObject.isPlayer) { - BasePlayer *player = 0; - if (worldObject.guid == Main::get().getLocalPlayer()->guid) { - player = Main::get().getLocalPlayer(); - LOG_APPEND(Log::LOG_VERBOSE, "-- running on local player"); - windowManager->setConsolePtr(static_cast(player)->getPlayerPtr()); + windowManager->setConsolePtr(Main::get().getLocalPlayer()->getPlayerPtr()); windowManager->executeCommandInConsole(consoleCommand); } else { - player = PlayerList::getPlayer(worldObject.guid); + DedicatedPlayer *player = PlayerList::getPlayer(worldObject.guid); if (player != 0) { LOG_APPEND(Log::LOG_VERBOSE, "-- running on player %s", player->npc.mName.c_str()); - windowManager->setConsolePtr(static_cast(player)->getPtr()); + windowManager->setConsolePtr(player->getPtr()); windowManager->executeCommandInConsole(consoleCommand); } } @@ -525,7 +521,7 @@ void WorldEvent::runConsoleCommands(MWWorld::CellStore* cellStore) } windowManager->clearConsolePtr(); - } + } } void WorldEvent::setLocalShorts(MWWorld::CellStore* cellStore) From 029dfc56ba7dcc0ada82a99e457ab5fe2f30fc74 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Thu, 1 Feb 2018 02:11:45 +0200 Subject: [PATCH 10/16] [General] Implement player scale as part of PlayerShapeshift --- apps/openmw-mp/Player.cpp | 1 + apps/openmw-mp/Script/Functions/Mechanics.cpp | 18 +++++++++++- apps/openmw-mp/Script/Functions/Mechanics.hpp | 24 +++++++++++++++- apps/openmw/mwmp/DedicatedPlayer.cpp | 1 + apps/openmw/mwmp/LocalPlayer.cpp | 15 +++++++++- apps/openmw/mwmp/LocalPlayer.hpp | 3 +- apps/openmw/mwscript/statsextensions.cpp | 2 +- .../mwscript/transformationextensions.cpp | 28 +++++++++++++------ components/openmw-mp/Base/BasePlayer.hpp | 1 + .../Packets/Player/PacketPlayerShapeshift.cpp | 1 + 10 files changed, 81 insertions(+), 13 deletions(-) diff --git a/apps/openmw-mp/Player.cpp b/apps/openmw-mp/Player.cpp index 4bdf0f6c9..4dea0b4a6 100644 --- a/apps/openmw-mp/Player.cpp +++ b/apps/openmw-mp/Player.cpp @@ -34,6 +34,7 @@ void Players::newPlayer(RakNet::RakNetGUID guid) players[guid]->npcStats.blank(); players[guid]->creatureStats.blank(); players[guid]->charClass.blank(); + players[guid]->scale = 1; players[guid]->isWerewolf = false; for (unsigned int i = 0; i < mwmp::Networking::get().maxConnections(); i++) diff --git a/apps/openmw-mp/Script/Functions/Mechanics.cpp b/apps/openmw-mp/Script/Functions/Mechanics.cpp index 127efe473..b1a3ce413 100644 --- a/apps/openmw-mp/Script/Functions/Mechanics.cpp +++ b/apps/openmw-mp/Script/Functions/Mechanics.cpp @@ -68,6 +68,14 @@ double MechanicsFunctions::GetMarkRotZ(unsigned short pid) noexcept return player->markPosition.rot[2]; } +double MechanicsFunctions::GetScale(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0.0f); + + return player->scale; +} + bool MechanicsFunctions::IsWerewolf(unsigned short pid) noexcept { Player *player; @@ -103,7 +111,15 @@ void MechanicsFunctions::SetMarkRot(unsigned short pid, double x, double z) noex player->markPosition.rot[2] = z; } -void MechanicsFunctions::SetWerewolfState(unsigned short pid, bool isWerewolf) +void MechanicsFunctions::SetScale(unsigned short pid, double scale) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + player->scale = scale; +} + +void MechanicsFunctions::SetWerewolfState(unsigned short pid, bool isWerewolf) noexcept { Player *player; GET_PLAYER(pid, player, ); diff --git a/apps/openmw-mp/Script/Functions/Mechanics.hpp b/apps/openmw-mp/Script/Functions/Mechanics.hpp index d2c4f0ee0..7db879f0f 100644 --- a/apps/openmw-mp/Script/Functions/Mechanics.hpp +++ b/apps/openmw-mp/Script/Functions/Mechanics.hpp @@ -13,12 +13,14 @@ {"GetMarkRotX", MechanicsFunctions::GetMarkRotX},\ {"GetMarkRotZ", MechanicsFunctions::GetMarkRotZ},\ \ + {"GetScale", MechanicsFunctions::GetScale},\ {"IsWerewolf", MechanicsFunctions::IsWerewolf},\ \ {"SetMarkCell", MechanicsFunctions::SetMarkCell},\ {"SetMarkPos", MechanicsFunctions::SetMarkPos},\ {"SetMarkRot", MechanicsFunctions::SetMarkRot},\ \ + {"SetScale", MechanicsFunctions::SetScale},\ {"SetWerewolfState", MechanicsFunctions::SetWerewolfState},\ \ {"SendMarkLocation", MechanicsFunctions::SendMarkLocation},\ @@ -87,6 +89,14 @@ public: */ static double GetMarkRotZ(unsigned short pid) noexcept; + /** + * \brief Get the scale of a player. + * + * \param pid The player ID. + * \return The scale. + */ + static double GetScale(unsigned short pid) noexcept; + /** * \brief Check whether a player is a werewolf. * @@ -139,6 +149,18 @@ public: */ static void SetMarkRot(unsigned short pid, double x, double z) noexcept; + /** + * \brief Set the scale of a player. + * + * This changes the scale recorded for that player in the server memory, but + * does not by itself send a packet. + * + * \param pid The player ID. + * \param bool The new scale. + * \return void + */ + static void SetScale(unsigned short pid, double scale) noexcept; + /** * \brief Set the werewolf state of a player. * @@ -149,7 +171,7 @@ public: * \param bool The new werewolf state. * \return void */ - static void SetWerewolfState(unsigned short pid, bool isWerewolf); + static void SetWerewolfState(unsigned short pid, bool isWerewolf) noexcept; /** * \brief Send a PlayerMiscellaneous packet with a Mark location to a player. diff --git a/apps/openmw/mwmp/DedicatedPlayer.cpp b/apps/openmw/mwmp/DedicatedPlayer.cpp index d4fddab80..1333f5b1d 100644 --- a/apps/openmw/mwmp/DedicatedPlayer.cpp +++ b/apps/openmw/mwmp/DedicatedPlayer.cpp @@ -243,6 +243,7 @@ void DedicatedPlayer::setCell() void DedicatedPlayer::setShapeshift() { + MWBase::Environment::get().getWorld()->scaleObject(ptr, scale); MWBase::Environment::get().getMechanicsManager()->setWerewolf(ptr, isWerewolf); } diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index 781c8d7dd..4eb824bde 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -64,6 +64,7 @@ LocalPlayer::LocalPlayer() jailProgressText = ""; jailEndText = ""; + scale = 1; isWerewolf = false; diedSinceArrestAttempt = false; @@ -1266,6 +1267,8 @@ void LocalPlayer::setMapExplored() void LocalPlayer::setShapeshift() { MWWorld::Ptr ptrPlayer = getPlayerPtr(); + + MWBase::Environment::get().getWorld()->scaleObject(ptrPlayer, scale); MWBase::Environment::get().getMechanicsManager()->setWerewolf(ptrPlayer, isWerewolf); } @@ -1553,7 +1556,17 @@ void LocalPlayer::sendBook(const std::string& bookId) getNetworking()->getPlayerPacket(ID_PLAYER_BOOK)->Send(); } -void LocalPlayer::sendShapeshift(bool werewolfState) +void LocalPlayer::sendScale(float newScale) +{ + scale = newScale; + + LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_PLAYER_SHAPESHIFT with scale of %f", scale); + + getNetworking()->getPlayerPacket(ID_PLAYER_SHAPESHIFT)->setPlayer(this); + getNetworking()->getPlayerPacket(ID_PLAYER_SHAPESHIFT)->Send(); +} + +void LocalPlayer::sendWerewolfState(bool werewolfState) { isWerewolf = werewolfState; diff --git a/apps/openmw/mwmp/LocalPlayer.hpp b/apps/openmw/mwmp/LocalPlayer.hpp index 7f92de89b..5efe3ffb5 100644 --- a/apps/openmw/mwmp/LocalPlayer.hpp +++ b/apps/openmw/mwmp/LocalPlayer.hpp @@ -89,7 +89,8 @@ namespace mwmp void sendTopic(const std::string& topic); void sendKill(const std::string& refId, int number); void sendBook(const std::string& bookId); - void sendShapeshift(bool isWerewolf); + void sendScale(float newScale); + void sendWerewolfState(bool isWerewolf); void sendMarkLocation(const ESM::Cell& newMarkCell, const ESM::Position& newMarkPosition); void clearCellStates(); diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 17ae6b304..c3618aa9e 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -1231,7 +1231,7 @@ namespace MWScript When the player's werewolf state changes, send an ID_PLAYER_SHAPESHIFT packet */ if (ptr == MWMechanics::getPlayer()) - mwmp::Main::get().getLocalPlayer()->sendShapeshift(set); + mwmp::Main::get().getLocalPlayer()->sendWerewolfState(set); /* End of tes3mp addition */ diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index ea0531fea..874cbe1b7 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -8,6 +8,8 @@ #include #include "../mwmp/Main.hpp" #include "../mwmp/Networking.hpp" +#include "../mwmp/LocalPlayer.hpp" +#include "../mwmp/PlayerList.hpp" #include "../mwmp/WorldEvent.hpp" /* End of tes3mp addition @@ -57,16 +59,26 @@ namespace MWScript /* Start of tes3mp addition - Send an ID_OBJECT_SCALE every time an object's scale is changed - through a script + Send an ID_PLAYER_SHAPESHIFT every time a player changes + their own scale + + Otherwise, send an ID_OBJECT_SCALE every time an object's + scale is changed through a script */ - if (ptr.isInCell() && (ptr.getCellRef().getScale() != scale)) + if (ptr == MWMechanics::getPlayer()) + mwmp::Main::get().getLocalPlayer()->sendScale(scale); + else if (ptr.isInCell() && (ptr.getCellRef().getScale() != scale)) { - - mwmp::WorldEvent *worldEvent = mwmp::Main::get().getNetworking()->getWorldEvent(); - worldEvent->reset(); - worldEvent->addObjectScale(ptr, scale); - worldEvent->sendObjectScale(); + // Ignore attempts to change another player's scale + if (mwmp::PlayerList::isDedicatedPlayer(ptr)) + return; + else + { + mwmp::WorldEvent *worldEvent = mwmp::Main::get().getNetworking()->getWorldEvent(); + worldEvent->reset(); + worldEvent->addObjectScale(ptr, scale); + worldEvent->sendObjectScale(); + } } /* End of tes3mp addition diff --git a/components/openmw-mp/Base/BasePlayer.hpp b/components/openmw-mp/Base/BasePlayer.hpp index 15939ee00..2865a22f6 100644 --- a/components/openmw-mp/Base/BasePlayer.hpp +++ b/components/openmw-mp/Base/BasePlayer.hpp @@ -283,6 +283,7 @@ namespace mwmp std::string sound; Animation animation; + float scale; bool isWerewolf; std::string creatureModel; bool useCreatureName; diff --git a/components/openmw-mp/Packets/Player/PacketPlayerShapeshift.cpp b/components/openmw-mp/Packets/Player/PacketPlayerShapeshift.cpp index 1e6c06a70..352342ccd 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerShapeshift.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerShapeshift.cpp @@ -12,5 +12,6 @@ void PacketPlayerShapeshift::Packet(RakNet::BitStream *bs, bool send) { PlayerPacket::Packet(bs, send); + RW(player->scale, send); RW(player->isWerewolf, send); } From cc0f7d19dcb4e11dbbdcf6df86785a13797b6f99 Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Fri, 2 Feb 2018 12:09:25 -0600 Subject: [PATCH 11/16] Removing "Use these settings at your own risk" --- files/ui/advancedpage.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index 39bb58758..34fa8cf24 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -14,7 +14,7 @@ - <html><head/><body><p>These settings are not available in the game. <span style=" font-weight:600;">Use at your own risk!</span></p></body></html> + <html><head/><body><p>These settings are not available in the game.</p></body></html> From a78acbac8599005b8ab5d2ef6818936faa6d2d1b Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Sun, 4 Feb 2018 13:38:11 -0600 Subject: [PATCH 12/16] Changing page description to address Zini's concerns --- files/ui/advancedpage.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index 34fa8cf24..8a0795d34 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -12,9 +12,9 @@ - + - <html><head/><body><p>These settings are not available in the game.</p></body></html> + <html><head/><body><p>This temporary page contains new settings that will be available in-game in a post-1.0 release of OpenMW.</p></body></html> From 74765b3ace5648db6f21b6959f3e7e746a49f72b Mon Sep 17 00:00:00 2001 From: David Cernat Date: Tue, 6 Feb 2018 06:36:46 +0200 Subject: [PATCH 13/16] [General] Implement selected spell sync as part of PlayerMiscellaneous --- apps/openmw-mp/Script/Functions/Mechanics.cpp | 27 ++++++++++++++++ apps/openmw-mp/Script/Functions/Mechanics.hpp | 31 +++++++++++++++++++ apps/openmw/mwgui/quickkeysmenu.cpp | 13 +++++++- apps/openmw/mwgui/spellwindow.cpp | 10 ++++++ apps/openmw/mwmp/LocalPlayer.cpp | 24 ++++++++++++++ apps/openmw/mwmp/LocalPlayer.hpp | 2 ++ .../player/ProcessorPlayerMiscellaneous.hpp | 2 ++ components/openmw-mp/Base/BasePlayer.hpp | 3 +- .../Player/PacketPlayerMiscellaneous.cpp | 2 ++ 9 files changed, 112 insertions(+), 2 deletions(-) diff --git a/apps/openmw-mp/Script/Functions/Mechanics.cpp b/apps/openmw-mp/Script/Functions/Mechanics.cpp index b1a3ce413..d4ddcef87 100644 --- a/apps/openmw-mp/Script/Functions/Mechanics.cpp +++ b/apps/openmw-mp/Script/Functions/Mechanics.cpp @@ -68,6 +68,14 @@ double MechanicsFunctions::GetMarkRotZ(unsigned short pid) noexcept return player->markPosition.rot[2]; } +const char *MechanicsFunctions::GetSelectedSpellId(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + return player->selectedSpellId.c_str(); +} + double MechanicsFunctions::GetScale(unsigned short pid) noexcept { Player *player; @@ -111,6 +119,14 @@ void MechanicsFunctions::SetMarkRot(unsigned short pid, double x, double z) noex player->markPosition.rot[2] = z; } +void MechanicsFunctions::SetSelectedSpellId(unsigned short pid, const char *spellId) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + player->selectedSpellId = spellId; +} + void MechanicsFunctions::SetScale(unsigned short pid, double scale) noexcept { Player *player; @@ -138,6 +154,17 @@ void MechanicsFunctions::SendMarkLocation(unsigned short pid) mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_MISCELLANEOUS)->Send(false); } +void MechanicsFunctions::SendSelectedSpell(unsigned short pid) +{ + Player *player; + GET_PLAYER(pid, player, ); + + player->miscellaneousChangeType = mwmp::MISCELLANEOUS_CHANGE_TYPE::SELECTED_SPELL; + + mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_MISCELLANEOUS)->setPlayer(player); + mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_MISCELLANEOUS)->Send(false); +} + void MechanicsFunctions::SendShapeshift(unsigned short pid) { Player *player; diff --git a/apps/openmw-mp/Script/Functions/Mechanics.hpp b/apps/openmw-mp/Script/Functions/Mechanics.hpp index 7db879f0f..f0e3e13d3 100644 --- a/apps/openmw-mp/Script/Functions/Mechanics.hpp +++ b/apps/openmw-mp/Script/Functions/Mechanics.hpp @@ -12,6 +12,7 @@ {"GetMarkPosZ", MechanicsFunctions::GetMarkPosZ},\ {"GetMarkRotX", MechanicsFunctions::GetMarkRotX},\ {"GetMarkRotZ", MechanicsFunctions::GetMarkRotZ},\ + {"GetSelectedSpellId", MechanicsFunctions::GetSelectedSpellId},\ \ {"GetScale", MechanicsFunctions::GetScale},\ {"IsWerewolf", MechanicsFunctions::IsWerewolf},\ @@ -19,11 +20,13 @@ {"SetMarkCell", MechanicsFunctions::SetMarkCell},\ {"SetMarkPos", MechanicsFunctions::SetMarkPos},\ {"SetMarkRot", MechanicsFunctions::SetMarkRot},\ + {"SetSelectedSpellId", MechanicsFunctions::SetSelectedSpellId},\ \ {"SetScale", MechanicsFunctions::SetScale},\ {"SetWerewolfState", MechanicsFunctions::SetWerewolfState},\ \ {"SendMarkLocation", MechanicsFunctions::SendMarkLocation},\ + {"SendSelectedSpell", MechanicsFunctions::SendSelectedSpell},\ {"SendShapeshift", MechanicsFunctions::SendShapeshift},\ \ {"Jail", MechanicsFunctions::Jail},\ @@ -89,6 +92,14 @@ public: */ static double GetMarkRotZ(unsigned short pid) noexcept; + /** + * \brief Get the ID of a player's selected spell. + * + * \param pid The player ID. + * \return The spell ID. + */ + static const char *GetSelectedSpellId(unsigned short pid) noexcept; + /** * \brief Get the scale of a player. * @@ -149,6 +160,18 @@ public: */ static void SetMarkRot(unsigned short pid, double x, double z) noexcept; + /** + * \brief Set the ID of a player's selected spell. + * + * This changes the spell ID recorded for that player in the server memory, but does not by itself + * send a packet. + * + * \param pid The player ID. + * \param spellId The spell ID. + * \return void + */ + static void SetSelectedSpellId(unsigned short pid, const char *spellId) noexcept; + /** * \brief Set the scale of a player. * @@ -181,6 +204,14 @@ public: */ static void SendMarkLocation(unsigned short pid); + /** + * \brief Send a PlayerMiscellaneous packet with a selected spell ID to a player. + * + * \param pid The player ID. + * \return void + */ + static void SendSelectedSpell(unsigned short pid); + /** * \brief Send a PlayerShapeshift packet about a player. * diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index aa2726799..61b064c38 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -232,7 +232,8 @@ namespace MWGui /* Start of tes3mp addition - Send a PLAYER_QUICKKEYS packet whenever a key is assigned to an item + Send a PlayerQuickKeys packet whenever a key is assigned to an item + by a player, not by a packet received from the server */ if (!mwmp::Main::get().getLocalPlayer()->isReceivingQuickKeys) mwmp::Main::get().getLocalPlayer()->sendQuickKey(mSelectedIndex, Type_Item, item.getCellRef().getRefId()); @@ -407,6 +408,16 @@ namespace MWGui store.setSelectedEnchantItem(store.end()); MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player))); MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell); + + /* + Start of tes3mp addition + + Send a PlayerMiscellaneous packet with the player's new selected spell + */ + mwmp::Main::get().getLocalPlayer()->sendSelectedSpell(spellId); + /* + End of tes3mp addition + */ } else if (type == Type_Item) { diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 1f9e65624..bc35929a7 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -186,6 +186,16 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player))); updateSpells(); + + /* + Start of tes3mp addition + + Send a PlayerMiscellaneous packet with the player's new selected spell + */ + mwmp::Main::get().getLocalPlayer()->sendSelectedSpell(spellId); + /* + End of tes3mp addition + */ } void SpellWindow::onDeleteSpellAccept() diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index 4eb824bde..4265b5c57 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -19,6 +19,7 @@ #include "../mwmechanics/aitravel.hpp" #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/mechanicsmanagerimp.hpp" +#include "../mwmechanics/spellcasting.hpp" #include "../mwscript/scriptmanagerimp.hpp" @@ -1280,6 +1281,20 @@ void LocalPlayer::setMarkLocation() MWBase::Environment::get().getWorld()->getPlayer().markPosition(ptrCellStore, markPosition); } +void LocalPlayer::setSelectedSpell() +{ + MWWorld::Ptr ptrPlayer = getPlayerPtr(); + + MWMechanics::CreatureStats& stats = ptrPlayer.getClass().getCreatureStats(ptrPlayer); + MWMechanics::Spells& spells = stats.getSpells(); + + if (!spells.hasSpell(selectedSpellId)) + return; + + MWBase::Environment::get().getWindowManager()->setSelectedSpell(selectedSpellId, + int(MWMechanics::getSpellSuccessChance(selectedSpellId, ptrPlayer))); +} + void LocalPlayer::sendClass() { MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -1586,6 +1601,15 @@ void LocalPlayer::sendMarkLocation(const ESM::Cell& newMarkCell, const ESM::Posi getNetworking()->getPlayerPacket(ID_PLAYER_MISCELLANEOUS)->Send(); } +void LocalPlayer::sendSelectedSpell(const std::string& newSelectedSpellId) +{ + miscellaneousChangeType = mwmp::MISCELLANEOUS_CHANGE_TYPE::SELECTED_SPELL; + selectedSpellId = newSelectedSpellId; + + getNetworking()->getPlayerPacket(ID_PLAYER_MISCELLANEOUS)->setPlayer(this); + getNetworking()->getPlayerPacket(ID_PLAYER_MISCELLANEOUS)->Send(); +} + void LocalPlayer::clearCellStates() { cellStateChanges.cellStates.clear(); diff --git a/apps/openmw/mwmp/LocalPlayer.hpp b/apps/openmw/mwmp/LocalPlayer.hpp index 5efe3ffb5..bd475977d 100644 --- a/apps/openmw/mwmp/LocalPlayer.hpp +++ b/apps/openmw/mwmp/LocalPlayer.hpp @@ -71,6 +71,7 @@ namespace mwmp void setMapExplored(); void setShapeshift(); void setMarkLocation(); + void setSelectedSpell(); void sendClass(); void sendInventory(); @@ -92,6 +93,7 @@ namespace mwmp void sendScale(float newScale); void sendWerewolfState(bool isWerewolf); void sendMarkLocation(const ESM::Cell& newMarkCell, const ESM::Position& newMarkPosition); + void sendSelectedSpell(const std::string& newSelectedSpellId); void clearCellStates(); void clearCurrentContainer(); diff --git a/apps/openmw/mwmp/processors/player/ProcessorPlayerMiscellaneous.hpp b/apps/openmw/mwmp/processors/player/ProcessorPlayerMiscellaneous.hpp index 4dcc8a5be..f23d1af13 100644 --- a/apps/openmw/mwmp/processors/player/ProcessorPlayerMiscellaneous.hpp +++ b/apps/openmw/mwmp/processors/player/ProcessorPlayerMiscellaneous.hpp @@ -26,6 +26,8 @@ namespace mwmp if (player->miscellaneousChangeType == mwmp::MISCELLANEOUS_CHANGE_TYPE::MARK_LOCATION) localPlayer.setMarkLocation(); + else if (player->miscellaneousChangeType == mwmp::MISCELLANEOUS_CHANGE_TYPE::SELECTED_SPELL) + localPlayer.setSelectedSpell(); } } }; diff --git a/components/openmw-mp/Base/BasePlayer.hpp b/components/openmw-mp/Base/BasePlayer.hpp index 2865a22f6..1a024c6a9 100644 --- a/components/openmw-mp/Base/BasePlayer.hpp +++ b/components/openmw-mp/Base/BasePlayer.hpp @@ -303,10 +303,11 @@ namespace mwmp ESM::Cell markCell; ESM::Position markPosition; + std::string selectedSpellId; - bool diedSinceArrestAttempt; bool isReceivingQuickKeys; bool isPlayingAnimation; + bool diedSinceArrestAttempt; }; } diff --git a/components/openmw-mp/Packets/Player/PacketPlayerMiscellaneous.cpp b/components/openmw-mp/Packets/Player/PacketPlayerMiscellaneous.cpp index cffb6a446..8aca6b52f 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerMiscellaneous.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerMiscellaneous.cpp @@ -23,4 +23,6 @@ void PacketPlayerMiscellaneous::Packet(RakNet::BitStream *bs, bool send) RW(player->markPosition.rot[0], send); RW(player->markPosition.rot[2], send); } + else if (player->miscellaneousChangeType == mwmp::MISCELLANEOUS_CHANGE_TYPE::SELECTED_SPELL) + RW(player->selectedSpellId, send, 1); } From f626a7fcc74c9d91e7843dcd290c43288058bb83 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 10 Feb 2018 17:58:30 +0400 Subject: [PATCH 14/16] Take in account PC rank during disposition calculation (bug #4322) --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index b51b55421..bd5fa1b11 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -566,9 +566,16 @@ namespace MWMechanics { std::string itFaction = playerFactionIt->first; + // Ignore the faction, if a player was expelled from it. + if (playerStats.getExpelled(itFaction)) + continue; + int itReaction = MWBase::Environment::get().getDialogueManager()->getFactionReaction(npcFaction, itFaction); if (playerFactionIt == playerStats.getFactionRanks().begin() || itReaction < reaction) + { reaction = static_cast(itReaction); + rank = playerFactionIt->second; + } } } else From f28024b54151b662d9ae3fadade0187492766698 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sat, 10 Feb 2018 23:11:03 +0000 Subject: [PATCH 15/16] Don't use Activate and Move keys for GUI navigation if bound to mouse buttons (Fixes #4225, Fixes #4320) --- apps/openmw/mwinput/inputmanagerimp.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 400dd7213..3b4ff25a0 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -174,10 +174,25 @@ namespace MWInput } } + bool isLeftOrRightButton(int action, ICS::InputControlSystem* ics, int deviceId, bool joystick) + { + int mouseBinding = ics->getMouseButtonBinding(ics->getControl(action), ICS::Control::INCREASE); + if (mouseBinding != ICS_MAX_DEVICE_BUTTONS) + return true; + int buttonBinding = ics->getJoystickButtonBinding(ics->getControl(action), deviceId, ICS::Control::INCREASE); + if (joystick && (buttonBinding == 0 || buttonBinding == 1)) + return true; + return false; + } + void InputManager::handleGuiArrowKey(int action) { if (SDL_IsTextInputActive()) return; + + if (isLeftOrRightButton(action, mInputBinder, mFakeDeviceID, mJoystickLastUsed)) + return; + MyGUI::KeyCode key; switch (action) { @@ -1115,7 +1130,7 @@ namespace MWInput { if (MWBase::Environment::get().getWindowManager()->isGuiMode()) { - if (!SDL_IsTextInputActive()) + if (!SDL_IsTextInputActive() && !isLeftOrRightButton(A_Activate, mInputBinder, mFakeDeviceID, mJoystickLastUsed)) MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Return, 0); } else if (mControlSwitch["playercontrols"]) From 899d464b0df6811d0a0c544d30da31807b1fdc8a Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sat, 10 Feb 2018 23:14:41 +0000 Subject: [PATCH 16/16] Cap the rain emitter's frame time (Fixes #4314) --- apps/openmw/mwrender/sky.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 6c599fc3f..2e4329f69 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -1203,6 +1203,18 @@ void SkyManager::create() mCreated = true; } +class RainCounter : public osgParticle::ConstantRateCounter +{ +public: + virtual int numParticlesToCreate(double dt) const + { + // limit dt to avoid large particle emissions if there are jumps in the simulation time + // 0.2 seconds is the same cap as used in Engine's frame loop + dt = std::min(dt, 0.2); + return ConstantRateCounter::numParticlesToCreate(dt); + } +}; + class RainShooter : public osgParticle::Shooter { public: @@ -1473,7 +1485,7 @@ void SkyManager::createRain() placer->setZRange(300, 300); emitter->setPlacer(placer); - osg::ref_ptr counter (new osgParticle::ConstantRateCounter); + osg::ref_ptr counter (new RainCounter); counter->setNumberOfParticlesPerSecondToCreate(600.0); emitter->setCounter(counter);