Skill Changes:

* Wizard/Warlock Skill
  * Moved Sightrasher (WZ_SIGHTRASHER) requirement to check Sight (SC_SIGHT) is active or not to skill_check_condition_castend section.
  * Fixed Sightrasher (WZ_SIGHTRASHER) splash area to 3x3. (bugreport:9298)
  * Now Comet (WL_COMET) cannot hits Hiding target (The mistake is not at flag 0x10000 in skill_db.txt, the flash should be added by SD_ANIMATION). (bugreport:8909).
  * Now Reading Spell Book (WL_READING_SB) checking the number of available spell books in Spell Book DB first to prevent infinite loop.
* Sage Skill
  * Now Abracadabra (SA_ABRACADABRA) checking the number of available skills in Abra DB first to prevent infinite loop.
  * Reduced MAX_SKILL_ABRA_DB from 350 to 160.
* Shadow Chaser Skill
  * Fixed Chaos Panic (SC_CHAOSPANIC) effect. (bugreport:9321).
* Genetic Skill
  * Now Wall of Thorn (GN_WALLOFTHORN) can be knocked back but not a whole skill group and durability (HP & max hit) for each skill unit.
* Guillotine Cross Skill
  * Now Magic Mushroom (SC_MAGICMUSHROOM) effect checks the number of available skills in Magic Mushroom DB first to prevent infinite loop.
  * Changed 'RemoveFlag' in db/magicmushroom_db.txt value to 1 to remove skill by importing. (bugreport:9322).
* Wanderer/Minstrel Skill
  * Now Randomize Spell (WM_RANDOMIZESPELL) checks the number of available skills in Improvise DB first to prevent infinite loop.
  * Reduced MAX_SKILL_IMPROVISE_DB from 50 to 30.
* Rebellion Skill
  * Cleaned up, added, corrected some (missing) sequences & DB values.
  * Fixed Hammer of God (RL_HAMMER_OF_GOD) splash damage.
  * Fixed Shaterred Strom (RL_S_STORM) push back & force to sit effect (for player, or stun for monsters) (first implementation leftover).
  * Fixed Slug Shot (RL_SLUGSHOT) hitrate-distance penalty (first implementation leftover).
  * Fixed Howling Mine (RL_H_MINE) damage ratios (first implementation leftover).
  * Now Bind Trap (RL_B_TRAP) only can be placed 1 at same time.
  * Fixed Bind Trap (RL_B_TRAP) damage calculation by using Caster's DEX, Target's Current HP, & Skill Level. FIXME: Exact formula still unknown (refers to idAthena formula).
  * Now Dragon Tail (RL_D_TAIL) doesn't split damage among targets anymore.
  * Now Crimson Marker (RL_C_MARKER) will fails to cast if no slot available.
  * Implemented official packet `ZC_C_MARKERINFO` of Crimson Marker (RL_C_MARKER) mini-map marker (first implementation leftover). !TODO: Confirm the packet for older or newer clients (idAthena partial merge r1497)
  * References: http://forums.irowiki.org/showpost.php?p=1387992&postcount=968, follow up 507f047, dd67f9d

Misc:
* Fixed some skills that should work only in shoot range (map_foreachinshootange, by default), and added check for respecting *skill_wall_check* (map_foreachinrange).
* Fixed item stackable check for `/item` command, follow up 9b4d922.
* Fixed npc source file isn't removed properly by @unloadnpcfile. (bugreport:9311).
* Added constantan for status_change_start() and sc_start() scripts as well
  * SCSTART_NONE = 0x0
  * SCSTART_NOAVOID = 0x1
  * SCSTART_NOTICKDEF = 0x2
  * SCSTART_LOADED = 0x4
  * SCSTART_NORATEDEF = 0x8
  * SCSTART_NOICON = 0x10
* Moved and changed itemdb_unique_id() to pc_generate_unique_id().
* Seperated check for skill SC requirement to skill_check_condition_sc_required().
* Added skill unit flag `UF_KNOCKBACK_GROUP`, just an option to make skill unit can be knocked back a whole group.
* Typos and other minor changes!

Signed-off-by: Cydh Ramdh <house.bad@gmail.com>
This commit is contained in:
Cydh Ramdh 2014-10-01 17:42:30 +07:00
parent c6ba813994
commit ce090ce916
30 changed files with 1041 additions and 727 deletions

View File

@ -4,5 +4,5 @@
// Structure of Database:
// SkillID{,RemoveFlag}
//
// - To remove entry by importing, put any value on 'RemoveFlag'
// - To remove entry by importing, put 1 value on 'RemoveFlag'

View File

@ -4,7 +4,7 @@
// Structure of Database:
// SkillID{,RemoveFlag}
//
// - To remove entry by importing, put any value on 'RemoveFlag'
// - To remove entry by importing, put 1 value on 'RemoveFlag'
7 //SM_MAGNUM
8 //SM_ENDURE

View File

@ -2244,6 +2244,7 @@ packet_ver: 45
0x023B,26,friendslistadd,2
0x0361,5,hommenu,2:4
0x0887,36,storagepassword,2:4:20
0x09C1,10,ZC_C_MARKERINFO,2:6:8
//2013-12-23Ragexe
packet_ver: 46
@ -2277,13 +2278,14 @@ packet_ver: 46
0x0361,5,hommenu,2:4
0x08A4,36,storagepassword,2:4:20
//New Packets
0x09D4,2,dull,0 //npcshopclosed
//0x097E,12 //ZC_UPDATE_RANKING_POINT
0x09B4,6,dull,0 //Cash Shop - Special Tab
0x09CE,102,itemmonster,2
0x09D4,2,dull,0 //npcshopclosed
//NPC Market
0x09D8,2,dull,0 //npcmarketclosed
0x09D6,-1,dull,0 //npcmarketpurchase
0x09D8,2,dull,0 //npcmarketclosed
0x09DF,7
0x09B4,6,dull,0 // Cash Shop - Special Tab
//Add new packets here
//packet_ver: 47

View File

@ -6,22 +6,23 @@
// layout = -1:special, 0:1*1, 1:3*3, 2:5*5, up to 5:11*11
// target = friend (party +guildmates +neutral players) / party / guild
// ally (party +guildmates) / all / sameguild (guild but no allies) / enemy
// flag 0x0001(UF_DEFNOTENEMY) If 'defunit_not_enemy' is set, the target is changed to 'friend'
// 0x0002(UF_NOREITERRATION) Spell cannot be stacked
// 0x0004(UF_NOFOOTSET) Spell cannot be cast near/on targets
// 0x0008(UF_NOOVERLAP) Spell effects do not overlap
// 0x0010(UF_PATHCHECK) Only cells with a shootable path will be placed
// 0x0020(UF_NOPC) Spell cannot affect players.
// 0x0040(UF_NOMOB) Spell cannot affect mobs.
// 0x0080(UF_SKILL) Spell CAN affect skills.
// 0x0100(UF_DANCE) Dance skill
// 0x0200(UF_ENSEMBLE) Ensemble skill
// 0x0400(UF_SONG) Song skill
// 0x0800(UF_DUALMODE) Spell has effects both at an interval and when you step in/out
// 0x1000(UF_NOKNOCKBACK) Cannot be knocked back (only unit that can be damaged)
// 0x2000(UF_RANGEDSINGLEUNIT) Layout hack, use layout range propriety but only display center.
// 0x4000(UF_REM_CRAZYWEED) Removed if be overlapped by GN_CRAZYWEED
// 0x8000(UF_REM_FIRERAIN) Removed if be overlapped by RL_FIRE_RAIN
// flag 0x00001(UF_DEFNOTENEMY) If 'defunit_not_enemy' is set, the target is changed to 'friend'
// 0x00002(UF_NOREITERRATION) Spell cannot be stacked
// 0x00004(UF_NOFOOTSET) Spell cannot be cast near/on targets
// 0x00008(UF_NOOVERLAP) Spell effects do not overlap
// 0x00010(UF_PATHCHECK) Only cells with a shootable path will be placed
// 0x00020(UF_NOPC) Spell cannot affect players.
// 0x00040(UF_NOMOB) Spell cannot affect mobs.
// 0x00080(UF_SKILL) Spell CAN affect skills.
// 0x00100(UF_DANCE) Dance skill
// 0x00200(UF_ENSEMBLE) Ensemble skill
// 0x00400(UF_SONG) Song skill
// 0x00800(UF_DUALMODE) Spell has effects both at an interval and when you step in/out
// 0x01000(UF_NOKNOCKBACK) Cannot be knocked back (only unit that can be damaged)
// 0x02000(UF_RANGEDSINGLEUNIT) Layout hack, use layout range propriety but only display center.
// 0x04000(UF_REM_CRAZYWEED) Removed if be overlapped by GN_CRAZYWEED
// 0x08000(UF_REM_FIRERAIN) Removed if be overlapped by RL_FIRE_RAIN
// 0x10000(UF_KNOCKBACK_GROUP) Knock back a whole skill group (by default, skill unit is knocked back each unit)
// Example: 0x006 = 0x002+0x004 -> Cannot be stacked nor cast near targets
//
// Notes:
@ -126,7 +127,7 @@
2299,0xcc, , 0, 1,1000,all, 0xC006 //SC_MANHOLE
2300,0xcd, , 0, 0,1000,all, 0xC006 //SC_DIMENSIONDOOR
2301,0xce, , 2, 0, -1,all, 0xE00E //SC_CHAOSPANIC
2301,0xce, , 2, 0,1000,all, 0xE00E //SC_CHAOSPANIC
2302,0xcf, , 2, 0, -1,all, 0xE002 //SC_MAELSTROM
2303,0xd0, , 3, 0, -1,all, 0xE058 //SC_BLOODYLUST
2304,0xd1, , 0, 2, 500,enemy, 0x018 //SC_FEINTBOMB
@ -151,7 +152,7 @@
2468,0xf4, , 0, 1,1000,all, 0x010 //SO_EARTH_INSIGNIA
2479,0xe5, , 0, 1,1000,enemy, 0xC006 //GN_THORNS_TRAP
2482,0xe6,0x7f, -1, 1, 300,enemy, 0xD000 //GN_WALLOFTHORN
2482,0xe6,0x7f, -1, 1, 300,enemy, 0xC000 //GN_WALLOFTHORN
2484,0x86, , 0, 1, 100,enemy, 0x080 //GN_CRAZYWEED_ATK
2485,0xe7, , 0, 2,2000,enemy, 0x8098 //GN_DEMONIC_FIRE
2487,0xe8, , 2, 0, -1,enemy, 0x2000 //GN_FIRE_EXPANSION_SMOKE_POWDER

View File

@ -1643,11 +1643,11 @@
//-- RL_RICHS_COIN
2552,0,1000,0,600000,0,0,-1
//-- RL_MASS_SPIRAL
2553,0,1000,0,0,30000,1000,-1
2553,2000,1000,0,0,30000,1000,-1
//-- RL_BANISHING_BUSTER
2554,3000:2500:2000:1500:1000,1000,0,0,0,1500,-1
//-- RL_B_TRAP
2555,0,0,0,10000:11000:12000:13000:14000,0,2000,-1
2555,0,0,0,4000,6000:7000:8000:9000:10000,2000,-1
//-- RL_FLICKER
2556,0,500,0,0,0,2000,-1
//-- RL_S_STORM
@ -1659,27 +1659,27 @@
//-- RL_C_MARKER
2560,0,0,0,30000,0,1000,-1
//-- RL_FIREDANCE
2561,0,1500,0,0,0,5000,-1
2561,1600:1500:1400:1200:1000,1500,0,0,0,5000,-1
//-- RL_H_MINE
2562,0,1500,0,30000,15000,2000,-1
2562,2000,1500,0,30000,15000,5000:4500:4000:3500:3000,-1
//-- RL_P_ALTER
2563,0,1000,0,60000,0,5000,-1
2563,0,1000,0,30000:45000:60000:75000:90000,0,5000,-1
//-- RL_FALLEN_ANGEL
2564,0,1500,0,0,0,4500:4000:3500:2500:2000,-1
//-- RL_R_TRIP
2565,0,1500,0,0,0,3000,-1
//-- RL_D_TAIL
2566,0,1500,0,0,0,5000,-1
2566,2000,1500,0,0,0,5000,-1
//-- RL_FIRE_RAIN
2567,0,1500,0,100,0,5000,-1
//-- RL_HEAT_BARREL
2568,0,1000,0,60000,10000,10000,-1
//-- RL_AM_BLAST
2569,2000,1500,0,0,6000:7000:8000:9000:10000,1000,-1
2569,2000,1500,0,0,6000:7000:8000:9000:10000,1000,1000
//-- RL_SLUGSHOT
2570,5000:6000:7000:8000:9000,1000,0,0,10000,1500,1000
2570,5000:6000:7000:8000:9000,1000,0,2000,0,1500,1000
//-- RL_HAMMER_OF_GOD
2571,0,1000,0,0,3000:3000:4000:4000:5000,3000,-1
2571,3000,1000,0,0,3000:3000:4000:4000:5000,3000,-1
//-- RL_R_TRIP_PLUSATK
//2572,0,0,0,0,0,0,-1
//-- RL_B_FLICKER_ATK

