Merge branch 'Upstream/master'

This commit is contained in:
nanakiwurtz 2013-12-25 04:23:29 +07:00
commit e797f085e5
27 changed files with 5205 additions and 1234 deletions

View File

@ -714,7 +714,10 @@
714: Item Shop List: %s (%d) 714: Item Shop List: %s (%d)
715: Point Shop List: '%s' 715: Point Shop List: '%s'
716: Your '%s' now: %d 716: Your '%s' now: %d
//717-899 free
//Item Group
717: [%s] has won [%s] from '%s'
//718-899 free
//------------------------------------ //------------------------------------
// More atcommands message // More atcommands message
@ -1517,7 +1520,7 @@
1484: You're currently not autolooting this item type. 1484: You're currently not autolooting this item type.
1485: Removed item type: '%s' {%d} from your autoloottype list. 1485: Removed item type: '%s' {%d} from your autoloottype list.
1486: To add an item type to the list, use "@aloottype +<type name or ID>". To remove an item type, use "@aloottype -<type name or ID>". 1486: To add an item type to the list, use "@aloottype +<type name or ID>". To remove an item type, use "@aloottype -<type name or ID>".
1487: Type List: healing = 0, usable = 2, etc = 3, weapon = 4, armor = 5, card = 6, petegg = 7, petarmor = 8, ammo = 10 1487: Type List: healing = 0, usable = 2, etc = 3, armor = 4, weapon = 5, card = 6, petegg = 7, petarmor = 8, ammo = 10
1488: "@aloottype reset" will clear your autoloottype list. 1488: "@aloottype reset" will clear your autoloottype list.
1489: Your autoloottype list is empty. 1489: Your autoloottype list is empty.
1490: Item types on your autoloottype list: 1490: Item types on your autoloottype list:
@ -1525,7 +1528,7 @@
// @dropall // @dropall
1492: Usage: @dropall {<type>} 1492: Usage: @dropall {<type>}
1493: Type List: (default) all = -1, healing = 0, usable = 2, etc = 3, weapon = 4, armor = 5, card = 6, petegg = 7, petarmor = 8, ammo = 10 1493: Type List: (default) all = -1, healing = 0, usable = 2, etc = 3, armor = 4, weapon = 5, card = 6, petegg = 7, petarmor = 8, ammo = 10
1494: %d items are dropped! 1494: %d items are dropped!
//Banking //Banking

View File

@ -713,7 +713,10 @@
714: Item Shop: %s (%d) 714: Item Shop: %s (%d)
715: Point Shop: '%s' 715: Point Shop: '%s'
716: '%s' milikmu saat ini: %d 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_MISC 0x40
ATF_SKILL 0x60 ATF_SKILL 0x60
//Item Group ID
IG_BlueBox 1 IG_BlueBox 1
IG_VioletBox 2 IG_VioletBox 2
IG_CardAlbum 3 IG_CardAlbum 3
@ -790,6 +791,321 @@ IG_CardAlbum_Shield 67
IG_CardAlbum_Weapon 68 IG_CardAlbum_Weapon 68
IG_CardAlbum_Garment 69 IG_CardAlbum_Garment 69
IG_Flamel_Card 70 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_ALL -1
SC_STONE 0 SC_STONE 0
@ -3387,8 +3703,8 @@ DIR_NORTHEAST 7
IT_HEALING 0 IT_HEALING 0
IT_USABLE 2 IT_USABLE 2
IT_ETC 3 IT_ETC 3
IT_WEAPON 4 IT_ARMOR 4
IT_ARMOR 5 IT_WEAPON 5
IT_CARD 6 IT_CARD 6
IT_PETEGG 7 IT_PETEGG 7
IT_PETARMOR 8 IT_PETARMOR 8

View File

@ -1,5 +1,7 @@
//
// Structure of Database:
// GroupID,ItemID,Rate // GroupID,ItemID,Rate
// //
// Cookie Bag // Cookie Bag
7,529,5 //Candy 7,529,5 //Candy
7,530,5 //Candy Cane 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/item_findingore.txt
import: db/re/item_giftbox.txt import: db/re/item_giftbox.txt
import: db/re/item_misc.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 // GroupID,ItemID,Rate
// //
// Cookie Bag // Cookie Bag
7,529,5 //Candy 7,529,5 //Candy
7,530,5 //Candy Cane 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 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'. 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; 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 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 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: For example, obtaining three of the same random item from Old Blue Box:
getrandgroupitem(1,3); 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

