feat: Implement GetNearest* routines
This commit is contained in:
parent
f8ada74c47
commit
85ba198dc4
7 changed files with 114 additions and 10 deletions
|
@ -1001,6 +1001,25 @@ shared_ptr<Object> Area::createObject(ObjectType type, const string &blueprintRe
|
|||
return move(object);
|
||||
}
|
||||
|
||||
shared_ptr<SpatialObject> Area::getNearestObject(const glm::vec3 &origin, int nth, const std::function<bool(const std::shared_ptr<SpatialObject> &)> &predicate) {
|
||||
vector<pair<shared_ptr<SpatialObject>, float>> candidates;
|
||||
|
||||
for (auto &object : _objects) {
|
||||
if (predicate(object)) {
|
||||
candidates.push_back(make_pair(object, object->distanceTo(origin)));
|
||||
}
|
||||
}
|
||||
sort(candidates.begin(), candidates.end(), [](auto &left, auto &right) { return left.second < right.second; });
|
||||
|
||||
int numCandidates = static_cast<int>(candidates.size());
|
||||
if (nth >= numCandidates) {
|
||||
warn(boost::format("Area: getNearestObject: nth is out of bounds: %d/%d") % nth % numCandidates);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return candidates[nth].first;
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
||||
|
|
|
@ -106,6 +106,13 @@ public:
|
|||
|
||||
ObjectList &getObjectsByType(ObjectType type);
|
||||
|
||||
/**
|
||||
* Find the nth nearest object for which the specified predicate returns true.
|
||||
*
|
||||
* @param nth a 0-based object index
|
||||
*/
|
||||
std::shared_ptr<SpatialObject> getNearestObject(const glm::vec3 &origin, int nth, const std::function<bool(const std::shared_ptr<SpatialObject> &)> &predicate);
|
||||
|
||||
// END Objects
|
||||
|
||||
// Cameras
|
||||
|
|
|
@ -37,6 +37,7 @@ enum class ObjectType {
|
|||
Area = 0x1001,
|
||||
Camera = 0x1002,
|
||||
|
||||
All = 0x7fff,
|
||||
Invalid = 0x7fff
|
||||
};
|
||||
|
||||
|
|
|
@ -179,6 +179,11 @@ private:
|
|||
script::Variable getLocked(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
script::Variable getModule(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
script::Variable getName(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
script::Variable getNearestCreature(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
script::Variable getNearestCreatureToLocation(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
script::Variable getNearestObject(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
script::Variable getNearestObjectByTag(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
script::Variable getNearestObjectToLocation(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
script::Variable getNextItemInInventory(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
script::Variable getObjectByTag(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
script::Variable getObjectType(const VariablesList &args, script::ExecutionContext &ctx);
|
||||
|
|
|
@ -76,7 +76,7 @@ void Routines::addKotorRoutines() {
|
|||
add("ActionPutDownItem", Void, { Object }, &Routines::actionPutDownItem);
|
||||
add("GetLastAttacker", Object, { Object });
|
||||
add("ActionAttack", Void, { Object, Int }, &Routines::actionAttack);
|
||||
add("GetNearestCreature", Object, { Int, Int, Object, Int, Int, Int, Int, Int });
|
||||
add("GetNearestCreature", Object, { Int, Int, Object, Int, Int, Int, Int, Int }, &Routines::getNearestCreature);
|
||||
add("ActionSpeakString", Void, { String, Int }, &Routines::actionSpeakString);
|
||||
add("ActionPlayAnimation", Void, { Int, Float, Float }, &Routines::actionPlayAnimation);
|
||||
add("GetDistanceToObject", Float, { Object }, &Routines::getDistanceToObject);
|
||||
|
@ -264,10 +264,10 @@ void Routines::addKotorRoutines() {
|
|||
add("GetPositionFromLocation", TVector, { Location }, &Routines::getPositionFromLocation);
|
||||
add("EffectBodyFuel", Effect, { }, &Routines::effectBodyFuel);
|
||||
add("GetFacingFromLocation", Float, { Location }, &Routines::getFacingFromLocation);
|
||||
add("GetNearestCreatureToLocation", Object, { Int, Int, Location, Int, Int, Int, Int, Int });
|
||||
add("GetNearestObject", Object, { Int, Object, Int });
|
||||
add("GetNearestObjectToLocation", Object, { Int, Location, Int });
|
||||
add("GetNearestObjectByTag", Object, { String, Object, Int });
|
||||
add("GetNearestCreatureToLocation", Object, { Int, Int, Location, Int, Int, Int, Int, Int }, &Routines::getNearestCreatureToLocation);
|
||||
add("GetNearestObject", Object, { Int, Object, Int }, &Routines::getNearestObject);
|
||||
add("GetNearestObjectToLocation", Object, { Int, Location, Int }, &Routines::getNearestObjectToLocation);
|
||||
add("GetNearestObjectByTag", Object, { String, Object, Int }, &Routines::getNearestObjectByTag);
|
||||
add("IntToFloat", Float, { Int }, &Routines::intToFloat);
|
||||
add("FloatToInt", Int, { Float }, &Routines::floatToInt);
|
||||
add("StringToInt", Int, { String }, &Routines::stringToInt);
|
||||
|
|
|
@ -513,6 +513,78 @@ Variable Routines::createObject(const VariablesList &args, ExecutionContext &ctx
|
|||
return static_pointer_cast<ScriptObject>(_game->module()->area()->createObject(objectType, blueprintResRef, location));
|
||||
}
|
||||
|
||||
Variable Routines::getNearestCreature(const VariablesList &args, ExecutionContext &ctx) {
|
||||
int firstCriteriaType = getInt(args, 0);
|
||||
int firstCriteriaValue = getInt(args, 1);
|
||||
auto target = getSpatialObjectOrCaller(args, 2, ctx);
|
||||
int nth = getInt(args, 3, 1);
|
||||
int secondCriteriaType = getInt(args, 4, -1);
|
||||
int secondCriteriaValue = getInt(args, 5, -1);
|
||||
int thirdCriteriaType = getInt(args, 6, -1);
|
||||
int thirdCriteriaValue = getInt(args, 7, -1);
|
||||
|
||||
// TODO: handle criterias
|
||||
shared_ptr<SpatialObject> object(_game->module()->area()->getNearestObject(target->position(), nth - 1, [](auto &object) {
|
||||
return object->type() == ObjectType::Creature;
|
||||
}));
|
||||
|
||||
return static_pointer_cast<ScriptObject>(object);
|
||||
}
|
||||
|
||||
Variable Routines::getNearestCreatureToLocation(const VariablesList &args, ExecutionContext &ctx) {
|
||||
int firstCriteriaType = getInt(args, 0);
|
||||
int firstCriteriaValue = getInt(args, 1);
|
||||
auto location = getLocationEngineType(args, 2);
|
||||
int nth = getInt(args, 3, 1);
|
||||
int secondCriteriaType = getInt(args, 4, -1);
|
||||
int secondCriteriaValue = getInt(args, 5, -1);
|
||||
int thirdCriteriaType = getInt(args, 6, -1);
|
||||
int thirdCriteriaValue = getInt(args, 7, -1);
|
||||
|
||||
// TODO: handle criterias
|
||||
shared_ptr<SpatialObject> object(_game->module()->area()->getNearestObject(location->position(), nth - 1, [](auto &object) {
|
||||
return object->type() == ObjectType::Creature;
|
||||
}));
|
||||
|
||||
return static_pointer_cast<ScriptObject>(object);
|
||||
}
|
||||
|
||||
Variable Routines::getNearestObject(const VariablesList &args, ExecutionContext &ctx) {
|
||||
auto objectType = static_cast<ObjectType>(getInt(args, 0, static_cast<int>(ObjectType::All)));
|
||||
auto target = getSpatialObjectOrCaller(args, 1, ctx);
|
||||
int nth = getInt(args, 2, 1);
|
||||
|
||||
shared_ptr<SpatialObject> object(_game->module()->area()->getNearestObject(target->position(), nth - 1, [&objectType](auto &object) {
|
||||
return object->type() == objectType;
|
||||
}));
|
||||
|
||||
return static_pointer_cast<ScriptObject>(object);
|
||||
}
|
||||
|
||||
Variable Routines::getNearestObjectToLocation(const VariablesList &args, ExecutionContext &ctx) {
|
||||
auto objectType = static_cast<ObjectType>(getInt(args, 0));
|
||||
auto location = getLocationEngineType(args, 1);
|
||||
int nth = getInt(args, 2, 1);
|
||||
|
||||
shared_ptr<SpatialObject> object(_game->module()->area()->getNearestObject(location->position(), nth - 1, [&objectType](auto &object) {
|
||||
return object->type() == objectType;
|
||||
}));
|
||||
|
||||
return static_pointer_cast<ScriptObject>(object);
|
||||
}
|
||||
|
||||
Variable Routines::getNearestObjectByTag(const VariablesList &args, ExecutionContext &ctx) {
|
||||
string tag(boost::to_lower_copy(getString(args, 0)));
|
||||
auto target = getSpatialObjectOrCaller(args, 1, ctx);
|
||||
int nth = getInt(args, 2, 1);
|
||||
|
||||
shared_ptr<SpatialObject> object(_game->module()->area()->getNearestObject(target->position(), nth - 1, [&tag](auto &object) {
|
||||
return object->tag() == tag;
|
||||
}));
|
||||
|
||||
return static_pointer_cast<ScriptObject>(object);
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
||||
|
|
|
@ -76,7 +76,7 @@ void Routines::addTslRoutines() {
|
|||
add("ActionPutDownItem", Void, { Object }, &Routines::actionPutDownItem);
|
||||
add("GetLastAttacker", Object, { Object });
|
||||
add("ActionAttack", Void, { Object, Int }, &Routines::actionAttack);
|
||||
add("GetNearestCreature", Object, { Int, Int, Object, Int, Int, Int, Int, Int });
|
||||
add("GetNearestCreature", Object, { Int, Int, Object, Int, Int, Int, Int, Int }, &Routines::getNearestCreature);
|
||||
add("ActionSpeakString", Void, { String, Int }, &Routines::actionSpeakString);
|
||||
add("ActionPlayAnimation", Void, { Int, Float, Float }, &Routines::actionPlayAnimation);
|
||||
add("GetDistanceToObject", Float, { Object }, &Routines::getDistanceToObject);
|
||||
|
@ -264,10 +264,10 @@ void Routines::addTslRoutines() {
|
|||
add("GetPositionFromLocation", TVector, { Location }, &Routines::getPositionFromLocation);
|
||||
add("EffectBodyFuel", Effect, { }, &Routines::effectBodyFuel);
|
||||
add("GetFacingFromLocation", Float, { Location }, &Routines::getFacingFromLocation);
|
||||
add("GetNearestCreatureToLocation", Object, { Int, Int, Location, Int, Int, Int, Int, Int });
|
||||
add("GetNearestObject", Object, { Int, Object, Int });
|
||||
add("GetNearestObjectToLocation", Object, { Int, Location, Int });
|
||||
add("GetNearestObjectByTag", Object, { String, Object, Int });
|
||||
add("GetNearestCreatureToLocation", Object, { Int, Int, Location, Int, Int, Int, Int, Int }, &Routines::getNearestCreatureToLocation);
|
||||
add("GetNearestObject", Object, { Int, Object, Int }, &Routines::getNearestObject);
|
||||
add("GetNearestObjectToLocation", Object, { Int, Location, Int }, &Routines::getNearestObjectToLocation);
|
||||
add("GetNearestObjectByTag", Object, { String, Object, Int }, &Routines::getNearestObjectByTag);
|
||||
add("IntToFloat", Float, { Int }, &Routines::intToFloat);
|
||||
add("FloatToInt", Int, { Float }, &Routines::floatToInt);
|
||||
add("StringToInt", Int, { String }, &Routines::stringToInt);
|
||||
|
|
Loading…
Reference in a new issue