View File

@ -864,7 +864,7 @@
1003,0,0,0,0,0,0,1,0,no,0,0x1,0,weapon,0,0x0, AS_SONICACCEL,Sonic Acceleration
1004,9,8,1,0,0x8,0,1,1,no,0,0x1,0,weapon,0,0x0, AS_VENOMKNIFE,Throw Venom Knife
1005,1,6,1,0,0x1,0,1,1,no,0,0x1,0,weapon,0,0x0, RG_CLOSECONFINE,Close Confine
1006,0,6,4,3,0,2,1,1,yes,0,0x1,0,magic,3,0x20, WZ_SIGHTBLASTER,Sight Blaster
1006,0,6,4,3,0,1,1,1,yes,0,0x1,0,magic,3,0x20, WZ_SIGHTBLASTER,Sight Blaster
1007,0,6,4,0,0x1,0,1,0,no,0,0x1,0,none,0,0x0, SA_CREATECON,Create Elemental Converter
1008,9,6,1,1,0x1,0,1,1,yes,0,0x1,0,magic,0,0x0, SA_ELEMENTWATER,Elemental Change Water
1009,-9,6,1,0,0,0,1,1,no,0,0x1,0,weapon,3,0x0, HT_PHANTASMIC,Phantasmic Arrow
@ -1235,25 +1235,25 @@
// Rebellion
//2551,0,0,0,0,0,0,10,0,no,0,0,0,none,0,0, RL_GLITTERING_GREED,Flip The Coin Greed
2552,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0,0x0, RL_RICHS_COIN,Rich's Coin
2553,15,6,1,-1,0,0,5,1,no,0,0,0,weapon,0,0x0, RL_MASS_SPIRAL,Mass Spiral
2554,9,6,1,-1,0x2,2,5,1,no,0,0,0,weapon,0,0x0, RL_BANISHING_BUSTER,Banishing Buster
2555,3,6,2,0,0x1,1,5,1,no,0,0,3,misc,0,0x0, RL_B_TRAP,Bind Trap
2553,-9,6,1,-1,0,0,5,1,no,0,0,0,weapon,0,0x0, RL_MASS_SPIRAL,Mass Spiral
2554,-9,6,1,-1,0x2,2,5,1,no,0,0,0,weapon,0,0x0, RL_BANISHING_BUSTER,Banishing Buster
2555,3:4:4:5:5,6,2,0,0x1,1,5,1,no,0,0,1,misc,0,0x0, RL_B_TRAP,Bind Trap
2556,0,6,4,0,0x3,-1,1,1,no,0,0,0,none,0,0x0, RL_FLICKER,Flicker
2557,9,6,1,-1,0x2,2,5,1,no,0,0,0,weapon,0,0x0, RL_S_STORM,Shatter Storm
2557,-9,6,1,-1,0x2,2,5,1,no,0,0,0,weapon,0,0x0, RL_S_STORM,Shatter Storm
2558,0,6,4,0,0x1,0,10,1,no,0,0,0,none,0,0x0, RL_E_CHAIN,Eternal Chain
2559,-9,6,4,-1,0x3,21,1,1,no,0,0x0,0,weapon,0,0x0, RL_QD_SHOT,Quick Draw Shot
2560,11,6,1,0,0x1,0,1,1,no,0,0,3,none,0,0x0, RL_C_MARKER,Crimson Marker
2561,0,6,4,-1,0x2,2,5,1,no,0,0,0,weapon,0,0x0, RL_FIREDANCE,Fire Dance
2562,7:8:9:10:11,6,1,-1,0x2,2,5,1,no,0,0,0,weapon,0,0x0, RL_H_MINE,Howling Mine
2559,-9,6,4,-1,0x0,10,1,1,no,0,0x0,0,weapon,0,0x0, RL_QD_SHOT,Quick Draw Shot
2560,-9,6,1,0,0x1,0,1,1,no,0,0,3,none,0,0x0, RL_C_MARKER,Crimson Marker
2561,0,6,4,-1,0x2,3,5,1,no,0,0,0,weapon,0,0x0, RL_FIREDANCE,Fire Dance
2562,-9,6,1,-1,0x0,2,5,1,no,0,0,0,weapon,0,0x0, RL_H_MINE,Howling Mine
2563,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x0, RL_P_ALTER,Platinum Alter
2564,9,6,2,0,0x1,0,5,1,no,0,0,0,none,0,0x0, RL_FALLEN_ANGEL,Fallen Angel
2564,-9,6,2,0,0x1,0,5,1,no,0,0,0,none,0,0x0, RL_FALLEN_ANGEL,Fallen Angel
2565,0,6,4,-1,0x2,3:3:4:5:6,5,1,no,0,0,0,weapon,3,0x0, RL_R_TRIP,Round Trip
2566,0,6,4,-1,0x3,-1,5,1,no,0,0,0,weapon,0,0x0, RL_D_TAIL,Dragon Tail
2567,9,6,2,-1,0x2,1,5,1,no,0,0,0,weapon,0,0, RL_FIRE_RAIN,Fire Rain
2567,-9,6,2,-1,0x2,1,5,1,no,0,0,0,weapon,0,0, RL_FIRE_RAIN,Fire Rain
2568,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x0, RL_HEAT_BARREL,Heat Barrel
2569,9,6,1,-1,0,0,5,1,no,0,0,0,weapon,0,0x0, RL_AM_BLAST,Anti-Material Blast
2570,9,6,1,-1,0,0,5,1,no,0,0,0,weapon,0,0x0, RL_SLUGSHOT,Slug Shot
2571,7:8:9:10:11,6,2,-1,0x2,2,5,1,no,0,0,0,weapon,0,0x0, RL_HAMMER_OF_GOD,Hammer of God
2569,-9,6,1,-1,0,0,5,1,no,0,0,0,weapon,0,0x0, RL_AM_BLAST,Anti-Material Blast
2570,-9,6,1,-1,0,0,5,1,no,0,0,0,weapon,6,0x0, RL_SLUGSHOT,Slug Shot
2571,-9,6,2,-1,0x2,2,5,1,no,0,0,0,weapon,0,0x0, RL_HAMMER_OF_GOD,Hammer of God
2572,0,6,1,-1,0x40,0,5,1,no,0,0,0,weapon,0,0, RL_R_TRIP_PLUSATK,Round Trip Plus Attack
//2573,0,6,1,-1,0,0,5,1,no,0,0,0,weapon,0,0, RL_B_FLICKER_ATK,Bind Flicker Attack
//2574,0,6,1,-1,0,0,10,1,no,0,0,0,weapon,0,0, RL_GLITTERING_GREED_ATK,Flip The Coin Greed Attack
@ -1266,7 +1266,7 @@
3004,3:4:5:6:7,8,1,-1,0,0,5,-2,no,0,0,0,weapon,0,0x0, KO_JYUMONJIKIRI,Cross Strike
3005,2,6,1,-1,0,0,5,1,no,0,0,0,weapon,0,0x0, KO_SETSUDAN,Soul Sever
3006,7:8:9:10:11,6,2,-1,0x42,2,5,1,no,0,0,0,weapon,0,0x0, KO_BAKURETSU,Bakuretsu Kunai
3007,5,6,4,-1,0x42,4:4:4:4:5,5,1,no,0,0,0,weapon,0,0x0, KO_HAPPOKUNAI,Happo Kunai
3007,0,6,4,-1,0x42,4:4:4:4:5,5,1,no,0,0,0,weapon,0,0x0, KO_HAPPOKUNAI,Happo Kunai
3008,11,8,2,0,0x56,1:1:1:1:1:1:1:1:1:2,10,-10,no,0,0,0,misc,0,0x0, KO_MUCHANAGE,Mucha Nage
3009,9:10:11:12:13,8,2,-1,0x2,3,5,2,no,0,0,0,weapon,0,0x0, KO_HUUMARANKA,Huuma Shuriken Ranka
3010,3,6,4,0,0x52,0,5,1,no,0,0x80,0,weapon,0,0x10, KO_MAKIBISHI,Makibishi

View File

@ -896,7 +896,7 @@
2554,0,0,55:60:65:70:75,0,0,0,20,3,1,none,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RL_BANISHING_BUSTER
2555,0,0,30:32:34:36:38,0,0,0,17:18:19:20:21,0,0,none,0,1,7940,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RL_B_TRAP
2556,0,0,2,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RL_FLICKER
2557,0,0,55:60:65:70:75,0,0,0,20,3,1,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RL_S_STORM
2557,0,0,55:60:65:70:75,0,0,0,20,3,1,none,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RL_S_STORM
2558,0,0,45,0,0,0,17:18:19:20:21,0,0,none,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RL_E_CHAIN
2559,0,0,5,0,0,0,17:18:19:20:21,3:4:5,1,none,SC_QD_SHOT_READY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RL_QD_SHOT
2560,0,0,10,0,0,0,17:18:19:20:21,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RL_C_MARKER

View File

@ -6,22 +6,23 @@
// layout = -1:special, 0:1*1, 1:3*3, 2:5*5, up to 5:11*11
// target = friend (party +guildmates +neutral players) / party / guild
// ally (party +guildmates) / all / sameguild (guild but no allies) / enemy
// flag 0x0001(UF_DEFNOTENEMY) If 'defunit_not_enemy' is set, the target is changed to 'friend'
// 0x0002(UF_NOREITERRATION) Spell cannot be stacked
// 0x0004(UF_NOFOOTSET) Spell cannot be cast near/on targets
// 0x0008(UF_NOOVERLAP) Spell effects do not overlap
// 0x0010(UF_PATHCHECK) Only cells with a shootable path will be placed
// 0x0020(UF_NOPC) Spell cannot affect players.
// 0x0040(UF_NOMOB) Spell cannot affect mobs.
// 0x0080(UF_SKILL) Spell CAN affect skills.
// 0x0100(UF_DANCE) Dance skill
// 0x0200(UF_ENSEMBLE) Ensemble skill
// 0x0400(UF_SONG) Song skill
// 0x0800(UF_DUALMODE) Spell has effects both at an interval and when you step in/out
// 0x1000(UF_NOKNOCKBACK) Cannot be knocked back (only unit that can be damaged)
// 0x2000(UF_RANGEDSINGLEUNIT) Layout hack, use layout range propriety but only display center.
// 0x4000(UF_REM_CRAZYWEED) Removed if be overlapped by GN_CRAZYWEED
// 0x8000(UF_REM_FIRERAIN) Removed if be overlapped by RL_FIRE_RAIN
// flag 0x00001(UF_DEFNOTENEMY) If 'defunit_not_enemy' is set, the target is changed to 'friend'
// 0x00002(UF_NOREITERRATION) Spell cannot be stacked
// 0x00004(UF_NOFOOTSET) Spell cannot be cast near/on targets
// 0x00008(UF_NOOVERLAP) Spell effects do not overlap
// 0x00010(UF_PATHCHECK) Only cells with a shootable path will be placed
// 0x00020(UF_NOPC) Spell cannot affect players.
// 0x00040(UF_NOMOB) Spell cannot affect mobs.
// 0x00080(UF_SKILL) Spell CAN affect skills.
// 0x00100(UF_DANCE) Dance skill
// 0x00200(UF_ENSEMBLE) Ensemble skill
// 0x00400(UF_SONG) Song skill
// 0x00800(UF_DUALMODE) Spell has effects both at an interval and when you step in/out
// 0x01000(UF_NOKNOCKBACK) Cannot be knocked back (only unit that can be damaged)
// 0x02000(UF_RANGEDSINGLEUNIT) Layout hack, use layout range propriety but only display center.
// 0x04000(UF_REM_CRAZYWEED) Removed if be overlapped by GN_CRAZYWEED
// 0x08000(UF_REM_FIRERAIN) Removed if be overlapped by RL_FIRE_RAIN
// 0x10000(UF_KNOCKBACK_GROUP) Knock back a whole skill group (by default, skill unit is knocked back each unit)
// Example: 0x006 = 0x002+0x004 -> Cannot be stacked nor cast near targets
//
// Notes:
@ -128,8 +129,8 @@
2299,0xcc, , 0, 1,1000,all, 0xC006 //SC_MANHOLE
2300,0xcd, , 0, 0,1000,all, 0xC006 //SC_DIMENSIONDOOR
2301,0xce, , 2, 0, -1,all, 0xC00E //SC_CHAOSPANIC
2302,0xcf, , 2, 0, -1,all, 0xC002 //SC_MAELSTROM
2301,0xce, , 2, 0,1000,all, 0xE00E //SC_CHAOSPANIC
2302,0xcf, , 2, 0, -1,all, 0xE002 //SC_MAELSTROM
2303,0xd0, , 3, 0, -1,all, 0xE058 //SC_BLOODYLUST
2304,0xd1, , 0, 2, 500,enemy, 0x018 //SC_FEINTBOMB
@ -153,7 +154,7 @@
2468,0xf4, , 0, 1,1000,all, 0x010 //SO_EARTH_INSIGNIA
2479,0xe5, , 0, 1,1000,enemy, 0xC006 //GN_THORNS_TRAP
2482,0xe6,0x7f, -1, 1, 300,enemy, 0xD000 //GN_WALLOFTHORN
2482,0xe6,0x7f, -1, 1, 300,enemy, 0xC000 //GN_WALLOFTHORN
2484,0x86, , 0, 1, 100,enemy, 0x080 //GN_CRAZYWEED_ATK
2485,0xe7, , 0, 2,2000,enemy, 0x8098 //GN_DEMONIC_FIRE
2487,0xe8, , 2, 0, -1,enemy, 0x2000 //GN_FIRE_EXPANSION_SMOKE_POWDER

