Added some official item packages!

- Added db/re/item_package.txt, imported file for item_group_db.txt
- Added doc/item_group.txt for more details about item group
- Added new IG_ids on db/const.txt, up to 300 additions
- Added 'getgroupitem' script command to get item from specified item group (see doc/script_commands.txt)
- Modified 'grouprandomitem', added an optional parameter: 'sub_group' (see doc/script_commands.txt)
- Modified 'getrandgroupitem', added an optional parameter: 'sub_group' (see doc/script_commands.txt)
- Updated db/re/item_db.txt
- Updated sql-files/item_db_re.sql, so for MySQL user, please udate your item db
NOTE:
- I ocmmented some lines because some items aren't exist yet on rAthena db (or maybe have different name?)
- For pre-re, maybe I can do it later, or will someone do it?
- If there's something I forget to tell you, it's habit

Signed-off-by: Cydh Ramdh <house.bad@gmail.com>
This commit is contained in:
Cydh Ramdh 2013-12-23 23:37:27 +07:00
parent 4cfaba055d
commit 51074a0637
18 changed files with 4531 additions and 707 deletions

View File

@ -714,7 +714,10 @@
714: Item Shop List: %s (%d)
715: Point Shop List: '%s'
716: Your '%s' now: %d
//717-899 free
//Item Group
717: [%s] has won [%s] from '%s'
//718-899 free
//------------------------------------
// More atcommands message

View File

@ -713,7 +713,10 @@
714: Item Shop: %s (%d)
715: Point Shop: '%s'
716: '%s' milikmu saat ini: %d
//717-899 kosong
//Item Group
717: [%s] mendapatkan [%s] dari '%s'
//718-899 kosong
//------------------------------------

View File

