diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index d51b02a15..0b0569376 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -889,12 +889,23 @@ namespace MWMechanics iter->second->update(duration); } - // Kill dead actors + // Kill dead actors, update some variables for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) { const MWWorld::Class &cls = MWWorld::Class::get(iter->first); CreatureStats &stats = cls.getCreatureStats(iter->first); + //KnockedOutOneFrameLogic + //Used for "OnKnockedOut" command + //Put here to ensure that it's run for PRECISELY one frame. + if(stats.getKnockedDown() && !stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Start it for one frame if nessesary + stats.setKnockedDownOneFrame(true); + } + else if (stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Turn off KnockedOutOneframe + stats.setKnockedDownOneFrame(false); + stats.setKnockedDownOverOneFrame(true); + } + if(!stats.isDead()) { if(iter->second->isDead()) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index f81613ed1..40ac92251 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -17,7 +17,7 @@ namespace MWMechanics mAttacked (false), mHostile (false), mAttackingOrSpell(false), mIsWerewolf(false), - mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mHitRecovery(false), mBlock(false), + mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f) { for (int i=0; i<4; ++i) @@ -387,6 +387,8 @@ namespace MWMechanics void CreatureStats::setKnockedDown(bool value) { mKnockdown = value; + if(!value) //Resets the "OverOneFrame" flag + setKnockedDownOverOneFrame(false); } bool CreatureStats::getKnockedDown() const @@ -394,6 +396,23 @@ namespace MWMechanics return mKnockdown; } + void CreatureStats::setKnockedDownOneFrame(bool value) + { + mKnockdownOneFrame = value; + } + + bool CreatureStats::getKnockedDownOneFrame() const + { + return mKnockdownOneFrame; + } + + void CreatureStats::setKnockedDownOverOneFrame(bool value) { + mKnockdownOverOneFrame = value; + } + bool CreatureStats::getKnockedDownOverOneFrame() const { + return mKnockdownOverOneFrame; + } + void CreatureStats::setHitRecovery(bool value) { mHitRecovery = value; @@ -479,7 +498,7 @@ namespace MWMechanics } // Relates to NPC gold reset delay - void CreatureStats::setTradeTime(MWWorld::TimeStamp tradeTime) + void CreatureStats::setTradeTime(MWWorld::TimeStamp tradeTime) { mTradeTime = tradeTime; } @@ -489,11 +508,11 @@ namespace MWMechanics return mTradeTime; } - void CreatureStats::setGoldPool(int pool) + void CreatureStats::setGoldPool(int pool) { mGoldPool = pool; } - int CreatureStats::getGoldPool() const + int CreatureStats::getGoldPool() const { return mGoldPool; } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 5dc59e5ab..633dc285c 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -41,6 +41,8 @@ namespace MWMechanics bool mHostile; bool mAttackingOrSpell; bool mKnockdown; + bool mKnockdownOneFrame; + bool mKnockdownOverOneFrame; bool mHitRecovery; bool mBlock; unsigned int mMovementFlags; @@ -188,7 +190,14 @@ namespace MWMechanics float getEvasion() const; void setKnockedDown(bool value); + ///Returns true for the entire duration of the actor being knocked down bool getKnockedDown() const; + void setKnockedDownOneFrame(bool value); + ///Returns true only for the first frame of the actor being knocked out; used for "onKnockedOut" command + bool getKnockedDownOneFrame() const; + void setKnockedDownOverOneFrame(bool value); + ///Returns true for all but the first frame of being knocked out; used to know to not reset mKnockedDownOneFrame + bool getKnockedDownOverOneFrame() const; void setHitRecovery(bool value); bool getHitRecovery() const; void setBlock(bool value); diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index ceea34466..bf2273b17 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -388,5 +388,7 @@ op 0x200023c: StopCombat op 0x200023d: StopCombatExplicit op 0x200023e: GetPcInJail op 0x200023f: GetPcTraveling +op 0x2000240: onKnockout +op 0x2000241: onKnockoutExplicit -opcodes 0x2000240-0x3ffffff unused +opcodes 0x2000242-0x3ffffff unused diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 36083e4b0..2f584e7ed 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -1060,6 +1060,22 @@ namespace MWScript } }; + template + class OpOnKnockout : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = + MWWorld::Class::get (ptr).getCreatureStats (ptr).getKnockedDownOneFrame(); + + runtime.push (value); + } + }; + template class OpIsWerewolf : public Interpreter::Opcode0 { @@ -1236,6 +1252,8 @@ namespace MWScript interpreter.installSegment5 (Compiler::Stats::opcodeOnDeath, new OpOnDeath); interpreter.installSegment5 (Compiler::Stats::opcodeOnDeathExplicit, new OpOnDeath); + interpreter.installSegment5 (Compiler::Stats::opcodeOnKnockout, new OpOnKnockout); + interpreter.installSegment5 (Compiler::Stats::opcodeOnKnockoutExplicit, new OpOnKnockout); interpreter.installSegment5 (Compiler::Stats::opcodeIsWerewolf, new OpIsWerewolf); interpreter.installSegment5 (Compiler::Stats::opcodeIsWerewolfExplicit, new OpIsWerewolf); @@ -1245,7 +1263,7 @@ namespace MWScript interpreter.installSegment5 (Compiler::Stats::opcodeUndoWerewolf, new OpSetWerewolf); interpreter.installSegment5 (Compiler::Stats::opcodeUndoWerewolfExplicit, new OpSetWerewolf); interpreter.installSegment5 (Compiler::Stats::opcodeSetWerewolfAcrobatics, new OpSetWerewolfAcrobatics); - interpreter.installSegment5 (Compiler::Stats::opcodeSetWerewolfAcrobaticsExplicit, new OpSetWerewolfAcrobatics); + interpreter.installSegment5 (Compiler::Stats::opcodeSetWerewolfAcrobaticsExplicit, new OpSetWerewolfAcrobatics); } } } diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index 7e3f7a3cf..638c738bd 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -90,7 +90,7 @@ namespace MWWorld bool wasTeleported() const; void setTeleported(bool teleported); - ///Checks all actors to see if anyone has an aipackage against you + ///Checks all nearby actors to see if anyone has an aipackage against you bool isInCombat(); void clear(); diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 531fe2959..db1ac1609 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -444,6 +444,7 @@ namespace Compiler extensions.registerInstruction ("lowerrank", "", opcodeLowerRank, opcodeLowerRankExplicit); extensions.registerFunction ("ondeath", 'l', "", opcodeOnDeath, opcodeOnDeathExplicit); + extensions.registerFunction ("onknockout", 'l', "", opcodeOnKnockout, opcodeOnKnockoutExplicit); extensions.registerFunction ("iswerewolf", 'l', "", opcodeIsWerewolf, opcodeIsWerewolfExplicit); diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index 27ee182cf..9e36cb68d 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -377,6 +377,8 @@ namespace Compiler const int opcodeLowerRankExplicit = 0x20001eb; const int opcodeOnDeath = 0x20001fc; const int opcodeOnDeathExplicit = 0x2000205; + const int opcodeOnKnockout = 0x2000240; + const int opcodeOnKnockoutExplicit = 0x2000241; const int opcodeBecomeWerewolf = 0x2000217; const int opcodeBecomeWerewolfExplicit = 0x2000218;