Implements SC_STONEWAIT (#6794)
* Fixes #6748. * Implements SC_STONEWAIT to be used with OPT1_STONEWAIT. * Removes a lot of hard coded OPT1_STONE checks now that the two states are split to their own statuses. * Fixes SC_STONE not ending when the target receives damage. * Fixes SC_STONE getting overwritten by other statuses the have OPT1 states. * SC_STONE should damage the target by 1% of MaxHP, not CurrentHP. * All skills that give StoneWait aside from Stone Curse are 100ms. * Confirmed that Sienna Execrate is 8 + 2 * SkillLv seconds of Stone. * Moves Provoke and Mind Breaker status clearings to the status database. * Converts EndReturn in the status database from a boolean to a list of statuses. Statuses defined in this list will be ended and then the status making the call will not take affect. Thanks to @Singe-Horizontal, @Playtester, and @Lemongrass3110!
This commit is contained in:
parent
3b47defa35
commit
cee161e677
@ -36,9 +36,9 @@
|
|||||||
# MinDuration Minimum duration in milliseconds after status change reduction. (Default: 1)
|
# MinDuration Minimum duration in milliseconds after status change reduction. (Default: 1)
|
||||||
# Fail: List of Status Changes that causes the status to fail to activate. (Optional)
|
# Fail: List of Status Changes that causes the status to fail to activate. (Optional)
|
||||||
# End: List of Status Changes that will end when the status activates. (Optional)
|
# End: List of Status Changes that will end when the status activates. (Optional)
|
||||||
# EndReturn If the status has an End list and succeeds to remove these status changes, it won't give its effect. (Default: false)
|
# EndReturn: List of Status Changes that will end when the status activates and won't give its effect. (Optional)
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
Header:
|
Header:
|
||||||
Type: STATUS_DB
|
Type: STATUS_DB
|
||||||
Version: 1
|
Version: 2
|
||||||
|
@ -796,8 +796,8 @@ Body:
|
|||||||
Element: Earth
|
Element: Earth
|
||||||
CastCancel: true
|
CastCancel: true
|
||||||
CastTime: 1000
|
CastTime: 1000
|
||||||
Duration1: 5000
|
Duration1: 20000
|
||||||
Duration2: 20000
|
Duration2: 5000
|
||||||
Requires:
|
Requires:
|
||||||
SpCost:
|
SpCost:
|
||||||
- Level: 1
|
- Level: 1
|
||||||
@ -823,7 +823,7 @@ Body:
|
|||||||
ItemCost:
|
ItemCost:
|
||||||
- Item: Red_Gemstone
|
- Item: Red_Gemstone
|
||||||
Amount: 1
|
Amount: 1
|
||||||
Status: Stone
|
Status: StoneWait
|
||||||
- Id: 17
|
- Id: 17
|
||||||
Name: MG_FIREBALL
|
Name: MG_FIREBALL
|
||||||
Description: Fire Ball
|
Description: Fire Ball
|
||||||
@ -5663,8 +5663,9 @@ Body:
|
|||||||
Hit: Single
|
Hit: Single
|
||||||
HitCount: 1
|
HitCount: 1
|
||||||
Element: Weapon
|
Element: Weapon
|
||||||
Duration2: 20000
|
Duration1: 20000
|
||||||
Status: Stone
|
Duration2: 100
|
||||||
|
Status: StoneWait
|
||||||
- Id: 181
|
- Id: 181
|
||||||
Name: NPC_CURSEATTACK
|
Name: NPC_CURSEATTACK
|
||||||
Description: Curse Attack
|
Description: Curse Attack
|
||||||
@ -15911,8 +15912,9 @@ Body:
|
|||||||
Area: 11
|
Area: 11
|
||||||
- Level: 5
|
- Level: 5
|
||||||
Area: 14
|
Area: 14
|
||||||
Duration2: 20000
|
Duration1: 20000
|
||||||
Status: Stone
|
Duration2: 100
|
||||||
|
Status: StoneWait
|
||||||
- Id: 667
|
- Id: 667
|
||||||
Name: NPC_WIDECONFUSE
|
Name: NPC_WIDECONFUSE
|
||||||
Description: Wide Confusion
|
Description: Wide Confusion
|
||||||
|
@ -36,37 +36,63 @@
|
|||||||
# MinDuration Minimum duration in milliseconds after status change reduction. (Default: 1)
|
# MinDuration Minimum duration in milliseconds after status change reduction. (Default: 1)
|
||||||
# Fail: List of Status Changes that causes the status to fail to activate. (Optional)
|
# Fail: List of Status Changes that causes the status to fail to activate. (Optional)
|
||||||
# End: List of Status Changes that will end when the status activates. (Optional)
|
# End: List of Status Changes that will end when the status activates. (Optional)
|
||||||
# EndReturn If the status has an End list and succeeds to remove these status changes, it won't give its effect. (Default: false)
|
# EndReturn: List of Status Changes that will end when the status activates and won't give its effect. (Optional)
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
Header:
|
Header:
|
||||||
Type: STATUS_DB
|
Type: STATUS_DB
|
||||||
Version: 1
|
Version: 2
|
||||||
|
|
||||||
Body:
|
Body:
|
||||||
- Status: Stone
|
- Status: Stone
|
||||||
DurationLookup: NPC_PETRIFYATTACK
|
DurationLookup: NPC_PETRIFYATTACK
|
||||||
States:
|
States:
|
||||||
NoMove: true
|
NoMove: true
|
||||||
NoMoveCond: true
|
|
||||||
NoCast: true
|
NoCast: true
|
||||||
NoAttack: true
|
NoAttack: true
|
||||||
CalcFlags:
|
CalcFlags:
|
||||||
Def_Ele: true
|
Def_Ele: true
|
||||||
Def: true
|
Def: true
|
||||||
Mdef: true
|
Mdef: true
|
||||||
|
Opt1: Stone
|
||||||
Flags:
|
Flags:
|
||||||
SendOption: true
|
SendOption: true
|
||||||
BossResist: true
|
BossResist: true
|
||||||
StopAttacking: true
|
StopAttacking: true
|
||||||
StopCasting: true
|
StopCasting: true
|
||||||
|
RemoveOnDamaged: true
|
||||||
Fail:
|
Fail:
|
||||||
Refresh: true
|
Refresh: true
|
||||||
Inspiration: true
|
Inspiration: true
|
||||||
Power_Of_Gaia: true
|
Power_Of_Gaia: true
|
||||||
Gvg_Stone: true
|
Gvg_Stone: true
|
||||||
|
Freeze: true
|
||||||
|
Stun: true
|
||||||
|
Sleep: true
|
||||||
|
Burning: true
|
||||||
|
#Undead: true
|
||||||
End:
|
End:
|
||||||
Dancing: true
|
Aeterna: true
|
||||||
|
EndReturn:
|
||||||
|
StoneWait: true
|
||||||
|
Stone: true
|
||||||
|
- Status: StoneWait
|
||||||
|
DurationLookup: NPC_PETRIFYATTACK
|
||||||
|
States:
|
||||||
|
NoCast: true
|
||||||
|
Opt1: StoneWait
|
||||||
|
Flags:
|
||||||
|
SendOption: true
|
||||||
|
StopAttacking: true
|
||||||
|
Fail:
|
||||||
|
Freeze: true
|
||||||
|
Stun: true
|
||||||
|
Sleep: true
|
||||||
|
Burning: true
|
||||||
|
#Undead: true
|
||||||
|
EndReturn:
|
||||||
|
StoneWait: true
|
||||||
|
Stone: true
|
||||||
- Status: Freeze
|
- Status: Freeze
|
||||||
DurationLookup: NPC_WIDEFREEZE
|
DurationLookup: NPC_WIDEFREEZE
|
||||||
States:
|
States:
|
||||||
@ -247,6 +273,11 @@ Body:
|
|||||||
BossResist: true
|
BossResist: true
|
||||||
Debuff: true
|
Debuff: true
|
||||||
NoSaveInfinite: true
|
NoSaveInfinite: true
|
||||||
|
End:
|
||||||
|
Freeze: true
|
||||||
|
Stone: true
|
||||||
|
Sleep: true
|
||||||
|
TrickDead: true
|
||||||
- Status: Endure
|
- Status: Endure
|
||||||
Icon: EFST_ENDURE
|
Icon: EFST_ENDURE
|
||||||
DurationLookup: SM_ENDURE
|
DurationLookup: SM_ENDURE
|
||||||
@ -505,6 +536,7 @@ Body:
|
|||||||
Flags:
|
Flags:
|
||||||
NoSave: true
|
NoSave: true
|
||||||
Fail:
|
Fail:
|
||||||
|
Stone: true
|
||||||
Freeze: true
|
Freeze: true
|
||||||
- Status: Adrenaline
|
- Status: Adrenaline
|
||||||
Icon: EFST_ADRENALINE
|
Icon: EFST_ADRENALINE
|
||||||
@ -1229,9 +1261,8 @@ Body:
|
|||||||
Fail:
|
Fail:
|
||||||
Quagmire: true
|
Quagmire: true
|
||||||
Dontforgetme: true
|
Dontforgetme: true
|
||||||
End:
|
EndReturn:
|
||||||
Decreaseagi: true
|
Decreaseagi: true
|
||||||
EndReturn: true
|
|
||||||
- Status: Chasewalk
|
- Status: Chasewalk
|
||||||
Icon: EFST_CHASEWALK
|
Icon: EFST_CHASEWALK
|
||||||
DurationLookup: ST_CHASEWALK
|
DurationLookup: ST_CHASEWALK
|
||||||
@ -1317,6 +1348,10 @@ Body:
|
|||||||
Flags:
|
Flags:
|
||||||
NoSave: true
|
NoSave: true
|
||||||
Debuff: true
|
Debuff: true
|
||||||
|
End:
|
||||||
|
Freeze: true
|
||||||
|
Stone: true
|
||||||
|
Sleep: true
|
||||||
- Status: Memorize
|
- Status: Memorize
|
||||||
Icon: EFST_MEMORIZE
|
Icon: EFST_MEMORIZE
|
||||||
DurationLookup: PF_MEMORIZE
|
DurationLookup: PF_MEMORIZE
|
||||||
@ -4179,9 +4214,8 @@ Body:
|
|||||||
Fail:
|
Fail:
|
||||||
Quagmire: true
|
Quagmire: true
|
||||||
Dontforgetme: true
|
Dontforgetme: true
|
||||||
End:
|
EndReturn:
|
||||||
Decreaseagi: true
|
Decreaseagi: true
|
||||||
EndReturn: true
|
|
||||||
- Status: Thornstrap
|
- Status: Thornstrap
|
||||||
Icon: EFST_THORNS_TRAP
|
Icon: EFST_THORNS_TRAP
|
||||||
DurationLookup: GN_THORNS_TRAP
|
DurationLookup: GN_THORNS_TRAP
|
||||||
@ -5698,9 +5732,8 @@ Body:
|
|||||||
NoBanishingBuster: true
|
NoBanishingBuster: true
|
||||||
NoClearance: true
|
NoClearance: true
|
||||||
NoForcedEnd: true
|
NoForcedEnd: true
|
||||||
End:
|
EndReturn:
|
||||||
All_Riding: true
|
All_Riding: true
|
||||||
EndReturn: true
|
|
||||||
- Status: Teargas_Sob
|
- Status: Teargas_Sob
|
||||||
Flags:
|
Flags:
|
||||||
BossResist: true
|
BossResist: true
|
||||||
|
@ -780,8 +780,8 @@ Body:
|
|||||||
Element: Earth
|
Element: Earth
|
||||||
CastCancel: true
|
CastCancel: true
|
||||||
CastTime: 800
|
CastTime: 800
|
||||||
Duration1: 5000
|
Duration1: 17000
|
||||||
Duration2: 17000
|
Duration2: 5000
|
||||||
FixedCastTime: 200
|
FixedCastTime: 200
|
||||||
Requires:
|
Requires:
|
||||||
SpCost:
|
SpCost:
|
||||||
@ -808,7 +808,7 @@ Body:
|
|||||||
ItemCost:
|
ItemCost:
|
||||||
- Item: Red_Gemstone
|
- Item: Red_Gemstone
|
||||||
Amount: 1
|
Amount: 1
|
||||||
Status: Stone
|
Status: StoneWait
|
||||||
- Id: 17
|
- Id: 17
|
||||||
Name: MG_FIREBALL
|
Name: MG_FIREBALL
|
||||||
Description: Fire Ball
|
Description: Fire Ball
|
||||||
@ -5933,8 +5933,9 @@ Body:
|
|||||||
Hit: Single
|
Hit: Single
|
||||||
HitCount: 1
|
HitCount: 1
|
||||||
Element: Weapon
|
Element: Weapon
|
||||||
Duration2: 17000
|
Duration1: 17000
|
||||||
Status: Stone
|
Duration2: 100
|
||||||
|
Status: StoneWait
|
||||||
- Id: 181
|
- Id: 181
|
||||||
Name: NPC_CURSEATTACK
|
Name: NPC_CURSEATTACK
|
||||||
Description: Curse Attack
|
Description: Curse Attack
|
||||||
@ -16310,8 +16311,9 @@ Body:
|
|||||||
Area: 11
|
Area: 11
|
||||||
- Level: 5
|
- Level: 5
|
||||||
Area: 14
|
Area: 14
|
||||||
Duration2: 17000
|
Duration1: 17000
|
||||||
Status: Stone
|
Duration2: 100
|
||||||
|
Status: StoneWait
|
||||||
- Id: 667
|
- Id: 667
|
||||||
Name: NPC_WIDECONFUSE
|
Name: NPC_WIDECONFUSE
|
||||||
Description: Wide Confusion
|
Description: Wide Confusion
|
||||||
@ -19241,6 +19243,7 @@ Body:
|
|||||||
Time: 13000
|
Time: 13000
|
||||||
- Level: 5
|
- Level: 5
|
||||||
Time: 15000
|
Time: 15000
|
||||||
|
Duration2: 100
|
||||||
Requires:
|
Requires:
|
||||||
SpCost:
|
SpCost:
|
||||||
- Level: 1
|
- Level: 1
|
||||||
@ -19256,7 +19259,7 @@ Body:
|
|||||||
ItemCost:
|
ItemCost:
|
||||||
- Item: Red_Gemstone
|
- Item: Red_Gemstone
|
||||||
Amount: 2
|
Amount: 2
|
||||||
Status: Stone
|
Status: StoneWait
|
||||||
- Id: 2208
|
- Id: 2208
|
||||||
Name: WL_RADIUS
|
Name: WL_RADIUS
|
||||||
Description: Radius
|
Description: Radius
|
||||||
@ -32010,6 +32013,7 @@ Body:
|
|||||||
CastCancel: true
|
CastCancel: true
|
||||||
AfterCastActDelay: 1000
|
AfterCastActDelay: 1000
|
||||||
Duration1: 10000
|
Duration1: 10000
|
||||||
|
Duration2: 5000
|
||||||
Requires:
|
Requires:
|
||||||
SpCost: 30
|
SpCost: 30
|
||||||
Unit:
|
Unit:
|
||||||
|
@ -36,37 +36,65 @@
|
|||||||
# MinDuration Minimum duration in milliseconds after status change reduction. (Default: 1)
|
# MinDuration Minimum duration in milliseconds after status change reduction. (Default: 1)
|
||||||
# Fail: List of Status Changes that causes the status to fail to activate. (Optional)
|
# Fail: List of Status Changes that causes the status to fail to activate. (Optional)
|
||||||
# End: List of Status Changes that will end when the status activates. (Optional)
|
# End: List of Status Changes that will end when the status activates. (Optional)
|
||||||
# EndReturn If the status has an End list and succeeds to remove these status changes, it won't give its effect. (Default: false)
|
# EndReturn: List of Status Changes that will end when the status activates and won't give its effect. (Optional)
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
Header:
|
Header:
|
||||||
Type: STATUS_DB
|
Type: STATUS_DB
|
||||||
Version: 1
|
Version: 2
|
||||||
|
|
||||||
Body:
|
Body:
|
||||||
- Status: Stone
|
- Status: Stone
|
||||||
DurationLookup: NPC_PETRIFYATTACK
|
DurationLookup: NPC_PETRIFYATTACK
|
||||||
States:
|
States:
|
||||||
NoMove: true
|
NoMove: true
|
||||||
NoMoveCond: true
|
|
||||||
NoCast: true
|
NoCast: true
|
||||||
NoAttack: true
|
NoAttack: true
|
||||||
CalcFlags:
|
CalcFlags:
|
||||||
Def_Ele: true
|
Def_Ele: true
|
||||||
Def: true
|
Def: true
|
||||||
Mdef: true
|
Mdef: true
|
||||||
|
Opt1: Stone
|
||||||
Flags:
|
Flags:
|
||||||
SendOption: true
|
SendOption: true
|
||||||
BossResist: true
|
BossResist: true
|
||||||
StopAttacking: true
|
StopAttacking: true
|
||||||
StopCasting: true
|
StopCasting: true
|
||||||
|
RemoveOnDamaged: true
|
||||||
Fail:
|
Fail:
|
||||||
Refresh: true
|
Refresh: true
|
||||||
Inspiration: true
|
Inspiration: true
|
||||||
Power_Of_Gaia: true
|
Power_Of_Gaia: true
|
||||||
Gvg_Stone: true
|
Gvg_Stone: true
|
||||||
|
Whiteimprison: true
|
||||||
|
Freeze: true
|
||||||
|
Stun: true
|
||||||
|
Sleep: true
|
||||||
|
Burning: true
|
||||||
|
#Undead: true
|
||||||
End:
|
End:
|
||||||
Dancing: true
|
Aeterna: true
|
||||||
|
EndReturn:
|
||||||
|
StoneWait: true
|
||||||
|
Stone: true
|
||||||
|
- Status: StoneWait
|
||||||
|
DurationLookup: NPC_PETRIFYATTACK
|
||||||
|
States:
|
||||||
|
NoCast: true
|
||||||
|
Opt1: StoneWait
|
||||||
|
Flags:
|
||||||
|
SendOption: true
|
||||||
|
StopAttacking: true
|
||||||
|
Fail:
|
||||||
|
Whiteimprison: true
|
||||||
|
Freeze: true
|
||||||
|
Stun: true
|
||||||
|
Sleep: true
|
||||||
|
Burning: true
|
||||||
|
#Undead: true
|
||||||
|
EndReturn:
|
||||||
|
StoneWait: true
|
||||||
|
Stone: true
|
||||||
- Status: Freeze
|
- Status: Freeze
|
||||||
DurationLookup: NPC_WIDEFREEZE
|
DurationLookup: NPC_WIDEFREEZE
|
||||||
States:
|
States:
|
||||||
@ -253,6 +281,11 @@ Body:
|
|||||||
BossResist: true
|
BossResist: true
|
||||||
Debuff: true
|
Debuff: true
|
||||||
NoSaveInfinite: true
|
NoSaveInfinite: true
|
||||||
|
End:
|
||||||
|
Freeze: true
|
||||||
|
Stone: true
|
||||||
|
Sleep: true
|
||||||
|
TrickDead: true
|
||||||
- Status: Endure
|
- Status: Endure
|
||||||
Icon: EFST_ENDURE
|
Icon: EFST_ENDURE
|
||||||
DurationLookup: SM_ENDURE
|
DurationLookup: SM_ENDURE
|
||||||
@ -515,6 +548,7 @@ Body:
|
|||||||
Flags:
|
Flags:
|
||||||
NoSave: true
|
NoSave: true
|
||||||
Fail:
|
Fail:
|
||||||
|
Stone: true
|
||||||
Freeze: true
|
Freeze: true
|
||||||
- Status: Adrenaline
|
- Status: Adrenaline
|
||||||
Icon: EFST_ADRENALINE
|
Icon: EFST_ADRENALINE
|
||||||
@ -1242,9 +1276,8 @@ Body:
|
|||||||
NoDispell: true
|
NoDispell: true
|
||||||
Fail:
|
Fail:
|
||||||
Quagmire: true
|
Quagmire: true
|
||||||
End:
|
EndReturn:
|
||||||
Decreaseagi: true
|
Decreaseagi: true
|
||||||
EndReturn: true
|
|
||||||
- Status: Chasewalk
|
- Status: Chasewalk
|
||||||
Icon: EFST_CHASEWALK
|
Icon: EFST_CHASEWALK
|
||||||
DurationLookup: ST_CHASEWALK
|
DurationLookup: ST_CHASEWALK
|
||||||
@ -1330,6 +1363,10 @@ Body:
|
|||||||
Flags:
|
Flags:
|
||||||
NoSave: true
|
NoSave: true
|
||||||
Debuff: true
|
Debuff: true
|
||||||
|
End:
|
||||||
|
Freeze: true
|
||||||
|
Stone: true
|
||||||
|
Sleep: true
|
||||||
- Status: Memorize
|
- Status: Memorize
|
||||||
Icon: EFST_MEMORIZE
|
Icon: EFST_MEMORIZE
|
||||||
DurationLookup: PF_MEMORIZE
|
DurationLookup: PF_MEMORIZE
|
||||||
@ -4323,9 +4360,8 @@ Body:
|
|||||||
Fail:
|
Fail:
|
||||||
Quagmire: true
|
Quagmire: true
|
||||||
Dontforgetme: true
|
Dontforgetme: true
|
||||||
End:
|
EndReturn:
|
||||||
Decreaseagi: true
|
Decreaseagi: true
|
||||||
EndReturn: true
|
|
||||||
- Status: Thornstrap
|
- Status: Thornstrap
|
||||||
Icon: EFST_THORNS_TRAP
|
Icon: EFST_THORNS_TRAP
|
||||||
DurationLookup: GN_THORNS_TRAP
|
DurationLookup: GN_THORNS_TRAP
|
||||||
@ -5931,9 +5967,8 @@ Body:
|
|||||||
NoBanishingBuster: true
|
NoBanishingBuster: true
|
||||||
NoClearance: true
|
NoClearance: true
|
||||||
NoForcedEnd: true
|
NoForcedEnd: true
|
||||||
End:
|
EndReturn:
|
||||||
All_Riding: true
|
All_Riding: true
|
||||||
EndReturn: true
|
|
||||||
- Status: Teargas_Sob
|
- Status: Teargas_Sob
|
||||||
Flags:
|
Flags:
|
||||||
BossResist: true
|
BossResist: true
|
||||||
|
@ -36,12 +36,12 @@
|
|||||||
# MinDuration Minimum duration in milliseconds after status change reduction. (Default: 1)
|
# MinDuration Minimum duration in milliseconds after status change reduction. (Default: 1)
|
||||||
# Fail: List of Status Changes that causes the status to fail to activate. (Optional)
|
# Fail: List of Status Changes that causes the status to fail to activate. (Optional)
|
||||||
# End: List of Status Changes that will end when the status activates. (Optional)
|
# End: List of Status Changes that will end when the status activates. (Optional)
|
||||||
# EndReturn If the status has an End list and succeeds to remove these status changes, it won't give its effect. (Default: false)
|
# EndReturn: List of Status Changes that will end when the status activates and won't give its effect. (Optional)
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
Header:
|
Header:
|
||||||
Type: STATUS_DB
|
Type: STATUS_DB
|
||||||
Version: 1
|
Version: 2
|
||||||
|
|
||||||
Footer:
|
Footer:
|
||||||
Imports:
|
Imports:
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
//===== By: ==================================================
|
//===== By: ==================================================
|
||||||
//= rAthena Dev Team
|
//= rAthena Dev Team
|
||||||
//===== Last Updated: ========================================
|
//===== Last Updated: ========================================
|
||||||
//= 20220222
|
//= 20220406
|
||||||
//===== Description: =========================================
|
//===== Description: =========================================
|
||||||
//= Explanation of the status.yml file and structure.
|
//= Explanation of the status.yml file and structure.
|
||||||
//============================================================
|
//============================================================
|
||||||
@ -270,7 +270,9 @@ End: List of status that will end if the status activates.
|
|||||||
|
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
EndReturn: If the status has any 'End' and succeeds to end other status in the list, it won't give its effect.
|
EndReturn: List of status that will end if the status activates and it won't give its effect.
|
||||||
|
The statuses checked in this list are done at the beginning of status_change_start(). If at least 1 status from this list
|
||||||
|
is removed then it will return back and not check anything else.
|
||||||
|
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
|
@ -940,7 +940,7 @@
|
|||||||
export_constant2("VAR_SHOES",LOOK_SHOES);
|
export_constant2("VAR_SHOES",LOOK_SHOES);
|
||||||
|
|
||||||
/* status changes */
|
/* status changes */
|
||||||
export_constant2("Eff_Stone",SC_STONE);
|
export_constant2("Eff_Stone",SC_STONEWAIT);
|
||||||
export_constant2("Eff_Freeze",SC_FREEZE);
|
export_constant2("Eff_Freeze",SC_FREEZE);
|
||||||
export_constant2("Eff_Stun",SC_STUN);
|
export_constant2("Eff_Stun",SC_STUN);
|
||||||
export_constant2("Eff_Sleep",SC_SLEEP);
|
export_constant2("Eff_Sleep",SC_SLEEP);
|
||||||
@ -972,6 +972,7 @@
|
|||||||
export_constant(SC_BLIND);
|
export_constant(SC_BLIND);
|
||||||
export_constant(SC_BLEEDING);
|
export_constant(SC_BLEEDING);
|
||||||
export_constant(SC_DPOISON);
|
export_constant(SC_DPOISON);
|
||||||
|
export_constant(SC_STONEWAIT);
|
||||||
export_constant(SC_PROVOKE);
|
export_constant(SC_PROVOKE);
|
||||||
export_constant(SC_ENDURE);
|
export_constant(SC_ENDURE);
|
||||||
export_constant(SC_TWOHANDQUICKEN);
|
export_constant(SC_TWOHANDQUICKEN);
|
||||||
|
@ -1622,7 +1622,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case NPC_PETRIFYATTACK:
|
case NPC_PETRIFYATTACK:
|
||||||
sc_start4(src,bl,SC_STONE,(20*skill_lv),skill_lv,0,0,skill_get_time(skill_id,skill_lv),skill_get_time2(skill_id,skill_lv));
|
sc_start4(src,bl,SC_STONEWAIT,(20*skill_lv),skill_lv,src->id,skill_get_time(skill_id,skill_lv),0,skill_get_time2(skill_id,skill_lv));
|
||||||
break;
|
break;
|
||||||
case NPC_CURSEATTACK:
|
case NPC_CURSEATTACK:
|
||||||
sc_start(src,bl,SC_CURSE,(20*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv));
|
sc_start(src,bl,SC_CURSE,(20*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv));
|
||||||
@ -7945,15 +7945,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|||||||
clif_skill_nodamage(src, bl, skill_id == SM_SELFPROVOKE ? SM_PROVOKE : skill_id, skill_lv, i);
|
clif_skill_nodamage(src, bl, skill_id == SM_SELFPROVOKE ? SM_PROVOKE : skill_id, skill_lv, i);
|
||||||
unit_skillcastcancel(bl, 2);
|
unit_skillcastcancel(bl, 2);
|
||||||
|
|
||||||
if( tsc && tsc->count )
|
|
||||||
{
|
|
||||||
status_change_end(bl, SC_FREEZE, INVALID_TIMER);
|
|
||||||
if( tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE )
|
|
||||||
status_change_end(bl, SC_STONE, INVALID_TIMER);
|
|
||||||
status_change_end(bl, SC_SLEEP, INVALID_TIMER);
|
|
||||||
status_change_end(bl, SC_TRICKDEAD, INVALID_TIMER);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( dstmd )
|
if( dstmd )
|
||||||
{
|
{
|
||||||
dstmd->state.provoke_flag = src->id;
|
dstmd->state.provoke_flag = src->id;
|
||||||
@ -8714,22 +8705,19 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|||||||
|
|
||||||
case MG_STONECURSE:
|
case MG_STONECURSE:
|
||||||
{
|
{
|
||||||
int brate = 0;
|
|
||||||
if (status_has_mode(tstatus,MD_STATUSIMMUNE)) {
|
if (status_has_mode(tstatus,MD_STATUSIMMUNE)) {
|
||||||
if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
if (sd)
|
||||||
|
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(status_isimmune(bl) || !tsc)
|
if(status_isimmune(bl) || !tsc)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
int32 brate = 0;
|
||||||
|
|
||||||
if (sd && sd->sc.data[SC_PETROLOGY_OPTION])
|
if (sd && sd->sc.data[SC_PETROLOGY_OPTION])
|
||||||
brate = sd->sc.data[SC_PETROLOGY_OPTION]->val3;
|
brate = sd->sc.data[SC_PETROLOGY_OPTION]->val3;
|
||||||
|
|
||||||
if (tsc && tsc->data[type]) {
|
|
||||||
status_change_end(bl, type, INVALID_TIMER);
|
|
||||||
if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (sc_start4(src,bl,type,(skill_lv*4+20)+brate,
|
if (sc_start4(src,bl,type,(skill_lv*4+20)+brate,
|
||||||
skill_lv, src->id, skill_get_time(skill_id, skill_lv), 0,
|
skill_lv, src->id, skill_get_time(skill_id, skill_lv), 0,
|
||||||
skill_get_time2(skill_id,skill_lv)))
|
skill_get_time2(skill_id,skill_lv)))
|
||||||
@ -9844,13 +9832,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|||||||
|
|
||||||
unit_skillcastcancel(bl,0);
|
unit_skillcastcancel(bl,0);
|
||||||
|
|
||||||
if(tsc && tsc->count){
|
|
||||||
status_change_end(bl, SC_FREEZE, INVALID_TIMER);
|
|
||||||
if(tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE)
|
|
||||||
status_change_end(bl, SC_STONE, INVALID_TIMER);
|
|
||||||
status_change_end(bl, SC_SLEEP, INVALID_TIMER);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dstmd)
|
if (dstmd)
|
||||||
mob_target(dstmd, src, skill_get_range2(src, skill_id, skill_lv, true));
|
mob_target(dstmd, src, skill_get_range2(src, skill_id, skill_lv, true));
|
||||||
}
|
}
|
||||||
@ -10333,8 +10314,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|||||||
case SC_BURNING:
|
case SC_BURNING:
|
||||||
sc_start4(src,bl,type,100,skill_lv,1000,src->id,0,skill_get_time2(skill_id,skill_lv));
|
sc_start4(src,bl,type,100,skill_lv,1000,src->id,0,skill_get_time2(skill_id,skill_lv));
|
||||||
break;
|
break;
|
||||||
case SC_VOICEOFSIREN:
|
case SC_STONEWAIT:
|
||||||
sc_start2(src,bl,type,100,skill_lv,src->id,skill_get_time2(skill_id,skill_lv));
|
sc_start4(src,bl,type,100,skill_lv,src->id,skill_get_time(skill_id, skill_lv), 0, skill_get_time2(skill_id,skill_lv));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_start2(src,bl,type,100,skill_lv,src->id,skill_get_time2(skill_id,skill_lv));
|
sc_start2(src,bl,type,100,skill_lv,src->id,skill_get_time2(skill_id,skill_lv));
|
||||||
@ -10784,22 +10765,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|||||||
if( bl->id == skill_area_temp[1] )
|
if( bl->id == skill_area_temp[1] )
|
||||||
break; // Already work on this target
|
break; // Already work on this target
|
||||||
|
|
||||||
if( tsc && tsc->data[type] )
|
status_change_start(src,bl,type,10000,skill_lv,src->id,skill_get_time(skill_id, skill_lv),0,skill_get_time2(skill_id,skill_lv), SCSTART_NOTICKDEF);
|
||||||
status_change_end(bl,type,INVALID_TIMER);
|
|
||||||
else
|
|
||||||
status_change_start(src,bl,type,10000,skill_lv,src->id,0,0,skill_get_time(skill_id, skill_lv),SCSTART_NOTICKDEF);
|
|
||||||
} else {
|
} else {
|
||||||
int rate = 45 + 5 * skill_lv + ( sd? sd->status.job_level : 50 ) / 4;
|
int rate = 45 + 5 * skill_lv + ( sd? sd->status.job_level : 50 ) / 4;
|
||||||
// IroWiki says Rate should be reduced by target stats, but currently unknown
|
// IroWiki says Rate should be reduced by target stats, but currently unknown
|
||||||
if( rnd()%100 < rate ) { // Success on First Target
|
if( rnd()%100 < rate ) { // Success on First Target
|
||||||
if( !tsc->data[type] )
|
if( status_change_start(src,bl,type,10000,skill_lv,src->id,skill_get_time(skill_id, skill_lv),0,skill_get_time2(skill_id,skill_lv), SCSTART_NOTICKDEF) ) {
|
||||||
rate = status_change_start(src,bl,type,10000,skill_lv,src->id,0,0,skill_get_time(skill_id, skill_lv),SCSTART_NOTICKDEF);
|
|
||||||
else {
|
|
||||||
rate = 1;
|
|
||||||
status_change_end(bl,type,INVALID_TIMER);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rate ) {
|
|
||||||
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
||||||
skill_area_temp[1] = bl->id;
|
skill_area_temp[1] = bl->id;
|
||||||
map_foreachinallrange(skill_area_sub,bl,skill_get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_nodamage_id);
|
map_foreachinallrange(skill_area_sub,bl,skill_get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_nodamage_id);
|
||||||
@ -15908,7 +15879,7 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, t_t
|
|||||||
case UNT_ZENKAI_LAND:
|
case UNT_ZENKAI_LAND:
|
||||||
switch (rnd()%2 + 1) {
|
switch (rnd()%2 + 1) {
|
||||||
case 1:
|
case 1:
|
||||||
sc_start2(ss, bl, SC_STONE, sg->val1*5, sg->skill_lv, ss->id, skill_get_time(sg->skill_id, sg->skill_lv));
|
sc_start4(ss, bl, SC_STONEWAIT, sg->val1*5, sg->skill_lv, ss->id, skill_get_time(sg->skill_id, sg->skill_lv), 0, skill_get_time2(sg->skill_id, sg->skill_lv));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
sc_start2(ss, bl, SC_POISON, sg->val1*5, sg->skill_lv, ss->id, skill_get_time(sg->skill_id, sg->skill_lv));
|
sc_start2(ss, bl, SC_POISON, sg->val1*5, sg->skill_lv, ss->id, skill_get_time(sg->skill_id, sg->skill_lv));
|
||||||
|
@ -1000,10 +1000,8 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
|
|||||||
for (const auto &it : status_db) {
|
for (const auto &it : status_db) {
|
||||||
sc_type type = static_cast<sc_type>(it.first);
|
sc_type type = static_cast<sc_type>(it.first);
|
||||||
|
|
||||||
if (it.second->flag[SCF_REMOVEONDAMAGED]) {
|
if (sc->data[type] && it.second->flag[SCF_REMOVEONDAMAGED])
|
||||||
if (type != SC_STONE || (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE))
|
status_change_end(target, type, INVALID_TIMER);
|
||||||
status_change_end(target, type, INVALID_TIMER);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ((sce=sc->data[SC_ENDURE]) && !sce->val4) {
|
if ((sce=sc->data[SC_ENDURE]) && !sce->val4) {
|
||||||
/** [Skotlex]
|
/** [Skotlex]
|
||||||
@ -1616,7 +1614,7 @@ bool status_check_skilluse(struct block_list *src, struct block_list *target, ui
|
|||||||
if((skill_id == WZ_STORMGUST || skill_id == WZ_FROSTNOVA || skill_id == NJ_HYOUSYOURAKU || skill_id == NPC_STORMGUST2)
|
if((skill_id == WZ_STORMGUST || skill_id == WZ_FROSTNOVA || skill_id == NJ_HYOUSYOURAKU || skill_id == NPC_STORMGUST2)
|
||||||
&& tsc->data[SC_FREEZE])
|
&& tsc->data[SC_FREEZE])
|
||||||
return false;
|
return false;
|
||||||
if(skill_id == PR_LEXAETERNA && (tsc->data[SC_FREEZE] || (tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE)))
|
if(skill_id == PR_LEXAETERNA && (tsc->data[SC_FREEZE] || tsc->data[SC_STONE]))
|
||||||
return false;
|
return false;
|
||||||
if (tsc->data[SC__MANHOLE] && !skill_get_inf2(skill_id, INF2_TARGETMANHOLE))
|
if (tsc->data[SC__MANHOLE] && !skill_get_inf2(skill_id, INF2_TARGETMANHOLE))
|
||||||
return false;
|
return false;
|
||||||
@ -4797,7 +4795,6 @@ void status_calc_state( struct block_list *bl, struct status_change *sc, std::bi
|
|||||||
(sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE
|
(sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE
|
||||||
))
|
))
|
||||||
|| (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB)
|
|| (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB)
|
||||||
|| (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
|
|
||||||
)
|
)
|
||||||
sc->cant.move += (start ? 1 : ((sc->cant.move) ? -1 : 0));
|
sc->cant.move += (start ? 1 : ((sc->cant.move) ? -1 : 0));
|
||||||
}
|
}
|
||||||
@ -6949,7 +6946,7 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc,
|
|||||||
def -= 20 + 10 * sc->data[SC_ANGRIFFS_MODUS]->val1;
|
def -= 20 + 10 * sc->data[SC_ANGRIFFS_MODUS]->val1;
|
||||||
if(sc->data[SC_STONEHARDSKIN])
|
if(sc->data[SC_STONEHARDSKIN])
|
||||||
def += sc->data[SC_STONEHARDSKIN]->val1;
|
def += sc->data[SC_STONEHARDSKIN]->val1;
|
||||||
if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
|
if(sc->data[SC_STONE])
|
||||||
def >>=1;
|
def >>=1;
|
||||||
if(sc->data[SC_FREEZE])
|
if(sc->data[SC_FREEZE])
|
||||||
def >>=1;
|
def >>=1;
|
||||||
@ -7113,7 +7110,7 @@ static defType status_calc_mdef(struct block_list *bl, struct status_change *sc,
|
|||||||
mdef += (sc->data[SC_ENDURE]->val4 == 0) ? sc->data[SC_ENDURE]->val1 : 1;
|
mdef += (sc->data[SC_ENDURE]->val4 == 0) ? sc->data[SC_ENDURE]->val1 : 1;
|
||||||
if(sc->data[SC_STONEHARDSKIN])
|
if(sc->data[SC_STONEHARDSKIN])
|
||||||
mdef += sc->data[SC_STONEHARDSKIN]->val1;
|
mdef += sc->data[SC_STONEHARDSKIN]->val1;
|
||||||
if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
|
if(sc->data[SC_STONE])
|
||||||
mdef += 25 * mdef / 100;
|
mdef += 25 * mdef / 100;
|
||||||
if(sc->data[SC_FREEZE])
|
if(sc->data[SC_FREEZE])
|
||||||
mdef += 25 * mdef / 100;
|
mdef += 25 * mdef / 100;
|
||||||
@ -7943,7 +7940,7 @@ static unsigned char status_calc_element(struct block_list *bl, struct status_ch
|
|||||||
|
|
||||||
if(sc->data[SC_FREEZE] || sc->data[SC_CRYSTAL_ARMOR_OPTION])
|
if(sc->data[SC_FREEZE] || sc->data[SC_CRYSTAL_ARMOR_OPTION])
|
||||||
return ELE_WATER;
|
return ELE_WATER;
|
||||||
if((sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) || sc->data[SC_STRONG_PROTECTION_OPTION])
|
if(sc->data[SC_STONE] || sc->data[SC_STRONG_PROTECTION_OPTION])
|
||||||
return ELE_EARTH;
|
return ELE_EARTH;
|
||||||
if(sc->data[SC_FLAMEARMOR_OPTION])
|
if(sc->data[SC_FLAMEARMOR_OPTION])
|
||||||
return ELE_FIRE;
|
return ELE_FIRE;
|
||||||
@ -7977,7 +7974,7 @@ static unsigned char status_calc_element_lv(struct block_list *bl, struct status
|
|||||||
|
|
||||||
if(sc->data[SC_FREEZE])
|
if(sc->data[SC_FREEZE])
|
||||||
return 1;
|
return 1;
|
||||||
if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
|
if(sc->data[SC_STONE])
|
||||||
return 1;
|
return 1;
|
||||||
if(sc->data[SC_BENEDICTIO])
|
if(sc->data[SC_BENEDICTIO])
|
||||||
return 1;
|
return 1;
|
||||||
@ -8730,7 +8727,7 @@ t_tick status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_
|
|||||||
sc = NULL;
|
sc = NULL;
|
||||||
|
|
||||||
#ifdef RENEWAL
|
#ifdef RENEWAL
|
||||||
uint16 levelAdv = (pow(max(0, status_get_lv(src) - status_get_lv(bl)), 2) / 5) * 100;
|
uint16 levelAdv = (static_cast<uint16>(pow(max(0, status_get_lv(src) - status_get_lv(bl)), 2)) / 5) * 100;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -9241,6 +9238,24 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
if(status->mode&MD_MVP && !(flag&SCSTART_NOAVOID) && scdb->flag[SCF_MVPRESIST])
|
if(status->mode&MD_MVP && !(flag&SCSTART_NOAVOID) && scdb->flag[SCF_MVPRESIST])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// End the SCs from the list and immediately return
|
||||||
|
// If anything in this list is removed, the rest is ignored.
|
||||||
|
if (!scdb->endreturn.empty()) {
|
||||||
|
bool isRemoved = false;
|
||||||
|
|
||||||
|
for (const auto &it : scdb->endreturn) {
|
||||||
|
sc_type rem_sc = it;
|
||||||
|
|
||||||
|
if (sc->data[rem_sc]) {
|
||||||
|
status_change_end(bl, rem_sc, INVALID_TIMER);
|
||||||
|
isRemoved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRemoved) // Something was removed, don't give the status
|
||||||
|
return 1; // Return 1 so that sc_start can be checked as success
|
||||||
|
}
|
||||||
|
|
||||||
// Check failing SCs from list
|
// Check failing SCs from list
|
||||||
if (!scdb->fail.empty()) {
|
if (!scdb->fail.empty()) {
|
||||||
for (const auto &it : scdb->fail) {
|
for (const auto &it : scdb->fail) {
|
||||||
@ -9288,10 +9303,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
if((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC)
|
if((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC)
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
case SC_AETERNA:
|
|
||||||
if( sc->data[SC_STONE] && sc->opt1 == OPT1_STONE )
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
case SC_KYRIE:
|
case SC_KYRIE:
|
||||||
case SC_TUNAPARTY:
|
case SC_TUNAPARTY:
|
||||||
if (bl->type == BL_MOB)
|
if (bl->type == BL_MOB)
|
||||||
@ -9611,14 +9622,45 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Before overlapping fail, one must check for status cured.
|
// Before overlapping fail, one must check for status cured.
|
||||||
|
std::vector<sc_type> endlist;
|
||||||
|
|
||||||
|
if (type == SC_BERSERK && val3 == SC__BLOODYLUST) //There is some reasons that using SC_BERSERK first before SC__BLOODYLUST itself on Akinari's fix
|
||||||
|
endlist = status_db.getEnd(SC__BLOODYLUST);
|
||||||
|
else
|
||||||
|
endlist = scdb->end;
|
||||||
|
|
||||||
|
// End the SCs from the list
|
||||||
|
if (!endlist.empty()) {
|
||||||
|
for (const auto &it : endlist) {
|
||||||
|
sc_type rem_sc = it;
|
||||||
|
|
||||||
|
if (sc->data[rem_sc]) {
|
||||||
|
switch (rem_sc) {
|
||||||
|
case SC_BERSERK:
|
||||||
|
case SC_SATURDAYNIGHTFEVER:
|
||||||
|
sc->data[rem_sc]->val2 = 0; // Mark to not lose hp
|
||||||
|
default:
|
||||||
|
status_change_end(bl, rem_sc, INVALID_TIMER);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// List of hardcoded status cured.
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case SC_STONE:
|
||||||
|
if (sc->data[SC_DANCING]) {
|
||||||
|
unit_stop_walking(bl, 1);
|
||||||
|
status_change_end(bl, SC_DANCING, INVALID_TIMER);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case SC_BLESSING:
|
case SC_BLESSING:
|
||||||
// !TODO: Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM
|
// !TODO: Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM
|
||||||
// !but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm]
|
// !but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm]
|
||||||
if ((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) {
|
if ((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) {
|
||||||
status_change_end(bl, SC_CURSE, INVALID_TIMER);
|
status_change_end(bl, SC_CURSE, INVALID_TIMER);
|
||||||
if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
|
status_change_end(bl, SC_STONE, INVALID_TIMER);
|
||||||
status_change_end(bl, SC_STONE, INVALID_TIMER);
|
|
||||||
if (sc->data[SC_CURSE]) {
|
if (sc->data[SC_CURSE]) {
|
||||||
status_change_end(bl, SC_CURSE, INVALID_TIMER);
|
status_change_end(bl, SC_CURSE, INVALID_TIMER);
|
||||||
return 1; // End Curse and do not give stat boost
|
return 1; // End Curse and do not give stat boost
|
||||||
@ -9659,36 +9701,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<sc_type> list;
|
|
||||||
|
|
||||||
if (type == SC_BERSERK && val3 == SC__BLOODYLUST) //There is some reasons that using SC_BERSERK first before SC__BLOODYLUST itself on Akinari's fix
|
|
||||||
list = status_db.getEnd(SC__BLOODYLUST);
|
|
||||||
else
|
|
||||||
list = scdb->end;
|
|
||||||
|
|
||||||
// End the SCs from the list
|
|
||||||
if (!list.empty()) {
|
|
||||||
bool isRemoving = false;
|
|
||||||
|
|
||||||
for (const auto &it : list) {
|
|
||||||
sc_type rem_sc = it;
|
|
||||||
|
|
||||||
if (sc->data[rem_sc]) {
|
|
||||||
switch (rem_sc) {
|
|
||||||
case SC_BERSERK:
|
|
||||||
case SC_SATURDAYNIGHTFEVER:
|
|
||||||
sc->data[rem_sc]->val2 = 0; // Mark to not lose hp
|
|
||||||
default:
|
|
||||||
status_change_end(bl, rem_sc, INVALID_TIMER);
|
|
||||||
isRemoving = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isRemoving && scdb->end_return)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for overlapping fails
|
// Check for overlapping fails
|
||||||
if( (sce = sc->data[type]) ) {
|
if( (sce = sc->data[type]) ) {
|
||||||
if (scdb->flag[SCF_OVERLAPFAIL])
|
if (scdb->flag[SCF_OVERLAPFAIL])
|
||||||
@ -10098,11 +10110,8 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SC_STONE:
|
case SC_STONEWAIT:
|
||||||
val3 = max(val3, 100); // Incubation time
|
val3 -= tick; // Petrify time - Incubation time
|
||||||
val4 = max(tick-val3, 100); // Petrify time
|
|
||||||
tick = val3;
|
|
||||||
calc_flag.reset(); // Actual status changes take effect on petrified state.
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SC_DPOISON:
|
case SC_DPOISON:
|
||||||
@ -10114,6 +10123,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
status_zap(bl, diff, 0);
|
status_zap(bl, diff, 0);
|
||||||
}
|
}
|
||||||
// Fall through
|
// Fall through
|
||||||
|
case SC_STONE:
|
||||||
case SC_POISON:
|
case SC_POISON:
|
||||||
case SC_BLEEDING:
|
case SC_BLEEDING:
|
||||||
case SC_BURNING:
|
case SC_BURNING:
|
||||||
@ -11887,7 +11897,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (calc_flag.none() && scdb->skill_id == 0 && scdb->icon == EFST_BLANK && scdb->opt1 == OPT1_NONE && scdb->opt2 == OPT2_NONE && scdb->state.none() && scdb->flag.none() && scdb->end.empty() && scdb->fail.empty()) {
|
if (calc_flag.none() && scdb->skill_id == 0 && scdb->icon == EFST_BLANK && scdb->opt1 == OPT1_NONE && scdb->opt2 == OPT2_NONE && scdb->state.none() && scdb->flag.none() && scdb->end.empty() && scdb->endreturn.empty() && scdb->fail.empty()) {
|
||||||
// Status change with no calc, no icon, and no skill associated...?
|
// Status change with no calc, no icon, and no skill associated...?
|
||||||
ShowWarning("status_change_start: Status %s (%d) is bare. Add the NoWarning flag to suppress this message.\n", script_get_constant_str("SC_", type), type);
|
ShowWarning("status_change_start: Status %s (%d) is bare. Add the NoWarning flag to suppress this message.\n", script_get_constant_str("SC_", type), type);
|
||||||
return 0;
|
return 0;
|
||||||
@ -11909,9 +11919,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
clif_changelook(bl,LOOK_BODY2,0);
|
clif_changelook(bl,LOOK_BODY2,0);
|
||||||
break;
|
break;
|
||||||
case SC_STONE:
|
case SC_STONE:
|
||||||
if (val3 > 0)
|
case SC_STONEWAIT:
|
||||||
break; //Incubation time still active
|
|
||||||
//Fall through
|
|
||||||
case SC_POISON:
|
case SC_POISON:
|
||||||
case SC_DPOISON:
|
case SC_DPOISON:
|
||||||
case SC_BLEEDING:
|
case SC_BLEEDING:
|
||||||
@ -12030,12 +12038,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
uint16 disable_opt_flag = false;
|
uint16 disable_opt_flag = false;
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case SC_STONE:
|
|
||||||
if (val3 > 0)
|
|
||||||
sc->opt1 = OPT1_STONEWAIT;
|
|
||||||
else
|
|
||||||
sc->opt1 = OPT1_STONE;
|
|
||||||
break;
|
|
||||||
case SC_DANCING:
|
case SC_DANCING:
|
||||||
if ((val1&0xFFFF) != CG_MOONLIT)
|
if ((val1&0xFFFF) != CG_MOONLIT)
|
||||||
sc->opt3 |= OPT3_MOONLIT;
|
sc->opt3 |= OPT3_MOONLIT;
|
||||||
@ -12129,8 +12131,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Non-zero
|
// Non-zero
|
||||||
// Calc state for SC_STONE when OPT1_STONE in the timer
|
if (sc_isnew && scdb->state.any())
|
||||||
if (sc_isnew && scdb->state.any() && type != SC_STONE)
|
|
||||||
status_calc_state(bl, sc, scdb->state, true);
|
status_calc_state(bl, sc, scdb->state, true);
|
||||||
|
|
||||||
if (sd) {
|
if (sd) {
|
||||||
@ -12385,6 +12386,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
|
|||||||
// delays status change ending so that a skill that sets opt1 fails to
|
// delays status change ending so that a skill that sets opt1 fails to
|
||||||
// trigger when it also removed one
|
// trigger when it also removed one
|
||||||
case SC_STONE:
|
case SC_STONE:
|
||||||
|
case SC_STONEWAIT:
|
||||||
sce->val4 = -1; // Petrify time
|
sce->val4 = -1; // Petrify time
|
||||||
case SC_FREEZE:
|
case SC_FREEZE:
|
||||||
case SC_STUN:
|
case SC_STUN:
|
||||||
@ -12952,9 +12954,6 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
|
|||||||
bool disable_opt_flag = false;
|
bool disable_opt_flag = false;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SC_STONE:
|
|
||||||
sc->opt1 = OPT1_NONE;
|
|
||||||
break;
|
|
||||||
case SC_DANCING:
|
case SC_DANCING:
|
||||||
if ((sce->val1&0xFFFF) == CG_MOONLIT)
|
if ((sce->val1&0xFFFF) == CG_MOONLIT)
|
||||||
sc->opt3 &= ~OPT3_MOONLIT;
|
sc->opt3 &= ~OPT3_MOONLIT;
|
||||||
@ -13031,6 +13030,10 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
|
|||||||
if(opt_flag[SCF_ONTOUCH] && sd && !sd->state.warping && map_getcell(bl->m,bl->x,bl->y,CELL_CHKNPC))
|
if(opt_flag[SCF_ONTOUCH] && sd && !sd->state.warping && map_getcell(bl->m,bl->x,bl->y,CELL_CHKNPC))
|
||||||
npc_touch_area_allnpc(sd,bl->m,bl->x,bl->y); // Trigger on-touch event.
|
npc_touch_area_allnpc(sd,bl->m,bl->x,bl->y); // Trigger on-touch event.
|
||||||
|
|
||||||
|
// Needed to be here to make sure OPT1_STONEWAIT has been cleared from the target
|
||||||
|
if (type == SC_STONEWAIT && sce->val4 > -1)
|
||||||
|
sc_start2(bl, bl, SC_STONE, 100, sce->val1, sce->val2, sce->val3);
|
||||||
|
|
||||||
ers_free(sc_data_ers, sce);
|
ers_free(sc_data_ers, sce);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -13140,28 +13143,8 @@ TIMER_FUNC(status_change_timer){
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SC_STONE:
|
case SC_STONE:
|
||||||
if (sc->opt1 == OPT1_STONEWAIT && sce->val4) {
|
if (sce->val4 >= 0 && status->hp > status->max_hp / 4)
|
||||||
sce->val3 = 0; //Incubation time used up
|
status_percent_damage(nullptr, bl, -1, 0, false);
|
||||||
unit_stop_attack(bl);
|
|
||||||
if (sc->data[SC_DANCING]) {
|
|
||||||
unit_stop_walking(bl, 1);
|
|
||||||
status_change_end(bl, SC_DANCING, INVALID_TIMER);
|
|
||||||
}
|
|
||||||
status_change_end(bl, SC_AETERNA, INVALID_TIMER);
|
|
||||||
sc->opt1 = OPT1_STONE;
|
|
||||||
|
|
||||||
std::shared_ptr<s_status_change_db> scdb = status_db.find(type);
|
|
||||||
|
|
||||||
status_calc_state(bl,sc,scdb->state,1);
|
|
||||||
clif_changeoption(bl);
|
|
||||||
sc_timer_next(min(sce->val4, interval) + tick);
|
|
||||||
sce->val4 -= interval; //Remaining time
|
|
||||||
status_calc_bl_(bl, scdb->calc_flag);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (sce->val4 >= 0 && !(sce->val3) && status->hp > status->max_hp / 4) {
|
|
||||||
status_percent_damage(NULL, bl, 1, 0, false);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SC_POISON:
|
case SC_POISON:
|
||||||
@ -15080,15 +15063,35 @@ uint64 StatusDatabase::parseBodyNode(const ryml::NodeRef& node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this->nodeExists(node, "EndReturn")) {
|
if (this->nodeExists(node, "EndReturn")) {
|
||||||
bool end;
|
const ryml::NodeRef &endNode = node["EndReturn"];
|
||||||
|
|
||||||
if (!this->asBool(node, "EndReturn", end))
|
for (const auto &it : endNode) {
|
||||||
return 0;
|
std::string end;
|
||||||
|
c4::from_chars(it.key(), &end);
|
||||||
|
|
||||||
status->end_return = end;
|
std::string end_constant = "SC_" + end;
|
||||||
} else {
|
int64 constant;
|
||||||
if (!exists)
|
|
||||||
status->end_return = false;
|
if (!script_get_constant(end_constant.c_str(), &constant)) {
|
||||||
|
this->invalidWarning(endNode, "EndReturn status %s is invalid.\n", end.c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->validateStatus(static_cast<sc_type>(constant))) {
|
||||||
|
this->invalidWarning(endNode, "EndReturn status %s is out of bounds.\n", end.c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool active;
|
||||||
|
|
||||||
|
if (!this->asBool(endNode, end, active))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (active)
|
||||||
|
status->endreturn.push_back(static_cast<sc_type>(constant));
|
||||||
|
else
|
||||||
|
util::vector_erase_if_exists(status->endreturn, static_cast<sc_type>(constant));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
|
@ -150,7 +150,7 @@ enum sc_type : int16 {
|
|||||||
|
|
||||||
//First we enumerate common status ailments which are often used around.
|
//First we enumerate common status ailments which are often used around.
|
||||||
SC_STONE = 0,
|
SC_STONE = 0,
|
||||||
SC_COMMON_MIN = 0, // begin
|
SC_COMMON_MIN = SC_STONE, // begin
|
||||||
SC_FREEZE,
|
SC_FREEZE,
|
||||||
SC_STUN,
|
SC_STUN,
|
||||||
SC_SLEEP,
|
SC_SLEEP,
|
||||||
@ -161,7 +161,8 @@ enum sc_type : int16 {
|
|||||||
SC_BLIND,
|
SC_BLIND,
|
||||||
SC_BLEEDING,
|
SC_BLEEDING,
|
||||||
SC_DPOISON, //10
|
SC_DPOISON, //10
|
||||||
SC_COMMON_MAX = 10, // end
|
SC_STONEWAIT,
|
||||||
|
SC_COMMON_MAX = SC_STONEWAIT, // end
|
||||||
|
|
||||||
//Next up, we continue on 20, to leave enough room for additional "common" ailments in the future.
|
//Next up, we continue on 20, to leave enough room for additional "common" ailments in the future.
|
||||||
SC_PROVOKE = 20,
|
SC_PROVOKE = 20,
|
||||||
@ -2870,14 +2871,14 @@ struct s_status_change_db {
|
|||||||
uint16 skill_id; ///< Associated skill for (addeff) duration lookups
|
uint16 skill_id; ///< Associated skill for (addeff) duration lookups
|
||||||
std::vector<sc_type> end; ///< List of SC that will be ended when this SC is activated
|
std::vector<sc_type> end; ///< List of SC that will be ended when this SC is activated
|
||||||
std::vector<sc_type> fail; ///< List of SC that causing this SC cannot be activated
|
std::vector<sc_type> fail; ///< List of SC that causing this SC cannot be activated
|
||||||
bool end_return; ///< After SC ends the SC from end list, it does nothing
|
std::vector<sc_type> endreturn; ///< List of SC that will be ended when this SC is activated and then immediately return
|
||||||
t_tick min_duration; ///< Minimum duration effect (after all status reduction)
|
t_tick min_duration; ///< Minimum duration effect (after all status reduction)
|
||||||
uint16 min_rate; ///< Minimum rate to be applied (after all status reduction)
|
uint16 min_rate; ///< Minimum rate to be applied (after all status reduction)
|
||||||
};
|
};
|
||||||
|
|
||||||
class StatusDatabase : public TypesafeCachedYamlDatabase<uint16, s_status_change_db> {
|
class StatusDatabase : public TypesafeCachedYamlDatabase<uint16, s_status_change_db> {
|
||||||
public:
|
public:
|
||||||
StatusDatabase() : TypesafeCachedYamlDatabase("STATUS_DB", 1) {
|
StatusDatabase() : TypesafeCachedYamlDatabase("STATUS_DB", 2) {
|
||||||
// All except BASE and extra flags.
|
// All except BASE and extra flags.
|
||||||
SCB_BATTLE.set();
|
SCB_BATTLE.set();
|
||||||
SCB_BATTLE.reset(SCB_BASE);
|
SCB_BATTLE.reset(SCB_BASE);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user