Skip to content

Commit

Permalink
improve: rework in unscripted weapons and moveevents
Browse files Browse the repository at this point in the history
Add moveevent and weapons unscripted to load in items.xml

TODO:
- [ ] Fix reload items crash
- [ ] Implement load weapons logic
  • Loading branch information
dudantas committed Aug 23, 2023
1 parent 99593cc commit dce63dc
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -241,28 +241,6 @@ local items = {
{"Royal Paladin"}
}
},
{
-- sanguine legs
itemid = 43876,
type = "equip",
slot = "legs",
level = 500,
vocation = {
{"Knight", true},
{"Elite Knight"}
}
},
{
-- sanguine legs
itemid = 43876,
type = "deequip",
slot = "legs",
level = 500,
vocation = {
{"Knight", true},
{"Elite Knight"}
}
},
{
-- grand sanguine battleaxe
itemid = 43875,
Expand Down
5 changes: 5 additions & 0 deletions data/items/items.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59248,6 +59248,11 @@
<attribute key="skillsword" value="4"/>
<attribute key="armor" value="12"/>
<attribute key="weight" value="3800"/>
<attribute key="script" value="moveevent">
<attribute key="slot" value="legs"/>
<attribute key="level" value="500"/>
<attribute key="vocation" value="Knight;true, Elite Knight"/>
</attribute>
</item>
<item id="43877" article="a" name="sanguine bow">
<attribute key="weaponType" value="distance"/>
Expand Down
12 changes: 7 additions & 5 deletions src/canary_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,13 @@ void CanaryServer::loadModules() {
auto coreFolder = g_configManager().getString(CORE_DIRECTORY);
// Load items dependencies
modulesLoadHelper((g_game().loadAppearanceProtobuf(coreFolder + "/items/appearances.dat") == ERROR_NONE), "appearances.dat");
// Load XML core first (dependencies that can be used on items.xml loading)
modulesLoadHelper(g_vocations().loadFromXml(), "XML/vocations.xml");
modulesLoadHelper(Outfits::getInstance().loadFromXml(), "XML/outfits.xml");
modulesLoadHelper(Familiars::getInstance().loadFromXml(), "XML/familiars.xml");
modulesLoadHelper(g_storages().loadFromXML(), "XML/storages.xml");
modulesLoadHelper(g_imbuements().loadFromXml(), "XML/imbuements.xml");

modulesLoadHelper(Item::items.loadFromXml(), "items.xml");

auto datapackFolder = g_configManager().getString(DATA_DIRECTORY);
Expand All @@ -332,12 +339,7 @@ void CanaryServer::loadModules() {
modulesLoadHelper(g_scripts().loadScripts(coreFolder + "/scripts", false, false), "/data/scripts");

// Second XML scripts
modulesLoadHelper(g_vocations().loadFromXml(), "XML/vocations.xml");
modulesLoadHelper(g_eventsScheduler().loadScheduleEventFromXml(), "XML/events.xml");
modulesLoadHelper(Outfits::getInstance().loadFromXml(), "XML/outfits.xml");
modulesLoadHelper(Familiars::getInstance().loadFromXml(), "XML/familiars.xml");
modulesLoadHelper(g_imbuements().loadFromXml(), "XML/imbuements.xml");
modulesLoadHelper(g_storages().loadFromXML(), "XML/storages.xml");
modulesLoadHelper(g_modules().loadFromXml(), "modules/modules.xml");
modulesLoadHelper(g_events().loadFromXml(), "events/events.xml");
modulesLoadHelper((g_npcs().load(true, false)), "npclib");
Expand Down
126 changes: 126 additions & 0 deletions src/items/functions/item/item_parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "pch.hpp"

#include "items/functions/item/item_parse.hpp"
#include "lua/creature/movement.hpp"
#include "utils/pugicast.hpp"

void ItemParse::initParse(const std::string &tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType) {
Expand Down Expand Up @@ -73,6 +74,7 @@ void ItemParse::initParse(const std::string &tmpStrValue, pugi::xml_node attribu
ItemParse::parseCleavePercent(tmpStrValue, valueAttribute, itemType);
ItemParse::parseReflectDamage(tmpStrValue, valueAttribute, itemType);
ItemParse::parseTransformOnUse(tmpStrValue, valueAttribute, itemType);
ItemParse::parseUnscriptedItems(tmpStrValue, attributeNode, valueAttribute, itemType);
}

void ItemParse::parseDummyRate(pugi::xml_node attributeNode, ItemType &itemType) {
Expand Down Expand Up @@ -940,3 +942,127 @@ void ItemParse::parseTransformOnUse(const std::string_view &tmpStrValue, pugi::x
itemType.m_transformOnUse = pugi::cast<uint16_t>(valueAttribute.value());
}
}

void ItemParse::createAndRegisterMoveEvent(MoveEvent_t eventType, const ItemType &itemType, pugi::xml_node attributeNode) {
auto moveevent = std::make_shared<MoveEvent>(nullptr);
moveevent->setItemId(itemType.id);
moveevent->setEventType(eventType);
if (eventType == MOVE_EVENT_EQUIP) {
moveevent->equipFunction = moveevent->EquipItem;
} else if (eventType == MOVE_EVENT_DEEQUIP) {
moveevent->equipFunction = moveevent->DeEquipItem;
}

for (auto subAttributeNode : attributeNode.children()) {
pugi::xml_attribute subKeyAttribute = subAttributeNode.attribute("key");
if (!subKeyAttribute) {
continue;
}

pugi::xml_attribute subValueAttribute = subAttributeNode.attribute("value");
if (!subValueAttribute) {
continue;
}

auto stringKey = asLowerCaseString(subKeyAttribute.as_string());
if (stringKey == "slot") {
if (moveevent->getEventType() == MOVE_EVENT_EQUIP || moveevent->getEventType() == MOVE_EVENT_DEEQUIP) {
auto slotName = asLowerCaseString(subValueAttribute.as_string());
if (slotName == "head") {
moveevent->setSlot(SLOTP_HEAD);
} else if (slotName == "necklace") {
moveevent->setSlot(SLOTP_NECKLACE);
} else if (slotName == "backpack") {
moveevent->setSlot(SLOTP_BACKPACK);
} else if (slotName == "armor" || slotName == "body") {
moveevent->setSlot(SLOTP_ARMOR);
} else if (slotName == "right-hand") {
moveevent->setSlot(SLOTP_RIGHT);
} else if (slotName == "left-hand") {
moveevent->setSlot(SLOTP_LEFT);
} else if (slotName == "hand" || slotName == "shield") {
moveevent->setSlot(SLOTP_RIGHT | SLOTP_LEFT);
} else if (slotName == "legs") {
moveevent->setSlot(SLOTP_LEGS);
} else if (slotName == "feet") {
moveevent->setSlot(SLOTP_FEET);
} else if (slotName == "ring") {
moveevent->setSlot(SLOTP_RING);
} else if (slotName == "ammo") {
moveevent->setSlot(SLOTP_AMMO);
} else {
g_logger().warn("[{}] unknown slot type: {}", __FUNCTION__, slotName);
}
}
} else if (stringKey == "level") {
auto numberValue = subValueAttribute.as_uint();
moveevent->setRequiredLevel(numberValue);
moveevent->setWieldInfo(WIELDINFO_LEVEL);
} else if (stringKey == "vocation") {
auto vocations = subValueAttribute.as_string();
std::string tmp;
std::stringstream ss(vocations);
std::string token;

while (std::getline(ss, token, ',')) {
token.erase(token.begin(), std::find_if(token.begin(), token.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
token.erase(std::find_if(token.rbegin(), token.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(),
token.end());

std::string v1;
bool showInDescription = false;

std::stringstream inner_ss(token);
std::getline(inner_ss, v1, ';');
std::string showInDescriptionStr;
std::getline(inner_ss, showInDescriptionStr, ';');
showInDescription = showInDescriptionStr == "true";

moveevent->addVocEquipMap(v1);
moveevent->setWieldInfo(WIELDINFO_VOCREQ);

if (showInDescription) {
if (moveevent->getVocationString().empty()) {
tmp = asLowerCaseString(v1);
tmp += "s";
moveevent->setVocationString(tmp);
} else {
tmp += ", ";
tmp += asLowerCaseString(v1);
tmp += "s";
}
}
}

size_t lastComma = tmp.rfind(',');
if (lastComma != std::string::npos) {
tmp.replace(lastComma, 1, " and");
moveevent->setVocationString(tmp);
}
}
}

if (!g_moveEvents().registerLuaItemEvent(moveevent)) {
g_logger().error("[{}] failed to register moveevent from item name {}", __FUNCTION__, itemType.name);
}
}

void ItemParse::parseUnscriptedItems(const std::string_view &tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType) {
if (tmpStrValue == "script") {
std::string scriptName = valueAttribute.as_string();
auto tokens = split(scriptName.data(), ';');
std::vector<std::shared_ptr<MoveEvent>> events;
for (const auto &token : tokens) {
if (token == "moveevent") {
createAndRegisterMoveEvent(MOVE_EVENT_EQUIP, itemType, attributeNode);
createAndRegisterMoveEvent(MOVE_EVENT_DEEQUIP, itemType, attributeNode);
} else if ((token == "weapon")) {
// TODO: add weapon logic
}
}
}
}
3 changes: 3 additions & 0 deletions src/items/functions/item/item_parse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ const phmap::flat_hash_map<std::string, ItemParseAttributes_t> ItemParseAttribut
{ "cleavepercent", ITEM_PARSE_CLEAVEPERCENT },
{ "reflectdamage", ITEM_PARSE_REFLECTDAMAGE },
{ "reflectpercentall", ITEM_PARSE_REFLECTPERCENTALL },
{ "script", ITEM_PARSE_SCRIPT },
};

const phmap::flat_hash_map<std::string, ItemTypes_t> ItemTypesMap = {
Expand Down Expand Up @@ -308,10 +309,12 @@ class ItemParse : public Items {
static void parseCleavePercent(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType);
static void parseReflectDamage(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType);
static void parseTransformOnUse(const std::string_view &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType);
static void parseUnscriptedItems(const std::string_view &tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType);

private:
// Parent of the function: static void parseField
static std::tuple<ConditionId_t, ConditionType_t> parseFieldConditions(std::string lowerStringValue, pugi::xml_attribute valueAttribute);
static CombatType_t parseFieldCombatType(std::string string, pugi::xml_attribute valueAttribute);
static void parseFieldCombatDamage(ConditionDamage* conditionDamage, std::string stringValue, pugi::xml_node attributeNode);
static void createAndRegisterMoveEvent(MoveEvent_t eventType, const ItemType &itemType, pugi::xml_node attributeNode);
};
1 change: 1 addition & 0 deletions src/items/items_definitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ enum ItemParseAttributes_t {
ITEM_PARSE_CLEAVEPERCENT,
ITEM_PARSE_REFLECTPERCENTALL,
ITEM_PARSE_REFLECTDAMAGE,
ITEM_PARSE_SCRIPT,
};

struct ImbuementInfo {
Expand Down
9 changes: 8 additions & 1 deletion src/lua/creature/movement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class MoveEvent final : public Script, public SharedObject {
return vocEquipMap;
}
void addVocEquipMap(std::string vocName) {
int32_t vocationId = g_vocations().getVocationId(vocName);
uint16_t vocationId = g_vocations().getVocationId(vocName);
if (vocationId != -1) {
vocEquipMap[vocationId] = true;
}
Expand Down Expand Up @@ -251,6 +251,10 @@ class MoveEvent final : public Script, public SharedObject {
static uint32_t EquipItem(const std::shared_ptr<MoveEvent> &moveEvent, Player* player, Item* item, Slots_t slot, bool boolean);
static uint32_t DeEquipItem(const std::shared_ptr<MoveEvent> &moveEvent, Player* player, Item* item, Slots_t slot, bool boolean);

void setFromLua(bool newFromLua) {
m_fromLua = newFromLua;
}

private:
std::string getScriptTypeName() const override;

Expand Down Expand Up @@ -290,10 +294,13 @@ class MoveEvent final : public Script, public SharedObject {
std::map<uint16_t, bool> vocEquipMap;
bool tileItem = false;

bool m_fromLua = true;

std::vector<uint32_t> itemIdVector;
std::vector<uint32_t> actionIdVector;
std::vector<uint32_t> uniqueIdVector;
std::vector<Position> positionVector;

friend class MoveEventFunctions;
friend class ItemParse;
};
4 changes: 2 additions & 2 deletions src/utils/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1625,11 +1625,11 @@ std::string formatPrice(std::string price, bool space /* = false*/) {
return price;
}

std::vector<std::string> split(const std::string &str) {
std::vector<std::string> split(const std::string &str, char delimiter /* = ','*/) {
std::vector<std::string> tokens;
std::string token;
std::istringstream tokenStream(str);
while (std::getline(tokenStream, token, ',')) {
while (std::getline(tokenStream, token, delimiter)) {
auto trimedToken = token;
trimString(trimedToken);
tokens.push_back(trimedToken);
Expand Down
2 changes: 1 addition & 1 deletion src/utils/tools.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ SpellGroup_t stringToSpellGroup(const std::string &value);
uint8_t forgeBonus(int32_t number);

std::string formatPrice(std::string price, bool space /* = false*/);
std::vector<std::string> split(const std::string &str);
std::vector<std::string> split(const std::string &str, char delimiter = ',');
std::string getFormattedTimeRemaining(uint32_t time);

static inline unsigned int getNumberOfCores() {
Expand Down

0 comments on commit dce63dc

Please sign in to comment.