Merge branch 'Upstream/master'
This commit is contained in:
commit
e797f085e5
@ -714,7 +714,10 @@
|
||||
714: Item Shop List: %s (%d)
|
||||
715: Point Shop List: '%s'
|
||||
716: Your '%s' now: %d
|
||||
//717-899 free
|
||||
|
||||
//Item Group
|
||||
717: [%s] has won [%s] from '%s'
|
||||
//718-899 free
|
||||
|
||||
//------------------------------------
|
||||
// More atcommands message
|
||||
@ -1517,7 +1520,7 @@
|
||||
1484: You're currently not autolooting this item type.
|
||||
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>".
|
||||
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.
|
||||
1489: Your autoloottype list is empty.
|
||||
1490: Item types on your autoloottype list:
|
||||
@ -1525,7 +1528,7 @@
|
||||
|
||||
// @dropall
|
||||
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!
|
||||
|
||||
//Banking
|
||||
|
@ -713,7 +713,10 @@
|
||||
714: Item Shop: %s (%d)
|
||||
715: Point Shop: '%s'
|
||||
716: '%s' milikmu saat ini: %d
|
||||
//717-899 kosong
|
||||
|
||||
//Item Group
|
||||
717: [%s] mendapatkan [%s] dari '%s'
|
||||
//718-899 kosong
|
||||
|
||||
|
||||
//------------------------------------
|
||||
|
320
db/const.txt
320
db/const.txt
@ -720,6 +720,7 @@ ATF_MAGIC 0x20
|
||||
ATF_MISC 0x40
|
||||
ATF_SKILL 0x60
|
||||
|
||||
//Item Group ID
|
||||
IG_BlueBox 1
|
||||
IG_VioletBox 2
|
||||
IG_CardAlbum 3
|
||||
@ -790,6 +791,321 @@ IG_CardAlbum_Shield 67
|
||||
IG_CardAlbum_Weapon 68
|
||||
IG_CardAlbum_Garment 69
|
||||
IG_Flamel_Card 70
|
||||
IG_Special_Box 71
|
||||
IG_Tresure_Box_WoE_ 72
|
||||
IG_RWC_Parti_Box 73
|
||||
IG_RWC_Final_Comp_Box 74
|
||||
IG_Gift_Bundle 75
|
||||
IG_Caracas_Ring_Box 76
|
||||
IG_Crumpled_Paper 77
|
||||
IG_Solo_Gift_Basket 78
|
||||
IG_Couple_Event_Basket 79
|
||||
IG_GM_Warp_Box 80
|
||||
IG_Fortune_Cookie1 81
|
||||
IG_Fortune_Cookie2 82
|
||||
IG_Fortune_Cookie3 83
|
||||
IG_New_Gift_Envelope 84
|
||||
IG_Passion_FB_Hat_Box 85
|
||||
IG_Cool_FB_Hat_Box 86
|
||||
IG_Victory_FB_Hat_Box 87
|
||||
IG_Glory_FB_Hat_Box 88
|
||||
IG_Passion_Hat_Box2 89
|
||||
IG_Cool_Hat_Box2 90
|
||||
IG_Victory_Hat_Box2 91
|
||||
IG_Aspersio_5_Scroll_Box 92
|
||||
IG_Pet_Egg_Scroll_Box1 93
|
||||
IG_Pet_Egg_Scroll_Box2 94
|
||||
IG_Pet_Egg_Scroll1 95
|
||||
IG_Pet_Egg_Scroll2 96
|
||||
IG_Pet_Egg_Scroll_Box3 97
|
||||
IG_Pet_Egg_Scroll_Box4 98
|
||||
IG_Pet_Egg_Scroll_Box5 99
|
||||
IG_Pet_Egg_Scroll3 100
|
||||
IG_Pet_Egg_Scroll4 101
|
||||
IG_Pet_Egg_Scroll5 102
|
||||
IG_Infiltrator_Box 103
|
||||
IG_Muramasa_Box 104
|
||||
IG_Excalibur_Box 105
|
||||
IG_Combat_Knife_Box 106
|
||||
IG_Counter_Dagger_Box 107
|
||||
IG_Kaiser_Knuckle_Box 108
|
||||
IG_Pole_Axe_Box 109
|
||||
IG_Mighty_Staff_Box 110
|
||||
IG_Right_Epsilon_Box 111
|
||||
IG_Balistar_Box 112
|
||||
IG_Diary_Of_Great_Sage_Box 113
|
||||
IG_Asura_Box 114
|
||||
IG_Apple_Of_Archer_Box 115
|
||||
IG_Bunny_Band_Box 116
|
||||
IG_Sahkkat_Box 117
|
||||
IG_Lord_Circlet_Box 118
|
||||
IG_Elven_Ears_Box 119
|
||||
IG_Steel_Flower_Box 120
|
||||
IG_Critical_Ring_Box 121
|
||||
IG_Earring_Box 122
|
||||
IG_Ring_Box 123
|
||||
IG_Necklace_Box 124
|
||||
IG_Glove_Box 125
|
||||
IG_Brooch_Box 126
|
||||
IG_Rosary_Box 127
|
||||
IG_Safety_Ring_Box 128
|
||||
IG_Vesper_Core01_Box 129
|
||||
IG_Vesper_Core02_Box 130
|
||||
IG_Vesper_Core03_Box 131
|
||||
IG_Vesper_Core04_Box 132
|
||||
IG_Pet_Egg_Scroll_Box6 133
|
||||
IG_Pet_Egg_Scroll_Box7 134
|
||||
IG_Pet_Egg_Scroll_Box8 135
|
||||
IG_Pet_Egg_Scroll_Box9 136
|
||||
IG_Pet_Egg_Scroll_Box10 137
|
||||
IG_Pet_Egg_Scroll_Box11 138
|
||||
IG_Pet_Egg_Scroll6 139
|
||||
IG_Pet_Egg_Scroll7 140
|
||||
IG_Pet_Egg_Scroll8 141
|
||||
IG_Pet_Egg_Scroll9 142
|
||||
IG_Pet_Egg_Scroll10 143
|
||||
IG_Pet_Egg_Scroll11 144
|
||||
IG_CP_Helm_Scroll_Box 145
|
||||
IG_CP_Shield_Scroll_Box 146
|
||||
IG_CP_Armor_Scroll_Box 147
|
||||
IG_CP_Weapon_Scroll_Box 148
|
||||
IG_Repair_Scroll_Box 149
|
||||
IG_Super_Pet_Egg1 150
|
||||
IG_Super_Pet_Egg2 151
|
||||
IG_Super_Pet_Egg3 152
|
||||
IG_Super_Pet_Egg4 153
|
||||
IG_Super_Card_Pet_Egg1 154
|
||||
IG_Super_Card_Pet_Egg2 155
|
||||
IG_Super_Card_Pet_Egg3 156
|
||||
IG_Super_Card_Pet_Egg4 157
|
||||
IG_Vigorgra_Package1 158
|
||||
IG_Vigorgra_Package2 159
|
||||
IG_Vigorgra_Package3 160
|
||||
IG_Vigorgra_Package4 161
|
||||
IG_Vigorgra_Package5 162
|
||||
IG_Vigorgra_Package6 163
|
||||
IG_Vigorgra_Package7 164
|
||||
IG_Vigorgra_Package8 165
|
||||
IG_Vigorgra_Package9 166
|
||||
IG_Vigorgra_Package10 167
|
||||
IG_Vigorgra_Package11 168
|
||||
IG_Vigorgra_Package12 169
|
||||
IG_Pet_Egg_Scroll12 170
|
||||
IG_Pet_Egg_Scroll13 171
|
||||
IG_Pet_Egg_Scroll14 172
|
||||
IG_Super_Pet_Egg5 173
|
||||
IG_Super_Pet_Egg6 174
|
||||
IG_Super_Pet_Egg7 175
|
||||
IG_Super_Pet_Egg8 176
|
||||
IG_Pet_Egg_Scroll_E 177
|
||||
IG_Ramen_Hat_Box 178
|
||||
IG_Mysterious_Travel_Sack1 179
|
||||
IG_Mysterious_Travel_Sack2 180
|
||||
IG_Mysterious_Travel_Sack3 181
|
||||
IG_Mysterious_Travel_Sack4 182
|
||||
IG_Magician_Card_Box 183
|
||||
IG_Acolyte_Card_Box 184
|
||||
IG_Archer_Card_Box 185
|
||||
IG_Swordman_Card_Box 186
|
||||
IG_Thief_Card_Box 187
|
||||
IG_Merchant_Card_Box 188
|
||||
IG_Hard_Core_Set_Box 189
|
||||
IG_Kitty_Set_Box 190
|
||||
IG_Soft_Core_Set_Box 191
|
||||
IG_Deviruchi_Set_Box 192
|
||||
IG_MVP_Hunt_Box 193
|
||||
IG_Brewing_Box 194
|
||||
IG_Xmas_Pet_Scroll 195
|
||||
IG_Lucky_Scroll08 196
|
||||
IG_Br_SwordPackage 197
|
||||
IG_Br_MagePackage 198
|
||||
IG_Br_AcolPackage 199
|
||||
IG_Br_ArcherPackage 200
|
||||
IG_Br_MerPackage 201
|
||||
IG_Br_ThiefPackage 202
|
||||
IG_Acidbomb_10_Box 203
|
||||
IG_Basic_Siege_Supply_Box 204
|
||||
IG_Adv_Siege_Supply_Box 205
|
||||
IG_Elite_Siege_Supply_Box 206
|
||||
IG_Sakura_Scroll 207
|
||||
IG_Beholder_Ring_Box 208
|
||||
IG_Hallow_Ring_Box 209
|
||||
IG_Clamorous_Ring_Box 210
|
||||
IG_Chemical_Ring_Box 211
|
||||
IG_Insecticide_Ring_Box 212
|
||||
IG_Fisher_Ring_Box 213
|
||||
IG_Decussate_Ring_Box 214
|
||||
IG_Bloody_Ring_Box 215
|
||||
IG_Satanic_Ring_Box 216
|
||||
IG_Dragoon_Ring_Box 217
|
||||
IG_Angel_Scroll 218
|
||||
IG_Devil_Scroll 219
|
||||
IG_Surprise_Scroll 220
|
||||
IG_July7_Scroll 221
|
||||
IG_Bacsojin_Scroll 222
|
||||
IG_Animal_Scroll 223
|
||||
IG_Heart_Scroll 224
|
||||
IG_New_Year_Scroll 225
|
||||
IG_Valentine_Pledge_Box 226
|
||||
IG_Ox_Tail_Scroll 227
|
||||
IG_Buddah_Scroll 228
|
||||
IG_Evil_Incarnation 229
|
||||
IG_F_Clover_Box_Mouth 230
|
||||
IG_Mouth_Bubble_Gum_Box 231
|
||||
IG_F_Clover_Box_Mouth2 232
|
||||
IG_F_Clover_Box_Mouth4 233
|
||||
IG_BGum_Box_In_Mouth2 234
|
||||
IG_BGum_Box_In_Mouth4 235
|
||||
IG_Tw_October_Scroll 236
|
||||
IG_My_Scroll1 237
|
||||
IG_Tw_Nov_Scroll 238
|
||||
IG_My_Scroll2 239
|
||||
IG_Pr_Reset_Stone_Box 240
|
||||
IG_FPr_Reset_Stone_Box 241
|
||||
IG_Majestic_Devil_Scroll 242
|
||||
IG_Life_Ribbon_Box 243
|
||||
IG_Life_Ribbon_Box2 244
|
||||
IG_Life_Ribbon_Box3 245
|
||||
IG_Magic_Candy_Box10 246
|
||||
IG_RWC2010_SuitcaseA 247
|
||||
IG_RWC2010_SuitcaseB 248
|
||||
IG_Sagittarius_Scroll 249
|
||||
IG_Sagittarius_Scr_Box 250
|
||||
IG_Sagittar_Diadem_Scroll 251
|
||||
IG_Sagittar_Di_Scroll_Box 252
|
||||
IG_Capri_Crown_Scroll 253
|
||||
IG_Capri_Crown_Scroll_Box 254
|
||||
IG_Capricon_Di_Scroll 255
|
||||
IG_Capricon_Di_Scroll_Box 256
|
||||
IG_Aquarius_Diadem_Scroll 257
|
||||
IG_Aquarius_Di_Scroll_Box 258
|
||||
IG_Lovely_Aquarius_Scroll 259
|
||||
IG_Lovely_Aquarius_Box 260
|
||||
IG_Pisces_Diadem_Scroll 261
|
||||
IG_Pisces_Diadem_Box 262
|
||||
IG_Energetic_Pisces_Scroll 263
|
||||
IG_Energetic_Pisces_Box 264
|
||||
IG_Aries_Scroll 265
|
||||
IG_Aries_Scroll_Box 266
|
||||
IG_Boarding_Halter_Box 267
|
||||
IG_Taurus_Diadem_Scroll 268
|
||||
IG_Taurus_Di_Scroll_Box 269
|
||||
IG_Umbala_Spirit_Box2 270
|
||||
IG_F_Umbala_Spirit_Box2 271
|
||||
IG_Taurus_Crown_Scroll 272
|
||||
IG_Taurus_Crown_Scroll_Box 273
|
||||
IG_Gemi_Diadem_Scroll 274
|
||||
IG_Gemi_Diadem_Scroll_Box 275
|
||||
IG_Super_Pet_Egg1_2 276
|
||||
IG_Super_Pet_Egg4_2 277
|
||||
IG_Fire_Brand_Box 278
|
||||
IG_BR_Independence_Scroll 279
|
||||
IG_All_In_One_Ring_Box 280
|
||||
IG_Gemi_Crown_Scroll 281
|
||||
IG_Gemi_Crown_Scroll_Box 282
|
||||
IG_RWC_Special_Scroll 283
|
||||
IG_RWC_Limited_Scroll 284
|
||||
IG_Asgard_Scroll 285
|
||||
IG_Ms_Cancer_Scroll 286
|
||||
IG_RWC_Super_Scroll 287
|
||||
IG_Leo_Scroll 288
|
||||
IG_Ms_Virgo_Scroll 289
|
||||
IG_Lucky_Egg_C6 290
|
||||
IG_Libra_Scroll 291
|
||||
IG_Hallo_Scroll 292
|
||||
IG_Ms_Scorpio_Scroll 293
|
||||
IG_TCG_Card_Scroll 294
|
||||
IG_Boitata_Scroll 295
|
||||
IG_Lucky_Egg_C2 296
|
||||
//IG_Lucky_Egg_C6 297
|
||||
IG_Lucky_Egg_C9 298
|
||||
IG_Lucky_Egg_C7 299
|
||||
IG_Lucky_Egg_C8 300
|
||||
IG_Lucky_Egg_C10 301
|
||||
IG_Wind_Type_Scroll 302
|
||||
IG_Lucky_Egg_C3 303
|
||||
IG_Lucky_Egg_C4 304
|
||||
IG_Lucky_Egg_C5 305
|
||||
IG_Weather_Report_Box 306
|
||||
IG_Comin_Actor_Box 307
|
||||
IG_Hen_Set_Box 308
|
||||
IG_Lucky_Egg_C 309
|
||||
IG_Water_Type_Scroll 310
|
||||
IG_Earth_Type_Scroll 311
|
||||
//IG_Earth_Type_Scroll 312
|
||||
IG_Splash_Scroll 313
|
||||
IG_Vocation_Scroll 314
|
||||
IG_Wisdom_Scroll 315
|
||||
IG_Patron_Scroll 316
|
||||
IG_Heaven_Scroll 317
|
||||
IG_Tw_Aug_Scroll 318
|
||||
IG_Tw_Nov_Scroll2 319
|
||||
IG_Illusion_Nothing 320
|
||||
IG_Tw_Sep_Scroll 321
|
||||
IG_Flame_Light 322
|
||||
IG_Tw_Rainbow_Scroll 323
|
||||
IG_Tw_Red_Scroll 324
|
||||
IG_Tw_Orange_Scroll 325
|
||||
IG_Tw_Yellow_Scroll 326
|
||||
IG_Scroll_Of_Death 327
|
||||
IG_Scroll_Of_Life 328
|
||||
IG_Scroll_Of_Magic 329
|
||||
IG_Scroll_Of_Thews 330
|
||||
IG_Scroll_Of_Darkness 331
|
||||
IG_Scroll_Of_Holiness 332
|
||||
IG_Horned_Scroll 333
|
||||
IG_Mercury_Scroll 334
|
||||
IG_Challenge_Kit 335
|
||||
IG_Tw_April_Scroll 336
|
||||
//IG_Tw_October_Scroll 337
|
||||
IG_Summer_Scroll3 338
|
||||
IG_C_Wing_Of_Fly_3Day_Box 339
|
||||
IG_RWC_2012_Set_Box 340
|
||||
IG_Ex_Def_Potion_Box 341
|
||||
IG_RWC_Scroll_2012 342
|
||||
IG_Old_Coin_Pocket 343
|
||||
IG_High_Coin_Pocket 344
|
||||
IG_Mid_Coin_Pocket 345
|
||||
IG_Low_Coin_Pocket 346
|
||||
IG_Sgrade_Pocket 347
|
||||
IG_Agrade_Pocket 348
|
||||
IG_Bgrade_Pocket 349
|
||||
IG_Cgrade_Pocket 350
|
||||
IG_Dgrade_Pocket 351
|
||||
IG_Egrade_Pocket 352
|
||||
IG_Ptotection_Seagod_Box 353
|
||||
IG_Hairtail_Box1 354
|
||||
IG_Hairtail_Box2 355
|
||||
IG_Spearfish_Box1 356
|
||||
IG_Spearfish_Box2 357
|
||||
IG_Saurel_Box1 358
|
||||
IG_Saurel_Box2 359
|
||||
IG_Tuna_Box1 360
|
||||
IG_Tuna_Box2 361
|
||||
IG_Malang_Crab_Box1 362
|
||||
IG_Malang_Crab_Box2 363
|
||||
IG_Brindle_Eel_Box1 364
|
||||
IG_Brindle_Eel_Box2 365
|
||||
IG_Ptotection_Seagod_Box2 366
|
||||
IG_Ptotection_Seagod_Box3 367
|
||||
IG_Octo_Hstick_Box 368
|
||||
IG_Octo_Hstick_Box2 369
|
||||
IG_Octo_Hstick_Box3 370
|
||||
IG_Silvervine_Fruit_Box10 371
|
||||
IG_Silvervine_Fruit_Box40 372
|
||||
IG_Silvervine_Fruit_Box4 373
|
||||
IG_Malang_Woe_Encard_Box 374
|
||||
IG_Xmas_Bless 375
|
||||
IG_Fire_Type_Scroll 376
|
||||
IG_Blue_Scroll 377
|
||||
IG_Good_Student_Gift_Box 378
|
||||
IG_Bad_Student_Gift_Box 379
|
||||
IG_Indigo_Scroll 380
|
||||
IG_Violet_Scroll 381
|
||||
IG_Bi_Hwang_Scroll 382
|
||||
IG_Jung_Bi_Scroll 383
|
||||
IG_Je_Un_Scroll 384
|
||||
IG_Yong_Kwang_Scroll 385
|
||||
|
||||
SC_ALL -1
|
||||
SC_STONE 0
|
||||
@ -3387,8 +3703,8 @@ DIR_NORTHEAST 7
|
||||
IT_HEALING 0
|
||||
IT_USABLE 2
|
||||
IT_ETC 3
|
||||
IT_WEAPON 4
|
||||
IT_ARMOR 5
|
||||
IT_ARMOR 4
|
||||
IT_WEAPON 5
|
||||
IT_CARD 6
|
||||
IT_PETEGG 7
|
||||
IT_PETARMOR 8
|
||||
|
@ -1,3 +1,5 @@
|
||||
//
|
||||
// Structure of Database:
|
||||
// GroupID,ItemID,Rate
|
||||
//
|
||||
// Cookie Bag
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,3 +4,4 @@ import: db/re/item_cardalbum.txt
|
||||
import: db/item_findingore.txt
|
||||
import: db/re/item_giftbox.txt
|
||||
import: db/re/item_misc.txt
|
||||
import: db/re/item_package.txt
|
||||
|
@ -1,3 +1,5 @@
|
||||
//
|
||||
// Structure of Database:
|
||||
// GroupID,ItemID,Rate
|
||||
//
|
||||
// Cookie Bag
|
||||
|
3100
db/re/item_package.txt
Normal file
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
132
doc/item_group.txt
Normal 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
|
@ -4422,7 +4422,7 @@ Example:
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*groupranditem <group id>;
|
||||
*groupranditem <group id>{,<sub_group>};
|
||||
|
||||
Returns the item_id of a random item picked from the group specified. The
|
||||
different groups and their group number are specified in 'db/(pre-)re/item_group_db.txt'.
|
||||
@ -4432,9 +4432,12 @@ example, for a random pet lure:
|
||||
|
||||
getitem groupranditem(15),1;
|
||||
|
||||
'sub_group' is used to get the available random items of item group from specified random
|
||||
group. More info, just like the explanation below.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*getrandgroupitem <group id>,<quantity>;
|
||||
*getrandgroupitem <group id>,<quantity>{,<sub_group>};
|
||||
|
||||
Similar to the above example, this command allows players to obtain the specified
|
||||
quantity of a random item from the group "<group id>". The different groups and
|
||||
@ -4443,6 +4446,47 @@ their group number are specified in db/(pre-)re/item_group_db.txt
|
||||
For example, obtaining three of the same random item from Old Blue Box:
|
||||
|
||||
getrandgroupitem(1,3);
|
||||
getrandgroupitem(IG_BlueBox,3); //see const.txt at 'Item Group ID' section
|
||||
|
||||
If quantity is 0, and if the item(s) at specified IG_ has defined amount, the amount of
|
||||
the item that will be obtained, will according to the amount on that IG_ data.
|
||||
|
||||
By default, if getrandgroupitem is used to get random item from IG_ which has more than
|
||||
defined random group, it always read random group 1, other item that as random item at
|
||||
random group > 2 never been touched. Use 'sub_group' to choose which random group will be
|
||||
obtained.
|
||||
|
||||
Example:
|
||||
|
||||
IG_ExGetGroupItem,Coat,2,2,1
|
||||
IG_ExGetGroupItem,Muffler,2,3,1
|
||||
IG_ExGetGroupItem,Yggdrasilberry,10,7,1
|
||||
|
||||
IG_ExGetGroupItem,Yggdrasilberry,10,7,2
|
||||
IG_ExGetGroupItem,Seed_Of_Yggdrasil,5,15,2
|
||||
|
||||
1. 'getrandgroupitem(IG_ExGetGroupItem,1)'
|
||||
Player has chance to get 1x Coat or 1x Muffler or 1x Yggdrasilberry. Player never
|
||||
has chance to get Seed_of_Yggdrasil because it is in different random group.
|
||||
|
||||
2. 'getrandgroupitem(IG_ExGetGroupItem,0)'
|
||||
Player has chance to get 2x Coat or 3x Muffler or 7x Yggdrasilberry. Player never
|
||||
has chance to get Seed_of_Yggdrasil because it is in different random group.
|
||||
|
||||
3. 'getrandgroupitem(IG_ExGetGroupItem,0,2)'
|
||||
Player has chance to get 10x Yggdrasilberry or 15x Seed_of_Yggdrasil. Player never
|
||||
has chance to get Coat, Muffler, and Seed_of_Yggdrasil because it is in different
|
||||
random group.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*getgroupitem <group_id>;
|
||||
|
||||
Gives item(s) to the attached player based on item group contents.
|
||||
This is not working like 'getrandgroupitem' which only give 1 item for specified
|
||||
item group.
|
||||
|
||||
Can use const data for 'group_id', see db/const.txt at 'Item Group ID' section
|
||||
|
||||
---------------------------------------
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -173,8 +173,8 @@ enum item_types {
|
||||
IT_UNKNOWN, //1
|
||||
IT_USABLE, //2
|
||||
IT_ETC, //3
|
||||
IT_WEAPON, //4
|
||||
IT_ARMOR, //5
|
||||
IT_ARMOR, //4
|
||||
IT_WEAPON, //5
|
||||
IT_CARD, //6
|
||||
IT_PETEGG, //7
|
||||
IT_PETARMOR,//8
|
||||
|
@ -5877,7 +5877,7 @@ ACMD_FUNC(autolootitem)
|
||||
* @autoloottype
|
||||
* Flags:
|
||||
* 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
|
||||
* 262144: IT_CASH
|
||||
*------------------------------------------
|
||||
@ -5913,10 +5913,10 @@ ACMD_FUNC(autoloottype)
|
||||
type = IT_USABLE;
|
||||
else if ((strncmp(message, "etc", 3) == 0) || (atoi(message) == 3))
|
||||
type = IT_ETC;
|
||||
else if ((strncmp(message, "weapon", 3) == 0) || (atoi(message) == 4))
|
||||
type = IT_WEAPON;
|
||||
else if ((strncmp(message, "armor", 3) == 0) || (atoi(message) == 5))
|
||||
else if ((strncmp(message, "armor", 3) == 0) || (atoi(message) == 4))
|
||||
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))
|
||||
type = IT_CARD;
|
||||
else if ((strncmp(message, "petegg", 4) == 0) || (atoi(message) == 7))
|
||||
@ -5959,7 +5959,7 @@ ACMD_FUNC(autoloottype)
|
||||
break;
|
||||
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,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.
|
||||
if (sd->state.autoloottype == ITEM_NONE)
|
||||
clif_displaymessage(fd, msg_txt(sd,1489)); // Your autoloottype list is empty.
|
||||
|
@ -1931,6 +1931,7 @@ void clif_scriptclear(struct map_session_data *sd, int npcid)
|
||||
struct s_packet_db* info;
|
||||
int16 len;
|
||||
int cmd = 0;
|
||||
int fd;
|
||||
|
||||
nullpo_retv(sd);
|
||||
|
||||
@ -1938,6 +1939,7 @@ void clif_scriptclear(struct map_session_data *sd, int npcid)
|
||||
if(!cmd) cmd = 0x8d6; //default
|
||||
info = &packet_db[sd->packet_ver][cmd];
|
||||
len = info->len;
|
||||
fd = sd->fd;
|
||||
|
||||
WFIFOHEAD(fd, len);
|
||||
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);
|
||||
}
|
||||
|
||||
///TODO: Special item that obtained, must be broadcasted by this packet
|
||||
//void clif_broadcast_obtain_special_item() {}
|
||||
|
||||
#ifdef DUMP_UNKNOWN_PACKET
|
||||
void DumpUnknow(int fd,TBL_PC *sd,int cmd,int packet_len){
|
||||
const char* packet_txt = "save/packet.txt";
|
||||
|
@ -837,4 +837,6 @@ void clif_channel_msg(struct Channel *channel, struct map_session_data *sd, char
|
||||
void clif_ranklist(struct map_session_data *sd, int16 rankingType);
|
||||
void clif_update_rankingpoint(struct map_session_data *sd, int rankingtype, int point);
|
||||
|
||||
//void clif_broadcast_obtain_special_item(); ///TODO!
|
||||
|
||||
#endif /* _CLIF_H_ */
|
||||
|
211
src/map/itemdb.c
211
src/map/itemdb.c
@ -21,7 +21,7 @@
|
||||
static struct item_data* itemdb_array[MAX_ITEMDB];
|
||||
static DBMap* itemdb_other;// int nameid -> struct item_data*
|
||||
|
||||
static struct item_group itemgroup_db[MAX_ITEMGROUP];
|
||||
static struct s_item_group_db itemgroup_db[MAX_ITEMGROUP];
|
||||
|
||||
struct item_data dummy_item; //This is the default dummy item used for non-existant items. [Skotlex]
|
||||
|
||||
@ -141,22 +141,131 @@ int itemdb_searchname_array(struct item_data** data, int size, const char *str)
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Return a random item id from group. (takes into account % chance giving/tot group)
|
||||
*------------------------------------------*/
|
||||
int itemdb_searchrandomid(int group)
|
||||
* @param group_id
|
||||
* @param sub_group: Default is 1
|
||||
* @return nameid
|
||||
*/
|
||||
int itemdb_searchrandomid(int group_id, uint8 sub_group)
|
||||
{
|
||||
if(group<1 || group>=MAX_ITEMGROUP) {
|
||||
ShowError("itemdb_searchrandomid: Invalid group id %d\n", group);
|
||||
if (sub_group == 0)
|
||||
sub_group = 1;
|
||||
if (group_id < 1 || group_id >= MAX_ITEMGROUP) {
|
||||
ShowError("itemdb_searchrandomid: Invalid group id %d\n", group_id);
|
||||
return UNKNOWN_ITEM_ID;
|
||||
}
|
||||
if (itemgroup_db[group].qty)
|
||||
return itemgroup_db[group].nameid[rnd()%itemgroup_db[group].qty];
|
||||
|
||||
ShowError("itemdb_searchrandomid: No item entries for group id %d\n", group);
|
||||
if (sub_group >= MAX_ITEMGROUP_RANDGROUP) {
|
||||
ShowError("itemdb_searchrandomid: Invalid sub_group %d\n", sub_group);
|
||||
return UNKNOWN_ITEM_ID;
|
||||
}
|
||||
if (itemgroup_db[group_id].random_qty[sub_group-1])
|
||||
return itemgroup_db[group_id].random[sub_group-1][rnd()%itemgroup_db[group_id].random_qty[sub_group-1]].nameid;
|
||||
|
||||
ShowError("itemdb_searchrandomid: No item entries for group id %d and sub group %d\n", group_id, sub_group);
|
||||
return UNKNOWN_ITEM_ID;
|
||||
}
|
||||
|
||||
/** [Cydh]
|
||||
* Return a number of item's amount that will be obtained for 'getrandgroupitem id,0;'
|
||||
* @param group_id
|
||||
* @param sub_group
|
||||
* @param nameid: The target item
|
||||
* @return amount
|
||||
*/
|
||||
uint16 itemdb_get_randgroupitem_count(uint16 group_id, uint8 sub_group, uint16 nameid) {
|
||||
uint16 i, amt = 1;
|
||||
if (group_id < 1 || group_id >= MAX_ITEMGROUP_RAND || sub_group > MAX_ITEMGROUP_RANDGROUP)
|
||||
return amt;
|
||||
if (!sub_group)
|
||||
sub_group = 1;
|
||||
ARR_FIND(0,itemgroup_db[group_id].random_qty[sub_group-1],i,itemgroup_db[group_id].random[sub_group-1][i].nameid == nameid);
|
||||
if (i < MAX_ITEMGROUP_RAND)
|
||||
amt = itemgroup_db[group_id].random[sub_group-1][i].amount;
|
||||
return amt;
|
||||
}
|
||||
|
||||
/** [Cydh]
|
||||
* Gives item(s) to the player based on item group
|
||||
* @param sd: Player that obtains item from item group
|
||||
* @param group_id: The group ID of item that obtained by player
|
||||
* @param nameid_from: The item that trigger this item group
|
||||
* @param *group: struct s_item_group from itemgroup_db[group_id].random[idx] or itemgroup_db[group_id].must[sub_group][idx]
|
||||
*/
|
||||
void itemdb_pc_get_itemgroup_sub(struct map_session_data *sd, uint16 group_id, uint16 nameid_from, struct s_item_group *group) {
|
||||
uint16 i;
|
||||
struct item tmp;
|
||||
|
||||
nullpo_retv(group);
|
||||
|
||||
memset(&tmp,0,sizeof(tmp));
|
||||
|
||||
tmp.nameid = group->nameid;
|
||||
tmp.amount = (itemdb_isstackable(group->nameid)) ? group->amount : 1;
|
||||
tmp.bound = group->bound;
|
||||
tmp.identify = 1;
|
||||
tmp.expire_time = (group->duration) ? (unsigned int)(time(NULL) + group->duration*60) : 0;
|
||||
if (group->isNamed) {
|
||||
tmp.card[0] = itemdb_isequip(group->nameid) ? CARD0_FORGE : CARD0_CREATE;
|
||||
tmp.card[1] = 0;
|
||||
tmp.card[2] = GetWord(sd->status.char_id, 0);
|
||||
tmp.card[3] = GetWord(sd->status.char_id, 1);
|
||||
}
|
||||
//Do loop for non-stackable item
|
||||
for (i = 0; i < group->amount; i++) {
|
||||
int flag;
|
||||
if ((flag = pc_additem(sd,&tmp,tmp.amount,LOG_TYPE_SCRIPT)))
|
||||
clif_additem(sd,0,0,flag);
|
||||
else if (!flag && group->isAnnounced) { ///TODO: Move this broadcast to proper behavior (it should on at different packet)
|
||||
char output[CHAT_SIZE_MAX];
|
||||
sprintf(output,msg_txt(sd,717),sd->status.name,itemdb_jname(group->nameid),itemdb_jname(nameid_from));
|
||||
clif_broadcast(&sd->bl,output,strlen(output),0,ALL_CLIENT);
|
||||
//clif_broadcast_obtain_special_item();
|
||||
}
|
||||
if (itemdb_isstackable(group->nameid))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** [Cydh]
|
||||
* Find item(s) that will be obtained by player based on Item Group
|
||||
* @param group_id: The group ID that will be gained by player
|
||||
* @param nameid: The item that trigger this item group
|
||||
* @param sd: Player that obtains item from item group
|
||||
* @return val: 0:success, 1:no sd, 2:invalid item group
|
||||
*/
|
||||
uint8 itemdb_pc_get_itemgroup(uint16 group_id, uint16 nameid, struct map_session_data *sd) {
|
||||
uint16 i = 0;
|
||||
|
||||
nullpo_retr(1,sd);
|
||||
|
||||
if (!group_id || group_id >= MAX_ITEMGROUP) {
|
||||
ShowError("getgroupitem: Invalid group id '%d' specified.",group_id);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//Get the 'must' item(s)
|
||||
for (i = 0; i < itemgroup_db[group_id].must_qty; i++) {
|
||||
if (itemdb_exists(itemgroup_db[group_id].must[i].nameid))
|
||||
itemdb_pc_get_itemgroup_sub(sd,group_id,nameid,&itemgroup_db[group_id].must[i]);
|
||||
}
|
||||
|
||||
//Get the 'random' item each random group
|
||||
for (i = 0; i < MAX_ITEMGROUP_RANDGROUP; i++) {
|
||||
uint16 rand, j = 0;
|
||||
if (!itemgroup_db[group_id].random_qty[i]) //Skip empty random group
|
||||
continue;
|
||||
rand = rnd()%itemgroup_db[group_id].random_qty[i];
|
||||
//Woops, why is the data empty? Every check should be done when load the item group! So this is bad day for the player :P
|
||||
if (!&itemgroup_db[group_id].random[i][rand] || !itemgroup_db[group_id].random[i][rand].nameid) {
|
||||
continue;
|
||||
}
|
||||
if (itemdb_exists(itemgroup_db[group_id].random[i][rand].nameid))
|
||||
itemdb_pc_get_itemgroup_sub(sd,group_id,nameid,&itemgroup_db[group_id].random[i][rand]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Calculates total item-group related bonuses for the given item
|
||||
@ -167,8 +276,8 @@ int itemdb_group_bonus(struct map_session_data* sd, int itemid)
|
||||
for (i=0; i < MAX_ITEMGROUP; i++) {
|
||||
if (!sd->itemgrouphealrate[i])
|
||||
continue;
|
||||
ARR_FIND( 0, itemgroup_db[i].qty, j, itemgroup_db[i].nameid[j] == itemid );
|
||||
if( j < itemgroup_db[i].qty )
|
||||
ARR_FIND( 0, itemgroup_db[i].random_qty[0], j, itemgroup_db[i].random[0][j].nameid == itemid );
|
||||
if( j < itemgroup_db[i].random_qty[0] )
|
||||
bonus += sd->itemgrouphealrate[i];
|
||||
}
|
||||
return bonus;
|
||||
@ -529,29 +638,32 @@ static bool itemdb_read_itemavail(char* str[], int columns, int current)
|
||||
|
||||
/*==========================================
|
||||
* read item group data
|
||||
* GroupID,ItemID,Rate{,Amount,isMust,isAnnounced,Duration,isNamed,isBound}
|
||||
*------------------------------------------*/
|
||||
static void itemdb_read_itemgroup_sub(const char* filename)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[1024];
|
||||
int ln=0, entries=0;
|
||||
int groupid,j,k,nameid;
|
||||
char *str[3],*p;
|
||||
char w1[1024], w2[1024];
|
||||
char line[1024];
|
||||
|
||||
if ((fp=fopen(filename,"r")) == NULL) {
|
||||
ShowError("can't read %s\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
while(fgets(line, sizeof(line), fp))
|
||||
{
|
||||
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;
|
||||
|
||||
ln++;
|
||||
if (line[0] == '/' && line[1] == '/')
|
||||
continue;
|
||||
if (strstr(line,"import")) {
|
||||
if (sscanf(line,"%[^:]: %[^\r\n]",w1,w2) == 2 &&
|
||||
strcmpi(w1, "import") == 0) {
|
||||
strcmpi(w1,"import") == 0)
|
||||
{
|
||||
itemdb_read_itemgroup_sub(w2);
|
||||
continue;
|
||||
}
|
||||
@ -559,6 +671,8 @@ static void itemdb_read_itemgroup_sub(const char* filename)
|
||||
memset(str,0,sizeof(str));
|
||||
for (j = 0, p = line; j < 3 && p;j++) {
|
||||
str[j] = p;
|
||||
if (j == 2)
|
||||
sscanf(str[j],"%d,%d,%d,%d,%d,%d,%d",&prob,&amt,&group,&announced,&dur,&named,&bound);
|
||||
p = strchr(p,',');
|
||||
if (p) *p++=0;
|
||||
}
|
||||
@ -569,23 +683,60 @@ static void itemdb_read_itemgroup_sub(const char* filename)
|
||||
ShowWarning("itemdb_read_itemgroup: Insufficient fields for entry at %s:%d\n", filename, ln);
|
||||
continue;
|
||||
}
|
||||
groupid = atoi(str[0]);
|
||||
if (groupid < 0 || groupid >= MAX_ITEMGROUP) {
|
||||
ShowWarning("itemdb_read_itemgroup: Invalid group %d in %s:%d\n", groupid, filename, ln);
|
||||
|
||||
//Checking group_id
|
||||
if (!atoi(str[0])) //Try reads group id by const
|
||||
script_get_constant(trim(str[0]),&group_id);
|
||||
else
|
||||
group_id = atoi(str[0]);
|
||||
if (!group_id || group_id >= MAX_ITEMGROUP || group >= MAX_ITEMGROUP_RANDGROUP) {
|
||||
ShowWarning("itemdb_read_itemgroup: Invalid group (id:%d sub:%d) in %s:%d\n", group_id, group, filename, ln);
|
||||
continue;
|
||||
}
|
||||
nameid = atoi(str[1]);
|
||||
if (!itemdb_exists(nameid)) {
|
||||
|
||||
//Checking item
|
||||
if (!atoi(str[1]) && itemdb_searchname(str[1])) {
|
||||
found = true;
|
||||
nameid = itemdb_searchname(str[1])->nameid;
|
||||
}
|
||||
else if ((nameid = atoi(str[1])) && itemdb_exists(nameid))
|
||||
found = true;
|
||||
if (!found) {
|
||||
ShowWarning("itemdb_read_itemgroup: Non-existant item %d in %s:%d\n", nameid, filename, ln);
|
||||
continue;
|
||||
}
|
||||
k = atoi(str[2]);
|
||||
if (itemgroup_db[groupid].qty+k >= MAX_RANDITEM) {
|
||||
ShowWarning("itemdb_read_itemgroup: Group %d is full (%d entries) in %s:%d\n", groupid, MAX_RANDITEM, filename, ln);
|
||||
|
||||
//Checking the capacity
|
||||
if ((group && itemgroup_db[group_id].random_qty[group-1]+prob >= MAX_ITEMGROUP_RAND) ||
|
||||
(!group && itemgroup_db[group_id].must_qty+1 >= MAX_ITEMGROUP_MUST))
|
||||
{
|
||||
ShowWarning("itemdb_read_itemgroup: Group id %d is overflow (%d entries) in %s:%d\n", group_id, (!group) ? MAX_ITEMGROUP_MUST : MAX_ITEMGROUP_RAND, filename, ln);
|
||||
continue;
|
||||
}
|
||||
for(j=0;j<k;j++)
|
||||
itemgroup_db[groupid].nameid[itemgroup_db[groupid].qty++] = nameid;
|
||||
|
||||
if (!group) {
|
||||
uint16 idx = itemgroup_db[group_id].must_qty;
|
||||
itemgroup_db[group_id].must[idx].nameid = nameid;
|
||||
itemgroup_db[group_id].must[idx].amount = min(amt,MAX_AMOUNT);
|
||||
itemgroup_db[group_id].must[idx].isAnnounced = (announced) ? true : false;
|
||||
itemgroup_db[group_id].must[idx].duration = min(dur,UINT16_MAX);
|
||||
itemgroup_db[group_id].must[idx].isNamed = (named) ? true : false;
|
||||
itemgroup_db[group_id].must[idx].bound = cap_value(bound,0,4);
|
||||
itemgroup_db[group_id].must_qty++;
|
||||
}
|
||||
for (j = 0; j < prob; j++) {
|
||||
uint16 idx;
|
||||
if (!group)
|
||||
group = 1;
|
||||
idx = itemgroup_db[group_id].random_qty[group-1];
|
||||
itemgroup_db[group_id].random[group-1][idx].nameid = nameid;
|
||||
itemgroup_db[group_id].random[group-1][idx].amount = min(amt,MAX_AMOUNT);
|
||||
itemgroup_db[group_id].random[group-1][idx].isAnnounced = (announced) ? true : false;
|
||||
itemgroup_db[group_id].random[group-1][idx].duration = min(dur,UINT16_MAX);
|
||||
itemgroup_db[group_id].random[group-1][idx].isNamed = (named) ? true : false;
|
||||
itemgroup_db[group_id].random[group-1][idx].bound = cap_value(bound,0,4);
|
||||
itemgroup_db[group_id].random_qty[group-1]++;
|
||||
}
|
||||
entries++;
|
||||
}
|
||||
fclose(fp);
|
||||
|
@ -11,7 +11,8 @@
|
||||
// 32k array entries in array (the rest goes to the db)
|
||||
#define MAX_ITEMDB 0x8000
|
||||
|
||||
#define MAX_RANDITEM 11000
|
||||
//Use apple for unknown items.
|
||||
#define UNKNOWN_ITEM_ID 512
|
||||
|
||||
// The maximum number of item delays
|
||||
#define MAX_ITEMDELAYS 10
|
||||
@ -21,6 +22,24 @@
|
||||
/* maximum amount of items a combo may require */
|
||||
#define MAX_ITEMS_PER_COMBO 6
|
||||
|
||||
//The only item group required by the code to be known. See const.txt for the full list.
|
||||
#define IG_FINDINGORE 6
|
||||
#define IG_POTION 37
|
||||
|
||||
#define MAX_ITEMGROUP 390 ///The max. item group count (increase this when needed).
|
||||
|
||||
#define MAX_ITEMGROUP_RAND 11000 ///Max item slots for random item group
|
||||
#define MAX_ITEMGROUP_MUST 20 ///Max item slots for 'must' item group
|
||||
#define MAX_ITEMGROUP_RANDGROUP 5 ///Max group for random item
|
||||
|
||||
#define CARD0_FORGE 0x00FF
|
||||
#define CARD0_CREATE 0x00FE
|
||||
#define CARD0_PET ((short)0xFF00)
|
||||
|
||||
//Marks if the card0 given is "special" (non-item id used to mark pets/created items. [Skotlex]
|
||||
#define itemdb_isspecial(i) (i == CARD0_FORGE || i == CARD0_CREATE || i == CARD0_PET)
|
||||
|
||||
///Enum of item id (for hardcoded purpose)
|
||||
enum item_itemid {
|
||||
ITEMID_EMPERIUM = 714,
|
||||
ITEMID_YELLOW_GEMSTONE = 715,
|
||||
@ -83,22 +102,6 @@ enum e_item_job {
|
||||
ITEMJ_THIRD_BABY = 0x20,
|
||||
};
|
||||
|
||||
//The only item group required by the code to be known. See const.txt for the full list.
|
||||
#define IG_FINDINGORE 6
|
||||
#define IG_POTION 37
|
||||
//The max. item group count (increase this when needed).
|
||||
#define MAX_ITEMGROUP 71
|
||||
|
||||
#define CARD0_FORGE 0x00FF
|
||||
#define CARD0_CREATE 0x00FE
|
||||
#define CARD0_PET ((short)0xFF00)
|
||||
|
||||
//Marks if the card0 given is "special" (non-item id used to mark pets/created items. [Skotlex]
|
||||
#define itemdb_isspecial(i) (i == CARD0_FORGE || i == CARD0_CREATE || i == CARD0_PET)
|
||||
|
||||
//Use apple for unknown items.
|
||||
#define UNKNOWN_ITEM_ID 512
|
||||
|
||||
struct item_data {
|
||||
uint16 nameid;
|
||||
char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH];
|
||||
@ -162,9 +165,21 @@ struct item_data {
|
||||
unsigned char combos_count;
|
||||
};
|
||||
|
||||
struct item_group {
|
||||
int nameid[MAX_RANDITEM];
|
||||
int qty; //Counts amount of items in the group.
|
||||
/* Struct of item group */
|
||||
struct s_item_group {
|
||||
uint16 nameid, ///item id
|
||||
duration; ///duration if item as rental item
|
||||
uint16 amount; ///amount of item will be obtained
|
||||
bool isAnnounced, ///broadcast if player get this item
|
||||
isNamed; ///named the item (if possible)
|
||||
char bound; ///makes the item as bound item (according to bound type)
|
||||
};
|
||||
|
||||
/* Struct of item group that will be used for db */
|
||||
struct s_item_group_db {
|
||||
struct s_item_group must[MAX_ITEMGROUP_MUST];
|
||||
struct s_item_group random[MAX_ITEMGROUP_RANDGROUP][MAX_ITEMGROUP_RAND]; ///NOTE: Is this good?
|
||||
uint16 must_qty, random_qty[MAX_ITEMGROUP_RANDGROUP];
|
||||
};
|
||||
|
||||
struct item_combo {
|
||||
@ -208,7 +223,7 @@ struct item_data* itemdb_exists(int nameid);
|
||||
const char* itemdb_typename(int type);
|
||||
|
||||
int itemdb_group_bonus(struct map_session_data* sd, int itemid);
|
||||
int itemdb_searchrandomid(int flags);
|
||||
int itemdb_searchrandomid(int group_id, uint8 sub_group);
|
||||
|
||||
#define itemdb_value_buy(n) itemdb_search(n)->value_buy
|
||||
#define itemdb_value_sell(n) itemdb_search(n)->value_sell
|
||||
@ -242,6 +257,9 @@ int itemdb_isstackable2(struct item_data *);
|
||||
uint64 itemdb_unique_id(int8 flag, int64 value); // Unique Item ID
|
||||
bool itemdb_isNoEquip(struct item_data *id, uint16 m);
|
||||
|
||||
uint8 itemdb_pc_get_itemgroup(uint16 group_id, uint16 nameid, struct map_session_data *sd);
|
||||
uint16 itemdb_get_randgroupitem_count(uint16 group_id, uint8 sub_group, uint16 nameid);
|
||||
|
||||
DBMap * itemdb_get_combodb();
|
||||
|
||||
void itemdb_reload(void);
|
||||
|
@ -2426,7 +2426,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
|
||||
|
||||
// Ore Discovery [Celest]
|
||||
if (sd == mvp_sd && pc_checkskill(sd,BS_FINDINGORE)>0 && battle_config.finding_ore_rate/10 >= rnd()%10000) {
|
||||
ditem = mob_setdropitem(itemdb_searchrandomid(IG_FINDINGORE), 1);
|
||||
ditem = mob_setdropitem(itemdb_searchrandomid(IG_FINDINGORE,1), 1);
|
||||
mob_item_drop(md, dlist, ditem, 0, battle_config.finding_ore_rate/10, homkillonly);
|
||||
}
|
||||
|
||||
@ -2454,7 +2454,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
|
||||
|
||||
if (rnd()%10000 >= drop_rate)
|
||||
continue;
|
||||
itemid = (sd->add_drop[i].id > 0) ? sd->add_drop[i].id : itemdb_searchrandomid(sd->add_drop[i].group);
|
||||
itemid = (sd->add_drop[i].id > 0) ? sd->add_drop[i].id : itemdb_searchrandomid(sd->add_drop[i].group,1);
|
||||
mob_item_drop(md, dlist, mob_setdropitem(itemid,1), 0, drop_rate, homkillonly);
|
||||
}
|
||||
}
|
||||
|
@ -10474,8 +10474,7 @@ void pc_bonus_script_check(struct map_session_data *sd, enum e_bonus_script_flag
|
||||
* @param sd player
|
||||
*/
|
||||
void pc_cell_basilica(struct map_session_data *sd) {
|
||||
if (!sd)
|
||||
return;
|
||||
nullpo_retv(sd);
|
||||
|
||||
if (!map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKBASILICA)) {
|
||||
if (&sd->sc && sd->sc.data[SC_BASILICA])
|
||||
|
@ -6637,14 +6637,11 @@ BUILDIN_FUNC(getnameditem)
|
||||
|
||||
/*==========================================
|
||||
* gets a random item ID from an item group [Skotlex]
|
||||
* groupranditem group_num
|
||||
* groupranditem <group_num>{,<sub_group>};
|
||||
*------------------------------------------*/
|
||||
BUILDIN_FUNC(grouprandomitem)
|
||||
{
|
||||
int group;
|
||||
|
||||
group = script_getnum(st,2);
|
||||
script_pushint(st,itemdb_searchrandomid(group));
|
||||
script_pushint(st,itemdb_searchrandomid(script_getnum(st,2),script_getnum(st,3)));
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -17510,40 +17507,50 @@ BUILDIN_FUNC(checkre)
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* getrandgroupitem <group_id>,<quantity> */
|
||||
/* getrandgroupitem <group_id>,<quantity>{,<sub_group>} */
|
||||
BUILDIN_FUNC(getrandgroupitem) {
|
||||
TBL_PC* sd;
|
||||
int i, get_count = 0, flag, nameid, group = script_getnum(st, 2), qty = script_getnum(st,3);
|
||||
int i, get_count = 0, flag;
|
||||
uint16 nameid, group = script_getnum(st,2), qty = script_getnum(st,3);
|
||||
uint8 sub_group = script_getnum(st,4);
|
||||
struct item item_tmp;
|
||||
|
||||
if (!( sd = script_rid2sd(st)))
|
||||
return 0;
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
|
||||
if( qty <= 0 ) {
|
||||
ShowError("getrandgroupitem: qty is <= 0!\n");
|
||||
return 1;
|
||||
if (!group) {
|
||||
ShowError("getrandgroupitem: Invalid group id (%d)!\n",script_getnum(st,2));
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
if( (nameid = itemdb_searchrandomid(group)) == UNKNOWN_ITEM_ID ) {
|
||||
return 1; //ensure valid itemid
|
||||
|
||||
if ((nameid = itemdb_searchrandomid(group,sub_group)) == UNKNOWN_ITEM_ID) {
|
||||
return SCRIPT_CMD_FAILURE; //ensure valid itemid
|
||||
}
|
||||
|
||||
memset(&item_tmp,0,sizeof(item_tmp));
|
||||
item_tmp.nameid = nameid;
|
||||
item_tmp.identify = itemdb_isidentified(nameid);
|
||||
|
||||
//Check if it's stackable.
|
||||
if (!itemdb_isstackable(nameid))
|
||||
get_count = 1;
|
||||
else
|
||||
get_count = qty;
|
||||
if (!qty)
|
||||
qty = itemdb_get_randgroupitem_count(group,sub_group,nameid);
|
||||
|
||||
for (i = 0; i < qty; i += get_count) {
|
||||
//Check if it's stackable.
|
||||
if (!itemdb_isstackable(nameid)) {
|
||||
item_tmp.amount = 1;
|
||||
get_count = qty;
|
||||
}
|
||||
else {
|
||||
item_tmp.amount = qty;
|
||||
get_count = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < get_count; i++) {
|
||||
// if not pet egg
|
||||
if (!pet_create_egg(sd, nameid)) {
|
||||
if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_SCRIPT))) {
|
||||
if ((flag = pc_additem(sd,&item_tmp,item_tmp.amount,LOG_TYPE_SCRIPT))) {
|
||||
clif_additem(sd,0,0,flag);
|
||||
if (pc_candrop(sd,&item_tmp))
|
||||
map_addflooritem(&item_tmp,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;
|
||||
}
|
||||
|
||||
/* getgroupitem <group_id>;
|
||||
* Gives item(s) to the attached player based on item group contents
|
||||
*/
|
||||
BUILDIN_FUNC(getgroupitem) {
|
||||
TBL_PC *sd;
|
||||
int group_id = script_getnum(st,2);
|
||||
|
||||
if (!(sd = script_rid2sd(st)))
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
|
||||
if (itemdb_pc_get_itemgroup(group_id,sd->itemid,sd)) {
|
||||
ShowError("getgroupitem: Invalid group id '%d' specified.",group_id);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* cleanmap <map_name>;
|
||||
* cleanarea <map_name>, <x0>, <y0>, <x1>, <y1>; */
|
||||
static int atcommand_cleanfloor_sub(struct block_list *bl, va_list ap)
|
||||
@ -18298,7 +18323,7 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(rentitem,"vi"),
|
||||
BUILDIN_DEF(getitem2,"viiiiiiii?"),
|
||||
BUILDIN_DEF(getnameditem,"vv"),
|
||||
BUILDIN_DEF2(grouprandomitem,"groupranditem","i"),
|
||||
BUILDIN_DEF2(grouprandomitem,"groupranditem","i?"),
|
||||
BUILDIN_DEF(makeitem,"visii"),
|
||||
BUILDIN_DEF(delitem,"vi?"),
|
||||
BUILDIN_DEF(delitem2,"viiiiiiii?"),
|
||||
@ -18690,7 +18715,7 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(is_function,"s"),
|
||||
BUILDIN_DEF(get_revision,""),
|
||||
BUILDIN_DEF(freeloop,"i"),
|
||||
BUILDIN_DEF(getrandgroupitem,"ii"),
|
||||
BUILDIN_DEF(getrandgroupitem,"ii?"),
|
||||
BUILDIN_DEF(cleanmap,"s"),
|
||||
BUILDIN_DEF2(cleanmap,"cleanarea","siiii"),
|
||||
BUILDIN_DEF(npcskill,"viii"),
|
||||
@ -18731,6 +18756,7 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(vip_status,"i?"),
|
||||
BUILDIN_DEF(vip_time,"i?"),
|
||||
BUILDIN_DEF(bonus_script,"si???"),
|
||||
BUILDIN_DEF(getgroupitem,"i"),
|
||||
|
||||
#include "../custom/script_def.inc"
|
||||
|
||||
|
@ -1412,6 +1412,8 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
|
||||
}
|
||||
|
||||
// Always run NPC scripts for players last
|
||||
//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);
|
||||
if( sd->bg_id ) {
|
||||
@ -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 hhp: How much HP 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)
|
||||
* @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 hp_rate: Percentage of HP 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
|
||||
* @return hp+sp through status_heal()
|
||||
**/
|
||||
|
@ -24,11 +24,15 @@
|
||||
#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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
nullpo_retv(items);
|
||||
@ -54,22 +63,32 @@ static void storage_sortitem(struct item* items, unsigned int size)
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Init/Terminate
|
||||
*------------------------------------------*/
|
||||
int do_init_storage(void) // Called from map.c::do_init()
|
||||
/**
|
||||
* Initiate storage module
|
||||
* Called from map.c::do_init()
|
||||
* @return 1
|
||||
*/
|
||||
int do_init_storage(void) //
|
||||
{
|
||||
guild_storage_db=idb_alloc(DB_OPT_RELEASE_DATA);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses storage and saves 'dirty' ones upon reconnect. [Skotlex]
|
||||
* Parses storage and saves 'dirty' ones upon reconnect.
|
||||
* @author [Skotlex]
|
||||
* @see DBApply
|
||||
* @return 0
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
guild_storage_db->foreach(guild_storage_db, storage_reconnect_sub);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Opens a storage. Returns:
|
||||
* 0 - success
|
||||
* 1 - fail
|
||||
*------------------------------------------*/
|
||||
/**
|
||||
* Player attempt tp open his storage.
|
||||
* @param sd : player
|
||||
* @return 0:success, 1:fail
|
||||
*/
|
||||
int storage_storageopen(struct map_session_data *sd)
|
||||
{
|
||||
nullpo_ret(sd);
|
||||
@ -111,8 +133,11 @@ int storage_storageopen(struct map_session_data *sd)
|
||||
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)
|
||||
{
|
||||
@ -130,9 +155,13 @@ int compare_item(struct item *a, struct item *b)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Add an item to the storage from the inventory.
|
||||
* @index : inventory idx
|
||||
* return
|
||||
* 0 : fail
|
||||
* 1 : success
|
||||
*------------------------------------------*/
|
||||
* @param sd : player
|
||||
* @param index : inventory index to take the item from
|
||||
* @param amount : number of item to take
|
||||
* @return 0:fail, 1:success
|
||||
*/
|
||||
int storage_storageadd(struct map_session_data* sd, int index, int amount)
|
||||
{
|
||||
nullpo_ret(sd);
|
||||
@ -242,13 +275,13 @@ int storage_storageadd(struct map_session_data* sd, int index, int amount)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Retrieve an item from the storage into inventory
|
||||
* @index : storage idx
|
||||
* return
|
||||
* 0 : fail
|
||||
* 1 : success
|
||||
*------------------------------------------*/
|
||||
* @param sd : player
|
||||
* @param index : storage index to take the item from
|
||||
* @param amount : number of item to take
|
||||
* @return 0:fail, 1:success
|
||||
*/
|
||||
int storage_storageget(struct map_session_data* sd, int index, int amount)
|
||||
{
|
||||
int flag;
|
||||
@ -270,13 +303,13 @@ int storage_storageget(struct map_session_data* sd, int index, int amount)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Move an item from cart to storage.
|
||||
* @index : cart inventory index
|
||||
* return
|
||||
* 0 : fail
|
||||
* 1 : success
|
||||
*------------------------------------------*/
|
||||
* @param sd : player
|
||||
* @param index : cart index to take the item from
|
||||
* @param amount : number of item to take
|
||||
* @return 0:fail, 1:success
|
||||
*/
|
||||
int storage_storageaddfromcart(struct map_session_data* sd, int index, int amount)
|
||||
{
|
||||
nullpo_ret(sd);
|
||||
@ -299,13 +332,13 @@ int storage_storageaddfromcart(struct map_session_data* sd, int index, int amoun
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Get from Storage to the Cart inventory
|
||||
* @index : storage index
|
||||
* return
|
||||
* 0 : fail
|
||||
* 1 : success
|
||||
*------------------------------------------*/
|
||||
* @param sd : player
|
||||
* @param index : storage index to take the item from
|
||||
* @param amount : number of item to take
|
||||
* @return 0:fail, 1:success
|
||||
*/
|
||||
int storage_storagegettocart(struct map_session_data* sd, int index, int amount)
|
||||
{
|
||||
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)
|
||||
{
|
||||
nullpo_retv(sd);
|
||||
@ -346,9 +381,14 @@ void storage_storageclose(struct map_session_data* sd)
|
||||
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)
|
||||
{
|
||||
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
|
||||
* @param key
|
||||
* @param args
|
||||
* @return
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 *gs = NULL;
|
||||
@ -378,25 +428,33 @@ struct guild_storage *guild2storage(int guild_id)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
idb_remove(guild_storage_db,guild_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Attempt to open guild storage for sd
|
||||
* return
|
||||
* 0 : success (open or req to create a new one)
|
||||
* 1 : fail
|
||||
* 2 : no guild for sd
|
||||
*------------------------------------------*/
|
||||
/**
|
||||
* Attempt to open guild storage for player
|
||||
* @param sd : player
|
||||
* @return * 0 : success, 1 : fail, 2 : no guild found
|
||||
*/
|
||||
int storage_guild_storageopen(struct map_session_data* sd)
|
||||
{
|
||||
struct guild_storage *gstor;
|
||||
@ -432,12 +490,14 @@ int storage_guild_storageopen(struct map_session_data* sd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Attempt to add an item in guild storage, then refresh it
|
||||
* return
|
||||
* 0 : success
|
||||
* 1 : fail
|
||||
*------------------------------------------*/
|
||||
* @param sd : player attempting to open the guild_storage
|
||||
* @param stor : guild_storage
|
||||
* @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)
|
||||
{
|
||||
struct item_data *data;
|
||||
@ -495,12 +555,14 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Attempt to delete an item in guild storage, then refresh it
|
||||
* return
|
||||
* 0 : success
|
||||
* 1 : fail
|
||||
*------------------------------------------*/
|
||||
* @param sd : player
|
||||
* @param stor : guild_storage
|
||||
* @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)
|
||||
{
|
||||
nullpo_retr(1, sd);
|
||||
@ -520,13 +582,12 @@ int guild_storage_delitem(struct map_session_data* sd, struct guild_storage* sto
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Attempt to add an item in guild storage from inventory, then refresh it
|
||||
* @index : inventory idx
|
||||
* return
|
||||
* 0 : fail
|
||||
* 1 : succes
|
||||
*------------------------------------------*/
|
||||
* @param sd : player
|
||||
* @param amount : number of item to delete
|
||||
* @return 1:success, 0:fail
|
||||
*/
|
||||
int storage_guild_storageadd(struct map_session_data* sd, int index, int amount)
|
||||
{
|
||||
struct guild_storage *stor;
|
||||
@ -561,13 +622,13 @@ int storage_guild_storageadd(struct map_session_data* sd, int index, int amount)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Attempt to retrieve an item from guild storage to inventory, then refresh it
|
||||
* @index : storage idx
|
||||
* return
|
||||
* 0 : fail
|
||||
* 1 : succes
|
||||
*------------------------------------------*/
|
||||
* @param sd : player
|
||||
* @param index : index of item in storage
|
||||
* @param amount : number of item to get
|
||||
* @return 1:success, 0:fail
|
||||
*/
|
||||
int storage_guild_storageget(struct map_session_data* sd, int index, int amount)
|
||||
{
|
||||
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)
|
||||
guild_storage_delitem(sd,stor,index,amount);
|
||||
else //inform fail
|
||||
else {//inform fail
|
||||
clif_additem(sd,0,0,flag);
|
||||
// log_fromstorage(sd, index, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
// log_fromstorage(sd, index, 1);
|
||||
|
||||
/*==========================================
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to add an item in guild storage from cart, then refresh it
|
||||
* @index : cart inventory idx
|
||||
* return
|
||||
* 0 : fail
|
||||
* 1 : succes
|
||||
*------------------------------------------*/
|
||||
* @param sd : player
|
||||
* @param index : index of item in cart
|
||||
* @param amount : number of item to transfer
|
||||
* @return 1:fail, 0:success
|
||||
*/
|
||||
int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int amount)
|
||||
{
|
||||
struct guild_storage *stor;
|
||||
@ -634,13 +697,13 @@ int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Attempt to retrieve an item from guild storage to cart, then refresh it
|
||||
* @index : storage idx
|
||||
* return
|
||||
* 0 : fail
|
||||
* 1 : succes
|
||||
*------------------------------------------*/
|
||||
* @param sd : player
|
||||
* @param index : index of item in storage
|
||||
* @param amount : number of item to transfert
|
||||
* @return 1:fail, 0:success
|
||||
*/
|
||||
int storage_guild_storagegettocart(struct map_session_data* sd, int index, int amount)
|
||||
{
|
||||
short flag;
|
||||
@ -666,17 +729,19 @@ int storage_guild_storagegettocart(struct map_session_data* sd, int index, int a
|
||||
else {
|
||||
clif_dropitem(sd,index,0);
|
||||
clif_cart_additem_ack(sd,(flag==1)?ADDITEM_TO_CART_FAIL_WEIGHT:ADDITEM_TO_CART_FAIL_COUNT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Request to save guild storage
|
||||
* return
|
||||
* 0 : fail (no storage)
|
||||
* 1 : succes
|
||||
*------------------------------------------*/
|
||||
* @param account_id : account requesting the save
|
||||
* @param guild_id : guild to take the guild_storage
|
||||
* @param flag : ?
|
||||
* @return 0 : fail (no storage), 1 : success (requested)
|
||||
*/
|
||||
int storage_guild_storagesave(int account_id, int guild_id, int flag)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* ACK save of guild storage
|
||||
* return
|
||||
* 0 : fail (no storage)
|
||||
* 1 : succes
|
||||
*------------------------------------------*/
|
||||
* @param guild_id : guild to use the storage
|
||||
* @return 0 : fail (no storage), 1 : succes
|
||||
*/
|
||||
int storage_guild_storagesaved(int guild_id)
|
||||
{
|
||||
struct guild_storage *stor;
|
||||
@ -712,7 +776,11 @@ int storage_guild_storagesaved(int guild_id)
|
||||
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)
|
||||
{
|
||||
struct guild_storage *stor;
|
||||
@ -734,6 +802,12 @@ int storage_guild_storageclose(struct map_session_data* sd)
|
||||
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)
|
||||
{
|
||||
struct guild_storage *stor;
|
||||
|
@ -20,13 +20,13 @@
|
||||
#include <stdio.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
|
||||
|
||||
/*==========================================
|
||||
* Initiates a trade request.
|
||||
*------------------------------------------*/
|
||||
/**
|
||||
* Player initiates a trade request.
|
||||
* @param sd : player requesting the trade
|
||||
* @param target_sd : player requested
|
||||
*/
|
||||
void trade_traderequest(struct map_session_data *sd, struct map_session_data *target_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);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
|
||||
/**
|
||||
* Reply to a trade-request.
|
||||
* Type values:
|
||||
* 0: Char is too far
|
||||
* 1: Character does not exist
|
||||
* 2: Trade failed
|
||||
* 3: Accept
|
||||
* 4: Cancel
|
||||
* Weird enough, the client should only send 3/4
|
||||
* @param sd : player receiving the trade request answer
|
||||
* @param type : answer code \n
|
||||
* 0: Char is too far \n
|
||||
* 1: Character does not exist \n
|
||||
* 2: Trade failed \n
|
||||
* 3: Accept \n
|
||||
* 4: Cancel \n
|
||||
* Weird enough, the client should only send 3/4 \n
|
||||
* and the server is the one that can reply 0~2
|
||||
*------------------------------------------*/
|
||||
*/
|
||||
void trade_tradeack(struct map_session_data *sd, int type)
|
||||
{
|
||||
struct map_session_data *tsd;
|
||||
@ -165,11 +167,14 @@ void trade_tradeack(struct map_session_data *sd, int type)
|
||||
clif_tradestart(sd, type);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* 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 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)
|
||||
{
|
||||
struct item inventory[MAX_INVENTORY];
|
||||
@ -229,9 +234,12 @@ int impossible_trade_check(struct map_session_data *sd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
struct item inventory[MAX_INVENTORY];
|
||||
@ -316,9 +324,12 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* 'Ok' button on the trade window is pressed.
|
||||
*------------------------------------------*/
|
||||
* @param sd : Player that pressed the button
|
||||
*/
|
||||
void trade_tradeok(struct map_session_data *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);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* '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)
|
||||
{
|
||||
struct map_session_data *target_sd;
|
||||
@ -515,9 +532,11 @@ void trade_tradecancel(struct map_session_data *sd)
|
||||
clif_tradecancelled(target_sd);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Execute the trade
|
||||
* 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)
|
||||
{
|
||||
struct map_session_data *tsd;
|
||||
|
170
src/map/unit.c
170
src/map/unit.c
@ -42,30 +42,43 @@
|
||||
#include <string.h>
|
||||
|
||||
|
||||
const short dirx[8]={0,-1,-1,-1,0,1,1,1};
|
||||
const short diry[8]={1,1,0,-1,-1,-1,0,1};
|
||||
// Directions values
|
||||
// 1 0 7
|
||||
// 2 . 6
|
||||
// 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
|
||||
const short diry[8]={1,1,0,-1,-1,-1,0,1}; ///lookup to know where will move to y according dir
|
||||
|
||||
//early declaration
|
||||
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);
|
||||
|
||||
/**
|
||||
* Get the unit_data related to the bl
|
||||
* @param bl : Object to get the unit_data from \n
|
||||
* 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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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 i;
|
||||
@ -123,7 +136,7 @@ int unit_walktoxy_sub(struct block_list *bl)
|
||||
* Retrieve the direct master of a bl if one exists.
|
||||
* @param bl: char to get his master [HOM|ELEM|PET|MER]
|
||||
* @return map_session_data of master or NULL
|
||||
**/
|
||||
*/
|
||||
TBL_PC* unit_get_master(struct block_list *bl)
|
||||
{
|
||||
if(bl)
|
||||
@ -140,7 +153,7 @@ TBL_PC* unit_get_master(struct block_list *bl)
|
||||
* Retrieve a unit's master's teleport timer
|
||||
* @param bl: char to get his master's teleport timer [HOM|ELEM|PET|MER]
|
||||
* @return timer or NULL
|
||||
**/
|
||||
*/
|
||||
int* unit_get_masterteleport_timer(struct block_list *bl)
|
||||
{
|
||||
if(bl)
|
||||
@ -161,7 +174,7 @@ int* unit_get_masterteleport_timer(struct block_list *bl)
|
||||
* @param id: Unit to warp
|
||||
* @param data: Data transferred from timer call
|
||||
* @return 0
|
||||
**/
|
||||
*/
|
||||
int unit_teleport_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
{
|
||||
struct block_list *bl = map_id2bl(id);
|
||||
@ -188,7 +201,7 @@ int unit_teleport_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
* 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]
|
||||
* @return 0
|
||||
**/
|
||||
*/
|
||||
int unit_check_start_teleport_timer(struct block_list *sbl)
|
||||
{
|
||||
TBL_PC *msd = unit_get_master(sbl);
|
||||
@ -223,7 +236,7 @@ int unit_check_start_teleport_timer(struct block_list *sbl)
|
||||
* @param tick: Current tick to decide next timer update
|
||||
* @param data: Data used in timer calls
|
||||
* @return 0 or unit_walktoxy_sub()
|
||||
**/
|
||||
*/
|
||||
static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
{
|
||||
int i;
|
||||
@ -394,7 +407,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
|
||||
* @param id: ID of bl to delay timer on
|
||||
* @param data: Data used in timer calls
|
||||
* @return 1: Success 0: Fail (No valid bl)
|
||||
**/
|
||||
*/
|
||||
int unit_delay_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
{
|
||||
struct block_list *bl = map_id2bl(id);
|
||||
@ -412,7 +425,7 @@ int unit_delay_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
* @param id: ID of bl to delay timer on
|
||||
* @param data: Data used in timer calls (target bl)
|
||||
* @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)
|
||||
{
|
||||
struct block_list *bl = map_id2bl(id), *tbl = map_id2bl(data);
|
||||
@ -438,7 +451,7 @@ int unit_delay_walktobl_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
* &2: Force walking (override can_move) \n
|
||||
* &4: Delay walking for can_move
|
||||
* @return 1: Success 0: Fail or unit_walktoxy_sub()
|
||||
**/
|
||||
*/
|
||||
int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
|
||||
{
|
||||
struct unit_data* ud = NULL;
|
||||
@ -500,7 +513,7 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
|
||||
* This should not be done if there's no path to reach
|
||||
* @param bl: Mob to set state on
|
||||
* @param flag: Whether to set state or not
|
||||
**/
|
||||
*/
|
||||
static inline void set_mobstate(struct block_list* bl, int flag)
|
||||
{
|
||||
struct mob_data* md = BL_CAST(BL_MOB,bl);
|
||||
@ -516,7 +529,7 @@ static inline void set_mobstate(struct block_list* bl, int flag)
|
||||
* @param id: Object's ID
|
||||
* @param data: Data passed through timer function (target)
|
||||
* @return 0
|
||||
**/
|
||||
*/
|
||||
static int unit_walktobl_sub(int tid, unsigned int tick, int id, intptr_t data)
|
||||
{
|
||||
struct block_list *bl = map_id2bl(id);
|
||||
@ -542,7 +555,7 @@ static int unit_walktobl_sub(int tid, unsigned int tick, int id, intptr_t data)
|
||||
* &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
|
||||
* @return 1: Started walking or set timer 0: Failed
|
||||
**/
|
||||
*/
|
||||
int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int flag)
|
||||
{
|
||||
struct unit_data *ud = NULL;
|
||||
@ -604,7 +617,7 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
|
||||
* Set a unit to run, checking for obstacles
|
||||
* @param bl: Object that is running
|
||||
* @return 1: Success 0: Fail
|
||||
**/
|
||||
*/
|
||||
int unit_run(struct block_list *bl)
|
||||
{
|
||||
struct status_change *sc = status_get_sc(bl);
|
||||
@ -675,12 +688,13 @@ int unit_run(struct block_list *bl)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** [Jobbie/3CeAM] \n
|
||||
* Exclusive function used for Wug Dash
|
||||
/**
|
||||
* Char movement with wugdash
|
||||
* @author [Jobbie/3CeAM]
|
||||
* @param bl: Object that is dashing
|
||||
* @param sd: Player
|
||||
* @return 1: Success 0: Fail
|
||||
**/
|
||||
*/
|
||||
int unit_wugdash(struct block_list *bl, struct map_session_data *sd)
|
||||
{
|
||||
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]))
|
||||
return 0;
|
||||
|
||||
nullpo_ret(sd);
|
||||
nullpo_ret(sd); //FIXME do we really need that check since we rechecking afterward
|
||||
nullpo_ret(bl);
|
||||
|
||||
if (!unit_can_move(bl)) {
|
||||
@ -751,7 +765,7 @@ int unit_wugdash(struct block_list *bl, struct map_session_data *sd)
|
||||
* @param target: Target
|
||||
* @param dist: How far bl should run
|
||||
* @return 1: Success 0: Fail
|
||||
**/
|
||||
*/
|
||||
int unit_escape(struct block_list *bl, struct block_list *target, short dist)
|
||||
{
|
||||
uint8 dir = map_calc_dir(target, bl->x, bl->y);
|
||||
@ -768,7 +782,7 @@ int unit_escape(struct block_list *bl, struct block_list *target, short dist)
|
||||
* @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
|
||||
* @return 1: Success 0: Fail
|
||||
**/
|
||||
*/
|
||||
int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath)
|
||||
{
|
||||
short dx,dy;
|
||||
@ -837,7 +851,7 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool
|
||||
* @param bl: Object to set direction
|
||||
* @param dir: Direction (0-7)
|
||||
* @return 0
|
||||
**/
|
||||
*/
|
||||
int unit_setdir(struct block_list *bl,unsigned char dir)
|
||||
{
|
||||
struct unit_data *ud;
|
||||
@ -855,7 +869,7 @@ int unit_setdir(struct block_list *bl,unsigned char dir)
|
||||
* Gets direction of a unit
|
||||
* @param bl: Object to get direction
|
||||
* @return direction (0-7)
|
||||
**/
|
||||
*/
|
||||
uint8 unit_getdir(struct block_list *bl)
|
||||
{
|
||||
struct unit_data *ud;
|
||||
@ -874,7 +888,7 @@ uint8 unit_getdir(struct block_list *bl)
|
||||
* @param count: How many cells to push bl
|
||||
* @param flag: Whether or not to send position packet updates
|
||||
* @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)
|
||||
{
|
||||
if(count) {
|
||||
@ -943,7 +957,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
|
||||
* @param y: Destination cell Y
|
||||
* @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)
|
||||
**/
|
||||
*/
|
||||
int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
|
||||
{
|
||||
struct unit_data *ud;
|
||||
@ -1019,7 +1033,7 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
|
||||
* &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)
|
||||
* @return Success(1); Failed(0);
|
||||
**/
|
||||
*/
|
||||
int unit_stop_walking(struct block_list *bl,int type)
|
||||
{
|
||||
struct unit_data *ud;
|
||||
@ -1070,7 +1084,7 @@ int unit_stop_walking(struct block_list *bl,int type)
|
||||
* @param skill_id: Skill ID
|
||||
* @param skill_lv: Skill Level
|
||||
* @return unit_skilluse_id2()
|
||||
**/
|
||||
*/
|
||||
int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv)
|
||||
{
|
||||
return unit_skilluse_id2(
|
||||
@ -1084,7 +1098,7 @@ int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uin
|
||||
* Checks if a unit is walking
|
||||
* @param bl: Object to check walk status
|
||||
* @return Walking(1); Not Walking(0)
|
||||
**/
|
||||
*/
|
||||
int unit_is_walking(struct block_list *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);
|
||||
}
|
||||
|
||||
/** [Skotlex] \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
|
||||
* Some statuses are still checked here due too specific variables
|
||||
* @author [Skotlex]
|
||||
* @param bl: Object to check
|
||||
* @return Can move(1); Can't move(0)
|
||||
**/
|
||||
*/
|
||||
int unit_can_move(struct block_list *bl) {
|
||||
struct map_session_data *sd;
|
||||
struct unit_data *ud;
|
||||
@ -1155,7 +1170,7 @@ int unit_can_move(struct block_list *bl) {
|
||||
* @param id: Object ID
|
||||
* @param data: Data passed through timer function (unit_data)
|
||||
* @return 0
|
||||
**/
|
||||
*/
|
||||
int unit_resume_running(int tid, unsigned int tick, int id, intptr_t data)
|
||||
{
|
||||
|
||||
@ -1184,7 +1199,7 @@ int unit_resume_running(int tid, unsigned int tick, int id, intptr_t data)
|
||||
* 0: Damage induced delay; Do not change previous delay \n
|
||||
* 1: Skill induced delay; Walk delay can only be increased, not decreased
|
||||
* @return Success(1); Fail(0);
|
||||
**/
|
||||
*/
|
||||
int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int type)
|
||||
{
|
||||
struct unit_data *ud = unit_bl2ud(bl);
|
||||
@ -1229,7 +1244,7 @@ int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int
|
||||
* @param casttime: Initial cast time before cast time reductions
|
||||
* @param castcancel: Whether or not the skill can be cancelled by interuption (hit)
|
||||
* @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)
|
||||
{
|
||||
struct unit_data *ud;
|
||||
@ -1591,7 +1606,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
|
||||
* @param skill_id: Skill ID
|
||||
* @param skill_lv: Skill Level
|
||||
* @return unit_skilluse_pos2()
|
||||
**/
|
||||
*/
|
||||
int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv)
|
||||
{
|
||||
return unit_skilluse_pos2(
|
||||
@ -1611,7 +1626,7 @@ int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, uint
|
||||
* @param casttime: Initial cast time before cast time reductions
|
||||
* @param castcancel: Whether or not the skill can be cancelled by interuption (hit)
|
||||
* @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)
|
||||
{
|
||||
struct map_session_data *sd = NULL;
|
||||
@ -1751,7 +1766,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
|
||||
* @param ud: Unit data
|
||||
* @param target_id: Target ID (bl->id)
|
||||
* @return 0
|
||||
**/
|
||||
*/
|
||||
int unit_set_target(struct unit_data* ud, int target_id)
|
||||
{
|
||||
struct unit_data * ux;
|
||||
@ -1774,7 +1789,7 @@ int unit_set_target(struct unit_data* ud, int target_id)
|
||||
* Stop a unit's attacks
|
||||
* @param bl: Object to stop
|
||||
* @return 0
|
||||
**/
|
||||
*/
|
||||
int unit_stop_attack(struct block_list *bl)
|
||||
{
|
||||
struct unit_data *ud = unit_bl2ud(bl);
|
||||
@ -1793,7 +1808,7 @@ int unit_stop_attack(struct block_list *bl)
|
||||
* Removes a unit's target due to being unattackable
|
||||
* @param bl: Object to unlock target
|
||||
* @return 0
|
||||
**/
|
||||
*/
|
||||
int unit_unattackable(struct block_list *bl)
|
||||
{
|
||||
struct unit_data *ud = unit_bl2ud(bl);
|
||||
@ -1815,7 +1830,7 @@ int unit_unattackable(struct block_list *bl)
|
||||
* @param target_id: Target ID (bl->id)
|
||||
* @param continuous: Whether or not the attack is ongoing
|
||||
* @return Success(0); Fail(1);
|
||||
**/
|
||||
*/
|
||||
int unit_attack(struct block_list *src,int target_id,int continuous)
|
||||
{
|
||||
struct block_list *target;
|
||||
@ -1867,12 +1882,13 @@ int unit_attack(struct block_list *src,int target_id,int continuous)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** [Skotlex] \n
|
||||
/**
|
||||
* Cancels an ongoing combo, resets attackable time, and restarts the \n
|
||||
* attack timer to resume attack after amotion time
|
||||
* @author [Skotlex]
|
||||
* @param bl: Object to cancel combo
|
||||
* @return Success(1); Fail(0);
|
||||
**/
|
||||
*/
|
||||
int unit_cancel_combo(struct block_list *bl)
|
||||
{
|
||||
struct unit_data *ud;
|
||||
@ -1900,7 +1916,7 @@ int unit_cancel_combo(struct block_list *bl)
|
||||
* @param y: Y coordinate that will be path searched
|
||||
* @param easy: Easy(1) or Hard(0) path check (hard attempts to go around obstacles)
|
||||
* @return true or false
|
||||
**/
|
||||
*/
|
||||
bool unit_can_reach_pos(struct block_list *bl,int x,int y, int easy)
|
||||
{
|
||||
nullpo_retr(false, bl);
|
||||
@ -1920,7 +1936,7 @@ bool unit_can_reach_pos(struct block_list *bl,int x,int y, int easy)
|
||||
* @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
|
||||
* @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)
|
||||
{
|
||||
int i;
|
||||
@ -1962,7 +1978,7 @@ bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range,
|
||||
* @param ty: Y coordinate to go to
|
||||
* @param dir: Direction which to be 2 cells from master's position
|
||||
* @return Success(0); Fail(1);
|
||||
**/
|
||||
*/
|
||||
int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
|
||||
{
|
||||
int dx, dy, x, y, i, k;
|
||||
@ -2019,7 +2035,7 @@ int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
|
||||
* @param tid: Timer ID
|
||||
* @param tick: Current tick
|
||||
* @return Attackable(1); Unattackable(0);
|
||||
**/
|
||||
*/
|
||||
static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int tick)
|
||||
{
|
||||
struct block_list *target;
|
||||
@ -2159,7 +2175,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
|
||||
* @param id: Object to cancel attack if applicable
|
||||
* @param data: Data passed from timer call
|
||||
* @return 0
|
||||
**/
|
||||
*/
|
||||
static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
{
|
||||
struct block_list *bl;
|
||||
@ -2176,7 +2192,7 @@ static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
* &1: Cast-Cancel invoked \n
|
||||
* &2: Cancel only if skill is cancellable
|
||||
* @return Success(1); Fail(0);
|
||||
**/
|
||||
*/
|
||||
int unit_skillcastcancel(struct block_list *bl,int type)
|
||||
{
|
||||
struct map_session_data *sd = NULL;
|
||||
@ -2235,7 +2251,7 @@ int unit_skillcastcancel(struct block_list *bl,int type)
|
||||
/**
|
||||
* Initialized data on a unit
|
||||
* @param bl: Object to initialize data on
|
||||
**/
|
||||
*/
|
||||
void unit_dataset(struct block_list *bl)
|
||||
{
|
||||
struct unit_data *ud;
|
||||
@ -2255,7 +2271,7 @@ void unit_dataset(struct block_list *bl)
|
||||
* Gets the number of units attacking another unit
|
||||
* @param bl: Object to check amount of targets
|
||||
* @return number of targets or 0
|
||||
**/
|
||||
*/
|
||||
int unit_counttargeted(struct block_list* bl)
|
||||
{
|
||||
struct unit_data* ud;
|
||||
@ -2264,25 +2280,12 @@ int unit_counttargeted(struct block_list* bl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this even used? Why is it a function?
|
||||
**/
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
nullpo_ret(bl);
|
||||
@ -2309,7 +2312,7 @@ int unit_changeviewsize(struct block_list *bl,short size)
|
||||
* 1: Death, appropriate cleanup performed
|
||||
* @param file, line, func: Call information for debug purposes
|
||||
* @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)
|
||||
{
|
||||
struct unit_data *ud = unit_bl2ud(bl);
|
||||
@ -2542,7 +2545,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
|
||||
* @param clrtype: How bl is being removed \n
|
||||
* 0: Assume bl is being warped \n
|
||||
* 1: Death, appropriate cleanup performed
|
||||
**/
|
||||
*/
|
||||
void unit_remove_map_pc(struct map_session_data *sd, clr_type 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
|
||||
* Also free his pets/homon/mercenary/elemental/etc if he have any
|
||||
* @param sd: Player
|
||||
**/
|
||||
*/
|
||||
void unit_free_pc(struct map_session_data *sd)
|
||||
{
|
||||
if (sd->pd) unit_free(&sd->pd->bl,CLR_OUTSIGHT);
|
||||
@ -2579,7 +2583,7 @@ void unit_free_pc(struct map_session_data *sd)
|
||||
* 0: Assume bl is being warped \n
|
||||
* 1: Death, appropriate cleanup performed
|
||||
* @return 0
|
||||
**/
|
||||
*/
|
||||
int unit_free(struct block_list *bl, clr_type clrtype)
|
||||
{
|
||||
struct unit_data *ud = unit_bl2ud( bl );
|
||||
@ -2804,7 +2808,8 @@ int unit_free(struct block_list *bl, clr_type clrtype)
|
||||
|
||||
/**
|
||||
* Initialization function for unit on map start
|
||||
**/
|
||||
* called in map::do_init
|
||||
*/
|
||||
int do_init_unit(void)
|
||||
{
|
||||
add_timer_func_list(unit_attack_timer, "unit_attack_timer");
|
||||
@ -2816,6 +2821,11 @@ int do_init_unit(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unit module destructor, (thing to do before closing the module)
|
||||
* called in map::do_final
|
||||
* @return 0
|
||||
*/
|
||||
int do_final_unit(void)
|
||||
{
|
||||
// Nothing to do
|
||||
|
@ -14,8 +14,11 @@ struct map_session_data;
|
||||
#include "path.h" // struct walkpath_data
|
||||
#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 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 skill_timerskill *skilltimerskill[MAX_SKILLTIMERSKILL];
|
||||
struct skill_unit_group *skillunit[MAX_SKILLUNITGROUP];
|
||||
@ -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_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.
|
||||
int unit_stop_walking(struct block_list *bl,int type);
|
||||
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_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_ */
|
||||
|
@ -20,21 +20,29 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static int vending_nextid = 0;
|
||||
static DBMap *vending_db;
|
||||
static int vending_nextid = 0; ///Vending_id counter
|
||||
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(){
|
||||
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;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Close shop
|
||||
*------------------------------------------*/
|
||||
/**
|
||||
* Make a player close his shop
|
||||
* @param sd : player session
|
||||
*/
|
||||
void vending_closevending(struct map_session_data* 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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
|
||||
* @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) {
|
||||
int i, j;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/// 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) {
|
||||
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) {
|
||||
int i, c, slot;
|
||||
unsigned int idx, cidx;
|
||||
@ -367,10 +396,19 @@ bool vending_searchall(struct map_session_data* sd, const struct s_search_store_
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the vending module
|
||||
* called in map::do_init
|
||||
*/
|
||||
void do_final_vending(void) {
|
||||
db_destroy(vending_db);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destory the vending module
|
||||
* called in map::do_final
|
||||
*/
|
||||
void do_init_vending(void) {
|
||||
vending_db = idb_alloc(DB_OPT_BASE);
|
||||
vending_nextid = 0;
|
||||
|
@ -10,9 +10,9 @@ struct map_session_data;
|
||||
struct s_search_store_search;
|
||||
|
||||
struct s_vending {
|
||||
short index; //cart index (return item data)
|
||||
short amount; //amout of the item for vending
|
||||
unsigned int value; //at wich price
|
||||
short index; /// cart index (return item data)
|
||||
short amount; ///amout of the item for vending
|
||||
unsigned int value; ///at wich price
|
||||
};
|
||||
|
||||
DBMap * vending_getdb();
|
||||
|
Loading…
x
Reference in New Issue
Block a user