-
Notifications
You must be signed in to change notification settings - Fork 754
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementation of Item Options System. #1598
Conversation
34da8c1
to
8592825
Compare
db/item_options.conf
Outdated
//= This file is part of Hercules. | ||
//= http://herc.ws - http://github.com/HerculesWS/Hercules | ||
//= | ||
//= Copyright (C) 2014-2016 Hercules Dev Team |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2017
npc/custom/item_options.txt
Outdated
mes(.@name$); | ||
mes("See you around!"); | ||
close; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Newline missing
src/map/clif.c
Outdated
j++; | ||
} | ||
} | ||
for (; j < MAX_ITEM_OPTIONS || j < 5; j++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MAX_ITEM_OPTIONS is there, why < 5 check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is in the case that MAX_ITEM_OPTIONS is < 5. The remaining buffer is appended with 0
. If MAX_ITEM_OPTIONS > 5, it is made to revert to 5 in mmo.h.
:) |
db/item_options.conf
Outdated
{ | ||
Id: 1 | ||
Name: "VAR_MAXHPAMOUNT" | ||
Script: <" bonus bMaxHP,getequippedoptioninfo(IT_OPT_VALUE); "> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space between comma
bonus bMaxHP, getequippedoptioninfo(IT_OPT_VALUE);
db/item_options.conf
Outdated
{ | ||
Id: 2 | ||
Name: "VAR_MAXSPAMOUNT" | ||
Script: <" bonus bMaxSP,getequippedoptioninfo(IT_OPT_VALUE); "> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above.
db/item_options.conf
Outdated
{ | ||
Id: 3 | ||
Name: "VAR_STRAMOUNT" | ||
Script: <" bonus bStr,getequippedoptioninfo(IT_OPT_VALUE); "> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same.
db/item_options.conf
Outdated
{ | ||
Id: 4 | ||
Name: "VAR_AGIAMOUNT" | ||
Script: <" bonus bAgi,getequippedoptioninfo(IT_OPT_VALUE); "> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same until the last Id.
src/common/mmo.h
Outdated
@@ -256,6 +256,12 @@ | |||
#define MAX_ELESKILLTREE 3 | |||
#endif | |||
|
|||
#define MAX_ITEM_OPTIONS 5 // Maximum item options [Smokexyz] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add #ifndef MAX_ITEM_OPTIONS before 259 line
and #endif after 263 line
This will allow override this settings from build script without changing code.
src/map/clif.c
Outdated
@@ -2386,14 +2386,26 @@ void clif_addcards2(unsigned short *cards, struct item* item) { | |||
* @param buf[in,out] The buffer to write to. The pointer must be valid and initialized. | |||
* @param item[in] The source item. | |||
*/ | |||
void clif_add_random_options(unsigned char* buf, struct item* item) | |||
void clif_add_random_options(struct RndOptions *buf, const struct item it) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use pointer here?
const struct item it -> const struct item *it
And why rename it from item to it?
src/map/clif.c
Outdated
p.option_data[i].index = 0; | ||
p.option_data[i].value = 0; | ||
p.option_data[i].param = 0; | ||
for (i = 0; i < MAX_ITEM_OPTIONS; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Block with adding options to pointer probably better move to separate function.
This will allow for plugins to change options what will be send to client
src/map/clif.c
Outdated
p->option_data[j].index = 0; | ||
p->option_data[j].value = 0; | ||
p->option_data[j].param = 0; | ||
for (i=0, j=0; i < MAX_ITEM_OPTIONS; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be moved to same function like previous options block from clif_additem
src/map/itemdb.c
Outdated
@@ -1299,6 +1309,69 @@ void itemdb_read_packages(void) { | |||
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, config_filename); | |||
} | |||
|
|||
void itemdb_read_options(void) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here { should be on new line
src/map/script.c
Outdated
int i = -1, index = script_getnum(st,2); | ||
struct map_session_data *sd = script->rid2sd(st); | ||
|
||
if (sd == NULL) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably here need add script_pushint(st, -1) or like this for prevent script from termination
src/map/script.c
Outdated
} else if (equip_index > 0 && equip_index <= ARRAYLENGTH(script->equip)) | ||
i = pc->checkequip(sd,script->equip[equip_index-1]); | ||
|
||
if (&sd->status.inventory[i] != NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This condition always true. May be you want check something else?
src/map/script.c
Outdated
return false; | ||
} else if (equip_index > 0 && equip_index <= ARRAYLENGTH(script->equip)) | ||
i = pc->checkequip(sd,script->equip[equip_index-1]); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here "i" can have -1, and in next lines it will be buffer underflow
like sd->status.inventory[-1]. This is error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, checked for in next line as if ( i >= 0 && ...)
Nice 👍 |
src/map/clif.c, line 2389 at r1 (raw file): Previously, 4144 (Andrei Karas) wrote…
Why should there be a pointer here when the function isn't writing any data to the pointer? Comments from Reviewable |
@Smokexyz because passing structs by value is bad idea. Example: const struct item *const it First const here mean data in struct item is constant. |
Review status: 0 of 29 files reviewed at latest revision, 15 unresolved discussions. db/item_options.conf, line 12 at r1 (raw file): Previously, dastgir (Dastgir) wrote…
Done. db/item_options.conf, line 50 at r1 (raw file): Previously, Jedzkie (Jedzkie) wrote…
Done. db/item_options.conf, line 55 at r1 (raw file): Previously, Jedzkie (Jedzkie) wrote…
Done. db/item_options.conf, line 60 at r1 (raw file): Previously, Jedzkie (Jedzkie) wrote…
Done. db/item_options.conf, line 65 at r1 (raw file): Previously, Jedzkie (Jedzkie) wrote…
Done. npc/custom/item_options.txt, line 234 at r1 (raw file): Previously, dastgir (Dastgir) wrote…
Done. src/common/mmo.h, line 259 at r1 (raw file): Previously, 4144 (Andrei Karas) wrote…
Done. src/map/clif.c, line 2389 at r1 (raw file): Previously, Smokexyz (smokexyz) wrote…
Done. src/map/clif.c, line 2460 at r1 (raw file): Previously, 4144 (Andrei Karas) wrote…
Done. src/map/clif.c, line 2468 at r1 (raw file): Previously, Smokexyz (smokexyz) wrote…
Done. src/map/clif.c, line 2596 at r1 (raw file): Previously, 4144 (Andrei Karas) wrote…
Done. src/map/itemdb.c, line 1312 at r1 (raw file): Previously, 4144 (Andrei Karas) wrote…
Done. src/map/script.c, line 9034 at r1 (raw file): Previously, 4144 (Andrei Karas) wrote…
Done. src/map/script.c, line 13704 at r1 (raw file): Previously, 4144 (Andrei Karas) wrote…
Done. src/map/script.c, line 13705 at r1 (raw file): Previously, 4144 (Andrei Karas) wrote…
Done. Comments from Reviewable |
Reviewed 29 of 29 files at r1. Comments from Reviewable |
db/item_options.conf
Outdated
//= This file is part of Hercules. | ||
//= http://herc.ws - http://github.com/HerculesWS/Hercules | ||
//= | ||
//= Copyright (C) 2014-2017 Hercules Dev Team |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copyright (C) 2017 Hercules Dev Team
db/item_options.conf
Outdated
//========================================================================= | ||
//= Items Options Database | ||
//============================= Credits =================================== | ||
// Smokexyz |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this up
npc/custom/item_options.txt
Outdated
//================= Current Version ======================================= | ||
//= 1.0 | ||
//==================== Credits ============================================ | ||
//= Smokexyz |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
credit already added up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
woops, thanks.
npc/custom/item_options.txt
Outdated
.enable_random_bonus = false; | ||
|
||
/* Item Option Descriptions */ | ||
setarray .options$[0],"Max HP", "Max SP", "STR", "AGI", "VIT", "INT", "DEX", "LUK"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missed a space .options$[0], "Max HP",
npc/custom/item_options.txt
Outdated
close; | ||
} | ||
// Build the Menu. | ||
setarray .@position$[1],"Head","Body","Left Hand","Right Hand","Robe","Shoes","Accessory 1","Accessory 2","Head 2","Head 3"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spaces here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
personally, its not really a good practice to initialize the array at index 1 ... the index 0 is wasted ...
perhaps you should consider to adjust it to index 0 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copied from the hd refiner file. Although, this is done by taking into consideration the index that is passed to the following getequipisequiped()
, getequipisenableopt()
, getequipisidentify()
checks. It is, in source, checked for if (num > 0 && num <= ARRAYLENGTH(script->equip))
. It would fail if the index is 0. And if we began the array at [0] we'd have to add a +1 to all the following places we require the check. @MishimaHaruna @4144 Shouldn't this be changed in source? maybe in a separate commit changing all scripts using such commands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nope, i mean this ...
setarray .@position$[1]....
it should be
setarray .@position$[0]....
same goes for the other script... hd refiner..in case this is copied from there.
should avoid initialize the array and left the value remain unused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the index that is passed to the following getequipisequiped(), getequipisenableopt(), getequipisidentify() checks. It is, in source, checked for if (num > 0 && num <= ARRAYLENGTH(script->equip)). It would fail if the index is 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Build the Menu.
setarray .@position$,"Head","Body","Left Hand","Right Hand","Robe","Shoes","Accessory 1","Accessory 2","Head 2","Head 3";
for (.@i = 0; .@i <= 10; .@i++) {
.@menu$ += (getequipisequiped(.@i + 1) ? getequipname(.@i + 1) : .@position$[.@i] + "-[Not equipped]") + ":";
}
.@equip_index = select(.@menu$);
or better
// Build the Menu.
setarray .@eqi_list,EQI_HEAD_TOP,EQI_ARMOR,EQI_HAND_L,EQI_HAND_R,EQI_GARMENT,EQI_SHOES,EQI_ACC_L,EQI_ACC_R,EQI_HEAD_MID,EQI_HEAD_LOW;
setarray .@position$,"Head","Body","Left Hand","Right Hand","Robe","Shoes","Accessory 1","Accessory 2","Head 2","Head 3";
for (.@i = 0; .@i <= 10; .@i++) {
.@menu$ += (getequipisequiped(.@eqi_list[.@i]) ? getequipname(.@eqi_list[.@i]) : .@position$[.@i] + "-[Not equipped]") + ":";
}
.@equip_index = .@eqi_list[select(.@menu$) - 1];
I believe these approach are better than having the array creating unused index 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your first case would work, but as I said you'd have to increment most .@i values in the loop by 1, which could be rather troublesome. Your second case, although more visually appealing, involves creating a whole new array[10] to make up for one unused index.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because it's more logical. It's more elegant, it makes more sense ... to have array start with index 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, but this scenario involves passing an incremented value to functions that I believe don't handle indexes properly. And so I'm requesting the input of @MishimaHaruna and/or @4144
npc/custom/item_options.txt
Outdated
// Build the Menu. | ||
setarray .@position$[1],"Head","Body","Left Hand","Right Hand","Robe","Shoes","Accessory 1","Accessory 2","Head 2","Head 3"; | ||
.@menu$ = ""; | ||
for (.@i = 1; .@i<=10; ++.@i) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.@i <= 10
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps the value .@i <= 10
could change to .@i <= getarraysize(.@array)
? since it actually depend on the array values.
and same with above, the .@i
should start from 0 since its actually refer to an index of an array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They array here is not dynamic in size, therefore there is no need to call on a size check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EQI_HEAD_TOP (1) - Upper head gear
EQI_ARMOR (2) - Armor (Where you keep your Jackets and Robes)
EQI_HAND_L (3) - What is in your Left hand.
EQI_HAND_R (4) - What is in your Right hand.
EQI_GARMENT (5) - The garment slot (Mufflers, Hoods, Manteaus)
EQI_SHOES (6) - What foot gear the player has on.
EQI_ACC_L (7) - Accessory 1.
EQI_ACC_R (8) - Accessory 2.
EQI_HEAD_MID (9) - Middle Headgear (masks and glasses)
EQI_HEAD_LOW (10) - Lower Headgear (beards, some masks)
btw, if you're referring to this list... to use the number 1 ~ 10 ... it's better to replace with the EQI_
constant.
it could help avoid potential script broken if these EQI values changed in future..... just how what happened in rA when they decided to update the values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm don't think we're on the same page, you can hit me up on the IRC to clarify.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am just suggesting the usage of dynamic size because users are normally confused with this kind of settings if they are not familiar ..
Example:
User: I added a new item to the array
.@position$
but it doesn't show up in the menu, why ?
tho its not really something that really need to focus on ...
npc/custom/item_options.txt
Outdated
setarray .@position$[1],"Head","Body","Left Hand","Right Hand","Robe","Shoes","Accessory 1","Accessory 2","Head 2","Head 3"; | ||
.@menu$ = ""; | ||
for (.@i = 1; .@i<=10; ++.@i) | ||
.@menu$ += ((getequipisequiped(.@i))?getequipname(.@i):.@position$[.@i]+"-[Not equipped]")+":"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spaces
npc/custom/item_options.txt
Outdated
.@option_variable = select(.@menu$); | ||
next; | ||
mes(.@name$); | ||
mes("You chose ^009900"+.options$[.@option_variable-1]+"^000000!"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use mesf ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Life-saving function, thanks.
src/char/char.c
Outdated
@@ -770,8 +773,12 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl | |||
SQL->StmtBindColumn(stmt, 9, SQLDT_UINT64, &item.unique_id, 0, NULL, NULL); | |||
for (j = 0; j < MAX_SLOTS; ++j) | |||
SQL->StmtBindColumn(stmt, 10+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL); | |||
for (j = 0; j < MAX_ITEM_OPTIONS; ++j) { | |||
SQL->StmtBindColumn(stmt, 10+MAX_SLOTS+j*2, SQLDT_INT16, &item.option[j].index, 0, NULL, NULL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
10 + MAX_SLOTS + j * 2
npc/custom/item_options.txt
Outdated
@@ -0,0 +1,234 @@ | |||
//================= Hercules Script ======================================= |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually not sure about the whole custom script. We talked before to drop support for custom folder entirely. Maybe better to remove it here and offer it in forums?
you also forgot parantheses supposed to be included in all commands, this means also in next(); or close();
exceptions here are break and end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are not this script suppose to be added into the doc/sample/
folder?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MishimaHaruna regarding the location and need for this file as we had discussed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point about the sample folder, I always forget it exists.
My opinion is:
- If the script is meant to be an example for users that want to implement their own custom script, it should go into doc/sample.
- If the script is meant to be usable as is, it's fine to keep it in npc/custom - keeping in mind that it'll eventually be split to another repository and won't be maintained officially.
Databaseby the way, I think previously Herc was also planning to do this Item Bonus system by storing these item_bonus_id / item_bonus_value in a separate SQL tables, the idea was dropped? Script Commanddo we support script command that allow direct creation of item with item bonus? same goes for these if possible ?
about the script command to get the current info of item bonus from selected equipment slot ...
I am not familiar with the item bonus option, but this script command just my opinion... and by the way is this based on rA implementation? o-o |
npc/custom/item_options.txt
Outdated
//= Smokexyz | ||
//========================================================================= | ||
prontera,153,180,4 script Option Master 4_DOG01,{ | ||
callsub(StartTalking); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is unnecessary, remove this line and move the whole StartTalking
label part up here .... ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was done to add the OnInit configuration at the beginning of the file. I couldn't think of a better way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OnInit
label can be located at any place in the script ... personally, I often place the OnInit
label at the end of the script ...
npc/custom/item_options.txt
Outdated
@@ -0,0 +1,234 @@ | |||
//================= Hercules Script ======================================= |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are not this script suppose to be added into the doc/sample/
folder?
npc/custom/item_options.txt
Outdated
close; | ||
} | ||
// Build the Menu. | ||
setarray .@position$[1],"Head","Body","Left Hand","Right Hand","Robe","Shoes","Accessory 1","Accessory 2","Head 2","Head 3"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
personally, its not really a good practice to initialize the array at index 1 ... the index 0 is wasted ...
perhaps you should consider to adjust it to index 0 ?
npc/custom/item_options.txt
Outdated
// Build the Menu. | ||
setarray .@position$[1],"Head","Body","Left Hand","Right Hand","Robe","Shoes","Accessory 1","Accessory 2","Head 2","Head 3"; | ||
.@menu$ = ""; | ||
for (.@i = 1; .@i<=10; ++.@i) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps the value .@i <= 10
could change to .@i <= getarraysize(.@array)
? since it actually depend on the array values.
and same with above, the .@i
should start from 0 since its actually refer to an index of an array.
npc/custom/item_options.txt
Outdated
mes(.@name$); | ||
mes("Please input the bonus amount of ^009900"+.options$[.@option_variable-1]+"^000000 you want to add!"); | ||
mes("(Min: "+.minimum_bonus_amount+", Max: "+.maximum_bonus_amount+")"); | ||
input .@value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider to use this since there are min
and max
value.
input(.@value, .minimum_bonus_amount, .maximum_bonus_amount);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I wasn't aware.
npc/custom/item_options.txt
Outdated
mes("(Min: "+.minimum_bonus_amount+", Max: "+.maximum_bonus_amount+")"); | ||
input .@value; | ||
next; | ||
} while (.@value < .minimum_bonus_amount || .@value == 0 || .@value > .maximum_bonus_amount); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra condition checking can be avoided if you applied the input(<variable>,<min>,<max);
Not a very good idea for this implementation.
not yet, no. But something like this is required for crimson weapons?
Can be done, it's a good suggestion.
only IT_OPT_INDEX and IT_OPT_VALUE. (0 or 1)
Well, since the code structure of the methods involved are almost the same between both emulators, there aren't many ways to implement such a system without it looking similar. Consider this a system like item cards, but with added fields. The item_options.conf and script commands allows potential to add custom bonus options (as long as the client side is edited.). The ID field allows specifying the index of the client side equivalent. The param field was dropped since we don't know it's use. There are many improvements in both code and design over rA's implementation. The packet structures were added by Dastgir last year. It is for many reasons not based on theirs. |
00210a7
to
b9e4a1d
Compare
2 script commands have been changed to -
db2sql update will be added before a merge. |
Logical issue, please review. |
@Atemo what? |
eaaa2f2
to
59a935a
Compare
src/map/itemdb.c
Outdated
|
||
/* Set Script */ | ||
t_opt.script = *str ? script->parse(str, filepath, t_opt.index, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add here call to function for read additional fields. For example like in mob.c mob->read_db_additional_fields.
This can be usefull for plugins too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
sql-files/main.sql
Outdated
`opt_idx3` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', | ||
`opt_val3` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', | ||
`opt_idx4` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', | ||
`opt_val4` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still missing the INSERT INTO sql_updates
lines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/common/mmo.h
Outdated
// Maximum item options [Smokexyz] | ||
#ifndef MAX_ITEM_OPTIONS | ||
#define MAX_ITEM_OPTIONS 5 | ||
STATIC_ASSERT(MAX_ITEM_OPTIONS <= 5, "This value is limited by the client and database layout and should only be increased if you know the consequences."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move this line to after the #endif
? (so that if it's defined elsewhere it still asserts)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/map/clif.c
Outdated
WBUFW(buf,i*5+0) = 0; // OptIndex | ||
WBUFW(buf,i*5+2) = 0; // Value | ||
WBUFB(buf,i*5+4) = 0; // Param1 | ||
unsigned int clif_add_random_options(struct ItemOptions *buf, struct item *it) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's a bug in the parser. The use of const pointers (just like const scalar variables) was never considered, since it doesn't affect the function's contract with the caller. It should be fixed in the parser, but it's not a very high priority task
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other things to consider that aren't part of the diff:
- storage.c:
compare_item()
claims to check for identical items but isn't considering the item options now. - npc.c:
npc_selllist_sub()
doesn't handle item options. - buyingstore.c:
buyingstore_trade()
doesn't handle item options (it currently blocks items that have cards in them, but doesn't handle item options) - I'm not sure how the searchstore system is supposed to handle item options. Did they add new searchstore packets that include these, or should we ignore it for now?
ADD COLUMN `opt_idx4` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `opt_val3`, | ||
ADD COLUMN `opt_val4` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `opt_idx4`; | ||
|
||
INSERT INTO `sql_updates` (`timestamp`, `ignored`) VALUES (1488744559 , 'No'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unterminated line at end of file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/char/char.c
Outdated
// They are the same item. | ||
ARR_FIND(0, MAX_SLOTS, j, items[i].card[j] != item.card[j]); | ||
if (j == MAX_SLOTS | ||
ARR_FIND(0, MAX_ITEM_OPTIONS, k, items[i].option[k].index != item.option[k].index); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this supposed to check that both index and value match?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thanks.
src/map/clif.h
Outdated
@@ -1351,7 +1351,7 @@ struct clif_interface { | |||
void (*pNPCMarketClosed) (int fd, struct map_session_data *sd); | |||
void (*pNPCMarketPurchase) (int fd, struct map_session_data *sd); | |||
/* */ | |||
void (*add_random_options) (unsigned char* buf, struct item* item); | |||
int (*add_random_options) (struct ItemOptions *buf, const struct item *it); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we're calling them Item Options rather than Random Options, I think this method should also be renamed accordingly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/map/itemdb.c
Outdated
} | ||
|
||
/* Set Constant */ | ||
script->set_constant(str, t_opt.index, false, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens when you reload the item DB? You might want to use script->set_constant2()
instead, that allows redefinition as long as the value doesn't change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to script->set_constant2()
. Thanks for the clarification.
src/map/itemdb.c
Outdated
const char *str = NULL; | ||
|
||
if (!libconfig->setting_lookup_int16(conf, "Id", &t_opt.index) || t_opt.index <= 0) { | ||
ShowError("itemdb_read_options: Invalid Option Id provided for entry %d in '%s', skipping...\n", t_opt.index, filepath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if it's a duplicated ID?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/map/script.c
Outdated
i = pc->checkequip(sd, script->equip[equip_index - 1]); | ||
} | ||
|
||
if (i >= 0 && sd->status.inventory[i].nameid) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And else? The documentation above says that I should expect -1 on failure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thank you.
src/map/status.c
Outdated
|
||
if (index >= 0 && sd->inventory_data[index]) { | ||
int j; | ||
struct item_option *ito = NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this to inside the for loop?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
src/map/status.c
Outdated
int j; | ||
struct item_option *ito = NULL; | ||
for (j = 0; j < MAX_ITEM_OPTIONS; j++) { | ||
short option_index = sd->status.inventory[index].option[j].index; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to use short here instead of int?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to a more appropriate uint16, the data-type for index in struct option
in struct item
(mmo.h)
src/map/status.c
Outdated
|
||
if ((ito = itemdb->option_exists(option_index)) == NULL || ito->script == NULL) | ||
continue; | ||
else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This else looks very redundant after the continue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true, removed.
src/map/status.c
Outdated
return 1; | ||
} | ||
} | ||
status->current_equip_option_index = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redundant. It's already cleared at the beginning of the loop. If you want to clean it up at the end, move this two lines below, after the end of the loop.
Also, does status->current_equip_index
not need to be cleared?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved two lines below along with the clearing statement for status->current_equip_item_index
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MishimaHaruna updated with changes.
PS. For now I have not touched the buying/searchstore
functions as the cards are set and passed on from the searchstore packet in clif_search_store_info_ack
and we'll have to wait until information on the options data in the packet is discovered.
int i = -1; | ||
struct map_session_data *sd = script->rid2sd(st); | ||
|
||
if (sd == NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/map/script.c
Outdated
i = pc->checkequip(sd, script->equip[equip_index - 1]); | ||
} | ||
|
||
if (i >= 0 && sd->status.inventory[i].nameid) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thank you.
src/map/status.c
Outdated
|
||
if (index >= 0 && sd->inventory_data[index]) { | ||
int j; | ||
struct item_option *ito = NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
src/map/status.c
Outdated
int j; | ||
struct item_option *ito = NULL; | ||
for (j = 0; j < MAX_ITEM_OPTIONS; j++) { | ||
short option_index = sd->status.inventory[index].option[j].index; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to a more appropriate uint16, the data-type for index in struct option
in struct item
(mmo.h)
src/map/status.c
Outdated
|
||
if ((ito = itemdb->option_exists(option_index)) == NULL || ito->script == NULL) | ||
continue; | ||
else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true, removed.
src/map/script.c
Outdated
int val = 0, type = script_getnum(st, 2); | ||
struct map_session_data *sd = NULL; | ||
|
||
if ((sd = script->rid2sd(st)) == NULL || status->current_equip_item_index == -1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thanks.
src/map/itemdb.c
Outdated
itemdb->destroy_item_data(&itemdb->dummy, 0); | ||
db_destroy(itemdb->names); | ||
} | ||
|
||
void do_init_itemdb(bool minimal) { | ||
memset(itemdb->array, 0, sizeof(itemdb->array)); | ||
itemdb->other = idb_alloc(DB_OPT_BASE); | ||
itemdb->options = idb_alloc(DB_OPT_RELEASE_BOTH); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thanks.
src/map/itemdb.c
Outdated
} | ||
|
||
/* Set Constant */ | ||
script->set_constant(str, t_opt.index, false, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to script->set_constant2()
. Thanks for the clarification.
src/map/itemdb.c
Outdated
} | ||
|
||
if (!libconfig->setting_lookup_string(conf, "Name", &str)) { | ||
ShowError("itemdb_read_options: Invalid Option variable name provided for Option Id %d in '%s', skipping...\n", t_opt.index, filepath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thanks.
src/char/char.c
Outdated
// They are the same item. | ||
ARR_FIND(0, MAX_SLOTS, j, items[i].card[j] != item.card[j]); | ||
if (j == MAX_SLOTS | ||
ARR_FIND(0, MAX_ITEM_OPTIONS, k, items[i].option[k].index != item.option[k].index); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thanks.
6711162
to
ffae6ac
Compare
src/map/script.c
Outdated
return false; | ||
} | ||
|
||
if (equip_index < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check happens twice (see line 13653). This one should be removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
src/map/script.c
Outdated
return false; | ||
} | ||
|
||
if (equip_index < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicated check here as well (line 13726)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
src/map/script.c
Outdated
return false; | ||
} | ||
|
||
if (sd->status.inventory[i].nameid) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please consider using an explicit != 0
when checking non-boolean numeric variables
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
src/map/script.c
Outdated
clif->refine(sd->fd, 0, i, sd->status.inventory[i].refine); // notify client of a refine. | ||
clif->delitem(sd, i, 1, DELITEM_MATERIALCHANGE); // notify client to simulate item deletion. | ||
/* Log the Item */ | ||
logs->pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i], sd->inventory_data[i]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logs should happen in pairs, there should be a matching entry with -1
before (see BUILDIN(successrefitem)
for reference)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
src/map/status.c
Outdated
if (index >= 0 && sd->inventory_data[index]) { | ||
int j = 0; | ||
for (j = 0; j < MAX_ITEM_OPTIONS; j++) { | ||
uint16 option_index = sd->status.inventory[index].option[j].index; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sd->status.inventory[index].option[j].index
is int16
, not uint16
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
src/map/storage.c
Outdated
for (i = 0; i < MAX_SLOTS && (a->card[i] == b->card[i]); i++); | ||
return (i == MAX_SLOTS); | ||
int i = 0, k = 0; | ||
ARR_FIND(0, MAX_SLOTS, i, a->card[i] == b->card[i]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean !=
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops. Yes, fixed.
Thank you, all clear from my side. Looks good to merge once rebased, if @4144 approves |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the value seem like different from others due to the naming of inventory
and cart_inventory
, perhaps centralize it in a way ?
src/map/script.c
Outdated
@@ -13706,7 +13919,7 @@ BUILDIN(petloot) | |||
BUILDIN(getinventorylist) | |||
{ | |||
struct map_session_data *sd = script->rid2sd(st); | |||
char card_var[NAME_LENGTH]; | |||
char card_var[26]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using a new define constant? or something like char card_var[NAME_LENGTH + 10];
?
src/map/script.c
Outdated
@@ -13739,7 +13960,7 @@ BUILDIN(getinventorylist) | |||
BUILDIN(getcartinventorylist) | |||
{ | |||
struct map_session_data *sd = script->rid2sd(st); | |||
char card_var[26]; | |||
char card_var[30]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using a new define constant? or something like char card_var[NAME_LENGTH + 10];
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not really NAME_LENGTH
-- it should rather be SCRIPT_VARNAME_LENGTH
, since it's a variable name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, it is now of SCRIPT_VAR_LENGTH
.
src/map/itemdb.c
Outdated
|
||
/* Store ptr in the database */ | ||
idb_put(itemdb->options, t_opt.index, s_opt); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here need call additional function for read custom plugin option flags. Same like in itemdb.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Woops, forgot the call the function 🤣
sql-files/main.sql
Outdated
@@ -79,6 +79,16 @@ CREATE TABLE IF NOT EXISTS `auction` ( | |||
`card1` SMALLINT(11) NOT NULL DEFAULT '0', | |||
`card2` SMALLINT(11) NOT NULL DEFAULT '0', | |||
`card3` SMALLINT(11) NOT NULL DEFAULT '0', | |||
`opt_idx0` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', | |||
`opt_val0` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess val shouldn't be unsigned?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, fixed. Thanks.
Allows the infusing of equipments with bonus item options. This feature is constrained to clients of packet versions greater than or equal to `20150226`. Item Options and their effects are defined server-side in `db/item_options.conf` and client side in `data/luafiles514/lua files/datainfo/addrandomoptionnametable.lub` The ID of the option must tally with the correct index of the description provided in the client side lua file to avoid bugs. IT_OPT_* keys and MAX_ITEM_OPTIONS macro are also exported from the source as constants. An additional flag `disable_options` has been added to sql, and as `DisableOptions: true/false (boolean, defaults to false !!for equipments only!!)` to item_db.conf files. Script commands documentation is also included. SQL file updates are included. Credits: [Smokexyz](https://github.com/Smokexyz) Style and Script Fixes by [Asheraf](https://github.com/Asheraf) Initial design Idea by [secretdataz](https://github.com/secretdataz)
ffae6ac
to
974222a
Compare
I think from my side clear too |
Ok, let's merge this then, thank you! |
Allows the infusing of equipments with up to 5 bonus item options.
Discussion Topic - http://herc.ws/board/topic/14021-random-item-option-system/
20150226
.db/item_options.conf
and client side indata/luafiles514/lua files/datainfo/addrandomoptionnametable.lub
npc/custom/item_options.txt
to make use of this feature and demonstrate examples of usage.IT_OPT_*
keys andMAX_ITEM_OPTIONS
macro are also exported from the source as constants.disable_options
has been added to sql, and asDisableOptions: true/false (boolean, defaults to false !!for equipments only!!)
to db/<pre-re/re>/item_db.conf files.Credits: smokexyz/Hercules
Code Style Formatting by Asheraf/Hercules
Initial design idea: secretdataz/rAthena
This change is