Skip to content

Commit

Permalink
add: core scriptapi
Browse files Browse the repository at this point in the history
  • Loading branch information
jd28 committed Jan 7, 2025
1 parent 027f50f commit 9682005
Show file tree
Hide file tree
Showing 13 changed files with 318 additions and 269 deletions.
2 changes: 1 addition & 1 deletion benchmarks/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include <nw/formats/StaticTwoDA.hpp>
#include <nw/formats/TwoDA.hpp>
#include <nw/functions.hpp>
#include <nw/i18n/Tlk.hpp>
#include <nw/kernel/Objects.hpp>
#include <nw/kernel/Resources.hpp>
Expand All @@ -9,6 +8,7 @@
#include <nw/model/Mdl.hpp>
#include <nw/objects/Creature.hpp>
#include <nw/script/Nss.hpp>
#include <nw/scriptapi.hpp>
#include <nw/serialization/Gff.hpp>
#include <nw/serialization/GffBuilder.hpp>

Expand Down
1 change: 1 addition & 0 deletions lib/nw/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ find_package(Threads)
add_library(nw STATIC
functions.cpp
log.cpp
scriptapi.cpp

formats/Dialog.cpp
formats/Faction.cpp
Expand Down
184 changes: 1 addition & 183 deletions lib/nw/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,19 @@

#include "kernel/EffectSystem.hpp"
#include "kernel/EventSystem.hpp"
#include "kernel/Rules.hpp"
#include "kernel/Strings.hpp"
#include "objects/Creature.hpp"
#include "rules/feats.hpp"
#include "scriptapi.hpp"

namespace nw {

// == Effects =================================================================
// ============================================================================

bool apply_effect(nw::ObjectBase* obj, nw::Effect* effect)
{
if (!obj || !effect) { return false; }
if (nw::kernel::effects().apply(obj, effect)) {
obj->effects().add(effect);
return true;
}
return false;
}

int effect_extract_int0(const nw::EffectHandle& handle)
{
return handle.effect ? handle.effect->get_int(0) : 0;
}

bool has_effect_applied(nw::ObjectBase* obj, nw::EffectType type, int subtype)
{
if (!obj || type == nw::EffectType::invalid()) { return false; }
auto it = find_first_effect_of(std::begin(obj->effects()), std::end(obj->effects()),
type, subtype);

return it != std::end(obj->effects());
}

int queue_remove_effect_by(nw::ObjectBase* obj, nw::ObjectHandle creator)
{
if (!obj) { return 0; }
Expand All @@ -49,170 +28,9 @@ int queue_remove_effect_by(nw::ObjectBase* obj, nw::ObjectHandle creator)
return processed;
}

bool remove_effect(nw::ObjectBase* obj, nw::Effect* effect, bool destroy)
{
if (nw::kernel::effects().remove(obj, effect)) {
obj->effects().remove(effect);
if (destroy) { nw::kernel::effects().destroy(effect); }
return true;
}
return false;
}

int remove_effects_by(nw::ObjectBase* obj, nw::ObjectHandle creator)
{
int result = 0;
auto it = std::remove_if(std::begin(obj->effects()), std::end(obj->effects()),
[&](const nw::EffectHandle& handle) {
if (handle.creator == creator && nw::kernel::effects().remove(obj, handle.effect)) {
nw::kernel::effects().destroy(handle.effect);
++result;
return true;
}
return false;
});

obj->effects().erase(it, std::end(obj->effects()));

return result;
}

// == Feats ===================================================================
// ============================================================================

int count_feats_in_range(const nw::Creature* obj, nw::Feat start, nw::Feat end)
{
if (!obj) { return 0; }

int result = 0;
int32_t s = *start, e = *end;

while (e >= s) {
if (obj->stats.has_feat(nw::Feat::make(e))) {
++result;
}
--e;
}
return result;
}

Vector<nw::Feat> get_all_available_feats(const nw::Creature* obj)
{
if (!obj) return {};

Vector<nw::Feat> result;

auto& feats = nw::kernel::rules().feats;
if (!obj) {
return result;
}

for (size_t i = 0; i < feats.entries.size(); ++i) {
if (feats.entries[i].valid()
&& !obj->stats.has_feat(nw::Feat::make(uint32_t(i))) // [TODO] Not efficient
&& nw::kernel::rules().meets_requirement(feats.entries[i].requirements, obj)) {
result.push_back(nw::Feat::make(uint32_t(i)));
}
}

return result;
}

bool knows_feat(const nw::Creature* obj, nw::Feat feat)
{
if (!obj) { return false; }

auto it = std::lower_bound(std::begin(obj->stats.feats()), std::end(obj->stats.feats()), feat);
return it != std::end(obj->stats.feats()) && *it == feat;
}

std::pair<nw::Feat, int> has_feat_successor(const nw::Creature* obj, nw::Feat feat)
{
nw::Feat highest = nw::Feat::invalid();
int count = 0;

auto featarray = &nw::kernel::rules().feats;
if (!featarray || !obj) {
return {highest, count};
}

auto it = std::lower_bound(std::begin(obj->stats.feats()), std::end(obj->stats.feats()), feat);
do {
if (it == std::end(obj->stats.feats()) || *it != feat) {
break;
}
highest = feat;
++count;
const auto next_entry = featarray->get(feat);
if (!next_entry || next_entry->successor == nw::Feat::invalid()) {
break;
}
feat = next_entry->successor;
it = std::lower_bound(it, std::end(obj->stats.feats()), feat);
} while (true);

return {highest, count};
}

nw::Feat highest_feat_in_range(const nw::Creature* obj, nw::Feat start, nw::Feat end)
{
if (!obj) { return nw::Feat::invalid(); }

int32_t s = *start, e = *end;
while (e >= s) {
if (obj->stats.has_feat(nw::Feat::make(e))) {
return nw::Feat::make(e);
}
--e;
}
return nw::Feat::invalid();
}

// == Item Properties =========================================================
// ============================================================================

bool item_has_property(const Item* item, ItemPropertyType type, int32_t subtype)
{
if (!item) { return false; }
for (const auto& ip : item->properties) {
if (ip.type == *type && (subtype == -1 || ip.subtype == subtype)) {
return true;
}
}
return false;
}

String itemprop_to_string(const nw::ItemProperty& ip)
{
String result;
if (ip.type == std::numeric_limits<uint16_t>::max()) { return result; }
auto type = nw::ItemPropertyType::make(ip.type);
auto def = nw::kernel::effects().ip_definition(type);
if (!def) { return result; }

result = nw::kernel::strings().get(def->game_string);

if (ip.subtype != std::numeric_limits<uint16_t>::max() && def->subtype) {
if (auto name = def->subtype->get<uint32_t>(ip.subtype, "Name")) {
result += " " + nw::kernel::strings().get(*name);
}
}

if (ip.cost_value != std::numeric_limits<uint16_t>::max() && def->cost_table) {
if (auto name = def->cost_table->get<uint32_t>(ip.cost_value, "Name")) {
result += " " + nw::kernel::strings().get(*name);
}
}

if (ip.param_value != std::numeric_limits<uint8_t>::max() && def->param_table) {
if (auto name = def->param_table->get<uint32_t>(ip.param_value, "Name")) {
result += " " + nw::kernel::strings().get(*name);
}
}

return result;
}

int process_item_properties(nw::Creature* obj, const nw::Item* item, nw::EquipIndex index, bool remove)
{
if (!obj || !item) { return 0; }
Expand Down
39 changes: 1 addition & 38 deletions lib/nw/functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ enum struct EquipIndex : uint32_t;
// == Effects =================================================================
// ============================================================================

/// Applies an effect to an object
bool apply_effect(nw::ObjectBase* obj, nw::Effect* effect);

/// Extracts the 0th integer value from an effect
int effect_extract_int0(const nw::EffectHandle& effect);

Expand Down Expand Up @@ -51,18 +48,9 @@ It find_first_effect_of(It begin, It end, nw::EffectType type, int subtype = -1)
return std::lower_bound(begin, end, needle, comp);
}

/// Determines if an effect type is applied to an object
bool has_effect_applied(nw::ObjectBase* obj, nw::EffectType type, int subtype = -1);

/// Queues remove effect events by effect creator
int queue_remove_effect_by(nw::ObjectBase* obj, nw::ObjectHandle creator);

/// Removes an effect from an object
bool remove_effect(nw::ObjectBase* obj, nw::Effect* effect, bool destroy = true);

/// Removes effects by creator
int remove_effects_by(nw::ObjectBase* obj, nw::ObjectHandle creator);

/**
* @brief Finds all applicable effects of a given type / subtype.
*
Expand Down Expand Up @@ -191,34 +179,9 @@ std::pair<T, It> sum_effects_of(It begin, It end, nw::EffectType type, int subty
return std::make_pair(result, it);
}

// == Feats ===================================================================
// == Item: Properties ========================================================
// ============================================================================

/// Counts the number of known feats in the range [start, end]
int count_feats_in_range(const nw::Creature* obj, nw::Feat start, nw::Feat end);

/// Gets all feats for which requirements are met
/// @note This is not yet very useful until a level up parameter is added.
Vector<nw::Feat> get_all_available_feats(const nw::Creature* obj);

/// Gets the highest known successor feat
std::pair<nw::Feat, int> has_feat_successor(const nw::Creature* obj, nw::Feat feat);

/// Gets the highest known feat in range [start, end]
nw::Feat highest_feat_in_range(const nw::Creature* obj, nw::Feat start, nw::Feat end);

/// Checks if an entity knows a given feat
bool knows_feat(const nw::Creature* obj, nw::Feat feat);

// == Item Properties =========================================================
// ============================================================================

/// Determines if item has a particular item property
bool item_has_property(const Item* item, ItemPropertyType type, int32_t subtype = -1);

/// Converts item property to in-game style string
String itemprop_to_string(const nw::ItemProperty& ip);

/// Processes item properties and applies resulting effects to creature
int process_item_properties(nw::Creature* obj, const nw::Item* item, nw::EquipIndex index, bool remove);

Expand Down
1 change: 1 addition & 0 deletions lib/nw/profiles/nwn1/rules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "../../kernel/EffectSystem.hpp"
#include "../../kernel/Rules.hpp"
#include "../../objects/Creature.hpp"
#include "../../scriptapi.hpp"

namespace nwk = nw::kernel;

Expand Down
Loading

0 comments on commit 9682005

Please sign in to comment.