@ -720,6 +720,7 @@ ATF_MAGIC 0x20
ATF_MISC 0x40
ATF_SKILL 0x60
//Item Group ID
IG_BlueBox 1
IG_VioletBox 2
IG_CardAlbum 3
@ -790,6 +791,321 @@ IG_CardAlbum_Shield 67
IG_CardAlbum_Weapon 68
IG_CardAlbum_Garment 69
IG_Flamel_Card 70
IG_Special_Box 71
IG_Tresure_Box_WoE_ 72
IG_RWC_Parti_Box 73
IG_RWC_Final_Comp_Box 74
IG_Gift_Bundle 75
IG_Caracas_Ring_Box 76
IG_Crumpled_Paper 77
IG_Solo_Gift_Basket 78
IG_Couple_Event_Basket 79
IG_GM_Warp_Box 80
IG_Fortune_Cookie1 81
IG_Fortune_Cookie2 82
IG_Fortune_Cookie3 83
IG_New_Gift_Envelope 84
IG_Passion_FB_Hat_Box 85
IG_Cool_FB_Hat_Box 86
IG_Victory_FB_Hat_Box 87
IG_Glory_FB_Hat_Box 88
IG_Passion_Hat_Box2 89
IG_Cool_Hat_Box2 90
IG_Victory_Hat_Box2 91
IG_Aspersio_5_Scroll_Box 92
IG_Pet_Egg_Scroll_Box1 93
IG_Pet_Egg_Scroll_Box2 94
IG_Pet_Egg_Scroll1 95
IG_Pet_Egg_Scroll2 96
IG_Pet_Egg_Scroll_Box3 97
IG_Pet_Egg_Scroll_Box4 98
IG_Pet_Egg_Scroll_Box5 99
IG_Pet_Egg_Scroll3 100
IG_Pet_Egg_Scroll4 101
IG_Pet_Egg_Scroll5 102
IG_Infiltrator_Box 103
IG_Muramasa_Box 104
IG_Excalibur_Box 105
IG_Combat_Knife_Box 106
IG_Counter_Dagger_Box 107
IG_Kaiser_Knuckle_Box 108
IG_Pole_Axe_Box 109
IG_Mighty_Staff_Box 110
IG_Right_Epsilon_Box 111
IG_Balistar_Box 112
IG_Diary_Of_Great_Sage_Box 113
IG_Asura_Box 114
IG_Apple_Of_Archer_Box 115
IG_Bunny_Band_Box 116
IG_Sahkkat_Box 117
IG_Lord_Circlet_Box 118
IG_Elven_Ears_Box 119
IG_Steel_Flower_Box 120
IG_Critical_Ring_Box 121
IG_Earring_Box 122
IG_Ring_Box 123
IG_Necklace_Box 124
IG_Glove_Box 125
IG_Brooch_Box 126
IG_Rosary_Box 127
IG_Safety_Ring_Box 128
IG_Vesper_Core01_Box 129
IG_Vesper_Core02_Box 130
IG_Vesper_Core03_Box 131
IG_Vesper_Core04_Box 132
IG_Pet_Egg_Scroll_Box6 133
IG_Pet_Egg_Scroll_Box7 134
IG_Pet_Egg_Scroll_Box8 135
IG_Pet_Egg_Scroll_Box9 136
IG_Pet_Egg_Scroll_Box10 137
IG_Pet_Egg_Scroll_Box11 138
IG_Pet_Egg_Scroll6 139
IG_Pet_Egg_Scroll7 140
IG_Pet_Egg_Scroll8 141
IG_Pet_Egg_Scroll9 142
IG_Pet_Egg_Scroll10 143
IG_Pet_Egg_Scroll11 144
IG_CP_Helm_Scroll_Box 145
IG_CP_Shield_Scroll_Box 146
IG_CP_Armor_Scroll_Box 147
IG_CP_Weapon_Scroll_Box 148
IG_Repair_Scroll_Box 149
IG_Super_Pet_Egg1 150
IG_Super_Pet_Egg2 151
IG_Super_Pet_Egg3 152
IG_Super_Pet_Egg4 153
IG_Super_Card_Pet_Egg1 154
IG_Super_Card_Pet_Egg2 155
IG_Super_Card_Pet_Egg3 156
IG_Super_Card_Pet_Egg4 157
IG_Vigorgra_Package1 158
IG_Vigorgra_Package2 159
IG_Vigorgra_Package3 160
IG_Vigorgra_Package4 161
IG_Vigorgra_Package5 162
IG_Vigorgra_Package6 163
IG_Vigorgra_Package7 164
IG_Vigorgra_Package8 165
IG_Vigorgra_Package9 166
IG_Vigorgra_Package10 167
IG_Vigorgra_Package11 168
IG_Vigorgra_Package12 169
IG_Pet_Egg_Scroll12 170
IG_Pet_Egg_Scroll13 171
IG_Pet_Egg_Scroll14 172
IG_Super_Pet_Egg5 173
IG_Super_Pet_Egg6 174
IG_Super_Pet_Egg7 175
IG_Super_Pet_Egg8 176
IG_Pet_Egg_Scroll_E 177
IG_Ramen_Hat_Box 178
IG_Mysterious_Travel_Sack1 179
IG_Mysterious_Travel_Sack2 180
IG_Mysterious_Travel_Sack3 181
IG_Mysterious_Travel_Sack4 182
IG_Magician_Card_Box 183
IG_Acolyte_Card_Box 184
IG_Archer_Card_Box 185
IG_Swordman_Card_Box 186
IG_Thief_Card_Box 187
IG_Merchant_Card_Box 188
IG_Hard_Core_Set_Box 189
IG_Kitty_Set_Box 190
IG_Soft_Core_Set_Box 191
IG_Deviruchi_Set_Box 192
IG_MVP_Hunt_Box 193
IG_Brewing_Box 194
IG_Xmas_Pet_Scroll 195
IG_Lucky_Scroll08 196
IG_Br_SwordPackage 197
IG_Br_MagePackage 198
IG_Br_AcolPackage 199
IG_Br_ArcherPackage 200
IG_Br_MerPackage 201
IG_Br_ThiefPackage 202
IG_Acidbomb_10_Box 203
IG_Basic_Siege_Supply_Box 204
IG_Adv_Siege_Supply_Box 205
IG_Elite_Siege_Supply_Box 206
IG_Sakura_Scroll 207
IG_Beholder_Ring_Box 208
IG_Hallow_Ring_Box 209
IG_Clamorous_Ring_Box 210
IG_Chemical_Ring_Box 211
IG_Insecticide_Ring_Box 212
IG_Fisher_Ring_Box 213
IG_Decussate_Ring_Box 214
IG_Bloody_Ring_Box 215
IG_Satanic_Ring_Box 216
IG_Dragoon_Ring_Box 217
IG_Angel_Scroll 218
IG_Devil_Scroll 219
IG_Surprise_Scroll 220
IG_July7_Scroll 221
IG_Bacsojin_Scroll 222
IG_Animal_Scroll 223
IG_Heart_Scroll 224
IG_New_Year_Scroll 225
IG_Valentine_Pledge_Box 226
IG_Ox_Tail_Scroll 227
IG_Buddah_Scroll 228
IG_Evil_Incarnation 229
IG_F_Clover_Box_Mouth 230
IG_Mouth_Bubble_Gum_Box 231
IG_F_Clover_Box_Mouth2 232
IG_F_Clover_Box_Mouth4 233
IG_BGum_Box_In_Mouth2 234
IG_BGum_Box_In_Mouth4 235
IG_Tw_October_Scroll 236
IG_My_Scroll1 237
IG_Tw_Nov_Scroll 238
IG_My_Scroll2 239
IG_Pr_Reset_Stone_Box 240
IG_FPr_Reset_Stone_Box 241
IG_Majestic_Devil_Scroll 242
IG_Life_Ribbon_Box 243
IG_Life_Ribbon_Box2 244
IG_Life_Ribbon_Box3 245
IG_Magic_Candy_Box10 246
IG_RWC2010_SuitcaseA 247
IG_RWC2010_SuitcaseB 248
IG_Sagittarius_Scroll 249
IG_Sagittarius_Scr_Box 250
IG_Sagittar_Diadem_Scroll 251
IG_Sagittar_Di_Scroll_Box 252
IG_Capri_Crown_Scroll 253
IG_Capri_Crown_Scroll_Box 254
IG_Capricon_Di_Scroll 255
IG_Capricon_Di_Scroll_Box 256
IG_Aquarius_Diadem_Scroll 257
IG_Aquarius_Di_Scroll_Box 258
IG_Lovely_Aquarius_Scroll 259
IG_Lovely_Aquarius_Box 260
IG_Pisces_Diadem_Scroll 261
IG_Pisces_Diadem_Box 262
IG_Energetic_Pisces_Scroll 263
IG_Energetic_Pisces_Box 264
IG_Aries_Scroll 265
IG_Aries_Scroll_Box 266
IG_Boarding_Halter_Box 267
IG_Taurus_Diadem_Scroll 268
IG_Taurus_Di_Scroll_Box 269
IG_Umbala_Spirit_Box2 270
IG_F_Umbala_Spirit_Box2 271
IG_Taurus_Crown_Scroll 272
IG_Taurus_Crown_Scroll_Box 273
IG_Gemi_Diadem_Scroll 274
IG_Gemi_Diadem_Scroll_Box 275
IG_Super_Pet_Egg1_2 276
IG_Super_Pet_Egg4_2 277
IG_Fire_Brand_Box 278
IG_BR_Independence_Scroll 279
IG_All_In_One_Ring_Box 280
IG_Gemi_Crown_Scroll 281
IG_Gemi_Crown_Scroll_Box 282
IG_RWC_Special_Scroll 283
IG_RWC_Limited_Scroll 284
IG_Asgard_Scroll 285
IG_Ms_Cancer_Scroll 286
IG_RWC_Super_Scroll 287
IG_Leo_Scroll 288
IG_Ms_Virgo_Scroll 289
IG_Lucky_Egg_C6 290
IG_Libra_Scroll 291
IG_Hallo_Scroll 292
IG_Ms_Scorpio_Scroll 293
IG_TCG_Card_Scroll 294
IG_Boitata_Scroll 295
IG_Lucky_Egg_C2 296
//IG_Lucky_Egg_C6 297
IG_Lucky_Egg_C9 298
IG_Lucky_Egg_C7 299
IG_Lucky_Egg_C8 300
IG_Lucky_Egg_C10 301
IG_Wind_Type_Scroll 302
IG_Lucky_Egg_C3 303
IG_Lucky_Egg_C4 304
IG_Lucky_Egg_C5 305
IG_Weather_Report_Box 306
IG_Comin_Actor_Box 307
IG_Hen_Set_Box 308
IG_Lucky_Egg_C 309
IG_Water_Type_Scroll 310
IG_Earth_Type_Scroll 311
//IG_Earth_Type_Scroll 312
IG_Splash_Scroll 313
IG_Vocation_Scroll 314
IG_Wisdom_Scroll 315
IG_Patron_Scroll 316
IG_Heaven_Scroll 317
IG_Tw_Aug_Scroll 318
IG_Tw_Nov_Scroll2 319
IG_Illusion_Nothing 320
IG_Tw_Sep_Scroll 321
IG_Flame_Light 322
IG_Tw_Rainbow_Scroll 323
IG_Tw_Red_Scroll 324
IG_Tw_Orange_Scroll 325
IG_Tw_Yellow_Scroll 326
IG_Scroll_Of_Death 327
IG_Scroll_Of_Life 328
IG_Scroll_Of_Magic 329
IG_Scroll_Of_Thews 330
IG_Scroll_Of_Darkness 331
IG_Scroll_Of_Holiness 332
IG_Horned_Scroll 333
IG_Mercury_Scroll 334
IG_Challenge_Kit 335
IG_Tw_April_Scroll 336
//IG_Tw_October_Scroll 337
IG_Summer_Scroll3 338
IG_C_Wing_Of_Fly_3Day_Box 339
IG_RWC_2012_Set_Box 340
IG_Ex_Def_Potion_Box 341
IG_RWC_Scroll_2012 342
IG_Old_Coin_Pocket 343
IG_High_Coin_Pocket 344
IG_Mid_Coin_Pocket 345
IG_Low_Coin_Pocket 346
IG_Sgrade_Pocket 347
IG_Agrade_Pocket 348
IG_Bgrade_Pocket 349
IG_Cgrade_Pocket 350
IG_Dgrade_Pocket 351
IG_Egrade_Pocket 352
IG_Ptotection_Seagod_Box 353
IG_Hairtail_Box1 354
IG_Hairtail_Box2 355
IG_Spearfish_Box1 356
IG_Spearfish_Box2 357
IG_Saurel_Box1 358
IG_Saurel_Box2 359
IG_Tuna_Box1 360
IG_Tuna_Box2 361
IG_Malang_Crab_Box1 362
IG_Malang_Crab_Box2 363
IG_Brindle_Eel_Box1 364
IG_Brindle_Eel_Box2 365
IG_Ptotection_Seagod_Box2 366
IG_Ptotection_Seagod_Box3 367
IG_Octo_Hstick_Box 368
IG_Octo_Hstick_Box2 369
IG_Octo_Hstick_Box3 370
IG_Silvervine_Fruit_Box10 371
IG_Silvervine_Fruit_Box40 372
IG_Silvervine_Fruit_Box4 373
IG_Malang_Woe_Encard_Box 374
IG_Xmas_Bless 375
IG_Fire_Type_Scroll 376
IG_Blue_Scroll 377
IG_Good_Student_Gift_Box 378
IG_Bad_Student_Gift_Box 379
IG_Indigo_Scroll 380
IG_Violet_Scroll 381
IG_Bi_Hwang_Scroll 382
IG_Jung_Bi_Scroll 383
IG_Je_Un_Scroll 384
IG_Yong_Kwang_Scroll 385
SC_ALL -1
SC_STONE 0

