mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-20 20:53:53 +00:00
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
729e079b0b
10 changed files with 59 additions and 34 deletions
|
@ -48,7 +48,7 @@ add_openmw_dir (mwscript
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwsound
|
add_openmw_dir (mwsound
|
||||||
soundmanagerimp openal_output ffmpeg_decoder
|
soundmanagerimp openal_output ffmpeg_decoder sound
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwworld
|
add_openmw_dir (mwworld
|
||||||
|
|
|
@ -96,6 +96,9 @@ namespace MWBase
|
||||||
/// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check!
|
/// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check!
|
||||||
virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) = 0;
|
virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) = 0;
|
||||||
|
|
||||||
|
/// Makes \a ptr fight \a target. Also shouts a combat taunt.
|
||||||
|
virtual void startCombat (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target) = 0;
|
||||||
|
|
||||||
enum OffenseType
|
enum OffenseType
|
||||||
{
|
{
|
||||||
OT_Theft, // Taking items owned by an NPC or a faction you are not a member of
|
OT_Theft, // Taking items owned by an NPC or a faction you are not a member of
|
||||||
|
|
|
@ -337,6 +337,12 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
// NOTE: 'object' and/or 'attacker' may be empty.
|
// NOTE: 'object' and/or 'attacker' may be empty.
|
||||||
|
|
||||||
|
getCreatureStats(ptr).setAttacked(true);
|
||||||
|
|
||||||
|
// Self defense
|
||||||
|
if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() < 80)
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, attacker);
|
||||||
|
|
||||||
if(!successful)
|
if(!successful)
|
||||||
{
|
{
|
||||||
// TODO: Handle HitAttemptOnMe script function
|
// TODO: Handle HitAttemptOnMe script function
|
||||||
|
|
|
@ -621,7 +621,7 @@ namespace MWClass
|
||||||
// NOTE: 'object' and/or 'attacker' may be empty.
|
// NOTE: 'object' and/or 'attacker' may be empty.
|
||||||
|
|
||||||
// Attacking peaceful NPCs is a crime
|
// Attacking peaceful NPCs is a crime
|
||||||
if (!attacker.isEmpty() && ptr.getClass().isNpc() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30)
|
if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30)
|
||||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
|
MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
|
||||||
|
|
||||||
getCreatureStats(ptr).setAttacked(true);
|
getCreatureStats(ptr).setAttacked(true);
|
||||||
|
|
|
@ -1447,7 +1447,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
return !MyGUI::InputManager::getInstance().isModalAny()
|
return !MyGUI::InputManager::getInstance().isModalAny()
|
||||||
// TODO: remove this, once we have properly serialized the state of open windows
|
// TODO: remove this, once we have properly serialized the state of open windows
|
||||||
&& (!isGuiMode() || (mGuiModes.size() == 1 && getMode() == GM_MainMenu));
|
&& (!isGuiMode() || (mGuiModes.size() == 1 && (getMode() == GM_MainMenu || getMode() == GM_Rest || getMode() == GM_RestBed)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::playVideo(const std::string &name, bool allowSkipping)
|
void WindowManager::playVideo(const std::string &name, bool allowSkipping)
|
||||||
|
|
|
@ -206,8 +206,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
if (LOS)
|
if (LOS)
|
||||||
{
|
{
|
||||||
creatureStats.getAiSequence().stack(AiCombat(MWBase::Environment::get().getWorld()->getPlayerPtr()), ptr);
|
MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player);
|
||||||
creatureStats.setHostile(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -762,16 +761,11 @@ namespace MWMechanics
|
||||||
if (ptr.getClass().isClass(ptr, "Guard"))
|
if (ptr.getClass().isClass(ptr, "Guard"))
|
||||||
creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr);
|
creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr);
|
||||||
else
|
else
|
||||||
creatureStats.getAiSequence().stack(AiCombat(player), ptr);
|
{
|
||||||
creatureStats.setHostile(true);
|
MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if I didn't report a crime was I attacked?
|
|
||||||
else if (creatureStats.getAttacked() && !creatureStats.isHostile())
|
|
||||||
{
|
|
||||||
creatureStats.getAiSequence().stack(AiCombat(player), ptr);
|
|
||||||
creatureStats.setHostile(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1081,6 +1075,8 @@ namespace MWMechanics
|
||||||
if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat)
|
if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat)
|
||||||
{
|
{
|
||||||
MWMechanics::AiCombat* package = static_cast<MWMechanics::AiCombat*>(stats.getAiSequence().getActivePackage());
|
MWMechanics::AiCombat* package = static_cast<MWMechanics::AiCombat*>(stats.getAiSequence().getActivePackage());
|
||||||
|
// TODO: This is wrong! It's comparing Ref IDs with Ogre handles. The only case where this (coincidentally) works is the player.
|
||||||
|
// possibly applies to other code using getTargetId.
|
||||||
if(package->getTargetId() == actor.getCellRef().mRefID)
|
if(package->getTargetId() == actor.getCellRef().mRefID)
|
||||||
list.push_front(*iter);
|
list.push_front(*iter);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
void stack (const AiPackage& package, const MWWorld::Ptr& actor);
|
void stack (const AiPackage& package, const MWWorld::Ptr& actor);
|
||||||
///< Add \a package to the front of the sequence (suspends current package)
|
///< Add \a package to the front of the sequence (suspends current package)
|
||||||
|
/// @param actor The actor that owns this AiSequence
|
||||||
|
|
||||||
void queue (const AiPackage& package);
|
void queue (const AiPackage& package);
|
||||||
///< Add \a package to the end of the sequence (executed after all other packages have been
|
///< Add \a package to the end of the sequence (executed after all other packages have been
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/aicombat.hpp"
|
||||||
|
|
||||||
#include <OgreSceneNode.h>
|
#include <OgreSceneNode.h>
|
||||||
|
|
||||||
#include "spellcasting.hpp"
|
#include "spellcasting.hpp"
|
||||||
|
@ -852,27 +854,45 @@ namespace MWMechanics
|
||||||
// Innocent until proven guilty
|
// Innocent until proven guilty
|
||||||
bool reported = false;
|
bool reported = false;
|
||||||
|
|
||||||
// Find all the NPCs within the alarm radius
|
// Find all the actors within the alarm radius
|
||||||
std::vector<MWWorld::Ptr> neighbors;
|
std::vector<MWWorld::Ptr> neighbors;
|
||||||
mActors.getObjectsInRange(Ogre::Vector3(ptr.getRefData().getPosition().pos),
|
mActors.getObjectsInRange(Ogre::Vector3(ptr.getRefData().getPosition().pos),
|
||||||
esmStore.get<ESM::GameSetting>().find("fAlarmRadius")->getInt(), neighbors);
|
esmStore.get<ESM::GameSetting>().find("fAlarmRadius")->getInt(), neighbors);
|
||||||
|
|
||||||
// Find an actor who witnessed the crime
|
int id = MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId();
|
||||||
|
|
||||||
|
// Find actors who witnessed the crime
|
||||||
for (std::vector<MWWorld::Ptr>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
|
for (std::vector<MWWorld::Ptr>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
|
||||||
{
|
{
|
||||||
if ( *it == ptr
|
if (*it == ptr) continue; // not the player
|
||||||
|| !it->getClass().isNpc()) continue; // not the player and is an NPC
|
|
||||||
|
|
||||||
// Was the crime seen?
|
// Was the crime seen?
|
||||||
if ( ( MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) ||
|
if (MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) )
|
||||||
type == OT_Assault )
|
|
||||||
{
|
{
|
||||||
|
// TODO: Add more messages
|
||||||
|
if (type == OT_Theft)
|
||||||
|
MWBase::Environment::get().getDialogueManager()->say(*it, "thief");
|
||||||
|
|
||||||
|
if (*it == victim)
|
||||||
|
{
|
||||||
|
// Self-defense
|
||||||
|
// The victim is aware of the criminal/assailant. If being assaulted, fight back now
|
||||||
|
// (regardless of whether the assault is reported or not)
|
||||||
|
// This applies to both NPCs and creatures
|
||||||
|
|
||||||
|
// ... except if this is a guard: then the player is given a chance to pay a fine / go to jail instead
|
||||||
|
if (type == OT_Assault && !ptr.getClass().isClass(ptr, "guard"))
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->startCombat(victim, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crime reporting only applies to NPCs
|
||||||
|
if (!it->getClass().isNpc())
|
||||||
|
continue;
|
||||||
|
|
||||||
// Will the witness report the crime?
|
// Will the witness report the crime?
|
||||||
if (it->getClass().getCreatureStats(*it).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm)
|
if (it->getClass().getCreatureStats(*it).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm)
|
||||||
{
|
{
|
||||||
reported = true;
|
reported = true;
|
||||||
int id = MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId();
|
|
||||||
|
|
||||||
// Tell everyone, including yourself
|
// Tell everyone, including yourself
|
||||||
for (std::vector<MWWorld::Ptr>::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1)
|
for (std::vector<MWWorld::Ptr>::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1)
|
||||||
|
@ -880,12 +900,6 @@ namespace MWMechanics
|
||||||
if ( *it1 == ptr
|
if ( *it1 == ptr
|
||||||
|| !it1->getClass().isNpc()) continue; // not the player and is an NPC
|
|| !it1->getClass().isNpc()) continue; // not the player and is an NPC
|
||||||
|
|
||||||
// TODO: Add more messages
|
|
||||||
if (type == OT_Theft)
|
|
||||||
MWBase::Environment::get().getDialogueManager()->say(*it1, "thief");
|
|
||||||
else if (type == OT_Assault)
|
|
||||||
MWBase::Environment::get().getDialogueManager()->say(*it1, "attack");
|
|
||||||
|
|
||||||
// Will other witnesses paticipate in crime
|
// Will other witnesses paticipate in crime
|
||||||
if ( it1->getClass().getCreatureStats(*it1).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm
|
if ( it1->getClass().getCreatureStats(*it1).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm
|
||||||
|| type == OT_Assault )
|
|| type == OT_Assault )
|
||||||
|
@ -896,7 +910,6 @@ namespace MWMechanics
|
||||||
// Mark as Alarmed for dialogue
|
// Mark as Alarmed for dialogue
|
||||||
it1->getClass().getCreatureStats(*it1).setAlarmed(true);
|
it1->getClass().getCreatureStats(*it1).setAlarmed(true);
|
||||||
}
|
}
|
||||||
break; // Someone saw the crime and everyone has been told
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1007,6 +1020,14 @@ namespace MWMechanics
|
||||||
return (roll >= target);
|
return (roll >= target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MechanicsManager::startCombat(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getDialogueManager()->say(ptr, "attack");
|
||||||
|
ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(MWMechanics::AiCombat(target), ptr);
|
||||||
|
if (target == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||||
|
ptr.getClass().getCreatureStats(ptr).setHostile(true);
|
||||||
|
}
|
||||||
|
|
||||||
void MechanicsManager::getObjectsInRange(const Ogre::Vector3 &position, float radius, std::vector<MWWorld::Ptr> &objects)
|
void MechanicsManager::getObjectsInRange(const Ogre::Vector3 &position, float radius, std::vector<MWWorld::Ptr> &objects)
|
||||||
{
|
{
|
||||||
mActors.getObjectsInRange(position, radius, objects);
|
mActors.getObjectsInRange(position, radius, objects);
|
||||||
|
|
|
@ -105,6 +105,9 @@ namespace MWMechanics
|
||||||
/// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check!
|
/// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check!
|
||||||
virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer);
|
virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer);
|
||||||
|
|
||||||
|
/// Makes \a ptr fight \a target. Also shouts a combat taunt.
|
||||||
|
virtual void startCombat (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Commit a crime. If any actors witness the crime and report it,
|
* @brief Commit a crime. If any actors witness the crime and report it,
|
||||||
* reportCrime will be called automatically.
|
* reportCrime will be called automatically.
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#include "../mwmechanics/aifollow.hpp"
|
#include "../mwmechanics/aifollow.hpp"
|
||||||
#include "../mwmechanics/aitravel.hpp"
|
#include "../mwmechanics/aitravel.hpp"
|
||||||
#include "../mwmechanics/aiwander.hpp"
|
#include "../mwmechanics/aiwander.hpp"
|
||||||
#include "../mwmechanics/aicombat.hpp"
|
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
@ -435,12 +434,8 @@ namespace MWScript
|
||||||
std::string targetID = runtime.getStringLiteral (runtime[0].mInteger);
|
std::string targetID = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
|
||||||
MWMechanics::CreatureStats& creatureStats = actor.getClass().getCreatureStats(actor);
|
MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(targetID, true);
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->startCombat(actor, target);
|
||||||
|
|
||||||
creatureStats.setHostile(true);
|
|
||||||
creatureStats.getAiSequence().stack(
|
|
||||||
MWMechanics::AiCombat(MWBase::Environment::get().getWorld()->getPtr(targetID, true) ), actor);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue