diff --git a/AUTHORS.md b/AUTHORS.md index 839a04e42..c4190343d 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -129,6 +129,7 @@ Programmers Radu-Marius Popovici (rpopovici) Rafael Moura (dhustkoder) rdimesio + rexelion riothamus Rob Cutmore (rcutmore) Robert MacGregor (Ragora) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3aac6e584..a7c3b1391 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,16 +27,8 @@ if (USE_QT) set_property(CACHE DESIRED_QT_VERSION PROPERTY STRINGS 4 5) endif() -if (APPLE) - # OS X build process relies on this fix: https://github.com/Kitware/CMake/commit/3df5147043d83aa09acd5c9ce31d5c602efb99db - cmake_minimum_required(VERSION 3.1.0) -elseif (USE_QT AND DESIRED_QT_VERSION MATCHES 5) - # 2.8.11+ is required to make Qt5 happy and allow linking QtMain on Windows. - cmake_minimum_required(VERSION 2.8.11) -else() - # We probably support older versions than this. - cmake_minimum_required(VERSION 2.6) -endif() +# set the minimum required version across the board +cmake_minimum_required(VERSION 3.1.0) project(OpenMW) @@ -440,7 +432,7 @@ IF(NOT WIN32 AND NOT APPLE) #ENDIF(BUILD_MYGUI_PLUGIN) # Install licenses - INSTALL(FILES "docs/license/DejaVu Font License.txt" DESTINATION "${LICDIR}" ) + INSTALL(FILES "files/mygui/DejaVu Font License.txt" DESTINATION "${LICDIR}" ) # Install icon and desktop file INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw") @@ -483,9 +475,9 @@ if(WIN32) INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg") INSTALL(FILES "${OpenMW_SOURCE_DIR}/CHANGELOG.md" DESTINATION "." RENAME "CHANGELOG.txt") INSTALL(FILES "${OpenMW_SOURCE_DIR}/README.md" DESTINATION "." RENAME "README.txt") + INSTALL(FILES "${OpenMW_SOURCE_DIR}/LICENSE" DESTINATION "." RENAME "LICENSE.txt") INSTALL(FILES - "${OpenMW_SOURCE_DIR}/Docs/license/GPL3.txt" - "${OpenMW_SOURCE_DIR}/Docs/license/DejaVu Font License.txt" + "${OpenMW_SOURCE_DIR}/files/mygui/DejaVu Font License.txt" "${OpenMW_BINARY_DIR}/settings-default.cfg" "${OpenMW_BINARY_DIR}/tes3mp-client-default.cfg" "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" diff --git a/docs/license/GPL3.txt b/LICENSE similarity index 99% rename from docs/license/GPL3.txt rename to LICENSE index 94a9ed024..9cecc1d46 100644 --- a/docs/license/GPL3.txt +++ b/LICENSE @@ -631,8 +631,8 @@ to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - - Copyright (C) + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: - Copyright (C) + {project} Copyright (C) {year} {fullname} This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. diff --git a/README.md b/README.md index d26b97a3b..fd1469e41 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,10 @@ TES3MP TES3MP is a project aiming to add multiplayer functionality to [OpenMW](https://github.com/OpenMW/openmw), a free and open source engine recreation of the popular Bethesda Softworks game "The Elder Scrolls III: Morrowind". * Version: 0.7-alpha -* License: GPLv3 (see docs/license/GPL3.txt for more information) +* License: GPLv3 (see [LICENSE](https://github.com/TES3MP/openmw-tes3mp/blob/master/LICENSE) for more information) Font Licenses: -* DejaVuLGCSansMono.ttf: custom (see docs/license/DejaVu Font License.txt for more information) +* DejaVuLGCSansMono.ttf: custom (see [files/mygui/DejaVu Font License.txt](https://github.com/TES3MP/openmw-tes3mp/blob/master/files/mygui/DejaVu%20Font%20License.txt) for more information) Project Status -------------- diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index a90c871bd..ce8a569f9 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -671,6 +671,9 @@ namespace MWGui MWWorld::Ptr player = MWMechanics::getPlayer(); MWBase::Environment::get().getWorld()->breakInvisibility(player); + + if (!object.getRefData().activate()) + return; MWBase::Environment::get().getMechanicsManager()->itemTaken(player, object, MWWorld::Ptr(), count); diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index a7ad687cb..61febf315 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -96,6 +96,12 @@ namespace MWGui return (!mTimeAdvancer.isRunning()); //Only exit if not currently waiting } + void WaitDialog::clear() + { + mSleeping = false; + mTimeAdvancer.stop(); + } + void WaitDialog::onOpen() { if (mTimeAdvancer.isRunning()) diff --git a/apps/openmw/mwgui/waitdialog.hpp b/apps/openmw/mwgui/waitdialog.hpp index eb6a55640..2aecb002f 100644 --- a/apps/openmw/mwgui/waitdialog.hpp +++ b/apps/openmw/mwgui/waitdialog.hpp @@ -33,6 +33,8 @@ namespace MWGui virtual bool exit(); + virtual void clear(); + void onFrame(float dt); bool getSleeping() { return mTimeAdvancer.isRunning() && mSleeping; } diff --git a/apps/openmw/mwmechanics/aipursue.cpp b/apps/openmw/mwmechanics/aipursue.cpp index 50a68c8e6..218bca20e 100644 --- a/apps/openmw/mwmechanics/aipursue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -80,9 +80,13 @@ bool AiPursue::execute (const MWWorld::Ptr& actor, CharacterController& characte //Set the target desition from the actor ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; + ESM::Position aPos = actor.getRefData().getPosition(); + float pathTolerance = 100.0; - if (pathTo(actor, dest, duration, 100)) { + if (pathTo(actor, dest, duration, pathTolerance) && + abs(dest.mZ - aPos.pos[2]) < pathTolerance) // check the true distance in case the target is far away in Z-direction + { target.getClass().activate(target,actor).get()->execute(actor); //Arrest player when reached /* diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index c6f33dedf..7ccac6ec1 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -270,6 +270,7 @@ void CharacterController::refreshHitRecoilAnims() || mPtr.getClass().getCreatureStats(mPtr).getFatigue().getBase() == 0) && mAnimation->hasAnimation("knockout")) { + mTimeUntilWake = Misc::Rng::rollClosedProbability() * 2 + 1; // Wake up after 1 to 3 seconds if (isSwimming && mAnimation->hasAnimation("swimknockout")) { mHitState = CharState_SwimKnockOut; @@ -354,7 +355,8 @@ void CharacterController::refreshHitRecoilAnims() mPtr.getClass().getCreatureStats(mPtr).setBlock(false); mHitState = CharState_None; } - else if (isKnockedOut() && mPtr.getClass().getCreatureStats(mPtr).getFatigue().getCurrent() > 0) + else if (isKnockedOut() && mPtr.getClass().getCreatureStats(mPtr).getFatigue().getCurrent() > 0 + && mTimeUntilWake <= 0) { mHitState = isSwimming ? CharState_SwimKnockDown : CharState_KnockDown; mAnimation->disable(mCurrentHit); @@ -388,21 +390,29 @@ void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState } } - if(mJumpState == JumpState_InAir) + if (!mCurrentJump.empty()) { mAnimation->disable(mCurrentJump); - mCurrentJump = jumpAnimName; - if (mAnimation->hasAnimation("jump")) - mAnimation->play(mCurrentJump, Priority_Jump, jumpmask, false, + mCurrentJump.clear(); + } + + if(mJumpState == JumpState_InAir) + { + if (mAnimation->hasAnimation(jumpAnimName)) + { + mAnimation->play(jumpAnimName, Priority_Jump, jumpmask, false, 1.0f, (startAtLoop?"loop start":"start"), "stop", 0.0f, ~0ul); + mCurrentJump = jumpAnimName; + } } - else + else if (mJumpState == JumpState_Landing) { - mAnimation->disable(mCurrentJump); - mCurrentJump.clear(); - if (mAnimation->hasAnimation("jump")) + if (mAnimation->hasAnimation(jumpAnimName)) + { mAnimation->play(jumpAnimName, Priority_Jump, jumpmask, true, 1.0f, "loop stop", "stop", 0.0f, 0); + mCurrentJump = jumpAnimName; + } } } } @@ -789,6 +799,7 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim , mSecondsOfRunning(0) , mTurnAnimationThreshold(0) , mAttackingOrSpell(false) + , mTimeUntilWake(0.f) { if(!mAnimation) return; @@ -1717,6 +1728,9 @@ void CharacterController::update(float duration) float speed = 0.f; updateMagicEffects(); + + if (isKnockedOut()) + mTimeUntilWake -= duration; bool godmode = mPtr == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState(); @@ -1810,7 +1824,6 @@ void CharacterController::update(float duration) mHasMovedInXY = std::abs(vec.x())+std::abs(vec.y()) > 0.0f; isrunning = isrunning && mHasMovedInXY; - // advance athletics if(mHasMovedInXY && mPtr == getPlayer()) { @@ -1965,7 +1978,8 @@ void CharacterController::update(float duration) } else { - jumpstate = JumpState_None; + jumpstate = mAnimation->isPlaying(mCurrentJump) ? JumpState_Landing : JumpState_None; + vec.z() = 0.0f; inJump = false; @@ -1995,9 +2009,15 @@ void CharacterController::update(float duration) else if(rot.z() != 0.0f && !sneak && !(mPtr == getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson())) { if(rot.z() > 0.0f) + { movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight; + mAnimation->disable(mCurrentJump); + } else if(rot.z() < 0.0f) + { movestate = inwater ? CharState_SwimTurnLeft : CharState_TurnLeft; + mAnimation->disable(mCurrentJump); + } } } diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index af90c18b8..6de18fe62 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -196,6 +196,8 @@ class CharacterController : public MWRender::Animation::TextKeyListener float mSecondsOfSwimming; float mSecondsOfRunning; + float mTimeUntilWake; + MWWorld::ConstPtr mHeadTrackTarget; float mTurnAnimationThreshold; // how long to continue playing turning animation after actor stopped turning diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 8211c2f5f..ece57c273 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -388,9 +388,6 @@ void NpcAnimation::rebuild() { updateNpcBase(); - if (mAlpha != 1.f) - mResourceSystem->getSceneManager()->recreateShaders(mObjectRoot); - MWBase::Environment::get().getMechanicsManager()->forceStateUpdate(mPtr); } @@ -651,6 +648,9 @@ void NpcAnimation::updateParts() if (wasArrowAttached) attachArrow(); + + if (mAlpha != 1.f) + mResourceSystem->getSceneManager()->recreateShaders(mObjectRoot); } @@ -917,6 +917,8 @@ void NpcAnimation::showWeapons(bool showWeapon) attachArrow(); } } + if (mAlpha != 1.f) + mResourceSystem->getSceneManager()->recreateShaders(mObjectRoot); } else { @@ -942,6 +944,8 @@ void NpcAnimation::showCarriedLeft(bool show) if (iter->getTypeName() == typeid(ESM::Light).name() && mObjectParts[ESM::PRT_Shield]) addExtraLight(mObjectParts[ESM::PRT_Shield]->getNode()->asGroup(), iter->get()->mBase); } + if (mAlpha != 1.f) + mResourceSystem->getSceneManager()->recreateShaders(mObjectRoot); } else removeIndividualPart(ESM::PRT_Shield); diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index cd04a425b..981f63e34 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -806,7 +806,7 @@ void MWWorld::ContainerStore::readState (const ESM::InventoryState& inventory) case ESM::REC_WEAP: readEquipmentState (getState (weapons, state), thisIndex, inventory); break; case ESM::REC_LIGH: readEquipmentState (getState (lights, state), thisIndex, inventory); break; case 0: - std::cerr << "Warning: Dropping reference to '" << state.mRef.mRefID << "' (object no longer exists)" << std::endl; + std::cerr << "Dropping inventory reference to '" << state.mRef.mRefID << "' (object no longer exists)" << std::endl; break; default: std::cerr << "Warning: Invalid item type in inventory state, refid " << state.mRef.mRefID << std::endl; diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 7cb49c6cb..5efd1b86e 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -131,7 +131,11 @@ namespace Shader { std::string shaderSource = templateIt->second; if (!parseDefines(shaderSource, defines)) + { + // Add to the cache anyway to avoid logging the same error over and over. + mShaders.insert(std::make_pair(std::make_pair(shaderTemplate, defines), nullptr)); return NULL; + } osg::ref_ptr shader (new osg::Shader(shaderType)); shader->setShaderSource(shaderSource); diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index 8aec54835..640f2932b 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -116,7 +116,10 @@ namespace Terrain osg::ref_ptr vertexShader = shaderManager->getShader("terrain_vertex.glsl", defineMap, osg::Shader::VERTEX); osg::ref_ptr fragmentShader = shaderManager->getShader("terrain_fragment.glsl", defineMap, osg::Shader::FRAGMENT); if (!vertexShader || !fragmentShader) - throw std::runtime_error("Unable to create shader"); + { + // Try again without shader. Error already logged by above + return createPasses(false, forcePerPixelLighting, clampLighting, shaderManager, layers, blendmaps, blendmapScale, layerTileSize); + } stateset->setAttributeAndModes(shaderManager->getProgram(vertexShader, fragmentShader)); } diff --git a/docs/license/DejaVu Font License.txt b/files/mygui/DejaVu Font License.txt similarity index 100% rename from docs/license/DejaVu Font License.txt rename to files/mygui/DejaVu Font License.txt