View File

@ -1,5 +1,7 @@
//
// Structure of Database:
// GroupID,ItemID,Rate
//
//
// Cookie Bag
7,529,5 //Candy
7,530,5 //Candy Cane

File diff suppressed because it is too large Load Diff

View File

@ -4,3 +4,4 @@ import: db/re/item_cardalbum.txt
import: db/item_findingore.txt
import: db/re/item_giftbox.txt
import: db/re/item_misc.txt
import: db/re/item_package.txt

View File

@ -1,5 +1,7 @@
//
// Structure of Database:
// GroupID,ItemID,Rate
//
//
// Cookie Bag
7,529,5 //Candy
7,530,5 //Candy Cane

3100
db/re/item_package.txt Normal file

File diff suppressed because it is too large Load Diff

132
doc/item_group.txt Normal file
View File

@ -0,0 +1,132 @@
//===== rAthena Documentation ================================
//= Item Database
//===== By: ==================================================
//= rAthena Dev Team
//===== Last Updated: ========================================
//= 20131223
//===== Description: =========================================
//= Explanation of the item_group.txt file and structure.
//============================================================
Items at item group can be used for 'getrandgroupitem' or 'getgroupitem' script.
See this table below to know which field that influences those scripts.
+===============+====================+================+
| Field | 'getrandgroupitem' | 'getgroupitem' |
+===============+====================+================+
| GroupID | YES | YES |
+===============+====================+================+
| ItemID | YES | YES |
+===============+====================+================+
| Rate | YES | YES |
+===============+====================+================+
| Amount | no | YES |
+===============+====================+================+
| Random | no | YES |
+===============+====================+================+
| isAnnounced | no | YES |
+===============+====================+================+
| Duration | no | YES |
+===============+====================+================+
| isNamed | no | YES |
+===============+====================+================+
| isBound | no | YES |
+===============+====================+================+
---------------------------------------
GroupID: See const.txt on 'Item Group ID' section for id. Supports IG_* const.
---------------------------------------
ItemID: Available item_id that will be obtained from this item group.
Supports AegisName of the item.
---------------------------------------
Rate: Probability to get the item. Not a percentage value!
Example:
IG_MyItemGroup,Knife,5
IG_MyItemGroup,Dagger,1
- Knife has chance 5/6 (83.3%) to be obtained
- Dagger has chance 1/6 (16.7%) to be obtained
---------------------------------------
Amount: Amount of item that will be obtained.
---------------------------------------
Random: Set this to '0' and the item always be obtained ("must" item).
Random value will allocates where the item will be stored at random group.
(max. random group is 4 a itemdb.c MAX_ITEMGROUP_RANDGROUP)
Example:
IG_MyItemGroup,Knife,0,1,0 //as 'must' item
IG_MyItemGroup,Dagger,0,1,0 //as 'must' item
IG_MyItemGroup,Stiletto,5,1,1 //random at group 1
IG_MyItemGroup,Stiletto_,2,1,1 //random at group 1
IG_MyItemGroup,Stiletto,5,1,2 //random at group 2
IG_MyItemGroup,Dagger_,4,1,2 //random at group 2
-> usage: 'getgroupitem(IG_MyItemGroup);'
- Player always get 1x Knife and 1x Dagger
- Player has chance to get 1x Stiletto by chance 5/7 from group 1
- Player has chance to get 1x Stiletto_ by chance 2/7 from group 1
- Player has chance to get 1x Stiletto by chance 5/9 from group 2
- Player has chance to get 1x Dagger_ by chance 4/9 from group 2
-----------------------------------------
If the 'Rate' for random '0' is not 0 (more than 0), that means this item
also can be obtained as random item.
If you want the "must" item only can be obtained without random chance,
change the 'Rate' for this item to 0.
Example:
IG_MyItemGroup2,Knife,0,1,0
IG_MyItemGroup2,Dagger,5,1,0
IG_MyItemGroup2,Stiletto,2,1,1
-> usage: 'getgroupitem(IG_MyItemGroup2);'
- 1x Knife always be obtained
- 1x Dagger always be obtained and also has chance to get 1 more by
chance 5/7
- 1x Stiletto can be obtained by chance 2/7
So, player will get 1x Knife, 1x Dagger, and 1x Dagger or 1x Stiletto
-> usage: 'getrandgroupitem(IG_MyItemGroup2,1);' (Ignores 'Amount' field)
- 1x Knife never be obtained!
- 1x Dagger can be obtained by chance 5/7
- 1x Stiletto can be obtained by chance 2/7
So, player will get only 1x Dagger or 1x Stiletto
---------------------------------------
isAnnounced: If player obtained this item, it will be broadcasted!
"[Player] has won [Item] from 'Box'"
---------------------------------------
Duration: Makes the item as rental item, will be removed when it is expire in
certain minute. If wanted it as hour, just do x*60.
Better use this for non-stackable item only.
---------------------------------------
isNamed: Makes the item is marked by the obtainer's name.
---------------------------------------
isBound: Makes the obtained item as bound item.
See doc/script_commands.txt at 'getitembound' for valid bound types.
---------------------------------------
Supports to import other file, usage:
import: db/path/filename.txt
Example:
import: db/re/item_bluebox.txt

