Fixes error reporting with SQL and ryml (#6778)

* Fixes #6768.
* Send 0 as the parse line in SQL mode for item scripts as the ryml parser isn't fully populated in SQL mode.
* Also cleans up some documentation references for EquipScript and UnEquipScript.
Thanks to @dralucon87 and @Lemongrass3110!
This commit is contained in:
Aleos 2022-04-02 12:44:30 -04:00 committed by GitHub
parent 185344a252
commit 163f8c2c35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 32 additions and 22 deletions

View File

@ -3,7 +3,7 @@
//===== By: ==================================================
//= rAthena Dev Team
//===== Last Updated: ========================================
//= 20200602
//= 20220402
//===== Description: =========================================
//= Explanation of the item_db.yml file and structure.
//============================================================
@ -280,10 +280,10 @@ Script: Script to execute when the item is used/equipped.
---------------------------------------
OnEquip_Script: Script to execute when the item is equipped.
Warning, not all item bonuses will work here as expected.
EquipScript: Script to execute when the item is equipped.
Warning, not all item bonuses will work here as expected.
---------------------------------------
OnUnequip_Script: Script to execute when the item is unequipped or when a rental item expires.
Warning, not all item bonuses will work here as expected.
UnEquipScript: Script to execute when the item is unequipped or when a rental item expires.
Warning, not all item bonuses will work here as expected.

View File

@ -398,15 +398,15 @@ implemented.
Item and pet scripts
--------------------
Each item in the item database has three special fields - Script , OnEquip_Script
and OnUnequip_Script. The first is script code run every time a character equips the item,
Each item in the item database has three special fields - Script , EquipScript
and UnEquipScript. The first is script code run every time a character equips the item,
with the RID of the equipping character. Every time they unequip an item, all
temporary bonuses given by the script commands are cleared, and all the scripts
are executed once again to rebuild them. This also happens in several other
situations (like upon login) but the full list is currently unknown.
OnEquip_Script is a piece of script code run whenever the item is used by a character
by double-clicking on it. OnUnequip_Script runs whenever the
EquipScript is a piece of script code run whenever the item is used by a character
by double-clicking on it. UnEquipScript runs whenever the
equipment is unequip by a character
Not all script commands work properly in the item scripts. Where commands and
@ -4904,7 +4904,7 @@ in <time> seconds and be automatically deleted. When receiving a rental item,
the character will receive a message in their chat window. The character will
also receive warning messages in their chat window before the item disappears.
When rentals expire it will call the OnUnequip Script of the item. This can be used
When rentals expire it will call the UnEquipScript of the item. This can be used
for special cases such as removing a status change or resetting a variable or state
of the player.
@ -8876,8 +8876,8 @@ You can remove an item's itemscript by leaving the itemscript argument empty.
Returns 1 on success, or 0 on fail (item_id not found or new item script is invalid).
Type can optionally be used indicates which script to set (default is 0):
0 - Script
1 - OnEquip_Script
2 - OnUnequip_Script
1 - EquipScript
2 - UnEquipScript
Example:
setitemscript 2637,"{ if (isequipped(2236) == 0)end; if (getskilllv(26)){skill 40,1;}else{skill 26,1+isequipped(2636);} }";

View File

@ -307,6 +307,14 @@ bool YamlDatabase::asUInt32Rate( const ryml::NodeRef node, const std::string& na
}
}
int32 YamlDatabase::getLineNumber(const ryml::NodeRef node) {
return parser.source().has_str() ? (int32)parser.location(node).line : 0;
}
int32 YamlDatabase::getColumnNumber(const ryml::NodeRef node) {
return parser.source().has_str() ? (int32)parser.location(node).col : 0;
}
void YamlDatabase::invalidWarning( const ryml::NodeRef node, const char* fmt, ... ){
va_list ap;
@ -319,7 +327,7 @@ void YamlDatabase::invalidWarning( const ryml::NodeRef node, const char* fmt, ..
va_end(ap);
ShowError( "Occurred in file '" CL_WHITE "%s" CL_RESET "' on line %zu and column %zu.\n", this->currentFile.c_str(), parser.location(node).line, parser.location(node).col);
ShowError( "Occurred in file '" CL_WHITE "%s" CL_RESET "' on line %d and column %d.\n", this->currentFile.c_str(), this->getLineNumber(node), this->getColumnNumber(node));
#ifdef DEBUG
std::cout << node;

View File

@ -37,6 +37,8 @@ protected:
// Helper functions
bool nodeExists( const ryml::NodeRef node, const std::string& name );
bool nodesExist( const ryml::NodeRef node, std::initializer_list<const std::string> names );
int32 getLineNumber(const ryml::NodeRef node);
int32 getColumnNumber(const ryml::NodeRef node);
void invalidWarning( const ryml::NodeRef node, const char* fmt, ... );
std::string getCurrentFile();

View File

@ -199,7 +199,7 @@ uint64 AchievementDatabase::parseBodyNode(const ryml::NodeRef node){
achievement->condition = nullptr;
}
achievement->condition = parse_script( condition.c_str(), this->getCurrentFile().c_str(), parser.location(node["Condition"]).line, SCRIPT_IGNORE_EXTERNAL_BRACKETS );
achievement->condition = parse_script( condition.c_str(), this->getCurrentFile().c_str(), this->getLineNumber(node["Condition"]), SCRIPT_IGNORE_EXTERNAL_BRACKETS );
}else{
if (!exists)
achievement->condition = nullptr;
@ -303,7 +303,7 @@ uint64 AchievementDatabase::parseBodyNode(const ryml::NodeRef node){
achievement->rewards.script = nullptr;
}
achievement->rewards.script = parse_script( script.c_str(), this->getCurrentFile().c_str(), parser.location(rewardNode["Script"]).line, SCRIPT_IGNORE_EXTERNAL_BRACKETS );
achievement->rewards.script = parse_script( script.c_str(), this->getCurrentFile().c_str(), this->getLineNumber(rewardNode["Script"]), SCRIPT_IGNORE_EXTERNAL_BRACKETS );
}else{
if (!exists)
achievement->rewards.script = nullptr;

View File

@ -1046,7 +1046,7 @@ uint64 ItemDatabase::parseBodyNode(const ryml::NodeRef node) {
item->script = nullptr;
}
item->script = parse_script(script.c_str(), this->getCurrentFile().c_str(), parser.location(node["Script"]).line, SCRIPT_IGNORE_EXTERNAL_BRACKETS);
item->script = parse_script(script.c_str(), this->getCurrentFile().c_str(), this->getLineNumber(node["Script"]), SCRIPT_IGNORE_EXTERNAL_BRACKETS);
} else {
if (!exists)
item->script = nullptr;
@ -1063,7 +1063,7 @@ uint64 ItemDatabase::parseBodyNode(const ryml::NodeRef node) {
item->equip_script = nullptr;
}
item->equip_script = parse_script(script.c_str(), this->getCurrentFile().c_str(), parser.location(node["EquipScript"]).line, SCRIPT_IGNORE_EXTERNAL_BRACKETS);
item->equip_script = parse_script(script.c_str(), this->getCurrentFile().c_str(), this->getLineNumber(node["EquipScript"]), SCRIPT_IGNORE_EXTERNAL_BRACKETS);
} else {
if (!exists)
item->equip_script = nullptr;
@ -1080,7 +1080,7 @@ uint64 ItemDatabase::parseBodyNode(const ryml::NodeRef node) {
item->unequip_script = nullptr;
}
item->unequip_script = parse_script(script.c_str(), this->getCurrentFile().c_str(), parser.location(node["UnEquipScript"]).line, SCRIPT_IGNORE_EXTERNAL_BRACKETS);
item->unequip_script = parse_script(script.c_str(), this->getCurrentFile().c_str(), this->getLineNumber(node["UnEquipScript"]), SCRIPT_IGNORE_EXTERNAL_BRACKETS);
} else {
if (!exists)
item->unequip_script = nullptr;
@ -2503,7 +2503,7 @@ uint64 ComboDatabase::parseBodyNode(const ryml::NodeRef node) {
script_free_code(combo->script);
combo->script = nullptr;
}
combo->script = parse_script(script.c_str(), this->getCurrentFile().c_str(), parser.location(node["Script"]).line, SCRIPT_IGNORE_EXTERNAL_BRACKETS);
combo->script = parse_script(script.c_str(), this->getCurrentFile().c_str(), this->getLineNumber(node["Script"]), SCRIPT_IGNORE_EXTERNAL_BRACKETS);
} else {
if (!exists) {
combo->script = nullptr;
@ -3056,7 +3056,7 @@ uint64 RandomOptionDatabase::parseBodyNode(const ryml::NodeRef node) {
randopt->script = nullptr;
}
randopt->script = parse_script(script.c_str(), this->getCurrentFile().c_str(), parser.location(node["Script"]).line, SCRIPT_IGNORE_EXTERNAL_BRACKETS);
randopt->script = parse_script(script.c_str(), this->getCurrentFile().c_str(), this->getLineNumber(node["Script"]), SCRIPT_IGNORE_EXTERNAL_BRACKETS);
}
if (!exists)

View File

@ -376,7 +376,7 @@ uint64 PetDatabase::parseBodyNode( const ryml::NodeRef node ){
pet->pet_bonus_script = nullptr;
}
pet->pet_bonus_script = parse_script( script.c_str(), this->getCurrentFile().c_str(), parser.location(node["Script"]).line, SCRIPT_IGNORE_EXTERNAL_BRACKETS );
pet->pet_bonus_script = parse_script( script.c_str(), this->getCurrentFile().c_str(), this->getLineNumber(node["Script"]), SCRIPT_IGNORE_EXTERNAL_BRACKETS );
}else{
if( !exists ){
pet->pet_bonus_script = nullptr;
@ -395,7 +395,7 @@ uint64 PetDatabase::parseBodyNode( const ryml::NodeRef node ){
pet->pet_support_script = nullptr;
}
pet->pet_support_script = parse_script( script.c_str(), this->getCurrentFile().c_str(), parser.location(node["SupportScript"]).line, SCRIPT_IGNORE_EXTERNAL_BRACKETS );
pet->pet_support_script = parse_script( script.c_str(), this->getCurrentFile().c_str(), this->getLineNumber(node["SupportScript"]), SCRIPT_IGNORE_EXTERNAL_BRACKETS );
}else{
if( !exists ){
pet->pet_support_script = nullptr;