View File

@ -100,8 +100,8 @@
// Renewal variable cast time reduction
#ifdef RENEWAL_CAST
#define VARCAST_REDUCTION(val){ \
if( (varcast_r += val) != 0 && varcast_r >= 0 ) \
time = time * (1 - (float)min(val, 100) / 100); \
if( (varcast_r += (val)) != 0 && varcast_r >= 0 ) \
time = time * (1 - (float)min((val), 100) / 100); \
}
#endif
/**

View File

@ -5775,7 +5775,7 @@ ACMD_FUNC(autotrade) {
if( battle_config.at_timeout ) {
int timeout = atoi(message);
status_change_start(NULL,&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0, ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, 0);
status_change_start(NULL,&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0, ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, SCSTART_NONE);
}
channel_pcquit(sd,0xF); //leave all chan

View File

@ -347,16 +347,16 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
if (sc && sc->count) { //increase dmg by src status
switch(atk_elem){
case ELE_FIRE:
if(sc->data[SC_VOLCANO]) ratio += enchant_eff[sc->data[SC_VOLCANO]->val1-1];
if (sc->data[SC_VOLCANO]) ratio += sc->data[SC_VOLCANO]->val3;
break;
case ELE_WIND:
if(sc->data[SC_VIOLENTGALE]) ratio += enchant_eff[sc->data[SC_VIOLENTGALE]->val1-1];
if (sc->data[SC_VIOLENTGALE]) ratio += sc->data[SC_VIOLENTGALE]->val3;
break;
case ELE_WATER:
if(sc->data[SC_DELUGE]) ratio += enchant_eff[sc->data[SC_DELUGE]->val1-1];
if (sc->data[SC_DELUGE]) ratio += sc->data[SC_DELUGE]->val3;
break;
case ELE_GHOST:
if(sc->data[SC_TELEKINESIS_INTENSE]) ratio += (sc->data[SC_TELEKINESIS_INTENSE]->val3);
if (sc->data[SC_TELEKINESIS_INTENSE]) ratio += (sc->data[SC_TELEKINESIS_INTENSE]->val3);
break;
}
}
@ -886,7 +886,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
else
sce->val3 = 1000; // Next shield
}
status_change_start(src,bl,SC_STUN,10000,0,0,0,0,1000,2);
status_change_start(src,bl,SC_STUN,10000,0,0,0,0,1000,SCSTART_NOTICKDEF);
}
return 0;
}
@ -2247,8 +2247,15 @@ static bool is_attack_hitting(struct Damage wd, struct block_list *src, struct b
hitrate -= 35 - 5 * skill_lv;
break;
case RL_SLUGSHOT:
if (distance_bl(src,target) > 3)
hitrate -= (10 - (skill_lv - 1));
{
int8 dist = distance_bl(src, target);
if (dist > 3) {
// Reduce n hitrate for each cell after initial 3 cells. Different each level
// -10:-9:-8:-7:-6
dist -= 3;
hitrate -= ((11 - skill_lv) * dist);
}
}
break;
}
} else if (sd && wd.type&DMG_MULTI_HIT && wd.div_ == 2) // +1 hit per level of Double Attack on a successful double attack (making sure other multi attack skills do not trigger this) [helvetica]
@ -2422,7 +2429,7 @@ static int battle_get_weapon_element(struct Damage wd, struct block_list *src, s
element = ELE_HOLY;
break;
case RL_H_MINE:
if (sd && sd->skill_id_old == RL_FLICKER) //Force RL_H_MINE deals fire damage if activated by RL_FLICKER
if (sd && sd->flicker) //Force RL_H_MINE deals fire damage if activated by RL_FLICKER
element = ELE_FIRE;
break;
}
@ -3034,9 +3041,10 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
skillratio += -100 + sc->data[SC_EXEEDBREAK]->val1;
status_change_end(src,SC_EXEEDBREAK,INVALID_TIMER);
}
if(sc->data[SC_HEAT_BARREL])
//!TODO: Verify this placement & skills that affected by these effects [Cydh]
if (sc->data[SC_HEAT_BARREL])
skillratio += 200;
if(sc->data[SC_P_ALTER])
if (sc->data[SC_P_ALTER])
skillratio += sc->data[SC_P_ALTER]->val2;
}
@ -3858,9 +3866,11 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
* Rebellion
**/
case RL_MASS_SPIRAL:
// 200%:400%:600%:800%:1000%
skillratio += -100 + (200 * skill_lv);
break;
case RL_FIREDANCE:
// 100%:200%:300%:400%:500% (+Level ??)
skillratio += -100 + (100 * skill_lv);
skillratio += (skillratio * status_get_lv(src)) / 300; //(custom)
break;
@ -3873,7 +3883,7 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
case RL_SLUGSHOT:
{
uint16 w = 50;
int16 idx = 0;
int16 idx = -1;
if (sd && (idx = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[idx])
w = sd->inventory_data[idx]->weight;
w /= 10;
@ -3881,9 +3891,8 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
}
break;
case RL_D_TAIL:
// 3000%:3500%:4000%:4500%:5000%
skillratio += -100 + (2500 + 500 * skill_lv );
//if (sd && &sd->c_marker)
// skillratio /= max(sd->c_marker.count,1);
break;
case RL_R_TRIP:
skillratio += -100 + (150 * skill_lv); //(custom)
@ -3892,10 +3901,11 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
skillratio += -100 + (50 * skill_lv); //(custom)
break;
case RL_H_MINE:
skillratio += 100 + (200 * skill_lv);
//If damaged by Flicker
if (sd && sd->skill_id_old == RL_FLICKER && tsc && tsc->data[SC_H_MINE] && tsc->data[SC_H_MINE]->val2 == src->id)
skillratio += 400 + (300 * skill_lv);
// 400%:600%:800%:1000%:1200%
skillratio += -100 + (200 + 200 * skill_lv);
//If damaged by Flicker, explosion damage (800%:1100%:1400%:1700%:2000%)
if (sd && sd->flicker)
skillratio += 300 + (100 * skill_lv);
break;
case RL_HAMMER_OF_GOD:
//! TODO: Please check the right formula. [Cydh]
@ -6156,7 +6166,8 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage = ( skill_lv * status_get_lv(src) * 10 ) + ( status_get_int(src) * 7 / 2 ) * ( 18 + (sd?sd->status.job_level:0) / 4 ) * ( 5 / (10 - ((sd) ? pc_checkskill(sd,AM_CANNIBALIZE) : skill_get_max(AM_CANNIBALIZE))) );
break;
case RL_B_TRAP:
md.damage = (200 + status_get_int(src) + status_get_dex(src)) * skill_lv * 10; //(custom)
// kRO 2014-02-12: Damage: Caster's DEX, Target's current HP, Skill Level
md.damage = ((200 + status_get_dex(src)) * skill_lv * 10) + sstatus->hp; // (custom)
break;
}

View File