View File

@ -4422,7 +4422,7 @@ Example:
---------------------------------------
*groupranditem <group id>;
*groupranditem <group id>{,<sub_group>};
Returns the item_id of a random item picked from the group specified. The
different groups and their group number are specified in 'db/(pre-)re/item_group_db.txt'.
@ -4432,9 +4432,12 @@ example, for a random pet lure:
getitem groupranditem(15),1;
'sub_group' is used to get the available random items of item group from specified random
group. More info, just like the explanation below.
---------------------------------------
*getrandgroupitem <group id>,<quantity>;
*getrandgroupitem <group id>,<quantity>{,<sub_group>};
Similar to the above example, this command allows players to obtain the specified
quantity of a random item from the group "<group id>". The different groups and
@ -4443,6 +4446,47 @@ their group number are specified in db/(pre-)re/item_group_db.txt
For example, obtaining three of the same random item from Old Blue Box:
getrandgroupitem(1,3);
getrandgroupitem(IG_BlueBox,3); //see const.txt at 'Item Group ID' section
If quantity is 0, and if the item(s) at specified IG_ has defined amount, the amount of
the item that will be obtained, will according to the amount on that IG_ data.
By default, if getrandgroupitem is used to get random item from IG_ which has more than
defined random group, it always read random group 1, other item that as random item at
random group > 2 never been touched. Use 'sub_group' to choose which random group will be
obtained.
Example:
IG_ExGetGroupItem,Coat,2,2,1
IG_ExGetGroupItem,Muffler,2,3,1
IG_ExGetGroupItem,Yggdrasilberry,10,7,1
IG_ExGetGroupItem,Yggdrasilberry,10,7,2
IG_ExGetGroupItem,Seed_Of_Yggdrasil,5,15,2
1. 'getrandgroupitem(IG_ExGetGroupItem,1)'
Player has chance to get 1x Coat or 1x Muffler or 1x Yggdrasilberry. Player never
has chance to get Seed_of_Yggdrasil because it is in different random group.
2. 'getrandgroupitem(IG_ExGetGroupItem,0)'
Player has chance to get 2x Coat or 3x Muffler or 7x Yggdrasilberry. Player never
has chance to get Seed_of_Yggdrasil because it is in different random group.
3. 'getrandgroupitem(IG_ExGetGroupItem,0,2)'
Player has chance to get 10x Yggdrasilberry or 15x Seed_of_Yggdrasil. Player never
has chance to get Coat, Muffler, and Seed_of_Yggdrasil because it is in different
random group.
---------------------------------------
*getgroupitem <group_id>;
Gives item(s) to the attached player based on item group contents.
This is not working like 'getrandgroupitem' which only give 1 item for specified
item group.
Can use const data for 'group_id', see db/const.txt at 'Item Group ID' section
---------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -17176,6 +17176,9 @@ void clif_parse_GMFullStrip(int fd, struct map_session_data *sd) {
is_atcommand(fd, sd, cmd, 1);
}
///TODO: Special item that obtained, must be broadcasted by this packet
//void clif_broadcast_obtain_special_item() {}
#ifdef DUMP_UNKNOWN_PACKET
void DumpUnknow(int fd,TBL_PC *sd,int cmd,int packet_len){
const char* packet_txt = "save/packet.txt";

View File

@ -353,11 +353,11 @@ enum clif_messages {
};
enum e_personalinfo {
PINFO_BASIC = 0,
PINFO_PREMIUM,
PINFO_SERVER,
PINFO_CAFE,
PINFO_MAX,
PINFO_BASIC = 0,
PINFO_PREMIUM,
PINFO_SERVER,
PINFO_CAFE,
PINFO_MAX,
};
int clif_setip(const char* ip);
@ -837,4 +837,6 @@ void clif_channel_msg(struct Channel *channel, struct map_session_data *sd, char
void clif_ranklist(struct map_session_data *sd, int16 rankingType);
void clif_update_rankingpoint(struct map_session_data *sd, int rankingtype, int point);
//void clif_broadcast_obtain_special_item(); ///TODO!
#endif /* _CLIF_H_ */

View File

@ -21,7 +21,7 @@
static struct item_data* itemdb_array[MAX_ITEMDB];
static DBMap* itemdb_other;// int nameid -> struct item_data*
static struct item_group itemgroup_db[MAX_ITEMGROUP];
static struct s_item_group_db itemgroup_db[MAX_ITEMGROUP];
struct item_data dummy_item; //This is the default dummy item used for non-existant items. [Skotlex]
@ -141,23 +141,132 @@ int itemdb_searchname_array(struct item_data** data, int size, const char *str)
return count;
}
/*==========================================
* Return a random item id from group. (takes into account % chance giving/tot group)
*------------------------------------------*/
int itemdb_searchrandomid(int group)
/**
* Return a random item id from group. (takes into account % chance giving/tot group)
* @param group_id
* @param sub_group: Default is 1
* @return nameid
*/
int itemdb_searchrandomid(int group_id, uint8 sub_group)
{
if(group<1 || group>=MAX_ITEMGROUP) {
ShowError("itemdb_searchrandomid: Invalid group id %d\n", group);
if (sub_group == 0)
sub_group = 1;
if (group_id < 1 || group_id >= MAX_ITEMGROUP) {
ShowError("itemdb_searchrandomid: Invalid group id %d\n", group_id);
return UNKNOWN_ITEM_ID;
}
if (itemgroup_db[group].qty)
return itemgroup_db[group].nameid[rnd()%itemgroup_db[group].qty];
if (sub_group >= MAX_ITEMGROUP_RANDGROUP) {
ShowError("itemdb_searchrandomid: Invalid sub_group %d\n", sub_group);
return UNKNOWN_ITEM_ID;
}
if (itemgroup_db[group_id].random_qty[sub_group-1])
return itemgroup_db[group_id].random[sub_group-1][rnd()%itemgroup_db[group_id].random_qty[sub_group-1]].nameid;
ShowError("itemdb_searchrandomid: No item entries for group id %d\n", group);
ShowError("itemdb_searchrandomid: No item entries for group id %d and sub group %d\n", group_id, sub_group);
return UNKNOWN_ITEM_ID;
}
/** [Cydh]
* Return a number of item's amount that will be obtained for 'getrandgroupitem id,0;'
* @param group_id
* @param sub_group
* @param nameid: The target item
* @return amount
*/
uint16 itemdb_get_randgroupitem_count(uint16 group_id, uint8 sub_group, uint16 nameid) {
uint16 i, amt = 1;
if (group_id < 1 || group_id >= MAX_ITEMGROUP_RAND || sub_group > MAX_ITEMGROUP_RANDGROUP)
return amt;
if (!sub_group)
sub_group = 1;
ARR_FIND(0,itemgroup_db[group_id].random_qty[sub_group-1],i,itemgroup_db[group_id].random[sub_group-1][i].nameid == nameid);
if (i < MAX_ITEMGROUP_RAND)
amt = itemgroup_db[group_id].random[sub_group-1][i].amount;
return amt;
}
/** [Cydh]
* Gives item(s) to the player based on item group
* @param sd: Player that obtains item from item group
* @param group_id: The group ID of item that obtained by player
* @param nameid_from: The item that trigger this item group
* @param *group: struct s_item_group from itemgroup_db[group_id].random[idx] or itemgroup_db[group_id].must[sub_group][idx]
*/
void itemdb_pc_get_itemgroup_sub(struct map_session_data *sd, uint16 group_id, uint16 nameid_from, struct s_item_group *group) {
uint16 i;
struct item tmp;
nullpo_retv(group);
memset(&tmp,0,sizeof(tmp));
tmp.nameid = group->nameid;
tmp.amount = (itemdb_isstackable(group->nameid)) ? group->amount : 1;
tmp.bound = group->bound;
tmp.identify = 1;
tmp.expire_time = (group->duration) ? (unsigned int)(time(NULL) + group->duration*60) : 0;
if (group->isNamed) {
tmp.card[0] = itemdb_isequip(group->nameid) ? CARD0_FORGE : CARD0_CREATE;
tmp.card[1] = 0;
tmp.card[2] = GetWord(sd->status.char_id, 0);
tmp.card[3] = GetWord(sd->status.char_id, 1);
}
//Do loop for non-stackable item
for (i = 0; i < group->amount; i++) {
int flag;
if ((flag = pc_additem(sd,&tmp,tmp.amount,LOG_TYPE_SCRIPT)))
clif_additem(sd,0,0,flag);
else if (!flag && group->isAnnounced) { ///TODO: Move this broadcast to proper behavior (it should on at different packet)
char output[CHAT_SIZE_MAX];
sprintf(output,msg_txt(sd,717),sd->status.name,itemdb_jname(group->nameid),itemdb_jname(nameid_from));
clif_broadcast(&sd->bl,output,strlen(output),0,ALL_CLIENT);
//clif_broadcast_obtain_special_item();
}
if (itemdb_isstackable(group->nameid))
break;
}
}
/** [Cydh]
* Find item(s) that will be obtained by player based on Item Group
* @param group_id: The group ID that will be gained by player
* @param nameid: The item that trigger this item group
* @param sd: Player that obtains item from item group
* @return val: 0:success, 1:no sd, 2:invalid item group
*/
uint8 itemdb_pc_get_itemgroup(uint16 group_id, uint16 nameid, struct map_session_data *sd) {
uint16 i = 0;
nullpo_retr(1,sd);
if (!group_id || group_id >= MAX_ITEMGROUP) {
ShowError("getgroupitem: Invalid group id '%d' specified.",group_id);
return 2;
}
//Get the 'must' item(s)
for (i = 0; i < itemgroup_db[group_id].must_qty; i++) {
if (itemdb_exists(itemgroup_db[group_id].must[i].nameid))
itemdb_pc_get_itemgroup_sub(sd,group_id,nameid,&itemgroup_db[group_id].must[i]);
}
//Get the 'random' item each random group
for (i = 0; i < MAX_ITEMGROUP_RANDGROUP; i++) {
uint16 rand, j = 0;
if (!itemgroup_db[group_id].random_qty[i]) //Skip empty random group
continue;
rand = rnd()%itemgroup_db[group_id].random_qty[i];
//Woops, why is the data empty? Every check should be done when load the item group! So this is bad day for the player :P
if (!&itemgroup_db[group_id].random[i][rand] || !itemgroup_db[group_id].random[i][rand].nameid) {
continue;
}
if (itemdb_exists(itemgroup_db[group_id].random[i][rand].nameid))
itemdb_pc_get_itemgroup_sub(sd,group_id,nameid,&itemgroup_db[group_id].random[i][rand]);
}
return 0;
}
/*==========================================
* Calculates total item-group related bonuses for the given item
*------------------------------------------*/
@ -167,8 +276,8 @@ int itemdb_group_bonus(struct map_session_data* sd, int itemid)
for (i=0; i < MAX_ITEMGROUP; i++) {
if (!sd->itemgrouphealrate[i])
continue;
ARR_FIND( 0, itemgroup_db[i].qty, j, itemgroup_db[i].nameid[j] == itemid );
if( j < itemgroup_db[i].qty )
ARR_FIND( 0, itemgroup_db[i].random_qty[0], j, itemgroup_db[i].random[0][j].nameid == itemid );
if( j < itemgroup_db[i].random_qty[0] )
bonus += sd->itemgrouphealrate[i];
}
return bonus;
@ -529,63 +638,105 @@ static bool itemdb_read_itemavail(char* str[], int columns, int current)
/*==========================================
* read item group data
* GroupID,ItemID,Rate{,Amount,isMust,isAnnounced,Duration,isNamed,isBound}
*------------------------------------------*/
static void itemdb_read_itemgroup_sub(const char* filename)
{
FILE *fp;
char line[1024];
int ln=0, entries=0;
int groupid,j,k,nameid;
char *str[3],*p;
char w1[1024], w2[1024];
char line[1024];
if( (fp=fopen(filename,"r"))==NULL ){
if ((fp=fopen(filename,"r")) == NULL) {
ShowError("can't read %s\n", filename);
return;
}
while (fgets(line,sizeof(line),fp)) {
uint16 nameid;
int j, group_id, prob = 1, amt = 1, group = 1, announced = 0, dur = 0, named = 0, bound = 0;
char *str[3], *p, w1[1024], w2[1024];
bool found = false;
while(fgets(line, sizeof(line), fp))
{
ln++;
if(line[0]=='/' && line[1]=='/')
if (line[0] == '/' && line[1] == '/')
continue;
if(strstr(line,"import")) {
if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2 &&
strcmpi(w1, "import") == 0) {
if (strstr(line,"import")) {
if (sscanf(line,"%[^:]: %[^\r\n]",w1,w2) == 2 &&
strcmpi(w1,"import") == 0)
{
itemdb_read_itemgroup_sub(w2);
continue;
}
}
memset(str,0,sizeof(str));
for(j=0,p=line;j<3 && p;j++){
str[j]=p;
p=strchr(p,',');
if(p) *p++=0;
for (j = 0, p = line; j < 3 && p;j++) {
str[j] = p;
if (j == 2)
sscanf(str[j],"%d,%d,%d,%d,%d,%d,%d",&prob,&amt,&group,&announced,&dur,&named,&bound);
p = strchr(p,',');
if (p) *p++=0;
}
if(str[0]==NULL)
if (str[0] == NULL)
continue;
if (j<3) {
if (j>1) //Or else it barks on blank lines...
if (j < 3) {
if (j > 1) //Or else it barks on blank lines...
ShowWarning("itemdb_read_itemgroup: Insufficient fields for entry at %s:%d\n", filename, ln);
continue;
}
groupid = atoi(str[0]);
if (groupid < 0 || groupid >= MAX_ITEMGROUP) {
ShowWarning("itemdb_read_itemgroup: Invalid group %d in %s:%d\n", groupid, filename, ln);
//Checking group_id
if (!atoi(str[0])) //Try reads group id by const
script_get_constant(trim(str[0]),&group_id);
else
group_id = atoi(str[0]);
if (!group_id || group_id >= MAX_ITEMGROUP || group >= MAX_ITEMGROUP_RANDGROUP) {
ShowWarning("itemdb_read_itemgroup: Invalid group (id:%d sub:%d) in %s:%d\n", group_id, group, filename, ln);
continue;
}
nameid = atoi(str[1]);
if (!itemdb_exists(nameid)) {
//Checking item
if (!atoi(str[1]) && itemdb_searchname(str[1])) {
found = true;
nameid = itemdb_searchname(str[1])->nameid;
}
else if ((nameid = atoi(str[1])) && itemdb_exists(nameid))
found = true;
if (!found) {
ShowWarning("itemdb_read_itemgroup: Non-existant item %d in %s:%d\n", nameid, filename, ln);
continue;
}
k = atoi(str[2]);
if (itemgroup_db[groupid].qty+k >= MAX_RANDITEM) {
ShowWarning("itemdb_read_itemgroup: Group %d is full (%d entries) in %s:%d\n", groupid, MAX_RANDITEM, filename, ln);
//Checking the capacity
if ((group && itemgroup_db[group_id].random_qty[group-1]+prob >= MAX_ITEMGROUP_RAND) ||
(!group && itemgroup_db[group_id].must_qty+1 >= MAX_ITEMGROUP_MUST))
{
ShowWarning("itemdb_read_itemgroup: Group id %d is overflow (%d entries) in %s:%d\n", group_id, (!group) ? MAX_ITEMGROUP_MUST : MAX_ITEMGROUP_RAND, filename, ln);
continue;
}
for(j=0;j<k;j++)
itemgroup_db[groupid].nameid[itemgroup_db[groupid].qty++] = nameid;
if (!group) {
uint16 idx = itemgroup_db[group_id].must_qty;
itemgroup_db[group_id].must[idx].nameid = nameid;
itemgroup_db[group_id].must[idx].amount = min(amt,MAX_AMOUNT);
itemgroup_db[group_id].must[idx].isAnnounced = (announced) ? true : false;
itemgroup_db[group_id].must[idx].duration = min(dur,UINT16_MAX);
itemgroup_db[group_id].must[idx].isNamed = (named) ? true : false;
itemgroup_db[group_id].must[idx].bound = cap_value(bound,0,4);
itemgroup_db[group_id].must_qty++;
}
for (j = 0; j < prob; j++) {
uint16 idx;
if (!group)
group = 1;
idx = itemgroup_db[group_id].random_qty[group-1];
itemgroup_db[group_id].random[group-1][idx].nameid = nameid;
itemgroup_db[group_id].random[group-1][idx].amount = min(amt,MAX_AMOUNT);
itemgroup_db[group_id].random[group-1][idx].isAnnounced = (announced) ? true : false;
itemgroup_db[group_id].random[group-1][idx].duration = min(dur,UINT16_MAX);
itemgroup_db[group_id].random[group-1][idx].isNamed = (named) ? true : false;
itemgroup_db[group_id].random[group-1][idx].bound = cap_value(bound,0,4);
itemgroup_db[group_id].random_qty[group-1]++;
}
entries++;
}
fclose(fp);

View File

@ -11,7 +11,8 @@
// 32k array entries in array (the rest goes to the db)
#define MAX_ITEMDB 0x8000
#define MAX_RANDITEM 11000
//Use apple for unknown items.
#define UNKNOWN_ITEM_ID 512
// The maximum number of item delays
#define MAX_ITEMDELAYS 10
@ -21,6 +22,24 @@
/* maximum amount of items a combo may require */
#define MAX_ITEMS_PER_COMBO 6
//The only item group required by the code to be known. See const.txt for the full list.
#define IG_FINDINGORE 6
#define IG_POTION 37
#define MAX_ITEMGROUP 390 ///The max. item group count (increase this when needed).
#define MAX_ITEMGROUP_RAND 11000 ///Max item slots for random item group
#define MAX_ITEMGROUP_MUST 20 ///Max item slots for 'must' item group
#define MAX_ITEMGROUP_RANDGROUP 5 ///Max group for random item
#define CARD0_FORGE 0x00FF
#define CARD0_CREATE 0x00FE
#define CARD0_PET ((short)0xFF00)
//Marks if the card0 given is "special" (non-item id used to mark pets/created items. [Skotlex]
#define itemdb_isspecial(i) (i == CARD0_FORGE || i == CARD0_CREATE || i == CARD0_PET)
///Enum of item id (for hardcoded purpose)
enum item_itemid {
ITEMID_EMPERIUM = 714,
ITEMID_YELLOW_GEMSTONE = 715,
@ -83,22 +102,6 @@ enum e_item_job {
ITEMJ_THIRD_BABY = 0x20,
};
//The only item group required by the code to be known. See const.txt for the full list.
#define IG_FINDINGORE 6
#define IG_POTION 37
//The max. item group count (increase this when needed).
#define MAX_ITEMGROUP 71
#define CARD0_FORGE 0x00FF
#define CARD0_CREATE 0x00FE
#define CARD0_PET ((short)0xFF00)
//Marks if the card0 given is "special" (non-item id used to mark pets/created items. [Skotlex]
#define itemdb_isspecial(i) (i == CARD0_FORGE || i == CARD0_CREATE || i == CARD0_PET)
//Use apple for unknown items.
#define UNKNOWN_ITEM_ID 512
struct item_data {
uint16 nameid;
char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH];
@ -162,9 +165,21 @@ struct item_data {
unsigned char combos_count;
};
struct item_group {
int nameid[MAX_RANDITEM];
int qty; //Counts amount of items in the group.
/* Struct of item group */
struct s_item_group {
uint16 nameid, ///item id
duration; ///duration if item as rental item
uint16 amount; ///amount of item will be obtained
bool isAnnounced, ///broadcast if player get this item
isNamed; ///named the item (if possible)
char bound; ///makes the item as bound item (according to bound type)
};
/* Struct of item group that will be used for db */
struct s_item_group_db {
struct s_item_group must[MAX_ITEMGROUP_MUST];
struct s_item_group random[MAX_ITEMGROUP_RANDGROUP][MAX_ITEMGROUP_RAND]; ///NOTE: Is this good?
uint16 must_qty, random_qty[MAX_ITEMGROUP_RANDGROUP];
};
struct item_combo {
@ -208,7 +223,7 @@ struct item_data* itemdb_exists(int nameid);
const char* itemdb_typename(int type);
int itemdb_group_bonus(struct map_session_data* sd, int itemid);
int itemdb_searchrandomid(int flags);
int itemdb_searchrandomid(int group_id, uint8 sub_group);
#define itemdb_value_buy(n) itemdb_search(n)->value_buy
#define itemdb_value_sell(n) itemdb_search(n)->value_sell
@ -242,6 +257,9 @@ int itemdb_isstackable2(struct item_data *);
uint64 itemdb_unique_id(int8 flag, int64 value); // Unique Item ID
bool itemdb_isNoEquip(struct item_data *id, uint16 m);
uint8 itemdb_pc_get_itemgroup(uint16 group_id, uint16 nameid, struct map_session_data *sd);
uint16 itemdb_get_randgroupitem_count(uint16 group_id, uint8 sub_group, uint16 nameid);
DBMap * itemdb_get_combodb();
void itemdb_reload(void);

View File

@ -2426,7 +2426,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
// Ore Discovery [Celest]
if (sd == mvp_sd && pc_checkskill(sd,BS_FINDINGORE)>0 && battle_config.finding_ore_rate/10 >= rnd()%10000) {
ditem = mob_setdropitem(itemdb_searchrandomid(IG_FINDINGORE), 1);
ditem = mob_setdropitem(itemdb_searchrandomid(IG_FINDINGORE,1), 1);
mob_item_drop(md, dlist, ditem, 0, battle_config.finding_ore_rate/10, homkillonly);
}
@ -2454,7 +2454,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
if (rnd()%10000 >= drop_rate)
continue;
itemid = (sd->add_drop[i].id > 0) ? sd->add_drop[i].id : itemdb_searchrandomid(sd->add_drop[i].group);
itemid = (sd->add_drop[i].id > 0) ? sd->add_drop[i].id : itemdb_searchrandomid(sd->add_drop[i].group,1);
mob_item_drop(md, dlist, mob_setdropitem(itemid,1), 0, drop_rate, homkillonly);
}
}

View File

@ -10474,8 +10474,7 @@ void pc_bonus_script_check(struct map_session_data *sd, enum e_bonus_script_flag
* @param sd player
*/
void pc_cell_basilica(struct map_session_data *sd) {
if (!sd)
return;
nullpo_retv(sd);
if (!map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKBASILICA)) {
if (&sd->sc && sd->sc.data[SC_BASILICA])

View File

@ -6637,14 +6637,11 @@ BUILDIN_FUNC(getnameditem)
/*==========================================
* gets a random item ID from an item group [Skotlex]
* groupranditem group_num
* groupranditem <group_num>{,<sub_group>};
*------------------------------------------*/
BUILDIN_FUNC(grouprandomitem)
{
int group;
group = script_getnum(st,2);
script_pushint(st,itemdb_searchrandomid(group));
script_pushint(st,itemdb_searchrandomid(script_getnum(st,2),script_getnum(st,3)));
return SCRIPT_CMD_SUCCESS;
}
@ -17510,40 +17507,50 @@ BUILDIN_FUNC(checkre)
return SCRIPT_CMD_SUCCESS;
}
/* getrandgroupitem <group_id>,<quantity> */
/* getrandgroupitem <group_id>,<quantity>{,<sub_group>} */
BUILDIN_FUNC(getrandgroupitem) {
TBL_PC* sd;
int i, get_count = 0, flag, nameid, group = script_getnum(st, 2), qty = script_getnum(st,3);
int i, get_count = 0, flag;
uint16 nameid, group = script_getnum(st,2), qty = script_getnum(st,3);
uint8 sub_group = script_getnum(st,4);
struct item item_tmp;
if( !( sd = script_rid2sd(st) ) )
return 0;
if (!( sd = script_rid2sd(st)))
return SCRIPT_CMD_SUCCESS;
if( qty <= 0 ) {
ShowError("getrandgroupitem: qty is <= 0!\n");
return 1;
if (!group) {
ShowError("getrandgroupitem: Invalid group id (%d)!\n",script_getnum(st,2));
return SCRIPT_CMD_FAILURE;
}
if( (nameid = itemdb_searchrandomid(group)) == UNKNOWN_ITEM_ID ) {
return 1; //ensure valid itemid
if ((nameid = itemdb_searchrandomid(group,sub_group)) == UNKNOWN_ITEM_ID) {
return SCRIPT_CMD_FAILURE; //ensure valid itemid
}
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid = nameid;
item_tmp.identify = itemdb_isidentified(nameid);
//Check if it's stackable.
if (!itemdb_isstackable(nameid))
get_count = 1;
else
get_count = qty;
if (!qty)
qty = itemdb_get_randgroupitem_count(group,sub_group,nameid);
for (i = 0; i < qty; i += get_count) {
//Check if it's stackable.
if (!itemdb_isstackable(nameid)) {
item_tmp.amount = 1;
get_count = qty;
}
else {
item_tmp.amount = qty;
get_count = 1;
}
for (i = 0; i < get_count; i++) {
// if not pet egg
if (!pet_create_egg(sd, nameid)) {
if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_SCRIPT))) {
clif_additem(sd, 0, 0, flag);
if( pc_candrop(sd,&item_tmp) )
map_addflooritem(&item_tmp,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
if ((flag = pc_additem(sd,&item_tmp,item_tmp.amount,LOG_TYPE_SCRIPT))) {
clif_additem(sd,0,0,flag);
if (pc_candrop(sd,&item_tmp))
map_addflooritem(&item_tmp,item_tmp.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
}
}
@ -17551,6 +17558,24 @@ BUILDIN_FUNC(getrandgroupitem) {
return SCRIPT_CMD_SUCCESS;
}
/* getgroupitem <group_id>;
* Gives item(s) to the attached player based on item group contents
*/
BUILDIN_FUNC(getgroupitem) {
TBL_PC *sd;
int group_id = script_getnum(st,2);
if (!(sd = script_rid2sd(st)))
return SCRIPT_CMD_SUCCESS;
if (itemdb_pc_get_itemgroup(group_id,sd->itemid,sd)) {
ShowError("getgroupitem: Invalid group id '%d' specified.",group_id);
return SCRIPT_CMD_FAILURE;
}
return SCRIPT_CMD_SUCCESS;
}
/* cleanmap <map_name>;
* cleanarea <map_name>, <x0>, <y0>, <x1>, <y1>; */
static int atcommand_cleanfloor_sub(struct block_list *bl, va_list ap)
@ -18298,7 +18323,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(rentitem,"vi"),
BUILDIN_DEF(getitem2,"viiiiiiii?"),
BUILDIN_DEF(getnameditem,"vv"),
BUILDIN_DEF2(grouprandomitem,"groupranditem","i"),
BUILDIN_DEF2(grouprandomitem,"groupranditem","i?"),
BUILDIN_DEF(makeitem,"visii"),
BUILDIN_DEF(delitem,"vi?"),
BUILDIN_DEF(delitem2,"viiiiiiii?"),
@ -18690,7 +18715,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(is_function,"s"),
BUILDIN_DEF(get_revision,""),
BUILDIN_DEF(freeloop,"i"),
BUILDIN_DEF(getrandgroupitem,"ii"),
BUILDIN_DEF(getrandgroupitem,"ii?"),
BUILDIN_DEF(cleanmap,"s"),
BUILDIN_DEF2(cleanmap,"cleanarea","siiii"),
BUILDIN_DEF(npcskill,"viii"),
@ -18731,6 +18756,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(vip_status,"i?"),
BUILDIN_DEF(vip_time,"i?"),
BUILDIN_DEF(bonus_script,"si???"),
BUILDIN_DEF(getgroupitem,"i"),
#include "../custom/script_def.inc"