@ -173,8 +173,8 @@ enum item_types {
IT_UNKNOWN, //1 IT_UNKNOWN, //1
IT_USABLE, //2 IT_USABLE, //2
IT_ETC, //3 IT_ETC, //3
IT_WEAPON, //4 IT_ARMOR, //4
IT_ARMOR, //5 IT_WEAPON, //5
IT_CARD, //6 IT_CARD, //6
IT_PETEGG, //7 IT_PETEGG, //7
IT_PETARMOR,//8 IT_PETARMOR,//8

View File

@ -5877,7 +5877,7 @@ ACMD_FUNC(autolootitem)
* @autoloottype * @autoloottype
* Flags: * Flags:
* 1: IT_HEALING, 2: IT_UNKNOWN, 4: IT_USABLE, 8: IT_ETC, * 1: IT_HEALING, 2: IT_UNKNOWN, 4: IT_USABLE, 8: IT_ETC,
* 16: IT_WEAPON, 32: IT_ARMOR, 64: IT_CARD, 128: IT_PETEGG, * 16: IT_ARMOR, 32: IT_WEAPON, 64: IT_CARD, 128: IT_PETEGG,
* 256: IT_PETARMOR, 512: IT_UNKNOWN2, 1024: IT_AMMO, 2048: IT_DELAYCONSUME * 256: IT_PETARMOR, 512: IT_UNKNOWN2, 1024: IT_AMMO, 2048: IT_DELAYCONSUME
* 262144: IT_CASH * 262144: IT_CASH
*------------------------------------------ *------------------------------------------
@ -5913,10 +5913,10 @@ ACMD_FUNC(autoloottype)
type = IT_USABLE; type = IT_USABLE;
else if ((strncmp(message, "etc", 3) == 0) || (atoi(message) == 3)) else if ((strncmp(message, "etc", 3) == 0) || (atoi(message) == 3))
type = IT_ETC; type = IT_ETC;
else if ((strncmp(message, "weapon", 3) == 0) || (atoi(message) == 4)) else if ((strncmp(message, "armor", 3) == 0) || (atoi(message) == 4))
type = IT_WEAPON;
else if ((strncmp(message, "armor", 3) == 0) || (atoi(message) == 5))
type = IT_ARMOR; type = IT_ARMOR;
else if ((strncmp(message, "weapon", 3) == 0) || (atoi(message) == 5))
type = IT_WEAPON;
else if ((strncmp(message, "card", 3) == 0) || (atoi(message) == 6)) else if ((strncmp(message, "card", 3) == 0) || (atoi(message) == 6))
type = IT_CARD; type = IT_CARD;
else if ((strncmp(message, "petegg", 4) == 0) || (atoi(message) == 7)) else if ((strncmp(message, "petegg", 4) == 0) || (atoi(message) == 7))
@ -5959,7 +5959,7 @@ ACMD_FUNC(autoloottype)
break; break;
case 3: case 3:
clif_displaymessage(fd, msg_txt(sd,1486)); // To add an item type to the list, use "@aloottype +<type name or ID>". To remove an item type, use "@aloottype -<type name or ID>". clif_displaymessage(fd, msg_txt(sd,1486)); // To add an item type to the list, use "@aloottype +<type name or ID>". To remove an item type, use "@aloottype -<type name or ID>".
clif_displaymessage(fd, msg_txt(sd,1487)); // Type List: healing = 0, usable = 2, etc = 3, weapon = 4, armor = 5, card = 6, petegg = 7, petarmor = 8, ammo = 10 clif_displaymessage(fd, msg_txt(sd,1487)); // Type List: healing = 0, usable = 2, etc = 3, armor = 4, weapon = 5, card = 6, petegg = 7, petarmor = 8, ammo = 10
clif_displaymessage(fd, msg_txt(sd,1488)); // "@aloottype reset" will clear your autoloottype list. clif_displaymessage(fd, msg_txt(sd,1488)); // "@aloottype reset" will clear your autoloottype list.
if (sd->state.autoloottype == ITEM_NONE) if (sd->state.autoloottype == ITEM_NONE)
clif_displaymessage(fd, msg_txt(sd,1489)); // Your autoloottype list is empty. clif_displaymessage(fd, msg_txt(sd,1489)); // Your autoloottype list is empty.

View File

@ -1931,6 +1931,7 @@ void clif_scriptclear(struct map_session_data *sd, int npcid)
struct s_packet_db* info; struct s_packet_db* info;
int16 len; int16 len;
int cmd = 0; int cmd = 0;
int fd;
nullpo_retv(sd); nullpo_retv(sd);
@ -1938,6 +1939,7 @@ void clif_scriptclear(struct map_session_data *sd, int npcid)
if(!cmd) cmd = 0x8d6; //default if(!cmd) cmd = 0x8d6; //default
info = &packet_db[sd->packet_ver][cmd]; info = &packet_db[sd->packet_ver][cmd];
len = info->len; len = info->len;
fd = sd->fd;
WFIFOHEAD(fd, len); WFIFOHEAD(fd, len);
WFIFOW(fd,0)=0x8d6; WFIFOW(fd,0)=0x8d6;
@ -17174,6 +17176,9 @@ void clif_parse_GMFullStrip(int fd, struct map_session_data *sd) {
is_atcommand(fd, sd, cmd, 1); 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 #ifdef DUMP_UNKNOWN_PACKET
void DumpUnknow(int fd,TBL_PC *sd,int cmd,int packet_len){ void DumpUnknow(int fd,TBL_PC *sd,int cmd,int packet_len){
const char* packet_txt = "save/packet.txt"; const char* packet_txt = "save/packet.txt";

View File

@ -353,11 +353,11 @@ enum clif_messages {
}; };
enum e_personalinfo { enum e_personalinfo {
PINFO_BASIC = 0, PINFO_BASIC = 0,
PINFO_PREMIUM, PINFO_PREMIUM,
PINFO_SERVER, PINFO_SERVER,
PINFO_CAFE, PINFO_CAFE,
PINFO_MAX, PINFO_MAX,
}; };
int clif_setip(const char* ip); 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_ranklist(struct map_session_data *sd, int16 rankingType);
void clif_update_rankingpoint(struct map_session_data *sd, int rankingtype, int point); void clif_update_rankingpoint(struct map_session_data *sd, int rankingtype, int point);
//void clif_broadcast_obtain_special_item(); ///TODO!
#endif /* _CLIF_H_ */ #endif /* _CLIF_H_ */

View File

@ -21,7 +21,7 @@
static struct item_data* itemdb_array[MAX_ITEMDB]; static struct item_data* itemdb_array[MAX_ITEMDB];
static DBMap* itemdb_other;// int nameid -> struct item_data* 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] 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 count;
} }
/**
/*========================================== * Return a random item id from group. (takes into account % chance giving/tot group)
* Return a random item id from group. (takes into account % chance giving/tot group) * @param group_id
*------------------------------------------*/ * @param sub_group: Default is 1
int itemdb_searchrandomid(int group) * @return nameid
*/
int itemdb_searchrandomid(int group_id, uint8 sub_group)
{ {
if(group<1 || group>=MAX_ITEMGROUP) { if (sub_group == 0)
ShowError("itemdb_searchrandomid: Invalid group id %d\n", group); 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; return UNKNOWN_ITEM_ID;
} }
if (itemgroup_db[group].qty) if (sub_group >= MAX_ITEMGROUP_RANDGROUP) {
return itemgroup_db[group].nameid[rnd()%itemgroup_db[group].qty]; 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; 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 * 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++) { for (i=0; i < MAX_ITEMGROUP; i++) {
if (!sd->itemgrouphealrate[i]) if (!sd->itemgrouphealrate[i])
continue; continue;
ARR_FIND( 0, itemgroup_db[i].qty, j, itemgroup_db[i].nameid[j] == itemid ); ARR_FIND( 0, itemgroup_db[i].random_qty[0], j, itemgroup_db[i].random[0][j].nameid == itemid );
if( j < itemgroup_db[i].qty ) if( j < itemgroup_db[i].random_qty[0] )
bonus += sd->itemgrouphealrate[i]; bonus += sd->itemgrouphealrate[i];
} }
return bonus; return bonus;
@ -529,63 +638,105 @@ static bool itemdb_read_itemavail(char* str[], int columns, int current)
/*========================================== /*==========================================
* read item group data * read item group data
* GroupID,ItemID,Rate{,Amount,isMust,isAnnounced,Duration,isNamed,isBound}
*------------------------------------------*/ *------------------------------------------*/
static void itemdb_read_itemgroup_sub(const char* filename) static void itemdb_read_itemgroup_sub(const char* filename)
{ {
FILE *fp; FILE *fp;
char line[1024];
int ln=0, entries=0; int ln=0, entries=0;
int groupid,j,k,nameid; char line[1024];
char *str[3],*p;
char w1[1024], w2[1024];
if( (fp=fopen(filename,"r"))==NULL ){ if ((fp=fopen(filename,"r")) == NULL) {
ShowError("can't read %s\n", filename); ShowError("can't read %s\n", filename);
return; 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++; ln++;
if(line[0]=='/' && line[1]=='/') if (line[0] == '/' && line[1] == '/')
continue; continue;
if(strstr(line,"import")) { if (strstr(line,"import")) {
if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2 && if (sscanf(line,"%[^:]: %[^\r\n]",w1,w2) == 2 &&
strcmpi(w1, "import") == 0) { strcmpi(w1,"import") == 0)
{
itemdb_read_itemgroup_sub(w2); itemdb_read_itemgroup_sub(w2);
continue; continue;
} }
} }
memset(str,0,sizeof(str)); memset(str,0,sizeof(str));
for(j=0,p=line;j<3 && p;j++){ for (j = 0, p = line; j < 3 && p;j++) {
str[j]=p; str[j] = p;
p=strchr(p,','); if (j == 2)
if(p) *p++=0; 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; continue;
if (j<3) { if (j < 3) {
if (j>1) //Or else it barks on blank lines... if (j > 1) //Or else it barks on blank lines...
ShowWarning("itemdb_read_itemgroup: Insufficient fields for entry at %s:%d\n", filename, ln); ShowWarning("itemdb_read_itemgroup: Insufficient fields for entry at %s:%d\n", filename, ln);
continue; continue;
} }
groupid = atoi(str[0]);
if (groupid < 0 || groupid >= MAX_ITEMGROUP) { //Checking group_id
ShowWarning("itemdb_read_itemgroup: Invalid group %d in %s:%d\n", groupid, filename, ln); 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; 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); ShowWarning("itemdb_read_itemgroup: Non-existant item %d in %s:%d\n", nameid, filename, ln);
continue; continue;
} }
k = atoi(str[2]);
if (itemgroup_db[groupid].qty+k >= MAX_RANDITEM) { //Checking the capacity
ShowWarning("itemdb_read_itemgroup: Group %d is full (%d entries) in %s:%d\n", groupid, MAX_RANDITEM, filename, ln); 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; 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++; entries++;
} }
fclose(fp); fclose(fp);

View File

@ -11,7 +11,8 @@
// 32k array entries in array (the rest goes to the db) // 32k array entries in array (the rest goes to the db)
#define MAX_ITEMDB 0x8000 #define MAX_ITEMDB 0x8000
#define MAX_RANDITEM 11000 //Use apple for unknown items.
#define UNKNOWN_ITEM_ID 512
// The maximum number of item delays // The maximum number of item delays
#define MAX_ITEMDELAYS 10 #define MAX_ITEMDELAYS 10
@ -21,6 +22,24 @@
/* maximum amount of items a combo may require */ /* maximum amount of items a combo may require */
#define MAX_ITEMS_PER_COMBO 6 #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 { enum item_itemid {
ITEMID_EMPERIUM = 714, ITEMID_EMPERIUM = 714,
ITEMID_YELLOW_GEMSTONE = 715, ITEMID_YELLOW_GEMSTONE = 715,
@ -83,22 +102,6 @@ enum e_item_job {
ITEMJ_THIRD_BABY = 0x20, 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 { struct item_data {
uint16 nameid; uint16 nameid;
char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH]; char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH];
@ -162,9 +165,21 @@ struct item_data {
unsigned char combos_count; unsigned char combos_count;
}; };
struct item_group { /* Struct of item group */
int nameid[MAX_RANDITEM]; struct s_item_group {
int qty; //Counts amount of items in the 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 { struct item_combo {
@ -208,7 +223,7 @@ struct item_data* itemdb_exists(int nameid);
const char* itemdb_typename(int type); const char* itemdb_typename(int type);
int itemdb_group_bonus(struct map_session_data* sd, int itemid); 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_buy(n) itemdb_search(n)->value_buy
#define itemdb_value_sell(n) itemdb_search(n)->value_sell #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 uint64 itemdb_unique_id(int8 flag, int64 value); // Unique Item ID
bool itemdb_isNoEquip(struct item_data *id, uint16 m); 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(); DBMap * itemdb_get_combodb();
void itemdb_reload(void); 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] // Ore Discovery [Celest]
if (sd == mvp_sd && pc_checkskill(sd,BS_FINDINGORE)>0 && battle_config.finding_ore_rate/10 >= rnd()%10000) { 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); 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) if (rnd()%10000 >= drop_rate)
continue; 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); 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 * @param sd player
*/ */
void pc_cell_basilica(struct map_session_data *sd) { void pc_cell_basilica(struct map_session_data *sd) {
if (!sd) nullpo_retv(sd);
return;
if (!map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKBASILICA)) { if (!map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKBASILICA)) {
if (&sd->sc && sd->sc.data[SC_BASILICA]) 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] * gets a random item ID from an item group [Skotlex]
* groupranditem group_num * groupranditem <group_num>{,<sub_group>};
*------------------------------------------*/ *------------------------------------------*/
BUILDIN_FUNC(grouprandomitem) BUILDIN_FUNC(grouprandomitem)
{ {
int group; script_pushint(st,itemdb_searchrandomid(script_getnum(st,2),script_getnum(st,3)));
group = script_getnum(st,2);
script_pushint(st,itemdb_searchrandomid(group));
return SCRIPT_CMD_SUCCESS; return SCRIPT_CMD_SUCCESS;
} }
@ -17510,40 +17507,50 @@ BUILDIN_FUNC(checkre)
return SCRIPT_CMD_SUCCESS; return SCRIPT_CMD_SUCCESS;
} }
/* getrandgroupitem <group_id>,<quantity> */ /* getrandgroupitem <group_id>,<quantity>{,<sub_group>} */
BUILDIN_FUNC(getrandgroupitem) { BUILDIN_FUNC(getrandgroupitem) {
TBL_PC* sd; 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; struct item item_tmp;
if( !( sd = script_rid2sd(st) ) ) if (!( sd = script_rid2sd(st)))
return 0; return SCRIPT_CMD_SUCCESS;
if( qty <= 0 ) { if (!group) {
ShowError("getrandgroupitem: qty is <= 0!\n"); ShowError("getrandgroupitem: Invalid group id (%d)!\n",script_getnum(st,2));
return 1; 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)); memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid = nameid; item_tmp.nameid = nameid;
item_tmp.identify = itemdb_isidentified(nameid); item_tmp.identify = itemdb_isidentified(nameid);
//Check if it's stackable. if (!qty)
if (!itemdb_isstackable(nameid)) qty = itemdb_get_randgroupitem_count(group,sub_group,nameid);
get_count = 1;
else
get_count = qty;
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 not pet egg
if (!pet_create_egg(sd, nameid)) { if (!pet_create_egg(sd, nameid)) {
if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_SCRIPT))) { if ((flag = pc_additem(sd,&item_tmp,item_tmp.amount,LOG_TYPE_SCRIPT))) {
clif_additem(sd, 0, 0, flag); clif_additem(sd,0,0,flag);
if( pc_candrop(sd,&item_tmp) ) 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); 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; 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>; /* cleanmap <map_name>;
* cleanarea <map_name>, <x0>, <y0>, <x1>, <y1>; */ * cleanarea <map_name>, <x0>, <y0>, <x1>, <y1>; */
static int atcommand_cleanfloor_sub(struct block_list *bl, va_list ap) 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(rentitem,"vi"),
BUILDIN_DEF(getitem2,"viiiiiiii?"), BUILDIN_DEF(getitem2,"viiiiiiii?"),
BUILDIN_DEF(getnameditem,"vv"), BUILDIN_DEF(getnameditem,"vv"),
BUILDIN_DEF2(grouprandomitem,"groupranditem","i"), BUILDIN_DEF2(grouprandomitem,"groupranditem","i?"),
BUILDIN_DEF(makeitem,"visii"), BUILDIN_DEF(makeitem,"visii"),
BUILDIN_DEF(delitem,"vi?"), BUILDIN_DEF(delitem,"vi?"),
BUILDIN_DEF(delitem2,"viiiiiiii?"), BUILDIN_DEF(delitem2,"viiiiiiii?"),
@ -18690,7 +18715,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(is_function,"s"), BUILDIN_DEF(is_function,"s"),
BUILDIN_DEF(get_revision,""), BUILDIN_DEF(get_revision,""),
BUILDIN_DEF(freeloop,"i"), BUILDIN_DEF(freeloop,"i"),
BUILDIN_DEF(getrandgroupitem,"ii"), BUILDIN_DEF(getrandgroupitem,"ii?"),
BUILDIN_DEF(cleanmap,"s"), BUILDIN_DEF(cleanmap,"s"),
BUILDIN_DEF2(cleanmap,"cleanarea","siiii"), BUILDIN_DEF2(cleanmap,"cleanarea","siiii"),
BUILDIN_DEF(npcskill,"viii"), BUILDIN_DEF(npcskill,"viii"),
@ -18731,6 +18756,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(vip_status,"i?"), BUILDIN_DEF(vip_status,"i?"),
BUILDIN_DEF(vip_time,"i?"), BUILDIN_DEF(vip_time,"i?"),
BUILDIN_DEF(bonus_script,"si???"), BUILDIN_DEF(bonus_script,"si???"),
BUILDIN_DEF(getgroupitem,"i"),
#include "../custom/script_def.inc" #include "../custom/script_def.inc"

View File

@ -1412,7 +1412,9 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
} }
// Always run NPC scripts for players last // Always run NPC scripts for players last
if(target->type == BL_PC) { //FIXME those ain't always run if a player die if he was resurect meanwhile
//cf SC_REBIRTH, SC_LIGHT_OF_REGENE, SC_KAIZEL, pc_dead...
if(target->type == BL_PC) {
TBL_PC *sd = BL_CAST(BL_PC,target); TBL_PC *sd = BL_CAST(BL_PC,target);
if( sd->bg_id ) { if( sd->bg_id ) {
struct battleground_data *bg; struct battleground_data *bg;
@ -1431,7 +1433,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
* @param bl: Object to heal [PC|MOB|HOM|MER|ELEM] * @param bl: Object to heal [PC|MOB|HOM|MER|ELEM]
* @param hhp: How much HP to heal * @param hhp: How much HP to heal
* @param hsp: How much SP to heal * @param hsp: How much SP to heal
* @param flag: Whether it's Forced(&1) or gives HP/SP(&2) heal effect * @param flag: Whether it's Forced(&1) or gives HP/SP(&2) heal effect \n
* Forced healing overrides heal impedement statuses (Berserk) * Forced healing overrides heal impedement statuses (Berserk)
* @return hp+sp * @return hp+sp
**/ **/
@ -1512,7 +1514,8 @@ int status_heal(struct block_list *bl,int64 hhp,int64 hsp, int flag)
* @param target: Object to modify HP/SP * @param target: Object to modify HP/SP
* @param hp_rate: Percentage of HP to modify * @param hp_rate: Percentage of HP to modify
* @param sp_rate: Percentage of SP to modify * @param sp_rate: Percentage of SP to modify
* @param flag: 0: Heal target * @param flag: \n
* 0: Heal target \n
* 2: Target must not die from subtraction * 2: Target must not die from subtraction
* @return hp+sp through status_heal() * @return hp+sp through status_heal()
**/ **/

View File

@ -24,11 +24,15 @@
#include <string.h> #include <string.h>
static DBMap* guild_storage_db; // int guild_id -> struct guild_storage* static DBMap* guild_storage_db; ///Databases of guild_storage : int guild_id -> struct guild_storage*
/*========================================== /**
* Sort items in the warehouse * Storage item comparator (for qsort)
*------------------------------------------*/ * sort by itemid and amount
* @param _i1 : item a
* @param _i2 : item b
* @return i1<=>i2
*/
static int storage_comp_item(const void *_i1, const void *_i2) static int storage_comp_item(const void *_i1, const void *_i2)
{ {
struct item *i1 = (struct item *)_i1; struct item *i1 = (struct item *)_i1;
@ -43,7 +47,12 @@ static int storage_comp_item(const void *_i1, const void *_i2)
return i1->nameid - i2->nameid; return i1->nameid - i2->nameid;
} }
//Sort item by storage_comp_item (nameid) /**
* Sort item by storage_comp_item (nameid)
* used when we open up our storage or guild_storage
* @param items : list of items to sort
* @param size : number of item in list
*/
static void storage_sortitem(struct item* items, unsigned int size) static void storage_sortitem(struct item* items, unsigned int size)
{ {
nullpo_retv(items); nullpo_retv(items);
@ -54,22 +63,32 @@ static void storage_sortitem(struct item* items, unsigned int size)
} }
} }
/*========================================== /**
* Init/Terminate * Initiate storage module
*------------------------------------------*/ * Called from map.c::do_init()
int do_init_storage(void) // Called from map.c::do_init() * @return 1
*/
int do_init_storage(void) //
{ {
guild_storage_db=idb_alloc(DB_OPT_RELEASE_DATA); guild_storage_db=idb_alloc(DB_OPT_RELEASE_DATA);
return 1; return 1;
} }
void do_final_storage(void) // by [MC Cameri]
/**
* Destroy storage module
* @author : [MC Cameri]
* Called from map.c::do_final()
*/
void do_final_storage(void)
{ {
guild_storage_db->destroy(guild_storage_db,NULL); guild_storage_db->destroy(guild_storage_db,NULL);
} }
/** /**
* Parses storage and saves 'dirty' ones upon reconnect. [Skotlex] * Parses storage and saves 'dirty' ones upon reconnect.
* @author [Skotlex]
* @see DBApply * @see DBApply
* @return 0
*/ */
static int storage_reconnect_sub(DBKey key, DBData *data, va_list ap) static int storage_reconnect_sub(DBKey key, DBData *data, va_list ap)
{ {
@ -80,17 +99,20 @@ static int storage_reconnect_sub(DBKey key, DBData *data, va_list ap)
return 0; return 0;
} }
//Function to be invoked upon server reconnection to char. To save all 'dirty' storages [Skotlex] /**
* Function to be invoked upon server reconnection to char. To save all 'dirty' storages
* @author [Skotlex]
*/
void do_reconnect_storage(void) void do_reconnect_storage(void)
{ {
guild_storage_db->foreach(guild_storage_db, storage_reconnect_sub); guild_storage_db->foreach(guild_storage_db, storage_reconnect_sub);
} }
/*========================================== /**
* Opens a storage. Returns: * Player attempt tp open his storage.
* 0 - success * @param sd : player
* 1 - fail * @return 0:success, 1:fail
*------------------------------------------*/ */
int storage_storageopen(struct map_session_data *sd) int storage_storageopen(struct map_session_data *sd)
{ {
nullpo_ret(sd); nullpo_ret(sd);
@ -111,8 +133,11 @@ int storage_storageopen(struct map_session_data *sd)
return 0; return 0;
} }
/* helper function /**
* checking if 2 item structure are identique * check if 2 item a and b have same values
* @param a : item 1
* @param b : item 2
* @return 1:same, 0:are different
*/ */
int compare_item(struct item *a, struct item *b) int compare_item(struct item *a, struct item *b)
{ {
@ -130,9 +155,13 @@ int compare_item(struct item *a, struct item *b)
return 0; return 0;
} }
/*========================================== /**
* Internal add-item function. * Make a player add an item to his storage
*------------------------------------------*/ * @param sd : player
* @param item_data : item to add
* @param amount : quantity of items
* @return 0:success, 1:failed
*/
static int storage_additem(struct map_session_data* sd, struct item* item_data, int amount) static int storage_additem(struct map_session_data* sd, struct item* item_data, int amount)
{ {
struct storage_data* stor = &sd->status.storage; struct storage_data* stor = &sd->status.storage;
@ -190,9 +219,13 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data,
return 0; return 0;
} }
/*========================================== /**
* Internal del-item function * Make a player delete an item from his storage
*------------------------------------------*/ * @param sd : player
* @param n : idx on storage to remove the item from
* @param amount :number of item to remove
* @return 0:sucess, 1:fail
*/
int storage_delitem(struct map_session_data* sd, int n, int amount) int storage_delitem(struct map_session_data* sd, int n, int amount)
{ {
if( sd->status.storage.items[n].nameid == 0 || sd->status.storage.items[n].amount < amount ) if( sd->status.storage.items[n].nameid == 0 || sd->status.storage.items[n].amount < amount )
@ -209,13 +242,13 @@ int storage_delitem(struct map_session_data* sd, int n, int amount)
return 0; return 0;
} }
/*========================================== /**
* Add an item to the storage from the inventory. * Add an item to the storage from the inventory.
* @index : inventory idx * @param sd : player
* return * @param index : inventory index to take the item from
* 0 : fail * @param amount : number of item to take
* 1 : success * @return 0:fail, 1:success
*------------------------------------------*/ */
int storage_storageadd(struct map_session_data* sd, int index, int amount) int storage_storageadd(struct map_session_data* sd, int index, int amount)
{ {
nullpo_ret(sd); nullpo_ret(sd);
@ -242,13 +275,13 @@ int storage_storageadd(struct map_session_data* sd, int index, int amount)
return 1; return 1;
} }
/*========================================== /**
* Retrieve an item from the storage into inventory * Retrieve an item from the storage into inventory
* @index : storage idx * @param sd : player
* return * @param index : storage index to take the item from
* 0 : fail * @param amount : number of item to take
* 1 : success * @return 0:fail, 1:success
*------------------------------------------*/ */
int storage_storageget(struct map_session_data* sd, int index, int amount) int storage_storageget(struct map_session_data* sd, int index, int amount)
{ {
int flag; int flag;
@ -270,13 +303,13 @@ int storage_storageget(struct map_session_data* sd, int index, int amount)
return 1; return 1;
} }
/*========================================== /**
* Move an item from cart to storage. * Move an item from cart to storage.
* @index : cart inventory index * @param sd : player
* return * @param index : cart index to take the item from
* 0 : fail * @param amount : number of item to take
* 1 : success * @return 0:fail, 1:success
*------------------------------------------*/ */
int storage_storageaddfromcart(struct map_session_data* sd, int index, int amount) int storage_storageaddfromcart(struct map_session_data* sd, int index, int amount)
{ {
nullpo_ret(sd); nullpo_ret(sd);
@ -299,13 +332,13 @@ int storage_storageaddfromcart(struct map_session_data* sd, int index, int amoun
return 1; return 1;
} }
/*========================================== /**
* Get from Storage to the Cart inventory * Get from Storage to the Cart inventory
* @index : storage index * @param sd : player
* return * @param index : storage index to take the item from
* 0 : fail * @param amount : number of item to take
* 1 : success * @return 0:fail, 1:success
*------------------------------------------*/ */
int storage_storagegettocart(struct map_session_data* sd, int index, int amount) int storage_storagegettocart(struct map_session_data* sd, int index, int amount)
{ {
short flag; short flag;
@ -331,9 +364,11 @@ int storage_storagegettocart(struct map_session_data* sd, int index, int amount)
} }
/*========================================== /**
* Modified By Valaris to save upon closing [massdriller] * Make player close his storage
*------------------------------------------*/ * @author : [massdriller] / modified by [Valaris]
* @param sd : player
*/
void storage_storageclose(struct map_session_data* sd) void storage_storageclose(struct map_session_data* sd)
{ {
nullpo_retv(sd); nullpo_retv(sd);
@ -346,9 +381,14 @@ void storage_storageclose(struct map_session_data* sd)
sd->state.storage_flag = 0; sd->state.storage_flag = 0;
} }
/*========================================== /**
* When quitting the game. * Force closing the storage for player without displaying result
*------------------------------------------*/ * (exemple when quitting the game)
* @param sd : player to close storage
* @param flag : \n
* 1: Character is quitting \n
* 2(x): Character is changing map-servers
*/
void storage_storage_quit(struct map_session_data* sd, int flag) void storage_storage_quit(struct map_session_data* sd, int flag)
{ {
nullpo_retv(sd); nullpo_retv(sd);
@ -360,7 +400,11 @@ void storage_storage_quit(struct map_session_data* sd, int flag)
} }
/** /**
* Create a guild_storage stucture and add it into the db
* @see DBCreateData * @see DBCreateData
* @param key
* @param args
* @return
*/ */
static DBData create_guildstorage(DBKey key, va_list args) static DBData create_guildstorage(DBKey key, va_list args)
{ {
@ -370,6 +414,12 @@ static DBData create_guildstorage(DBKey key, va_list args)
return db_ptr2data(gs); return db_ptr2data(gs);
} }
/**
* Retrieve the guild_storage of a guild
* will create a new storage if none found for the guild
* @param guild_id : id of the guild
* @return guild_storage
*/
struct guild_storage *guild2storage(int guild_id) struct guild_storage *guild2storage(int guild_id)
{ {
struct guild_storage *gs = NULL; struct guild_storage *gs = NULL;
@ -378,25 +428,33 @@ struct guild_storage *guild2storage(int guild_id)
return gs; return gs;
} }
//For just locating a storage without creating one. [Skotlex] /**
* See if the guild_storage exist in db and fetch it if it,s the case
* @author : [Skotlex]
* @param guild_id : guild_id to search the storage
* @return guild_storage or NULL
*/
struct guild_storage *guild2storage2(int guild_id) struct guild_storage *guild2storage2(int guild_id)
{ {
return (struct guild_storage*)idb_get(guild_storage_db,guild_id); return (struct guild_storage*)idb_get(guild_storage_db,guild_id);
} }
/**
* Delete a guild_storage and remove it from db
* @param guild_id : guild to remove the storage from
* @return 0
*/
int guild_storage_delete(int guild_id) int guild_storage_delete(int guild_id)
{ {
idb_remove(guild_storage_db,guild_id); idb_remove(guild_storage_db,guild_id);
return 0; return 0;
} }
/*========================================== /**
* Attempt to open guild storage for sd * Attempt to open guild storage for player
* return * @param sd : player
* 0 : success (open or req to create a new one) * @return * 0 : success, 1 : fail, 2 : no guild found
* 1 : fail */
* 2 : no guild for sd
*------------------------------------------*/
int storage_guild_storageopen(struct map_session_data* sd) int storage_guild_storageopen(struct map_session_data* sd)
{ {
struct guild_storage *gstor; struct guild_storage *gstor;
@ -432,12 +490,14 @@ int storage_guild_storageopen(struct map_session_data* sd)
return 0; return 0;
} }
/*========================================== /**
* Attempt to add an item in guild storage, then refresh it * Attempt to add an item in guild storage, then refresh it
* return * @param sd : player attempting to open the guild_storage
* 0 : success * @param stor : guild_storage
* 1 : fail * @param item_data : item to add
*------------------------------------------*/ * @param amount : number of item to add
* @return 0 : success, 1 : fail
*/
int guild_storage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item_data, int amount) int guild_storage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item_data, int amount)
{ {
struct item_data *data; struct item_data *data;
@ -495,12 +555,14 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
return 0; return 0;
} }
/*========================================== /**
* Attempt to delete an item in guild storage, then refresh it * Attempt to delete an item in guild storage, then refresh it
* return * @param sd : player
* 0 : success * @param stor : guild_storage
* 1 : fail * @param n : index of item in guild storage
*------------------------------------------*/ * @param amount : number of item to delete
* @return 0 : success, 1 : fail
*/
int guild_storage_delitem(struct map_session_data* sd, struct guild_storage* stor, int n, int amount) int guild_storage_delitem(struct map_session_data* sd, struct guild_storage* stor, int n, int amount)
{ {
nullpo_retr(1, sd); nullpo_retr(1, sd);
@ -520,13 +582,12 @@ int guild_storage_delitem(struct map_session_data* sd, struct guild_storage* sto
return 0; return 0;
} }
/*========================================== /**
* Attempt to add an item in guild storage from inventory, then refresh it * Attempt to add an item in guild storage from inventory, then refresh it
* @index : inventory idx * @param sd : player
* return * @param amount : number of item to delete
* 0 : fail * @return 1:success, 0:fail
* 1 : succes */
*------------------------------------------*/
int storage_guild_storageadd(struct map_session_data* sd, int index, int amount) int storage_guild_storageadd(struct map_session_data* sd, int index, int amount)
{ {
struct guild_storage *stor; struct guild_storage *stor;
@ -561,13 +622,13 @@ int storage_guild_storageadd(struct map_session_data* sd, int index, int amount)
return 1; return 1;
} }
/*========================================== /**
* Attempt to retrieve an item from guild storage to inventory, then refresh it * Attempt to retrieve an item from guild storage to inventory, then refresh it
* @index : storage idx * @param sd : player
* return * @param index : index of item in storage
* 0 : fail * @param amount : number of item to get
* 1 : succes * @return 1:success, 0:fail
*------------------------------------------*/ */
int storage_guild_storageget(struct map_session_data* sd, int index, int amount) int storage_guild_storageget(struct map_session_data* sd, int index, int amount)
{ {
struct guild_storage *stor; struct guild_storage *stor;
@ -595,20 +656,22 @@ int storage_guild_storageget(struct map_session_data* sd, int index, int amount)
if((flag = pc_additem(sd,&stor->items[index],amount,LOG_TYPE_GSTORAGE)) == 0) if((flag = pc_additem(sd,&stor->items[index],amount,LOG_TYPE_GSTORAGE)) == 0)
guild_storage_delitem(sd,stor,index,amount); guild_storage_delitem(sd,stor,index,amount);
else //inform fail else {//inform fail
clif_additem(sd,0,0,flag); clif_additem(sd,0,0,flag);
return 0;
}
// log_fromstorage(sd, index, 1); // log_fromstorage(sd, index, 1);
return 0; return 1;
} }
/*========================================== /**
* Attempt to add an item in guild storage from cart, then refresh it * Attempt to add an item in guild storage from cart, then refresh it
* @index : cart inventory idx * @param sd : player
* return * @param index : index of item in cart
* 0 : fail * @param amount : number of item to transfer
* 1 : succes * @return 1:fail, 0:success
*------------------------------------------*/ */
int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int amount) int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int amount)
{ {
struct guild_storage *stor; struct guild_storage *stor;
@ -634,13 +697,13 @@ int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int
return 1; return 1;
} }
/*========================================== /**
* Attempt to retrieve an item from guild storage to cart, then refresh it * Attempt to retrieve an item from guild storage to cart, then refresh it
* @index : storage idx * @param sd : player
* return * @param index : index of item in storage
* 0 : fail * @param amount : number of item to transfert
* 1 : succes * @return 1:fail, 0:success
*------------------------------------------*/ */
int storage_guild_storagegettocart(struct map_session_data* sd, int index, int amount) int storage_guild_storagegettocart(struct map_session_data* sd, int index, int amount)
{ {
short flag; short flag;
@ -666,17 +729,19 @@ int storage_guild_storagegettocart(struct map_session_data* sd, int index, int a
else { else {
clif_dropitem(sd,index,0); clif_dropitem(sd,index,0);
clif_cart_additem_ack(sd,(flag==1)?ADDITEM_TO_CART_FAIL_WEIGHT:ADDITEM_TO_CART_FAIL_COUNT); clif_cart_additem_ack(sd,(flag==1)?ADDITEM_TO_CART_FAIL_WEIGHT:ADDITEM_TO_CART_FAIL_COUNT);
return 0;
} }
return 1; return 1;
} }
/*========================================== /**
* Request to save guild storage * Request to save guild storage
* return * @param account_id : account requesting the save
* 0 : fail (no storage) * @param guild_id : guild to take the guild_storage
* 1 : succes * @param flag : ?
*------------------------------------------*/ * @return 0 : fail (no storage), 1 : success (requested)
*/
int storage_guild_storagesave(int account_id, int guild_id, int flag) int storage_guild_storagesave(int account_id, int guild_id, int flag)
{ {
struct guild_storage *stor = guild2storage2(guild_id); struct guild_storage *stor = guild2storage2(guild_id);
@ -692,12 +757,11 @@ int storage_guild_storagesave(int account_id, int guild_id, int flag)
return 0; return 0;
} }
/*========================================== /**
* ACK save of guild storage * ACK save of guild storage
* return * @param guild_id : guild to use the storage
* 0 : fail (no storage) * @return 0 : fail (no storage), 1 : succes
* 1 : succes */
*------------------------------------------*/
int storage_guild_storagesaved(int guild_id) int storage_guild_storagesaved(int guild_id)
{ {
struct guild_storage *stor; struct guild_storage *stor;
@ -712,7 +776,11 @@ int storage_guild_storagesaved(int guild_id)
return 0; return 0;
} }
//Close storage for sd and save it /**
* Close storage for player then save it
* @param sd : player
* @return 0
*/
int storage_guild_storageclose(struct map_session_data* sd) int storage_guild_storageclose(struct map_session_data* sd)
{ {
struct guild_storage *stor; struct guild_storage *stor;
@ -734,6 +802,12 @@ int storage_guild_storageclose(struct map_session_data* sd)
return 0; return 0;
} }
/**
* Close storage for player then save it
* @param sd
* @param flag
* @return
*/
int storage_guild_storage_quit(struct map_session_data* sd, int flag) int storage_guild_storage_quit(struct map_session_data* sd, int flag)
{ {
struct guild_storage *stor; struct guild_storage *stor;

View File

@ -20,13 +20,13 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#define TRADE_DISTANCE 2 ///Max distance from traders to enable a trade to take place.
//Max distance from traders to enable a trade to take place. /**
#define TRADE_DISTANCE 2 * Player initiates a trade request.
* @param sd : player requesting the trade
/*========================================== * @param target_sd : player requested
* Initiates a trade request. */
*------------------------------------------*/
void trade_traderequest(struct map_session_data *sd, struct map_session_data *target_sd) void trade_traderequest(struct map_session_data *sd, struct map_session_data *target_sd)
{ {
nullpo_retv(sd); nullpo_retv(sd);
@ -88,17 +88,19 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
clif_traderequest(target_sd, sd->status.name); clif_traderequest(target_sd, sd->status.name);
} }
/*==========================================
/**
* Reply to a trade-request. * Reply to a trade-request.
* Type values: * @param sd : player receiving the trade request answer
* 0: Char is too far * @param type : answer code \n
* 1: Character does not exist * 0: Char is too far \n
* 2: Trade failed * 1: Character does not exist \n
* 3: Accept * 2: Trade failed \n
* 4: Cancel * 3: Accept \n
* Weird enough, the client should only send 3/4 * 4: Cancel \n
* Weird enough, the client should only send 3/4 \n
* and the server is the one that can reply 0~2 * and the server is the one that can reply 0~2
*------------------------------------------*/ */
void trade_tradeack(struct map_session_data *sd, int type) void trade_tradeack(struct map_session_data *sd, int type)
{ {
struct map_session_data *tsd; struct map_session_data *tsd;
@ -165,11 +167,14 @@ void trade_tradeack(struct map_session_data *sd, int type)
clif_tradestart(sd, type); clif_tradestart(sd, type);
} }
/*========================================== /**
* Check here hacker for duplicate item in trade * Check here hacker for duplicate item in trade
* normal client refuse to have 2 same types of item (except equipment) in same trade window * normal client refuse to have 2 same types of item (except equipment) in same trade window
* normal client authorise only no equiped item and only from inventory * normal client authorise only no equiped item and only from inventory
*------------------------------------------*/ * This function could end player connection if too much hack is detected
* @param sd : player to check
* @return -1:zeny hack, 0:all fine, 1:item hack
*/
int impossible_trade_check(struct map_session_data *sd) int impossible_trade_check(struct map_session_data *sd)
{ {
struct item inventory[MAX_INVENTORY]; struct item inventory[MAX_INVENTORY];
@ -229,9 +234,12 @@ int impossible_trade_check(struct map_session_data *sd)
return 0; return 0;
} }
/*========================================== /**
* Checks if trade is possible (against zeny limits, inventory limits, etc) * Checks if trade is possible (against zeny limits, inventory limits, etc)
*------------------------------------------*/ * @param sd : player 1 trading
* @param tsd : player 2 trading
* @return 0:error, 1:success
*/
int trade_check(struct map_session_data *sd, struct map_session_data *tsd) int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
{ {
struct item inventory[MAX_INVENTORY]; struct item inventory[MAX_INVENTORY];
@ -316,9 +324,12 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
return 1; return 1;
} }
/*========================================== /**
* Adds an item/qty to the trade window * Adds an item/qty to the trade window
*------------------------------------------*/ * @param sd : Player requesting to add stuff to the trade
* @param index : index of item in inventory
* @param amount : amount of item to add from index
*/
void trade_tradeadditem(struct map_session_data *sd, short index, short amount) void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
{ {
struct map_session_data *target_sd; struct map_session_data *target_sd;
@ -409,9 +420,13 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
clif_tradeadditem(sd, target_sd, index+2, amount); clif_tradeadditem(sd, target_sd, index+2, amount);
} }
/*========================================== /**
* Adds the specified amount of zeny to the trade window * Adds the specified amount of zeny to the trade window
*------------------------------------------*/ * This function will check if the player have enough money to do so
* And if the target player have enough space for that money
* @param sd : Player who's adding zeny
* @param amount : zeny amount
*/
void trade_tradeaddzeny(struct map_session_data* sd, int amount) void trade_tradeaddzeny(struct map_session_data* sd, int amount)
{ {
struct map_session_data* target_sd; struct map_session_data* target_sd;
@ -436,9 +451,10 @@ void trade_tradeaddzeny(struct map_session_data* sd, int amount)
clif_tradeadditem(sd, target_sd, 0, amount); clif_tradeadditem(sd, target_sd, 0, amount);
} }
/*========================================== /**
* 'Ok' button on the trade window is pressed. * 'Ok' button on the trade window is pressed.
*------------------------------------------*/ * @param sd : Player that pressed the button
*/
void trade_tradeok(struct map_session_data *sd) void trade_tradeok(struct map_session_data *sd)
{ {
struct map_session_data *target_sd; struct map_session_data *target_sd;
@ -456,9 +472,10 @@ void trade_tradeok(struct map_session_data *sd)
clif_tradedeal_lock(target_sd, 1); clif_tradedeal_lock(target_sd, 1);
} }
/*========================================== /**
* 'Cancel' is pressed. (or trade was force-cancelled by the code) * 'Cancel' is pressed. (or trade was force-cancelled by the code)
*------------------------------------------*/ * @param sd : Player that pressed the button
*/
void trade_tradecancel(struct map_session_data *sd) void trade_tradecancel(struct map_session_data *sd)
{ {
struct map_session_data *target_sd; struct map_session_data *target_sd;
@ -515,9 +532,11 @@ void trade_tradecancel(struct map_session_data *sd)
clif_tradecancelled(target_sd); clif_tradecancelled(target_sd);
} }
/*========================================== /**
* Execute the trade
* lock sd and tsd trade data, execute the trade, clear, then save players * lock sd and tsd trade data, execute the trade, clear, then save players
*------------------------------------------*/ * @param sd : Player that has click on trade button
*/
void trade_tradecommit(struct map_session_data *sd) void trade_tradecommit(struct map_session_data *sd)
{ {
struct map_session_data *tsd; struct map_session_data *tsd;

View File

@ -42,30 +42,43 @@
#include <string.h> #include <string.h>
const short dirx[8]={0,-1,-1,-1,0,1,1,1}; // Directions values
const short diry[8]={1,1,0,-1,-1,-1,0,1}; // 1 0 7
// 2 . 6
struct unit_data* unit_bl2ud(struct block_list *bl) // 3 4 5
{ const short dirx[8]={0,-1,-1,-1,0,1,1,1}; ///lookup to know where will move to x according dir
if( bl == NULL) return NULL; const short diry[8]={1,1,0,-1,-1,-1,0,1}; ///lookup to know where will move to y according dir
if( bl->type == BL_PC) return &((struct map_session_data*)bl)->ud;
if( bl->type == BL_MOB) return &((struct mob_data*)bl)->ud;
if( bl->type == BL_PET) return &((struct pet_data*)bl)->ud;
if( bl->type == BL_NPC) return &((struct npc_data*)bl)->ud;
if( bl->type == BL_HOM) return &((struct homun_data*)bl)->ud;
if( bl->type == BL_MER) return &((struct mercenary_data*)bl)->ud;
if( bl->type == BL_ELEM) return &((struct elemental_data*)bl)->ud;
return NULL;
}
//early declaration
static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data); static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data);
static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data); static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data);
/** /**
* Tells a unit to walk to a specific coordinate * Get the unit_data related to the bl
* @param bl: Unit to walk [ALL] * @param bl : Object to get the unit_data from \n
* @return 1: Success 0: Fail * valid type are : BL_PC|BL_MOB|BL_PET|BL_NPC|BL_HOM|BL_MER|BL_ELEM
**/ * @return unit_data of bl or NULL
*/
struct unit_data* unit_bl2ud(struct block_list *bl)
{
if( bl == NULL) return NULL;
switch(bl->type){
case BL_PC: return &((struct map_session_data*)bl)->ud;
case BL_MOB: return &((struct mob_data*)bl)->ud;
case BL_PET: return &((struct pet_data*)bl)->ud;
case BL_NPC: return &((struct npc_data*)bl)->ud;
case BL_HOM: return &((struct homun_data*)bl)->ud;
case BL_MER: return &((struct mercenary_data*)bl)->ud;
case BL_ELEM: return &((struct elemental_data*)bl)->ud;
default : return NULL;
}
}
/**
* Tells a unit to walk to a specific coordinate
* @param bl: Unit to walk [ALL]
* @return 1: Success 0: Fail
*/
int unit_walktoxy_sub(struct block_list *bl) int unit_walktoxy_sub(struct block_list *bl)
{ {
int i; int i;
@ -120,10 +133,10 @@ int unit_walktoxy_sub(struct block_list *bl)
/** /**
* Retrieve the direct master of a bl if one exists. * Retrieve the direct master of a bl if one exists.
* @param bl: char to get his master [HOM|ELEM|PET|MER] * @param bl: char to get his master [HOM|ELEM|PET|MER]
* @return map_session_data of master or NULL * @return map_session_data of master or NULL
**/ */
TBL_PC* unit_get_master(struct block_list *bl) TBL_PC* unit_get_master(struct block_list *bl)
{ {
if(bl) if(bl)
@ -137,10 +150,10 @@ TBL_PC* unit_get_master(struct block_list *bl)
} }
/** /**
* Retrieve a unit's master's teleport timer * Retrieve a unit's master's teleport timer
* @param bl: char to get his master's teleport timer [HOM|ELEM|PET|MER] * @param bl: char to get his master's teleport timer [HOM|ELEM|PET|MER]
* @return timer or NULL * @return timer or NULL
**/ */
int* unit_get_masterteleport_timer(struct block_list *bl) int* unit_get_masterteleport_timer(struct block_list *bl)
{ {
if(bl) if(bl)
@ -154,14 +167,14 @@ int* unit_get_masterteleport_timer(struct block_list *bl)
} }
/** /**
* Warps a unit to its master master has gone out of site (3 second default) \n * Warps a unit to its master master has gone out of site (3 second default) \n
* Can be any object with a master [MOB|PET|HOM|MER|ELEM] * Can be any object with a master [MOB|PET|HOM|MER|ELEM]
* @param tid: Timer * @param tid: Timer
* @param tick: tick (unused) * @param tick: tick (unused)
* @param id: Unit to warp * @param id: Unit to warp
* @param data: Data transferred from timer call * @param data: Data transferred from timer call
* @return 0 * @return 0
**/ */
int unit_teleport_timer(int tid, unsigned int tick, int id, intptr_t data) int unit_teleport_timer(int tid, unsigned int tick, int id, intptr_t data)
{ {
struct block_list *bl = map_id2bl(id); struct block_list *bl = map_id2bl(id);
@ -184,11 +197,11 @@ int unit_teleport_timer(int tid, unsigned int tick, int id, intptr_t data)
} }
/** /**
* Checks if a slave unit is outside their max distance from master \n * Checks if a slave unit is outside their max distance from master \n
* If so, starts a timer for (default: 3 seconds) which will teleport the unit back to master * If so, starts a timer for (default: 3 seconds) which will teleport the unit back to master
* @param sbl: Object with a master [MOB|PET|HOM|MER|ELEM] * @param sbl: Object with a master [MOB|PET|HOM|MER|ELEM]
* @return 0 * @return 0
**/ */
int unit_check_start_teleport_timer(struct block_list *sbl) int unit_check_start_teleport_timer(struct block_list *sbl)
{ {
TBL_PC *msd = unit_get_master(sbl); TBL_PC *msd = unit_get_master(sbl);
@ -217,13 +230,13 @@ int unit_check_start_teleport_timer(struct block_list *sbl)
} }
/** /**
* Defines when to refresh the walking character to object and restart the timer if applicable \n * Defines when to refresh the walking character to object and restart the timer if applicable \n
* Also checks for speed update, target location, and slave teleport timers * Also checks for speed update, target location, and slave teleport timers
* @param tid: Timer ID * @param tid: Timer ID
* @param tick: Current tick to decide next timer update * @param tick: Current tick to decide next timer update
* @param data: Data used in timer calls * @param data: Data used in timer calls
* @return 0 or unit_walktoxy_sub() * @return 0 or unit_walktoxy_sub()
**/ */
static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data) static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data)
{ {
int i; int i;
@ -388,13 +401,13 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
} }
/** /**
* Delays an xy timer * Delays an xy timer
* @param tid: Timer ID * @param tid: Timer ID
* @param tick: Unused * @param tick: Unused
* @param id: ID of bl to delay timer on * @param id: ID of bl to delay timer on
* @param data: Data used in timer calls * @param data: Data used in timer calls
* @return 1: Success 0: Fail (No valid bl) * @return 1: Success 0: Fail (No valid bl)
**/ */
int unit_delay_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data) int unit_delay_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data)
{ {
struct block_list *bl = map_id2bl(id); struct block_list *bl = map_id2bl(id);
@ -406,13 +419,13 @@ int unit_delay_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data)
} }
/** /**
* Delays an walk-to-bl timer * Delays an walk-to-bl timer
* @param tid: Timer ID * @param tid: Timer ID
* @param tick: Unused * @param tick: Unused
* @param id: ID of bl to delay timer on * @param id: ID of bl to delay timer on
* @param data: Data used in timer calls (target bl) * @param data: Data used in timer calls (target bl)
* @return 1: Success 0: Fail (No valid bl or target) * @return 1: Success 0: Fail (No valid bl or target)
**/ */
int unit_delay_walktobl_timer(int tid, unsigned int tick, int id, intptr_t data) int unit_delay_walktobl_timer(int tid, unsigned int tick, int id, intptr_t data)
{ {
struct block_list *bl = map_id2bl(id), *tbl = map_id2bl(data); struct block_list *bl = map_id2bl(id), *tbl = map_id2bl(data);
@ -428,17 +441,17 @@ int unit_delay_walktobl_timer(int tid, unsigned int tick, int id, intptr_t data)
} }
/** /**
* Begins the function of walking a unit to an x,y location \n * Begins the function of walking a unit to an x,y location \n
* This is where the path searches and unit can_move checks are done * This is where the path searches and unit can_move checks are done
* @param bl: Object to send to x,y coordinate * @param bl: Object to send to x,y coordinate
* @param x: X coordinate where the object will be walking to * @param x: X coordinate where the object will be walking to
* @param y: Y coordinate where the object will be walking to * @param y: Y coordinate where the object will be walking to
* @param flag: Parameter to decide how to walk \n * @param flag: Parameter to decide how to walk \n
* &1: Easy walk (fail if CELL_CHKNOPASS is in direct path) \n * &1: Easy walk (fail if CELL_CHKNOPASS is in direct path) \n
* &2: Force walking (override can_move) \n * &2: Force walking (override can_move) \n
* &4: Delay walking for can_move * &4: Delay walking for can_move
* @return 1: Success 0: Fail or unit_walktoxy_sub() * @return 1: Success 0: Fail or unit_walktoxy_sub()
**/ */
int unit_walktoxy( struct block_list *bl, short x, short y, int flag) int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
{ {
struct unit_data* ud = NULL; struct unit_data* ud = NULL;
@ -496,11 +509,11 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
} }
/** /**
* Sets a mob's CHASE/FOLLOW state \n * Sets a mob's CHASE/FOLLOW state \n
* This should not be done if there's no path to reach * This should not be done if there's no path to reach
* @param bl: Mob to set state on * @param bl: Mob to set state on
* @param flag: Whether to set state or not * @param flag: Whether to set state or not
**/ */
static inline void set_mobstate(struct block_list* bl, int flag) static inline void set_mobstate(struct block_list* bl, int flag)
{ {
struct mob_data* md = BL_CAST(BL_MOB,bl); struct mob_data* md = BL_CAST(BL_MOB,bl);
@ -510,13 +523,13 @@ static inline void set_mobstate(struct block_list* bl, int flag)
} }
/** /**
* Timer to walking a unit to another unit's location \n * Timer to walking a unit to another unit's location \n
* Calls unit_walktoxy_sub once determined the unit can move * Calls unit_walktoxy_sub once determined the unit can move
* @param tid: Object's timer ID * @param tid: Object's timer ID
* @param id: Object's ID * @param id: Object's ID
* @param data: Data passed through timer function (target) * @param data: Data passed through timer function (target)
* @return 0 * @return 0
**/ */
static int unit_walktobl_sub(int tid, unsigned int tick, int id, intptr_t data) static int unit_walktobl_sub(int tid, unsigned int tick, int id, intptr_t data)
{ {
struct block_list *bl = map_id2bl(id); struct block_list *bl = map_id2bl(id);
@ -534,15 +547,15 @@ static int unit_walktobl_sub(int tid, unsigned int tick, int id, intptr_t data)
} }
/** /**
* Tells a unit to walk to a target's location (chase) * Tells a unit to walk to a target's location (chase)
* @param bl: Object that is walking to target * @param bl: Object that is walking to target
* @param tbl: Target object * @param tbl: Target object
* @param range: How close to get to target (or attack range if flag&2) * @param range: How close to get to target (or attack range if flag&2)
* @param flag: Extra behaviour \n * @param flag: Extra behaviour \n
* &1: Use hard path seek (obstacles will be walked around if possible) \n * &1: Use hard path seek (obstacles will be walked around if possible) \n
* &2: Start attacking upon arrival within range, otherwise just walk to target * &2: Start attacking upon arrival within range, otherwise just walk to target
* @return 1: Started walking or set timer 0: Failed * @return 1: Started walking or set timer 0: Failed
**/ */
int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int flag) int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int flag)
{ {
struct unit_data *ud = NULL; struct unit_data *ud = NULL;
@ -601,10 +614,10 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
} }
/** /**
* Set a unit to run, checking for obstacles * Set a unit to run, checking for obstacles
* @param bl: Object that is running * @param bl: Object that is running
* @return 1: Success 0: Fail * @return 1: Success 0: Fail
**/ */
int unit_run(struct block_list *bl) int unit_run(struct block_list *bl)
{ {
struct status_change *sc = status_get_sc(bl); struct status_change *sc = status_get_sc(bl);
@ -675,12 +688,13 @@ int unit_run(struct block_list *bl)
return 1; return 1;
} }
/** [Jobbie/3CeAM] \n /**
* Exclusive function used for Wug Dash * Char movement with wugdash
* @param bl: Object that is dashing * @author [Jobbie/3CeAM]
* @param sd: Player * @param bl: Object that is dashing
* @return 1: Success 0: Fail * @param sd: Player
**/ * @return 1: Success 0: Fail
*/
int unit_wugdash(struct block_list *bl, struct map_session_data *sd) int unit_wugdash(struct block_list *bl, struct map_session_data *sd)
{ {
struct status_change *sc = status_get_sc(bl); struct status_change *sc = status_get_sc(bl);
@ -690,7 +704,7 @@ int unit_wugdash(struct block_list *bl, struct map_session_data *sd)
if (!(sc && sc->data[SC_WUGDASH])) if (!(sc && sc->data[SC_WUGDASH]))
return 0; return 0;
nullpo_ret(sd); nullpo_ret(sd); //FIXME do we really need that check since we rechecking afterward
nullpo_ret(bl); nullpo_ret(bl);
if (!unit_can_move(bl)) { if (!unit_can_move(bl)) {
@ -746,12 +760,12 @@ int unit_wugdash(struct block_list *bl, struct map_session_data *sd)
} }
/** /**
* Makes unit attempt to run away from target using hard paths * Makes unit attempt to run away from target using hard paths
* @param bl: Object that is running away from target * @param bl: Object that is running away from target
* @param target: Target * @param target: Target
* @param dist: How far bl should run * @param dist: How far bl should run
* @return 1: Success 0: Fail * @return 1: Success 0: Fail
**/ */
int unit_escape(struct block_list *bl, struct block_list *target, short dist) int unit_escape(struct block_list *bl, struct block_list *target, short dist)
{ {
uint8 dir = map_calc_dir(target, bl->x, bl->y); uint8 dir = map_calc_dir(target, bl->x, bl->y);
@ -761,14 +775,14 @@ int unit_escape(struct block_list *bl, struct block_list *target, short dist)
} }
/** /**
* Instant warps a unit to x,y coordinate * Instant warps a unit to x,y coordinate
* @param bl: Object to instant warp * @param bl: Object to instant warp
* @param dst_x: X coordinate to warp to * @param dst_x: X coordinate to warp to
* @param dst_y: Y coordinate to warp to * @param dst_y: Y coordinate to warp to
* @param easy: Easy(1) or Hard(0) path check (hard attempts to go around obstacles) * @param easy: Easy(1) or Hard(0) path check (hard attempts to go around obstacles)
* @param checkpath: Whether or not to do a cell and path check for NOPASS and NOREACH * @param checkpath: Whether or not to do a cell and path check for NOPASS and NOREACH
* @return 1: Success 0: Fail * @return 1: Success 0: Fail
**/ */
int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath) int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath)
{ {
short dx,dy; short dx,dy;
@ -833,11 +847,11 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool
} }
/** /**
* Sets direction of a unit * Sets direction of a unit
* @param bl: Object to set direction * @param bl: Object to set direction
* @param dir: Direction (0-7) * @param dir: Direction (0-7)
* @return 0 * @return 0
**/ */
int unit_setdir(struct block_list *bl,unsigned char dir) int unit_setdir(struct block_list *bl,unsigned char dir)
{ {
struct unit_data *ud; struct unit_data *ud;
@ -852,10 +866,10 @@ int unit_setdir(struct block_list *bl,unsigned char dir)
} }
/** /**
* Gets direction of a unit * Gets direction of a unit
* @param bl: Object to get direction * @param bl: Object to get direction
* @return direction (0-7) * @return direction (0-7)
**/ */
uint8 unit_getdir(struct block_list *bl) uint8 unit_getdir(struct block_list *bl)
{ {
struct unit_data *ud; struct unit_data *ud;
@ -866,15 +880,15 @@ uint8 unit_getdir(struct block_list *bl)
} }
/** /**
* Pushes a unit in a direction by a given amount of cells \n * Pushes a unit in a direction by a given amount of cells \n
* There is no path check, only map cell restrictions are respected * There is no path check, only map cell restrictions are respected
* @param bl: Object to push * @param bl: Object to push
* @param dx: Destination cell X * @param dx: Destination cell X
* @param dy: Destination cell Y * @param dy: Destination cell Y
* @param count: How many cells to push bl * @param count: How many cells to push bl
* @param flag: Whether or not to send position packet updates * @param flag: Whether or not to send position packet updates
* @return count (can be modified due to map cell restrictions) * @return count (can be modified due to map cell restrictions)
**/ */
int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag) int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
{ {
if(count) { if(count) {
@ -934,16 +948,16 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
} }
/** /**
* Warps a unit to a map/position \n * Warps a unit to a map/position \n
* pc_setpos is used for player warping \n * pc_setpos is used for player warping \n
* This function checks for "no warp" map flags, so it's safe to call without doing nowarpto/nowarp checks * This function checks for "no warp" map flags, so it's safe to call without doing nowarpto/nowarp checks
* @param bl: Object to warp * @param bl: Object to warp
* @param m: Map ID from bl structure (NOT index) * @param m: Map ID from bl structure (NOT index)
* @param x: Destination cell X * @param x: Destination cell X
* @param y: Destination cell Y * @param y: Destination cell Y
* @param type: Clear type used in clif_clearunit_area() * @param type: Clear type used in clif_clearunit_area()
* @return Success(0); Failed(1); Error(2); unit_remove_map() Failed(3); map_addblock Failed(4) * @return Success(0); Failed(1); Error(2); unit_remove_map() Failed(3); map_addblock Failed(4)
**/ */
int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type) int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
{ {
struct unit_data *ud; struct unit_data *ud;
@ -1011,15 +1025,15 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
} }
/** /**
* Stops a unit from walking * Stops a unit from walking
* @param bl: Object to stop walking * @param bl: Object to stop walking
* @param type: Options \n * @param type: Options \n
* &0x1: Issue a fixpos packet afterwards \n * &0x1: Issue a fixpos packet afterwards \n
* &0x2: Force the unit to move one cell if it hasn't yet \n * &0x2: Force the unit to move one cell if it hasn't yet \n
* &0x4: Enable moving to the next cell when unit was already half-way there \n * &0x4: Enable moving to the next cell when unit was already half-way there \n
* (may cause on-touch/place side-effects, such as a scripted map change) * (may cause on-touch/place side-effects, such as a scripted map change)
* @return Success(1); Failed(0); * @return Success(1); Failed(0);
**/ */
int unit_stop_walking(struct block_list *bl,int type) int unit_stop_walking(struct block_list *bl,int type)
{ {
struct unit_data *ud; struct unit_data *ud;
@ -1064,13 +1078,13 @@ int unit_stop_walking(struct block_list *bl,int type)
} }
/** /**
* Initiates a skill use by a unit * Initiates a skill use by a unit
* @param src: Source object initiating skill use * @param src: Source object initiating skill use
* @param target_id: Target ID (bl->id) * @param target_id: Target ID (bl->id)
* @param skill_id: Skill ID * @param skill_id: Skill ID
* @param skill_lv: Skill Level * @param skill_lv: Skill Level
* @return unit_skilluse_id2() * @return unit_skilluse_id2()
**/ */
int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv) int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv)
{ {
return unit_skilluse_id2( return unit_skilluse_id2(
@ -1081,10 +1095,10 @@ int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uin
} }
/** /**
* Checks if a unit is walking * Checks if a unit is walking
* @param bl: Object to check walk status * @param bl: Object to check walk status
* @return Walking(1); Not Walking(0) * @return Walking(1); Not Walking(0)
**/ */
int unit_is_walking(struct block_list *bl) int unit_is_walking(struct block_list *bl)
{ {
struct unit_data *ud = unit_bl2ud(bl); struct unit_data *ud = unit_bl2ud(bl);
@ -1093,13 +1107,14 @@ int unit_is_walking(struct block_list *bl)
return (ud->walktimer != INVALID_TIMER); return (ud->walktimer != INVALID_TIMER);
} }
/** [Skotlex] \n /**
* Checks if a unit is able to move based on status changes \n * Checks if a unit is able to move based on status changes \n
* View the StatusChangeStateTable in status.c for a list of statuses \n * View the StatusChangeStateTable in status.c for a list of statuses \n
* Some statuses are still checked here due too specific variables * Some statuses are still checked here due too specific variables
* @param bl: Object to check * @author [Skotlex]
* @return Can move(1); Can't move(0) * @param bl: Object to check
**/ * @return Can move(1); Can't move(0)
*/
int unit_can_move(struct block_list *bl) { int unit_can_move(struct block_list *bl) {
struct map_session_data *sd; struct map_session_data *sd;
struct unit_data *ud; struct unit_data *ud;
@ -1150,12 +1165,12 @@ int unit_can_move(struct block_list *bl) {
} }
/** /**
* Resumes running (RA_WUGDASH or TK_RUN) after a walk delay * Resumes running (RA_WUGDASH or TK_RUN) after a walk delay
* @param tid: Timer ID * @param tid: Timer ID
* @param id: Object ID * @param id: Object ID
* @param data: Data passed through timer function (unit_data) * @param data: Data passed through timer function (unit_data)
* @return 0 * @return 0
**/ */
int unit_resume_running(int tid, unsigned int tick, int id, intptr_t data) int unit_resume_running(int tid, unsigned int tick, int id, intptr_t data)
{ {
@ -1176,15 +1191,15 @@ int unit_resume_running(int tid, unsigned int tick, int id, intptr_t data)
} }
/** /**
* Applies a walk delay to a unit * Applies a walk delay to a unit
* @param bl: Object to apply walk delay to * @param bl: Object to apply walk delay to
* @param tick: Current tick * @param tick: Current tick
* @param delay: Amount of time to set walk delay * @param delay: Amount of time to set walk delay
* @param type: Type of delay \n * @param type: Type of delay \n
* 0: Damage induced delay; Do not change previous delay \n * 0: Damage induced delay; Do not change previous delay \n
* 1: Skill induced delay; Walk delay can only be increased, not decreased * 1: Skill induced delay; Walk delay can only be increased, not decreased
* @return Success(1); Fail(0); * @return Success(1); Fail(0);
**/ */
int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int type) int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int type)
{ {
struct unit_data *ud = unit_bl2ud(bl); struct unit_data *ud = unit_bl2ud(bl);
@ -1221,15 +1236,15 @@ int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int
} }
/** /**
* Performs checks for a unit using a skill and executes after cast time completion * Performs checks for a unit using a skill and executes after cast time completion
* @param src: Object using skill * @param src: Object using skill
* @param target_id: Target ID (bl->id) * @param target_id: Target ID (bl->id)
* @param skill_id: Skill ID * @param skill_id: Skill ID
* @param skill_lv: Skill Level * @param skill_lv: Skill Level
* @param casttime: Initial cast time before cast time reductions * @param casttime: Initial cast time before cast time reductions
* @param castcancel: Whether or not the skill can be cancelled by interuption (hit) * @param castcancel: Whether or not the skill can be cancelled by interuption (hit)
* @return Success(1); Fail(0); * @return Success(1); Fail(0);
**/ */
int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel) int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel)
{ {
struct unit_data *ud; struct unit_data *ud;
@ -1584,14 +1599,14 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
} }
/** /**
* Initiates a placement (ground/non-targeted) skill * Initiates a placement (ground/non-targeted) skill
* @param src: Object using skill * @param src: Object using skill
* @param skill_x: X coordinate where skill is being casted (center) * @param skill_x: X coordinate where skill is being casted (center)
* @param skill_y: Y coordinate where skill is being casted (center) * @param skill_y: Y coordinate where skill is being casted (center)
* @param skill_id: Skill ID * @param skill_id: Skill ID
* @param skill_lv: Skill Level * @param skill_lv: Skill Level
* @return unit_skilluse_pos2() * @return unit_skilluse_pos2()
**/ */
int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv) int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv)
{ {
return unit_skilluse_pos2( return unit_skilluse_pos2(
@ -1602,16 +1617,16 @@ int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, uint
} }
/** /**
* Performs checks for a unit using a skill and executes after cast time completion * Performs checks for a unit using a skill and executes after cast time completion
* @param src: Object using skill * @param src: Object using skill
* @param skill_x: X coordinate where skill is being casted (center) * @param skill_x: X coordinate where skill is being casted (center)
* @param skill_y: Y coordinate where skill is being casted (center) * @param skill_y: Y coordinate where skill is being casted (center)
* @param skill_id: Skill ID * @param skill_id: Skill ID
* @param skill_lv: Skill Level * @param skill_lv: Skill Level
* @param casttime: Initial cast time before cast time reductions * @param casttime: Initial cast time before cast time reductions
* @param castcancel: Whether or not the skill can be cancelled by interuption (hit) * @param castcancel: Whether or not the skill can be cancelled by interuption (hit)
* @return Success(1); Fail(0); * @return Success(1); Fail(0);
**/ */
int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel) int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel)
{ {
struct map_session_data *sd = NULL; struct map_session_data *sd = NULL;
@ -1747,11 +1762,11 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
} }
/** /**
* Update a unit's attack target * Update a unit's attack target
* @param ud: Unit data * @param ud: Unit data
* @param target_id: Target ID (bl->id) * @param target_id: Target ID (bl->id)
* @return 0 * @return 0
**/ */
int unit_set_target(struct unit_data* ud, int target_id) int unit_set_target(struct unit_data* ud, int target_id)
{ {
struct unit_data * ux; struct unit_data * ux;
@ -1771,10 +1786,10 @@ int unit_set_target(struct unit_data* ud, int target_id)
} }
/** /**
* Stop a unit's attacks * Stop a unit's attacks
* @param bl: Object to stop * @param bl: Object to stop
* @return 0 * @return 0
**/ */
int unit_stop_attack(struct block_list *bl) int unit_stop_attack(struct block_list *bl)
{ {
struct unit_data *ud = unit_bl2ud(bl); struct unit_data *ud = unit_bl2ud(bl);
@ -1790,10 +1805,10 @@ int unit_stop_attack(struct block_list *bl)
} }
/** /**
* Removes a unit's target due to being unattackable * Removes a unit's target due to being unattackable
* @param bl: Object to unlock target * @param bl: Object to unlock target
* @return 0 * @return 0
**/ */
int unit_unattackable(struct block_list *bl) int unit_unattackable(struct block_list *bl)
{ {
struct unit_data *ud = unit_bl2ud(bl); struct unit_data *ud = unit_bl2ud(bl);
@ -1810,12 +1825,12 @@ int unit_unattackable(struct block_list *bl)
} }
/** /**
* Requests a unit to attack a target * Requests a unit to attack a target
* @param src: Object initiating attack * @param src: Object initiating attack
* @param target_id: Target ID (bl->id) * @param target_id: Target ID (bl->id)
* @param continuous: Whether or not the attack is ongoing * @param continuous: Whether or not the attack is ongoing
* @return Success(0); Fail(1); * @return Success(0); Fail(1);
**/ */
int unit_attack(struct block_list *src,int target_id,int continuous) int unit_attack(struct block_list *src,int target_id,int continuous)
{ {
struct block_list *target; struct block_list *target;
@ -1867,12 +1882,13 @@ int unit_attack(struct block_list *src,int target_id,int continuous)
return 0; return 0;
} }
/** [Skotlex] \n /**
* Cancels an ongoing combo, resets attackable time, and restarts the \n * Cancels an ongoing combo, resets attackable time, and restarts the \n
* attack timer to resume attack after amotion time * attack timer to resume attack after amotion time
* @param bl: Object to cancel combo * @author [Skotlex]
* @return Success(1); Fail(0); * @param bl: Object to cancel combo
**/ * @return Success(1); Fail(0);
*/
int unit_cancel_combo(struct block_list *bl) int unit_cancel_combo(struct block_list *bl)
{ {
struct unit_data *ud; struct unit_data *ud;
@ -1894,13 +1910,13 @@ int unit_cancel_combo(struct block_list *bl)
} }
/** /**
* Does a path_search to check if a position can be reached * Does a path_search to check if a position can be reached
* @param bl: Object to check path * @param bl: Object to check path
* @param x: X coordinate that will be path searched * @param x: X coordinate that will be path searched
* @param y: Y coordinate that will be path searched * @param y: Y coordinate that will be path searched
* @param easy: Easy(1) or Hard(0) path check (hard attempts to go around obstacles) * @param easy: Easy(1) or Hard(0) path check (hard attempts to go around obstacles)
* @return true or false * @return true or false
**/ */
bool unit_can_reach_pos(struct block_list *bl,int x,int y, int easy) bool unit_can_reach_pos(struct block_list *bl,int x,int y, int easy)
{ {
nullpo_retr(false, bl); nullpo_retr(false, bl);
@ -1912,15 +1928,15 @@ bool unit_can_reach_pos(struct block_list *bl,int x,int y, int easy)
} }
/** /**
* Does a path_search to check if a unit can be reached * Does a path_search to check if a unit can be reached
* @param bl: Object to check path * @param bl: Object to check path
* @param tbl: Target to be checked for available path * @param tbl: Target to be checked for available path
* @param range: The number of cells away from bl that the path should be checked * @param range: The number of cells away from bl that the path should be checked
* @param easy: Easy(1) or Hard(0) path check (hard attempts to go around obstacles) * @param easy: Easy(1) or Hard(0) path check (hard attempts to go around obstacles)
* @param x: Pointer storing a valid X coordinate around tbl that can be reached * @param x: Pointer storing a valid X coordinate around tbl that can be reached
* @param y: Pointer storing a valid Y coordinate around tbl that can be reached * @param y: Pointer storing a valid Y coordinate around tbl that can be reached
* @return true or false * @return true or false
**/ */
bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range, int easy, short *x, short *y) bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range, int easy, short *x, short *y)
{ {
int i; int i;
@ -1956,13 +1972,13 @@ bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range,
} }
/** /**
* Calculates position of Pet/Mercenary/Homunculus/Elemental * Calculates position of Pet/Mercenary/Homunculus/Elemental
* @param bl: Object to calculate position * @param bl: Object to calculate position
* @param tx: X coordinate to go to * @param tx: X coordinate to go to
* @param ty: Y coordinate to go to * @param ty: Y coordinate to go to
* @param dir: Direction which to be 2 cells from master's position * @param dir: Direction which to be 2 cells from master's position
* @return Success(0); Fail(1); * @return Success(0); Fail(1);
**/ */
int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir) int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
{ {
int dx, dy, x, y, i, k; int dx, dy, x, y, i, k;
@ -2014,12 +2030,12 @@ int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
} }
/** /**
* Function timer to continuously attack * Function timer to continuously attack
* @param src: Object to continuously attack * @param src: Object to continuously attack
* @param tid: Timer ID * @param tid: Timer ID
* @param tick: Current tick * @param tick: Current tick
* @return Attackable(1); Unattackable(0); * @return Attackable(1); Unattackable(0);
**/ */
static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int tick) static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int tick)
{ {
struct block_list *target; struct block_list *target;
@ -2153,13 +2169,13 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
} }
/** /**
* Timer function to cancel attacking if unit has become unattackable * Timer function to cancel attacking if unit has become unattackable
* @param tid: Timer ID * @param tid: Timer ID
* @param tick: Current tick * @param tick: Current tick
* @param id: Object to cancel attack if applicable * @param id: Object to cancel attack if applicable
* @param data: Data passed from timer call * @param data: Data passed from timer call
* @return 0 * @return 0
**/ */
static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data) static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data)
{ {
struct block_list *bl; struct block_list *bl;
@ -2170,13 +2186,13 @@ static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data)
} }
/** /**
* Cancels a skill's cast * Cancels a skill's cast
* @param bl: Object to cancel cast * @param bl: Object to cancel cast
* @param type: Cancel check flag \n * @param type: Cancel check flag \n
* &1: Cast-Cancel invoked \n * &1: Cast-Cancel invoked \n
* &2: Cancel only if skill is cancellable * &2: Cancel only if skill is cancellable
* @return Success(1); Fail(0); * @return Success(1); Fail(0);
**/ */
int unit_skillcastcancel(struct block_list *bl,int type) int unit_skillcastcancel(struct block_list *bl,int type)
{ {
struct map_session_data *sd = NULL; struct map_session_data *sd = NULL;
@ -2233,9 +2249,9 @@ int unit_skillcastcancel(struct block_list *bl,int type)
} }
/** /**
* Initialized data on a unit * Initialized data on a unit
* @param bl: Object to initialize data on * @param bl: Object to initialize data on
**/ */
void unit_dataset(struct block_list *bl) void unit_dataset(struct block_list *bl)
{ {
struct unit_data *ud; struct unit_data *ud;
@ -2252,10 +2268,10 @@ void unit_dataset(struct block_list *bl)
} }
/** /**
* Gets the number of units attacking another unit * Gets the number of units attacking another unit
* @param bl: Object to check amount of targets * @param bl: Object to check amount of targets
* @return number of targets or 0 * @return number of targets or 0
**/ */
int unit_counttargeted(struct block_list* bl) int unit_counttargeted(struct block_list* bl)
{ {
struct unit_data* ud; struct unit_data* ud;
@ -2265,24 +2281,11 @@ int unit_counttargeted(struct block_list* bl)
} }
/** /**
* Is this even used? Why is it a function? * Changes the size of a unit
**/ * @param bl: Object to change size [PC|MOB]
int unit_fixdamage(struct block_list *src,struct block_list *target,unsigned int tick,int sdelay,int ddelay,int64 damage,int div,int type,int64 damage2) * @param size: New size of bl
{ * @return 0
nullpo_ret(target); */
if(damage+damage2 <= 0)
return 0;
return status_fix_damage(src,target,damage+damage2,clif_damage(target,target,tick,sdelay,ddelay,damage,div,type,damage2));
}
/**
* Changes the size of a unit
* @param bl: Object to change size [PC|MOB]
* @param size: New size of bl
* @return 0
**/
int unit_changeviewsize(struct block_list *bl,short size) int unit_changeviewsize(struct block_list *bl,short size)
{ {
nullpo_ret(bl); nullpo_ret(bl);
@ -2301,15 +2304,15 @@ int unit_changeviewsize(struct block_list *bl,short size)
} }
/** /**
* Removes a bl/ud from the map \n * Removes a bl/ud from the map \n
* On kill specifics are not performed here, check status_damage() * On kill specifics are not performed here, check status_damage()
* @param bl: Object to remove from map * @param bl: Object to remove from map
* @param clrtype: How bl is being removed \n * @param clrtype: How bl is being removed \n
* 0: Assume bl is being warped \n * 0: Assume bl is being warped \n
* 1: Death, appropriate cleanup performed * 1: Death, appropriate cleanup performed
* @param file, line, func: Call information for debug purposes * @param file, line, func: Call information for debug purposes
* @return Success(1); Couldn't be removed or bl was free'd(0) * @return Success(1); Couldn't be removed or bl was free'd(0)
**/ */
int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, int line, const char* func) int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, int line, const char* func)
{ {
struct unit_data *ud = unit_bl2ud(bl); struct unit_data *ud = unit_bl2ud(bl);
@ -2537,12 +2540,12 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
} }
/** /**
* Removes units of a master when the master is removed from map * Removes units of a master when the master is removed from map
* @param sd: Player * @param sd: Player
* @param clrtype: How bl is being removed \n * @param clrtype: How bl is being removed \n
* 0: Assume bl is being warped \n * 0: Assume bl is being warped \n
* 1: Death, appropriate cleanup performed * 1: Death, appropriate cleanup performed
**/ */
void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype) void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype)
{ {
unit_remove_map(&sd->bl,clrtype); unit_remove_map(&sd->bl,clrtype);
@ -2560,9 +2563,10 @@ void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype)
} }
/** /**
* Frees units of a master when the master is removed from map * Frees units of a player when is removed from map
* @param sd: Player * Also free his pets/homon/mercenary/elemental/etc if he have any
**/ * @param sd: Player
*/
void unit_free_pc(struct map_session_data *sd) void unit_free_pc(struct map_session_data *sd)
{ {
if (sd->pd) unit_free(&sd->pd->bl,CLR_OUTSIGHT); if (sd->pd) unit_free(&sd->pd->bl,CLR_OUTSIGHT);
@ -2573,13 +2577,13 @@ void unit_free_pc(struct map_session_data *sd)
} }
/** /**
* Frees all related resources to the unit * Frees all related resources to the unit
* @param bl: Object being removed from map * @param bl: Object being removed from map
* @param clrtype: How bl is being removed \n * @param clrtype: How bl is being removed \n
* 0: Assume bl is being warped \n * 0: Assume bl is being warped \n
* 1: Death, appropriate cleanup performed * 1: Death, appropriate cleanup performed
* @return 0 * @return 0
**/ */
int unit_free(struct block_list *bl, clr_type clrtype) int unit_free(struct block_list *bl, clr_type clrtype)
{ {
struct unit_data *ud = unit_bl2ud( bl ); struct unit_data *ud = unit_bl2ud( bl );
@ -2803,8 +2807,9 @@ int unit_free(struct block_list *bl, clr_type clrtype)
} }
/** /**
* Initialization function for unit on map start * Initialization function for unit on map start
**/ * called in map::do_init
*/
int do_init_unit(void) int do_init_unit(void)
{ {
add_timer_func_list(unit_attack_timer, "unit_attack_timer"); add_timer_func_list(unit_attack_timer, "unit_attack_timer");
@ -2816,6 +2821,11 @@ int do_init_unit(void)
return 0; return 0;
} }
/**
* Unit module destructor, (thing to do before closing the module)
* called in map::do_final
* @return 0
*/
int do_final_unit(void) int do_final_unit(void)
{ {
// Nothing to do // Nothing to do

View File

@ -14,9 +14,12 @@ struct map_session_data;
#include "path.h" // struct walkpath_data #include "path.h" // struct walkpath_data
#include "skill.h" // struct skill_timerskill, struct skill_unit_group, struct skill_unit_group_tickset #include "skill.h" // struct skill_timerskill, struct skill_unit_group, struct skill_unit_group_tickset
extern const short dirx[8]; ///lookup to know where will move to x according dir
extern const short diry[8]; ///lookup to know where will move to y according dir
struct unit_data { struct unit_data {
struct block_list *bl; struct block_list *bl; ///link to owner object BL_CHAR (BL_PC|BL_HOM|BL_PET|BL_ELE|BL_MER)
struct walkpath_data walkpath; struct walkpath_data walkpath;
struct skill_timerskill *skilltimerskill[MAX_SKILLTIMERSKILL]; struct skill_timerskill *skilltimerskill[MAX_SKILLTIMERSKILL];
struct skill_unit_group *skillunit[MAX_SKILLUNITGROUP]; struct skill_unit_group *skillunit[MAX_SKILLUNITGROUP];
struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET]; struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET];
@ -78,6 +81,9 @@ int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir);
int unit_delay_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data); int unit_delay_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data);
int unit_delay_walktobl_timer(int tid, unsigned int tick, int id, intptr_t data); int unit_delay_walktobl_timer(int tid, unsigned int tick, int id, intptr_t data);
// Ranger
int unit_wugdash(struct block_list *bl, struct map_session_data *sd);
// Causes the target object to stop moving. // Causes the target object to stop moving.
int unit_stop_walking(struct block_list *bl,int type); int unit_stop_walking(struct block_list *bl,int type);
int unit_can_move(struct block_list *bl); int unit_can_move(struct block_list *bl);
@ -130,10 +136,5 @@ int unit_changeviewsize(struct block_list *bl,short size);
int do_init_unit(void); int do_init_unit(void);
int do_final_unit(void); int do_final_unit(void);
// Ranger
int unit_wugdash(struct block_list *bl, struct map_session_data *sd);
extern const short dirx[8];
extern const short diry[8];
#endif /* _UNIT_H_ */ #endif /* _UNIT_H_ */

