diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp index adfd6d5fce..c92b2c0403 100644 --- a/apps/openmw/mwmechanics/alchemy.cpp +++ b/apps/openmw/mwmechanics/alchemy.cpp @@ -273,7 +273,7 @@ void MWMechanics::Alchemy::addPotion (const std::string& name) newRecord.mName = name; - int index = static_cast (std::rand()/static_cast (RAND_MAX+1)*6); + int index = static_cast (std::rand()/(static_cast (RAND_MAX)+1)*6); assert (index>=0 && index<6); static const char *name[] = { "standard", "bargain", "cheap", "fresh", "exclusive", "quality" }; diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 52ed43be37..c0450c3443 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -342,4 +342,18 @@ namespace MWMechanics { return mLastHitObject; } + + bool CreatureStats::canUsePower(const std::string &power) + { + std::map::iterator it = mUsedPowers.find(power); + if (it == mUsedPowers.end() || it->second + 24 <= MWBase::Environment::get().getWorld()->getTimeStamp()) + return true; + else + return false; + } + + void CreatureStats::usePower(const std::string &power) + { + mUsedPowers[power] = MWBase::Environment::get().getWorld()->getTimeStamp(); + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 1a7cb5d698..989f1d48c5 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -40,6 +40,8 @@ namespace MWMechanics std::string mLastHitObject; // The last object to hit this actor + std::map mUsedPowers; + protected: bool mIsWerewolf; Stat mWerewolfAttributes[8]; @@ -47,6 +49,9 @@ namespace MWMechanics public: CreatureStats(); + bool canUsePower (const std::string& power); + void usePower (const std::string& power); + const Stat & getAttribute(int index) const; const DynamicStat & getHealth() const; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 6c18ec4fd6..a352c0e11b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1991,6 +1991,7 @@ namespace MWWorld stats.setAttackingOrSpell(false); std::string selectedSpell = stats.getSpells().getSelectedSpell(); + std::string sourceName = ""; if (!selectedSpell.empty()) { const ESM::Spell* spell = getStore().get().search(selectedSpell); @@ -2011,6 +2012,18 @@ namespace MWWorld stats.setMagicka(magicka); } + // If this is a power, check if it was already used in last 24h + if (!fail && spell->mData.mType & ESM::Spell::ST_Power) + { + if (stats.canUsePower(selectedSpell)) + stats.usePower(selectedSpell); + else + { + MWBase::Environment::get().getWindowManager()->messageBox("#{sPowerAlreadyUsed}"); + fail = true; + } + } + // Check success int successChance = MWMechanics::getSpellSuccessChance(selectedSpell, actor); int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] @@ -2042,18 +2055,13 @@ namespace MWWorld actor.getClass().skillUsageSucceeded(actor, MWMechanics::spellSchoolToSkill(MWMechanics::getSpellSchool(selectedSpell, actor)), 0); - actor.getClass().getCreatureStats(actor).getActiveSpells().addSpell(selectedSpell, actor, ESM::RT_Self); - // TODO: RT_Range, RT_Touch - return; } - InventoryStore& inv = actor.getClass().getInventoryStore(actor); - if (inv.getSelectedEnchantItem() != inv.end()) + if (selectedSpell.empty() && inv.getSelectedEnchantItem() != inv.end()) { MWWorld::Ptr item = *inv.getSelectedEnchantItem(); - std::string id = item.getClass().getEnchantment(item); - const ESM::Enchantment* enchantment = getStore().get().search (id); - + selectedSpell = item.getClass().getEnchantment(item); + const ESM::Enchantment* enchantment = getStore().get().search (selectedSpell); if (enchantment->mData.mType == ESM::Enchantment::WhenUsed) { @@ -2080,8 +2088,7 @@ namespace MWWorld item.getRefData().setCount(item.getRefData().getCount()-1); } - std::string itemName = item.getClass().getName(item); - actor.getClass().getCreatureStats(actor).getActiveSpells().addSpell(id, actor, ESM::RT_Self, itemName); + sourceName = item.getClass().getName(item); if (!item.getRefData().getCount()) { @@ -2091,10 +2098,28 @@ namespace MWWorld } else MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item); // Set again to show the modified charge - - - // TODO: RT_Range, RT_Touch } + + // Now apply the spell! + + // Apply Self portion + actor.getClass().getCreatureStats(actor).getActiveSpells().addSpell(selectedSpell, actor, ESM::RT_Self, sourceName); + + // Apply Touch portion + // TODO: Distance is probably incorrect, and should it be hardcoded? + std::pair contact = getHitContact(actor, 100); + if (!contact.first.isEmpty()) + { + if (contact.first.getClass().isActor()) + contact.first.getClass().getCreatureStats(contact.first).getActiveSpells().addSpell(selectedSpell, contact.first, ESM::RT_Touch, sourceName); + else + { + // We hit a non-actor, e.g. a door. Only instant effects are relevant. + // inflictSpellOnNonActor(contact.first, selectedSpell, ESM::RT_Touch); + } + } + + // TODO: Launch projectile if there's a Target portion } }