@ -1375,7 +1375,7 @@ int chrif_load_scdata(int fd) {
for (i = 0; i < count; i++) {
struct status_change_data *data = (struct status_change_data*)RFIFOP(fd,14 + i*sizeof(struct status_change_data));
status_change_start(NULL,&sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 1|2|4|8);
status_change_start(NULL,&sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, SCSTART_NOAVOID|SCSTART_NOTICKDEF|SCSTART_LOADED|SCSTART_NORATEDEF);
}
pc_scdata_received(sd);

View File

@ -753,22 +753,22 @@ void clif_dropflooritem(struct flooritem_data* fitem)
nullpo_retv(fitem);
if (fitem->item_data.nameid == 0)
if (fitem->item.nameid == 0)
return;
WBUFW(buf, offset+0) = header;
WBUFL(buf, offset+2) = fitem->bl.id;
WBUFW(buf, offset+6) = ((view = itemdb_viewid(fitem->item_data.nameid)) > 0) ? view : fitem->item_data.nameid;
WBUFW(buf, offset+6) = ((view = itemdb_viewid(fitem->item.nameid)) > 0) ? view : fitem->item.nameid;
#if PACKETVER >= 20130000
WBUFW(buf, offset+8) = itemtype(fitem->item_data.nameid);
WBUFW(buf, offset+8) = itemtype(fitem->item.nameid);
offset +=2;
#endif
WBUFB(buf, offset+8) = fitem->item_data.identify;
WBUFB(buf, offset+8) = fitem->item.identify;
WBUFW(buf, offset+9) = fitem->bl.x;
WBUFW(buf, offset+11) = fitem->bl.y;
WBUFB(buf, offset+13) = fitem->subx;
WBUFB(buf, offset+14) = fitem->suby;
WBUFW(buf, offset+15) = fitem->item_data.amount;
WBUFW(buf, offset+15) = fitem->item.amount;
clif_send(buf, packet_len(header), &fitem->bl, AREA);
}
@ -4498,14 +4498,14 @@ void clif_getareachar_item(struct map_session_data* sd,struct flooritem_data* fi
WFIFOHEAD(fd,packet_len(0x9d));
WFIFOW(fd,0)=0x9d;
WFIFOL(fd,2)=fitem->bl.id;
if((view = itemdb_viewid(fitem->item_data.nameid)) > 0)
if((view = itemdb_viewid(fitem->item.nameid)) > 0)
WFIFOW(fd,6)=view;
else
WFIFOW(fd,6)=fitem->item_data.nameid;
WFIFOB(fd,8)=fitem->item_data.identify;
WFIFOW(fd,6)=fitem->item.nameid;
WFIFOB(fd,8)=fitem->item.identify;
WFIFOW(fd,9)=fitem->bl.x;
WFIFOW(fd,11)=fitem->bl.y;
WFIFOW(fd,13)=fitem->item_data.amount;
WFIFOW(fd,13)=fitem->item.amount;
WFIFOB(fd,15)=fitem->subx;
WFIFOB(fd,16)=fitem->suby;
WFIFOSET(fd,packet_len(0x9d));
@ -13173,7 +13173,7 @@ void clif_parse_GM_Item_Monster(int fd, struct map_session_data *sd)
// Item
if( (id = itemdb_searchname(str)) ) {
StringBuf_Init(&command);
if( id->type == IT_WEAPON || id->type == IT_ARMOR ) //Nonstackable
if( !itemdb_isstackable2(id) ) //Nonstackable
StringBuf_Printf(&command, "%citem2 %d 1 0 0 0 0 0 0 0", atcommand_symbol, id->nameid);
else
StringBuf_Printf(&command, "%citem %d 20", atcommand_symbol, id->nameid);
@ -17340,21 +17340,36 @@ void clif_parse_GMFullStrip(int fd, struct map_session_data *sd) {
/**
* Marks Crimson Marker target on mini-map to the caster
* TODO: Please, check the proper packet for Crimson Marker [Cydh]
* 09C1 <id>.L <x>.W <y>.W (ZC_C_MARKERINFO)
* @param fd
* @param bl Crimson Marker target
* @param remove True remove the marker from map, false therwise
**/
void clif_crimson_marker(int fd, struct block_list *bl, bool remove) {
WFIFOHEAD(fd,packet_len(0x107));
WFIFOW(fd,0) = 0x107;
WFIFOL(fd,2) = bl->id;
WFIFOW(fd,6) = (remove) ? -1 : bl->x;
WFIFOW(fd,8) = (remove) ? -1 : bl->y;
WFIFOSET(fd,packet_len(0x107));
void clif_crimson_marker(struct map_session_data *sd, struct block_list *bl, bool remove) {
struct s_packet_db* info;
int cmd = 0;
int16 len;
unsigned char buf[11];
nullpo_retv(sd);
cmd = packet_db_ack[sd->packet_ver][ZC_C_MARKERINFO];
if (!cmd)
cmd = 0x09C1; //default
info = &packet_db[sd->packet_ver][cmd];
if (!(len = info->len))
return;
WBUFW(buf, 0) = cmd;
WBUFL(buf, info->pos[0]) = bl->id;
WBUFW(buf, info->pos[1]) = (remove ? -1 : bl->x);
WBUFW(buf, info->pos[2]) = (remove ? -1 : bl->y);
clif_send(buf, len, &sd->bl, SELF);
}
///TODO: Special item that obtained, must be broadcasted by this packet
/**
* !TODO: Special item that obtained, must be broadcasted by this packet
* 07fd ?? (ZC_BROADCASTING_SPECIAL_ITEM_OBTAIN)
*/
//void clif_broadcast_obtain_special_item() {}
#ifdef DUMP_UNKNOWN_PACKET
@ -17531,7 +17546,7 @@ void packetdb_readdb(void)
int max_cmd=-1;
bool skip_ver = false;
int warned = 0;
char *str[64],*p,*str2[64],*p2,w1[256],w2[256];
int packet_ver = MAX_PACKET_VER; // read into packet_db's version by default
int packet_len_table[MAX_PACKET_DB] = {
10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -18012,6 +18027,7 @@ void packetdb_readdb(void)
{ "ZC_PERSONAL_INFOMATION", ZC_PERSONAL_INFOMATION},
{ "ZC_PERSONAL_INFOMATION_CHN", ZC_PERSONAL_INFOMATION_CHN},
{ "ZC_CLEAR_DIALOG", ZC_CLEAR_DIALOG},
{ "ZC_C_MARKERINFO", ZC_C_MARKERINFO},
};
const char *filename[] = { "packet_db.txt", DBIMPORT"/packet_db.txt"};
int f;
@ -18022,14 +18038,14 @@ void packetdb_readdb(void)
packet_len(i) = packet_len_table[i];
clif_config.packet_db_ver = MAX_PACKET_VER;
for(f = 0; f<ARRAYLENGTH(filename); f++){
for(f = 0; f < ARRAYLENGTH(filename); f++){
int ln=0;
int entries = 0;
int packet_ver = MAX_PACKET_VER; // read into packet_db's version by default
sprintf(line, "%s/%s", db_path,filename[f]);
if( (fp=fopen(line,"r"))==NULL ){
if(f==0) {
char *str[64],*p,*str2[64],*p2;
sprintf(line, "%s/%s", db_path, filename[f]);
if( (fp = fopen(line,"r")) == NULL ){
if (f == 0) {
ShowFatalError("Can't read %s\n", line);
exit(EXIT_FAILURE);
}
@ -18037,12 +18053,12 @@ void packetdb_readdb(void)
}
while( fgets(line, sizeof(line), fp) ) {
char w1[256],w2[256];
ln++;
if(line[0]=='/' && line[1]=='/')
continue;
if (sscanf(line,"%255[^:]: %255[^\r\n]",w1,w2) == 2)
{
if(strcmpi(w1,"packet_ver")==0) {
if (sscanf(line,"%255[^:]: %255[^\r\n]",w1,w2) == 2) {
if (strcmpi(w1,"packet_ver") == 0) {
int prev_ver = packet_ver;
skip_ver = false;
packet_ver = atoi(w2);
@ -18080,7 +18096,7 @@ void packetdb_readdb(void)
memcpy(&packet_db_ack[packet_ver], &packet_db_ack[prev_ver], sizeof(packet_db_ack[0]));
continue;
} else if(strcmpi(w1,"packet_db_ver")==0) {
if(strcmpi(w2,"default")==0) //This is the preferred version.
if (strcmpi(w2,"default") == 0) //This is the preferred version.
clif_config.packet_db_ver = MAX_PACKET_VER;
else // to manually set the packet DB version
clif_config.packet_db_ver = cap_value(atoi(w2), 0, MAX_PACKET_VER);
@ -18092,14 +18108,15 @@ void packetdb_readdb(void)
continue; // Skipping current packet version
memset(str,0,sizeof(str));
for(j=0,p=line;j<4 && p; ++j) {
str[j]=p;
p=strchr(p,',');
if(p) *p++=0;
for (j = 0, p = line; j < 4 && p; ++j) {
str[j] = p;
p = strchr(p,',');
if (p)
*p++=0;
}
if(str[0]==NULL)
if (str[0] == NULL)
continue;
cmd=strtol(str[0],(char **)NULL,0);
cmd = strtol(str[0],(char **)NULL,0);
if(max_cmd < cmd)
max_cmd = cmd;
@ -18139,11 +18156,12 @@ void packetdb_readdb(void)
ShowError("packet_db: packet error\n");
exit(EXIT_FAILURE);
}
for(j=0,p2=str[3];p2;j++){
for(j = 0, p2 = str[3]; p2; j++){
short k;
str2[j]=p2;
p2=strchr(p2,':');
if(p2) *p2++=0;
str2[j] = p2;
p2 = strchr(p2,':');
if(p2)
*p2++=0;
k = atoi(str2[j]);
// if (packet_db[packet_ver][cmd].pos[j] != k && clif_config.prefer_packet_db) // not used for now

View File

@ -46,6 +46,7 @@ enum e_packet_ack {
ZC_PERSONAL_INFOMATION,
ZC_PERSONAL_INFOMATION_CHN,
ZC_CLEAR_DIALOG,
ZC_C_MARKERINFO,
//add other here
MAX_ACK_FUNC //auto upd len
};
@ -380,7 +381,6 @@ enum clif_messages {
NEED_REINS_OF_MOUNT = 0x78c,
};
enum e_personalinfo {
PINFO_BASIC = 0,
PINFO_PREMIUM,
@ -881,7 +881,7 @@ 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_crimson_marker(int fd, struct block_list *bl, bool remove);
void clif_crimson_marker(struct map_session_data *sd, struct block_list *bl, bool remove);
//void clif_broadcast_obtain_special_item(); ///TODO!

View File

@ -1430,15 +1430,6 @@ static int itemdb_read_sqldb(void) {
return 0;
}
/**
* Unique item ID function
* @param sd : Player
* @return unique_id
*/
uint64 itemdb_unique_id(struct map_session_data *sd) {
return ((uint64)sd->status.char_id << 32) | sd->status.uniqueitem_counter++;
}
/** Check if the item is restricted by item_noequip.txt
* @param id Item that will be checked
* @param m Map ID
@ -1465,10 +1456,10 @@ bool itemdb_isNoEquip(struct item_data *id, uint16 m) {
*/
bool itemdb_is_spellbook2(unsigned short nameid) {
unsigned char i;
if (!nameid || !itemdb_exists(nameid))
if (!nameid || !itemdb_exists(nameid) || !skill_spellbook_count)
return false;
ARR_FIND(0, MAX_SKILL_SPELLBOOK_DB, i, skill_spellbook_db[i].nameid == nameid);
if (i >= MAX_SKILL_SPELLBOOK_DB)
if (i == MAX_SKILL_SPELLBOOK_DB)
return false;
return true;
}

View File

@ -480,7 +480,6 @@ bool itemdb_isequip2(struct item_data *id);
char itemdb_isidentified(unsigned short nameid);
bool itemdb_isstackable2(struct item_data *id);
#define itemdb_isstackable(nameid) itemdb_isstackable2(itemdb_search(nameid))
uint64 itemdb_unique_id(struct map_session_data *sd); // Unique Item ID
bool itemdb_isNoEquip(struct item_data *id, uint16 m);
struct item_combo *itemdb_combo_exists(unsigned short combo_id);

View File

@ -1289,8 +1289,8 @@ int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr_t data)
}
if (search_petDB_index(fitem->item_data.nameid, PET_EGG) >= 0)
intif_delete_petdata(MakeDWord(fitem->item_data.card[1], fitem->item_data.card[2]));
if (search_petDB_index(fitem->item.nameid, PET_EGG) >= 0)
intif_delete_petdata(MakeDWord(fitem->item.card[1], fitem->item.card[2]));
clif_clearflooritem(fitem, 0);
map_deliddb(&fitem->bl);
@ -1442,14 +1442,14 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
* @param flag: &1 MVP item. &2 do stacking check. &4 bypass droppable check.
* @return 0:failure, x:item_gid [MIN_FLOORITEM;MAX_FLOORITEM]==[2;START_ACCOUNT_NUM]
*------------------------------------------*/
int map_addflooritem(struct item *item_data,int amount,int16 m,int16 x,int16 y,int first_charid,int second_charid,int third_charid,int flags)
int map_addflooritem(struct item *item,int amount,int16 m,int16 x,int16 y,int first_charid,int second_charid,int third_charid,int flags)
{
int r;
struct flooritem_data *fitem=NULL;
nullpo_ret(item_data);
nullpo_ret(item);
if(!(flags&4) && battle_config.item_onfloor && (itemdb_traderight(item_data->nameid)&1) )
if(!(flags&4) && battle_config.item_onfloor && (itemdb_traderight(item->nameid)&1) )
return 0; //can't be dropped
if(!map_searchrandfreecell(m,&x,&y,flags&2?1:0))
@ -1475,8 +1475,8 @@ int map_addflooritem(struct item *item_data,int amount,int16 m,int16 x,int16 y,i
fitem->third_get_charid = third_charid;
fitem->third_get_tick = fitem->second_get_tick + (flags&1 ? battle_config.mvp_item_third_get_time : battle_config.item_third_get_time);
memcpy(&fitem->item_data,item_data,sizeof(*item_data));
fitem->item_data.amount=amount;
memcpy(&fitem->item,item,sizeof(*item));
fitem->item.amount=amount;
fitem->subx=(r&3)*3+3;
fitem->suby=((r>>2)&3)*3+3;
fitem->cleartimer=add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0);

View File

@ -425,7 +425,7 @@ struct flooritem_data {
int cleartimer;
int first_get_charid,second_get_charid,third_get_charid;
unsigned int first_get_tick,second_get_tick,third_get_tick;
struct item item_data;
struct item item;
};
enum _sp {
@ -795,7 +795,7 @@ bool map_addnpc(int16 m,struct npc_data *);
int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr_t data);
int map_removemobs_timer(int tid, unsigned int tick, int id, intptr_t data);
void map_clearflooritem(struct block_list* bl);
int map_addflooritem(struct item *item_data,int amount,int16 m,int16 x,int16 y,int first_charid,int second_charid,int third_charid,int flags);
int map_addflooritem(struct item *item,int amount,int16 m,int16 x,int16 y,int first_charid,int second_charid,int third_charid,int flags);
// instances
int map_addinstancemap(const char*,int);

View File

@ -417,7 +417,7 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target)
return true;
} while(0);
status_change_start(src, target, SC_KSPROTECTED, 10000, sd->bl.id, sd->state.noks, sd->status.party_id, sd->status.guild_id, battle_config.ksprotection, 0);
status_change_start(src, target, SC_KSPROTECTED, 10000, sd->bl.id, sd->state.noks, sd->status.party_id, sd->status.guild_id, battle_config.ksprotection, SCSTART_NOAVOID);
return false;
}
@ -1603,15 +1603,15 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
fitem = (struct flooritem_data *)tbl;
//Logs items, taken by (L)ooter Mobs [Lupus]
log_pick_mob(md, LOG_TYPE_LOOT, fitem->item_data.amount, &fitem->item_data);
log_pick_mob(md, LOG_TYPE_LOOT, fitem->item.amount, &fitem->item);
if (md->lootitem_count < LOOTITEM_SIZE) {
memcpy (&md->lootitem[md->lootitem_count++], &fitem->item_data, sizeof(md->lootitem[0]));
memcpy (&md->lootitem[md->lootitem_count++], &fitem->item, sizeof(md->lootitem[0]));
} else { //Destroy first looted item...
if (md->lootitem[0].card[0] == CARD0_PET)
intif_delete_petdata( MakeDWord(md->lootitem[0].card[1],md->lootitem[0].card[2]) );
memmove(&md->lootitem[0], &md->lootitem[1], (LOOTITEM_SIZE-1)*sizeof(md->lootitem[0]));
memcpy (&md->lootitem[LOOTITEM_SIZE-1], &fitem->item_data, sizeof(md->lootitem[0]));
memcpy (&md->lootitem[LOOTITEM_SIZE-1], &fitem->item, sizeof(md->lootitem[0]));
}
if (pcdb_checkid(md->vd->class_))
{ //Give them walk act/delay to properly mimic players. [Skotlex]

View File

@ -4175,6 +4175,8 @@ bool npc_unloadfile( const char* path ) {
if( found ) /* refresh event cache */
npc_read_event_script();
npc_delsrcfile(path);
return found;
}

View File

@ -4311,7 +4311,7 @@ char pc_additem(struct map_session_data *sd,struct item *item,int amount,e_log_p
clif_additem(sd,i,amount,0);
}
if( !itemdb_isstackable2(id) && !item->unique_id )
sd->status.inventory[i].unique_id = itemdb_unique_id(sd);
sd->status.inventory[i].unique_id = pc_generate_unique_id(sd);
log_pick_pc(sd, log_type, amount, &sd->status.inventory[i]);
sd->weight += w;
@ -4471,7 +4471,7 @@ bool pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
}
//This function takes care of giving the item to whoever should have it, considering party-share options.
if ((flag = party_share_loot(p,sd,&fitem->item_data, fitem->first_get_charid))) {
if ((flag = party_share_loot(p,sd,&fitem->item, fitem->first_get_charid))) {
clif_additem(sd,0,0,flag);
return true;
}
@ -9546,7 +9546,7 @@ void pc_check_available_item(struct map_session_data *sd) {
continue;
}
if (!sd->status.inventory[i].unique_id && !itemdb_isstackable(it))
sd->status.inventory[i].unique_id = itemdb_unique_id(sd);
sd->status.inventory[i].unique_id = pc_generate_unique_id(sd);
}
}
@ -9564,7 +9564,7 @@ void pc_check_available_item(struct map_session_data *sd) {
continue;
}
if (!sd->status.cart[i].unique_id && !itemdb_isstackable(it))
sd->status.cart[i].unique_id = itemdb_unique_id(sd);
sd->status.cart[i].unique_id = pc_generate_unique_id(sd);
}
}
@ -9582,7 +9582,7 @@ void pc_check_available_item(struct map_session_data *sd) {
continue;
}
if (!sd->status.storage.items[i].unique_id && !itemdb_isstackable(it))
sd->status.storage.items[i].unique_id = itemdb_unique_id(sd);
sd->status.storage.items[i].unique_id = pc_generate_unique_id(sd);
}
}
}
@ -10964,22 +10964,21 @@ enum e_BANKING_WITHDRAW_ACK pc_bank_withdraw(struct map_session_data *sd, int mo
}
/**
* Clear Cirmson Marker data from caster
* Clear Crimson Marker data from caster
* @param sd: Player
**/
void pc_crimson_marker_clear(struct map_session_data *sd) {
uint8 i;
if (!sd || !(&sd->c_marker) || !sd->c_marker.target)
if (!sd)
return;
for (i = 0; i < MAX_SKILL_CRIMSON_MARKER; i++) {
struct block_list *bl = NULL;
if (sd->c_marker.target[i] && (bl = map_id2bl(sd->c_marker.target[i])))
if (sd->c_marker[i] && (bl = map_id2bl(sd->c_marker[i])))
status_change_end(bl,SC_C_MARKER,INVALID_TIMER);
sd->c_marker.target[i] = 0;
sd->c_marker[i] = 0;
}
sd->c_marker.count = 0;
}
/**
@ -11233,6 +11232,15 @@ bool pc_is_same_equip_index(enum equip_index eqi, short *equip_index, short inde
return false;
}
/**
* Generate Unique item ID for player
* @param sd : Player
* @return A generated Unique item ID
*/
uint64 pc_generate_unique_id(struct map_session_data *sd) {
return ((uint64)sd->status.char_id << 32) | sd->status.uniqueitem_counter++;
}
/*==========================================
* pc Init/Terminate
*------------------------------------------*/

View File

@ -591,11 +591,8 @@ struct map_session_data {
uint16 dmglog[DAMAGELOG_SIZE_PC]; ///target ids
struct s_crimson_marker { ///Store target that marked by Crimson Marker [Cydh]
int target[MAX_SKILL_CRIMSON_MARKER]; //Target id storage
uint8 count; //Count of target for skill used (i.e. RL_D_TAIL).
} c_marker;
bool flicker; ///Is Flicker Skill skill as player's last action? [Cydh]
int c_marker[MAX_SKILL_CRIMSON_MARKER]; /// Store target that marked by Crimson Marker [Cydh]
bool flicker; /// Check RL_FLICKER usage status [Cydh]
int storage_size; /// Holds player storage size (VIP system).
#ifdef VIP_ENABLE
@ -879,6 +876,8 @@ char pc_additem(struct map_session_data *sd, struct item *item, int amount, e_lo
char pc_getzeny(struct map_session_data *sd, int zeny, enum e_log_pick_type type, struct map_session_data *tsd);
char pc_delitem(struct map_session_data *sd, int n, int amount, int type, short reason, e_log_pick_type log_type);
uint64 pc_generate_unique_id(struct map_session_data *sd);
//Bound items
int pc_bound_chk(TBL_PC *sd,enum bound_type type,int *idxlist);

View File

@ -946,8 +946,8 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns
} else{
struct flooritem_data *fitem = (struct flooritem_data *)target;
if(pd->loot->count < pd->loot->max){
memcpy(&pd->loot->item[pd->loot->count++],&fitem->item_data,sizeof(pd->loot->item[0]));
pd->loot->weight += itemdb_weight(fitem->item_data.nameid)*fitem->item_data.amount;
memcpy(&pd->loot->item[pd->loot->count++],&fitem->item,sizeof(pd->loot->item[0]));
pd->loot->weight += itemdb_weight(fitem->item.nameid)*fitem->item.amount;
map_clearflooritem(target);
}
//Target is unlocked regardless of whether it was picked or not.

View File

@ -2369,6 +2369,14 @@ void script_hardcoded_constants(void) {
script_set_constant("BSF_REM_DEBUFF",BSF_REM_DEBUFF,false);
script_set_constant("BSF_ALL",BSF_ALL,false);
script_set_constant("BSF_CLEARALL",BSF_CLEARALL,false);
/* sc_start flags */
script_set_constant("SCSTART_NONE",SCSTART_NONE,false);
script_set_constant("SCSTART_NOAVOID",SCSTART_NOAVOID,false);
script_set_constant("SCSTART_NOTICKDEF",SCSTART_NOTICKDEF,false);
script_set_constant("SCSTART_LOADED",SCSTART_LOADED,false);
script_set_constant("SCSTART_NORATEDEF",SCSTART_NORATEDEF,false);
script_set_constant("SCSTART_NOICON",SCSTART_NOICON,false);
}
/*==========================================
@ -7753,8 +7761,31 @@ BUILDIN_FUNC(strnpcinfo)
}
// aegis->athena slot position conversion table
static unsigned int equip[] = {EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_GARMENT,EQP_SHOES,EQP_ACC_L,EQP_ACC_R,EQP_HEAD_MID,EQP_HEAD_LOW,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_GARMENT,EQP_AMMO,EQP_SHADOW_ARMOR,EQP_SHADOW_WEAPON,EQP_SHADOW_SHIELD,EQP_SHADOW_SHOES,EQP_SHADOW_ACC_R,EQP_SHADOW_ACC_L};
/// aegis->athena slot position conversion table
/// Index is used by EQI_ in db/const.txt
static unsigned int equip[] = {
EQP_HEAD_TOP,
EQP_ARMOR,
EQP_HAND_L,
EQP_HAND_R,
EQP_GARMENT,
EQP_SHOES,
EQP_ACC_L,
EQP_ACC_R,
EQP_HEAD_MID,
EQP_HEAD_LOW,
EQP_COSTUME_HEAD_LOW,
EQP_COSTUME_HEAD_MID,
EQP_COSTUME_HEAD_TOP,
EQP_COSTUME_GARMENT,
EQP_AMMO,
EQP_SHADOW_ARMOR,
EQP_SHADOW_WEAPON,
EQP_SHADOW_SHIELD,
EQP_SHADOW_SHOES,
EQP_SHADOW_ACC_R,
EQP_SHADOW_ACC_L
};
/*==========================================
* GetEquipID(Pos); Pos: 1-14
@ -10267,12 +10298,12 @@ BUILDIN_FUNC(getareausers)
*------------------------------------------*/
static int buildin_getareadropitem_sub(struct block_list *bl,va_list ap)
{
int item=va_arg(ap,int);
int nameid=va_arg(ap,int);
int *amount=va_arg(ap,int *);
struct flooritem_data *drop=(struct flooritem_data *)bl;
if(drop->item_data.nameid==item)
(*amount)+=drop->item_data.amount;
if(drop->item.nameid==nameid)
(*amount)+=drop->item.amount;
return 0;
}
@ -10280,7 +10311,7 @@ BUILDIN_FUNC(getareadropitem)
{
const char *str;
int16 m,x0,y0,x1,y1;
int item,amount=0;
int nameid,amount=0;
struct script_data *data;
str=script_getstr(st,2);
@ -10294,18 +10325,18 @@ BUILDIN_FUNC(getareadropitem)
if( data_isstring(data) ){
const char *name=conv_str(st,data);
struct item_data *item_data = itemdb_searchname(name);
item=UNKNOWN_ITEM_ID;
nameid=UNKNOWN_ITEM_ID;
if( item_data )
item=item_data->nameid;
nameid=item_data->nameid;
}else
item=conv_num(st,data);
nameid=conv_num(st,data);
if( (m=map_mapname2mapid(str))< 0){
script_pushint(st,-1);
return 0;
}
map_foreachinarea(buildin_getareadropitem_sub,
m,x0,y0,x1,y1,BL_ITEM,item,&amount);
m,x0,y0,x1,y1,BL_ITEM,nameid,&amount);
script_pushint(st,amount);
return SCRIPT_CMD_SUCCESS;
}
@ -10492,7 +10523,7 @@ BUILDIN_FUNC(getscrate)
bl = map_id2bl(st->rid);
if (bl)
rate = status_get_sc_def(NULL,bl, (sc_type)type, 10000, 10000, 0);
rate = status_get_sc_def(NULL,bl, (sc_type)type, 10000, 10000, SCSTART_NONE);
script_pushint(st,rate);
return SCRIPT_CMD_SUCCESS;
@ -16674,7 +16705,7 @@ BUILDIN_FUNC(mercenary_sc_start)
tick = script_getnum(st,3);
val1 = script_getnum(st,4);
status_change_start(NULL, &sd->md->bl, type, 10000, val1, 0, 0, 0, tick, 2);
status_change_start(NULL, &sd->md->bl, type, 10000, val1, 0, 0, 0, tick, SCSTART_NOTICKDEF);
return SCRIPT_CMD_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@ -18,10 +18,10 @@ struct status_change_entry;
#define MAX_PRODUCE_RESOURCE 12 /// Max Produce requirements
#define MAX_SKILL_ARROW_DB 150 /// Max Arrow Creation DB
#define MAX_ARROW_RESULT 5 /// Max Arrow results/created
#define MAX_SKILL_ABRA_DB 350 /// Max Skill list of Abracadabra DB
#define MAX_SKILL_IMPROVISE_DB 50 /// Max Skill for Improvise
#define MAX_SKILL_ABRA_DB 160 /// Max Skill list of Abracadabra DB
#define MAX_SKILL_IMPROVISE_DB 30 /// Max Skill for Improvise
#define MAX_SKILL_LEVEL 100 /// Max Skill Level
#define MAX_SKILL_CRIMSON_MARKER 3 /// Max Crimson Marker targets
#define MAX_SKILL_CRIMSON_MARKER 3 /// Max Crimson Marker targets (RL_C_MARKER)
#define SKILL_NAME_LENGTH 31 /// Max Skill Name length
#define SKILL_DESC_LENGTH 31 /// Max Skill Desc length
@ -101,7 +101,7 @@ enum e_skill_inf3 {
/// Flags passed to skill_attack/skill_area_sub
enum e_skill_display {
SD_LEVEL = 0x1000, // skill_attack will send -1 instead of skill level (affects display of some skills)
SD_ANIMATION = 0x2000, // skill_attack will use '5' instead of the skill's 'type' (this makes skills show an animation)
SD_ANIMATION = 0x2000, // skill_attack will use '5' instead of the skill's 'type' (this makes skills show an animation). Also being used in skill_attack for splash skill (NK_SPLASH) to check status_check_skilluse
SD_SPLASH = 0x4000, // skill_area_sub will count targets in skill_area_temp[2]
SD_PREAMBLE = 0x8000, // skill_area_sub will transmit a 'magic' damage packet (-30000 dmg) for the first target selected
};
@ -259,22 +259,23 @@ struct skill_unit_group_tickset {
enum {
UF_DEFNOTENEMY = 0x0001, // If 'defunit_not_enemy' is set, the target is changed to 'friend'
UF_NOREITERATION = 0x0002, // Spell cannot be stacked
UF_NOFOOTSET = 0x0004, // Spell cannot be cast near/on targets
UF_NOOVERLAP = 0x0008, // Spell effects do not overlap
UF_PATHCHECK = 0x0010, // Only cells with a shootable path will be placed
UF_NOPC = 0x0020, // May not target players
UF_NOMOB = 0x0040, // May not target mobs
UF_SKILL = 0x0080, // May target skills
UF_DANCE = 0x0100, // Dance
UF_ENSEMBLE = 0x0200, // Duet
UF_SONG = 0x0400, // Song
UF_DUALMODE = 0x0800, // Spells should trigger both ontimer and onplace/onout/onleft effects.
UF_NOKNOCKBACK = 0x1000, // Skill unit cannot be knocked back
UF_RANGEDSINGLEUNIT = 0x2000, // hack for ranged layout, only display center
UF_REM_CRAZYWEED = 0x4000, // removed by Crazyweed
UF_REM_FIRERAIN = 0x8000, // removed by Fire Rain
UF_DEFNOTENEMY = 0x00001, // If 'defunit_not_enemy' is set, the target is changed to 'friend'
UF_NOREITERATION = 0x00002, // Spell cannot be stacked
UF_NOFOOTSET = 0x00004, // Spell cannot be cast near/on targets
UF_NOOVERLAP = 0x00008, // Spell effects do not overlap
UF_PATHCHECK = 0x00010, // Only cells with a shootable path will be placed
UF_NOPC = 0x00020, // May not target players
UF_NOMOB = 0x00040, // May not target mobs
UF_SKILL = 0x00080, // May target skills
UF_DANCE = 0x00100, // Dance
UF_ENSEMBLE = 0x00200, // Duet
UF_SONG = 0x00400, // Song
UF_DUALMODE = 0x00800, // Spells should trigger both ontimer and onplace/onout/onleft effects.
UF_NOKNOCKBACK = 0x01000, // Skill unit cannot be knocked back
UF_RANGEDSINGLEUNIT = 0x02000, // hack for ranged layout, only display center
UF_REM_CRAZYWEED = 0x04000, // removed by Crazyweed
UF_REM_FIRERAIN = 0x08000, // removed by Fire Rain
UF_KNOCKBACK_GROUP = 0x10000, // knockback skill unit with its group instead of single unit
};
/// Create Database item
@ -303,9 +304,7 @@ struct s_skill_abra_db {
int per[MAX_SKILL_LEVEL]; /// Probability summoned
};
extern struct s_skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB];
extern int enchant_eff[5];
extern int deluge_eff[5];
extern unsigned short skill_abra_count;
void do_init_skill(void);
void do_final_skill(void);
@ -414,6 +413,7 @@ int skill_check_unit_cell(uint16 skill_id,int16 m,int16 x,int16 y,int unit_id);
int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range);
int skill_unit_move(struct block_list *bl,unsigned int tick,int flag);
void skill_unit_move_unit_group( struct skill_unit_group *group, int16 m,int16 dx,int16 dy);
void skill_unit_move_unit(struct block_list *bl, int dx, int dy);
struct skill_unit_group *skill_check_dancing( struct block_list *src );
@ -1984,17 +1984,19 @@ struct s_skill_spellbook_db {
unsigned short point;
};
extern struct s_skill_spellbook_db skill_spellbook_db[MAX_SKILL_SPELLBOOK_DB];
int skill_spellbook (struct map_session_data *sd, unsigned short nameid);
extern unsigned short skill_spellbook_count;
void skill_spellbook (struct map_session_data *sd, unsigned short nameid);
int skill_block_check(struct block_list *bl, enum sc_type type, uint16 skill_id);
/**
* Guilottine Cross
**/
#define MAX_SKILL_MAGICMUSHROOM_DB 23
#define MAX_SKILL_MAGICMUSHROOM_DB 25
struct s_skill_magicmushroom_db {
uint16 skill_id;
};
extern struct s_skill_magicmushroom_db skill_magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB];
extern unsigned short skill_magicmushroom_count;
int skill_maelstrom_suction(struct block_list *bl, va_list ap);
bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit);

View File

@ -689,7 +689,7 @@ void initChangeTables(void)
set_sc( SC_WEAKNESS , SC__WEAKNESS , SI_WEAKNESS , SCB_MAXHP );
set_sc( SC_STRIPACCESSARY , SC__STRIPACCESSORY , SI_STRIPACCESSARY , SCB_DEX|SCB_INT|SCB_LUK );
set_sc_with_vfx( SC_MANHOLE , SC__MANHOLE , SI_MANHOLE , SCB_NONE );
add_sc( SC_CHAOSPANIC , SC__CHAOS );
add_sc( SC_CHAOSPANIC , SC_CONFUSION );
add_sc( SC_BLOODYLUST , SC_BERSERK );
add_sc( SC_FEINTBOMB , SC__FEINTBOMB );
@ -801,6 +801,7 @@ void initChangeTables(void)
/* Rebellion */
add_sc( RL_MASS_SPIRAL , SC_BLEEDING );
add_sc( RL_HAMMER_OF_GOD , SC_STUN );
set_sc( RL_H_MINE , SC_H_MINE , SI_H_MINE , SCB_NONE);
set_sc( RL_B_TRAP , SC_B_TRAP , SI_B_TRAP , SCB_SPEED );
set_sc( RL_E_CHAIN , SC_E_CHAIN , SI_E_CHAIN , SCB_NONE );
set_sc( RL_P_ALTER , SC_P_ALTER , SI_P_ALTER , SCB_NONE );
@ -981,7 +982,6 @@ void initChangeTables(void)
StatusIconChangeTable[SC_MTF_CRIDAMAGE] = SI_MTF_CRIDAMAGE;
StatusIconChangeTable[SC_MOONSTAR] = SI_MOONSTAR;
StatusIconChangeTable[SC_SUPER_STAR] = SI_SUPER_STAR;
StatusIconChangeTable[SC_H_MINE] = SI_H_MINE;
StatusIconChangeTable[SC_QD_SHOT_READY] = SI_E_QD_SHOT_READY;
StatusIconChangeTable[SC_HEAT_BARREL_AFTER] = SI_HEAT_BARREL_AFTER;
StatusIconChangeTable[SC_STRANGELIGHTS] = SI_STRANGELIGHTS;
@ -1918,9 +1918,8 @@ bool status_check_skilluse(struct block_list *src, struct block_list *target, ui
return false;
if(skill_id == PR_LEXAETERNA && (tsc->data[SC_FREEZE] || (tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE)))
return false;
if (tsc->data[SC__MANHOLE])
if (!(skill_get_inf3(skill_id)&INF3_USABLE_MANHOLE))
return false;
if (tsc->data[SC__MANHOLE] && !(skill_get_inf3(skill_id)&INF3_USABLE_MANHOLE))
return false;
}
// If targetting, cloak+hide protect you, otherwise only hiding does.
@ -5491,6 +5490,7 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
if(sc->data[SC_TINDER_BREAKER] || sc->data[SC_TINDER_BREAKER2])
return 1; // 1 = min flee
// Fixed value
if(sc->data[SC_INCFLEE])
flee += sc->data[SC_INCFLEE]->val1;
if(sc->data[SC_FLEEFOOD])
@ -5521,11 +5521,14 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
flee += sc->data[SC_HALLUCINATIONWALK]->val2;
if( sc->data[SC_WATER_BARRIER] )
flee -= sc->data[SC_WATER_BARRIER]->val3;
if( sc->data[SC_C_MARKER] )
flee -= sc->data[SC_C_MARKER]->val3;
#ifdef RENEWAL
if( sc->data[SC_SPEARQUICKEN] )
flee += 2 * sc->data[SC_SPEARQUICKEN]->val1;
#endif
// Rate value
if(sc->data[SC_INCFLEERATE])
flee += flee * sc->data[SC_INCFLEERATE]->val1/100;
if(sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1)
@ -5558,8 +5561,8 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
flee += flee * 20 / 100;
if (sc->data[SC_TEARGAS])
flee -= flee * 50 / 100;
if( sc->data[SC_C_MARKER] )
flee -= (flee * sc->data[SC_C_MARKER]->val3) / 100;
//if( sc->data[SC_C_MARKER] )
// flee -= (flee * sc->data[SC_C_MARKER]->val3) / 100;
if(sc->data[SC_HEAT_BARREL])
flee -= sc->data[SC_HEAT_BARREL]->val4;
@ -7043,14 +7046,10 @@ void status_change_init(struct block_list *bl)
* @param type: Status change (SC_*)
* @param rate: Initial percentage rate of affecting bl
* @param tick: Initial duration that the status change affects bl
* @param flag: Value which determines what parts to calculate
* &1: Cannot be avoided (it has to start)
* &2: Tick should not be reduced (by vit, luk, lv, etc)
* &4: sc_data loaded, no value has to be altered.
* &8: rate should not be reduced
* @param flag: Value which determines what parts to calculate. See e_status_change_start_flags
* @return adjusted duration based on flag values
**/
int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag)
int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, unsigned char flag)
{
/// Resistance rate: 10000 = 100%
/// Example: 50% (5000) -> sc_def = 5000 -> 25%;
@ -7269,6 +7268,9 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
case SC_VOICEOFSIREN:
tick_def2 = (status_get_lv(bl) * 100) + ((bl->type == BL_PC)?((TBL_PC*)bl)->status.job_level * 200 : 0);
break;
case SC_B_TRAP:
tick_def = b_status->str * 50; // (custom)
break;
default:
// Effect that cannot be reduced? Likely a buff.
if (!(rnd()%10000 < rate))
@ -7320,7 +7322,7 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
tick_def = sc_def;
// Natural resistance
if (!(flag&8)) {
if (!(flag&SCSTART_NORATEDEF)) {
rate -= rate*sc_def/10000;
rate -= sc_def2;
@ -7347,10 +7349,11 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
return 0;
// Even if a status change doesn't have a duration, it should still trigger
if (tick < 1) return 1;
if (tick < 1)
return 1;
// Rate reduction
if (flag&2)
// Duration cannot be reduced
if (flag&SCSTART_NOTICKDEF)
return tick;
tick -= tick*tick_def/10000;
@ -7458,16 +7461,10 @@ void status_display_remove(struct map_session_data *sd, enum sc_type type) {
* @param rate: Initial percentage rate of affecting bl (0~10000)
* @param val1~4: Depends on type of status change
* @param tick: Initial duration that the status change affects bl
* @param flag: Value which determines what parts to calculate
* &1 : Cannot be avoided (it has to start)
* &2 : Tick should not be reduced (by vit, luk, lv, etc)
* &4 : sc_data loaded, no value has to be altered.
* &8 : rate should not be reduced
* &16: don't send SI
* @param flag: Value which determines what parts to calculate. See e_status_change_start_flags
* @return adjusted duration based on flag values
**/
int status_change_start(struct block_list* src, struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag)
{
int status_change_start(struct block_list* src, struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,unsigned char flag) {
struct map_session_data *sd = NULL;
struct status_change* sc;
struct status_change_entry* sce;
@ -7565,11 +7562,14 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
sd = BL_CAST(BL_PC, bl);
// Adjust tick according to status resistances
if( !(flag&(1|4)) ) {
if( !(flag&(SCSTART_NOAVOID|SCSTART_LOADED)) ) {
tick = status_get_sc_def(src, bl, type, rate, tick, flag);
if( !tick ) return 0;
if( !tick )
return 0;
}
vd = status_get_viewdata(bl);
undead_flag = battle_check_undead(status->race,status->def_ele);
// Check for immunities / sc fails
switch (type) {
@ -7595,7 +7595,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
return 0;
case SC_FREEZE:
// Undead are immune to Freeze/Stone
if (undead_flag && !(flag&1))
if (undead_flag && !(flag&SCSTART_NOAVOID))
return 0;
case SC_DEEPSLEEP:
case SC_SLEEP:
@ -7724,7 +7724,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
break;
// Strip skills, need to divest something or it fails.
case SC_STRIPWEAPON:
if (sd && !(flag&4)) { // Apply sc anyway if loading saved sc_data
if (sd && !(flag&SCSTART_LOADED)) { // Apply sc anyway if loading saved sc_data
short i;
opt_flag = 0; // Reuse to check success condition.
if(sd->bonus.unstripable_equip&EQP_WEAPON)
@ -7747,7 +7747,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
case SC_STRIPSHIELD:
if( val2 == 1 ) val2 = 0; // GX effect. Do not take shield off..
else
if (sd && !(flag&4)) {
if (sd && !(flag&SCSTART_LOADED)) {
short i;
if(sd->bonus.unstripable_equip&EQP_SHIELD)
return 0;
@ -7759,7 +7759,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
if (tick == 1) return 1; // Minimal duration: Only strip without causing the SC
break;
case SC_STRIPARMOR:
if (sd && !(flag&4)) {
if (sd && !(flag&SCSTART_LOADED)) {
short i;
if(sd->bonus.unstripable_equip&EQP_ARMOR)
return 0;
@ -7771,7 +7771,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
if (tick == 1) return 1; // Minimal duration: Only strip without causing the SC
break;
case SC_STRIPHELM:
if (sd && !(flag&4)) {
if (sd && !(flag&SCSTART_LOADED)) {
short i;
if(sd->bonus.unstripable_equip&EQP_HELM)
return 0;
@ -7896,20 +7896,19 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
if (sc->data[SC_P_ALTER] || sc->data[SC_HEAT_BARREL])
return 0;
break;
case SC_C_MARKER:
if (src == bl)
case SC_WEDDING:
case SC_XMAS:
case SC_SUMMER:
case SC_HANBOK:
case SC_OKTOBERFEST:
if (!vd)
return 0;
else {
struct status_change *tsc = status_get_sc(bl);
// Failed if the target is already marked and the new marker that isn't same marker
if (tsc && tsc->data[type] && tsc->data[type]->val2 != src->id)
return 0;
}
break;
}
// Check for BOSS resistances
if(status->mode&MD_BOSS && !(flag&1)) {
if(status->mode&MD_BOSS && !(flag&SCSTART_NOAVOID)) {
if (type>=SC_COMMON_MIN && type <= SC_COMMON_MAX)
return 0;
switch (type) {
@ -7953,7 +7952,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
}
}
// Check for mvp resistance // atm only those who OS
if(status->mode&MD_MVP && !(flag&1)) {
if(status->mode&MD_MVP && !(flag&SCSTART_NOAVOID)) {
switch (type) {
case SC_COMA:
// continue list...
@ -8274,7 +8273,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
case SC__LAZINESS:
case SC__WEAKNESS:
case SC__UNLUCKY:
case SC__CHAOS:
//case SC__CHAOS:
return 0;
case SC_COMBO:
case SC_DANCING:
@ -8337,11 +8336,26 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
}
}
vd = status_get_viewdata(bl);
calc_flag = StatusChangeFlagTable[type];
if(!(flag&4)) // &4 - Do not parse val settings when loading SCs
if(!(flag&SCSTART_LOADED)) // &4 - Do not parse val settings when loading SCs
switch(type)
{
/* Permanent effects */
case SC_AETERNA:
case SC_MODECHANGE:
case SC_WEIGHT50:
case SC_WEIGHT90:
case SC_BROKENWEAPON:
case SC_BROKENARMOR:
case SC_READYSTORM:
case SC_READYDOWN:
case SC_READYCOUNTER:
case SC_READYTURN:
case SC_DODGE:
case SC_PUSH_CART:
tick = -1;
break;
case SC_DECREASEAGI:
case SC_INCREASEAGI:
case SC_ADORAMUS:
@ -8351,17 +8365,17 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
break;
case SC_ENDURE:
val2 = 7; // Hit-count [Celest]
if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground && !val4 ) {
if( !(flag&SCSTART_NOAVOID) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground && !val4 ) {
struct map_session_data *tsd;
if( sd ) {
int i;
for( i = 0; i < MAX_DEVOTION; i++ ) {
if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) )
status_change_start(src,&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1|16);
status_change_start(src,&tsd->bl, type, 10000, val1, val2, val3, val4, tick, SCSTART_NOAVOID|SCSTART_NOICON);
}
}
else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
status_change_start(src,&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1);
status_change_start(src,&tsd->bl, type, 10000, val1, val2, val3, val4, tick, SCSTART_NOAVOID|SCSTART_NOICON);
}
// val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk)
if( val4 )
@ -8445,17 +8459,17 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
case SC_REFLECTSHIELD:
val2 = 10+val1*3; // %Dmg reflected
// val4 used to mark if reflect shield is an inheritance bonus from Devotion
if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) ) {
if( !(flag&SCSTART_NOAVOID) && (bl->type&(BL_PC|BL_MER)) ) {
struct map_session_data *tsd;
if( sd ) {
int i;
for( i = 0; i < MAX_DEVOTION; i++ ) {
if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) )
status_change_start(src,&tsd->bl, type, 10000, val1, val2, 0, 1, tick, 1|16);
status_change_start(src,&tsd->bl, type, 10000, val1, val2, 0, 1, tick, SCSTART_NOAVOID|SCSTART_NOICON);
}
}
else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
status_change_start(src,&tsd->bl, type, 10000, val1, val2, 0, 1, tick, 1);
status_change_start(src,&tsd->bl, type, 10000, val1, val2, 0, 1, tick, SCSTART_NOAVOID|SCSTART_NOICON);
}
break;
case SC_STRIPWEAPON:
@ -8481,25 +8495,44 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
val4 = 5 + val1*2; // Chance of casting
break;
case SC_VOLCANO:
val2 = val1*10; // Watk increase
{
int8 enchant_eff[] = { 10, 14, 17, 19, 20 }; // Enchant addition
uint8 i = max((val1-1)%5, 0);
val2 = val1*10; // Watk increase
#ifndef RENEWAL
if (status->def_ele != ELE_FIRE)
val2 = 0;
if (status->def_ele != ELE_FIRE)
val2 = 0;
#endif
val3 = enchant_eff[i];
}
break;
case SC_VIOLENTGALE:
val2 = val1*3; // Flee increase
{
int8 enchant_eff[] = { 10, 14, 17, 19, 20 }; // Enchant addition
uint8 i = max((val1-1)%5, 0);
val2 = val1*3; // Flee increase
#ifndef RENEWAL
if (status->def_ele != ELE_WIND)
val2 = 0;
if (status->def_ele != ELE_WIND)
val2 = 0;
#endif
val3 = enchant_eff[i];
}
break;
case SC_DELUGE:
val2 = deluge_eff[val1-1]; // HP increase
{
int8 deluge_eff[] = { 5, 9, 12, 14, 15 }; // HP addition rate n/100
int8 enchant_eff[] = { 10, 14, 17, 19, 20 }; // Enchant addition
uint8 i = max((val1-1)%5, 0);
val2 = deluge_eff[i]; // HP increase
#ifndef RENEWAL
if(status->def_ele != ELE_WATER)
val2 = 0;
if (status->def_ele != ELE_WATER)
val2 = 0;
#endif
val3 = enchant_eff[i];
}
break;
case SC_SUITON:
if (!val2 || (sd && (sd->class_&MAPID_BASEMASK) == MAPID_NINJA)) {
@ -8551,15 +8584,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
val2 = 50*(2+type-SC_ASPDPOTION0);
break;
case SC_WEDDING:
case SC_XMAS:
case SC_SUMMER:
case SC_HANBOK:
case SC_OKTOBERFEST:
if (!vd) return 0;
// Store previous values as they could be removed.
unit_stop_attack(bl);
break;
case SC_NOCHAT:
// A hardcoded interval of 60 seconds is expected, as the time that SC_NOCHAT uses is defined by
// mmocharstatus.manner, each negative point results in 1 minute with this status activated.
@ -8607,7 +8631,8 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
break;
case SC_CONFUSION:
clif_emotion(bl,E_WHAT);
if (!val4)
clif_emotion(bl,E_WHAT);
break;
case SC_BLEEDING:
val4 = tick/10000;
@ -8674,24 +8699,8 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
tick_time = 10; // [GodLesZ] tick time
break;
/* Permanent effects */
case SC_AETERNA:
case SC_MODECHANGE:
case SC_WEIGHT50:
case SC_WEIGHT90:
case SC_BROKENWEAPON:
case SC_BROKENARMOR:
case SC_READYSTORM:
case SC_READYDOWN:
case SC_READYCOUNTER:
case SC_READYTURN:
case SC_DODGE:
case SC_PUSH_CART:
tick = -1;
break;
case SC_AUTOGUARD:
if( !(flag&1) ) {
if( !(flag&SCSTART_NOAVOID) ) {
struct map_session_data *tsd;
int i;
for( i = val2 = 0; i < val1; i++) {
@ -8703,17 +8712,17 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
if( sd ) {
for( i = 0; i < MAX_DEVOTION; i++ ) {
if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) )
status_change_start(src,&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1|16);
status_change_start(src,&tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCSTART_NOAVOID|SCSTART_NOICON);
}
}
else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
status_change_start(src,&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
status_change_start(src,&tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCSTART_NOAVOID|SCSTART_NOICON);
}
}
break;
case SC_DEFENDER:
if (!(flag&1)) {
if (!(flag&SCSTART_NOAVOID)) {
val2 = 5 + 15*val1; // Damage reduction
val3 = 0; // Unused, previously speed adjustment
val4 = 250 - 50*val1; // Aspd adjustment
@ -8723,7 +8732,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
int i;
for (i = 0; i < MAX_DEVOTION; i++) { // See if there are devoted characters, and pass the status to them. [Skotlex]
if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])))
status_change_start(src,&tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,1);
status_change_start(src,&tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,SCSTART_NOAVOID);
}
}
}
@ -8848,7 +8857,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
while( i >= 0 ) {
enum sc_type type2 = types[i];
if( d_sc->data[type2] )
status_change_start(d_bl, bl, type2, 10000, d_sc->data[type2]->val1, 0, 0, (type2 == SC_REFLECTSHIELD ? 1 : 0), skill_get_time(status_sc2skill(type2),d_sc->data[type2]->val1), (type2 == SC_DEFENDER) ? 1 : 1|16);
status_change_start(d_bl, bl, type2, 10000, d_sc->data[type2]->val1, 0, 0, (type2 == SC_REFLECTSHIELD ? 1 : 0), skill_get_time(status_sc2skill(type2),d_sc->data[type2]->val1), (type2 == SC_DEFENDER) ? 1 : SCSTART_NOAVOID|SCSTART_NOICON);
i--;
}
}
@ -9239,7 +9248,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
tick_time = 4000; // [GodLesZ] tick time
break;
case SC_PYREXIA:
status_change_start(src,bl,SC_BLIND,10000,val1,0,0,0,30000,11); // Blind status that last for 30 seconds
status_change_start(src,bl,SC_BLIND,10000,val1,0,0,0,30000,SCSTART_NOAVOID|SCSTART_NOTICKDEF|SCSTART_NORATEDEF); // Blind status that last for 30 seconds
val4 = tick / 3000;
tick_time = 3000; // [GodLesZ] tick time
break;
@ -9355,14 +9364,14 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
break;
case SC__UNLUCKY:
{
short rand_eff;
sc_type rand_eff;
switch(rand() % 3) {
case 1: rand_eff = SC_BLIND; break;
case 2: rand_eff = SC_SILENCE; break;
default: rand_eff = SC_POISON; break;
}
val2 = 10 * val1; // Crit and Flee2 Reduction
status_change_start(src,bl,rand_eff,10000,val1,0,0,0,tick,10);
status_change_start(src,bl,rand_eff,10000,val1,0,0,0,tick,SCSTART_NOTICKDEF|SCSTART_NORATEDEF);
break;
}
case SC__WEAKNESS:
@ -9842,11 +9851,12 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
val3 = val1 * 25; // -movespeed (custom)
break;
case SC_C_MARKER:
val2 = src->id;
val3 = 10; //-10% flee
// val1 = skill_lv
// val2 = src_id
val3 = 10; // -10 flee
//Start timer to send mark on mini map
val4 = tick/1000;
tick_time = 1000;
tick_time = 1000; // Sends every 1 seconds
break;
case SC_H_MINE:
val2 = src->id;
@ -9854,8 +9864,9 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
case SC_HEAT_BARREL:
//kRO Update 2014-02-26
{
short n = 10;
if (sd) n = sd->spiritball_old;
uint8 n = 10;
if (sd)
n = (uint8)sd->spiritball_old;
val2 = val1 * 5; // -fixed casttime (custom)
val3 = val1 * n / 5; // +aspd (custom)
val4 = 75 - val1 * 5; // -flee
@ -9863,8 +9874,9 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
break;
case SC_P_ALTER:
{
short n = 10;
if (sd) n = sd->spiritball_old;
uint8 n = 10;
if (sd)
n = (uint8)sd->spiritball_old;
val2 = val1 * n * 2; // +atk (custom)
val3 = val1 * 15; // +def (custom)
}
@ -9872,7 +9884,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
case SC_E_CHAIN:
val2 = 10;
if (sd)
val2 = (uint8)sd->spiritball_old;
val2 = sd->spiritball_old;
break;
case SC_ANTI_M_BLAST:
val2 = val1 * 10;
@ -10007,7 +10019,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
case SC_BITE:
case SC_THORNSTRAP:
case SC__MANHOLE:
case SC__CHAOS:
//case SC__CHAOS:
case SC_CRYSTALIZE:
case SC_CURSEDCIRCLE_ATKER:
case SC_FEAR:
@ -10017,11 +10029,11 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
case SC_PARALYSIS:
case SC_MAGNETICFIELD:
unit_stop_walking(bl,1);
break;
break;
case SC_ANKLE:
if( battle_config.skill_trap_type || !map_flag_gvg(bl->m) )
unit_stop_walking(bl,1);
break;
break;
case SC_HIDING:
case SC_CLOAKING:
case SC_CLOAKINGEXCEED:
@ -10031,16 +10043,21 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
case SC_CAMOUFLAGE:
case SC_VOICEOFSIREN:
case SC_HEAT_BARREL_AFTER:
case SC_WEDDING:
case SC_XMAS:
case SC_SUMMER:
case SC_HANBOK:
case SC_OKTOBERFEST:
unit_stop_attack(bl);
break;
break;
case SC_SILENCE:
if (battle_config.sc_castcancel&bl->type)
unit_skillcastcancel(bl, 0);
break;
break;
case SC_VACUUM_EXTREME:
if (!map_flag_gvg(bl->m))
unit_stop_walking(bl, 1);
break;
break;
case SC_ITEMSCRIPT: // Shows Buff Icons
if (sd && val2 != SI_BLANK)
clif_status_change(bl, (enum si_type)val2, 1, tick, 0, 0, 0);
@ -10231,7 +10248,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
calc_flag&=~SCB_DYE;
}
if(!(flag&16) && !(flag&4 && StatusDisplayType[type]))
if(!(flag&SCSTART_NOICON) && !(flag&SCSTART_LOADED && StatusDisplayType[type]))
clif_status_change(bl,StatusIconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0);
// Used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first.
@ -10333,7 +10350,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
case SC_C_MARKER:
//Send mini-map, don't wait for first timer triggered
if (src->type == BL_PC && (sd = map_id2sd(src->id)))
clif_crimson_marker(sd->fd,bl,false);
clif_crimson_marker(sd, bl, false);
break;
}
@ -10495,7 +10512,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
struct status_change_entry *sce;
struct status_data *status;
struct view_data *vd;
int opt_flag=0, calc_flag,temp_n = 0;
int opt_flag = 0, calc_flag;
nullpo_ret(bl);
@ -10542,11 +10559,6 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
if ( StatusChangeStateTable[type] )
status_calc_state(bl,sc,( enum scs_flag ) StatusChangeStateTable[type],false);
switch (type) {
case SC_H_MINE: temp_n = sc->data[type]->val3; break; // If ended by RL_FLICKER, don't drop the trap
case SC_C_MARKER: temp_n = sc->data[type]->val2; break; // Player who gave mark
}
sc->data[type] = NULL;
if (sd && StatusDisplayType[type])
@ -10984,15 +10996,15 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
case SC_C_MARKER:
{
// Remove mark data from caster
struct map_session_data *caster = map_id2sd(temp_n);
struct map_session_data *caster = map_id2sd(sce->val2);
uint8 i = 0;
if (!caster || !&caster->c_marker || !caster->c_marker.target)
if (!caster)
break;
ARR_FIND(0,MAX_SKILL_CRIMSON_MARKER,i,caster->c_marker.target[i] == bl->id);
ARR_FIND(0,MAX_SKILL_CRIMSON_MARKER,i,caster->c_marker[i] == bl->id);
if (i < MAX_SKILL_CRIMSON_MARKER) {
caster->c_marker.target[i] = 0;
clif_crimson_marker(caster->fd,bl,true);
caster->c_marker[i] = 0;
clif_crimson_marker(caster, bl, true);
}
}
break;
@ -11000,15 +11012,17 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
{
// Drop the material from target if expired
struct item it;
if (temp_n)
struct map_session_data *caster = NULL;
if (sce->val3 || status_isdead(bl) || !(caster = map_id2sd(sce->val2)))
break;
if (!itemdb_exists(skill_get_itemid(RL_H_MINE,0)))
break;
memset(&it,0,sizeof(it));
memset(&it, 0, sizeof(it));
it.nameid = skill_get_itemid(RL_H_MINE,0);
it.amount = max(skill_get_itemqty(RL_H_MINE,0),1);
it.identify = 1;
map_addflooritem(&it,it.amount,bl->m,bl->x,bl->y,0,0,0,4);
map_addflooritem(&it, it.amount, bl->m,bl->x, bl->y, caster->status.char_id, 0, 0, 4);
}
break;
}
@ -11646,15 +11660,18 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
}
if( !flag ) { // Random Skill Cast
if (sd && !pc_issit(sd)) { // Can't cast if sit
int mushroom_skill_id = 0;
if (skill_magicmushroom_count && sd && !pc_issit(sd)) { // Can't cast if sit
int mushroom_skill_id = 0, checked = 0, checked_max = MAX_SKILL_MAGICMUSHROOM_DB * 3;
unit_stop_attack(bl);
unit_skillcastcancel(bl,1);
do {
int i = rnd() % MAX_SKILL_MAGICMUSHROOM_DB;
mushroom_skill_id = skill_magicmushroom_db[i].skill_id;
}
while( mushroom_skill_id == 0 );
while( checked++ < checked_max && mushroom_skill_id == 0 );
if (!skill_get_index(mushroom_skill_id))
break;
switch( skill_get_casttype(mushroom_skill_id) ) { // Magic Mushroom skills are buffs or area damage
case CAST_GROUND:
@ -12114,17 +12131,18 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
break;
case SC_C_MARKER:
if( --(sce->val4) >= 0 ) {
TBL_PC *tsd = map_id2sd(sce->val2);
if (!tsd || tsd->bl.m != bl->m) //End the SC if caster isn't in same map
TBL_PC *caster = map_id2sd(sce->val2);
if (!caster || caster->bl.m != bl->m) //End the SC if caster isn't in same map
break;
sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
clif_crimson_marker(tsd->fd,bl,false);
clif_crimson_marker(caster, bl, false);
return 0;
}
break;
}
// Default for all non-handled control paths is to end the status
return status_change_end( bl,type,tid );
#undef sc_timer_next
}
@ -12474,7 +12492,7 @@ int status_change_spread( struct block_list *src, struct block_list *bl )
data.val2 = sc->data[i]->val2;
data.val3 = sc->data[i]->val3;
data.val4 = sc->data[i]->val4;
status_change_start(src,bl,(sc_type)i,10000,data.val1,data.val2,data.val3,data.val4,data.tick,1|2|8);
status_change_start(src,bl,(sc_type)i,10000,data.val1,data.val2,data.val3,data.val4,data.tick,SCSTART_NOAVOID|SCSTART_NOTICKDEF|SCSTART_NORATEDEF);
flag = 1;
}
}

View File

@ -1732,6 +1732,16 @@ enum e_status_calc_opt {
SCO_FORCE = 0x2, /* Only relevant to BL_PC types, ensures call bypasses the queue caused by delayed damage */
};
/// Flags for status_change_start and status_get_sc_def
enum e_status_change_start_flags {
SCSTART_NONE = 0x00,
SCSTART_NOAVOID = 0x01, /// Cannot be avoided (it has to start)
SCSTART_NOTICKDEF = 0x02, /// Tick should not be reduced (by statuses or bonuses)
SCSTART_LOADED = 0x04, /// When sc_data loaded (fetched from table), no values (val1 ~ val4) have to be altered/recalculate
SCSTART_NORATEDEF = 0x08, /// Rate should not be reduced (by statuses or bonuses)
SCSTART_NOICON = 0x10, /// Status icon won't be sent to client
};
///Enum for bonus_script's flag [Cydh]
enum e_bonus_script_flags {
BSF_REM_ON_DEAD = 0x001, ///Removed when dead
@ -1995,13 +2005,13 @@ struct status_change *status_get_sc(struct block_list *bl);
int status_isdead(struct block_list *bl);
int status_isimmune(struct block_list *bl);
int status_get_sc_def(struct block_list *src,struct block_list *bl, enum sc_type type, int rate, int tick, int flag);
int status_get_sc_def(struct block_list *src,struct block_list *bl, enum sc_type type, int rate, int tick, unsigned char flag);
//Short version, receives rate in 1->100 range, and does not uses a flag setting.
#define sc_start(src, bl, type, rate, val1, tick) status_change_start(src,bl,type,100*(rate),val1,0,0,0,tick,0)
#define sc_start2(src, bl, type, rate, val1, val2, tick) status_change_start(src,bl,type,100*(rate),val1,val2,0,0,tick,0)
#define sc_start4(src, bl, type, rate, val1, val2, val3, val4, tick) status_change_start(src,bl,type,100*(rate),val1,val2,val3,val4,tick,0)
#define sc_start(src, bl, type, rate, val1, tick) status_change_start(src,bl,type,100*(rate),val1,0,0,0,tick,SCSTART_NONE)
#define sc_start2(src, bl, type, rate, val1, val2, tick) status_change_start(src,bl,type,100*(rate),val1,val2,0,0,tick,SCSTART_NONE)
#define sc_start4(src, bl, type, rate, val1, val2, val3, val4, tick) status_change_start(src,bl,type,100*(rate),val1,val2,val3,val4,tick,SCSTART_NONE)
int status_change_start(struct block_list* src, struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag);
int status_change_start(struct block_list* src, struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,unsigned char flag);
int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line);
#define status_change_end(bl,type,tid) status_change_end_(bl,type,tid,__FILE__,__LINE__)
int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data);

View File

@ -934,8 +934,12 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
if(dx || dy) {
map_foreachinmovearea(clif_outsight, bl, AREA_SIZE, dx, dy, bl->type == BL_PC ? BL_ALL : BL_PC, bl);
if(su)
skill_unit_move_unit_group(su->group, bl->m, dx, dy);
if(su) {
if (su->group && skill_get_unit_flag(su->group->skill_id)&UF_KNOCKBACK_GROUP)
skill_unit_move_unit_group(su->group, bl->m, dx, dy);
else
skill_unit_move_unit(bl, nx, ny);
}
else
map_moveblock(bl, nx, ny, gettick());
@ -1424,6 +1428,19 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
}
}
break;
case RL_C_MARKER:
{
uint8 i = 0;
ARR_FIND(0, MAX_SKILL_CRIMSON_MARKER, i, sd->c_marker[i] == target_id);
if (i == MAX_SKILL_CRIMSON_MARKER) {
ARR_FIND(0, MAX_SKILL_CRIMSON_MARKER, i, sd->c_marker[i] == 0);
if (i == MAX_SKILL_CRIMSON_MARKER) { // No free slots, skill Fail
clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
return 0;
}
}
}
break;
}
if (!skill_check_condition_castbegin(sd, skill_id, skill_lv))
return 0;

View File

@ -24,8 +24,8 @@ Main($sCmd,$sTarget);
sub GetArgs {
GetOptions(
'cmd=s' => \$sCmd, # wich command to run
'atcf=s' => \$sAtcf, #atc doc file
'cmd=s' => \$sCmd, # which command to run
'atcf=s' => \$sAtcf, #atcommand doc file
'scriptf=s' => \$sSctf, #script doc file
'inc_atcf=s' => \$sInc_atcf, #include script doc file (for customs doc)
'inc_scrtf=s' => \$sInc_scrtf, #include script doc file (for customs doc)
@ -35,7 +35,7 @@ sub GetArgs {
) or $sHelp=1; #display help if invalid option
if( $sHelp ) {
print "Incorect option specified, available option are:\n"
print "Incorrect option specified, available options are:\n"
."\t --atcf filename => file (specify atcommand doc to use)\n"
."\t --inc_atcf filename => include file (specify atcommand doc to use)\n"
."\t --scriptf filename => file (specify script doc to use)\n"
@ -46,12 +46,12 @@ sub GetArgs {
exit;
}
unless($sTarget =~ /$sValidTarget/i){
print "Incorect target specified, available target are:\n"
print "Incorrect target specified, available target is:\n"
."\t --target => target (specify wich check to run [(default)$sValidTarget])\n";
exit;
}
unless($sCmd =~ /$sValidCmd/i){
print "Incorect command specified, available command are:\n"
print "Incorrect command specified, available command is:\n"
."\t --cmd => cmd (specify wich command to run [(default)$sValidCmd])\n";
exit;
}
@ -65,14 +65,14 @@ sub Main { my ($sCmd,$sTarget) = @_;
if($sTarget=~/script/i){ #find which script commands are missing from doc/script_commands.txt
my $raSct_cmd = Script_GetCmd();
if($sCmd =~ /ls/i) {
print "The list of script-command found are = \n[ @$raSct_cmd ] \n\n";
print "The list of script-commands found are = \n[ @$raSct_cmd ] \n\n";
}
if($sCmd =~ /chk/i) { Script_Chk($raSct_cmd); }
}
if($sTarget=~/atc/i){ #find which atcommands are missing from doc/atcommands.txt
my $raAct_cmd = Atc_GetCmd();
if($sCmd =~ /ls/i) {
print "The list of atcommand found are = \n[ @$raAct_cmd ] \n\n";
print "The list of atcommands found are = \n[ @$raAct_cmd ] \n\n";
}
if($sCmd =~ /chk/i) { Atc_Chk($raAct_cmd); }
}
@ -240,12 +240,12 @@ sub Atc_Chk { my ($raDef_act) = @_;
if($sLeftOverChk){
my $raLeftover_sct = Chk(\@aDoc_act,$raDef_act); #we just inverse the chk for leftover
if(scalar(@$raLeftover_sct)){
print "Those atcommand command was found in doc but no source associated, leftover ? : {\n";
print "Those atcommands were found in doc but no source associated, leftover ? : {\n";
foreach(@$raLeftover_sct){
print "\t$_ \n";
}
print "}\n\n";
}
else { print "All atcommand in documentation match a source ATCMD, no leftover found\n"; }
else { print "All atcommands in documentation match a source ATCMD, no leftover found\n"; }
}
}