mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-01 15:09:41 +00:00
Add OpenMW commits up to 2 May 2019
# Conflicts: # CMakeLists.txt # apps/openmw/mwmechanics/mechanicsmanagerimp.cpp # apps/openmw/mwscript/statsextensions.cpp
This commit is contained in:
commit
5181c601c0
178 changed files with 3110 additions and 2250 deletions
|
@ -126,6 +126,7 @@ Programmers
|
|||
Michael Hogan (Xethik)
|
||||
Michael Mc Donnell
|
||||
Michael Papageorgiou (werdanith)
|
||||
Michael Stopa (Stomy)
|
||||
Michał Ściubidło (mike-sc)
|
||||
Michał Bień (Glorf)
|
||||
Michał Moroz (dragonee)
|
||||
|
@ -135,6 +136,7 @@ Programmers
|
|||
Mitchell Schwitzer (schwitzerm)
|
||||
naclander
|
||||
Narmo
|
||||
Nat Meo (Utopium)
|
||||
Nathan Jeffords (blunted2night)
|
||||
NeveHanter
|
||||
Nialsy
|
||||
|
@ -182,7 +184,6 @@ Programmers
|
|||
Stanislaw Halik (sthalik)
|
||||
Star-Demon
|
||||
stil-t
|
||||
Stomy
|
||||
svaante
|
||||
Sylvain Thesnieres (Garvek)
|
||||
t6
|
||||
|
|
47
CHANGELOG.md
47
CHANGELOG.md
|
@ -6,25 +6,32 @@
|
|||
Bug #3006: 'else if' operator breaks script compilation
|
||||
Bug #3109: SetPos/Position handles actors differently
|
||||
Bug #3282: Unintended behaviour when assigning F3 and Windows keys
|
||||
Bug #3623: Fix HiDPI on Windows
|
||||
Bug #3623: Display scaling breaks mouse recognition
|
||||
Bug #3725: Using script function in a non-conditional expression breaks script compilation
|
||||
Bug #3733: Normal maps are inverted on mirrored UVs
|
||||
Bug #3765: DisableTeleporting makes Mark/Recall/Intervention effects undetectable
|
||||
Bug #3778: [Mod] Improved Thrown Weapon Projectiles - weapons have wrong transformation during throw animation
|
||||
Bug #3812: Wrong multiline tooltips width when word-wrapping is enabled
|
||||
Bug #4329: Removed birthsign abilities are restored after reloading the save
|
||||
Bug #4383: Bow model obscures crosshair when arrow is drawn
|
||||
Bug #4384: Resist Normal Weapons only checks ammunition for ranged weapons
|
||||
Bug #4411: Reloading a saved game while falling prevents damage in some cases
|
||||
Bug #4540: Rain delay when exiting water
|
||||
Bug #4701: PrisonMarker record is not hardcoded like other markers
|
||||
Bug #4703: Editor: it's possible to preview levelled list records
|
||||
Bug #4705: Editor: unable to open exterior cell views from Instances table
|
||||
Bug #4714: Crash upon game load in the repair menu while the "Your repair failed!" message is active
|
||||
Bug #4715: "Cannot get class of an empty object" exception after pressing ESC in the dialogue mode
|
||||
Bug #4720: Inventory avatar has shield with two-handed weapon during [un]equipping animation
|
||||
Bug #4723: ResetActors command works incorrectly
|
||||
Bug #4745: Editor: Interior cell lighting field values are not displayed as colors
|
||||
Bug #4736: LandTexture records overrides do not work
|
||||
Bug #4745: Editor: Interior cell lighting field values are not displayed as colors
|
||||
Bug #4746: Non-solid player can't run or sneak
|
||||
Bug #4747: Bones are not read from X.NIF file for NPC animation
|
||||
Bug #4748: Editor: Cloned, moved, added instances re-use RefNum indices
|
||||
Bug #4750: Sneaking doesn't work in first person view if the player is in attack ready state
|
||||
Bug #4756: Animation issues with VAOs
|
||||
Bug #4757: Content selector: files can be cleared when there aren't any files to clear
|
||||
Bug #4768: Fallback numerical value recovery chokes on invalid arguments
|
||||
Bug #4775: Slowfall effect resets player jumping flag
|
||||
Bug #4778: Interiors of Illusion puzzle in Sotha Sil Expanded mod is broken
|
||||
|
@ -32,15 +39,19 @@
|
|||
Bug #4800: Standing collisions are not updated immediately when an object is teleported without a cell change
|
||||
Bug #4803: Stray special characters before begin statement break script compilation
|
||||
Bug #4804: Particle system with the "Has Sizes = false" causes an exception
|
||||
Bug #4805: NPC movement speed calculations do not take race Weight into account
|
||||
Bug #4810: Raki creature broken in OpenMW
|
||||
Bug #4813: Creatures with known file but no "Sound Gen Creature" assigned use default sounds
|
||||
Bug #4815: "Finished" journal entry with lower index doesn't close journal, SetJournalIndex closes journal
|
||||
Bug #4820: Spell absorption is broken
|
||||
Bug #4823: Jail progress bar works incorrectly
|
||||
Bug #4826: Uninitialized memory in unit test
|
||||
Bug #4827: NiUVController is handled incorrectly
|
||||
Bug #4828: Potion looping effects VFX are not shown for NPCs
|
||||
Bug #4837: CTD when a mesh with NiLODNode root node with particles is loaded
|
||||
Bug #4841: Russian localization ignores implicit keywords
|
||||
Bug #4841: Russian localization ignores implicit keywords
|
||||
Bug #4847: Idle animation reset oddities
|
||||
Bug #4851: No shadows since switch to OSG
|
||||
Bug #4860: Actors outside of processing range visible for one frame after spawning
|
||||
Bug #4867: Arbitrary text after local variable declarations breaks script compilation
|
||||
Bug #4876: AI ratings handling inconsistencies
|
||||
|
@ -49,15 +60,39 @@
|
|||
Bug #4896: Title screen music doesn't loop
|
||||
Bug #4911: Editor: QOpenGLContext::swapBuffers() warning with Qt5
|
||||
Bug #4916: Specular power (shininess) material parameter is ignored when shaders are used.
|
||||
Bug #4918: Abilities don't play looping VFX when they're initially applied
|
||||
Bug #4920: Combat AI uses incorrect invisibility check
|
||||
Bug #4922: Werewolves can not attack if the transformation happens during attack
|
||||
Bug #4927: Spell effect having both a skill and an attribute assigned is a fatal error
|
||||
Bug #4932: Invalid records matching when loading save with edited plugin
|
||||
Bug #4933: Field of View not equal with Morrowind
|
||||
Bug #4938: Strings from subrecords with actually empty headers can't be empty
|
||||
Bug #4942: Hand-to-Hand attack type is chosen randomly when "always use best attack" is turned off
|
||||
Bug #4945: Poor random magic magnitude distribution
|
||||
Bug #4947: Player character doesn't use lip animation
|
||||
Bug #4948: Footstep sounds while levitating on ground level
|
||||
Bug #4963: Enchant skill progress is incorrect
|
||||
Bug #4964: Multiple effect spell projectile sounds play louder than vanilla
|
||||
Bug #4965: Global light attenuation settings setup is lacking
|
||||
Bug #4969: "Miss" sound plays for any actor
|
||||
Bug #4971: OpenMW-CS: Make rotations display as degrees instead of radians
|
||||
Bug #4972: Player is able to use quickkeys while disableplayerfighting is active
|
||||
Bug #4979: AiTravel maximum range depends on "actors processing range" setting
|
||||
Bug #4980: Drowning mechanics is applied for actors indifferently from distance to player
|
||||
Bug #4984: "Friendly hits" feature should be used only for player's followers
|
||||
Bug #4989: Object dimension-dependent VFX scaling behavior is inconsistent
|
||||
Bug #4990: Dead bodies prevent you from hitting
|
||||
Bug #5004: Werewolves shield their eyes during storm
|
||||
Feature #1774: Handle AvoidNode
|
||||
Feature #2229: Improve pathfinding AI
|
||||
Feature #3025: Analogue gamepad movement controls
|
||||
Feature #3442: Default values for fallbacks from ini file
|
||||
Feature #3610: Option to invert X axis
|
||||
Feature #3893: Implicit target for "set" function in console
|
||||
Feature #3980: In-game option to disable controller
|
||||
Feature #4001: Toggle sneak controller shortcut
|
||||
Feature #4209: Editor: Faction rank sub-table
|
||||
Feature #4360: Improve default controller bindings
|
||||
Feature #4673: Weapon sheathing
|
||||
Feature #4675: Support for NiRollController
|
||||
Feature #4730: Native animated containers support
|
||||
|
@ -66,8 +101,14 @@
|
|||
Feature #4859: Make water reflections more configurable
|
||||
Feature #4887: Add openmw command option to set initial random seed
|
||||
Feature #4890: Make Distant Terrain configurable
|
||||
Feature #4958: Support eight blood types
|
||||
Feature #4962: Add casting animations for magic items
|
||||
Feature #4968: Scalable UI widget skins
|
||||
Feature #4994: Persistent pinnable windows hiding
|
||||
Feature #5000: Compressed BSA format support
|
||||
Task #4686: Upgrade media decoder to a more current FFmpeg API
|
||||
Task #4695: Optimize Distant Terrain memory consumption
|
||||
Task #4721: Add NMake support to the Windows prebuild script
|
||||
|
||||
0.45.0
|
||||
------
|
||||
|
|
109
CHANGELOG_PR.md
Normal file
109
CHANGELOG_PR.md
Normal file
|
@ -0,0 +1,109 @@
|
|||
*** PLEASE PUT YOUR ISSUE DESCRIPTION FOR DUMMIES HERE FOR REVIEW ***
|
||||
|
||||
- I'm just a placeholder description (#1337)
|
||||
- I'm also just a placeholder description, but I'm a more recent one (#42)
|
||||
|
||||
***
|
||||
|
||||
0.46.0
|
||||
------
|
||||
|
||||
The OpenMW team is proud to announce the release of version 0.46.0! Grab it from our Downloads Page for all operating systems. ***short summary: shadows, recastnavigation, etc.***
|
||||
|
||||
Check out the release video (***add link***) and the OpenMW-CS release video (***add link***) by the ***add flattering adjective*** Atahualpa, and see below for the full list of changes.
|
||||
|
||||
Known Issues:
|
||||
- There's currently no way to redirect the logging output to the command prompt on Windows Release builds -- this will be resolved in version 0.46.0
|
||||
- To use generic Linux binaries, Qt4 and libpng12 must be installed on your system
|
||||
- On macOS, launching OpenMW from OpenMW-CS requires OpenMW.app and OpenMW-CS.app to be siblings
|
||||
|
||||
New Features:
|
||||
- NIF files which contain an "AvoidNode" are ignored by the pathfinding algorithm (#1724)
|
||||
- Navmeshes are used for AI pathfinding which should resolve most related issues (#2229)
|
||||
- Movement input from gamepad joysticks is transformed into analogue values (#3025)
|
||||
- Sane default values for openmw.cfg file to overcome the original morrowind.ini file (#3442)
|
||||
- Option to invert x-axis for controllers (#3610)
|
||||
- Local variables of objects selected in the console can now be directly read and set without explicitly stating the object (#3893)
|
||||
- In-game option to enable or disable controllers (#3980)
|
||||
- Sneak mode can be toggled using a controller (#4001)
|
||||
- Controllers use original engine's default key bindings (#4360)
|
||||
- Support for sheathing animations, including weapon holstering, scabbards (except for throwing weapons), and quivers for projectiles (#4673)
|
||||
- Support for "NiRollController" in NIF files to ensure correct rotation of models in "Weapon Sheathing" mod (#4675)
|
||||
- Support for native animated containers (#4730)
|
||||
- Support for VAO ("Vertex Array Objects") from OSG 3.5.6 or later (#4756)
|
||||
- Support for "NiSwitchNode" in NIF files to allow future implementation of native support for extended features like harvestable plants or glowing - windows (#4812)
|
||||
- Native support for glowing windows (and other daytime-dependent meshes) by adding internal day-night-mode switch (#4836)
|
||||
- Shadows (#4851)
|
||||
- More configuration options for in-game water reflections (#4859)
|
||||
- Command line option to specify a random seed to be used by the game's random-number generator ("RNG") for debugging purposes (#4887)
|
||||
- Configuration options for distant terrain to adjust quality and performance impact (#4890)
|
||||
|
||||
New Editor Features:
|
||||
- "Faction Ranks" table for "Faction" records (#4209)
|
||||
|
||||
Bug Fixes:
|
||||
- Scripted Items cannot be stacked anymore to avoid multiple script execution (#2969)
|
||||
- Stray text after an "else" statement is now ignored, like in the original engine, to handle mods which erroneously use "else if" statements (#3006)
|
||||
- "SetPos" and "SetPosition" commands now more closely replicate the original engine's behaviour (#3109)
|
||||
- "Reserved keys [F3], [F4], [F10], and [F11] cannot be assigned to in-game controls anymore (#3282)
|
||||
- Windows: Reserved [Windows] key cannot be assigned to in-game controls anymore (#3282)"
|
||||
- Windows: Windows-internal display scaling no longer breaks main menu (#3623)
|
||||
- Normal maps on mirrored UVs are no longer inverted (#3733)
|
||||
- Teleporting attempts are now also detected if teleporting is disabled to ensure compatibility with certain mods (#3765)
|
||||
- Throwing weapons are now correctly rotated during throwing animation when using the "Improved Thrown Weapon Projectiles" mod (#3778)
|
||||
- Birthsign abilities are no longer restored upon loading to ensure mod compatibility (#4329)
|
||||
- Player character's model is no longer scaled in first-person mode to prevent issues with arrows obscuring the crosshair (#4383)
|
||||
- Optional: Ranged attacks now bypass normal weapon resistance or weakness if ammunition and/or bow are appropriate (#4384)
|
||||
- Fall damage is now also applied when first reloading a savegame and when your character is near the ground in the loaded game (#4411)
|
||||
- Rain drops are no longer delayed when your character emerges from water (#4540)
|
||||
- ESM record for prison markers is now hardcoded like, e.g., door markers or temple markers (#4701)
|
||||
- Loading a savegame which includes active messages no longer crashes the game (#4714)
|
||||
- An empty pointer actor no longer throws an exception upon exiting the dialogue menu (#4715)
|
||||
- Inventory paper doll no longer simultaneously displays shield and two-handed weapon during drawing and holstering animations (#4720)
|
||||
- "Reset actors" command ("ra") no longer tries to reset actors originating from inactive cells, e.g., followers (#4723)
|
||||
- "Reset actors" command ("ra") now traces reset actors to the ground and also resets fall damage (#4723)"
|
||||
- Land texture records can now be overwritten by content files to create mods like "Winter in Morrowind" (#4736)
|
||||
- Disabling collision no longer forces your character to walking speed, but also allows them to run or sneak (#4746)
|
||||
- NPCs now also use the skeleton associated with their specified model, not only the animations (#4747)
|
||||
- Sneaking und swimming idle animations are no longer interrupted if your character is in attack-ready state in first-person view (#4750)
|
||||
- Numerical fallback values with invalid values (e.g., stray text) in the openmw.cfg file no longer crash or break the game (#4768)
|
||||
- Character's "jumping" flag is no longer unnecessarily reset to ensure compatibility with certain mods, e.g., "Sotha Sil Expanded" (#4775)
|
||||
- Calling "GetSpellEffects", "GetEffect", or "GetSpell" function on non-actor objects now returns 0, fixing issues with "Sotha Sil Expanded" - (#4778)
|
||||
- AI values for actors without AIDT ("AI Data") subrecord are now set to zero upon loading instead of filling in "random" values (#4778)
|
||||
- Running and sneaking are now also considered in in-game checks when your character is in midair, fixing an issue with the "Reign of Fire" mod - (#4797)
|
||||
- Collision checks are now immediately updated when an object is moved to ensure compatibility with "Sotha Sil Expanded" (#4800)
|
||||
- Stray special characters before the "begin" statement of a script are now ignored to ensure, once again, compatibility with "Sotha Sil Expanded" - (#4803)
|
||||
- Particle nodes with an empty "sizes" array are now correctly loaded and no longer cause an exception (#4804)
|
||||
- Handling of "root bone" and "bip01" nodes in NIF files now matches the original engine's behaviour to ensure compatibility with "Skyrim: Home of - the Nords" (#4810)
|
||||
- Creatures without specified sound files now fallback to the sounds of the first creature sharing the same model (#4813)
|
||||
- "Journal" command now also closes a quest when the specified "finish quest" entry has a lower value than the current one for that quest (#4815)
|
||||
- Spell effects are no longer applied when a spell is successfully absorbed (#4820)
|
||||
- World state is no longer updated for every in-game hour your character is in jail but only once, which should significantly reduce loading times - (#4823)
|
||||
- "NiUVController" in NIF files now only affects textures which use the specified "UV Set" index, usually 0; ensures compatibility with "Glow in the Dahrk" (#4827)
|
||||
- Visual effects ("VFX") for magic effects are now played immediately after the effect is triggered to not accidentally skip the VFX, e.g., when actors drink potions in battle (#4828)
|
||||
- Meshes with "NiLODNode" or "NiSwitchNode" no longer cause crashes when they contain particles (#4837)
|
||||
- Localisations can now make use of implicit keywords to create hyperlinks in dialogue text (#4841)
|
||||
- Actors outside of the processing range no longer appear for one frame when they are spawned (#4860)
|
||||
- Stray text after a local-variable declaration is now ignored to ensure mod compatibility (#4867)
|
||||
- Range and default values of AI data fields now match the original engine's ones (#4876)
|
||||
- "Startup" scripts are now always run once upon starting OpenMW (#4877)
|
||||
- Stray explicit reference calls for global variables are now ignored to ensure mod compatibility, e.g., with "Sotha Sil Expanded" (#4888)
|
||||
- Title screen music now loops (#4896)
|
||||
- "Specular power" is no longer hardcoded but uses the specified value in the shader code (#4916)
|
||||
- Werewolves can now also attack if their transformation happened during an attack move (#4922)
|
||||
- Plug-ins with valid empty subrecords are now correctly loaded, which fixes issues with the "DC - Return of Great House Dagoth" mod (#4938)
|
||||
- Hand-to-hand attacks are now movement-based when the "always use best attack" option is turned off, like in the original engine (#4942)
|
||||
|
||||
Editor Bug Fixes:
|
||||
- Certain numerical fields now only accept unsigned 8-bit integers to avoid overflows (#2987)
|
||||
- Preview option is now disabled for levelled lists (#4703)
|
||||
- Opening the "Scene" view from the "Instances" table now also works for exterior cells (#4705)
|
||||
- Colour fields in interior-cell records now also use the colour picker widget (#4745)
|
||||
- Cloned, added, or moved instances no longer disappear at load-time (#4748)
|
||||
- "Clear" function in the content selector no longer tries to execute a "Remove" action on an empty file list (#4757)
|
||||
- Engine no longer tries to swap buffers of windows which weren't exposed to Qt's window management system (#4911)
|
||||
|
||||
Miscellaneous:
|
||||
- Upgraded to FFMPEG3 for media decoding (#4686)
|
||||
- Optimised terrain code to drastically increase performance with distant terrain enabled (#4695)
|
||||
- Windows: Added support for NMake to the prebuild script (#4721)
|
|
@ -19,7 +19,7 @@ DATE=$(date +'%d%m%Y')
|
|||
SHORT_COMMIT=$(git rev-parse --short "${TRAVIS_COMMIT}")
|
||||
TARGET_FILENAME="OpenMW-${DATE}-${SHORT_COMMIT}.dmg"
|
||||
|
||||
if ! ssh -p "$OSX_DEPLOY_PORT" -i "$SSH_KEY_PATH" "$OSX_DEPLOY_HOST" sh -c "ls \"$REMOTE_PATH\"" | grep "$SHORT_COMMIT" > /dev/null; then
|
||||
if ! ssh -p "$OSX_DEPLOY_PORT" -i "$SSH_KEY_PATH" "$OSX_DEPLOY_HOST" "ls \"$REMOTE_PATH\"" | grep "$SHORT_COMMIT" > /dev/null; then
|
||||
scp -P "$OSX_DEPLOY_PORT" -i "$SSH_KEY_PATH" ./*.dmg "$OSX_DEPLOY_HOST:$REMOTE_PATH/$TARGET_FILENAME"
|
||||
else
|
||||
echo "An existing nightly build for commit ${SHORT_COMMIT} has been found, skipping upload."
|
||||
|
|
|
@ -311,7 +311,7 @@ IF(BUILD_OPENMW OR BUILD_OPENCS)
|
|||
set(REQUIRED_BULLET_VERSION 283) # but for build testing, 283 is fine
|
||||
endif()
|
||||
|
||||
find_package(MyGUI 3.2.1 REQUIRED)
|
||||
find_package(MyGUI 3.2.2 REQUIRED)
|
||||
find_package(SDL2 REQUIRED)
|
||||
find_package(OpenAL REQUIRED)
|
||||
find_package(Bullet ${REQUIRED_BULLET_VERSION} REQUIRED COMPONENTS BulletCollision LinearMath)
|
||||
|
@ -429,7 +429,7 @@ endif()
|
|||
# CXX Compiler settings
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wundef -Wno-unused-parameter -pedantic -Wno-long-long")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wundef -Wno-unused-parameter -std=c++14 -pedantic -Wno-long-long")
|
||||
add_definitions( -DBOOST_NO_CXX11_SCOPED_ENUMS=ON )
|
||||
|
||||
if (APPLE)
|
||||
|
|
|
@ -704,29 +704,25 @@ std::string creatureFlags(int flags)
|
|||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::Creature::None) properties += "All ";
|
||||
if (flags & ESM::Creature::Base) properties += "Base ";
|
||||
if (flags & ESM::Creature::Walks) properties += "Walks ";
|
||||
if (flags & ESM::Creature::Swims) properties += "Swims ";
|
||||
if (flags & ESM::Creature::Flies) properties += "Flies ";
|
||||
if (flags & ESM::Creature::Bipedal) properties += "Bipedal ";
|
||||
if (flags & ESM::Creature::Respawn) properties += "Respawn ";
|
||||
if (flags & ESM::Creature::Weapon) properties += "Weapon ";
|
||||
if (flags & ESM::Creature::Skeleton) properties += "Skeleton ";
|
||||
if (flags & ESM::Creature::Metal) properties += "Metal ";
|
||||
if (flags & ESM::Creature::Essential) properties += "Essential ";
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(ESM::Creature::None|
|
||||
int unused = (0xFF ^
|
||||
(ESM::Creature::Base|
|
||||
ESM::Creature::Walks|
|
||||
ESM::Creature::Swims|
|
||||
ESM::Creature::Flies|
|
||||
ESM::Creature::Bipedal|
|
||||
ESM::Creature::Respawn|
|
||||
ESM::Creature::Weapon|
|
||||
ESM::Creature::Skeleton|
|
||||
ESM::Creature::Metal|
|
||||
ESM::Creature::Essential));
|
||||
if (flags & unused) properties += "Invalid ";
|
||||
properties += str(boost::format("(0x%08X)") % flags);
|
||||
properties += str(boost::format("(0x%02X)") % flags);
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -828,33 +824,21 @@ std::string npcFlags(int flags)
|
|||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
// Mythicmods and the ESM component differ. Mythicmods says
|
||||
// 0x8=None and 0x10=AutoCalc, while our code previously defined
|
||||
// 0x8 as AutoCalc. The former seems to be correct. All Bethesda
|
||||
// records have bit 0x8 set. Previously, suspiciously large portion
|
||||
// of females had autocalc turned off.
|
||||
if (flags & 0x00000008) properties += "Unknown ";
|
||||
if (flags & ESM::NPC::Base) properties += "Base ";
|
||||
if (flags & ESM::NPC::Autocalc) properties += "Autocalc ";
|
||||
if (flags & ESM::NPC::Female) properties += "Female ";
|
||||
if (flags & ESM::NPC::Respawn) properties += "Respawn ";
|
||||
if (flags & ESM::NPC::Essential) properties += "Essential ";
|
||||
// These two flags do not appear on any NPCs and may have been
|
||||
// confused with the flags for creatures.
|
||||
if (flags & ESM::NPC::Skeleton) properties += "Skeleton ";
|
||||
if (flags & ESM::NPC::Metal) properties += "Metal ";
|
||||
// Whether corpses persist is a bit that is unaccounted for,
|
||||
// however the only unknown bit occurs on ALL records, and
|
||||
// relatively few NPCs have this bit set.
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(0x00000008|
|
||||
// however relatively few NPCs have this bit set.
|
||||
int unused = (0xFF ^
|
||||
(ESM::NPC::Base|
|
||||
ESM::NPC::Autocalc|
|
||||
ESM::NPC::Female|
|
||||
ESM::NPC::Respawn|
|
||||
ESM::NPC::Essential|
|
||||
ESM::NPC::Skeleton|
|
||||
ESM::NPC::Metal));
|
||||
ESM::NPC::Essential));
|
||||
if (flags & unused) properties += "Invalid ";
|
||||
properties += str(boost::format("(0x%08X)") % flags);
|
||||
properties += str(boost::format("(0x%02X)") % flags);
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
|
|
@ -618,7 +618,8 @@ void Record<ESM::Creature>::print()
|
|||
std::cout << " Name: " << mData.mName << std::endl;
|
||||
std::cout << " Model: " << mData.mModel << std::endl;
|
||||
std::cout << " Script: " << mData.mScript << std::endl;
|
||||
std::cout << " Flags: " << creatureFlags(mData.mFlags) << std::endl;
|
||||
std::cout << " Flags: " << creatureFlags((int)mData.mFlags) << std::endl;
|
||||
std::cout << " Blood Type: " << mData.mBloodType+1 << std::endl;
|
||||
std::cout << " Original: " << mData.mOriginal << std::endl;
|
||||
std::cout << " Scale: " << mData.mScale << std::endl;
|
||||
|
||||
|
@ -1022,7 +1023,9 @@ void Record<ESM::NPC>::print()
|
|||
std::cout << " Script: " << mData.mScript << std::endl;
|
||||
if (!mData.mFaction.empty())
|
||||
std::cout << " Faction: " << mData.mFaction << std::endl;
|
||||
std::cout << " Flags: " << npcFlags(mData.mFlags) << std::endl;
|
||||
std::cout << " Flags: " << npcFlags((int)mData.mFlags) << std::endl;
|
||||
if (mData.mBloodType != 0)
|
||||
std::cout << " Blood Type: " << mData.mBloodType+1 << std::endl;
|
||||
|
||||
if (mData.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
|
||||
{
|
||||
|
|
|
@ -74,13 +74,14 @@ bool Launcher::AdvancedPage::loadSettings()
|
|||
loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
||||
loadSettingBool(classicReflectedAbsorbSpellsCheckBox, "classic reflected absorb spells behavior", "Game");
|
||||
loadSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
||||
loadSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game");
|
||||
loadSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
||||
loadSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
||||
int unarmedFactorsStrengthIndex = mEngineSettings.getInt("strength influences hand to hand", "Game");
|
||||
if (unarmedFactorsStrengthIndex >= 0 && unarmedFactorsStrengthIndex <= 2)
|
||||
unarmedFactorsStrengthComboBox->setCurrentIndex(unarmedFactorsStrengthIndex);
|
||||
loadSettingBool(requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game");
|
||||
loadSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
||||
loadSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game");
|
||||
|
||||
// Input Settings
|
||||
loadSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
||||
|
@ -134,13 +135,14 @@ void Launcher::AdvancedPage::saveSettings()
|
|||
saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
||||
saveSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
||||
saveSettingBool(classicReflectedAbsorbSpellsCheckBox, "classic reflected absorb spells behavior", "Game");
|
||||
saveSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game");
|
||||
saveSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
||||
saveSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
||||
int unarmedFactorsStrengthIndex = unarmedFactorsStrengthComboBox->currentIndex();
|
||||
if (unarmedFactorsStrengthIndex != mEngineSettings.getInt("strength influences hand to hand", "Game"))
|
||||
mEngineSettings.setInt("strength influences hand to hand", "Game", unarmedFactorsStrengthIndex);
|
||||
saveSettingBool(requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game");
|
||||
saveSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
||||
saveSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game");
|
||||
|
||||
// Input Settings
|
||||
saveSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
||||
|
|
|
@ -230,9 +230,19 @@ MwIniImporter::MwIniImporter()
|
|||
"Blood:Texture 0",
|
||||
"Blood:Texture 1",
|
||||
"Blood:Texture 2",
|
||||
"Blood:Texture 3",
|
||||
"Blood:Texture 4",
|
||||
"Blood:Texture 5",
|
||||
"Blood:Texture 6",
|
||||
"Blood:Texture 7",
|
||||
"Blood:Texture Name 0",
|
||||
"Blood:Texture Name 1",
|
||||
"Blood:Texture Name 2",
|
||||
"Blood:Texture Name 3",
|
||||
"Blood:Texture Name 4",
|
||||
"Blood:Texture Name 5",
|
||||
"Blood:Texture Name 6",
|
||||
"Blood:Texture Name 7",
|
||||
|
||||
// movies
|
||||
"Movies:Company Logo",
|
||||
|
@ -624,17 +634,6 @@ MwIniImporter::MwIniImporter()
|
|||
"Moons:Masser Fade Out Finish",
|
||||
"Moons:Script Color",
|
||||
|
||||
// blood
|
||||
"Blood:Model 0",
|
||||
"Blood:Model 1",
|
||||
"Blood:Model 2",
|
||||
"Blood:Texture 0",
|
||||
"Blood:Texture 1",
|
||||
"Blood:Texture 2",
|
||||
"Blood:Texture Name 0",
|
||||
"Blood:Texture Name 1",
|
||||
"Blood:Texture Name 2",
|
||||
|
||||
// werewolf (Bloodmoon)
|
||||
"General:Werewolf FOV",
|
||||
|
||||
|
|
|
@ -21,12 +21,13 @@ using namespace Fallback;
|
|||
|
||||
CS::Editor::Editor (int argc, char **argv)
|
||||
: mSettingsState (mCfgMgr), mDocumentManager (mCfgMgr),
|
||||
mViewManager (mDocumentManager), mPid(""),
|
||||
mLock(), mMerge (mDocumentManager),
|
||||
mPid(""), mLock(), mMerge (mDocumentManager),
|
||||
mIpcServerName ("org.openmw.OpenCS"), mServer(nullptr), mClientSocket(nullptr)
|
||||
{
|
||||
{
|
||||
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
|
||||
|
||||
mViewManager = new CSVDoc::ViewManager(mDocumentManager);
|
||||
|
||||
setupDataFiles (config.first);
|
||||
|
||||
NifOsg::Loader::setShowMarkers(true);
|
||||
|
@ -44,11 +45,11 @@ CS::Editor::Editor (int argc, char **argv)
|
|||
connect (&mDocumentManager, SIGNAL (lastDocumentDeleted()),
|
||||
this, SLOT (lastDocumentDeleted()));
|
||||
|
||||
connect (&mViewManager, SIGNAL (newGameRequest ()), this, SLOT (createGame ()));
|
||||
connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ()));
|
||||
connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ()));
|
||||
connect (&mViewManager, SIGNAL (editSettingsRequest()), this, SLOT (showSettings ()));
|
||||
connect (&mViewManager, SIGNAL (mergeDocument (CSMDoc::Document *)), this, SLOT (mergeDocument (CSMDoc::Document *)));
|
||||
connect (mViewManager, SIGNAL (newGameRequest ()), this, SLOT (createGame ()));
|
||||
connect (mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ()));
|
||||
connect (mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ()));
|
||||
connect (mViewManager, SIGNAL (editSettingsRequest()), this, SLOT (showSettings ()));
|
||||
connect (mViewManager, SIGNAL (mergeDocument (CSMDoc::Document *)), this, SLOT (mergeDocument (CSMDoc::Document *)));
|
||||
|
||||
connect (&mStartup, SIGNAL (createGame()), this, SLOT (createGame ()));
|
||||
connect (&mStartup, SIGNAL (createAddon()), this, SLOT (createAddon ()));
|
||||
|
@ -69,6 +70,8 @@ CS::Editor::Editor (int argc, char **argv)
|
|||
|
||||
CS::Editor::~Editor ()
|
||||
{
|
||||
delete mViewManager;
|
||||
|
||||
mPidFile.close();
|
||||
|
||||
if(mServer && boost::filesystem::exists(mPid))
|
||||
|
@ -107,7 +110,9 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
|||
|
||||
boost::program_options::notify(variables);
|
||||
|
||||
mCfgMgr.readConfiguration(variables, desc, quiet);
|
||||
mCfgMgr.readConfiguration(variables, desc, false);
|
||||
|
||||
Fallback::Map::init(variables["fallback"].as<FallbackMap>().mMap);
|
||||
|
||||
const std::string encoding = variables["encoding"].as<Files::EscapeHashString>().toStdString();
|
||||
mDocumentManager.setEncoding (ToUTF8::calculateEncoding (encoding));
|
||||
|
@ -115,8 +120,6 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
|||
|
||||
mDocumentManager.setResourceDir (mResources = variables["resources"].as<Files::EscapeHashString>().toStdString());
|
||||
|
||||
mDocumentManager.setFallbackMap (variables["fallback"].as<FallbackMap>().mMap);
|
||||
|
||||
if (variables["script-blacklist-use"].as<bool>())
|
||||
mDocumentManager.setBlacklistedScripts (
|
||||
variables["script-blacklist"].as<Files::EscapeStringVector>().toStdStringVector());
|
||||
|
@ -367,7 +370,7 @@ int CS::Editor::run()
|
|||
|
||||
void CS::Editor::documentAdded (CSMDoc::Document *document)
|
||||
{
|
||||
mViewManager.addView (document);
|
||||
mViewManager->addView (document);
|
||||
}
|
||||
|
||||
void CS::Editor::documentAboutToBeRemoved (CSMDoc::Document *document)
|
||||
|
|
|
@ -42,7 +42,6 @@ namespace CS
|
|||
Files::ConfigurationManager mCfgMgr;
|
||||
CSMPrefs::State mSettingsState;
|
||||
CSMDoc::DocumentManager mDocumentManager;
|
||||
CSVDoc::ViewManager mViewManager;
|
||||
CSVDoc::StartupDialogue mStartup;
|
||||
CSVDoc::NewGameDialogue mNewGame;
|
||||
CSVPrefs::Dialogue mSettings;
|
||||
|
@ -54,6 +53,7 @@ namespace CS
|
|||
boost::filesystem::ofstream mPidFile;
|
||||
bool mFsStrict;
|
||||
CSVTools::Merge mMerge;
|
||||
CSVDoc::ViewManager* mViewManager;
|
||||
|
||||
void setupDataFiles (const Files::PathContainer& dataDirs);
|
||||
|
||||
|
|
|
@ -273,18 +273,16 @@ 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,
|
||||
const Fallback::Map* fallback,
|
||||
ToUTF8::FromType encoding,
|
||||
const std::vector<std::string>& blacklistedScripts,
|
||||
ToUTF8::FromType encoding, const std::vector<std::string>& blacklistedScripts,
|
||||
bool fsStrict, const Files::PathContainer& dataPaths, const std::vector<std::string>& archives)
|
||||
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, fsStrict, dataPaths, archives, fallback, resDir),
|
||||
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, fsStrict, dataPaths, archives, resDir),
|
||||
mTools (*this, encoding),
|
||||
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
||||
(savePath.filename().string() + ".project")),
|
||||
mSavingOperation (*this, mProjectPath, encoding),
|
||||
mSaving (&mSavingOperation),
|
||||
mResDir(resDir), mFallbackMap(fallback),
|
||||
mRunner (mProjectPath), mDirty (false), mIdCompletionManager(mData)
|
||||
mResDir(resDir), mRunner (mProjectPath),
|
||||
mDirty (false), mIdCompletionManager(mData)
|
||||
{
|
||||
if (mContentFiles.empty())
|
||||
throw std::runtime_error ("Empty content file sequence");
|
||||
|
|
|
@ -69,7 +69,6 @@ namespace CSMDoc
|
|||
Saving mSavingOperation;
|
||||
OperationHolder mSaving;
|
||||
boost::filesystem::path mResDir;
|
||||
const Fallback::Map* mFallbackMap;
|
||||
Blacklist mBlacklist;
|
||||
Runner mRunner;
|
||||
bool mDirty;
|
||||
|
@ -105,8 +104,7 @@ 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,
|
||||
const Fallback::Map* fallback, ToUTF8::FromType encoding,
|
||||
const std::vector<std::string>& blacklistedScripts,
|
||||
ToUTF8::FromType encoding, const std::vector<std::string>& blacklistedScripts,
|
||||
bool fsStrict, const Files::PathContainer& dataPaths, const std::vector<std::string>& archives);
|
||||
|
||||
~Document();
|
||||
|
|
|
@ -62,7 +62,7 @@ CSMDoc::Document *CSMDoc::DocumentManager::makeDocument (
|
|||
const std::vector< boost::filesystem::path >& files,
|
||||
const boost::filesystem::path& savePath, bool new_)
|
||||
{
|
||||
return new Document (mConfiguration, files, new_, savePath, mResDir, &mFallbackMap, mEncoding, mBlacklistedScripts, mFsStrict, mDataPaths, mArchives);
|
||||
return new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mBlacklistedScripts, mFsStrict, mDataPaths, mArchives);
|
||||
}
|
||||
|
||||
void CSMDoc::DocumentManager::insertDocument (CSMDoc::Document *document)
|
||||
|
@ -98,11 +98,6 @@ void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& par
|
|||
mResDir = boost::filesystem::system_complete(parResDir);
|
||||
}
|
||||
|
||||
void CSMDoc::DocumentManager::setFallbackMap(const std::map<std::string, std::string>& fallbackMap)
|
||||
{
|
||||
mFallbackMap = Fallback::Map(fallbackMap);
|
||||
}
|
||||
|
||||
void CSMDoc::DocumentManager::setEncoding (ToUTF8::FromType encoding)
|
||||
{
|
||||
mEncoding = encoding;
|
||||
|
|
|
@ -41,7 +41,6 @@ namespace CSMDoc
|
|||
std::vector<std::string> mBlacklistedScripts;
|
||||
|
||||
boost::filesystem::path mResDir;
|
||||
Fallback::Map mFallbackMap;
|
||||
|
||||
bool mFsStrict;
|
||||
Files::PathContainer mDataPaths;
|
||||
|
@ -72,8 +71,6 @@ namespace CSMDoc
|
|||
|
||||
void setResourceDir (const boost::filesystem::path& parResDir);
|
||||
|
||||
void setFallbackMap (const std::map<std::string, std::string>& fallbackMap);
|
||||
|
||||
void setEncoding (ToUTF8::FromType encoding);
|
||||
|
||||
void setBlacklistedScripts (const std::vector<std::string>& scriptIds);
|
||||
|
|
|
@ -38,11 +38,11 @@ bool CSMFilter::TextNode::test (const CSMWorld::IdTableBase& table, int row,
|
|||
{
|
||||
int value = data.toInt();
|
||||
|
||||
std::vector<std::string> enums =
|
||||
std::vector<std::pair<int,std::string>> enums =
|
||||
CSMWorld::Columns::getEnums (static_cast<CSMWorld::Columns::ColumnId> (mColumnId));
|
||||
|
||||
if (value>=0 && value<static_cast<int> (enums.size()))
|
||||
string = QString::fromUtf8 (enums[value].c_str());
|
||||
string = QString::fromUtf8 (enums[value].second.c_str());
|
||||
}
|
||||
else if (data.type()==QVariant::Bool)
|
||||
{
|
||||
|
|
|
@ -75,11 +75,11 @@ void CSMTools::Search::searchRecordStateCell (const CSMWorld::IdTableBase *model
|
|||
|
||||
if (data==mValue)
|
||||
{
|
||||
std::vector<std::string> states =
|
||||
std::vector<std::pair<int,std::string>> states =
|
||||
CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_Modification);
|
||||
|
||||
const std::string hint = "r: " + std::to_string(model->getColumnId(index.column()));
|
||||
messages.add (id, states.at(data), hint);
|
||||
messages.add (id, states.at(data).second, hint);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,16 @@
|
|||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <components/esm/loadland.hpp>
|
||||
#include <components/misc/constants.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
const int cellSize {ESM::Land::REAL_SIZE};
|
||||
const int landSize {ESM::Land::LAND_SIZE};
|
||||
const int landTextureSize {ESM::Land::LAND_TEXTURE_SIZE};
|
||||
}
|
||||
|
||||
CSMWorld::CellCoordinates::CellCoordinates() : mX (0), mY (0) {}
|
||||
|
||||
CSMWorld::CellCoordinates::CellCoordinates (int x, int y) : mX (x), mY (y) {}
|
||||
|
@ -32,11 +40,13 @@ CSMWorld::CellCoordinates CSMWorld::CellCoordinates::move (int x, int y) const
|
|||
std::string CSMWorld::CellCoordinates::getId (const std::string& worldspace) const
|
||||
{
|
||||
// we ignore the worldspace for now, since there is only one (will change in 1.1)
|
||||
std::ostringstream stream;
|
||||
return generateId(mX, mY);
|
||||
}
|
||||
|
||||
stream << "#" << mX << " " << mY;
|
||||
|
||||
return stream.str();
|
||||
std::string CSMWorld::CellCoordinates::generateId (int x, int y)
|
||||
{
|
||||
std::string cellId = "#" + std::to_string(x) + " " + std::to_string(y);
|
||||
return cellId;
|
||||
}
|
||||
|
||||
bool CSMWorld::CellCoordinates::isExteriorCell (const std::string& id)
|
||||
|
@ -66,6 +76,50 @@ std::pair<int, int> CSMWorld::CellCoordinates::coordinatesToCellIndex (float x,
|
|||
return std::make_pair (std::floor (x / Constants::CellSizeInUnits), std::floor (y / Constants::CellSizeInUnits));
|
||||
}
|
||||
|
||||
std::pair<int, int> CSMWorld::CellCoordinates::toTextureCoords(osg::Vec3d worldPos)
|
||||
{
|
||||
const auto xd = static_cast<float>(worldPos.x() * landTextureSize / cellSize - 0.25f);
|
||||
const auto yd = static_cast<float>(worldPos.y() * landTextureSize / cellSize + 0.25f);
|
||||
|
||||
const auto x = static_cast<int>(std::floor(xd));
|
||||
const auto y = static_cast<int>(std::floor(yd));
|
||||
|
||||
return std::make_pair(x, y);
|
||||
}
|
||||
|
||||
std::pair<int, int> CSMWorld::CellCoordinates::toVertexCoords(osg::Vec3d worldPos)
|
||||
{
|
||||
const auto xd = static_cast<float>(worldPos.x() * (landSize - 1) / cellSize + 0.5f);
|
||||
const auto yd = static_cast<float>(worldPos.y() * (landSize - 1) / cellSize + 0.5f);
|
||||
|
||||
const auto x = static_cast<int>(std::floor(xd));
|
||||
const auto y = static_cast<int>(std::floor(yd));
|
||||
|
||||
return std::make_pair(x, y);
|
||||
}
|
||||
|
||||
float CSMWorld::CellCoordinates::textureSelectionToWorldCoords(int pos)
|
||||
{
|
||||
return cellSize * static_cast<float>(pos) / landTextureSize;
|
||||
}
|
||||
|
||||
float CSMWorld::CellCoordinates::vertexSelectionToWorldCoords(int pos)
|
||||
{
|
||||
return cellSize * static_cast<float>(pos) / (landSize - 1);
|
||||
}
|
||||
|
||||
int CSMWorld::CellCoordinates::vertexSelectionToInCellCoords(int pos)
|
||||
{
|
||||
return static_cast<int>(pos - std::floor(static_cast<float>(pos) / (landSize - 1)) * (landSize - 1));
|
||||
}
|
||||
|
||||
std::string CSMWorld::CellCoordinates::vertexGlobalToCellId(std::pair<int, int> vertexGlobal)
|
||||
{
|
||||
int x = std::floor(static_cast<float>(vertexGlobal.first) / (landSize - 1));
|
||||
int y = std::floor(static_cast<float>(vertexGlobal.second) / (landSize - 1));
|
||||
return generateId(x, y);
|
||||
}
|
||||
|
||||
bool CSMWorld::operator== (const CellCoordinates& left, const CellCoordinates& right)
|
||||
{
|
||||
return left.getX()==right.getX() && left.getY()==right.getY();
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include <QMetaType>
|
||||
|
||||
#include <osg/Vec3d>
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class CellCoordinates
|
||||
|
@ -29,6 +31,9 @@ namespace CSMWorld
|
|||
CellCoordinates move (int x, int y) const;
|
||||
///< Return a copy of *this, moved by the given offset.
|
||||
|
||||
///Generate cell id string from x and y coordinates
|
||||
static std::string generateId (int x, int y);
|
||||
|
||||
std::string getId (const std::string& worldspace) const;
|
||||
///< Return the ID for the cell at these coordinates.
|
||||
|
||||
|
@ -42,6 +47,24 @@ namespace CSMWorld
|
|||
|
||||
/// \return cell coordinates such that given world coordinates are in it.
|
||||
static std::pair<int, int> coordinatesToCellIndex (float x, float y);
|
||||
|
||||
///Converts worldspace coordinates to global texture selection, taking in account the texture offset.
|
||||
static std::pair<int, int> toTextureCoords(osg::Vec3d worldPos);
|
||||
|
||||
///Converts worldspace coordinates to global vertex selection.
|
||||
static std::pair<int, int> toVertexCoords(osg::Vec3d worldPos);
|
||||
|
||||
///Converts global texture coordinate to worldspace coordinate that is at the upper left corner of the selected texture.
|
||||
static float textureSelectionToWorldCoords(int);
|
||||
|
||||
///Converts global vertex coordinate to worldspace coordinate
|
||||
static float vertexSelectionToWorldCoords(int);
|
||||
|
||||
///Converts local cell's heightmap coordinates from the global vertex coordinate
|
||||
static int vertexSelectionToInCellCoords(int);
|
||||
|
||||
///Converts global vertex coordinates to cell id
|
||||
static std::string vertexGlobalToCellId(std::pair<int, int>);
|
||||
};
|
||||
|
||||
bool operator== (const CellCoordinates& left, const CellCoordinates& right);
|
||||
|
|
|
@ -86,6 +86,8 @@ namespace CSMWorld
|
|||
Display_Enchantment,
|
||||
//CONCRETE TYPES ENDS HERE
|
||||
|
||||
Display_SignedInteger8,
|
||||
Display_SignedInteger16,
|
||||
Display_UnsignedInteger8,
|
||||
Display_UnsignedInteger16,
|
||||
Display_Integer,
|
||||
|
|
|
@ -1376,7 +1376,7 @@ namespace CSMWorld
|
|||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
const ESM::Position& position = record.get().*mPosition;
|
||||
return position.rot[mIndex];
|
||||
return osg::RadiansToDegrees(position.rot[mIndex]);
|
||||
}
|
||||
|
||||
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||
|
@ -1385,7 +1385,7 @@ namespace CSMWorld
|
|||
|
||||
ESM::Position& position = record2.*mPosition;
|
||||
|
||||
position.rot[mIndex] = data.toFloat();
|
||||
position.rot[mIndex] = osg::DegreesToRadians(data.toFloat());
|
||||
|
||||
record.setModified (record2);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "columns.hpp"
|
||||
|
||||
#include <components/fallback/fallback.hpp>
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "universalid.hpp"
|
||||
|
@ -573,11 +574,6 @@ namespace
|
|||
"Book", "Scroll", 0
|
||||
};
|
||||
|
||||
static const char *sBloodType[] =
|
||||
{
|
||||
"Default (Red)", "Skeleton Blood (White)", "Metal Blood (Golden)", 0
|
||||
};
|
||||
|
||||
static const char *sEmitterType[] =
|
||||
{
|
||||
"<None>", "Flickering", "Flickering (Slow)", "Pulsing", "Pulsing (Slow)", 0
|
||||
|
@ -613,7 +609,6 @@ namespace
|
|||
case CSMWorld::Columns::ColumnId_InfoCondFunc: return CSMWorld::ConstInfoSelectWrapper::FunctionEnumStrings;
|
||||
case CSMWorld::Columns::ColumnId_InfoCondComp: return CSMWorld::ConstInfoSelectWrapper::RelationEnumStrings;
|
||||
case CSMWorld::Columns::ColumnId_BookType: return sBookType;
|
||||
case CSMWorld::Columns::ColumnId_BloodType: return sBloodType;
|
||||
case CSMWorld::Columns::ColumnId_EmitterType: return sEmitterType;
|
||||
|
||||
default: return 0;
|
||||
|
@ -626,19 +621,28 @@ bool CSMWorld::Columns::hasEnums (ColumnId column)
|
|||
return getEnumNames (column)!=0 || column==ColumnId_RecordType;
|
||||
}
|
||||
|
||||
std::vector<std::string> CSMWorld::Columns::getEnums (ColumnId column)
|
||||
std::vector<std::pair<int,std::string>>CSMWorld::Columns::getEnums (ColumnId column)
|
||||
{
|
||||
std::vector<std::string> enums;
|
||||
std::vector<std::pair<int,std::string>> enums;
|
||||
|
||||
if (const char **table = getEnumNames (column))
|
||||
for (int i=0; table[i]; ++i)
|
||||
enums.push_back (table[i]);
|
||||
enums.emplace_back(i, table[i]);
|
||||
else if (column==ColumnId_BloodType)
|
||||
{
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
const std::string& bloodName = Fallback::Map::getString("Blood_Texture_Name_" + std::to_string(i));
|
||||
if (!bloodName.empty())
|
||||
enums.emplace_back(i, bloodName);
|
||||
}
|
||||
}
|
||||
else if (column==ColumnId_RecordType)
|
||||
{
|
||||
enums.push_back (""); // none
|
||||
enums.emplace_back(UniversalId::Type_None, ""); // none
|
||||
|
||||
for (int i=UniversalId::Type_None+1; i<UniversalId::NumberOfTypes; ++i)
|
||||
enums.push_back (UniversalId (static_cast<UniversalId::Type> (i)).getTypeName());
|
||||
enums.emplace_back (i, UniversalId (static_cast<UniversalId::Type> (i)).getTypeName());
|
||||
}
|
||||
|
||||
return enums;
|
||||
|
|
|
@ -390,7 +390,7 @@ namespace CSMWorld
|
|||
|
||||
bool hasEnums (ColumnId column);
|
||||
|
||||
std::vector<std::string> getEnums (ColumnId column);
|
||||
std::vector<std::pair<int,std::string>> getEnums (ColumnId column);
|
||||
///< Returns an empty vector, if \a column isn't an enum type column.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include <components/esm/cellref.hpp>
|
||||
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/sceneutil/shadow.hpp>
|
||||
#include <components/shader/shadermanager.hpp>
|
||||
#include <components/vfs/manager.hpp>
|
||||
#include <components/vfs/registerarchives.hpp>
|
||||
|
||||
|
@ -64,9 +66,9 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec
|
|||
}
|
||||
|
||||
CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::PathContainer& dataPaths,
|
||||
const std::vector<std::string>& archives, const Fallback::Map* fallback, const boost::filesystem::path& resDir)
|
||||
const std::vector<std::string>& archives, const boost::filesystem::path& resDir)
|
||||
: mEncoder (encoding), mPathgrids (mCells), mRefs (mCells),
|
||||
mFallbackMap(fallback), mReader (0), mDialogue (0), mReaderIndex(1),
|
||||
mReader (0), mDialogue (0), mReaderIndex(1),
|
||||
mFsStrict(fsStrict), mDataPaths(dataPaths), mArchives(archives)
|
||||
{
|
||||
mVFS.reset(new VFS::Manager(mFsStrict));
|
||||
|
@ -75,6 +77,14 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat
|
|||
mResourcesManager.setVFS(mVFS.get());
|
||||
mResourceSystem.reset(new Resource::ResourceSystem(mVFS.get()));
|
||||
|
||||
Shader::ShaderManager::DefineMap defines = mResourceSystem->getSceneManager()->getShaderManager().getGlobalDefines();
|
||||
Shader::ShaderManager::DefineMap shadowDefines = SceneUtil::ShadowManager::getShadowsDisabledDefines();
|
||||
defines["forcePPL"] = "0";
|
||||
defines["clamp"] = "1";
|
||||
for (const auto& define : shadowDefines)
|
||||
defines[define.first] = define.second;
|
||||
mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(defines);
|
||||
|
||||
mResourceSystem->getSceneManager()->setShaderPath((resDir / "shaders").string());
|
||||
|
||||
int index = 0;
|
||||
|
@ -1360,8 +1370,3 @@ const VFS::Manager* CSMWorld::Data::getVFS() const
|
|||
{
|
||||
return mVFS.get();
|
||||
}
|
||||
|
||||
const Fallback::Map* CSMWorld::Data::getFallbackMap() const
|
||||
{
|
||||
return mFallbackMap;
|
||||
}
|
||||
|
|
|
@ -112,7 +112,6 @@ namespace CSMWorld
|
|||
IdCollection<ESM::Filter> mFilters;
|
||||
Collection<MetaData> mMetaData;
|
||||
std::unique_ptr<ActorAdapter> mActorAdapter;
|
||||
const Fallback::Map* mFallbackMap;
|
||||
std::vector<QAbstractItemModel *> mModels;
|
||||
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
||||
ESM::ESMReader *mReader;
|
||||
|
@ -151,15 +150,12 @@ namespace CSMWorld
|
|||
public:
|
||||
|
||||
Data (ToUTF8::FromType encoding, bool fsStrict, const Files::PathContainer& dataPaths,
|
||||
const std::vector<std::string>& archives, const Fallback::Map* fallback,
|
||||
const boost::filesystem::path& resDir);
|
||||
const std::vector<std::string>& archives, const boost::filesystem::path& resDir);
|
||||
|
||||
virtual ~Data();
|
||||
|
||||
const VFS::Manager* getVFS() const;
|
||||
|
||||
const Fallback::Map* getFallbackMap() const;
|
||||
|
||||
std::shared_ptr<Resource::ResourceSystem> getResourceSystem();
|
||||
|
||||
std::shared_ptr<const Resource::ResourceSystem> getResourceSystem() const;
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
std::string getEnumValue(const std::vector<std::string> &values, int index)
|
||||
std::string getEnumValue(const std::vector<std::pair<int,std::string>> &values, int index)
|
||||
{
|
||||
if (index < 0 || index >= static_cast<int>(values.size()))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return values[index];
|
||||
return values[index].second;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace CSMWorld
|
|||
|
||||
// Cache of enum values for enum columns (e.g. Modified, Record Type).
|
||||
// Used to speed up comparisons during the sort by such columns.
|
||||
typedef std::map<Columns::ColumnId, std::vector<std::string> > EnumColumnCache;
|
||||
typedef std::map<Columns::ColumnId, std::vector<std::pair<int,std::string>> > EnumColumnCache;
|
||||
mutable EnumColumnCache mEnumColumnCache;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -491,17 +491,7 @@ QVariant CSMWorld::CreatureRefIdAdapter::getData (const RefIdColumn *column, con
|
|||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
if (column == mColumns.mBloodType)
|
||||
{
|
||||
int mask = ESM::Creature::Skeleton | ESM::Creature::Metal;
|
||||
|
||||
if ((record.get().mFlags & mask) == ESM::Creature::Skeleton)
|
||||
return 1;
|
||||
|
||||
if ((record.get().mFlags & mask) == ESM::Creature::Metal)
|
||||
return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
return record.get().mBloodType;
|
||||
|
||||
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||
mColumns.mFlags.find (column);
|
||||
|
@ -527,16 +517,7 @@ void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdDa
|
|||
else if (column==mColumns.mOriginal)
|
||||
creature.mOriginal = value.toString().toUtf8().constData();
|
||||
else if (column == mColumns.mBloodType)
|
||||
{
|
||||
int mask = ~(ESM::Creature::Skeleton | ESM::Creature::Metal);
|
||||
|
||||
if (value.toInt() == 1)
|
||||
creature.mFlags = (creature.mFlags & mask) | ESM::Creature::Skeleton;
|
||||
else if (value.toInt() == 2)
|
||||
creature.mFlags = (creature.mFlags & mask) | ESM::Creature::Metal;
|
||||
else
|
||||
creature.mFlags = creature.mFlags & mask;
|
||||
}
|
||||
creature.mBloodType = value.toInt();
|
||||
else
|
||||
{
|
||||
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||
|
@ -797,17 +778,7 @@ QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const Re
|
|||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
if (column == mColumns.mBloodType)
|
||||
{
|
||||
int mask = ESM::NPC::Skeleton | ESM::NPC::Metal;
|
||||
|
||||
if ((record.get().mFlags & mask) == ESM::NPC::Skeleton)
|
||||
return 1;
|
||||
|
||||
if ((record.get().mFlags & mask) == ESM::NPC::Metal)
|
||||
return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
return record.get().mBloodType;
|
||||
|
||||
if (column == mColumns.mGender)
|
||||
{
|
||||
|
@ -846,16 +817,7 @@ void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& d
|
|||
else if (column==mColumns.mHead)
|
||||
npc.mHead = value.toString().toUtf8().constData();
|
||||
else if (column == mColumns.mBloodType)
|
||||
{
|
||||
int mask = ~(ESM::NPC::Skeleton | ESM::NPC::Metal);
|
||||
|
||||
if (value.toInt() == 1)
|
||||
npc.mFlags = (npc.mFlags & mask) | ESM::NPC::Skeleton;
|
||||
else if (value.toInt() == 2)
|
||||
npc.mFlags = (npc.mFlags & mask) | ESM::NPC::Metal;
|
||||
else
|
||||
npc.mFlags = npc.mFlags & mask;
|
||||
}
|
||||
npc.mBloodType = value.toInt();
|
||||
else if (column == mColumns.mGender)
|
||||
{
|
||||
// Implemented this way to allow additional gender types in the future.
|
||||
|
|
|
@ -512,7 +512,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Attribute, CSMWorld::ColumnBase::Display_Attribute, false, false));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_UnsignedInteger8));
|
||||
|
||||
// Nested table
|
||||
mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcSkills,
|
||||
|
@ -524,7 +524,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Skill, CSMWorld::ColumnBase::Display_SkillId, false, false));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_UnsignedInteger8));
|
||||
|
||||
// Nested list
|
||||
mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcMisc,
|
||||
|
@ -534,21 +534,21 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||
miscMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcMiscRefIdAdapter()));
|
||||
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), miscMap));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Level, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_Level, CSMWorld::ColumnBase::Display_SignedInteger16));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcFactionID, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_NpcFactionID, CSMWorld::ColumnBase::Display_SignedInteger8));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Health, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_Health, CSMWorld::ColumnBase::Display_UnsignedInteger16));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Mana, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_Mana, CSMWorld::ColumnBase::Display_UnsignedInteger16));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Fatigue, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_Fatigue, CSMWorld::ColumnBase::Display_UnsignedInteger16));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcDisposition, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_NpcDisposition, CSMWorld::ColumnBase::Display_UnsignedInteger8));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcReputation, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_NpcReputation, CSMWorld::ColumnBase::Display_UnsignedInteger8));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcRank, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_NpcRank, CSMWorld::ColumnBase::Display_UnsignedInteger8));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Gold, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
|
|
|
@ -164,7 +164,7 @@ namespace CSVRender
|
|||
mWaterGeometry->setStateSet(SceneUtil::createSimpleWaterStateSet(Alpha, RenderBin));
|
||||
|
||||
// Add water texture
|
||||
std::string textureName = mData.getFallbackMap()->getFallbackString("Water_SurfaceTexture");
|
||||
std::string textureName = Fallback::Map::getString("Water_SurfaceTexture");
|
||||
textureName = "textures/water/" + textureName + "00.dds";
|
||||
|
||||
Resource::ImageManager* imageManager = mData.getResourceSystem()->getImageManager();
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/sceneutil/lightutil.hpp>
|
||||
#include <components/sceneutil/lightmanager.hpp>
|
||||
#include <components/fallback/fallback.hpp>
|
||||
|
||||
#include "actor.hpp"
|
||||
#include "mask.hpp"
|
||||
|
@ -140,17 +139,8 @@ void CSVRender::Object::update()
|
|||
|
||||
if (light)
|
||||
{
|
||||
const Fallback::Map* fallback = mData.getFallbackMap();
|
||||
static bool outQuadInLin = fallback->getFallbackBool("LightAttenuation_OutQuadInLin");
|
||||
static bool useQuadratic = fallback->getFallbackBool("LightAttenuation_UseQuadratic");
|
||||
static float quadraticValue = fallback->getFallbackFloat("LightAttenuation_QuadraticValue");
|
||||
static float quadraticRadiusMult = fallback->getFallbackFloat("LightAttenuation_QuadraticRadiusMult");
|
||||
static bool useLinear = fallback->getFallbackBool("LightAttenuation_UseLinear");
|
||||
static float linearRadiusMult = fallback->getFallbackFloat("LightAttenuation_LinearRadiusMult");
|
||||
static float linearValue = fallback->getFallbackFloat("LightAttenuation_LinearValue");
|
||||
bool isExterior = false; // FIXME
|
||||
SceneUtil::addLight(mBaseNode, light, Mask_ParticleSystem, Mask_Lighting, isExterior, outQuadInLin, useQuadratic,
|
||||
quadraticValue, quadraticRadiusMult, useLinear, linearRadiusMult, linearValue);
|
||||
SceneUtil::addLight(mBaseNode, light, Mask_ParticleSystem, Mask_Lighting, isExterior);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,13 +40,13 @@ CSVTools::SearchBox::SearchBox (QWidget *parent)
|
|||
mLayout = new QGridLayout (this);
|
||||
|
||||
// search panel
|
||||
std::vector<std::string> states =
|
||||
std::vector<std::pair<int,std::string>> states =
|
||||
CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_Modification);
|
||||
states.resize (states.size()-1); // ignore erased state
|
||||
|
||||
for (std::vector<std::string>::const_iterator iter (states.begin()); iter!=states.end();
|
||||
for (std::vector<std::pair<int,std::string>>::const_iterator iter (states.begin()); iter!=states.end();
|
||||
++iter)
|
||||
mRecordState.addItem (QString::fromUtf8 (iter->c_str()));
|
||||
mRecordState.addItem (QString::fromUtf8 (iter->second.c_str()));
|
||||
|
||||
mMode.addItem (tr("Text"));
|
||||
mMode.addItem (tr("Text (RegEx)"));
|
||||
|
|
|
@ -76,9 +76,9 @@ void CSVWorld::NotEditableSubDelegate::setEditorData (QWidget* editor, const QMo
|
|||
else if (CSMWorld::Columns::hasEnums (columnId))
|
||||
{
|
||||
int data = v.toInt();
|
||||
std::vector<std::string> enumNames (CSMWorld::Columns::getEnums (columnId));
|
||||
std::vector<std::pair<int,std::string>> enumNames (CSMWorld::Columns::getEnums (columnId));
|
||||
|
||||
label->setText(QString::fromUtf8(enumNames.at(data).c_str()));
|
||||
label->setText(QString::fromUtf8(enumNames.at(data).second.c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -155,7 +155,7 @@ CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const char **names, bool all
|
|||
add (i, names[i]);
|
||||
}
|
||||
|
||||
CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const std::vector<std::string>& names,
|
||||
CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const std::vector<std::pair<int,std::string>>& names,
|
||||
bool allowNone)
|
||||
{
|
||||
if (allowNone)
|
||||
|
@ -164,7 +164,7 @@ CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const std::vector<std::strin
|
|||
int size = static_cast<int> (names.size());
|
||||
|
||||
for (int i=0; i<size; ++i)
|
||||
add (i, names[i].c_str());
|
||||
add (names[i].first, names[i].second.c_str());
|
||||
}
|
||||
|
||||
CSVWorld::CommandDelegate *CSVWorld::EnumDelegateFactory::makeDelegate (
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace CSVWorld
|
|||
///< \param names Array of char pointer with a 0-pointer as end mark
|
||||
/// \param allowNone Use value of -1 for "none selected" (empty string)
|
||||
|
||||
EnumDelegateFactory (const std::vector<std::string>& names, bool allowNone = false);
|
||||
EnumDelegateFactory (const std::vector<std::pair<int,std::string>>& names, bool allowNone = false);
|
||||
/// \param allowNone Use value of -1 for "none selected" (empty string)
|
||||
|
||||
virtual CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const;
|
||||
|
|
|
@ -22,7 +22,7 @@ CSVWorld::CommandDelegate *CSVWorld::RecordStatusDelegateFactory::makeDelegate (
|
|||
|
||||
CSVWorld::RecordStatusDelegateFactory::RecordStatusDelegateFactory()
|
||||
{
|
||||
std::vector<std::string> enums =
|
||||
std::vector<std::pair<int,std::string>> enums =
|
||||
CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_Modification);
|
||||
|
||||
static const char *sIcons[] =
|
||||
|
@ -31,5 +31,8 @@ CSVWorld::RecordStatusDelegateFactory::RecordStatusDelegateFactory()
|
|||
};
|
||||
|
||||
for (int i=0; sIcons[i]; ++i)
|
||||
add (i, enums.at (i).c_str(), sIcons[i]);
|
||||
{
|
||||
auto& enumPair = enums.at(i);
|
||||
add (enumPair.first, enumPair.second.c_str(), sIcons[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -212,6 +212,19 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
|
|||
return sb;
|
||||
}
|
||||
|
||||
case CSMWorld::ColumnBase::Display_SignedInteger8:
|
||||
{
|
||||
DialogueSpinBox *sb = new DialogueSpinBox(parent);
|
||||
sb->setRange(std::numeric_limits<signed char>::min(), std::numeric_limits<signed char>::max());
|
||||
return sb;
|
||||
}
|
||||
case CSMWorld::ColumnBase::Display_SignedInteger16:
|
||||
{
|
||||
DialogueSpinBox *sb = new DialogueSpinBox(parent);
|
||||
sb->setRange(std::numeric_limits<short>::min(), std::numeric_limits<short>::max());
|
||||
return sb;
|
||||
}
|
||||
|
||||
case CSMWorld::ColumnBase::Display_UnsignedInteger8:
|
||||
{
|
||||
DialogueSpinBox *sb = new DialogueSpinBox(parent);
|
||||
|
|
|
@ -73,11 +73,11 @@ CSVWorld::CommandDelegate *CSVWorld::VarTypeDelegateFactory::makeDelegate (
|
|||
|
||||
void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type)
|
||||
{
|
||||
std::vector<std::string> enums =
|
||||
std::vector<std::pair<int,std::string>> enums =
|
||||
CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_ValueType);
|
||||
|
||||
if (static_cast<size_t>(type) >= enums.size())
|
||||
throw std::logic_error ("Unsupported variable type");
|
||||
|
||||
mValues.push_back (std::make_pair (type, QString::fromUtf8 (enums[type].c_str())));
|
||||
mValues.emplace_back(type, QString::fromUtf8 (enums[type].second.c_str()));
|
||||
}
|
||||
|
|
|
@ -8,8 +8,7 @@ set(GAME
|
|||
)
|
||||
|
||||
if (ANDROID)
|
||||
set(GAME ${GAME} android_commandLine.cpp)
|
||||
set(GAME ${GAME} android_main.c)
|
||||
set(GAME ${GAME} android_main.cpp)
|
||||
endif()
|
||||
|
||||
set(GAME_HEADER
|
||||
|
@ -32,7 +31,7 @@ add_openmw_dir (mwinput
|
|||
add_openmw_dir (mwgui
|
||||
layout textinput widgets race class birth review windowmanagerimp console dialogue
|
||||
windowbase statswindow messagebox journalwindow charactercreation
|
||||
mapwindow windowpinnablebase tooltips scrollwindow bookwindow
|
||||
mapwindow windowpinnablebase tooltips scrollwindow bookwindow resourceskin
|
||||
formatting inventorywindow container hud countdialog tradewindow settingswindow
|
||||
confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
|
||||
itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
#include "android_commandLine.h"
|
||||
#include "string.h"
|
||||
|
||||
const char **argvData;
|
||||
int argcData;
|
||||
|
||||
extern "C" void releaseArgv();
|
||||
|
||||
void releaseArgv() {
|
||||
delete[] argvData;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_ui_activity_GameActivity_commandLine(JNIEnv *env,
|
||||
jobject obj, jint argc, jobjectArray stringArray) {
|
||||
jboolean iscopy;
|
||||
argcData = (int) argc;
|
||||
argvData = new const char *[argcData + 1];
|
||||
argvData[0] = "openmw";
|
||||
for (int i = 1; i < argcData + 1; i++) {
|
||||
jstring string = (jstring) (env)->GetObjectArrayElement(stringArray,
|
||||
i - 1);
|
||||
argvData[i] = (env)->GetStringUTFChars(string, &iscopy);
|
||||
(env)->DeleteLocalRef(string);
|
||||
}
|
||||
(env)->DeleteLocalRef(stringArray);
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
#ifndef _Included_ui_activity_GameActivity_commandLine
|
||||
#define _Included_ui_activity_GameActivity_commandLine
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
JNIEXPORT void JNICALL Java_ui_activity_GameActivity_commandLine(JNIEnv *env, jobject obj,jint argcData, jobjectArray stringArray);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -18,35 +18,35 @@ extern const char **argvData;
|
|||
void releaseArgv();
|
||||
|
||||
|
||||
int Java_org_libsdl_app_SDLActivity_getMouseX(JNIEnv *env, jclass cls, jobject obj) {
|
||||
extern "C" int Java_org_libsdl_app_SDLActivity_getMouseX(JNIEnv *env, jclass cls, jobject obj) {
|
||||
int ret = 0;
|
||||
SDL_GetMouseState(&ret, NULL);
|
||||
SDL_GetMouseState(&ret, nullptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int Java_org_libsdl_app_SDLActivity_getMouseY(JNIEnv *env, jclass cls, jobject obj) {
|
||||
extern "C" int Java_org_libsdl_app_SDLActivity_getMouseY(JNIEnv *env, jclass cls, jobject obj) {
|
||||
int ret = 0;
|
||||
SDL_GetMouseState(NULL, &ret);
|
||||
SDL_GetMouseState(nullptr, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Java_org_libsdl_app_SDLActivity_isMouseShown(JNIEnv *env, jclass cls, jobject obj) {
|
||||
extern "C" int Java_org_libsdl_app_SDLActivity_isMouseShown(JNIEnv *env, jclass cls, jobject obj) {
|
||||
return SDL_ShowCursor(SDL_QUERY);
|
||||
}
|
||||
|
||||
extern SDL_Window *Android_Window;
|
||||
int SDL_SendMouseMotion(SDL_Window * window, int mouseID, int relative, int x, int y);
|
||||
void Java_org_libsdl_app_SDLActivity_sendRelativeMouseMotion(JNIEnv *env, jclass cls, int x, int y) {
|
||||
extern "C" int SDL_SendMouseMotion(SDL_Window * window, int mouseID, int relative, int x, int y);
|
||||
extern "C" void Java_org_libsdl_app_SDLActivity_sendRelativeMouseMotion(JNIEnv *env, jclass cls, int x, int y) {
|
||||
SDL_SendMouseMotion(Android_Window, 0, 1, x, y);
|
||||
}
|
||||
|
||||
int SDL_SendMouseButton(SDL_Window * window, int mouseID, Uint8 state, Uint8 button);
|
||||
void Java_org_libsdl_app_SDLActivity_sendMouseButton(JNIEnv *env, jclass cls, int state, int button) {
|
||||
extern "C" int SDL_SendMouseButton(SDL_Window * window, int mouseID, Uint8 state, Uint8 button);
|
||||
extern "C" void Java_org_libsdl_app_SDLActivity_sendMouseButton(JNIEnv *env, jclass cls, int state, int button) {
|
||||
SDL_SendMouseButton(Android_Window, 0, state, button);
|
||||
}
|
||||
|
||||
int Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject obj) {
|
||||
extern "C" int Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject obj) {
|
||||
setenv("OPENMW_DECOMPRESS_TEXTURES", "1", 1);
|
||||
|
||||
// On Android, we use a virtual controller with guid="Virtual"
|
|
@ -549,11 +549,11 @@ void OMW::Engine::createWindow(Settings::Manager& settings)
|
|||
|
||||
osg::ref_ptr<osg::Camera> camera = mViewer->getCamera();
|
||||
camera->setGraphicsContext(graphicsWindow);
|
||||
camera->setViewport(0, 0, width, height);
|
||||
camera->setViewport(0, 0, traits->width, traits->height);
|
||||
|
||||
mViewer->realize();
|
||||
|
||||
mViewer->getEventQueue()->getCurrentEventState()->setWindowRectangle(0, 0, width, height);
|
||||
mViewer->getEventQueue()->getCurrentEventState()->setWindowRectangle(0, 0, traits->width, traits->height);
|
||||
}
|
||||
|
||||
void OMW::Engine::setWindowIcon()
|
||||
|
@ -655,24 +655,24 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
|||
rootNode->addChild(guiRoot);
|
||||
MWGui::WindowManager* window = new MWGui::WindowManager(mViewer, guiRoot, mResourceSystem.get(), mWorkQueue.get(),
|
||||
mCfgMgr.getLogPath().string() + std::string("/"), myguiResources,
|
||||
mScriptConsoleMode, mTranslationDataStorage, mEncoding, mExportFonts, mFallbackMap,
|
||||
mScriptConsoleMode, mTranslationDataStorage, mEncoding, mExportFonts,
|
||||
Version::getOpenmwVersionDescription(mResDir.string()), mCfgMgr.getUserConfigPath().string());
|
||||
mEnvironment.setWindowManager (window);
|
||||
|
||||
// Create sound system
|
||||
mEnvironment.setSoundManager (new MWSound::SoundManager(mVFS.get(), mFallbackMap, mUseSound));
|
||||
mEnvironment.setSoundManager (new MWSound::SoundManager(mVFS.get(), mUseSound));
|
||||
|
||||
if (!mSkipMenu)
|
||||
{
|
||||
std::string logo = mFallbackMap["Movies_Company_Logo"];
|
||||
const std::string& logo = Fallback::Map::getString("Movies_Company_Logo");
|
||||
if (!logo.empty())
|
||||
window->playVideo(logo, true);
|
||||
}
|
||||
|
||||
// Create the world
|
||||
mEnvironment.setWorld( new MWWorld::World (mViewer, rootNode, mResourceSystem.get(), mWorkQueue.get(),
|
||||
mFileCollections, mContentFiles, mEncoder, mFallbackMap,
|
||||
mActivationDistanceOverride, mCellName, mResDir.string(), mCfgMgr.getUserDataPath().string()));
|
||||
mFileCollections, mContentFiles, mEncoder, mActivationDistanceOverride, mCellName,
|
||||
mStartupScript, mResDir.string(), mCfgMgr.getUserDataPath().string()));
|
||||
mEnvironment.getWorld()->setupPlayer();
|
||||
input->setPlayer(&mEnvironment.getWorld()->getPlayer());
|
||||
|
||||
|
@ -806,6 +806,11 @@ void OMW::Engine::go()
|
|||
mViewer = new osgViewer::Viewer;
|
||||
mViewer->setReleaseContextAtEndOfFrameHint(false);
|
||||
|
||||
#if OSG_VERSION_GREATER_OR_EQUAL(3,5,5)
|
||||
// Do not try to outsmart the OS thread scheduler (see bug #4785).
|
||||
mViewer->setUseConfigureAffinity(false);
|
||||
#endif
|
||||
|
||||
mScreenCaptureOperation = new WriteScreenshotToFileOperation(mCfgMgr.getUserDataPath().string(),
|
||||
Settings::Manager::getString("screenshot format", "General"));
|
||||
|
||||
|
@ -864,7 +869,7 @@ void OMW::Engine::go()
|
|||
// start in main menu
|
||||
mEnvironment.getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
|
||||
mEnvironment.getSoundManager()->playTitleMusic();
|
||||
std::string logo = mFallbackMap["Movies_Morrowind_Logo"];
|
||||
const std::string& logo = Fallback::Map::getString("Movies_Morrowind_Logo");
|
||||
if (!logo.empty())
|
||||
mEnvironment.getWindowManager()->playVideo(logo, true);
|
||||
}
|
||||
|
@ -949,11 +954,6 @@ void OMW::Engine::setEncoding(const ToUTF8::FromType& encoding)
|
|||
mEncoding = encoding;
|
||||
}
|
||||
|
||||
void OMW::Engine::setFallbackValues(std::map<std::string,std::string> fallbackMap)
|
||||
{
|
||||
mFallbackMap = fallbackMap;
|
||||
}
|
||||
|
||||
void OMW::Engine::setScriptConsoleMode (bool enabled)
|
||||
{
|
||||
mScriptConsoleMode = enabled;
|
||||
|
|
|
@ -91,7 +91,6 @@ namespace OMW
|
|||
bool mCompileAllDialogue;
|
||||
int mWarningsMode;
|
||||
std::string mFocusName;
|
||||
std::map<std::string,std::string> mFallbackMap;
|
||||
bool mScriptConsoleMode;
|
||||
std::string mStartupScript;
|
||||
int mActivationDistanceOverride;
|
||||
|
@ -182,8 +181,6 @@ namespace OMW
|
|||
/// Font encoding
|
||||
void setEncoding(const ToUTF8::FromType& encoding);
|
||||
|
||||
void setFallbackValues(std::map<std::string,std::string> map);
|
||||
|
||||
/// Enable console-only script functionality
|
||||
void setScriptConsoleMode (bool enabled);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <components/version/version.hpp>
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
#include <components/files/escape.hpp>
|
||||
#include <components/fallback/fallback.hpp>
|
||||
#include <components/fallback/validate.hpp>
|
||||
#include <components/debug/debugging.hpp>
|
||||
#include <components/misc/rng.hpp>
|
||||
|
@ -314,8 +315,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
engine.setSaveGameFile (variables["load-savegame"].as<Files::EscapeHashString>().toStdString());
|
||||
|
||||
// other settings
|
||||
Fallback::Map::init(variables["fallback"].as<FallbackMap>().mMap);
|
||||
engine.setSoundUsage(!variables["no-sound"].as<bool>());
|
||||
engine.setFallbackValues(variables["fallback"].as<FallbackMap>().mMap);
|
||||
engine.setActivationDistanceOverride (variables["activate-dist"].as<int>());
|
||||
engine.enableFontExport(variables["export-fonts"].as<bool>());
|
||||
engine.setRandomSeed(variables["random-seed"].as<unsigned int>());
|
||||
|
|
|
@ -73,11 +73,6 @@ namespace MWWorld
|
|||
typedef std::vector<std::pair<MWWorld::Ptr,MWMechanics::Movement> > PtrMovementList;
|
||||
}
|
||||
|
||||
namespace Fallback
|
||||
{
|
||||
class Map;
|
||||
}
|
||||
|
||||
namespace MWBase
|
||||
{
|
||||
/// \brief Interface for the World (implemented in MWWorld)
|
||||
|
@ -131,8 +126,6 @@ namespace MWBase
|
|||
|
||||
virtual void adjustSky() = 0;
|
||||
|
||||
virtual const Fallback::Map *getFallback () const = 0;
|
||||
|
||||
virtual MWWorld::Player& getPlayer() = 0;
|
||||
virtual MWWorld::Ptr getPlayerPtr() = 0;
|
||||
virtual MWWorld::ConstPtr getPlayerConstPtr() const = 0;
|
||||
|
@ -631,8 +624,9 @@ namespace MWBase
|
|||
{
|
||||
Rest_Allowed = 0,
|
||||
Rest_OnlyWaiting = 1,
|
||||
Rest_PlayerIsUnderwater = 2,
|
||||
Rest_EnemiesAreNearby = 3
|
||||
Rest_PlayerIsInAir = 2,
|
||||
Rest_PlayerIsUnderwater = 3,
|
||||
Rest_EnemiesAreNearby = 4
|
||||
};
|
||||
|
||||
/// check if the player is allowed to rest
|
||||
|
|
|
@ -466,7 +466,8 @@ namespace MWClass
|
|||
if (!successful)
|
||||
{
|
||||
// Missed
|
||||
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, "miss", 1.0f, 1.0f);
|
||||
if (!attacker.isEmpty() && attacker == MWMechanics::getPlayer())
|
||||
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, "miss", 1.0f, 1.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -856,6 +857,8 @@ namespace MWClass
|
|||
if(name == "left")
|
||||
{
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
if(world->isFlying(ptr))
|
||||
return -1;
|
||||
osg::Vec3f pos(ptr.getRefData().getPosition().asVec3());
|
||||
if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr))
|
||||
return ESM::SoundGenerator::SwimLeft;
|
||||
|
@ -866,6 +869,8 @@ namespace MWClass
|
|||
if(name == "right")
|
||||
{
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
if(world->isFlying(ptr))
|
||||
return -1;
|
||||
osg::Vec3f pos(ptr.getRefData().getPosition().asVec3());
|
||||
if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr))
|
||||
return ESM::SoundGenerator::SwimRight;
|
||||
|
@ -911,13 +916,7 @@ namespace MWClass
|
|||
|
||||
int Creature::getBloodTexture(const MWWorld::ConstPtr &ptr) const
|
||||
{
|
||||
int flags = ptr.get<ESM::Creature>()->mBase->mFlags;
|
||||
|
||||
if (flags & ESM::Creature::Skeleton)
|
||||
return 1;
|
||||
if (flags & ESM::Creature::Metal)
|
||||
return 2;
|
||||
return 0;
|
||||
return ptr.get<ESM::Creature>()->mBase->mBloodType;
|
||||
}
|
||||
|
||||
void Creature::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||
|
|
|
@ -800,7 +800,8 @@ namespace MWClass
|
|||
if (!successful)
|
||||
{
|
||||
// Missed
|
||||
sndMgr->playSound3D(ptr, "miss", 1.0f, 1.0f);
|
||||
if (!attacker.isEmpty() && attacker == MWMechanics::getPlayer())
|
||||
sndMgr->playSound3D(ptr, "miss", 1.0f, 1.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1399,6 +1400,8 @@ namespace MWClass
|
|||
if(name == "left" || name == "right")
|
||||
{
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
if(world->isFlying(ptr))
|
||||
return std::string();
|
||||
osg::Vec3f pos(ptr.getRefData().getPosition().asVec3());
|
||||
if(world->isSwimming(ptr))
|
||||
return (name == "left") ? "Swim Left" : "Swim Right";
|
||||
|
@ -1468,13 +1471,7 @@ namespace MWClass
|
|||
|
||||
int Npc::getBloodTexture(const MWWorld::ConstPtr &ptr) const
|
||||
{
|
||||
const MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
||||
|
||||
if (ref->mBase->mFlags & ESM::NPC::Skeleton)
|
||||
return 1;
|
||||
if (ref->mBase->mFlags & ESM::NPC::Metal)
|
||||
return 2;
|
||||
return 0;
|
||||
return ptr.get<ESM::NPC>()->mBase->mBloodType;
|
||||
}
|
||||
|
||||
void Npc::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||
|
|
|
@ -62,8 +62,7 @@ namespace MWDialogue
|
|||
DialogueManager::DialogueManager (const Compiler::Extensions& extensions, Translation::Storage& translationDataStorage) :
|
||||
mTranslationDataStorage(translationDataStorage)
|
||||
, mCompilerContext (MWScript::CompilerContext::Type_Dialogue)
|
||||
, mErrorStream(std::cout.rdbuf())
|
||||
, mErrorHandler(mErrorStream)
|
||||
, mErrorHandler()
|
||||
, mTalkedTo(false)
|
||||
, mTemporaryDispositionChange(0.f)
|
||||
, mPermanentDispositionChange(0.f)
|
||||
|
@ -241,8 +240,7 @@ namespace MWDialogue
|
|||
|
||||
if (!success)
|
||||
{
|
||||
Log(Debug::Warning)
|
||||
<< "Warning: compiling failed (dialogue script)\n" << cmd << "\n\n";
|
||||
Log(Debug::Error) << "Error: compiling failed (dialogue script): \n" << cmd << "\n";
|
||||
}
|
||||
|
||||
return success;
|
||||
|
|
|
@ -33,7 +33,6 @@ namespace MWDialogue
|
|||
|
||||
Translation::Storage& mTranslationDataStorage;
|
||||
MWScript::CompilerContext mCompilerContext;
|
||||
std::ostream mErrorStream;
|
||||
Compiler::StreamErrorHandler mErrorHandler;
|
||||
|
||||
MWWorld::Ptr mActor;
|
||||
|
|
|
@ -28,8 +28,7 @@ void test(const MWWorld::Ptr& actor, int &compiled, int &total, const Compiler::
|
|||
|
||||
MWScript::CompilerContext compilerContext(MWScript::CompilerContext::Type_Dialogue);
|
||||
compilerContext.setExtensions(extensions);
|
||||
std::ostream errorStream(std::cout.rdbuf());
|
||||
Compiler::StreamErrorHandler errorHandler(errorStream);
|
||||
Compiler::StreamErrorHandler errorHandler;
|
||||
errorHandler.setWarningsMode (warningsMode);
|
||||
|
||||
const MWWorld::Store<ESM::Dialogue>& dialogues = MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
|
||||
|
@ -84,8 +83,7 @@ void test(const MWWorld::Ptr& actor, int &compiled, int &total, const Compiler::
|
|||
|
||||
if (!success)
|
||||
{
|
||||
Log(Debug::Warning)
|
||||
<< "compiling failed (dialogue script)\n" << info->mResultScript << "\n\n";
|
||||
Log(Debug::Error) << "Error: compiling failed (dialogue script): \n" << info->mResultScript << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace MWGui
|
|||
{
|
||||
|
||||
BookWindow::BookWindow ()
|
||||
: WindowBase("openmw_book.layout")
|
||||
: BookWindowBase("openmw_book.layout")
|
||||
, mCurrentPage(0)
|
||||
, mTakeButtonShow(true)
|
||||
, mTakeButtonAllowed(true)
|
||||
|
@ -43,10 +43,10 @@ namespace MWGui
|
|||
getWidget(mLeftPage, "LeftPage");
|
||||
getWidget(mRightPage, "RightPage");
|
||||
|
||||
adjustButton(mCloseButton);
|
||||
adjustButton(mTakeButton);
|
||||
adjustButton(mNextPageButton);
|
||||
adjustButton(mPrevPageButton);
|
||||
adjustButton("CloseButton");
|
||||
adjustButton("TakeButton");
|
||||
adjustButton("PrevPageBTN");
|
||||
float scale = adjustButton("NextPageBTN");
|
||||
|
||||
mLeftPage->setNeedMouseFocus(true);
|
||||
mLeftPage->eventMouseWheel += MyGUI::newDelegate(this, &BookWindow::onMouseWheel);
|
||||
|
@ -62,7 +62,7 @@ namespace MWGui
|
|||
{
|
||||
// english button has a 7 pixel wide strip of garbage on its right edge
|
||||
mNextPageButton->setSize(64-7, mNextPageButton->getSize().height);
|
||||
mNextPageButton->setImageCoord(MyGUI::IntCoord(0,0,64-7,mNextPageButton->getSize().height));
|
||||
mNextPageButton->setImageCoord(MyGUI::IntCoord(0,0,(64-7)*scale,mNextPageButton->getSize().height*scale));
|
||||
}
|
||||
|
||||
center();
|
||||
|
@ -187,15 +187,6 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
void BookWindow::adjustButton (Gui::ImageButton* button)
|
||||
{
|
||||
MyGUI::IntSize diff = button->getSize() - button->getRequestedSize();
|
||||
button->setSize(button->getRequestedSize());
|
||||
|
||||
if (button->getAlign().isRight())
|
||||
button->setPosition(button->getPosition() + MyGUI::IntPoint(diff.width,0));
|
||||
}
|
||||
|
||||
void BookWindow::nextPage()
|
||||
{
|
||||
if ((mCurrentPage+1)*2 < mPages.size())
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
namespace MWGui
|
||||
{
|
||||
class BookWindow : public WindowBase
|
||||
class BookWindow : public BookWindowBase
|
||||
{
|
||||
public:
|
||||
BookWindow();
|
||||
|
@ -34,7 +34,6 @@ namespace MWGui
|
|||
|
||||
void updatePages();
|
||||
void clearPages();
|
||||
void adjustButton(Gui::ImageButton* button);
|
||||
|
||||
private:
|
||||
typedef std::pair<int, int> Page;
|
||||
|
|
|
@ -33,14 +33,15 @@ namespace
|
|||
};
|
||||
|
||||
const ESM::Class::Specialization mSpecializations[3]={ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}; // The specialization for each answer
|
||||
Step sGenerateClassSteps(int number) {
|
||||
Step sGenerateClassSteps(int number)
|
||||
{
|
||||
number++;
|
||||
const Fallback::Map* fallback=MWBase::Environment::get().getWorld()->getFallback();
|
||||
Step step = {fallback->getFallbackString("Question_"+MyGUI::utility::toString(number)+"_Question"),
|
||||
{fallback->getFallbackString("Question_"+MyGUI::utility::toString(number)+"_AnswerOne"),
|
||||
fallback->getFallbackString("Question_"+MyGUI::utility::toString(number)+"_AnswerTwo"),
|
||||
fallback->getFallbackString("Question_"+MyGUI::utility::toString(number)+"_AnswerThree")},
|
||||
"vo\\misc\\chargen qa"+MyGUI::utility::toString(number)+".wav"
|
||||
Step step = {
|
||||
Fallback::Map::getString("Question_"+MyGUI::utility::toString(number)+"_Question"),
|
||||
{Fallback::Map::getString("Question_"+MyGUI::utility::toString(number)+"_AnswerOne"),
|
||||
Fallback::Map::getString("Question_"+MyGUI::utility::toString(number)+"_AnswerTwo"),
|
||||
Fallback::Map::getString("Question_"+MyGUI::utility::toString(number)+"_AnswerThree")},
|
||||
"vo\\misc\\chargen qa"+MyGUI::utility::toString(number)+".wav"
|
||||
};
|
||||
return step;
|
||||
}
|
||||
|
|
|
@ -254,16 +254,6 @@ namespace MWGui
|
|||
if (plainText.size() && brAtEnd)
|
||||
plainText.erase(plainText.end()-1);
|
||||
|
||||
#if (MYGUI_VERSION < MYGUI_DEFINE_VERSION(3, 2, 2))
|
||||
// splitting won't be fully functional until 3.2.2 (see TextElement::pageSplit())
|
||||
// hack: prevent newlines at the end of the book possibly creating unnecessary pages
|
||||
if (event == BookTextParser::Event_EOF)
|
||||
{
|
||||
while (plainText.size() && plainText[plainText.size()-1] == '\n')
|
||||
plainText.erase(plainText.end()-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!plainText.empty() || brBeforeLastTag || isPrevImg)
|
||||
{
|
||||
TextElement elem(paper, pag, mBlockStyle,
|
||||
|
@ -443,8 +433,6 @@ namespace MWGui
|
|||
int ret = mPaginator.getCurrentTop() + lastLine * lineHeight;
|
||||
|
||||
// first empty lines that would go to the next page should be ignored
|
||||
// unfortunately, getLineInfo method won't be available until 3.2.2
|
||||
#if (MYGUI_VERSION >= MYGUI_DEFINE_VERSION(3, 2, 2))
|
||||
mPaginator.setIgnoreLeadingEmptyLines(true);
|
||||
|
||||
const MyGUI::VectorLineInfo & lines = mEditBox->getSubWidgetText()->castType<MyGUI::EditText>()->getLineInfo();
|
||||
|
@ -458,7 +446,6 @@ namespace MWGui
|
|||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <MyGUI_FactoryManager.h>
|
||||
#include <MyGUI_ImageBox.h>
|
||||
#include <MyGUI_RenderManager.h>
|
||||
#include <MyGUI_TextBox.h>
|
||||
|
||||
// correctIconPath
|
||||
|
@ -30,6 +31,7 @@ namespace
|
|||
|
||||
namespace MWGui
|
||||
{
|
||||
std::map<std::string, float> ItemWidget::mScales;
|
||||
|
||||
ItemWidget::ItemWidget()
|
||||
: mItem(nullptr)
|
||||
|
@ -146,10 +148,29 @@ namespace MWGui
|
|||
if (backgroundTex != "")
|
||||
backgroundTex += ".dds";
|
||||
|
||||
float scale = 1.f;
|
||||
if (!backgroundTex.empty())
|
||||
{
|
||||
auto found = mScales.find(backgroundTex);
|
||||
if (found == mScales.end())
|
||||
{
|
||||
// By default, background icons are supposed to use the 42x42 part of 64x64 image.
|
||||
// If the image has a different size, we should use a different chunk size
|
||||
// Cache result to do not retrieve background texture every frame.
|
||||
MyGUI::ITexture* texture = MyGUI::RenderManager::getInstance().getTexture(backgroundTex);
|
||||
if (texture)
|
||||
scale = texture->getHeight() / 64.f;
|
||||
|
||||
mScales[backgroundTex] = scale;
|
||||
}
|
||||
else
|
||||
scale = found->second;
|
||||
}
|
||||
|
||||
if (state == Barter && !isMagic)
|
||||
setFrame(backgroundTex, MyGUI::IntCoord(2,2,42,42));
|
||||
setFrame(backgroundTex, MyGUI::IntCoord(2*scale,2*scale,44*scale,44*scale));
|
||||
else
|
||||
setFrame(backgroundTex, MyGUI::IntCoord(0,0,42,42));
|
||||
setFrame(backgroundTex, MyGUI::IntCoord(0,0,44*scale,44*scale));
|
||||
|
||||
setIcon(ptr);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ namespace MWGui
|
|||
|
||||
std::string mCurrentIcon;
|
||||
std::string mCurrentFrame;
|
||||
|
||||
static std::map<std::string, float> mScales;
|
||||
};
|
||||
|
||||
class SpellWidget : public ItemWidget
|
||||
|
|
|
@ -153,7 +153,7 @@ namespace
|
|||
}
|
||||
|
||||
adjustButton(PrevPageBTN);
|
||||
adjustButton(NextPageBTN);
|
||||
float nextButtonScale = adjustButton(NextPageBTN);
|
||||
adjustButton(CloseBTN);
|
||||
adjustButton(CancelBTN);
|
||||
adjustButton(JournalBTN);
|
||||
|
@ -168,7 +168,7 @@ namespace
|
|||
{
|
||||
// english button has a 7 pixel wide strip of garbage on its right edge
|
||||
nextButton->setSize(64-7, nextButton->getSize().height);
|
||||
nextButton->setImageCoord(MyGUI::IntCoord(0,0,64-7,nextButton->getSize().height));
|
||||
nextButton->setImageCoord(MyGUI::IntCoord(0,0,(64-7)*nextButtonScale,nextButton->getSize().height*nextButtonScale));
|
||||
}
|
||||
|
||||
if (!questList)
|
||||
|
@ -226,17 +226,6 @@ namespace
|
|||
mTopicsMode = false;
|
||||
}
|
||||
|
||||
void adjustButton (char const * name)
|
||||
{
|
||||
Gui::ImageButton* button = getWidget<Gui::ImageButton>(name);
|
||||
|
||||
MyGUI::IntSize diff = button->getSize() - button->getRequestedSize();
|
||||
button->setSize(button->getRequestedSize());
|
||||
|
||||
if (button->getAlign().isRight())
|
||||
button->setPosition(button->getPosition() + MyGUI::IntPoint(diff.width,0));
|
||||
}
|
||||
|
||||
void onOpen()
|
||||
{
|
||||
if (!MWBase::Environment::get().getWindowManager ()->getJournalAllowed ())
|
||||
|
@ -665,7 +654,7 @@ MWGui::JournalWindow * MWGui::JournalWindow::create (JournalViewModel::Ptr Model
|
|||
}
|
||||
|
||||
MWGui::JournalWindow::JournalWindow()
|
||||
:WindowBase("openmw_journal.layout")
|
||||
: BookWindowBase("openmw_journal.layout")
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace MWGui
|
|||
{
|
||||
struct JournalViewModel;
|
||||
|
||||
struct JournalWindow : public WindowBase
|
||||
struct JournalWindow : public BookWindowBase
|
||||
{
|
||||
JournalWindow();
|
||||
|
||||
|
|
|
@ -140,10 +140,10 @@ namespace MWGui
|
|||
mLevelText->setCaptionWithReplacing("#{sLevelUpMenu1} " + MyGUI::utility::toString(level));
|
||||
|
||||
std::string levelupdescription;
|
||||
levelupdescription=world->getFallback()->getFallbackString("Level_Up_Level"+MyGUI::utility::toString(level));
|
||||
levelupdescription = Fallback::Map::getString("Level_Up_Level"+MyGUI::utility::toString(level));
|
||||
|
||||
if (levelupdescription == "")
|
||||
levelupdescription=world->getFallback()->getFallbackString("Level_Up_Default");
|
||||
levelupdescription = Fallback::Map::getString("Level_Up_Default");
|
||||
|
||||
mLevelDescription->setCaption (levelupdescription);
|
||||
|
||||
|
|
|
@ -302,15 +302,18 @@ namespace MWGui
|
|||
Gui::ImageButton* button = mButtons[buttonId];
|
||||
button->setVisible(true);
|
||||
|
||||
// By default, assume that all menu buttons textures should have 64 height.
|
||||
// If they have a different resolution, scale them.
|
||||
MyGUI::IntSize requested = button->getRequestedSize();
|
||||
float scale = requested.height / 64.f;
|
||||
|
||||
button->setImageCoord(MyGUI::IntCoord(0, 0, requested.width, requested.height));
|
||||
// Trim off some of the excessive padding
|
||||
// TODO: perhaps do this within ImageButton?
|
||||
int height = requested.height-16;
|
||||
button->setImageTile(MyGUI::IntSize(requested.width, height));
|
||||
button->setCoord((maxwidth-requested.width) / 2, curH, requested.width, height);
|
||||
curH += height;
|
||||
int height = requested.height;
|
||||
button->setImageTile(MyGUI::IntSize(requested.width, requested.height-16*scale));
|
||||
button->setCoord((maxwidth-requested.width/scale) / 2, curH, requested.width/scale, height/scale-16);
|
||||
curH += height/scale-16;
|
||||
}
|
||||
|
||||
if (state == MWBase::StateManager::State_NoGame)
|
||||
|
|
83
apps/openmw/mwgui/resourceskin.cpp
Normal file
83
apps/openmw/mwgui/resourceskin.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
#include "resourceskin.hpp"
|
||||
|
||||
#include <MyGUI_RenderManager.h>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
void resizeSkin(MyGUI::xml::ElementPtr _node)
|
||||
{
|
||||
_node->setAttribute("type", "ResourceSkin");
|
||||
const std::string size = _node->findAttribute("size");
|
||||
if (!size.empty())
|
||||
return;
|
||||
|
||||
const std::string textureName = _node->findAttribute("texture");
|
||||
if (textureName.empty())
|
||||
return;
|
||||
|
||||
MyGUI::ITexture* texture = MyGUI::RenderManager::getInstance().getTexture(textureName);
|
||||
if (!texture)
|
||||
return;
|
||||
|
||||
MyGUI::IntCoord coord(0, 0, texture->getWidth(), texture->getHeight());
|
||||
MyGUI::xml::ElementEnumerator basis = _node->getElementEnumerator();
|
||||
const std::string textureSize = std::to_string(coord.width) + " " + std::to_string(coord.height);
|
||||
_node->addAttribute("size", textureSize);
|
||||
while (basis.next())
|
||||
{
|
||||
if (basis->getName() != "BasisSkin")
|
||||
continue;
|
||||
|
||||
const std::string basisSkinType = basis->findAttribute("type");
|
||||
if (Misc::StringUtils::ciEqual(basisSkinType, "SimpleText"))
|
||||
continue;
|
||||
|
||||
const std::string offset = basis->findAttribute("offset");
|
||||
if (!offset.empty())
|
||||
continue;
|
||||
|
||||
basis->addAttribute("offset", coord);
|
||||
|
||||
MyGUI::xml::ElementEnumerator state = basis->getElementEnumerator();
|
||||
while (state.next())
|
||||
{
|
||||
if (state->getName() == "State")
|
||||
{
|
||||
const std::string stateOffset = state->findAttribute("offset");
|
||||
if (!stateOffset.empty())
|
||||
continue;
|
||||
|
||||
state->addAttribute("offset", coord);
|
||||
if (Misc::StringUtils::ciEqual(basisSkinType, "TileRect"))
|
||||
{
|
||||
MyGUI::xml::ElementEnumerator property = state->getElementEnumerator();
|
||||
bool hasTileSize = false;
|
||||
while (property.next("Property"))
|
||||
{
|
||||
const std::string key = property->findAttribute("key");
|
||||
if (key != "TileSize")
|
||||
continue;
|
||||
|
||||
hasTileSize = true;
|
||||
}
|
||||
|
||||
if (!hasTileSize)
|
||||
{
|
||||
MyGUI::xml::ElementPtr tileSizeProperty = state->createChild("Property");
|
||||
tileSizeProperty->addAttribute("key", "TileSize");
|
||||
tileSizeProperty->addAttribute("value", textureSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AutoSizedResourceSkin::deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version)
|
||||
{
|
||||
resizeSkin(_node);
|
||||
Base::deserialization(_node, _version);
|
||||
}
|
||||
}
|
18
apps/openmw/mwgui/resourceskin.hpp
Normal file
18
apps/openmw/mwgui/resourceskin.hpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef MWGUI_RESOURCESKIN_H
|
||||
#define MWGUI_RESOURCESKIN_H
|
||||
|
||||
#include <MyGUI_ResourceSkin.h>
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class AutoSizedResourceSkin : public MyGUI::ResourceSkin
|
||||
{
|
||||
MYGUI_RTTI_DERIVED( AutoSizedResourceSkin )
|
||||
|
||||
public:
|
||||
virtual void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -16,23 +16,11 @@
|
|||
|
||||
#include "formatting.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
void adjustButton (Gui::ImageButton* button)
|
||||
{
|
||||
MyGUI::IntSize diff = button->getSize() - button->getRequestedSize();
|
||||
button->setSize(button->getRequestedSize());
|
||||
|
||||
if (button->getAlign().isRight())
|
||||
button->setPosition(button->getPosition() + MyGUI::IntPoint(diff.width,0));
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
||||
ScrollWindow::ScrollWindow ()
|
||||
: WindowBase("openmw_scroll.layout")
|
||||
: BookWindowBase("openmw_scroll.layout")
|
||||
, mTakeButtonShow(true)
|
||||
, mTakeButtonAllowed(true)
|
||||
{
|
||||
|
@ -44,8 +32,8 @@ namespace MWGui
|
|||
getWidget(mTakeButton, "TakeButton");
|
||||
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ScrollWindow::onTakeButtonClicked);
|
||||
|
||||
adjustButton(mCloseButton);
|
||||
adjustButton(mTakeButton);
|
||||
adjustButton("CloseButton");
|
||||
adjustButton("TakeButton");
|
||||
|
||||
mCloseButton->eventKeyButtonPressed += MyGUI::newDelegate(this, &ScrollWindow::onKeyButtonPressed);
|
||||
mTakeButton->eventKeyButtonPressed += MyGUI::newDelegate(this, &ScrollWindow::onKeyButtonPressed);
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Gui
|
|||
|
||||
namespace MWGui
|
||||
{
|
||||
class ScrollWindow : public WindowBase
|
||||
class ScrollWindow : public BookWindowBase
|
||||
{
|
||||
public:
|
||||
ScrollWindow ();
|
||||
|
|
|
@ -71,11 +71,8 @@ namespace MWGui
|
|||
std::set<MWWorld::Ptr> followers;
|
||||
MWWorld::ActionTeleport::getFollowersToTeleport(player, followers);
|
||||
|
||||
// Apply followers cost, in vanilla one follower travels for free
|
||||
if (Settings::Manager::getBool("charge for every follower travelling", "Game"))
|
||||
price *= 1 + static_cast<int>(followers.size());
|
||||
else
|
||||
price *= std::max(1, static_cast<int>(followers.size()));
|
||||
// Apply followers cost, unlike vanilla the first follower doesn't travel for free
|
||||
price *= 1 + static_cast<int>(followers.size());
|
||||
|
||||
int lineHeight = MWBase::Environment::get().getWindowManager()->getFontHeight() + 2;
|
||||
|
||||
|
|
|
@ -91,10 +91,17 @@ namespace MWGui
|
|||
mTimeAdvancer.eventInterrupted += MyGUI::newDelegate(this, &WaitDialog::onWaitingInterrupted);
|
||||
mTimeAdvancer.eventFinished += MyGUI::newDelegate(this, &WaitDialog::onWaitingFinished);
|
||||
}
|
||||
|
||||
void WaitDialog::onReferenceUnavailable ()
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Rest);
|
||||
resetReference();
|
||||
}
|
||||
|
||||
void WaitDialog::setPtr(const MWWorld::Ptr &ptr)
|
||||
{
|
||||
setCanRest(!ptr.isEmpty() || MWBase::Environment::get().getWorld ()->canRest () == MWBase::World::Rest_Allowed);
|
||||
mPtr = ptr;
|
||||
setCanRest(!mPtr.isEmpty() || MWBase::Environment::get().getWorld ()->canRest () == MWBase::World::Rest_Allowed);
|
||||
|
||||
if (mUntilHealedButton->getVisible())
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mUntilHealedButton);
|
||||
|
@ -111,6 +118,7 @@ namespace MWGui
|
|||
{
|
||||
mSleeping = false;
|
||||
mTimeAdvancer.stop();
|
||||
resetReference();
|
||||
}
|
||||
|
||||
void WaitDialog::onOpen()
|
||||
|
@ -140,7 +148,13 @@ namespace MWGui
|
|||
}
|
||||
else if (canRest == MWBase::World::Rest_PlayerIsUnderwater)
|
||||
{
|
||||
// resting underwater or mid-air not allowed
|
||||
// resting underwater not allowed
|
||||
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage1}");
|
||||
MWBase::Environment::get().getWindowManager()->popGuiMode ();
|
||||
}
|
||||
else if (mPtr.isEmpty() && canRest == MWBase::World::Rest_PlayerIsInAir)
|
||||
{
|
||||
// Resting in air is not allowed either, unless you're using a bed
|
||||
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage1}");
|
||||
MWBase::Environment::get().getWindowManager()->popGuiMode ();
|
||||
}
|
||||
|
@ -337,6 +351,8 @@ namespace MWGui
|
|||
|
||||
void WaitDialog::onFrame(float dt)
|
||||
{
|
||||
checkReferenceAvailable();
|
||||
|
||||
mTimeAdvancer.onFrame(dt);
|
||||
|
||||
if (mFadeTimeRemaining <= 0)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "timeadvancer.hpp"
|
||||
|
||||
#include "windowbase.hpp"
|
||||
#include "referenceinterface.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
@ -22,7 +23,7 @@ namespace MWGui
|
|||
MyGUI::TextBox* mProgressText;
|
||||
};
|
||||
|
||||
class WaitDialog : public WindowBase
|
||||
class WaitDialog : public WindowBase, public ReferenceInterface
|
||||
{
|
||||
public:
|
||||
WaitDialog();
|
||||
|
@ -63,6 +64,8 @@ namespace MWGui
|
|||
|
||||
WaitDialogProgressBar mProgressBar;
|
||||
|
||||
virtual void onReferenceUnavailable();
|
||||
|
||||
void onUntilHealedButtonClicked(MyGUI::Widget* sender);
|
||||
void onWaitButtonClicked(MyGUI::Widget* sender);
|
||||
void onCancelButtonClicked(MyGUI::Widget* sender);
|
||||
|
|
|
@ -535,9 +535,7 @@ namespace MWGui
|
|||
, mRepeatStepTime(0.1f)
|
||||
, mIsIncreasing(true)
|
||||
{
|
||||
#if MYGUI_VERSION >= MYGUI_DEFINE_VERSION(3,2,2)
|
||||
ScrollBar::setRepeatEnabled(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
MWScrollBar::~MWScrollBar()
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
||||
#include <components/widgets/imagebutton.hpp>
|
||||
|
||||
#include "draganddrop.hpp"
|
||||
|
||||
using namespace MWGui;
|
||||
|
@ -120,3 +122,30 @@ void NoDrop::setAlpha(float alpha)
|
|||
if (mWidget)
|
||||
mWidget->setAlpha(alpha);
|
||||
}
|
||||
|
||||
BookWindowBase::BookWindowBase(const std::string& parLayout)
|
||||
: WindowBase(parLayout)
|
||||
{
|
||||
}
|
||||
|
||||
float BookWindowBase::adjustButton (char const * name)
|
||||
{
|
||||
Gui::ImageButton* button;
|
||||
WindowBase::getWidget (button, name);
|
||||
MyGUI::IntSize requested = button->getRequestedSize();
|
||||
float scale = requested.height / button->getSize().height;
|
||||
MyGUI::IntSize newSize = requested;
|
||||
newSize.width /= scale;
|
||||
newSize.height /= scale;
|
||||
button->setSize(newSize);
|
||||
|
||||
if (button->getAlign().isRight())
|
||||
{
|
||||
MyGUI::IntSize diff = (button->getSize() - requested);
|
||||
diff.width /= scale;
|
||||
diff.height /= scale;
|
||||
button->setPosition(button->getPosition() + MyGUI::IntPoint(diff.width,0));
|
||||
}
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
|
|
@ -82,6 +82,15 @@ namespace MWGui
|
|||
DragAndDrop* mDrag;
|
||||
bool mTransparent;
|
||||
};
|
||||
|
||||
class BookWindowBase : public WindowBase
|
||||
{
|
||||
public:
|
||||
BookWindowBase(const std::string& parLayout);
|
||||
|
||||
protected:
|
||||
float adjustButton (char const * name);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <MyGUI_InputManager.h>
|
||||
#include <MyGUI_Gui.h>
|
||||
#include <MyGUI_ClipboardManager.h>
|
||||
#include <MyGUI_RenderManager.h>
|
||||
#include <MyGUI_WidgetManager.h>
|
||||
|
||||
#include <SDL_keyboard.h>
|
||||
|
@ -124,6 +123,7 @@
|
|||
#include "jailscreen.hpp"
|
||||
#include "itemchargeview.hpp"
|
||||
#include "keyboardnavigation.hpp"
|
||||
#include "resourceskin.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -141,7 +141,7 @@ namespace MWGui
|
|||
WindowManager::WindowManager(
|
||||
osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
||||
const std::string& logpath, const std::string& resourcePath, bool consoleOnlyScripts, Translation::Storage& translationDataStorage,
|
||||
ToUTF8::FromType encoding, bool exportFonts, const std::map<std::string, std::string>& fallbackMap, const std::string& versionDescription, const std::string& userDataPath)
|
||||
ToUTF8::FromType encoding, bool exportFonts, const std::string& versionDescription, const std::string& userDataPath)
|
||||
: mStore(nullptr)
|
||||
, mResourceSystem(resourceSystem)
|
||||
, mWorkQueue(workQueue)
|
||||
|
@ -201,7 +201,6 @@ namespace MWGui
|
|||
, mForceHidden(GW_None)
|
||||
, mAllowed(GW_ALL)
|
||||
, mRestAllowed(true)
|
||||
, mFallbackMap(fallbackMap)
|
||||
, mShowOwned(0)
|
||||
, mEncoding(encoding)
|
||||
, mFontHeight(16)
|
||||
|
@ -253,6 +252,7 @@ namespace MWGui
|
|||
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerFollowMouse>("Controller");
|
||||
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer");
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<AutoSizedResourceSkin>("Resource", "AutoSizedResourceSkin");
|
||||
MyGUI::ResourceManager::getInstance().load("core.xml");
|
||||
loadUserFonts();
|
||||
|
||||
|
@ -303,14 +303,13 @@ namespace MWGui
|
|||
|
||||
void WindowManager::loadFontDelegate(MyGUI::xml::ElementPtr _node, const std::string& _file, MyGUI::Version _version)
|
||||
{
|
||||
const std::string templateName = "Journalbook ";
|
||||
MyGUI::xml::ElementEnumerator font = _node->getElementEnumerator();
|
||||
MyGUI::xml::ElementEnumerator resourceNode = _node->getElementEnumerator();
|
||||
bool createCopy = false;
|
||||
while (font.next("Resource"))
|
||||
while (resourceNode.next("Resource"))
|
||||
{
|
||||
std::string type, name;
|
||||
font->findAttribute("type", type);
|
||||
font->findAttribute("name", name);
|
||||
resourceNode->findAttribute("type", type);
|
||||
resourceNode->findAttribute("name", name);
|
||||
|
||||
if (name.empty())
|
||||
continue;
|
||||
|
@ -328,18 +327,19 @@ namespace MWGui
|
|||
float uiScale = Settings::Manager::getFloat("scaling factor", "GUI");
|
||||
resolution *= uiScale;
|
||||
|
||||
MyGUI::xml::ElementPtr resolutionNode = font->createChild("Property");
|
||||
MyGUI::xml::ElementPtr resolutionNode = resourceNode->createChild("Property");
|
||||
resolutionNode->addAttribute("key", "Resolution");
|
||||
resolutionNode->addAttribute("value", std::to_string(resolution));
|
||||
|
||||
MyGUI::xml::ElementPtr sizeNode = font->createChild("Property");
|
||||
MyGUI::xml::ElementPtr sizeNode = resourceNode->createChild("Property");
|
||||
sizeNode->addAttribute("key", "Size");
|
||||
sizeNode->addAttribute("value", std::to_string(mFontHeight));
|
||||
}
|
||||
else if (Misc::StringUtils::ciEqual(type, "ResourceSkin"))
|
||||
else if (Misc::StringUtils::ciEqual(type, "ResourceSkin") ||
|
||||
Misc::StringUtils::ciEqual(type, "AutoSizedResourceSkin"))
|
||||
{
|
||||
// We should adjust line height for MyGUI widgets depending on font size
|
||||
MyGUI::xml::ElementPtr heightNode = font->createChild("Property");
|
||||
MyGUI::xml::ElementPtr heightNode = resourceNode->createChild("Property");
|
||||
heightNode->addAttribute("key", "HeightLine");
|
||||
heightNode->addAttribute("value", std::to_string(mFontHeight+2));
|
||||
}
|
||||
|
@ -1255,7 +1255,7 @@ namespace MWGui
|
|||
{
|
||||
_result = mTranslationDataStorage.translateCellName(tag.substr(tokenLength));
|
||||
}
|
||||
else if (Gui::replaceTag(tag, _result, mFallbackMap))
|
||||
else if (Gui::replaceTag(tag, _result))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -1575,6 +1575,32 @@ namespace MWGui
|
|||
if (getMode() != GM_Inventory)
|
||||
return;
|
||||
|
||||
std::string settingName;
|
||||
switch (wnd)
|
||||
{
|
||||
case GW_Inventory:
|
||||
settingName = "inventory";
|
||||
break;
|
||||
case GW_Map:
|
||||
settingName = "map";
|
||||
break;
|
||||
case GW_Magic:
|
||||
settingName = "spells";
|
||||
break;
|
||||
case GW_Stats:
|
||||
settingName = "stats";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!settingName.empty())
|
||||
{
|
||||
settingName += " hidden";
|
||||
bool hidden = Settings::Manager::getBool(settingName, "Windows");
|
||||
Settings::Manager::setBool(settingName, "Windows", !hidden);
|
||||
}
|
||||
|
||||
mShown = (GuiWindow)(mShown ^ wnd);
|
||||
updateVisible();
|
||||
}
|
||||
|
@ -2058,12 +2084,20 @@ namespace MWGui
|
|||
void WindowManager::updatePinnedWindows()
|
||||
{
|
||||
mInventoryWindow->setPinned(Settings::Manager::getBool("inventory pin", "Windows"));
|
||||
if (Settings::Manager::getBool("inventory hidden", "Windows"))
|
||||
mShown = (GuiWindow)(mShown ^ GW_Inventory);
|
||||
|
||||
mMap->setPinned(Settings::Manager::getBool("map pin", "Windows"));
|
||||
if (Settings::Manager::getBool("map hidden", "Windows"))
|
||||
mShown = (GuiWindow)(mShown ^ GW_Map);
|
||||
|
||||
mSpellWindow->setPinned(Settings::Manager::getBool("spells pin", "Windows"));
|
||||
if (Settings::Manager::getBool("spells hidden", "Windows"))
|
||||
mShown = (GuiWindow)(mShown ^ GW_Magic);
|
||||
|
||||
mStatsWindow->setPinned(Settings::Manager::getBool("stats pin", "Windows"));
|
||||
if (Settings::Manager::getBool("stats hidden", "Windows"))
|
||||
mShown = (GuiWindow)(mShown ^ GW_Stats);
|
||||
}
|
||||
|
||||
void WindowManager::pinWindow(GuiWindow window)
|
||||
|
@ -2246,6 +2280,9 @@ namespace MWGui
|
|||
|
||||
void WindowManager::createCursors()
|
||||
{
|
||||
// FIXME: currently we do not scale cursor since it is not a MyGUI widget.
|
||||
// In theory, we can do it manually (rescale the cursor image via osg::Imag::scaleImage() and scale the hotspot position).
|
||||
// Unfortunately, this apploach can lead to driver crashes on some setups (e.g. on laptops with nvidia-prime on Linux).
|
||||
MyGUI::ResourceManager::EnumeratorPtr enumerator = MyGUI::ResourceManager::getInstance().getEnumerator();
|
||||
while (enumerator.next())
|
||||
{
|
||||
|
|
|
@ -132,7 +132,7 @@ namespace MWGui
|
|||
|
||||
WindowManager(osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
||||
const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, Translation::Storage& translationDataStorage,
|
||||
ToUTF8::FromType encoding, bool exportFonts, const std::map<std::string,std::string>& fallbackMap, const std::string& versionDescription, const std::string& localPath);
|
||||
ToUTF8::FromType encoding, bool exportFonts, const std::string& versionDescription, const std::string& localPath);
|
||||
virtual ~WindowManager();
|
||||
|
||||
/// Set the ESMStore to use for retrieving of GUI-related strings.
|
||||
|
@ -611,8 +611,6 @@ namespace MWGui
|
|||
|
||||
void updateMap();
|
||||
|
||||
std::map<std::string, std::string> mFallbackMap;
|
||||
|
||||
int mShowOwned;
|
||||
|
||||
ToUTF8::FromType mEncoding;
|
||||
|
|
|
@ -791,7 +791,7 @@ namespace MWInput
|
|||
mMouseLookEnabled = !guiMode;
|
||||
if (guiMode)
|
||||
MWBase::Environment::get().getWindowManager()->showCrosshair(false);
|
||||
MWBase::Environment::get().getWindowManager()->setCursorVisible(guiMode && (mJoystickLastUsed && !mGamepadGuiCursorEnabled));
|
||||
MWBase::Environment::get().getWindowManager()->setCursorVisible(guiMode && (!mJoystickLastUsed || mGamepadGuiCursorEnabled));
|
||||
// if not in gui mode, the camera decides whether to show crosshair or not.
|
||||
}
|
||||
|
||||
|
@ -1403,7 +1403,7 @@ namespace MWInput
|
|||
|
||||
void InputManager::quickKey (int index)
|
||||
{
|
||||
if (!mControlSwitch["playercontrols"])
|
||||
if (!mControlSwitch["playercontrols"] || !mControlSwitch["playerfighting"] || !mControlSwitch["playermagic"])
|
||||
return;
|
||||
if (!checkAllowedToUseItems())
|
||||
return;
|
||||
|
|
|
@ -1725,7 +1725,10 @@ namespace MWMechanics
|
|||
|
||||
if(iter->first.getClass().isNpc())
|
||||
{
|
||||
updateDrowning(iter->first, duration, ctrl->isKnockedOut(), isPlayer);
|
||||
// We can not update drowning state for actors outside of AI distance - they can not resurface to breathe
|
||||
if (inProcessingRange)
|
||||
updateDrowning(iter->first, duration, ctrl->isKnockedOut(), isPlayer);
|
||||
|
||||
calculateNpcStatModifiers(iter->first, duration);
|
||||
|
||||
if (timerUpdateEquippedLight == 0)
|
||||
|
|
|
@ -403,12 +403,9 @@ namespace MWMechanics
|
|||
ESM::Position actorPos = actor.getRefData().getPosition();
|
||||
ESM::Position enemyPos = enemy.getRefData().getPosition();
|
||||
|
||||
const CreatureStats& enemyStats = enemy.getClass().getCreatureStats(enemy);
|
||||
if (enemyStats.getMagicEffects().get(ESM::MagicEffect::Invisibility).getMagnitude() > 0
|
||||
|| enemyStats.getMagicEffects().get(ESM::MagicEffect::Chameleon).getMagnitude() > 0)
|
||||
if (isTargetMagicallyHidden(enemy) && !MWBase::Environment::get().getMechanicsManager()->awarenessCheck(enemy, actor))
|
||||
{
|
||||
if (!MWBase::Environment::get().getMechanicsManager()->awarenessCheck(enemy, actor))
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actor.getClass().isPureWaterCreature(actor))
|
||||
|
|
|
@ -261,7 +261,7 @@ const MWMechanics::PathgridGraph& MWMechanics::AiPackage::getPathGridGraph(const
|
|||
CacheMap::iterator found = cache.find(id);
|
||||
if (found == cache.end())
|
||||
{
|
||||
cache.insert(std::make_pair(id, std::unique_ptr<MWMechanics::PathgridGraph>(new MWMechanics::PathgridGraph(cell))));
|
||||
cache.insert(std::make_pair(id, std::make_unique<MWMechanics::PathgridGraph>(MWMechanics::PathgridGraph(cell))));
|
||||
}
|
||||
return *cache[id].get();
|
||||
}
|
||||
|
@ -335,13 +335,6 @@ bool MWMechanics::AiPackage::doesPathNeedRecalc(const osg::Vec3f& newDest, const
|
|||
|| mPathFinder.getPathCell() != currentCell;
|
||||
}
|
||||
|
||||
bool MWMechanics::AiPackage::isTargetMagicallyHidden(const MWWorld::Ptr& target)
|
||||
{
|
||||
const MagicEffects& magicEffects(target.getClass().getCreatureStats(target).getMagicEffects());
|
||||
return (magicEffects.get(ESM::MagicEffect::Invisibility).getMagnitude() > 0)
|
||||
|| (magicEffects.get(ESM::MagicEffect::Chameleon).getMagnitude() > 75);
|
||||
}
|
||||
|
||||
bool MWMechanics::AiPackage::isNearInactiveCell(osg::Vec3f position)
|
||||
{
|
||||
const ESM::Cell* playerCell(getPlayer().getCell()->getCell());
|
||||
|
|
|
@ -102,8 +102,6 @@ namespace MWMechanics
|
|||
/// Reset pathfinding state
|
||||
void reset();
|
||||
|
||||
bool isTargetMagicallyHidden(const MWWorld::Ptr& target);
|
||||
|
||||
/// Return if actor's rotation speed is sufficient to rotate to the destination pathpoint on the run. Otherwise actor should rotate while standing.
|
||||
static bool isReachableRotatingOnTheRun(const MWWorld::Ptr& actor, const osg::Vec3f& dest);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "movement.hpp"
|
||||
#include "creaturestats.hpp"
|
||||
#include "combat.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include <components/esm/aisequence.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
|
@ -19,9 +18,8 @@ bool isWithinMaxRange(const osg::Vec3f& pos1, const osg::Vec3f& pos2)
|
|||
{
|
||||
// Maximum travel distance for vanilla compatibility.
|
||||
// Was likely meant to prevent NPCs walking into non-loaded exterior cells, but for some reason is used in interior cells as well.
|
||||
// The specific range below is configurable, but its limit is currently 7168 units. Anything greater will break shoddily-written content (*cough* MW *cough*) in bizarre ways.
|
||||
float aiDistance = MWBase::Environment::get().getMechanicsManager()->getActorsProcessingRange();
|
||||
return (pos1 - pos2).length2() <= aiDistance*aiDistance;
|
||||
// We can make this configurable at some point, but the default *must* be the below value. Anything else will break shoddily-written content (*cough* MW *cough*) in bizarre ways.
|
||||
return (pos1 - pos2).length2() <= 7168*7168;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -366,11 +366,6 @@ void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState
|
|||
if (!force && jump == mJumpState && idle == CharState_None)
|
||||
return;
|
||||
|
||||
if (jump == JumpState_InAir)
|
||||
{
|
||||
idle = CharState_None;
|
||||
}
|
||||
|
||||
std::string jumpAnimName;
|
||||
MWRender::Animation::BlendMask jumpmask = MWRender::Animation::BlendMask_All;
|
||||
if (jump != JumpState_None)
|
||||
|
@ -1244,7 +1239,7 @@ bool CharacterController::updateCreatureState()
|
|||
*/
|
||||
|
||||
MWMechanics::CastSpell cast(mPtr, nullptr, false, mCastingManualSpell);
|
||||
cast.playSpellCastingEffects(spellid);
|
||||
cast.playSpellCastingEffects(spellid, false);
|
||||
|
||||
/*
|
||||
Start of tes3mp addition
|
||||
|
@ -1575,9 +1570,31 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
|
|||
stats.getSpells().setSelectedSpell(selectedSpell);
|
||||
}
|
||||
std::string spellid = stats.getSpells().getSelectedSpell();
|
||||
bool isMagicItem = false;
|
||||
bool canCast = mCastingManualSpell || MWBase::Environment::get().getWorld()->startSpellCast(mPtr);
|
||||
|
||||
if(!spellid.empty() && canCast)
|
||||
if (spellid.empty())
|
||||
{
|
||||
if (mPtr.getClass().hasInventoryStore(mPtr))
|
||||
{
|
||||
MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr);
|
||||
if (inv.getSelectedEnchantItem() != inv.end())
|
||||
{
|
||||
const MWWorld::Ptr& enchantItem = *inv.getSelectedEnchantItem();
|
||||
spellid = enchantItem.getClass().getEnchantment(enchantItem);
|
||||
isMagicItem = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const bool useCastingAnimations = Settings::Manager::getBool("use magic item animations", "Game");
|
||||
if (isMagicItem && !useCastingAnimations)
|
||||
{
|
||||
// Enchanted items by default do not use casting animations
|
||||
MWBase::Environment::get().getWorld()->castSpell(mPtr);
|
||||
resetIdle = false;
|
||||
}
|
||||
else if(!spellid.empty() && canCast)
|
||||
{
|
||||
/*
|
||||
Start of tes3mp addition
|
||||
|
@ -1599,18 +1616,26 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
|
|||
*/
|
||||
|
||||
MWMechanics::CastSpell cast(mPtr, nullptr, false, mCastingManualSpell);
|
||||
cast.playSpellCastingEffects(spellid);
|
||||
cast.playSpellCastingEffects(spellid, isMagicItem);
|
||||
|
||||
std::vector<ESM::ENAMstruct> effects;
|
||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
||||
const ESM::ENAMstruct &lastEffect = spell->mEffects.mList.back();
|
||||
const ESM::MagicEffect *effect;
|
||||
if (isMagicItem)
|
||||
{
|
||||
const ESM::Enchantment *enchantment = store.get<ESM::Enchantment>().find(spellid);
|
||||
effects = enchantment->mEffects.mList;
|
||||
}
|
||||
else
|
||||
{
|
||||
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
||||
effects = spell->mEffects.mList;
|
||||
}
|
||||
|
||||
effect = store.get<ESM::MagicEffect>().find(lastEffect.mEffectID); // use last effect of list for color of VFX_Hands
|
||||
const ESM::MagicEffect *effect = store.get<ESM::MagicEffect>().find(effects.back().mEffectID); // use last effect of list for color of VFX_Hands
|
||||
|
||||
const ESM::Static* castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_Hands");
|
||||
|
||||
for (size_t iter = 0; iter < spell->mEffects.mList.size(); ++iter) // play hands vfx for each effect
|
||||
for (size_t iter = 0; iter < effects.size(); ++iter) // play hands vfx for each effect
|
||||
{
|
||||
if (mAnimation->getNode("Bip01 L Hand"))
|
||||
mAnimation->addEffect("meshes\\" + castStatic->mModel, -1, false, "Bip01 L Hand", effect->mParticle);
|
||||
|
@ -1619,7 +1644,7 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
|
|||
mAnimation->addEffect("meshes\\" + castStatic->mModel, -1, false, "Bip01 R Hand", effect->mParticle);
|
||||
}
|
||||
|
||||
const ESM::ENAMstruct &firstEffect = spell->mEffects.mList.at(0); // first effect used for casting animation
|
||||
const ESM::ENAMstruct &firstEffect = effects.at(0); // first effect used for casting animation
|
||||
|
||||
std::string startKey;
|
||||
std::string stopKey;
|
||||
|
@ -1653,17 +1678,6 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
|
|||
{
|
||||
resetIdle = false;
|
||||
}
|
||||
|
||||
if (mPtr.getClass().hasInventoryStore(mPtr))
|
||||
{
|
||||
MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr);
|
||||
if (inv.getSelectedEnchantItem() != inv.end())
|
||||
{
|
||||
// Enchanted items cast immediately (no animation)
|
||||
MWBase::Environment::get().getWorld()->castSpell(mPtr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if(mWeaponType == WeapType_PickProbe)
|
||||
{
|
||||
|
@ -1756,7 +1770,7 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
|
|||
idle != CharState_IdleSneak && idle != CharState_IdleSwim &&
|
||||
mIdleState != CharState_IdleSneak && mIdleState != CharState_IdleSwim)
|
||||
{
|
||||
idle = CharState_None;
|
||||
mAnimation->disable(mCurrentIdle);
|
||||
}
|
||||
|
||||
animPlaying = mAnimation->getInfo(mCurrentWeapon, &complete);
|
||||
|
@ -2242,6 +2256,9 @@ void CharacterController::update(float duration, bool animationOnly)
|
|||
jumpstate = JumpState_Landing;
|
||||
vec.z() = 0.0f;
|
||||
|
||||
// We should reset idle animation during landing
|
||||
mAnimation->disable(mCurrentIdle);
|
||||
|
||||
float height = cls.getCreatureStats(mPtr).land(isPlayer);
|
||||
float healthLost = getFallDamage(mPtr, height);
|
||||
|
||||
|
@ -2474,6 +2491,20 @@ void CharacterController::update(float duration, bool animationOnly)
|
|||
else
|
||||
moved = osg::Vec3f(0.f, 0.f, 0.f);
|
||||
|
||||
float scale = mPtr.getCellRef().getScale();
|
||||
moved.x() *= scale;
|
||||
moved.y() *= scale;
|
||||
|
||||
static const bool normalizeSpeed = Settings::Manager::getBool("normalise race speed", "Game");
|
||||
if (mPtr.getClass().isNpc() && !normalizeSpeed)
|
||||
{
|
||||
const ESM::NPC* npc = mPtr.get<ESM::NPC>()->mBase;
|
||||
const ESM::Race* race = world->getStore().get<ESM::Race>().find(npc->mRace);
|
||||
float weight = npc->isMale() ? race->mData.mWeight.mMale : race->mData.mWeight.mFemale;
|
||||
moved.x() *= weight;
|
||||
moved.y() *= weight;
|
||||
}
|
||||
|
||||
// Ensure we're moving in generally the right direction...
|
||||
if(speed > 0.f)
|
||||
{
|
||||
|
|
|
@ -600,4 +600,11 @@ namespace MWMechanics
|
|||
|
||||
return (iFightDistanceBase - fFightDistanceMultiplier * d);
|
||||
}
|
||||
|
||||
bool isTargetMagicallyHidden(const MWWorld::Ptr& target)
|
||||
{
|
||||
const MagicEffects& magicEffects = target.getClass().getCreatureStats(target).getMagicEffects();
|
||||
return (magicEffects.get(ESM::MagicEffect::Invisibility).getMagnitude() > 0)
|
||||
|| (magicEffects.get(ESM::MagicEffect::Chameleon).getMagnitude() > 75);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@ void getHandToHandDamage (const MWWorld::Ptr& attacker, const MWWorld::Ptr& vict
|
|||
void applyFatigueLoss(const MWWorld::Ptr& attacker, const MWWorld::Ptr& weapon, float attackStrength);
|
||||
|
||||
float getFightDistanceBias(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2);
|
||||
|
||||
bool isTargetMagicallyHidden(const MWWorld::Ptr& target);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -57,6 +57,7 @@ namespace MWMechanics
|
|||
{
|
||||
// Contracted disease!
|
||||
actor.getClass().getCreatureStats(actor).getSpells().add(it->first);
|
||||
MWBase::Environment::get().getWorld()->applyLoopingParticles(actor);
|
||||
|
||||
std::string msg = "sMagicContractDisease";
|
||||
msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(msg)->mValue.getString();
|
||||
|
|
|
@ -1559,22 +1559,24 @@ namespace MWMechanics
|
|||
|
||||
bool MechanicsManager::actorAttacked(const MWWorld::Ptr &target, const MWWorld::Ptr &attacker)
|
||||
{
|
||||
if (target == getPlayer() || !attacker.getClass().isActor())
|
||||
const MWWorld::Ptr& player = getPlayer();
|
||||
if (target == player || !attacker.getClass().isActor())
|
||||
return false;
|
||||
|
||||
std::set<MWWorld::Ptr> followersAttacker;
|
||||
getActorsSidingWith(attacker, followersAttacker);
|
||||
|
||||
MWMechanics::CreatureStats& statsTarget = target.getClass().getCreatureStats(target);
|
||||
|
||||
if (followersAttacker.find(target) != followersAttacker.end())
|
||||
if (attacker == player)
|
||||
{
|
||||
statsTarget.friendlyHit();
|
||||
|
||||
if (statsTarget.getFriendlyHits() < 4)
|
||||
std::set<MWWorld::Ptr> followersAttacker;
|
||||
getActorsSidingWith(attacker, followersAttacker);
|
||||
if (followersAttacker.find(target) != followersAttacker.end())
|
||||
{
|
||||
MWBase::Environment::get().getDialogueManager()->say(target, "hit");
|
||||
return false;
|
||||
statsTarget.friendlyHit();
|
||||
|
||||
if (statsTarget.getFriendlyHits() < 4)
|
||||
{
|
||||
MWBase::Environment::get().getDialogueManager()->say(target, "hit");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1589,10 +1591,10 @@ namespace MWMechanics
|
|||
Make it possible to start combat with DedicatedPlayers and DedicatedActors by
|
||||
adding additional conditions for them
|
||||
*/
|
||||
if (!attacker.isEmpty() && (attacker.getClass().getCreatureStats(attacker).getAiSequence().isInCombat(target)
|
||||
|| attacker == getPlayer() || mwmp::PlayerList::isDedicatedPlayer(attacker)
|
||||
|| mwmp::Main::get().getCellController()->isDedicatedActor(attacker))
|
||||
&& !seq.isInCombat(attacker))
|
||||
if (!attacker.isEmpty()
|
||||
&& (attacker.getClass().getCreatureStats(attacker).getAiSequence().isInCombat(target) || attacker == player
|
||||
|| mwmp::PlayerList::isDedicatedPlayer(attacker) || mwmp::Main::get().getCellController()->isDedicatedActor(attacker))
|
||||
&& !seq.isInCombat(attacker))
|
||||
/*
|
||||
End of tes3mp change (major)
|
||||
*/
|
||||
|
@ -1605,7 +1607,7 @@ namespace MWMechanics
|
|||
// he will attack the player only if we will force him (e.g. via StartCombat console command)
|
||||
bool peaceful = false;
|
||||
std::string script = target.getClass().getScript(target);
|
||||
if (!script.empty() && target.getRefData().getLocals().hasVar(script, "onpchitme") && attacker == getPlayer())
|
||||
if (!script.empty() && target.getRefData().getLocals().hasVar(script, "onpchitme") && attacker == player)
|
||||
{
|
||||
int fight = std::max(0, target.getClass().getCreatureStats(target).getAiSetting(CreatureStats::AI_Fight).getModified());
|
||||
peaceful = (fight == 0);
|
||||
|
|
|
@ -327,8 +327,7 @@ namespace MWMechanics
|
|||
}
|
||||
catch (const DetourNavigator::NavigatorException& exception)
|
||||
{
|
||||
DetourNavigator::log("PathFinder::buildPathByNavigator navigator exception: ", exception.what());
|
||||
Log(Debug::Verbose) << "Build path by navigator exception: \"" << exception.what()
|
||||
Log(Debug::Debug) << "Build path by navigator exception: \"" << exception.what()
|
||||
<< "\" for \"" << actor.getClass().getName(actor) << "\" (" << actor.getBase()
|
||||
<< ") from " << startPoint << " to " << endPoint << " with flags ("
|
||||
<< DetourNavigator::WriteFlags {flags} << ")";
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <limits>
|
||||
#include <iomanip>
|
||||
|
||||
#include <components/misc/constants.hpp>
|
||||
#include <components/misc/rng.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
|
@ -551,8 +552,7 @@ namespace MWMechanics
|
|||
|
||||
if (magnitudeMult > 0 && !absorbed)
|
||||
{
|
||||
float random = Misc::Rng::rollClosedProbability();
|
||||
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
|
||||
float magnitude = effectIt->mMagnMin + Misc::Rng::rollDice(effectIt->mMagnMax - effectIt->mMagnMin + 1);
|
||||
magnitude *= magnitudeMult;
|
||||
|
||||
if (!target.getClass().isActor())
|
||||
|
@ -977,16 +977,15 @@ namespace MWMechanics
|
|||
if (mCaster == getPlayer())
|
||||
mCaster.getClass().skillUsageSucceeded (mCaster, ESM::Skill::Enchant, 1);
|
||||
}
|
||||
if (enchantment->mData.mType == ESM::Enchantment::CastOnce && !godmode)
|
||||
else if (enchantment->mData.mType == ESM::Enchantment::CastOnce)
|
||||
{
|
||||
item.getContainerStore()->remove(item, 1, mCaster);
|
||||
if (!godmode)
|
||||
item.getContainerStore()->remove(item, 1, mCaster);
|
||||
}
|
||||
else if (enchantment->mData.mType != ESM::Enchantment::WhenStrikes)
|
||||
else if (enchantment->mData.mType == ESM::Enchantment::WhenStrikes)
|
||||
{
|
||||
if (mCaster == getPlayer())
|
||||
{
|
||||
mCaster.getClass().skillUsageSucceeded (mCaster, ESM::Skill::Enchant, 3);
|
||||
}
|
||||
}
|
||||
|
||||
inflict(mCaster, mCaster, enchantment->mEffects, ESM::RT_Self);
|
||||
|
@ -1102,7 +1101,7 @@ namespace MWMechanics
|
|||
|
||||
// A non-actor doesn't play its spell cast effects from a character controller, so play them here
|
||||
if (!mCaster.getClass().isActor())
|
||||
playSpellCastingEffects(mId);
|
||||
playSpellCastingEffects(mId, false);
|
||||
|
||||
inflict(mCaster, mCaster, spell->mEffects, ESM::RT_Self);
|
||||
|
||||
|
@ -1177,15 +1176,27 @@ namespace MWMechanics
|
|||
return true;
|
||||
}
|
||||
|
||||
void CastSpell::playSpellCastingEffects(const std::string &spellid)
|
||||
void CastSpell::playSpellCastingEffects(const std::string &spellid, bool enchantment)
|
||||
{
|
||||
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
||||
if (enchantment)
|
||||
{
|
||||
const ESM::Enchantment *spell = store.get<ESM::Enchantment>().find(spellid);
|
||||
playSpellCastingEffects(spell->mEffects.mList);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
||||
playSpellCastingEffects(spell->mEffects.mList);
|
||||
}
|
||||
}
|
||||
|
||||
void CastSpell::playSpellCastingEffects(const std::vector<ESM::ENAMstruct>& effects)
|
||||
{
|
||||
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||
std::vector<std::string> addedEffects;
|
||||
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator iter = spell->mEffects.mList.begin();
|
||||
iter != spell->mEffects.mList.end(); ++iter)
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator iter = effects.begin(); iter != effects.end(); ++iter)
|
||||
{
|
||||
const ESM::MagicEffect *effect;
|
||||
effect = store.get<ESM::MagicEffect>().find(iter->mEffectID);
|
||||
|
@ -1205,41 +1216,18 @@ namespace MWMechanics
|
|||
|
||||
std::string texture = effect->mParticle;
|
||||
|
||||
float scale = 1.0f;
|
||||
osg::Vec3f pos (mCaster.getRefData().getPosition().asVec3());
|
||||
|
||||
if (animation && mCaster.getClass().isNpc())
|
||||
{
|
||||
// For NPC we should take race height as scaling factor
|
||||
const ESM::NPC *npc = mCaster.get<ESM::NPC>()->mBase;
|
||||
const MWWorld::ESMStore &esmStore =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
|
||||
const ESM::Race *race =
|
||||
esmStore.get<ESM::Race>().find(npc->mRace);
|
||||
|
||||
scale = npc->isMale() ? race->mData.mHeight.mMale : race->mData.mHeight.mFemale;
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::Vec3f halfExtents = MWBase::Environment::get().getWorld()->getHalfExtents(mCaster);
|
||||
|
||||
// TODO: take a size of particle or NPC with height and weight = 1.0 as scale = 1.0
|
||||
float scaleX = halfExtents.x() * 2 / 60.f;
|
||||
float scaleY = halfExtents.y() * 2 / 60.f;
|
||||
float scaleZ = halfExtents.z() * 2 / 120.f;
|
||||
|
||||
scale = std::max({ scaleX, scaleY, scaleZ });
|
||||
}
|
||||
|
||||
// If the caster has no animation, add the effect directly to the effectManager
|
||||
if (animation)
|
||||
{
|
||||
animation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex, false, "", texture, scale);
|
||||
animation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex, false, "", texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We should set scale for effect manager manually
|
||||
// If the caster has no animation, add the effect directly to the effectManager
|
||||
// We should scale it manually
|
||||
osg::Vec3f bounds (MWBase::Environment::get().getWorld()->getHalfExtents(mCaster) * 2.f / Constants::UnitsPerFoot);
|
||||
float scale = std::max({ bounds.x()/3.f, bounds.y()/3.f, bounds.z()/6.f });
|
||||
float meshScale = !mCaster.getClass().isActor() ? mCaster.getCellRef().getScale() : 1.0f;
|
||||
MWBase::Environment::get().getWorld()->spawnEffect("meshes\\" + castStatic->mModel, effect->mParticle, pos, scale * meshScale);
|
||||
}
|
||||
|
|
|
@ -83,6 +83,9 @@ namespace MWMechanics
|
|||
private:
|
||||
MWWorld::Ptr mCaster; // May be empty
|
||||
MWWorld::Ptr mTarget; // May be empty
|
||||
|
||||
void playSpellCastingEffects(const std::vector<ESM::ENAMstruct>& effects);
|
||||
|
||||
public:
|
||||
bool mStack;
|
||||
std::string mId; // ID of spell, potion, item etc
|
||||
|
@ -109,7 +112,7 @@ namespace MWMechanics
|
|||
/// @note Auto detects if spell, ingredient or potion
|
||||
bool cast (const std::string& id);
|
||||
|
||||
void playSpellCastingEffects(const std::string &spellid);
|
||||
void playSpellCastingEffects(const std::string &spellid, bool enchantment);
|
||||
|
||||
bool spellIncreasesSkill();
|
||||
|
||||
|
|
|
@ -94,7 +94,10 @@ namespace MWMechanics
|
|||
for (unsigned int i=0; i<spell->mEffects.mList.size();++i)
|
||||
{
|
||||
if (spell->mEffects.mList[i].mMagnMin != spell->mEffects.mList[i].mMagnMax)
|
||||
random[i] = Misc::Rng::rollClosedProbability();
|
||||
{
|
||||
int delta = spell->mEffects.mList[i].mMagnMax - spell->mEffects.mList[i].mMagnMin;
|
||||
random[i] = Misc::Rng::rollDice(delta + 1) / static_cast<float>(delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -698,7 +698,7 @@ namespace MWPhysics
|
|||
{
|
||||
// First of all, try to hit where you aim to
|
||||
int hitmask = CollisionType_World | CollisionType_Door | CollisionType_HeightMap | CollisionType_Actor;
|
||||
RayResult result = castRay(origin, origin + (orient * osg::Vec3f(0.0f, queryDistance, 0.0f)), actor, targets, CollisionType_Actor, hitmask);
|
||||
RayResult result = castRay(origin, origin + (orient * osg::Vec3f(0.0f, queryDistance, 0.0f)), actor, targets, hitmask, CollisionType_Actor);
|
||||
|
||||
if (result.mHit)
|
||||
{
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
#include <components/sceneutil/lightutil.hpp>
|
||||
#include <components/sceneutil/visitor.hpp>
|
||||
|
||||
#include <components/fallback/fallback.hpp>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
@ -428,19 +426,10 @@ void ActorAnimation::addHiddenItemLight(const MWWorld::ConstPtr& item, const ESM
|
|||
if (mItemLights.find(item) != mItemLights.end())
|
||||
return;
|
||||
|
||||
const Fallback::Map* fallback = MWBase::Environment::get().getWorld()->getFallback();
|
||||
static bool outQuadInLin = fallback->getFallbackBool("LightAttenuation_OutQuadInLin");
|
||||
static bool useQuadratic = fallback->getFallbackBool("LightAttenuation_UseQuadratic");
|
||||
static float quadraticValue = fallback->getFallbackFloat("LightAttenuation_QuadraticValue");
|
||||
static float quadraticRadiusMult = fallback->getFallbackFloat("LightAttenuation_QuadraticRadiusMult");
|
||||
static bool useLinear = fallback->getFallbackBool("LightAttenuation_UseLinear");
|
||||
static float linearRadiusMult = fallback->getFallbackFloat("LightAttenuation_LinearRadiusMult");
|
||||
static float linearValue = fallback->getFallbackFloat("LightAttenuation_LinearValue");
|
||||
bool exterior = mPtr.isInCell() && mPtr.getCell()->getCell()->isExterior();
|
||||
|
||||
osg::Vec4f ambient(1,1,1,1);
|
||||
osg::ref_ptr<SceneUtil::LightSource> lightSource = SceneUtil::createLightSource(esmLight, Mask_Lighting, exterior, outQuadInLin,
|
||||
useQuadratic, quadraticValue, quadraticRadiusMult, useLinear, linearRadiusMult, linearValue, ambient);
|
||||
osg::ref_ptr<SceneUtil::LightSource> lightSource = SceneUtil::createLightSource(esmLight, Mask_Lighting, exterior, ambient);
|
||||
|
||||
mInsert->addChild(lightSource);
|
||||
|
||||
|
|
|
@ -38,8 +38,6 @@
|
|||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include <components/fallback/fallback.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
@ -1628,21 +1626,12 @@ namespace MWRender
|
|||
|
||||
void Animation::addExtraLight(osg::ref_ptr<osg::Group> parent, const ESM::Light *esmLight)
|
||||
{
|
||||
const Fallback::Map* fallback = MWBase::Environment::get().getWorld()->getFallback();
|
||||
static bool outQuadInLin = fallback->getFallbackBool("LightAttenuation_OutQuadInLin");
|
||||
static bool useQuadratic = fallback->getFallbackBool("LightAttenuation_UseQuadratic");
|
||||
static float quadraticValue = fallback->getFallbackFloat("LightAttenuation_QuadraticValue");
|
||||
static float quadraticRadiusMult = fallback->getFallbackFloat("LightAttenuation_QuadraticRadiusMult");
|
||||
static bool useLinear = fallback->getFallbackBool("LightAttenuation_UseLinear");
|
||||
static float linearRadiusMult = fallback->getFallbackFloat("LightAttenuation_LinearRadiusMult");
|
||||
static float linearValue = fallback->getFallbackFloat("LightAttenuation_LinearValue");
|
||||
bool exterior = mPtr.isInCell() && mPtr.getCell()->getCell()->isExterior();
|
||||
|
||||
SceneUtil::addLight(parent, esmLight, Mask_ParticleSystem, Mask_Lighting, exterior, outQuadInLin,
|
||||
useQuadratic, quadraticValue, quadraticRadiusMult, useLinear, linearRadiusMult, linearValue);
|
||||
SceneUtil::addLight(parent, esmLight, Mask_ParticleSystem, Mask_Lighting, exterior);
|
||||
}
|
||||
|
||||
void Animation::addEffect (const std::string& model, int effectId, bool loop, const std::string& bonename, const std::string& texture, float scale)
|
||||
void Animation::addEffect (const std::string& model, int effectId, bool loop, const std::string& bonename, const std::string& texture)
|
||||
{
|
||||
if (!mObjectRoot.get())
|
||||
return;
|
||||
|
@ -1674,7 +1663,12 @@ namespace MWRender
|
|||
}
|
||||
|
||||
osg::ref_ptr<osg::PositionAttitudeTransform> trans = new osg::PositionAttitudeTransform;
|
||||
trans->setScale(osg::Vec3f(scale, scale, scale));
|
||||
if (!mPtr.getClass().isNpc())
|
||||
{
|
||||
osg::Vec3f bounds (MWBase::Environment::get().getWorld()->getHalfExtents(mPtr) * 2.f / Constants::UnitsPerFoot);
|
||||
float scale = std::max({ bounds.x()/3.f, bounds.y()/3.f, bounds.z()/6.f });
|
||||
trans->setScale(osg::Vec3f(scale, scale, scale));
|
||||
}
|
||||
parentNode->addChild(trans);
|
||||
|
||||
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->getInstance(model, trans);
|
||||
|
@ -1834,14 +1828,12 @@ namespace MWRender
|
|||
}
|
||||
else
|
||||
{
|
||||
// TODO: use global attenuation settings
|
||||
|
||||
// 1 pt of Light magnitude corresponds to 1 foot of radius
|
||||
float radius = effect * std::ceil(Constants::UnitsPerFoot);
|
||||
const float linearValue = 3.f; // Currently hardcoded: unmodified Morrowind attenuation settings
|
||||
float linearAttenuation = linearValue / radius;
|
||||
// Arbitrary multiplier used to make the obvious cut-off less obvious
|
||||
float cutoffMult = 3;
|
||||
|
||||
if (!mGlowLight || linearAttenuation != mGlowLight->getLight(0)->getLinearAttenuation())
|
||||
if (!mGlowLight || (radius * cutoffMult) != mGlowLight->getRadius())
|
||||
{
|
||||
if (mGlowLight)
|
||||
{
|
||||
|
@ -1853,7 +1845,9 @@ namespace MWRender
|
|||
light->setDiffuse(osg::Vec4f(0,0,0,0));
|
||||
light->setSpecular(osg::Vec4f(0,0,0,0));
|
||||
light->setAmbient(osg::Vec4f(1.5f,1.5f,1.5f,1.f));
|
||||
light->setLinearAttenuation(linearAttenuation);
|
||||
|
||||
bool isExterior = mPtr.isInCell() && mPtr.getCell()->getCell()->isExterior();
|
||||
SceneUtil::configureLight(light, radius, isExterior);
|
||||
|
||||
mGlowLight = new SceneUtil::LightSource;
|
||||
mGlowLight->setNodeMask(Mask_Lighting);
|
||||
|
@ -1861,8 +1855,7 @@ namespace MWRender
|
|||
mGlowLight->setLight(light);
|
||||
}
|
||||
|
||||
// Make the obvious cut-off a bit less obvious
|
||||
mGlowLight->setRadius(radius * 3);
|
||||
mGlowLight->setRadius(radius * cutoffMult);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -365,7 +365,7 @@ public:
|
|||
* @param texture override the texture specified in the model's materials - if empty, do not override
|
||||
* @note Will not add an effect twice.
|
||||
*/
|
||||
void addEffect (const std::string& model, int effectId, bool loop = false, const std::string& bonename = "", const std::string& texture = "", float scale = 1.0f);
|
||||
void addEffect (const std::string& model, int effectId, bool loop = false, const std::string& bonename = "", const std::string& texture = "");
|
||||
void removeEffect (int effectId);
|
||||
void removeEffects ();
|
||||
void getLoopingEffects (std::vector<int>& out) const;
|
||||
|
|
|
@ -168,16 +168,15 @@ namespace MWRender
|
|||
stateset->setAttributeAndModes(lightmodel, osg::StateAttribute::ON);
|
||||
|
||||
osg::ref_ptr<osg::Light> light = new osg::Light;
|
||||
const Fallback::Map* fallback = MWBase::Environment::get().getWorld()->getFallback();
|
||||
float diffuseR = fallback->getFallbackFloat("Inventory_DirectionalDiffuseR");
|
||||
float diffuseG = fallback->getFallbackFloat("Inventory_DirectionalDiffuseG");
|
||||
float diffuseB = fallback->getFallbackFloat("Inventory_DirectionalDiffuseB");
|
||||
float ambientR = fallback->getFallbackFloat("Inventory_DirectionalAmbientR");
|
||||
float ambientG = fallback->getFallbackFloat("Inventory_DirectionalAmbientG");
|
||||
float ambientB = fallback->getFallbackFloat("Inventory_DirectionalAmbientB");
|
||||
float azimuth = osg::DegreesToRadians(180.f - fallback->getFallbackFloat("Inventory_DirectionalRotationX"));
|
||||
float altitude = osg::DegreesToRadians(fallback->getFallbackFloat("Inventory_DirectionalRotationY"));
|
||||
float positionX = std::cos(azimuth) * std::sin(altitude);
|
||||
float diffuseR = Fallback::Map::getFloat("Inventory_DirectionalDiffuseR");
|
||||
float diffuseG = Fallback::Map::getFloat("Inventory_DirectionalDiffuseG");
|
||||
float diffuseB = Fallback::Map::getFloat("Inventory_DirectionalDiffuseB");
|
||||
float ambientR = Fallback::Map::getFloat("Inventory_DirectionalAmbientR");
|
||||
float ambientG = Fallback::Map::getFloat("Inventory_DirectionalAmbientG");
|
||||
float ambientB = Fallback::Map::getFloat("Inventory_DirectionalAmbientB");
|
||||
float azimuth = osg::DegreesToRadians(Fallback::Map::getFloat("Inventory_DirectionalRotationX"));
|
||||
float altitude = osg::DegreesToRadians(Fallback::Map::getFloat("Inventory_DirectionalRotationY"));
|
||||
float positionX = -std::cos(azimuth) * std::sin(altitude);
|
||||
float positionY = std::sin(azimuth) * std::sin(altitude);
|
||||
float positionZ = std::cos(altitude);
|
||||
light->setPosition(osg::Vec4(positionX,positionY,positionZ, 0.0));
|
||||
|
|
|
@ -493,7 +493,7 @@ void NpcAnimation::updateNpcBase()
|
|||
if(!is1stPerson)
|
||||
{
|
||||
const std::string base = "meshes\\xbase_anim.nif";
|
||||
if (smodel != base)
|
||||
if (smodel != base && !isWerewolf)
|
||||
addAnimSource(base, smodel);
|
||||
|
||||
if (smodel != defaultSkeleton && base != defaultSkeleton)
|
||||
|
@ -507,7 +507,7 @@ void NpcAnimation::updateNpcBase()
|
|||
else
|
||||
{
|
||||
const std::string base = "meshes\\xbase_anim.1st.nif";
|
||||
if (smodel != base)
|
||||
if (smodel != base && !isWerewolf)
|
||||
addAnimSource(base, smodel);
|
||||
|
||||
addAnimSource(smodel, smodel);
|
||||
|
|
|
@ -195,8 +195,7 @@ namespace MWRender
|
|||
|
||||
RenderingManager::RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode,
|
||||
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
||||
const Fallback::Map* fallback, const std::string& resourcePath,
|
||||
DetourNavigator::Navigator& navigator)
|
||||
const std::string& resourcePath, DetourNavigator::Navigator& navigator)
|
||||
: mViewer(viewer)
|
||||
, mRootNode(rootNode)
|
||||
, mResourceSystem(resourceSystem)
|
||||
|
@ -207,9 +206,9 @@ namespace MWRender
|
|||
, mLandFogEnd(std::numeric_limits<float>::max())
|
||||
, mUnderwaterFogStart(0.f)
|
||||
, mUnderwaterFogEnd(std::numeric_limits<float>::max())
|
||||
, mUnderwaterColor(fallback->getFallbackColour("Water_UnderwaterColor"))
|
||||
, mUnderwaterWeight(fallback->getFallbackFloat("Water_UnderwaterColorWeight"))
|
||||
, mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog"))
|
||||
, mUnderwaterColor(Fallback::Map::getColour("Water_UnderwaterColor"))
|
||||
, mUnderwaterWeight(Fallback::Map::getFloat("Water_UnderwaterColorWeight"))
|
||||
, mUnderwaterIndoorFog(Fallback::Map::getFloat("Water_UnderwaterIndoorFog"))
|
||||
, mNightEyeFactor(0.f)
|
||||
, mDistantFog(false)
|
||||
, mDistantTerrain(false)
|
||||
|
@ -275,7 +274,7 @@ namespace MWRender
|
|||
|
||||
mEffectManager.reset(new EffectManager(sceneRoot, mResourceSystem));
|
||||
|
||||
mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback, resourcePath));
|
||||
mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), resourcePath));
|
||||
|
||||
DLLandFogStart = Settings::Manager::getFloat("distant land fog start", "Fog");
|
||||
DLLandFogEnd = Settings::Manager::getFloat("distant land fog end", "Fog");
|
||||
|
@ -312,7 +311,6 @@ namespace MWRender
|
|||
else
|
||||
mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile, Mask_Debug));
|
||||
|
||||
mTerrain->setDefaultViewer(mViewer->getCamera());
|
||||
mTerrain->setTargetFrameRate(Settings::Manager::getFloat("target framerate", "Cells"));
|
||||
mTerrain->setWorkQueue(mWorkQueue.get());
|
||||
|
||||
|
|
|
@ -86,8 +86,7 @@ namespace MWRender
|
|||
public:
|
||||
RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode,
|
||||
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
||||
const Fallback::Map* fallback, const std::string& resourcePath,
|
||||
DetourNavigator::Navigator& navigator);
|
||||
const std::string& resourcePath, DetourNavigator::Navigator& navigator);
|
||||
~RenderingManager();
|
||||
|
||||
MWRender::Objects& getObjects();
|
||||
|
|
|
@ -26,13 +26,13 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
void createWaterRippleStateSet(Resource::ResourceSystem* resourceSystem, const Fallback::Map* fallback, osg::Node* node)
|
||||
void createWaterRippleStateSet(Resource::ResourceSystem* resourceSystem,osg::Node* node)
|
||||
{
|
||||
int rippleFrameCount = fallback->getFallbackInt("Water_RippleFrameCount");
|
||||
int rippleFrameCount = Fallback::Map::getInt("Water_RippleFrameCount");
|
||||
if (rippleFrameCount <= 0)
|
||||
return;
|
||||
|
||||
std::string tex = fallback->getFallbackString("Water_RippleTexture");
|
||||
const std::string& tex = Fallback::Map::getString("Water_RippleTexture");
|
||||
|
||||
std::vector<osg::ref_ptr<osg::Texture2D> > textures;
|
||||
for (int i=0; i<rippleFrameCount; ++i)
|
||||
|
@ -81,7 +81,7 @@ namespace
|
|||
namespace MWRender
|
||||
{
|
||||
|
||||
RippleSimulation::RippleSimulation(osg::Group *parent, Resource::ResourceSystem* resourceSystem, const Fallback::Map* fallback)
|
||||
RippleSimulation::RippleSimulation(osg::Group *parent, Resource::ResourceSystem* resourceSystem)
|
||||
: mParent(parent)
|
||||
{
|
||||
mParticleSystem = new osgParticle::ParticleSystem;
|
||||
|
@ -94,8 +94,8 @@ RippleSimulation::RippleSimulation(osg::Group *parent, Resource::ResourceSystem*
|
|||
particleTemplate.setSizeRange(osgParticle::rangef(15, 180));
|
||||
particleTemplate.setColorRange(osgParticle::rangev4(osg::Vec4f(1,1,1,0.7), osg::Vec4f(1,1,1,0.7)));
|
||||
particleTemplate.setAlphaRange(osgParticle::rangef(1.f, 0.f));
|
||||
particleTemplate.setAngularVelocity(osg::Vec3f(0,0,fallback->getFallbackFloat("Water_RippleRotSpeed")));
|
||||
particleTemplate.setLifeTime(fallback->getFallbackFloat("Water_RippleLifetime"));
|
||||
particleTemplate.setAngularVelocity(osg::Vec3f(0,0,Fallback::Map::getFloat("Water_RippleRotSpeed")));
|
||||
particleTemplate.setLifeTime(Fallback::Map::getFloat("Water_RippleLifetime"));
|
||||
|
||||
osg::ref_ptr<osgParticle::ParticleSystemUpdater> updater (new osgParticle::ParticleSystemUpdater);
|
||||
updater->addParticleSystem(mParticleSystem);
|
||||
|
@ -105,7 +105,7 @@ RippleSimulation::RippleSimulation(osg::Group *parent, Resource::ResourceSystem*
|
|||
mParticleNode->addChild(mParticleSystem);
|
||||
mParticleNode->setNodeMask(Mask_Effect);
|
||||
|
||||
createWaterRippleStateSet(resourceSystem, fallback, mParticleNode);
|
||||
createWaterRippleStateSet(resourceSystem, mParticleNode);
|
||||
|
||||
mParent->addChild(mParticleNode);
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace MWRender
|
|||
class RippleSimulation
|
||||
{
|
||||
public:
|
||||
RippleSimulation(osg::Group* parent, Resource::ResourceSystem* resourceSystem, const Fallback::Map* fallback);
|
||||
RippleSimulation(osg::Group* parent, Resource::ResourceSystem* resourceSystem);
|
||||
~RippleSimulation();
|
||||
|
||||
/// @param dt Time since the last frame
|
||||
|
|
|
@ -266,16 +266,16 @@ public:
|
|||
|
||||
META_Node(MWRender, CameraRelativeTransform)
|
||||
|
||||
const osg::Vec3f& getLastEyePoint() const
|
||||
const osg::Vec3f& getLastViewPoint() const
|
||||
{
|
||||
return mEyePoint;
|
||||
return mViewPoint;
|
||||
}
|
||||
|
||||
virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const
|
||||
{
|
||||
if (nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
|
||||
{
|
||||
mEyePoint = static_cast<osgUtil::CullVisitor*>(nv)->getEyePoint();
|
||||
mViewPoint = static_cast<osgUtil::CullVisitor*>(nv)->getViewPoint();
|
||||
}
|
||||
|
||||
if (_referenceFrame==RELATIVE_RF)
|
||||
|
@ -337,8 +337,8 @@ public:
|
|||
}
|
||||
};
|
||||
private:
|
||||
// eyePoint for the current frame
|
||||
mutable osg::Vec3f mEyePoint;
|
||||
// viewPoint for the current frame
|
||||
mutable osg::Vec3f mViewPoint;
|
||||
};
|
||||
|
||||
class ModVertexAlphaVisitor : public osg::NodeVisitor
|
||||
|
@ -391,7 +391,7 @@ private:
|
|||
/// @brief Hides the node subgraph if the eye point is below water.
|
||||
/// @note Must be added as cull callback.
|
||||
/// @note Meant to be used on a node that is child of a CameraRelativeTransform.
|
||||
/// The current eye point must be retrieved by the CameraRelativeTransform since we can't get it anymore once we are in camera-relative space.
|
||||
/// The current view point must be retrieved by the CameraRelativeTransform since we can't get it anymore once we are in camera-relative space.
|
||||
class UnderwaterSwitchCallback : public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
|
@ -404,8 +404,8 @@ public:
|
|||
|
||||
bool isUnderwater()
|
||||
{
|
||||
osg::Vec3f eyePoint = mCameraRelativeTransform->getLastEyePoint();
|
||||
return mEnabled && eyePoint.z() < mWaterLevel;
|
||||
osg::Vec3f viewPoint = mCameraRelativeTransform->getLastViewPoint();
|
||||
return mEnabled && viewPoint.z() < mWaterLevel;
|
||||
}
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
|
@ -828,10 +828,9 @@ private:
|
|||
, mTimeOfDayFade(1.f)
|
||||
, mGlareView(1.f)
|
||||
{
|
||||
const Fallback::Map* fallback = MWBase::Environment::get().getWorld()->getFallback();
|
||||
mColor = fallback->getFallbackColour("Weather_Sun_Glare_Fader_Color");
|
||||
mSunGlareFaderMax = fallback->getFallbackFloat("Weather_Sun_Glare_Fader_Max");
|
||||
mSunGlareFaderAngleMax = fallback->getFallbackFloat("Weather_Sun_Glare_Fader_Angle_Max");
|
||||
mColor = Fallback::Map::getColour("Weather_Sun_Glare_Fader_Color");
|
||||
mSunGlareFaderMax = Fallback::Map::getFloat("Weather_Sun_Glare_Fader_Max");
|
||||
mSunGlareFaderAngleMax = Fallback::Map::getFloat("Weather_Sun_Glare_Fader_Angle_Max");
|
||||
|
||||
// Replicating a design flaw in MW. The color was being set on both ambient and emissive properties, which multiplies the result by two,
|
||||
// then finally gets clamped by the fixed function pipeline. With the default INI settings, only the red component gets clamped,
|
||||
|
@ -1179,9 +1178,8 @@ void SkyManager::create()
|
|||
|
||||
mSun.reset(new Sun(mEarlyRenderBinRoot, *mSceneManager->getImageManager()));
|
||||
|
||||
const Fallback::Map* fallback=MWBase::Environment::get().getWorld()->getFallback();
|
||||
mMasser.reset(new Moon(mEarlyRenderBinRoot, *mSceneManager->getImageManager(), fallback->getFallbackFloat("Moons_Masser_Size")/125, Moon::Type_Masser));
|
||||
mSecunda.reset(new Moon(mEarlyRenderBinRoot, *mSceneManager->getImageManager(), fallback->getFallbackFloat("Moons_Secunda_Size")/125, Moon::Type_Secunda));
|
||||
mMasser.reset(new Moon(mEarlyRenderBinRoot, *mSceneManager->getImageManager(), Fallback::Map::getFloat("Moons_Masser_Size")/125, Moon::Type_Masser));
|
||||
mSecunda.reset(new Moon(mEarlyRenderBinRoot, *mSceneManager->getImageManager(), Fallback::Map::getFloat("Moons_Secunda_Size")/125, Moon::Type_Secunda));
|
||||
|
||||
mCloudNode = new osg::PositionAttitudeTransform;
|
||||
mEarlyRenderBinRoot->addChild(mCloudNode);
|
||||
|
@ -1205,7 +1203,7 @@ void SkyManager::create()
|
|||
mEarlyRenderBinRoot->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||
mEarlyRenderBinRoot->getOrCreateStateSet()->setMode(GL_FOG, osg::StateAttribute::OFF);
|
||||
|
||||
mMoonScriptColor = fallback->getFallbackColour("Moons_Script_Color");
|
||||
mMoonScriptColor = Fallback::Map::getColour("Moons_Script_Color");
|
||||
|
||||
mCreated = true;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue