diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 36d1ae4f4..a80575985 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -167,7 +167,8 @@ namespace MWClass return; } - // TODO: Handle HitOnMe script function + if(!object.isEmpty()) + getCreatureStats(ptr).setLastHitObject(MWWorld::Class::get(object).getId(object)); if(!attacker.isEmpty() && attacker.getRefData().getHandle() == "player") { diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 12144bedb..3ed45ac72 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -392,7 +392,8 @@ namespace MWClass return; } - // TODO: Handle HitOnMe script function + if(!object.isEmpty()) + getCreatureStats(ptr).setLastHitObject(MWWorld::Class::get(object).getId(object)); if(!attacker.isEmpty() && attacker.getRefData().getHandle() == "player") { diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index cb394d089..db07fb553 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -22,6 +22,13 @@ namespace MWClass { + std::string Weapon::getId (const MWWorld::Ptr& ptr) const + { + MWWorld::LiveCellRef *ref = ptr.get(); + + return ref->mBase->mId; + } + void Weapon::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 3902ef612..181c637db 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -12,6 +12,9 @@ namespace MWClass public: + virtual std::string getId (const MWWorld::Ptr& ptr) const; + ///< Return ID of \a ptr + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index baa264aa4..fb273c7c1 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -221,7 +221,11 @@ namespace MWMechanics for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) { - if(!MWWorld::Class::get(iter->first).getCreatureStats(iter->first).isDead()) + const MWWorld::Class &cls = MWWorld::Class::get(iter->first); + CreatureStats &stats = cls.getCreatureStats(iter->first); + + stats.setLastHitObject(std::string()); + if(!stats.isDead()) { if(iter->second->isDead()) iter->second->resurrect(); @@ -230,7 +234,7 @@ namespace MWMechanics if(iter->first.getTypeName() == typeid(ESM::NPC).name()) updateNpc(iter->first, totalDuration, paused); - if(!MWWorld::Class::get(iter->first).getCreatureStats(iter->first).isDead()) + if(!stats.isDead()) continue; } @@ -238,16 +242,15 @@ namespace MWMechanics // \todo remove workaround, once player death can be handled if(iter->first.getRefData().getHandle()=="player") { - MWMechanics::DynamicStat stat ( - MWWorld::Class::get(iter->first).getCreatureStats(iter->first).getHealth()); + MWMechanics::DynamicStat stat(stats.getHealth()); - if (stat.getModified()<1) + if(stat.getModified()<1) { - stat.setModified (1, 0); - MWWorld::Class::get(iter->first).getCreatureStats(iter->first).setHealth(stat); + stat.setModified(1, 0); + stats.setHealth(stat); } - MWWorld::Class::get(iter->first).getCreatureStats(iter->first).resurrect(); + stats.resurrect(); continue; } @@ -256,11 +259,10 @@ namespace MWMechanics iter->second->kill(); - ++mDeathCount[MWWorld::Class::get(iter->first).getId(iter->first)]; + ++mDeathCount[cls.getId(iter->first)]; - if(MWWorld::Class::get(iter->first).isEssential(iter->first)) - MWBase::Environment::get().getWindowManager()->messageBox( - "#{sKilledEssential}"); + if(cls.isEssential(iter->first)) + MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}"); } } diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index c43b80a25..5b4621905 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -318,4 +318,14 @@ namespace MWMechanics { return false; } + + void CreatureStats::setLastHitObject(const std::string& objectid) + { + mLastHitObject = objectid; + } + + const std::string &CreatureStats::getLastHitObject() const + { + return mLastHitObject; + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index a9a3caa49..fe46ed072 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -38,6 +38,8 @@ namespace MWMechanics int mAttackType; + std::string mLastHitObject; // The last object to hit this actor + public: CreatureStats(); @@ -155,6 +157,9 @@ namespace MWMechanics void setHostile (bool hostile); bool getCreatureTargetted() const; + + void setLastHitObject(const std::string &objectid); + const std::string &getLastHitObject() const; }; } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 85d8deaec..1b8682542 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -338,5 +338,7 @@ op 0x200020f: GetStandingActor, explicit op 0x2000210: GetStartingAngle op 0x2000211: GetStartingAngle, explicit op 0x2000212: GetWindSpeed +op 0x2000213: HitOnMe +op 0x2000214: HitOnMe, explicit -opcodes 0x2000213-0x3ffffff unused +opcodes 0x2000215-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 5ed26119c..453f6fbba 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -599,6 +599,23 @@ namespace MWScript } }; + template + class OpHitOnMe : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + std::string objectID = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + MWMechanics::CreatureStats &stats = MWWorld::Class::get(ptr).getCreatureStats(ptr); + runtime.push(::Misc::StringUtils::ciEqual(objectID, stats.getLastHitObject())); + } + }; + const int opcodeXBox = 0x200000c; const int opcodeOnActivate = 0x200000d; const int opcodeActivate = 0x2000075; @@ -650,6 +667,9 @@ namespace MWScript const int opcodePlayBink = 0x20001f7; + const int opcodeHitOnMe = 0x2000213; + const int opcodeHitOnMeExplicit = 0x2000214; + void registerExtensions (Compiler::Extensions& extensions) { extensions.registerFunction ("xbox", 'l', "", opcodeXBox); @@ -692,6 +712,7 @@ namespace MWScript extensions.registerFunction ("getstandingpc", 'l', "", opcodeGetStandingPc, opcodeGetStandingPcExplicit); extensions.registerFunction ("getstandingactor", 'l', "", opcodeGetStandingActor, opcodeGetStandingActorExplicit); extensions.registerFunction ("getwindspeed", 'f', "", opcodeGetWindSpeed); + extensions.registerFunction ("hitonme", 'l', "S", opcodeHitOnMe, opcodeHitOnMeExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -745,6 +766,8 @@ namespace MWScript interpreter.installSegment5 (opcodeGetStandingActor, new OpGetStandingActor); interpreter.installSegment5 (opcodeGetStandingActorExplicit, new OpGetStandingActor); interpreter.installSegment5 (opcodeGetWindSpeed, new OpGetWindSpeed); + interpreter.installSegment5 (opcodeHitOnMe, new OpHitOnMe); + interpreter.installSegment5 (opcodeHitOnMeExplicit, new OpHitOnMe); } } }