View File

@ -20,21 +20,29 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
static int vending_nextid = 0; static int vending_nextid = 0; ///Vending_id counter
static DBMap *vending_db; static DBMap *vending_db; ///Db holder the vender : charid -> map_session_data
/**
* Lookup to get the vending_db outside module
* @return the vending_db
*/
DBMap * vending_getdb(){ DBMap * vending_getdb(){
return vending_db; return vending_db;
} }
/// Returns an unique vending shop id.
static int vending_getuid(void) /**
{ * Create an unique vending shop id.
* @return the next vending_id
*/
static int vending_getuid(void){
return ++vending_nextid; return ++vending_nextid;
} }
/*========================================== /**
* Close shop * Make a player close his shop
*------------------------------------------*/ * @param sd : player session
*/
void vending_closevending(struct map_session_data* sd) void vending_closevending(struct map_session_data* sd)
{ {
nullpo_retv(sd); nullpo_retv(sd);
@ -46,9 +54,11 @@ void vending_closevending(struct map_session_data* sd)
} }
} }
/*========================================== /**
* Request a shop's item list * Player request a shop's item list (a player shop)
*------------------------------------------*/ * @param sd : player requestion the list
* @param id : vender account id (gid)
*/
void vending_vendinglistreq(struct map_session_data* sd, int id) void vending_vendinglistreq(struct map_session_data* sd, int id)
{ {
struct map_session_data* vsd; struct map_session_data* vsd;
@ -70,9 +80,15 @@ void vending_vendinglistreq(struct map_session_data* sd, int id)
clif_vendinglist(sd, id, vsd->vending); clif_vendinglist(sd, id, vsd->vending);
} }
/*========================================== /**
* Purchase item(s) from a shop * Purchase item(s) from a shop
*------------------------------------------*/ * @param sd : buyer player session
* @param aid : account id of vender
* @param uid : shop unique id
* @param data : items data who would like to purchase \n
* data := {<index>.w <amount>.w }[count]
* @param count : number of different items he's trying to buy
*/
void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const uint8* data, int count) void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const uint8* data, int count)
{ {
int i, j, cursor, w, new_ = 0, blank, vend_list[MAX_VENDING]; int i, j, cursor, w, new_ = 0, blank, vend_list[MAX_VENDING];
@ -226,10 +242,14 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
} }
} }
/*========================================== /**
* Open shop * Player setup a new shop
* data := {<index>.w <amount>.w <value>.l}[count] * @param sd : player opening the shop
*------------------------------------------*/ * @param message : shop title
* @param data : itemlist data \n
* data := {<index>.w <amount>.w <value>.l}[count]
* @param count : number of different items
*/
void vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count) { void vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count) {
int i, j; int i, j;
int vending_skill_lvl; int vending_skill_lvl;
@ -297,8 +317,12 @@ void vending_openvending(struct map_session_data* sd, const char* message, const
idb_put(vending_db, sd->status.char_id, sd); idb_put(vending_db, sd->status.char_id, sd);
} }
/**
/// Checks if an item is being sold in given player's vending. * Checks if an item is being sold in given player's vending.
* @param sd : vender session (player)
* @param nameid : item id
* @return 0:not selling it, 1: yes
*/
bool vending_search(struct map_session_data* sd, unsigned short nameid) { bool vending_search(struct map_session_data* sd, unsigned short nameid) {
int i; int i;
@ -315,8 +339,13 @@ bool vending_search(struct map_session_data* sd, unsigned short nameid) {
} }
/// Searches for all items in a vending, that match given ids, price and possible cards.
/// @return Whether or not the search should be continued. /**
* Searches for all items in a vending, that match given ids, price and possible cards.
* @param sd : The vender session to search into
* @param s : parameter of the search (see s_search_store_search)
* @return Whether or not the search should be continued.
*/
bool vending_searchall(struct map_session_data* sd, const struct s_search_store_search* s) { bool vending_searchall(struct map_session_data* sd, const struct s_search_store_search* s) {
int i, c, slot; int i, c, slot;
unsigned int idx, cidx; unsigned int idx, cidx;
@ -367,10 +396,19 @@ bool vending_searchall(struct map_session_data* sd, const struct s_search_store_
return true; return true;
} }
/**
* Initialise the vending module
* called in map::do_init
*/
void do_final_vending(void) { void do_final_vending(void) {
db_destroy(vending_db); db_destroy(vending_db);
} }
/**
* Destory the vending module
* called in map::do_final
*/
void do_init_vending(void) { void do_init_vending(void) {
vending_db = idb_alloc(DB_OPT_BASE); vending_db = idb_alloc(DB_OPT_BASE);
vending_nextid = 0; vending_nextid = 0;

View File

@ -10,9 +10,9 @@ struct map_session_data;
struct s_search_store_search; struct s_search_store_search;
struct s_vending { struct s_vending {
short index; //cart index (return item data) short index; /// cart index (return item data)
short amount; //amout of the item for vending short amount; ///amout of the item for vending
unsigned int value; //at wich price unsigned int value; ///at wich price
}; };
DBMap * vending_getdb(); DBMap * vending_getdb();