Implementation of Status Changes in YAML (#1685)
* Removes the initialization of Status Changes via hard-code and puts it into YAML form. * From this database it is much easier to delegate icons, calc flags, opt flags, miscellaneous flags, and several other things for all stats changes. * Statuses can quickly be reloaded via atcommand reloadstatus. Thanks to @cydh, @Atemo, @Lemongrass3110, and the others who helped! Signed-off-by: Cydh Ramdh <cydh@pservero.com> Co-authored-by: atemo <capucrath@gmail.com> Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
This commit is contained in:
parent
e74bbfd37e
commit
f28d207274
@ -220,9 +220,6 @@ backstab_bow_penalty: yes
|
||||
// Use 0 to disable (max allowed value is 255)
|
||||
skill_steal_max_tries: 0
|
||||
|
||||
// Does Berserk/Frenzy cancel other self-buffs when used?
|
||||
berserk_cancels_buffs: no
|
||||
|
||||
// Level and Strength of "MVP heal". When someone casts a heal of this level or
|
||||
// above, the heal formula is bypassed and this value is used instead.
|
||||
max_heal: 9999
|
||||
|
@ -13,13 +13,11 @@
|
||||
status_cast_cancel: 0
|
||||
|
||||
// Will certain skill status-changes be removed on logout?
|
||||
// This mimics official servers, where Extremity Fist's no SP regen,
|
||||
// Strip Equipment, and some other buffs are removed when you logout. Setting is:
|
||||
// 0 = remove nothing.
|
||||
// 1 = remove negative buffs (stripping, EF)
|
||||
// 2 = remove positive buffs (maximize power, steel body...)
|
||||
// 3 = remove both negative and positive buffs.
|
||||
debuff_on_logout: 3
|
||||
// 0 = (Default) Only remove status that has the SCF_NO_SAVE flag.
|
||||
// 1 = Remove negative buffs (status that are flagged as debuff)
|
||||
// 2 = Remove positive buffs.
|
||||
// 3 = Remove all.
|
||||
debuff_on_logout: 0
|
||||
|
||||
// Adjustment for the natural rate of resistance from status changes.
|
||||
// If 50, status defense is halved, and you need twice as much stats to block
|
||||
|
@ -135,6 +135,7 @@
|
||||
# Interval Skill unit interval in milliseconds. (Default: 0)
|
||||
# Target Skill unit target type. (Default: All)
|
||||
# Flag: Skill unit flags. (Default: None)
|
||||
# Status Status Change that is associated to the skill. (Optional)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
|
44
db/import-tmpl/status.yml
Normal file
44
db/import-tmpl/status.yml
Normal file
@ -0,0 +1,44 @@
|
||||
# This file is a part of rAthena.
|
||||
# Copyright(C) 2022 rAthena Development Team
|
||||
# https://rathena.org - https://github.com/rathena
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Status Change Database
|
||||
###########################################################################
|
||||
#
|
||||
# Status Change Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Status Status change name.
|
||||
# Icon Status change icon. (Default: EFST_BLANK)
|
||||
# DurationLookup Default status change duration. (Default: 0)
|
||||
# States: Status change state to determine player states. (Default: None)
|
||||
# CalcFlags: Status change calculation to indicate which stat is adjusted. (Default: None)
|
||||
# Opt1 Special effect when a status change is active. Non-stackable. (Default: None)
|
||||
# Opt2: Special options/client effects when a status change is active. (Default: None)
|
||||
# Opt3: Special options/client effects when a status change is active. (Default: Normal)
|
||||
# Options: Special options/client effects when a status change is active. (Default: Nothing)
|
||||
# Flags: Special flags which trigger during certain events. (Default: None)
|
||||
# MinRate Minimum rate after status change reduction (10000 = 100%). (Default: 0)
|
||||
# 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)
|
||||
# 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)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: STATUS_DB
|
||||
Version: 1
|
File diff suppressed because it is too large
Load Diff
6817
db/pre-re/status.yml
Normal file
6817
db/pre-re/status.yml
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
7946
db/re/status.yml
Normal file
7946
db/re/status.yml
Normal file
File diff suppressed because it is too large
Load Diff
@ -135,6 +135,7 @@
|
||||
# Interval Skill unit interval in milliseconds. (Default: 0)
|
||||
# Target Skill unit target type. (Default: All)
|
||||
# Flag: Skill unit flags. (Default: None)
|
||||
# Status Status Change that is associated to the skill. (Optional)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
|
52
db/status.yml
Normal file
52
db/status.yml
Normal file
@ -0,0 +1,52 @@
|
||||
# This file is a part of rAthena.
|
||||
# Copyright(C) 2022 rAthena Development Team
|
||||
# https://rathena.org - https://github.com/rathena
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Status Change Database
|
||||
###########################################################################
|
||||
#
|
||||
# Status Change Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Status Status change name.
|
||||
# Icon Status change icon. (Default: EFST_BLANK)
|
||||
# DurationLookup Default status change duration. (Default: 0)
|
||||
# States: Status change state to determine player states. (Default: None)
|
||||
# CalcFlags: Status change calculation to indicate which stat is adjusted. (Default: None)
|
||||
# Opt1 Special effect when a status change is active. Non-stackable. (Default: None)
|
||||
# Opt2: Special options/client effects when a status change is active. (Default: None)
|
||||
# Opt3: Special options/client effects when a status change is active. (Default: Normal)
|
||||
# Options: Special options/client effects when a status change is active. (Default: Nothing)
|
||||
# Flags: Special flags which trigger during certain events. (Default: None)
|
||||
# MinRate Minimum rate after status change reduction (10000 = 100%). (Default: 0)
|
||||
# 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)
|
||||
# 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)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: STATUS_DB
|
||||
Version: 1
|
||||
|
||||
Footer:
|
||||
Imports:
|
||||
- Path: db/pre-re/status.yml
|
||||
Mode: Prerenewal
|
||||
- Path: db/re/status.yml
|
||||
Mode: Renewal
|
||||
- Path: db/import/status.yml
|
@ -925,3 +925,7 @@ CrazyWeedImmune - Immune to GN_CRAZYWEED.
|
||||
RemovedByFireRain - Removed by RL_FIRE_RAIN.
|
||||
KnockbackGroup - Knock back a whole skill group (by default, skill unit is knocked back by each unit).
|
||||
HiddenTrap - Hidden trap. See battle_config::traps_setting to enable this flag.
|
||||
|
||||
------------------
|
||||
|
||||
Status: Status Change that is associated to the skill. The status is used in association with the status.yml database.
|
||||
|
297
doc/status.txt
Normal file
297
doc/status.txt
Normal file
@ -0,0 +1,297 @@
|
||||
//===== rAthena Documentation ================================
|
||||
//= Status Change Database Structure
|
||||
//===== By: ==================================================
|
||||
//= rAthena Dev Team
|
||||
//===== Last Updated: ========================================
|
||||
//= 20220222
|
||||
//===== Description: =========================================
|
||||
//= Explanation of the status.yml file and structure.
|
||||
//============================================================
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Status: Status change name.
|
||||
|
||||
See src/map/script_constants.hpp for SC_ constants.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Icon: Status change icon or client effect that will be displayed client-side.
|
||||
|
||||
See src/map/script_constants.hpp for EFST_ constants.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
DurationLookup: Used for default duration lookup in skill_db.yml. The lookup is used for some item bonuses as default duration.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
States: Specified states given when the SC is active.
|
||||
|
||||
None - No special state. (Default)
|
||||
NoMove - Cannot move.
|
||||
NoMoveCond - Condition check for SCS_NOMOVE.
|
||||
NoPickItem - Cannot pick item.
|
||||
NoPickItemCond - Condition check for SCS_NOPICKITEM.
|
||||
NoDropItem - Cannot drop item.
|
||||
NoDropItemCond - Condition check for SCS_NODROPITEM.
|
||||
NoCast - Cannot cast a skill.
|
||||
NoCastCond - Condition check for SCS_NOCAST.
|
||||
NoChat - Cannot chat and open chat room.
|
||||
NoChatCond - Condition check for SCS_NOCHATCOND.
|
||||
NoEquipItem - Cannot put on equipment.
|
||||
NoEquipItemCond - Condition check for SCS_NOEQUIPITEM.
|
||||
NoUnEquipItem - Cannot put off equipment.
|
||||
NoUnEquipItemCond - Condition check for SCS_NOUNEQUIPITEM.
|
||||
NoConsumeItem - Cannot consume item.
|
||||
NoConsumeItemCond - Condition check for SCS_NOCONSUMEITEM.
|
||||
NoAttack - Cannot attack.
|
||||
NoAttackCond - Condition check for SCS_NOATTACK.
|
||||
NoWarp - Cannot warp.
|
||||
NoWarpCond - Condition check for SCS_NOWARP.
|
||||
NoDeathPenalty - Cannot lose experience on death.
|
||||
NoDeathPenaltyCond - Condition check for SCS_NODEATHPENALTY.
|
||||
NoInteract - Cannot interact with client (sit/stand or talk with NPC).
|
||||
NoInteractCond - Condition check for SCS_NOINTERACT.
|
||||
|
||||
States that have a suffix of "Cond" means the State has hard coded conditions in status.cpp::status_calc_state
|
||||
|
||||
---------------------------------------
|
||||
|
||||
CalcFlags: Flag that indicates which status calculation needs to be performed. Even if the value is changed in the status_db.yml the SC must have the respective bonus defined in source.
|
||||
|
||||
None - Calculates nothing. (Default)
|
||||
Base - Base status
|
||||
MaxHp - Maximum HP
|
||||
MaxSp - Maximum SP
|
||||
Str - STR
|
||||
Agi - AGI
|
||||
Vit - VIT
|
||||
Int - INT
|
||||
Dex - DEX
|
||||
Luk - LUK
|
||||
Batk - Base Attack
|
||||
Watk - Weapon Attack
|
||||
Matk - Magic Attack
|
||||
Hit - Hit/accuracy rate
|
||||
Flee - Flee/dodge rate
|
||||
Def - Equipment Defense
|
||||
Def2 - Defense
|
||||
Mdef - Equipment Magic Defense
|
||||
Mdef2 - Magic Defense
|
||||
Speed - Walk speed
|
||||
Aspd - Attack speed
|
||||
Dspd - Damage delay speed
|
||||
Cri - Critical rate
|
||||
Flee2 - Perfect dodge rate
|
||||
Atk_Ele - Attack Element
|
||||
Def_Ele - Defense Element
|
||||
Mode - Mode
|
||||
Size - Size
|
||||
Race - Race
|
||||
Range - Range
|
||||
Regen - Regeneration
|
||||
MaxAp - Maximum AP
|
||||
Pow - POW
|
||||
Sta - STA
|
||||
Wis - WIS
|
||||
Spl - SPL
|
||||
Con - CON
|
||||
Crt - CRT
|
||||
Patk - Physical Power
|
||||
Smatk - Spell Magic Attack
|
||||
Res - Physical Resistance
|
||||
Mres - Magic Resistance
|
||||
Hplus - Heal Plus
|
||||
Crate - Critical Rate
|
||||
Dye - Dye
|
||||
All - Calculates all CalcFlags
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Opt1: Special effect when status is active (Aegis: BODYSTATE_*). This option is not stackable. These effects also apply their special behaviors.
|
||||
|
||||
None - No effect (Default)
|
||||
Stone - Stone curse effect
|
||||
Freeze - Freeze effect
|
||||
Stun - Stun effect
|
||||
Sleep - Sleep effect
|
||||
StoneWait - Effect before Stone is really applied
|
||||
Burning - Burning effect
|
||||
Imprison - Imprison effect
|
||||
Crystalize - Crystalize effect
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Opt2: Special option/client effect when status is active (Aegis: HEALTHSTATE_*).
|
||||
|
||||
None - No effect (Default)
|
||||
Poison - Posioned effect
|
||||
Curse - Cursed effect
|
||||
Silence - Silenced effect
|
||||
SignumCrucis - Signum Crucis effect
|
||||
Blind - Blind effect
|
||||
Angelus - Angelus effect
|
||||
Bleeding - Bleeding effect
|
||||
Dpoison - Heavy Poisoned effect
|
||||
Fear - Fear effect
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Opt3: Special option/client effect when status is active (Aegis: SHOW_EFST_*)
|
||||
|
||||
Normal - No effect (Default)
|
||||
Quicken - Quicken effect
|
||||
OverThrust - Overthrust effect
|
||||
EnergyCoat - Energy Coat effect
|
||||
ExplosionSpirits - Explosion Spirits effect
|
||||
SteelBody - Steel Body effect
|
||||
BladeStop - Blade Stop effect
|
||||
AuraBlade - Aura Blade effect
|
||||
Berserk - Berserk effect
|
||||
LightBlade - Light Blade effect
|
||||
Moonlit - Moonlit effect
|
||||
Marionette - Marionette effect
|
||||
Assumptio - Assumptio effect
|
||||
Warm - Warm effect
|
||||
Kaite - Kaite effect
|
||||
Bunsin - Bunshin effect
|
||||
SoulLink - Soul Link effect
|
||||
Undead - Undead effect
|
||||
Contract - Contract effect
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Options: Special option/client effect state when status is active.
|
||||
|
||||
Nothing - No effect (Default)
|
||||
Sight - Sight effect
|
||||
Hide - Hide effect
|
||||
Cloak - Cloaking effect
|
||||
Falcon - Falcon effect
|
||||
Riding - Riding effect
|
||||
Invisible - Invisible effect
|
||||
Orcish - Orcish effect, the ugly face!
|
||||
Wedding - Wedding costume
|
||||
Ruwach - Ruwach effect
|
||||
ChaseWalk - Chasewalk effect
|
||||
Flying - Flying effect (Star Gladiator's Union)
|
||||
Xmas - Christmas costume
|
||||
Transform - Transformation
|
||||
Summer - Summer costume
|
||||
Dragon1 - Dragon
|
||||
Dragon2 - Dragon
|
||||
Dragon3 - Dragon
|
||||
Dragon4 - Dragon
|
||||
Dragon5 - Dragon
|
||||
Wug - Wug
|
||||
WugRider - Riding a Wug
|
||||
Madogear - Madogear
|
||||
Hanbok - Hanbok costume
|
||||
Oktoberfest - Oktoberfest costume
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Flags: Various status flags for specific status change events.
|
||||
|
||||
None - No special flag. (Default)
|
||||
BlEffect - Status should have BL_SCEFFECT as relevant effect, must have an EFST (displays on BL_PC, BL_HOM, BL_MER, BL_MOB, BL_ELEM). BL_PC is the default value.
|
||||
DisplayPc - Displays status effect when player logs in.
|
||||
DislpayNpc - Displays status effect on a NPC.
|
||||
Debuff - Status is considered a debuff. Used in combination with 'battle_config.debuff_on_logout'.
|
||||
SetStand - Sets player to standing state.
|
||||
OverlapFail - The status will fail to activate if the status is already active.
|
||||
OverlapIgnoreLevel - The status will successfully activate for any level if the status is already active.
|
||||
FailedMado - Cannot be applied if Madogear is active.
|
||||
MadoCancel - Cancels the status when mounting Madogear.
|
||||
MadoEndCancel - Cancels the status when unmounting Madogear.
|
||||
MobLoseTarget - When active on a monster it will lose the target.
|
||||
RestartOnMapWarp - Restarts the timer of a status when warping to another map.
|
||||
SpreadEffect - Passes the status onto a target when SC_DEADLYINFECT is active.
|
||||
SendVal1 - Notifies the client of a status change (val1).
|
||||
SendVal2 - Notifies the client of a status change (val2).
|
||||
SendVal3 - Notifies the client of a status change (val3).
|
||||
|
||||
NoClearbuff - Cannot be removed by 'status_change_clear_buffs()', 'sc_end SC_ALL', 'status_change_clear(3)', etc.
|
||||
NoRemoveOnDead - Cannot be removed when a player dies.
|
||||
NoDispell - Cannot be removed by SA_DISPELL.
|
||||
NoClearance - Cannot be removed by AB_CLEARANCE.
|
||||
NoBanishingBuster - Cannot be removed by RL_BANISHING_BUSTER.
|
||||
NoSave - Won't be saved when player logs out.
|
||||
NoSaveInfinite - Infinite duration status won't be saved when player logs out.
|
||||
|
||||
RemoveOnDamaged - Removed when receiving damage.
|
||||
RemoveOnRefresh - Removed by RK_REFRESH.
|
||||
RemoveOnLuxAnima - Removed by RK_LUXANIMA.
|
||||
RemoveOnMapWarp - Removed when warping to another map.
|
||||
RemoveOnChangeMap - Removed when changing map-server.
|
||||
RemoveChemicalProtect - Removed by AM_CP_ARMOR/AM_CP_HELM/AM_CP_SHIELD/AM_CP_WEAPON.
|
||||
RemoveElementalOption - Removed by elemental changing modes/quitting/EL_TIDAL_WEAPON/EL_WATER_SCREEN on the master and elemental.
|
||||
|
||||
StopAttacking - Makes the unit stop attacking.
|
||||
StopCasting - Makes the unit stop casting skills.
|
||||
StopWalking - Makes the unit stop walking.
|
||||
|
||||
BossResist - Cannot be applied to Boss Monster (Mob has mode MD_STATUS_IMMUNE).
|
||||
MvpResist - Cannot be applied to MvP (Mob has mode MD_MVP).
|
||||
|
||||
SendOption - Sends the STATE_CHANGE packet. For statuses that have Opt1, Opt2, or Opt3 values.
|
||||
SendLook - Sends the STATE_CHANGE packet. For statuses that have body/look changes through 'Option' flags (only for players).
|
||||
OnTouch - Triggers OnTouch_ NPC events. For statuses that have an invisible effect.
|
||||
UnitMove - Triggers when the player has moved location and invokes the skill unit on place.
|
||||
NonPlayer - Sends the NPC_SHOWEFST_UPDATE packet. Used to send effects to NPC/monsters.
|
||||
|
||||
RequireWeapon - Status requires a weapon to be equipped.
|
||||
RequireShield - Status requires a shield to be equipped.
|
||||
|
||||
SuperNoviceAngel - Status that is given from Super Novice Angel.
|
||||
TaekwonAngel - Status that is given from Taekwon Angel.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
MinDuration: Minimum duration, in milliseconds, after reduction calculation for status resistance.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
MinRate: Minimum success rate, at n/10000, after reduction calculation for status resistance.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Fail: List of status that causes the status to fail to activate.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Notes:
|
||||
|
||||
By default, statuses are 'Buff' (those that aren't explicitely given the 'Debuff' flag) which are removable by 'map_quit' in combination with 'battle_config.debuff_on_logout'.
|
||||
|
||||
The NoClearbuff flag prevents some permanent and non-permanent statuses that cannot be removed by 'status_change_clear', 'status_change_clear_buffs', 'map_quit', or other
|
||||
clearing means.
|
||||
The function 'status_change_clear_buffs' is called by CG_TAROTCARD, RK_REFRESH, RK_LUXANIMA, CG_HERMODE, PA_GOSPEL, and LG_INSPIRATION.
|
||||
|
||||
CG_TAROTCARD and CG_HERMODE only remove buffs while PA_GOSPEL and LG_INSPIRATION remove buffs and debuffs.
|
||||
|
||||
RK_REFRESH and RK_LUXANIMA only remove statuses that have the Rem_On_Rerfresh or RemoveOnLuxAnima flag. Works just like SA_DISPELL, AB_CLEARANCE, RL_BANISHING_BUSTER that has the
|
||||
effect to remove buffs or debuffs.
|
||||
|
||||
---- Removed comments from source ----
|
||||
- Mado is immune to increase agi, wind walk, cart boost, etc (others above) [Ind]
|
||||
- Cart Boost cannot be affected by Slow grace. Assumed if player got Slow Grace first, Cart Boost is failed since Cart Boost doesn't cancel Slow Grace effect
|
||||
http://irowiki.org/wiki/Cart_Boost_%28Genetic%29 (view date: 2014-01-26)
|
||||
http://irowiki.org/wiki/Cart_Boost (view date: 2014-01-26)
|
||||
- kRO Update 2014-02-12: Cannot be stacked with Platinum Alter and Madness Canceler (and otherwise?) [Cydh]
|
||||
- SC_BERSERK, SC_SATURDAYNIGHTFEVER, and SC__BLOODYLUST are all like berserk, do not everlap each other.
|
||||
- SC_STONE, SC_FREEZE, SC_DEEPSLEEP, SC_SLEEP, SC_STUN, SC_FREEZING, and SC_CRYSTALIZE cannot override other opt1 status changes. [Skotlex]
|
||||
TODO: SC that has OPT1: SC_STONE, SC_FREEZE, SC_STUN, SC_SLEEP, SC_BURNING, SC_WHITEIMPRISON, SC_CRYSTALIZE
|
||||
- Immune to Frozen and Freezing status if under Warmer status. [Jobbie]
|
||||
- SC_ONEHAND removes the Aspd potion effect, as reported by Vicious. [Skotlex]
|
||||
- SC_ALL_RIDING. Already mounted, just dismount.
|
||||
- SC_GN_CARTBOOST andSC_CARTBOOST cancel Decrease Agi, but take no further effect [Skotlex]
|
@ -45,7 +45,7 @@ SC_POISON ()
|
||||
desc: DEF -25%; if HP>25% lose 1.5% + 2 HP/sec; SP Regeneration is disabled
|
||||
val1: Skill Level
|
||||
val2: Caster's object ID
|
||||
val3:
|
||||
val3:
|
||||
val4: Remaining tick
|
||||
|
||||
SC_CURSE ()
|
||||
@ -75,7 +75,7 @@ SC_DPOISON ()
|
||||
desc: DEF -25%; if HP>25% lose 10/15% HP/sec
|
||||
val1: Skill Level
|
||||
val2: Caster's object ID (for mob_log_damage)
|
||||
val3:
|
||||
val3:
|
||||
val4: Remaining tick
|
||||
|
||||
SC_PROVOKE (EFST_PROVOKE)
|
||||
@ -1760,7 +1760,7 @@ SC_RAISINGDRAGON ()
|
||||
val1:
|
||||
|
||||
SC_GT_ENERGYGAIN (EFST_GENTLETOUCH_ENERGYGAIN)
|
||||
desc:
|
||||
desc:
|
||||
val1: SR_GENTLETOUCH_ENERGYGAIN Skill Level
|
||||
val2: Sphere Gain Chance
|
||||
|
||||
@ -2368,7 +2368,7 @@ SC_REBOUND (EFST_REBOUND)
|
||||
val1:
|
||||
|
||||
SC_UNLIMIT (EFST_UNLIMIT)
|
||||
desc: Increase attak rate & set Def/MDef to 1,
|
||||
desc: Increase attak rate & set Def/MDef to 1,
|
||||
val1:
|
||||
val2: +% Attack
|
||||
|
||||
@ -2710,13 +2710,81 @@ SC_LHZ_DUN_N4 (EFST_LHZ_DUN_N4)
|
||||
desc: Increases and reduces damage against MVPs of Biolab 5.
|
||||
val1: +% Damage
|
||||
val2: +% Defense
|
||||
|
||||
|
||||
SC_DORAM_BUF_01 ()
|
||||
desc: Recovers 10 HP every 10 seconds.
|
||||
|
||||
|
||||
SC_DORAM_BUF_02 ()
|
||||
desc: Recovers 5 SP every 10 seconds.
|
||||
|
||||
SC_INCREASE_MAXHP (EFST_ATKER_ASPD)
|
||||
desc: Increases MaxHP. Increases natural HP regeneration.
|
||||
val1: + HP
|
||||
val2: +% HP regeneration
|
||||
|
||||
SC_INCREASE_MAXSP (EFST_ATKER_MOVESPEED)
|
||||
desc: Increases MaxSP. Increases natural SP regeneration.
|
||||
val1: + SP
|
||||
val2: +% SP regeneration
|
||||
|
||||
SC_REF_T_POTION (EFST_REF_T_POTION)
|
||||
desc: Decreases reflected damage by 100%.
|
||||
|
||||
SC_ADD_ATK_DAMAGE (EFST_ADD_ATK_DAMAGE)
|
||||
desc: Increases melee physical damage by 15%. Increases ranged physical damage by 15%.
|
||||
val1:
|
||||
|
||||
SC_ADD_MATK_DAMAGE (EFST_ADD_MATK_DAMAGE)
|
||||
desc: Increases all elemental magical damage by 15%.
|
||||
|
||||
SC_HELPANGEL (EFST_HELPANGEL)
|
||||
desc: Recover 1000 HP every second. Recover 350 SP every second.
|
||||
val1:
|
||||
val2:
|
||||
val3:
|
||||
val4: Tick time (milliseconds)
|
||||
|
||||
SC_SOUNDOFDESTRUCTION (EFST_SOUND_OF_DESTRUCTION)
|
||||
desc: Doubles incoming damage for 10 seconds.
|
||||
|
||||
SC_LUXANIMA (EFST_LUXANIMA)
|
||||
desc: Physical attacks has the chance to activate Storm Blast Level 1. Increases physical damage against all sizes.
|
||||
Increases Critical Damage. Increases Melee and Ranged Physical Damage.
|
||||
val1:
|
||||
val2: Storm Blast success 15% (hardcoded)
|
||||
val3: Damage/HP/SP 30% increase (hardcoded)
|
||||
|
||||
SC_REUSE_LIMIT_LUXANIMA ()
|
||||
desc:
|
||||
val1:
|
||||
|
||||
SC_ENSEMBLEFATIGUE (EFST_ENSEMBLEFATIGUE)
|
||||
desc: Disables skill use. Movement and attack speed reduced by 30%.
|
||||
val1:
|
||||
val2: + 30 Speed and ASPD rates penalty (hardcoded)
|
||||
|
||||
SC_MISTY_FROST (EFST_MISTY_FROST)
|
||||
desc: Freezing.
|
||||
|
||||
SC_MAGIC_POISON (EFST_MAGIC_POISON)
|
||||
desc: Decreases resistance against all elemental attacks by 50%.
|
||||
val1:
|
||||
val2: Attribute Reduction (50, hardcoded).
|
||||
|
||||
SC_EP16_2_BUFF_SS (EFST_EP16_2_BUFF_SS)
|
||||
desc: ASPD +10.
|
||||
|
||||
SC_EP16_2_BUFF_SC (EFST_EP16_2_BUFF_SC)
|
||||
desc: CRIT +30.
|
||||
|
||||
SC_EP16_2_BUFF_AC (EFST_EP16_2_BUFF_AC)
|
||||
desc: Reduce variable cast time by 80%.
|
||||
|
||||
SC_EMERGENCY_MOVE (EFST_INC_AGI)
|
||||
desc: Increase AGI and walkspeed, AL_INCAGI effect.
|
||||
val1:
|
||||
val2: Movement speed +25 (hardcoded)
|
||||
|
||||
SC_PACKING_ENVELOPE1 (EFST_PACKING_ENVELOPE1)
|
||||
desc: Increases ATK
|
||||
val1: + watk
|
||||
|
@ -118,4 +118,5 @@
|
||||
# Interval Skill unit interval in milliseconds. (Default: 0)
|
||||
# Target Skill unit target type. (Default: All)
|
||||
# Flag: Skill unit flags. (Default: None)
|
||||
# Status Status Change that is associated to the skill. (Optional)
|
||||
###########################################################################
|
||||
|
@ -150,12 +150,7 @@ public:
|
||||
|
||||
void clear() override{
|
||||
TypesafeYamlDatabase<keytype, datatype>::clear();
|
||||
|
||||
// Restore size after clearing
|
||||
size_t cap = cache.capacity();
|
||||
|
||||
cache.clear();
|
||||
cache.resize(cap, nullptr);
|
||||
}
|
||||
|
||||
std::shared_ptr<datatype> find( keytype key ) override{
|
||||
|
@ -1704,7 +1704,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
|
||||
}
|
||||
|
||||
if( sc->data[SC__DEADLYINFECT] && (flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 )
|
||||
status_change_spread(bl, src, 1); // Deadly infect attacked side
|
||||
status_change_spread(bl, src);
|
||||
|
||||
} //End of target SC_ check
|
||||
|
||||
@ -1771,7 +1771,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
|
||||
}
|
||||
|
||||
if( sc->data[SC__DEADLYINFECT] && (flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 )
|
||||
status_change_spread(src, bl, 0);
|
||||
status_change_spread(src, bl);
|
||||
|
||||
if (sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val1 == MH_MD_FIGHTING) {
|
||||
TBL_HOM *hd = BL_CAST(BL_HOM,src); //when attacking
|
||||
@ -9803,9 +9803,8 @@ static const struct _battle_data {
|
||||
{ "display_version", &battle_config.display_version, 1, 0, 1, },
|
||||
{ "display_hallucination", &battle_config.display_hallucination, 1, 0, 1, },
|
||||
{ "use_statpoint_table", &battle_config.use_statpoint_table, 1, 0, 1, },
|
||||
{ "berserk_cancels_buffs", &battle_config.berserk_cancels_buffs, 0, 0, 1, },
|
||||
{ "debuff_on_logout", &battle_config.debuff_on_logout, 1|2, 0, 1|2, },
|
||||
{ "monster_ai", &battle_config.mob_ai, 0x000, 0x000, 0xFFF, },
|
||||
{ "debuff_on_logout", &battle_config.debuff_on_logout, 0, 0, 1|2, },
|
||||
{ "monster_ai", &battle_config.mob_ai, 0x000, 0x000, 0x77F, },
|
||||
{ "hom_setting", &battle_config.hom_setting, 0xFFFF, 0x0000, 0xFFFF, },
|
||||
{ "dynamic_mobs", &battle_config.dynamic_mobs, 1, 0, 1, },
|
||||
{ "mob_remove_damaged", &battle_config.mob_remove_damaged, 1, 0, 1, },
|
||||
|
@ -423,7 +423,6 @@ struct Battle_Config
|
||||
int display_hallucination; // [Skotlex]
|
||||
int use_statpoint_table; // [Skotlex]
|
||||
|
||||
int berserk_cancels_buffs; // [Aru]
|
||||
int debuff_on_logout; // Removes a few "official" negative Scs on logout. [Skotlex]
|
||||
int mob_ai; //Configures various mob_ai settings to make them smarter or dumber(official). [Skotlex]
|
||||
int hom_setting; //Configures various homunc settings which make them behave unlike normal characters.. [Skotlex]
|
||||
|
@ -1656,7 +1656,8 @@ int chrif_bsdata_save(struct map_session_data *sd, bool quit) {
|
||||
|
||||
// Removing...
|
||||
if (quit && sd->bonus_script.head) {
|
||||
uint16 flag = BSF_REM_ON_LOGOUT; //Remove bonus when logout
|
||||
uint32 flag = BSF_REM_ON_LOGOUT; //Remove bonus when logout
|
||||
|
||||
if (battle_config.debuff_on_logout&1) //Remove negative buffs
|
||||
flag |= BSF_REM_DEBUFF;
|
||||
if (battle_config.debuff_on_logout&2) //Remove positive buffs
|
||||
@ -1734,7 +1735,7 @@ int chrif_bsdata_received(int fd) {
|
||||
if (bs->script_str[0] == '\0' || !bs->tick)
|
||||
continue;
|
||||
|
||||
if (!(entry = pc_bonus_script_add(sd, bs->script_str, bs->tick, (enum efst_types)bs->icon, bs->flag, bs->type)))
|
||||
if (!(entry = pc_bonus_script_add(sd, bs->script_str, bs->tick, (enum efst_type)bs->icon, bs->flag, bs->type)))
|
||||
continue;
|
||||
|
||||
linkdb_insert(&sd->bonus_script.head, (void *)((intptr_t)entry), entry);
|
||||
|
@ -4288,7 +4288,7 @@ void clif_changeoption_target( struct block_list* bl, struct block_list* target
|
||||
if( sc->data[SC_PROVOKE] ){
|
||||
const struct TimerData *td = get_timer( sc->data[SC_PROVOKE]->timer );
|
||||
|
||||
clif_status_change( bl, StatusIconChangeTable[SC_PROVOKE], 1, ( !td ? INFINITE_TICK : DIFF_TICK( td->tick, gettick() ) ), 0, 0, 0 );
|
||||
clif_status_change( bl, status_db.getIcon(SC_PROVOKE), 1, ( !td ? INFINITE_TICK : DIFF_TICK( td->tick, gettick() ) ), 0, 0, 0 );
|
||||
}
|
||||
}else{
|
||||
if( disguised( bl ) ){
|
||||
@ -6371,7 +6371,7 @@ void clif_cooking_list( struct map_session_data *sd, int trigger, uint16 skill_i
|
||||
/// 0983 <index>.W <id>.L <state>.B <total msec>.L <remain msec>.L { <val>.L }*3 (ZC_MSG_STATE_CHANGE3) (PACKETVER >= 20120618)
|
||||
/// @param bl Sends packet to clients around this object
|
||||
/// @param id ID of object that has this effect
|
||||
/// @param type Status icon see enum efst_types
|
||||
/// @param type Status icon see enum efst_type
|
||||
/// @param flag 1:Active, 0:Deactive
|
||||
/// @param tick Duration in ms
|
||||
/// @param val1
|
||||
@ -6433,7 +6433,7 @@ void clif_status_change_sub(struct block_list *bl, int id, int type, int flag, t
|
||||
|
||||
/* Sends status effect to clients around the bl
|
||||
* @param bl Object that has the effect
|
||||
* @param type Status icon see enum efst_types
|
||||
* @param type Status icon see enum efst_type
|
||||
* @param flag 1:Active, 0:Deactive
|
||||
* @param tick Duration in ms
|
||||
* @param val1
|
||||
@ -6452,11 +6452,17 @@ void clif_status_change(struct block_list *bl, int type, int flag, t_tick tick,
|
||||
if (type == EFST_ILLUSION && !battle_config.display_hallucination) // Disable Hallucination.
|
||||
return;
|
||||
|
||||
#if PACKETVER_MAIN_NUM < 20191120 || PACKETVER_RE_NUM < 20191106
|
||||
// Older clients display normal riding icon.
|
||||
if (type == EFST_MADOGEAR)
|
||||
type = EFST_RIDING;
|
||||
#endif
|
||||
|
||||
nullpo_retv(bl);
|
||||
|
||||
sd = BL_CAST(BL_PC, bl);
|
||||
|
||||
if (!(status_type2relevant_bl_types(type)&bl->type)) // only send status changes that actually matter to the client
|
||||
if (!(status_efst_get_bl_type((efst_type)type)&bl->type)) // only send status changes that actually matter to the client
|
||||
return;
|
||||
|
||||
clif_status_change_sub(bl, bl->id, type, flag, tick, val1, val2, val3, ((sd ? (pc_isinvisible(sd) ? SELF : AREA) : AREA_WOS)));
|
||||
@ -6525,9 +6531,9 @@ void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl,
|
||||
}
|
||||
|
||||
#if PACKETVER > 20120418
|
||||
clif_efst_status_change(tbl, bl->id, target, StatusIconChangeTable[type], tick, sc_display[i]->val1, sc_display[i]->val2, sc_display[i]->val3);
|
||||
clif_efst_status_change(tbl, bl->id, target, status_db.getIcon(type), tick, sc_display[i]->val1, sc_display[i]->val2, sc_display[i]->val3);
|
||||
#else
|
||||
clif_status_change_sub(tbl, bl->id, StatusIconChangeTable[type], 1, tick, sc_display[i]->val1, sc_display[i]->val2, sc_display[i]->val3, target);
|
||||
clif_status_change_sub(tbl, bl->id, status_db.getIcon(type), 1, tick, sc_display[i]->val1, sc_display[i]->val2, sc_display[i]->val3, target);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -11724,19 +11730,12 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
|
||||
return;
|
||||
}
|
||||
|
||||
// Statuses that don't let the player sit / attack / talk with NPCs(targeted)
|
||||
// (not all are included in pc_can_attack)
|
||||
if (sd->sc.count &&
|
||||
(sd->sc.data[SC_TRICKDEAD] ||
|
||||
(sd->sc.data[SC_AUTOCOUNTER] && action_type != 0x07) ||
|
||||
sd->sc.data[SC_BLADESTOP] ||
|
||||
sd->sc.data[SC__MANHOLE] ||
|
||||
sd->sc.data[SC_SUHIDE] ||
|
||||
sd->sc.data[SC_GRAVITYCONTROL]))
|
||||
return;
|
||||
|
||||
if(action_type != 0x00 && action_type != 0x07)
|
||||
// Statuses that don't let the player sit / stand / talk with NPCs (targeted)
|
||||
if (action_type != 0x00 && action_type != 0x07) {
|
||||
if (sd->sc.cant.interact)
|
||||
return;
|
||||
pc_stop_walking(sd, 1);
|
||||
}
|
||||
pc_stop_attack(sd);
|
||||
|
||||
if(target_id<0 && -target_id == sd->bl.id) // for disguises [Valaris]
|
||||
@ -11747,10 +11746,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
|
||||
case 0x00: // once attack
|
||||
case 0x07: // continuous attack
|
||||
|
||||
if( pc_cant_act(sd) || sd->sc.option&OPTION_HIDE )
|
||||
return;
|
||||
|
||||
if( sd->sc.option&OPTION_COSTUME )
|
||||
if( pc_cant_act(sd) )
|
||||
return;
|
||||
|
||||
if (!battle_config.sdelay_attack_enable && pc_checkskill(sd, SA_FREECAST) <= 0) {
|
||||
@ -12073,11 +12069,7 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd){
|
||||
if (pc_cant_act2(sd) || sd->npc_id)
|
||||
break;
|
||||
|
||||
if (sd->sc.count && (
|
||||
sd->sc.data[SC_AUTOCOUNTER] ||
|
||||
sd->sc.data[SC_BLADESTOP] ||
|
||||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM)
|
||||
))
|
||||
if (sd->sc.cant.drop)
|
||||
break;
|
||||
|
||||
if (!pc_dropitem(sd, item_index, item_amount))
|
||||
@ -15176,7 +15168,7 @@ void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd)
|
||||
int percent = (int)( ( (double)sd->status.base_exp/(double)next )*1000. );
|
||||
|
||||
if( percent && ( percent%100 ) == 0 ) {// 10.0%, 20.0%, ..., 90.0%
|
||||
sc_start(&sd->bl,&sd->bl, status_skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill_get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex]
|
||||
sc_start(&sd->bl,&sd->bl, SC_EXPLOSIONSPIRITS, 100, 17, skill_get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex]
|
||||
clif_skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions
|
||||
}
|
||||
}
|
||||
|
@ -286,137 +286,11 @@ int elemental_data_received(s_elemental *ele, bool flag) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int elemental_clean_single_effect(s_elemental_data *ed, uint16 skill_id) {
|
||||
nullpo_ret(ed);
|
||||
|
||||
sc_type type = status_skill2sc(skill_id);
|
||||
block_list *bl = battle_get_master(&ed->bl);
|
||||
|
||||
if( type ) {
|
||||
switch( type ) {
|
||||
// Just remove status change.
|
||||
case SC_PYROTECHNIC_OPTION:
|
||||
case SC_HEATER_OPTION:
|
||||
case SC_TROPIC_OPTION:
|
||||
case SC_FIRE_CLOAK_OPTION:
|
||||
case SC_AQUAPLAY_OPTION:
|
||||
case SC_WATER_SCREEN_OPTION:
|
||||
case SC_COOLER_OPTION:
|
||||
case SC_CHILLY_AIR_OPTION:
|
||||
case SC_GUST_OPTION:
|
||||
case SC_WIND_STEP_OPTION:
|
||||
case SC_BLAST_OPTION:
|
||||
case SC_WATER_DROP_OPTION:
|
||||
case SC_WIND_CURTAIN_OPTION:
|
||||
case SC_WILD_STORM_OPTION:
|
||||
case SC_PETROLOGY_OPTION:
|
||||
case SC_SOLID_SKIN_OPTION:
|
||||
case SC_CURSED_SOIL_OPTION:
|
||||
case SC_STONE_SHIELD_OPTION:
|
||||
case SC_UPHEAVAL_OPTION:
|
||||
case SC_CIRCLE_OF_FIRE_OPTION:
|
||||
case SC_TIDAL_WEAPON_OPTION:
|
||||
case SC_FLAMETECHNIC_OPTION:
|
||||
case SC_FLAMEARMOR_OPTION:
|
||||
case SC_COLD_FORCE_OPTION:
|
||||
case SC_CRYSTAL_ARMOR_OPTION:
|
||||
case SC_GRACE_BREEZE_OPTION:
|
||||
case SC_EYES_OF_STORM_OPTION:
|
||||
case SC_EARTH_CARE_OPTION:
|
||||
case SC_STRONG_PROTECTION_OPTION:
|
||||
case SC_DEEP_POISONING_OPTION:
|
||||
case SC_POISON_SHIELD_OPTION:
|
||||
if( bl ) status_change_end(bl,type,INVALID_TIMER); // Master
|
||||
status_change_end(&ed->bl,static_cast<sc_type>(type-1),INVALID_TIMER); // Elemental Spirit
|
||||
break;
|
||||
case SC_ZEPHYR:
|
||||
if( bl ) status_change_end(bl,type,INVALID_TIMER);
|
||||
break;
|
||||
default:
|
||||
ShowWarning("Invalid SC=%d in elemental_clean_single_effect\n",type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int elemental_clean_effect(s_elemental_data *ed) {
|
||||
nullpo_ret(ed);
|
||||
|
||||
map_session_data *sd;
|
||||
|
||||
// Elemental side
|
||||
status_change_end(&ed->bl, SC_TROPIC, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_HEATER, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_AQUAPLAY, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_COOLER, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_CHILLY_AIR, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_PYROTECHNIC, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_FIRE_CLOAK, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_WATER_DROP, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_WATER_SCREEN, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_GUST, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_WIND_STEP, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_BLAST, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_WIND_CURTAIN, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_WILD_STORM, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_PETROLOGY, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_SOLID_SKIN, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_CURSED_SOIL, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_STONE_SHIELD, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_UPHEAVAL, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_CIRCLE_OF_FIRE, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_TIDAL_WEAPON, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_FLAMETECHNIC, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_FLAMEARMOR, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_COLD_FORCE, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_CRYSTAL_ARMOR, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_GRACE_BREEZE, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_EYES_OF_STORM, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_EARTH_CARE, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_STRONG_PROTECTION, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_DEEP_POISONING, INVALID_TIMER);
|
||||
status_change_end(&ed->bl, SC_POISON_SHIELD, INVALID_TIMER);
|
||||
|
||||
if( (sd = ed->master) == NULL )
|
||||
return 0;
|
||||
|
||||
// Master side
|
||||
status_change_end(&sd->bl, SC_TROPIC_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_HEATER_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_AQUAPLAY_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_COOLER_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_CHILLY_AIR_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_PYROTECHNIC_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_FIRE_CLOAK_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_WATER_DROP_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_WATER_SCREEN_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_GUST_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_WIND_STEP_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_BLAST_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_WATER_DROP_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_WIND_CURTAIN_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_WILD_STORM_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_ZEPHYR, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_WIND_STEP_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_PETROLOGY_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SOLID_SKIN_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_CURSED_SOIL_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_STONE_SHIELD_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_UPHEAVAL_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_CIRCLE_OF_FIRE_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_TIDAL_WEAPON_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_FLAMETECHNIC_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_FLAMEARMOR_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_COLD_FORCE_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_CRYSTAL_ARMOR_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_GRACE_BREEZE_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_EYES_OF_STORM_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_EARTH_CARE_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_STRONG_PROTECTION_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_DEEP_POISONING_OPTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_POISON_SHIELD_OPTION, INVALID_TIMER);
|
||||
status_db.removeByStatusFlag(&ed->bl, { SCF_REMOVEELEMENTALOPTION });
|
||||
status_db.removeByStatusFlag(battle_get_master(&ed->bl), { SCF_REMOVEELEMENTALOPTION });
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -125,7 +125,6 @@ t_tick elemental_get_lifetime(s_elemental_data *ed);
|
||||
int elemental_unlocktarget(s_elemental_data *ed);
|
||||
bool elemental_skillnotok(uint16 skill_id, s_elemental_data *ed);
|
||||
int elemental_set_target( map_session_data *sd, block_list *bl );
|
||||
int elemental_clean_single_effect(s_elemental_data *ed, uint16 skill_id);
|
||||
int elemental_clean_effect(s_elemental_data *ed);
|
||||
int elemental_action(s_elemental_data *ed, block_list *bl, t_tick tick);
|
||||
struct s_skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv);
|
||||
@ -133,7 +132,6 @@ struct s_skill_condition elemental_skill_get_requirements(uint16 skill_id, uint1
|
||||
#define elemental_stop_walking(ed, type) unit_stop_walking(&(ed)->bl, type)
|
||||
#define elemental_stop_attack(ed) unit_stop_attack(&(ed)->bl)
|
||||
|
||||
void read_elemental_skilldb(void);
|
||||
void do_init_elemental(void);
|
||||
void do_final_elemental(void);
|
||||
|
||||
|
@ -1529,14 +1529,15 @@ void guild_guildaura_refresh(struct map_session_data *sd, uint16 skill_id, uint1
|
||||
if( !skill_lv )
|
||||
return;
|
||||
|
||||
std::shared_ptr<s_skill_unit_group> group;
|
||||
sc_type type = status_skill2sc(skill_id);
|
||||
sc_type type = skill_get_sc(skill_id);
|
||||
|
||||
if (type == SC_NONE)
|
||||
return;
|
||||
|
||||
status_change_end(&sd->bl, type, INVALID_TIMER);
|
||||
|
||||
std::shared_ptr<s_skill_unit_group> group = skill_unitsetting(&sd->bl,skill_id,skill_lv,sd->bl.x,sd->bl.y,0);
|
||||
|
||||
if( sd->sc.data[type] && (group = skill_id2group(sd->sc.data[type]->val4)) ) {
|
||||
skill_delunitgroup(group);
|
||||
status_change_end(&sd->bl,type,INVALID_TIMER);
|
||||
}
|
||||
group = skill_unitsetting(&sd->bl,skill_id,skill_lv,sd->bl.x,sd->bl.y,0);
|
||||
if( group )
|
||||
sc_start4(NULL,&sd->bl,type,100,(battle_config.guild_aura&16)?0:skill_lv,0,0,group->group_id,600000);//duration doesn't matter these status never end with val4
|
||||
return;
|
||||
|
@ -270,7 +270,7 @@ int hom_dead(struct homun_data *hd)
|
||||
clif_emotion(&sd->bl, ET_CRY);
|
||||
|
||||
#ifdef RENEWAL
|
||||
status_change_end(&sd->bl, status_skill2sc(AM_CALLHOMUN), INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_HOMUN_TIME, INVALID_TIMER);
|
||||
#endif
|
||||
|
||||
//Remove from map (if it has no intimacy, it is auto-removed from memory)
|
||||
@ -310,7 +310,7 @@ int hom_vaporize(struct map_session_data *sd, int flag)
|
||||
hom_save(hd);
|
||||
|
||||
#ifdef RENEWAL
|
||||
status_change_end(&sd->bl, status_skill2sc(AM_CALLHOMUN), INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_HOMUN_TIME, INVALID_TIMER);
|
||||
#endif
|
||||
|
||||
return unit_remove_map(&hd->bl, CLR_OUTSIGHT);
|
||||
@ -1183,7 +1183,7 @@ bool hom_call(struct map_session_data *sd)
|
||||
unit_warp(&hd->bl,sd->bl.m, sd->bl.x, sd->bl.y,CLR_OUTSIGHT);
|
||||
|
||||
#ifdef RENEWAL
|
||||
sc_start(&sd->bl, &sd->bl, status_skill2sc(AM_CALLHOMUN), 100, 1, skill_get_time(AM_CALLHOMUN, 1));
|
||||
sc_start(&sd->bl, &sd->bl, SC_HOMUN_TIME, 100, 1, skill_get_time(AM_CALLHOMUN, 1));
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@ -1243,7 +1243,7 @@ int hom_recv_data(uint32 account_id, struct s_homunculus *sh, int flag)
|
||||
}
|
||||
|
||||
#ifdef RENEWAL
|
||||
sc_start(&sd->bl, &sd->bl, status_skill2sc(AM_CALLHOMUN), 100, 1, skill_get_time(AM_CALLHOMUN, 1));
|
||||
sc_start(&sd->bl, &sd->bl, SC_HOMUN_TIME, 100, 1, skill_get_time(AM_CALLHOMUN, 1));
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
@ -1332,7 +1332,7 @@ int hom_ressurect(struct map_session_data* sd, unsigned char per, short x, short
|
||||
}
|
||||
|
||||
#ifdef RENEWAL
|
||||
sc_start(&sd->bl, &sd->bl, status_skill2sc(AM_CALLHOMUN), 100, 1, skill_get_time(AM_CALLHOMUN, 1));
|
||||
sc_start(&sd->bl, &sd->bl, SC_HOMUN_TIME, 100, 1, skill_get_time(AM_CALLHOMUN, 1));
|
||||
#endif
|
||||
|
||||
return status_revive(&hd->bl, per, 0);
|
||||
|
@ -345,6 +345,7 @@
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\spellbook_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\spellbook_db.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\statpoint.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\statpoint.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\status_disabled.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\status_disabled.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\status.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\status.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\stylist.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\stylist.yml')" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
100
src/map/map.cpp
100
src/map/map.cpp
@ -2084,85 +2084,27 @@ int map_quit(struct map_session_data *sd) {
|
||||
//map_quit handles extra specific data which is related to quitting normally
|
||||
//(changing map-servers invokes unit_free but bypasses map_quit)
|
||||
if( sd->sc.count ) {
|
||||
//Status that are not saved...
|
||||
status_change_end(&sd->bl, SC_BOSSMAPINFO, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_AUTOTRADE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SPURT, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_BERSERK, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC__BLOODYLUST, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_TRICKDEAD, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_LEADERSHIP, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_GLORYWOUNDS, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SOULCOLD, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_HAWKEYES, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_EMERGENCY_MOVE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_CHASEWALK2, INVALID_TIMER);
|
||||
if(sd->sc.data[SC_PROVOKE] && sd->sc.data[SC_PROVOKE]->timer == INVALID_TIMER)
|
||||
status_change_end(&sd->bl, SC_PROVOKE, INVALID_TIMER); //Infinite provoke ends on logout
|
||||
status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_WEIGHT90, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SATURDAYNIGHTFEVER, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_KYOUGAKU, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_C_MARKER, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_READYSTORM, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_READYDOWN, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_READYTURN, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_READYCOUNTER, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_DODGE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_CBC, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_EQC, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SPRITEMABLE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SV_ROOTTWIST, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_GUARD_STANCE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_ATTACK_STANCE, INVALID_TIMER);
|
||||
// Remove visuals effect from headgear
|
||||
status_change_end(&sd->bl, SC_MOONSTAR, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SUPER_STAR, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_STRANGELIGHTS, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_DECORATION_OF_MUSIC, INVALID_TIMER);
|
||||
if (battle_config.debuff_on_logout&1) { //Remove negative buffs
|
||||
status_change_end(&sd->bl, SC_ORCISH, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_STRIPWEAPON, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_STRIPARMOR, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_STRIPSHIELD, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_STRIPHELM, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_EXTREMITYFIST, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_EXPLOSIONSPIRITS, INVALID_TIMER);
|
||||
if(sd->sc.data[SC_REGENERATION] && sd->sc.data[SC_REGENERATION]->val4)
|
||||
status_change_end(&sd->bl, SC_REGENERATION, INVALID_TIMER);
|
||||
//TO-DO Probably there are way more NPC_type negative status that are removed
|
||||
status_change_end(&sd->bl, SC_CHANGEUNDEAD, INVALID_TIMER);
|
||||
// Both these statuses are removed on logout. [L0ne_W0lf]
|
||||
status_change_end(&sd->bl, SC_SLOWCAST, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_CRITICALWOUND, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_H_MINE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_ANTI_M_BLAST, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_B_TRAP, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SHADOW_STRIP, INVALID_TIMER);
|
||||
}
|
||||
if (battle_config.debuff_on_logout&2) { //Remove positive buffs
|
||||
status_change_end(&sd->bl, SC_MAXIMIZEPOWER, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_MAXOVERTHRUST, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_STEELBODY, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_PRESERVE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_KAAHI, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SPIRIT, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_HEAT_BARREL, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_P_ALTER, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_E_CHAIN, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SIGHTBLASTER, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_BENEDICTIO, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_GLASTHEIM_ATK, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_GLASTHEIM_DEF, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_GLASTHEIM_HEAL, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_GLASTHEIM_HIDDEN, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_GLASTHEIM_STATE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_GLASTHEIM_ITEMDEF, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_GLASTHEIM_HPSP, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SOULGOLEM, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SOULSHADOW, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SOULFALCON, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SOULFAIRY, INVALID_TIMER);
|
||||
for (const auto &it : status_db) {
|
||||
std::bitset<SCF_MAX> &flag = it.second->flag;
|
||||
|
||||
//No need to save infinite status
|
||||
if (flag[SCF_NOSAVEINFINITE] && sd->sc.data[it.first] && sd->sc.data[it.first]->val4 > 0) {
|
||||
status_change_end(&sd->bl, static_cast<sc_type>(it.first), INVALID_TIMER);
|
||||
continue;
|
||||
}
|
||||
|
||||
//Status that are not saved
|
||||
if (flag[SCF_NOSAVE]) {
|
||||
status_change_end(&sd->bl, static_cast<sc_type>(it.first), INVALID_TIMER);
|
||||
continue;
|
||||
}
|
||||
//Removes status by config
|
||||
if (battle_config.debuff_on_logout&1 && flag[SCF_DEBUFF] || //Removes debuffs
|
||||
(battle_config.debuff_on_logout&2 && !(flag[SCF_DEBUFF]))) //Removes buffs
|
||||
{
|
||||
status_change_end(&sd->bl, static_cast<sc_type>(it.first), INVALID_TIMER);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1698,8 +1698,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
|
||||
return false;
|
||||
|
||||
// Abnormalities
|
||||
if(( md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT && md->sc.opt1 != OPT1_BURNING )
|
||||
|| md->sc.data[SC_BLADESTOP] || md->sc.data[SC__MANHOLE] || md->sc.data[SC_CURSEDCIRCLE_TARGET]) {//Should reset targets.
|
||||
if(( md->sc.opt1 && md->sc.opt1 != OPT1_STONEWAIT && md->sc.opt1 != OPT1_BURNING ) || status_db.hasSCF(&md->sc, SCF_MOBLOSETARGET)) {//Should reset targets.
|
||||
md->target_id = md->attacked_id = md->norm_attacked_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
190
src/map/pc.cpp
190
src/map/pc.cpp
@ -2690,7 +2690,7 @@ static void pc_bonus_addeff(std::vector<s_addeffect> &effect, enum sc_type sc, s
|
||||
flag |= ATF_WEAPON; //Default type: weapon.
|
||||
|
||||
if (!duration)
|
||||
duration = (unsigned int)skill_get_time2(status_sc2skill(sc), 7);
|
||||
duration = (unsigned int)skill_get_time2(status_db.getSkill(sc), 7);
|
||||
|
||||
for (auto &it : effect) {
|
||||
if (it.sc == sc && it.flag == flag) {
|
||||
@ -2732,7 +2732,7 @@ static void pc_bonus_addeff_onskill(std::vector<s_addeffectonskill> &effect, enu
|
||||
}
|
||||
|
||||
if (!duration)
|
||||
duration = (unsigned int)skill_get_time2(status_sc2skill(sc), 7);
|
||||
duration = (unsigned int)skill_get_time2(status_db.getSkill(sc), 7);
|
||||
|
||||
for (auto &it : effect) {
|
||||
if (it.sc == sc && it.skill_id == skill_id && it.target == target) {
|
||||
@ -5697,7 +5697,7 @@ bool pc_isUseitem(struct map_session_data *sd,int n)
|
||||
case ITEMID_M_BERSERK_POTION:
|
||||
if( sd->md == NULL || sd->md->db == NULL )
|
||||
return false;
|
||||
if( sd->md->sc.data[SC_BERSERK] )
|
||||
if( sd->md->sc.cant.consume )
|
||||
return false;
|
||||
if( nameid == ITEMID_M_AWAKENING_POTION && sd->md->db->lv < 40 )
|
||||
return false;
|
||||
@ -5738,24 +5738,7 @@ bool pc_isUseitem(struct map_session_data *sd,int n)
|
||||
if (!pc_job_can_use_item(sd,item))
|
||||
return false;
|
||||
|
||||
if (sd->sc.count && (
|
||||
sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] ||
|
||||
(sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) ||
|
||||
sd->sc.data[SC_TRICKDEAD] ||
|
||||
sd->sc.data[SC_HIDING] ||
|
||||
sd->sc.data[SC__SHADOWFORM] ||
|
||||
sd->sc.data[SC__INVISIBILITY] ||
|
||||
sd->sc.data[SC__MANHOLE] ||
|
||||
sd->sc.data[SC_DEEPSLEEP] ||
|
||||
sd->sc.data[SC_CRYSTALIZE] ||
|
||||
sd->sc.data[SC_KAGEHUMI] ||
|
||||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM) ||
|
||||
sd->sc.data[SC_KINGS_GRACE] ||
|
||||
sd->sc.data[SC_SUHIDE] ||
|
||||
sd->sc.data[SC_HANDICAPSTATE_FROSTBITE] ||
|
||||
sd->sc.data[SC_HANDICAPSTATE_SWOONING] ||
|
||||
sd->sc.data[SC_HANDICAPSTATE_LIGHTNINGSTRIKE] ||
|
||||
sd->sc.data[SC_HANDICAPSTATE_CRYSTALLIZATION]))
|
||||
if (sd->sc.cant.consume)
|
||||
return false;
|
||||
|
||||
if (!pc_isItemClass(sd,item))
|
||||
@ -6292,24 +6275,23 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in
|
||||
|
||||
sd->state.pmap = sd->bl.m;
|
||||
if (sc && sc->count) { // Cancel some map related stuff.
|
||||
if (sc->data[SC_JAILED])
|
||||
return SETPOS_MAPINDEX; //You may not get out!
|
||||
status_change_end(&sd->bl, SC_BOSSMAPINFO, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_WARM, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SUN_COMFORT, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_MOON_COMFORT, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_STAR_COMFORT, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_MIRACLE, INVALID_TIMER);
|
||||
if (sc->data[SC_KNOWLEDGE]) {
|
||||
struct status_change_entry *sce = sc->data[SC_KNOWLEDGE];
|
||||
if (sce->timer != INVALID_TIMER)
|
||||
delete_timer(sce->timer, status_change_timer);
|
||||
sce->timer = add_timer(gettick() + skill_get_time(SG_KNOWLEDGE, sce->val1), status_change_timer, sd->bl.id, SC_KNOWLEDGE);
|
||||
if (sc->cant.warp)
|
||||
return SETPOS_MAPINDEX; // You may not get out!
|
||||
|
||||
for (const auto &it : status_db) {
|
||||
if (sc->data[it.first]) {
|
||||
if (it.second->flag[SCF_REMOVEONMAPWARP])
|
||||
status_change_end(&sd->bl, static_cast<sc_type>(it.first), INVALID_TIMER);
|
||||
|
||||
if (it.second->flag[SCF_RESTARTONMAPWARP] && it.second->skill_id > 0) {
|
||||
status_change_entry *sce = sd->sc.data[it.first];
|
||||
|
||||
if (sce->timer != INVALID_TIMER)
|
||||
delete_timer(sce->timer, status_change_timer);
|
||||
sce->timer = add_timer(gettick() + skill_get_time(it.second->skill_id, sce->val1), status_change_timer, sd->bl.id, it.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
status_change_end(&sd->bl, SC_PROPERTYWALK, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_CLOAKING, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SUHIDE, INVALID_TIMER);
|
||||
}
|
||||
for(int i = 0; i < EQI_MAX; i++ ) {
|
||||
if( sd->equip_index[i] >= 0 )
|
||||
@ -6685,47 +6667,26 @@ uint8 pc_checkskill_imperial_guard(struct map_session_data *sd, short flag)
|
||||
*/
|
||||
static void pc_checkallowskill(struct map_session_data *sd)
|
||||
{
|
||||
const enum sc_type scw_list[] = {
|
||||
SC_TWOHANDQUICKEN,
|
||||
SC_ONEHAND,
|
||||
SC_AURABLADE,
|
||||
SC_PARRYING,
|
||||
SC_SPEARQUICKEN,
|
||||
SC_ADRENALINE,
|
||||
SC_ADRENALINE2,
|
||||
SC_DANCING,
|
||||
SC_GATLINGFEVER,
|
||||
SC_DANCING_KNIFE,
|
||||
};
|
||||
uint8 i;
|
||||
nullpo_retv(sd);
|
||||
|
||||
if(!sd->sc.count)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAYLENGTH(scw_list); i++)
|
||||
{ // Skills requiring specific weapon types
|
||||
if( scw_list[i] == SC_DANCING && !battle_config.dancing_weaponswitch_fix )
|
||||
continue;
|
||||
if(sd->sc.data[scw_list[i]] &&
|
||||
!pc_check_weapontype(sd,skill_get_weapontype(status_sc2skill(scw_list[i]))))
|
||||
status_change_end(&sd->bl, scw_list[i], INVALID_TIMER);
|
||||
}
|
||||
for (const auto &it : status_db) {
|
||||
sc_type status = it.second->type;
|
||||
std::bitset<SCF_MAX> flag = it.second->flag;
|
||||
|
||||
if(sd->sc.data[SC_SPURT] && sd->status.weapon)
|
||||
// Spurt requires bare hands (feet, in fact xD)
|
||||
status_change_end(&sd->bl, SC_SPURT, INVALID_TIMER);
|
||||
if (flag[SCF_REQUIREWEAPON]) { // Skills requiring specific weapon types
|
||||
if (status == SC_DANCING && !battle_config.dancing_weaponswitch_fix)
|
||||
continue;
|
||||
if (sd->sc.data[status] && !pc_check_weapontype(sd, skill_get_weapontype(it.second->skill_id)))
|
||||
status_change_end(&sd->bl, status, INVALID_TIMER);
|
||||
}
|
||||
|
||||
if(sd->status.shield <= 0) { // Skills requiring a shield
|
||||
const enum sc_type scs_list[] = {
|
||||
SC_AUTOGUARD,
|
||||
SC_DEFENDER,
|
||||
SC_REFLECTSHIELD,
|
||||
SC_REFLECTDAMAGE
|
||||
};
|
||||
for (i = 0; i < ARRAYLENGTH(scs_list); i++)
|
||||
if(sd->sc.data[scs_list[i]])
|
||||
status_change_end(&sd->bl, scs_list[i], INVALID_TIMER);
|
||||
if (flag[SCF_REQUIRESHIELD]) { // Skills requiring a shield
|
||||
if (sd->sc.data[status] && sd->status.shield <= 0)
|
||||
status_change_end(&sd->bl, status, INVALID_TIMER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7539,16 +7500,17 @@ int pc_checkbaselevelup(struct map_session_data *sd) {
|
||||
status_percent_heal(&sd->bl,100,100);
|
||||
|
||||
if ((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) {
|
||||
sc_start(&sd->bl,&sd->bl,status_skill2sc(PR_KYRIE),100,1,skill_get_time(PR_KYRIE,1));
|
||||
sc_start(&sd->bl,&sd->bl,status_skill2sc(PR_IMPOSITIO),100,1,skill_get_time(PR_IMPOSITIO,1));
|
||||
sc_start(&sd->bl,&sd->bl,status_skill2sc(PR_MAGNIFICAT),100,1,skill_get_time(PR_MAGNIFICAT,1));
|
||||
sc_start(&sd->bl,&sd->bl,status_skill2sc(PR_GLORIA),100,1,skill_get_time(PR_GLORIA,1));
|
||||
sc_start(&sd->bl,&sd->bl,status_skill2sc(PR_SUFFRAGIUM),100,1,skill_get_time(PR_SUFFRAGIUM,1));
|
||||
for (const auto &status : status_db) {
|
||||
if (status.second->flag[SCF_SUPERNOVICEANGEL])
|
||||
sc_start(&sd->bl, &sd->bl, status.second->type, 100, 1, skill_get_time(status.second->skill_id, 1));
|
||||
}
|
||||
if (sd->state.snovice_dead_flag)
|
||||
sd->state.snovice_dead_flag = 0; //Reenable steelbody resurrection on dead.
|
||||
} else if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) {
|
||||
sc_start(&sd->bl,&sd->bl,status_skill2sc(AL_INCAGI),100,10,600000);
|
||||
sc_start(&sd->bl,&sd->bl,status_skill2sc(AL_BLESSING),100,10,600000);
|
||||
for (const auto &status : status_db) {
|
||||
if (status.second->flag[SCF_TAEKWONANGEL])
|
||||
sc_start(&sd->bl, &sd->bl, status.second->type, 100, 10, 600000);
|
||||
}
|
||||
}
|
||||
clif_misceffect(&sd->bl,0);
|
||||
npc_script_event(sd, NPCE_BASELVUP); //LORDALFA - LVLUPEVENT
|
||||
@ -9035,7 +8997,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
|
||||
clif_resurrection(&sd->bl, 1);
|
||||
if(battle_config.pc_invincible_time)
|
||||
pc_setinvincibletimer(sd, battle_config.pc_invincible_time);
|
||||
sc_start(&sd->bl,&sd->bl,status_skill2sc(MO_STEELBODY),100,5,skill_get_time(MO_STEELBODY,5));
|
||||
sc_start(&sd->bl,&sd->bl,SC_STEELBODY,100,5,skill_get_time(MO_STEELBODY,5));
|
||||
if(mapdata_flag_gvg2(mapdata))
|
||||
pc_respawn_timer(INVALID_TIMER, gettick(), sd->bl.id, 0);
|
||||
return 0;
|
||||
@ -9243,7 +9205,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
|
||||
// changed penalty options, added death by player if pk_mode [Valaris]
|
||||
if(battle_config.death_penalty_type
|
||||
&& (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE // only novices will receive no penalty
|
||||
&& !sd->sc.data[SC_BABY] && !sd->sc.data[SC_LIFEINSURANCE]
|
||||
&& !sd->sc.cant.deathpenalty
|
||||
&& !mapdata->flag[MF_NOEXPPENALTY] && !mapdata_flag_gvg2(mapdata))
|
||||
{
|
||||
t_exp base_penalty = 0;
|
||||
@ -10154,16 +10116,7 @@ bool pc_jobchange(struct map_session_data *sd,int job, char upper)
|
||||
}
|
||||
|
||||
if ( (b_class&MAPID_UPPERMASK) != (sd->class_&MAPID_UPPERMASK) ) { //Things to remove when changing class tree.
|
||||
std::shared_ptr<s_skill_tree> tree = skill_tree_db.find(sd->status.class_);
|
||||
|
||||
if (tree != nullptr && !tree->skills.empty()) {
|
||||
for (const auto &skillsit : tree->skills) {
|
||||
//Remove status specific to your current tree skills.
|
||||
enum sc_type sc = status_skill2sc(skillsit.first);
|
||||
if (sc > SC_COMMON_MAX && sd->sc.data[sc])
|
||||
status_change_end(&sd->bl, sc, INVALID_TIMER);
|
||||
}
|
||||
}
|
||||
status_db.changeSkillTree(sd);
|
||||
}
|
||||
|
||||
if( (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && (b_class&MAPID_UPPERMASK) != MAPID_STAR_GLADIATOR) {
|
||||
@ -10613,45 +10566,6 @@ bool pc_candrop(struct map_session_data *sd, struct item *item)
|
||||
return (itemdb_isdropable(item, pc_get_group_level(sd)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a player can attack based on status changes
|
||||
* Why not use status_check_skilluse?
|
||||
* "src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack."
|
||||
* Even ground-based attacks should be blocked by these statuses
|
||||
* Called from unit_attack and unit_attack_timer_sub
|
||||
* @retval true Can attack
|
||||
**/
|
||||
bool pc_can_attack( struct map_session_data *sd, int target_id ) {
|
||||
nullpo_retr(false, sd);
|
||||
|
||||
if( pc_is90overweight(sd) || pc_isridingwug(sd) )
|
||||
return false;
|
||||
|
||||
if (sd->state.block_action & PCBLOCK_ATTACK)
|
||||
return false;
|
||||
|
||||
if(
|
||||
#ifdef RENEWAL
|
||||
sd->sc.data[SC_BASILICA_CELL] ||
|
||||
#else
|
||||
sd->sc.data[SC_BASILICA] ||
|
||||
#endif
|
||||
sd->sc.data[SC__SHADOWFORM] ||
|
||||
sd->sc.data[SC_CURSEDCIRCLE_ATKER] ||
|
||||
sd->sc.data[SC_CURSEDCIRCLE_TARGET] ||
|
||||
sd->sc.data[SC_CRYSTALIZE] ||
|
||||
sd->sc.data[SC_ALL_RIDING] || // The client doesn't let you, this is to make cheat-safe
|
||||
sd->sc.data[SC_TRICKDEAD] ||
|
||||
(sd->sc.data[SC_VOICEOFSIREN] && sd->sc.data[SC_VOICEOFSIREN]->val2 == target_id) ||
|
||||
sd->sc.data[SC_BLADESTOP] ||
|
||||
sd->sc.data[SC_DEEPSLEEP] ||
|
||||
(sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) ||
|
||||
sd->sc.data[SC_KINGS_GRACE] )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Read '@type' variables (temporary numeric char reg)
|
||||
*------------------------------------------*/
|
||||
@ -11355,8 +11269,7 @@ bool pc_equipitem(struct map_session_data *sd,short n,int req_pos,bool equipswit
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if( sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] ||
|
||||
sd->sc.data[SC_KYOUGAKU] || (sd->sc.data[SC_PYROCLASTIC] && sd->inventory_data[n]->type == IT_WEAPON)) ) {
|
||||
if( sd->sc.count && (sd->sc.cant.equip || (sd->sc.data[SC_PYROCLASTIC] && sd->inventory_data[n]->type == IT_WEAPON)) ) {
|
||||
if( equipswitch ){
|
||||
clif_equipswitch_add( sd, n, req_pos, ITEM_EQUIP_ACK_FAIL );
|
||||
}else{
|
||||
@ -11678,13 +11591,8 @@ bool pc_unequipitem(struct map_session_data *sd, int n, int flag) {
|
||||
return false; //Nothing to unequip
|
||||
}
|
||||
// status change that makes player cannot unequip equipment
|
||||
if (!(flag&2) && sd->sc.count &&
|
||||
(sd->sc.data[SC_BERSERK] ||
|
||||
sd->sc.data[SC_SATURDAYNIGHTFEVER] ||
|
||||
sd->sc.data[SC__BLOODYLUST] ||
|
||||
sd->sc.data[SC_KYOUGAKU] ||
|
||||
(sd->sc.data[SC_PYROCLASTIC] &&
|
||||
sd->inventory_data[n]->type == IT_WEAPON))) // can't switch weapon
|
||||
if (!(flag&2) && sd->sc.count &&( sd->sc.cant.unequip ||
|
||||
(sd->sc.data[SC_PYROCLASTIC] && sd->inventory_data[n]->type == IT_WEAPON))) // can't switch weapon
|
||||
{
|
||||
clif_unequipitemack(sd,n,0,0);
|
||||
return false;
|
||||
@ -14236,7 +14144,7 @@ void pc_bonus_script(struct map_session_data *sd) {
|
||||
* @return New created entry pointer or NULL if failed or NULL if duplicate fail
|
||||
* @author [Cydh]
|
||||
**/
|
||||
struct s_bonus_script_entry *pc_bonus_script_add(struct map_session_data *sd, const char *script_str, t_tick dur, enum efst_types icon, uint16 flag, uint8 type) {
|
||||
struct s_bonus_script_entry *pc_bonus_script_add(struct map_session_data *sd, const char *script_str, t_tick dur, enum efst_type icon, uint16 flag, uint8 type) {
|
||||
struct script_code *script = NULL;
|
||||
struct linkdb_node *node = NULL;
|
||||
struct s_bonus_script_entry *entry = NULL;
|
||||
@ -14361,7 +14269,7 @@ TIMER_FUNC(pc_bonus_script_timer){
|
||||
* @param flag: Reason to remove the bonus_script. e_bonus_script_flags or e_bonus_script_types
|
||||
* @author [Cydh]
|
||||
**/
|
||||
void pc_bonus_script_clear(struct map_session_data *sd, uint16 flag) {
|
||||
void pc_bonus_script_clear(struct map_session_data *sd, uint32 flag) {
|
||||
struct linkdb_node *node = NULL;
|
||||
uint16 count = 0;
|
||||
|
||||
|
@ -291,7 +291,7 @@ struct s_bonus_script_entry {
|
||||
StringBuf *script_buf; //Used for comparing and storing on table
|
||||
t_tick tick;
|
||||
uint16 flag;
|
||||
enum efst_types icon;
|
||||
enum efst_type icon;
|
||||
uint8 type; //0 - Ignore; 1 - Buff; 2 - Debuff
|
||||
int tid;
|
||||
};
|
||||
@ -1459,7 +1459,6 @@ void pc_regen (struct map_session_data *sd, t_tick diff_tick);
|
||||
|
||||
bool pc_setstand(struct map_session_data *sd, bool force);
|
||||
bool pc_candrop(struct map_session_data *sd,struct item *item);
|
||||
bool pc_can_attack(struct map_session_data *sd, int target_id);
|
||||
|
||||
uint64 pc_jobid2mapid(unsigned short b_class); // Skotlex
|
||||
int pc_mapid2jobid(uint64 class_, int sex); // Skotlex
|
||||
@ -1573,8 +1572,8 @@ void pc_show_version(struct map_session_data *sd);
|
||||
|
||||
TIMER_FUNC(pc_bonus_script_timer);
|
||||
void pc_bonus_script(struct map_session_data *sd);
|
||||
struct s_bonus_script_entry *pc_bonus_script_add(struct map_session_data *sd, const char *script_str, t_tick dur, enum efst_types icon, uint16 flag, uint8 type);
|
||||
void pc_bonus_script_clear(struct map_session_data *sd, uint16 flag);
|
||||
struct s_bonus_script_entry *pc_bonus_script_add(struct map_session_data *sd, const char *script_str, t_tick dur, enum efst_type icon, uint16 flag, uint8 type);
|
||||
void pc_bonus_script_clear(struct map_session_data *sd, uint32 flag);
|
||||
|
||||
void pc_cell_basilica(struct map_session_data *sd);
|
||||
|
||||
|
@ -11944,9 +11944,11 @@ BUILDIN_FUNC(sc_start)
|
||||
else
|
||||
bl = map_id2bl(st->rid);
|
||||
|
||||
if(tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status_sc2skill(type) != 0)
|
||||
uint16 skill_id;
|
||||
|
||||
if(tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && (skill_id = status_db.getSkill(type)) > 0)
|
||||
{// When there isn't a duration specified, try to get it from the skill_db
|
||||
tick = skill_get_time(status_sc2skill(type), val1);
|
||||
tick = skill_get_time(skill_id, val1);
|
||||
}
|
||||
|
||||
if(potion_flag == 1 && potion_target) { //skill.cpp set the flags before running the script, this is a potion-pitched effect.
|
||||
@ -11996,45 +11998,16 @@ BUILDIN_FUNC(sc_end)
|
||||
if (!bl)
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
|
||||
if (type >= 0 && type < SC_MAX) {
|
||||
if (type >= SC_NONE && type < SC_MAX) {
|
||||
struct status_change *sc = status_get_sc(bl);
|
||||
struct status_change_entry *sce = sc ? sc->data[type] : NULL;
|
||||
|
||||
if (!sce)
|
||||
if (!sc)
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
|
||||
switch (type) {
|
||||
case SC_WEIGHT50:
|
||||
case SC_WEIGHT90:
|
||||
case SC_NOCHAT:
|
||||
case SC_PUSH_CART:
|
||||
case SC_ALL_RIDING:
|
||||
case SC_STYLE_CHANGE:
|
||||
case SC_MONSTER_TRANSFORM:
|
||||
case SC_ACTIVE_MONSTER_TRANSFORM:
|
||||
case SC_MTF_ASPD:
|
||||
case SC_MTF_RANGEATK:
|
||||
case SC_MTF_MATK:
|
||||
case SC_MTF_MLEATKED:
|
||||
case SC_MTF_CRIDAMAGE:
|
||||
case SC_MTF_ASPD2:
|
||||
case SC_MTF_RANGEATK2:
|
||||
case SC_MTF_MATK2:
|
||||
case SC_MTF_MHP:
|
||||
case SC_MTF_MSP:
|
||||
case SC_MTF_PUMPKIN:
|
||||
case SC_MTF_HITFLEE:
|
||||
case SC_ATTHASTE_CASH:
|
||||
case SC_REUSE_LIMIT_A: case SC_REUSE_LIMIT_B: case SC_REUSE_LIMIT_C:
|
||||
case SC_REUSE_LIMIT_D: case SC_REUSE_LIMIT_E: case SC_REUSE_LIMIT_F:
|
||||
case SC_REUSE_LIMIT_G: case SC_REUSE_LIMIT_H: case SC_REUSE_LIMIT_MTF:
|
||||
case SC_REUSE_LIMIT_ASPD_POTION: case SC_REUSE_MILLENNIUMSHIELD: case SC_REUSE_CRUSHSTRIKE:
|
||||
case SC_REUSE_STORMBLAST: case SC_ALL_RIDING_REUSE_LIMIT: case SC_REUSE_REFRESH:
|
||||
case SC_REUSE_LIMIT_ECL: case SC_REUSE_LIMIT_RECALL:
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (status_db.hasSCF(sc, SCF_NOCLEARBUFF))
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
|
||||
struct status_change_entry *sce = sc ? sc->data[type] : NULL;
|
||||
|
||||
//This should help status_change_end force disabling the SC in case it has no limit.
|
||||
sce->val1 = sce->val2 = sce->val3 = sce->val4 = 0;
|
||||
@ -12053,7 +12026,6 @@ BUILDIN_FUNC(sc_end)
|
||||
BUILDIN_FUNC(sc_end_class)
|
||||
{
|
||||
struct map_session_data *sd;
|
||||
uint16 skill_id;
|
||||
int class_;
|
||||
|
||||
if (!script_charid2sd(2, sd))
|
||||
@ -12069,17 +12041,7 @@ BUILDIN_FUNC(sc_end_class)
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_skill_tree> tree = skill_tree_db.find(class_);
|
||||
|
||||
if( tree != nullptr ){
|
||||
for (const auto &it : tree->skills) {
|
||||
skill_id = it.first;
|
||||
enum sc_type sc = status_skill2sc(skill_id);
|
||||
|
||||
if (sc > SC_COMMON_MAX && sd->sc.data[sc])
|
||||
status_change_end(&sd->bl, sc, INVALID_TIMER);
|
||||
}
|
||||
}
|
||||
status_db.changeSkillTree(sd, class_);
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
@ -23021,7 +22983,7 @@ BUILDIN_FUNC(bonus_script) {
|
||||
if (icon <= EFST_BLANK || icon >= EFST_MAX)
|
||||
icon = EFST_BLANK;
|
||||
|
||||
if ((entry = pc_bonus_script_add(sd, script_str, dur, (enum efst_types)icon, flag, type))) {
|
||||
if ((entry = pc_bonus_script_add(sd, script_str, dur, (enum efst_type)icon, flag, type))) {
|
||||
linkdb_insert(&sd->bonus_script.head, (void *)((intptr_t)entry), entry);
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
}
|
||||
|
@ -1054,7 +1054,8 @@
|
||||
export_constant(SC_ARMOR);
|
||||
export_constant(SC_ARMOR_ELEMENT_WATER);
|
||||
export_constant(SC_NOCHAT);
|
||||
export_constant(SC_BABY);
|
||||
export_constant(SC_PROTECTEXP);
|
||||
export_deprecated_constant3("SC_BABY", SC_PROTECTEXP, "SC_PROTECTEXP");
|
||||
export_constant(SC_AURABLADE);
|
||||
export_constant(SC_PARRYING);
|
||||
export_constant(SC_CONCENTRATION);
|
||||
@ -1611,6 +1612,7 @@
|
||||
export_constant(SC_GOLDENMACECLAN);
|
||||
export_constant(SC_CROSSBOWCLAN);
|
||||
export_constant(SC_JUMPINGCLAN);
|
||||
export_constant(SC_TAROTCARD);
|
||||
export_constant(SC_GEFFEN_MAGIC1);
|
||||
export_constant(SC_GEFFEN_MAGIC2);
|
||||
export_constant(SC_GEFFEN_MAGIC3);
|
||||
@ -1647,6 +1649,7 @@
|
||||
export_constant(SC_ANCILLA);
|
||||
export_constant(SC_EARTHSHAKER);
|
||||
export_constant(SC_WEAPONBLOCK_ON);
|
||||
export_constant(SC_SPORE_EXPLOSION);
|
||||
export_constant(SC_ENTRY_QUEUE_APPLY_DELAY);
|
||||
export_constant(SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT);
|
||||
export_constant(SC_ADAPTATION);
|
||||
@ -1691,6 +1694,8 @@
|
||||
export_constant(SC_LUXANIMA);
|
||||
export_constant(SC_REUSE_LIMIT_LUXANIMA);
|
||||
export_constant(SC_ENSEMBLEFATIGUE);
|
||||
export_constant(SC_MISTY_FROST);
|
||||
export_constant(SC_MAGIC_POISON);
|
||||
export_constant(SC_EP16_2_BUFF_SS);
|
||||
export_constant(SC_EP16_2_BUFF_SC);
|
||||
export_constant(SC_EP16_2_BUFF_AC);
|
||||
@ -8724,6 +8729,169 @@
|
||||
export_constant(EL_SKILLMODE_ASSIST);
|
||||
export_constant(EL_SKILLMODE_AGGRESSIVE);
|
||||
|
||||
/* status calc bl */
|
||||
export_constant(SCB_NONE);
|
||||
export_constant(SCB_BASE);
|
||||
export_constant(SCB_MAXHP);
|
||||
export_constant(SCB_MAXSP);
|
||||
export_constant(SCB_STR);
|
||||
export_constant(SCB_AGI);
|
||||
export_constant(SCB_VIT);
|
||||
export_constant(SCB_INT);
|
||||
export_constant(SCB_DEX);
|
||||
export_constant(SCB_LUK);
|
||||
export_constant(SCB_BATK);
|
||||
export_constant(SCB_WATK);
|
||||
export_constant(SCB_MATK);
|
||||
export_constant(SCB_HIT);
|
||||
export_constant(SCB_FLEE);
|
||||
export_constant(SCB_DEF);
|
||||
export_constant(SCB_DEF2);
|
||||
export_constant(SCB_MDEF);
|
||||
export_constant(SCB_MDEF2);
|
||||
export_constant(SCB_SPEED);
|
||||
export_constant(SCB_ASPD);
|
||||
export_constant(SCB_DSPD);
|
||||
export_constant(SCB_CRI);
|
||||
export_constant(SCB_FLEE2);
|
||||
export_constant(SCB_ATK_ELE);
|
||||
export_constant(SCB_DEF_ELE);
|
||||
export_constant(SCB_MODE);
|
||||
export_constant(SCB_SIZE);
|
||||
export_constant(SCB_RACE);
|
||||
export_constant(SCB_RANGE);
|
||||
export_constant(SCB_REGEN);
|
||||
export_constant(SCB_DYE);
|
||||
export_constant(SCB_BATTLE);
|
||||
export_constant(SCB_MAXAP);
|
||||
export_constant(SCB_POW);
|
||||
export_constant(SCB_STA);
|
||||
export_constant(SCB_WIS);
|
||||
export_constant(SCB_SPL);
|
||||
export_constant(SCB_CON);
|
||||
export_constant(SCB_CRT);
|
||||
export_constant(SCB_PATK);
|
||||
export_constant(SCB_SMATK);
|
||||
export_constant(SCB_RES);
|
||||
export_constant(SCB_MRES);
|
||||
export_constant(SCB_HPLUS);
|
||||
export_constant(SCB_CRATE);
|
||||
export_constant(SCB_ALL);
|
||||
|
||||
/* status change states */
|
||||
export_constant(SCS_NONE);
|
||||
export_constant(SCS_NOMOVECOND);
|
||||
export_constant(SCS_NOMOVE);
|
||||
export_constant(SCS_NOPICKITEMCOND);
|
||||
export_constant(SCS_NOPICKITEM);
|
||||
export_constant(SCS_NODROPITEMCOND);
|
||||
export_constant(SCS_NODROPITEM);
|
||||
export_constant(SCS_NOCASTCOND);
|
||||
export_constant(SCS_NOCAST);
|
||||
export_constant(SCS_NOCHAT);
|
||||
export_constant(SCS_NOCHATCOND);
|
||||
export_constant(SCS_NOEQUIPITEM);
|
||||
export_constant(SCS_NOEQUIPITEMCOND);
|
||||
export_constant(SCS_NOUNEQUIPITEM);
|
||||
export_constant(SCS_NOUNEQUIPITEMCOND);
|
||||
export_constant(SCS_NOCONSUMEITEM);
|
||||
export_constant(SCS_NOCONSUMEITEMCOND);
|
||||
export_constant(SCS_NOATTACK);
|
||||
export_constant(SCS_NOATTACKCOND);
|
||||
export_constant(SCS_NOWARP);
|
||||
export_constant(SCS_NOWARPCOND);
|
||||
export_constant(SCS_NODEATHPENALTY);
|
||||
export_constant(SCS_NODEATHPENALTYCOND);
|
||||
export_constant(SCS_NOINTERACT);
|
||||
export_constant(SCS_NOINTERACTCOND);
|
||||
|
||||
/* body states */
|
||||
export_constant(OPT1_STONE);
|
||||
export_constant(OPT1_FREEZE);
|
||||
export_constant(OPT1_STUN);
|
||||
export_constant(OPT1_SLEEP);
|
||||
export_constant(OPT1_STONEWAIT);
|
||||
export_constant(OPT1_BURNING);
|
||||
export_constant(OPT1_IMPRISON);
|
||||
|
||||
/* health states */
|
||||
export_constant(OPT2_POISON);
|
||||
export_constant(OPT2_CURSE);
|
||||
export_constant(OPT2_SILENCE);
|
||||
export_constant(OPT2_SIGNUMCRUCIS);
|
||||
export_constant(OPT2_BLIND);
|
||||
export_constant(OPT2_ANGELUS);
|
||||
export_constant(OPT2_BLEEDING);
|
||||
export_constant(OPT2_DPOISON);
|
||||
export_constant(OPT2_FEAR);
|
||||
|
||||
/* show effect states */
|
||||
export_constant(OPT3_NORMAL);
|
||||
export_constant(OPT3_QUICKEN);
|
||||
export_constant(OPT3_OVERTHRUST);
|
||||
export_constant(OPT3_ENERGYCOAT);
|
||||
export_constant(OPT3_EXPLOSIONSPIRITS);
|
||||
export_constant(OPT3_STEELBODY);
|
||||
export_constant(OPT3_BLADESTOP);
|
||||
export_constant(OPT3_AURABLADE);
|
||||
export_constant(OPT3_BERSERK);
|
||||
export_constant(OPT3_LIGHTBLADE);
|
||||
export_constant(OPT3_MOONLIT);
|
||||
export_constant(OPT3_MARIONETTE);
|
||||
export_constant(OPT3_ASSUMPTIO);
|
||||
export_constant(OPT3_WARM);
|
||||
export_constant(OPT3_KAITE);
|
||||
export_constant(OPT3_BUNSIN);
|
||||
export_constant(OPT3_SOULLINK);
|
||||
export_constant(OPT3_UNDEAD);
|
||||
export_constant(OPT3_CONTRACT);
|
||||
|
||||
/* status change flags */
|
||||
export_constant(SCF_BLEFFECT);
|
||||
export_constant(SCF_DISPLAYPC);
|
||||
export_constant(SCF_NOCLEARBUFF);
|
||||
export_constant(SCF_NOREMOVEONDEAD);
|
||||
export_constant(SCF_NODISPELL);
|
||||
export_constant(SCF_NOCLEARANCE);
|
||||
export_constant(SCF_NOBANISHINGBUSTER);
|
||||
export_constant(SCF_NOSAVE);
|
||||
export_constant(SCF_NOSAVEINFINITE);
|
||||
export_constant(SCF_REMOVEONDAMAGED);
|
||||
export_constant(SCF_REMOVEONREFRESH);
|
||||
export_constant(SCF_REMOVEONLUXANIMA);
|
||||
export_constant(SCF_STOPATTACKING);
|
||||
export_constant(SCF_STOPCASTING);
|
||||
export_constant(SCF_STOPWALKING);
|
||||
export_constant(SCF_BOSSRESIST);
|
||||
export_constant(SCF_MVPRESIST);
|
||||
export_constant(SCF_SETSTAND);
|
||||
export_constant(SCF_FAILEDMADO);
|
||||
export_constant(SCF_DEBUFF);
|
||||
export_constant(SCF_REMOVEONCHANGEMAP);
|
||||
export_constant(SCF_REMOVEONMAPWARP);
|
||||
export_constant(SCF_REMOVECHEMICALPROTECT);
|
||||
export_constant(SCF_OVERLAPFAIL);
|
||||
export_constant(SCF_OVERLAPIGNORELEVEL);
|
||||
export_constant(SCF_SENDOPTION);
|
||||
export_constant(SCF_ONTOUCH);
|
||||
export_constant(SCF_UNITMOVE);
|
||||
export_constant(SCF_NONPLAYER);
|
||||
export_constant(SCF_SENDLOOK);
|
||||
export_constant(SCF_DISPLAYNPC);
|
||||
export_constant(SCF_REQUIREWEAPON);
|
||||
export_constant(SCF_REQUIRESHIELD);
|
||||
export_constant(SCF_MOBLOSETARGET);
|
||||
export_constant(SCF_REMOVEELEMENTALOPTION);
|
||||
export_constant(SCF_SUPERNOVICEANGEL);
|
||||
export_constant(SCF_TAEKWONANGEL);
|
||||
export_constant(SCF_MADOCANCEL);
|
||||
export_constant(SCF_MADOENDCANCEL);
|
||||
export_constant(SCF_RESTARTONMAPWARP);
|
||||
export_constant(SCF_SPREADEFFECT);
|
||||
export_constant(SCF_SENDVAL1);
|
||||
export_constant(SCF_SENDVAL2);
|
||||
export_constant(SCF_SENDVAL3);
|
||||
|
||||
#undef export_constant
|
||||
#undef export_constant2
|
||||
#undef export_parameter
|
||||
|
@ -218,6 +218,7 @@ int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { skill_get_l
|
||||
int skill_get_state( uint16 skill_id ) { skill_get(skill_id, skill_db.find(skill_id)->require.state); }
|
||||
int skill_get_status_count( uint16 skill_id ) { skill_get(skill_id, skill_db.find(skill_id)->require.status.size()); }
|
||||
int skill_get_spiritball( uint16 skill_id, uint16 skill_lv ) { skill_get_lv(skill_id, skill_lv, skill_db.find(skill_id)->require.spiritball); }
|
||||
sc_type skill_get_sc(int16 skill_id) { if (!skill_check(skill_id)) return SC_NONE; return skill_db.find(skill_id)->sc; }
|
||||
|
||||
int skill_get_splash( uint16 skill_id , uint16 skill_lv ) {
|
||||
int splash = skill_get_splash_(skill_id, skill_lv);
|
||||
@ -1601,22 +1602,34 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
||||
break;
|
||||
|
||||
case NPC_PETRIFYATTACK:
|
||||
sc_start4(src,bl,status_skill2sc(skill_id),(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_STONE,50+10*skill_lv,skill_lv,0,0,skill_get_time(skill_id,skill_lv),skill_get_time2(skill_id,skill_lv));
|
||||
break;
|
||||
case NPC_CURSEATTACK:
|
||||
sc_start(src,bl,SC_CURSE,(20*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv));
|
||||
break;
|
||||
case NPC_SLEEPATTACK:
|
||||
sc_start(src,bl,SC_SLEEP,(20*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv));
|
||||
break;
|
||||
case NPC_BLINDATTACK:
|
||||
sc_start(src,bl,SC_BLIND,(20*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv));
|
||||
break;
|
||||
case NPC_POISON:
|
||||
sc_start(src,bl,SC_POISON,(20*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv));
|
||||
break;
|
||||
case NPC_SILENCEATTACK:
|
||||
sc_start(src,bl,SC_SILENCE,(20*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv));
|
||||
break;
|
||||
case NPC_STUNATTACK:
|
||||
sc_start(src,bl,SC_STUN,(20*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv));
|
||||
break;
|
||||
case NPC_BLEEDING:
|
||||
sc_start(src,bl,status_skill2sc(skill_id),(20*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv));
|
||||
sc_start(src,bl,SC_BLEEDING,(20*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv));
|
||||
break;
|
||||
case NPC_ACIDBREATH:
|
||||
sc_start(src,bl,SC_POISON,70,skill_lv,skill_get_time2(skill_id,skill_lv));
|
||||
break;
|
||||
case NPC_ICEBREATH:
|
||||
sc_start(src,bl,status_skill2sc(skill_id),70,skill_lv,skill_get_time2(skill_id,skill_lv));
|
||||
sc_start(src,bl,SC_FREEZE,70,skill_lv,skill_get_time2(skill_id,skill_lv));
|
||||
break;
|
||||
case NPC_MENTALBREAKER:
|
||||
{ //Based on observations by Tharis, Mental Breaker should do SP damage
|
||||
@ -1772,7 +1785,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
||||
sc_start(src,bl, SC_ADORAMUS, skill_lv * 4 + (sd ? sd->status.job_level : 50) / 2, skill_lv, skill_get_time2(skill_id, skill_lv));
|
||||
break;
|
||||
case WL_COMET:
|
||||
sc_start(src, bl, status_skill2sc(skill_id), 100, skill_lv, 20000);
|
||||
sc_start(src, bl, SC_BURNING, 100, skill_lv, 20000);
|
||||
break;
|
||||
case NPC_COMET:
|
||||
sc_start4(src,bl,SC_BURNING,100,skill_lv,1000,src->id,0,skill_get_time(skill_id,skill_lv));
|
||||
@ -1899,7 +1912,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
||||
sc_start(src,bl, SC_POISON, 5 * skill_lv, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
break;
|
||||
case GN_SPORE_EXPLOSION:
|
||||
sc_start(src, bl, status_skill2sc(skill_id), 100, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
sc_start(src, bl, SC_SPORE_EXPLOSION, 100, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
break;
|
||||
case GN_SLINGITEM_RANGEMELEEATK:
|
||||
if( sd ) {
|
||||
@ -1935,8 +1948,10 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
||||
sc_start(src,bl, SC_STUN, rate, skill_lv, skill_get_time(skill_id,skill_lv));
|
||||
break;
|
||||
case EL_ROCK_CRUSHER:
|
||||
sc_start(src,bl, SC_ROCK_CRUSHER,50,skill_lv,skill_get_time(EL_ROCK_CRUSHER,skill_lv));
|
||||
break;
|
||||
case EL_ROCK_CRUSHER_ATK:
|
||||
sc_start(src,bl,status_skill2sc(skill_id),50,skill_lv,skill_get_time(EL_ROCK_CRUSHER,skill_lv));
|
||||
sc_start(src,bl,SC_ROCK_CRUSHER_ATK,50,skill_lv,skill_get_time(EL_ROCK_CRUSHER,skill_lv));
|
||||
break;
|
||||
case EL_TYPOON_MIS:
|
||||
sc_start(src,bl,SC_SILENCE,10*skill_lv,skill_lv,skill_get_time(skill_id,skill_lv));
|
||||
@ -1993,8 +2008,6 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
||||
sc_start(src,bl,SC_STUN,100,skill_lv,skill_get_time2(skill_id,skill_lv));
|
||||
break;
|
||||
case RL_BANISHING_BUSTER: {
|
||||
uint16 i, n = skill_lv;
|
||||
|
||||
if (!tsc || !tsc->count)
|
||||
break;
|
||||
|
||||
@ -2007,99 +2020,24 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; n > 0 && i < SC_MAX; i++) {
|
||||
if (!tsc->data[i])
|
||||
uint16 n = skill_lv;
|
||||
|
||||
for (const auto &it : status_db) {
|
||||
sc_type status = static_cast<sc_type>(it.first);
|
||||
|
||||
if (n <= 0)
|
||||
break;
|
||||
if (!tsc->data[status])
|
||||
continue;
|
||||
switch (i) {
|
||||
case SC_WEIGHT50: case SC_WEIGHT90: case SC_HALLUCINATION:
|
||||
case SC_STRIPWEAPON: case SC_STRIPSHIELD: case SC_STRIPARMOR:
|
||||
case SC_STRIPHELM: case SC_CP_WEAPON: case SC_CP_SHIELD:
|
||||
case SC_CP_ARMOR: case SC_CP_HELM: case SC_COMBO:
|
||||
case SC_STRFOOD: case SC_AGIFOOD: case SC_VITFOOD:
|
||||
case SC_INTFOOD: case SC_DEXFOOD: case SC_LUKFOOD:
|
||||
case SC_HITFOOD: case SC_FLEEFOOD: case SC_BATKFOOD:
|
||||
case SC_WATKFOOD: case SC_MATKFOOD: case SC_CRIFOOD:
|
||||
case SC_DANCING: case SC_SPIRIT: case SC_AUTOBERSERK:
|
||||
case SC_CARTBOOST: case SC_MELTDOWN: case SC_SAFETYWALL:
|
||||
case SC_SMA: case SC_SPEEDUP0: case SC_NOCHAT:
|
||||
case SC_ANKLE: case SC_SPIDERWEB: case SC_JAILED:
|
||||
case SC_ITEMBOOST: case SC_EXPBOOST: case SC_LIFEINSURANCE:
|
||||
case SC_BOSSMAPINFO: case SC_PNEUMA: case SC_AUTOSPELL:
|
||||
case SC_INCHITRATE: case SC_INCATKRATE: case SC_NEN:
|
||||
case SC_READYSTORM: case SC_READYDOWN: case SC_READYTURN:
|
||||
case SC_READYCOUNTER: case SC_DODGE: case SC_WARM:
|
||||
/*case SC_SPEEDUP1:*/ case SC_AUTOTRADE: case SC_CRITICALWOUND:
|
||||
case SC_JEXPBOOST: case SC_INVINCIBLE: case SC_INVINCIBLEOFF:
|
||||
case SC_HELLPOWER: case SC_MANU_ATK: case SC_MANU_DEF:
|
||||
case SC_SPL_ATK: case SC_SPL_DEF: case SC_MANU_MATK:
|
||||
case SC_SPL_MATK: case SC_RICHMANKIM: case SC_ETERNALCHAOS:
|
||||
case SC_DRUMBATTLE: case SC_NIBELUNGEN: case SC_ROKISWEIL:
|
||||
case SC_INTOABYSS: case SC_SIEGFRIED: case SC_FOOD_STR_CASH:
|
||||
case SC_FOOD_AGI_CASH: case SC_FOOD_VIT_CASH: case SC_FOOD_DEX_CASH:
|
||||
case SC_FOOD_INT_CASH: case SC_FOOD_LUK_CASH: case SC_ELECTRICSHOCKER:
|
||||
case SC__STRIPACCESSORY: case SC__ENERVATION: case SC__GROOMY:
|
||||
case SC__IGNORANCE: case SC__LAZINESS: case SC__UNLUCKY:
|
||||
case SC__WEAKNESS: case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD:
|
||||
case SC_MAGNETICFIELD: case SC_MINOR_BBQ: case SC_SIROMA_ICE_TEA:
|
||||
case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES: case SC_NEUTRALBARRIER_MASTER:
|
||||
case SC_NEUTRALBARRIER: case SC_STEALTHFIELD_MASTER: case SC_STEALTHFIELD:
|
||||
case SC_LEADERSHIP: case SC_GLORYWOUNDS: case SC_SOULCOLD:
|
||||
case SC_HAWKEYES: case SC_REGENERATION: case SC_SEVENWIND:
|
||||
case SC_MIRACLE: case SC_S_LIFEPOTION: case SC_L_LIFEPOTION:
|
||||
case SC_INCHEALRATE: case SC_PUSH_CART: case SC_PARTYFLEE:
|
||||
case SC_RAISINGDRAGON: case SC_GT_REVITALIZE: case SC_GT_ENERGYGAIN:
|
||||
case SC_GT_CHANGE: case SC_ANGEL_PROTECT: case SC_MONSTER_TRANSFORM:
|
||||
case SC_FULL_THROTTLE: case SC_REBOUND: case SC_TELEKINESIS_INTENSE:
|
||||
case SC_MOONSTAR: case SC_SUPER_STAR: case SC_ALL_RIDING:
|
||||
case SC_MTF_ASPD: case SC_MTF_RANGEATK: case SC_MTF_MATK:
|
||||
case SC_MTF_MLEATKED: case SC_MTF_CRIDAMAGE: case SC_HEAT_BARREL:
|
||||
case SC_P_ALTER: case SC_E_CHAIN:
|
||||
case SC_C_MARKER: case SC_B_TRAP: case SC_H_MINE:
|
||||
case SC_STRANGELIGHTS: case SC_DECORATION_OF_MUSIC: case SC_GN_CARTBOOST:
|
||||
case SC_RECOGNIZEDSPELL: case SC_CHASEWALK2: case SC_BITE:
|
||||
case SC_ACTIVE_MONSTER_TRANSFORM: case SC_DORAM_BUF_01: case SC_DORAM_BUF_02:
|
||||
case SC_SPORE_EXPLOSION:
|
||||
case SC_NEWMOON: case SC_FLASHKICK: case SC_NOVAEXPLOSING:
|
||||
case SC_SOULUNITY: case SC_SOULSHADOW: case SC_SOULFAIRY:
|
||||
case SC_SOULFALCON: case SC_SOULGOLEM: case SC_USE_SKILL_SP_SPA:
|
||||
case SC_USE_SKILL_SP_SHA: case SC_SP_SHA:
|
||||
// 4th Jobs
|
||||
case SC_SERVANTWEAPON: case SC_SERVANT_SIGN: case SC_GUARD_STANCE:
|
||||
case SC_ATTACK_STANCE: case SC_PROTECTSHADOWEQUIP: case SC_SHADOW_STRIP:
|
||||
case SC_ABYSSFORCEWEAPON:
|
||||
#ifdef RENEWAL
|
||||
case SC_EXTREMITYFIST2:
|
||||
#endif
|
||||
case SC_HIDING: case SC_CLOAKING: case SC_CHASEWALK:
|
||||
case SC_CLOAKINGEXCEED: case SC__INVISIBILITY: case SC_UTSUSEMI:
|
||||
case SC_MTF_ASPD2: case SC_MTF_RANGEATK2: case SC_MTF_MATK2:
|
||||
case SC_2011RWC_SCROLL: case SC_JP_EVENT04: case SC_MTF_MHP:
|
||||
case SC_MTF_MSP: case SC_MTF_PUMPKIN: case SC_MTF_HITFLEE:
|
||||
case SC_ATTHASTE_CASH: case SC_REUSE_REFRESH:
|
||||
case SC_REUSE_LIMIT_A: case SC_REUSE_LIMIT_B: case SC_REUSE_LIMIT_C:
|
||||
case SC_REUSE_LIMIT_D: case SC_REUSE_LIMIT_E: case SC_REUSE_LIMIT_F:
|
||||
case SC_REUSE_LIMIT_G: case SC_REUSE_LIMIT_H: case SC_REUSE_LIMIT_MTF:
|
||||
case SC_REUSE_LIMIT_ASPD_POTION: case SC_REUSE_MILLENNIUMSHIELD: case SC_REUSE_CRUSHSTRIKE:
|
||||
case SC_REUSE_STORMBLAST: case SC_ALL_RIDING_REUSE_LIMIT:
|
||||
case SC_SPRITEMABLE: case SC_BITESCAR:
|
||||
case SC_CLAN_INFO: case SC_SWORDCLAN: case SC_ARCWANDCLAN:
|
||||
case SC_GOLDENMACECLAN: case SC_CROSSBOWCLAN:
|
||||
case SC_DAILYSENDMAILCNT:
|
||||
case SC_WEDDING: case SC_XMAS: case SC_SUMMER:
|
||||
case SC_DRESSUP: case SC_HANBOK: case SC_OKTOBERFEST:
|
||||
case SC_LHZ_DUN_N1: case SC_LHZ_DUN_N2: case SC_LHZ_DUN_N3: case SC_LHZ_DUN_N4:
|
||||
case SC_ENTRY_QUEUE_APPLY_DELAY: case SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT:
|
||||
case SC_REUSE_LIMIT_LUXANIMA: case SC_LUXANIMA: case SC_SOULENERGY:
|
||||
case SC_EP16_2_BUFF_SS: case SC_EP16_2_BUFF_SC: case SC_EP16_2_BUFF_AC:
|
||||
case SC_EMERGENCY_MOVE: case SC_MADOGEAR: case SC_HOMUN_TIME:
|
||||
case SC_PACKING_ENVELOPE1: case SC_PACKING_ENVELOPE2: case SC_PACKING_ENVELOPE3:
|
||||
case SC_PACKING_ENVELOPE4: case SC_PACKING_ENVELOPE5: case SC_PACKING_ENVELOPE6:
|
||||
case SC_PACKING_ENVELOPE7: case SC_PACKING_ENVELOPE8: case SC_PACKING_ENVELOPE9: case SC_PACKING_ENVELOPE10:
|
||||
continue;
|
||||
|
||||
if (it.second->flag[SCF_NOBANISHINGBUSTER])
|
||||
continue;
|
||||
|
||||
switch (status) {
|
||||
case SC_WHISTLE: case SC_ASSNCROS: case SC_POEMBRAGI:
|
||||
case SC_APPLEIDUN: case SC_HUMMING: case SC_DONTFORGETME:
|
||||
case SC_FORTUNE: case SC_SERVICE4U:
|
||||
if (!battle_config.dispel_song || tsc->data[i]->val4 == 0)
|
||||
if (!battle_config.dispel_song || tsc->data[status]->val4 == 0)
|
||||
continue; //If in song area don't end it, even if config enabled
|
||||
break;
|
||||
case SC_ASSUMPTIO:
|
||||
@ -2107,9 +2045,9 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if( i == SC_BERSERK || i == SC_SATURDAYNIGHTFEVER )
|
||||
tsc->data[i]->val2 = 0;
|
||||
status_change_end(bl,(sc_type)i,INVALID_TIMER);
|
||||
if( status == SC_BERSERK || status == SC_SATURDAYNIGHTFEVER )
|
||||
tsc->data[status]->val2 = 0;
|
||||
status_change_end(bl,status,INVALID_TIMER);
|
||||
n--;
|
||||
}
|
||||
//Remove bonus_script by Banishing Buster
|
||||
@ -2802,7 +2740,7 @@ int skill_break_equip(struct block_list *src, struct block_list *bl, unsigned sh
|
||||
else if (rnd()%10000 >= rate)
|
||||
where&=~where_list[i];
|
||||
else if (!sd) //Cause Strip effect.
|
||||
sc_start(src,bl,scatk[i],100,0,skill_get_time(status_sc2skill(scatk[i]),1));
|
||||
sc_start(src,bl,scatk[i],100,0,skill_get_time(status_db.getSkill(scatk[i]),1));
|
||||
}
|
||||
}
|
||||
if (!where) //Nothing to break.
|
||||
@ -4490,14 +4428,19 @@ static TIMER_FUNC(skill_timerskill){
|
||||
case PR_LEXDIVINA:
|
||||
if (src->type == BL_MOB) {
|
||||
// Monsters use the default duration when casting Lex Divina
|
||||
sc_start(src, target, status_skill2sc(skl->skill_id), skl->type, skl->skill_lv, skill_get_time2(status_sc2skill(status_skill2sc(skl->skill_id)), 1));
|
||||
sc_start(src, target, SC_SILENCE, skl->type, skl->skill_lv, skill_get_time2(status_db.getSkill(SC_SILENCE), 1));
|
||||
break;
|
||||
}
|
||||
// Fall through
|
||||
sc_start(src, target, SC_SILENCE, skl->type, skl->skill_lv, skill_get_time2(skl->skill_id, skl->skill_lv));
|
||||
break;
|
||||
case PR_STRECOVERY:
|
||||
sc_start(src, target, SC_BLIND, skl->type, skl->skill_lv, skill_get_time2(skl->skill_id, skl->skill_lv));
|
||||
break;
|
||||
case BS_HAMMERFALL:
|
||||
sc_start(src, target, SC_STUN, skl->type, skl->skill_lv, skill_get_time2(skl->skill_id, skl->skill_lv));
|
||||
break;
|
||||
case MER_LEXDIVINA:
|
||||
sc_start(src, target, status_skill2sc(skl->skill_id), skl->type, skl->skill_lv, skill_get_time2(skl->skill_id, skl->skill_lv));
|
||||
sc_start(src, target, SC_SILENCE, skl->type, skl->skill_lv, skill_get_time2(skl->skill_id, skl->skill_lv));
|
||||
break;
|
||||
case WZ_WATERBALL:
|
||||
{
|
||||
@ -4884,15 +4827,15 @@ static int skill_tarotcard(struct block_list* src, struct block_list *target, ui
|
||||
{
|
||||
enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE };
|
||||
uint8 rand_eff = rnd() % 3;
|
||||
int time = ((rand_eff == 0) ? skill_get_time2(skill_id, skill_lv) : skill_get_time2(status_sc2skill(sc[rand_eff]), 1));
|
||||
int time = ((rand_eff == 0) ? skill_get_time2(skill_id, skill_lv) : skill_get_time2(status_db.getSkill(sc[rand_eff]), 1));
|
||||
sc_start(src, target, sc[rand_eff], 100, skill_lv, time);
|
||||
break;
|
||||
}
|
||||
case 9: // DEATH - curse, coma and poison
|
||||
{
|
||||
status_change_start(src, target, SC_COMA, 10000, skill_lv, 0, src->id, 0, 0, SCSTART_NONE);
|
||||
sc_start(src, target, SC_CURSE, 100, skill_lv, skill_get_time2(status_sc2skill(SC_CURSE), 1));
|
||||
sc_start2(src, target, SC_POISON, 100, skill_lv, src->id, skill_get_time2(status_sc2skill(SC_POISON), 1));
|
||||
sc_start(src, target, SC_CURSE, 100, skill_lv, skill_get_time2(status_db.getSkill(SC_CURSE), 1));
|
||||
sc_start2(src, target, SC_POISON, 100, skill_lv, src->id, skill_get_time2(status_db.getSkill(SC_POISON), 1));
|
||||
break;
|
||||
}
|
||||
case 10: // TEMPERANCE - confusion
|
||||
@ -4906,7 +4849,7 @@ static int skill_tarotcard(struct block_list* src, struct block_list *target, ui
|
||||
clif_damage(src, target, tick, 0, 0, 6666, 0, DMG_NORMAL, 0, false);
|
||||
sc_start(src, target, SC_INCATKRATE, 100, -50, skill_get_time2(skill_id, skill_lv));
|
||||
sc_start(src, target, SC_INCMATKRATE, 100, -50, skill_get_time2(skill_id, skill_lv));
|
||||
sc_start(src, target, SC_CURSE, skill_lv, 100, skill_get_time2(status_sc2skill(SC_CURSE), 1));
|
||||
sc_start(src, target, SC_CURSE, skill_lv, 100, skill_get_time2(status_db.getSkill(SC_CURSE), 1));
|
||||
break;
|
||||
}
|
||||
case 12: // THE TOWER - 4444 damage
|
||||
@ -4917,7 +4860,7 @@ static int skill_tarotcard(struct block_list* src, struct block_list *target, ui
|
||||
}
|
||||
case 13: // THE STAR - stun
|
||||
{
|
||||
sc_start(src, target, SC_STUN, 100, skill_lv, skill_get_time2(status_sc2skill(SC_STUN), 1));
|
||||
sc_start(src, target, SC_STUN, 100, skill_lv, skill_get_time2(status_db.getSkill(SC_STUN), 1));
|
||||
break;
|
||||
}
|
||||
default: // THE SUN - atk, matk, hit, flee and def reduced, immune to more tarot card effects
|
||||
@ -4966,7 +4909,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
||||
|
||||
if (skill_id && skill_id != AG_DEADLY_PROJECTION && skill_get_type(skill_id) == BF_MAGIC && status_isimmune(bl) == 100)
|
||||
{ //GTB makes all targetted magic display miss with a single bolt.
|
||||
sc_type sct = status_skill2sc(skill_id);
|
||||
sc_type sct = skill_get_sc(skill_id);
|
||||
if(sct != SC_NONE)
|
||||
status_change_end(bl, sct, INVALID_TIMER);
|
||||
clif_skill_damage(src, bl, tick, status_get_amotion(src), status_get_dmotion(bl), 0, 1, skill_id, skill_lv, skill_get_hit(skill_id));
|
||||
@ -5957,7 +5900,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
||||
|
||||
case NPC_MAGICALATTACK:
|
||||
skill_attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag);
|
||||
sc_start(src,src,status_skill2sc(skill_id),100,skill_lv,skill_get_time(skill_id,skill_lv));
|
||||
sc_start(src,src,SC_MAGICALATTACK,100,skill_lv,skill_get_time(skill_id,skill_lv));
|
||||
break;
|
||||
|
||||
case HVAN_CAPRICE: //[blackhole89]
|
||||
@ -6209,7 +6152,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
||||
|
||||
case GC_DARKCROW:
|
||||
skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
|
||||
sc_start(src, bl, status_skill2sc(skill_id), 100, skill_lv, skill_get_time(skill_id, skill_lv)); // Should be applied even on miss
|
||||
sc_start(src, bl, SC_DARKCROW, 100, skill_lv, skill_get_time(skill_id, skill_lv)); // Should be applied even on miss
|
||||
break;
|
||||
|
||||
case WL_DRAINLIFE:
|
||||
@ -6376,7 +6319,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
||||
break;
|
||||
case WL_FROSTMISTY:
|
||||
// Causes Freezing status through walls.
|
||||
sc_start(src, bl, status_skill2sc(skill_id), 25 + 5 * skill_lv, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
sc_start(src, bl, SC_FREEZING, 25 + 5 * skill_lv, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
sc_start(src, bl, SC_MISTY_FROST, 100, skill_lv, skill_get_time2(skill_id, skill_lv));
|
||||
// Doesn't deal damage through non-shootable walls.
|
||||
if( !battle_config.skill_wall_check || (battle_config.skill_wall_check && path_search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKWALL)) )
|
||||
@ -6632,14 +6575,13 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
||||
if( src->type == BL_ELEM ) {
|
||||
s_elemental_data *ele = BL_CAST(BL_ELEM,src);
|
||||
struct status_change *tsc_ele = status_get_sc(&ele->bl);
|
||||
sc_type type = status_skill2sc(skill_id), type2;
|
||||
|
||||
type2 = static_cast<sc_type>(type - 1);
|
||||
sc_type type = SC_TIDAL_WEAPON_OPTION, type2 = SC_TIDAL_WEAPON;
|
||||
|
||||
clif_skill_nodamage(src,battle_get_master(src),skill_id,skill_lv,1);
|
||||
clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, DMG_SINGLE);
|
||||
if( (tsc_ele && tsc_ele->data[type2]) || (tsc && tsc->data[type]) ) {
|
||||
elemental_clean_single_effect(ele, skill_id);
|
||||
status_change_end(battle_get_master(src),type,INVALID_TIMER);
|
||||
status_change_end(src,type2,INVALID_TIMER);
|
||||
}
|
||||
if( rnd()%100 < 50 )
|
||||
skill_attack(skill_get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag);
|
||||
@ -6676,13 +6618,21 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
||||
{
|
||||
TBL_HOM *hd = BL_CAST(BL_HOM,src);
|
||||
int duration = max(skill_lv, (status_get_str(src) / 7 - status_get_str(bl) / 10)) * 1000; //Yommy formula
|
||||
sc_type type;
|
||||
|
||||
if (skill_id == MH_TINDER_BREAKER && unit_movepos(src, bl->x, bl->y, 1, 1)) {
|
||||
clif_blown(src);
|
||||
clif_skill_poseffect(src,skill_id,skill_lv,bl->x,bl->y,tick);
|
||||
if( skill_id == MH_TINDER_BREAKER ){
|
||||
type = SC_TINDER_BREAKER2;
|
||||
if( unit_movepos(src, bl->x, bl->y, 1, 1) ){
|
||||
clif_blown(src);
|
||||
clif_skill_poseffect(src,skill_id,skill_lv,bl->x,bl->y,tick);
|
||||
}
|
||||
}else if( skill_id == MH_CBC ){
|
||||
type = SC_CBC;
|
||||
}else if( skill_id == MH_EQC ){
|
||||
type = SC_EQC;
|
||||
}
|
||||
clif_skill_nodamage(src,bl,skill_id,skill_lv,
|
||||
sc_start4(src,bl,status_skill2sc(skill_id),100,skill_lv,src->id,0,0,duration));
|
||||
|
||||
clif_skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,bl,type,100,skill_lv,src->id,0,0,duration));
|
||||
skill_attack(skill_get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag);
|
||||
}
|
||||
break;
|
||||
@ -6742,13 +6692,12 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
||||
break;
|
||||
|
||||
case SU_SCAROFTAROU:
|
||||
sc_start(src, bl, SC_BITESCAR, 10, skill_lv, skill_get_time(skill_id, skill_lv)); //! TODO: What's the activation chance for the Bite effect?
|
||||
skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
|
||||
break;
|
||||
case SU_SV_STEMSPEAR:
|
||||
if (skill_id == SU_SCAROFTAROU)
|
||||
sc_start(src, bl, status_skill2sc(skill_id), 10, skill_lv, skill_get_time(skill_id, skill_lv)); //! TODO: What's the activation chance for the Bite effect?
|
||||
else {
|
||||
if (sd && pc_checkskill(sd, SU_SPIRITOFLAND))
|
||||
sc_start(src, src, SC_DORAM_WALKSPEED, 100, 50, skill_get_time(SU_SPIRITOFLAND, 1));
|
||||
}
|
||||
if (sd && pc_checkskill(sd, SU_SPIRITOFLAND))
|
||||
sc_start(src, src, SC_DORAM_WALKSPEED, 100, 50, skill_get_time(SU_SPIRITOFLAND, 1));
|
||||
skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
|
||||
break;
|
||||
|
||||
@ -6903,7 +6852,7 @@ static int skill_apply_songs(struct block_list* target, va_list ap)
|
||||
default: // Buff/Debuff type songs
|
||||
if (skill_id == CG_HERMODE && src->id != target->id)
|
||||
status_change_clear_buffs(target, SCCB_BUFFS); // Should dispell only allies.
|
||||
return sc_start(src, target, status_skill2sc(skill_id), 100, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
return sc_start(src, target, skill_get_sc(skill_id), 100, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
}
|
||||
}
|
||||
|
||||
@ -7061,12 +7010,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
return skill_castend_pos2(src,bl->x,bl->y,skill_id,skill_lv,tick,0);
|
||||
}
|
||||
|
||||
type = status_skill2sc(skill_id);
|
||||
status_change *sc = status_get_sc(src);
|
||||
type = skill_get_sc(skill_id);
|
||||
tsc = status_get_sc(bl);
|
||||
tsce = (tsc && type != -1)?tsc->data[type]:NULL;
|
||||
tsce = (tsc && type != SC_NONE)?tsc->data[type]:NULL;
|
||||
|
||||
if (src!=bl && type > -1 &&
|
||||
if (src!=bl && type > SC_NONE &&
|
||||
CHK_ELEMENT((i = skill_get_ele(skill_id, skill_lv))) && i > ELE_NEUTRAL &&
|
||||
skill_get_inf(skill_id) != INF_SUPPORT_SKILL &&
|
||||
battle_attr_fix(NULL, NULL, 100, i, tstatus->def_ele, tstatus->ele_lv) <= 0)
|
||||
@ -7703,6 +7651,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
sc_start(src, bl, type, 100, skill_lv, skill_get_time2(skill_id, skill_lv));
|
||||
} else {
|
||||
uint16 climax_lv = 0, splash_size = skill_get_splash(skill_id, skill_lv);
|
||||
status_change *sc = status_get_sc(src);
|
||||
|
||||
if (sc && sc->data[SC_CLIMAX])
|
||||
climax_lv = sc->data[SC_CLIMAX]->val1;
|
||||
@ -7885,23 +7834,16 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)));
|
||||
break;
|
||||
|
||||
case AS_ENCHANTPOISON: // Prevent spamming [Valaris]
|
||||
if (sd && dstsd && dstsd->sc.count) {
|
||||
if (dstsd->sc.data[SC_FIREWEAPON] ||
|
||||
dstsd->sc.data[SC_WATERWEAPON] ||
|
||||
dstsd->sc.data[SC_WINDWEAPON] ||
|
||||
dstsd->sc.data[SC_EARTHWEAPON] ||
|
||||
dstsd->sc.data[SC_SHADOWWEAPON] ||
|
||||
dstsd->sc.data[SC_GHOSTWEAPON]
|
||||
// dstsd->sc.data[SC_ENCPOISON] //People say you should be able to recast to lengthen the timer. [Skotlex]
|
||||
) {
|
||||
clif_skill_nodamage(src,bl,skill_id,skill_lv,0);
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
||||
break;
|
||||
case AS_ENCHANTPOISON:
|
||||
if( sc_start( src, bl, type, 100, skill_lv, skill_get_time( skill_id, skill_lv ) ) ){
|
||||
clif_skill_nodamage( src, bl, skill_id, skill_lv, 1 );
|
||||
}else{
|
||||
clif_skill_nodamage( src, bl, skill_id, skill_lv, 0 );
|
||||
|
||||
if( sd != nullptr ){
|
||||
clif_skill_fail( sd, skill_id, USESKILL_FAIL_LEVEL, 0 );
|
||||
}
|
||||
}
|
||||
clif_skill_nodamage(src,bl,skill_id,skill_lv,
|
||||
sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)));
|
||||
break;
|
||||
|
||||
case LK_TENSIONRELAX:
|
||||
@ -8544,7 +8486,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
}
|
||||
|
||||
if( skill_id == SP_SOULCOLLECT ){
|
||||
clif_skill_nodamage(src, bl, skill_id, skill_lv, sc_start2(src, bl, type, 100, skill_lv, pc_checkskill(sd, SP_SOULENERGY), max(1000, skill_get_time(skill_id, skill_lv))));
|
||||
clif_skill_nodamage(src, bl, skill_id, skill_lv, sc_start2(src, bl, type, 100, skill_lv, pc_checkskill(sd, SP_SOULENERGY), skill_get_time(skill_id, skill_lv)));
|
||||
}else{
|
||||
clif_skill_nodamage(src, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv)));
|
||||
}
|
||||
@ -9237,116 +9179,21 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
if(!tsc || !tsc->count)
|
||||
break;
|
||||
|
||||
for(i=0;i<SC_MAX;i++) {
|
||||
if (!tsc->data[i])
|
||||
//Statuses that can't be Dispelled
|
||||
for (const auto &it : status_db) {
|
||||
sc_type status = static_cast<sc_type>(it.first);
|
||||
|
||||
if (!tsc->data[status])
|
||||
continue;
|
||||
switch (i) {
|
||||
case SC_WEIGHT50: case SC_WEIGHT90: case SC_HALLUCINATION:
|
||||
case SC_STRIPWEAPON: case SC_STRIPSHIELD: case SC_STRIPARMOR:
|
||||
case SC_STRIPHELM: case SC_CP_WEAPON: case SC_CP_SHIELD:
|
||||
case SC_CP_ARMOR: case SC_CP_HELM: case SC_COMBO:
|
||||
case SC_STRFOOD: case SC_AGIFOOD: case SC_VITFOOD:
|
||||
case SC_INTFOOD: case SC_DEXFOOD: case SC_LUKFOOD:
|
||||
case SC_HITFOOD: case SC_FLEEFOOD: case SC_BATKFOOD:
|
||||
case SC_WATKFOOD: case SC_MATKFOOD: case SC_CRIFOOD:
|
||||
case SC_DANCING: case SC_EDP: case SC_AUTOBERSERK:
|
||||
case SC_CARTBOOST: case SC_MELTDOWN: case SC_SAFETYWALL:
|
||||
case SC_SMA: case SC_SPEEDUP0: case SC_NOCHAT:
|
||||
case SC_ANKLE: case SC_SPIDERWEB: case SC_JAILED:
|
||||
case SC_ITEMBOOST: case SC_EXPBOOST: case SC_LIFEINSURANCE:
|
||||
case SC_BOSSMAPINFO: case SC_PNEUMA: case SC_AUTOSPELL:
|
||||
case SC_INCHITRATE: case SC_INCATKRATE: case SC_NEN:
|
||||
case SC_READYSTORM: case SC_READYDOWN: case SC_READYTURN:
|
||||
case SC_READYCOUNTER: case SC_DODGE: case SC_WARM:
|
||||
/*case SC_SPEEDUP1:*/ case SC_AUTOTRADE: case SC_CRITICALWOUND:
|
||||
case SC_JEXPBOOST: case SC_INVINCIBLE: case SC_INVINCIBLEOFF:
|
||||
case SC_HELLPOWER: case SC_MANU_ATK: case SC_MANU_DEF:
|
||||
case SC_SPL_ATK: case SC_SPL_DEF: case SC_MANU_MATK:
|
||||
case SC_SPL_MATK: case SC_RICHMANKIM: case SC_ETERNALCHAOS:
|
||||
case SC_DRUMBATTLE: case SC_NIBELUNGEN: case SC_ROKISWEIL:
|
||||
case SC_INTOABYSS: case SC_SIEGFRIED: case SC_FOOD_STR_CASH:
|
||||
case SC_FOOD_AGI_CASH: case SC_FOOD_VIT_CASH: case SC_FOOD_DEX_CASH:
|
||||
case SC_FOOD_INT_CASH: case SC_FOOD_LUK_CASH: case SC_SEVENWIND:
|
||||
case SC_MIRACLE: case SC_S_LIFEPOTION: case SC_L_LIFEPOTION:
|
||||
case SC_INCHEALRATE: case SC_ELECTRICSHOCKER: case SC__STRIPACCESSORY:
|
||||
case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD: case SC_MINOR_BBQ:
|
||||
case SC_SIROMA_ICE_TEA: case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES:
|
||||
case SC_NEUTRALBARRIER_MASTER: case SC_NEUTRALBARRIER: case SC_STEALTHFIELD_MASTER:
|
||||
case SC_STEALTHFIELD: case SC_GIANTGROWTH: case SC_MILLENNIUMSHIELD:
|
||||
case SC_REFRESH: case SC_STONEHARDSKIN: case SC_VITALITYACTIVATION:
|
||||
case SC_FIGHTINGSPIRIT: case SC_ABUNDANCE: case SC__SHADOWFORM:
|
||||
case SC_RECOGNIZEDSPELL:case SC_LEADERSHIP: case SC_GLORYWOUNDS:
|
||||
case SC_SOULCOLD: case SC_HAWKEYES: case SC_REGENERATION:
|
||||
case SC_PUSH_CART: case SC_RAISINGDRAGON: case SC_GT_ENERGYGAIN:
|
||||
case SC_GT_CHANGE: case SC_GT_REVITALIZE: case SC_REFLECTDAMAGE:
|
||||
case SC_INSPIRATION: case SC_EXEEDBREAK: case SC_FORCEOFVANGUARD:
|
||||
case SC_BANDING: case SC_DUPLELIGHT: case SC_EXPIATIO:
|
||||
case SC_LAUDAAGNUS: case SC_LAUDARAMUS: case SC_GATLINGFEVER:
|
||||
case SC_INCREASING: case SC_ADJUSTMENT: case SC_MADNESSCANCEL:
|
||||
case SC_ANGEL_PROTECT: case SC_MONSTER_TRANSFORM: case SC_FULL_THROTTLE:
|
||||
case SC_REBOUND: case SC_TELEKINESIS_INTENSE: case SC_MOONSTAR:
|
||||
case SC_SUPER_STAR: case SC_ALL_RIDING: case SC_MTF_ASPD:
|
||||
case SC_MTF_RANGEATK: case SC_MTF_MATK: case SC_MTF_MLEATKED:
|
||||
case SC_MTF_CRIDAMAGE: case SC_HEAT_BARREL:
|
||||
case SC_P_ALTER: case SC_E_CHAIN: case SC_C_MARKER:
|
||||
case SC_B_TRAP: case SC_H_MINE: case SC_STRANGELIGHTS:
|
||||
case SC_DECORATION_OF_MUSIC: case SC_GN_CARTBOOST: case SC_CHASEWALK2:
|
||||
case SC_ACTIVE_MONSTER_TRANSFORM: case SC_DORAM_BUF_01: case SC_DORAM_BUF_02:
|
||||
case SC_SPORE_EXPLOSION:
|
||||
case SC_NEWMOON: case SC_FLASHKICK: case SC_NOVAEXPLOSING:
|
||||
case SC_SOULUNITY: case SC_SOULSHADOW: case SC_SOULFAIRY:
|
||||
case SC_SOULFALCON: case SC_SOULGOLEM: case SC_USE_SKILL_SP_SPA:
|
||||
case SC_USE_SKILL_SP_SHA: case SC_SP_SHA:
|
||||
// 4th Jobs
|
||||
case SC_SERVANTWEAPON: case SC_SERVANT_SIGN: case SC_GUARD_STANCE:
|
||||
case SC_ATTACK_STANCE: case SC_PROTECTSHADOWEQUIP: case SC_SHADOW_STRIP:
|
||||
case SC_ABYSSFORCEWEAPON:
|
||||
#ifdef RENEWAL
|
||||
case SC_EXTREMITYFIST2:
|
||||
#endif
|
||||
case SC_HIDING: case SC_CLOAKING: case SC_CHASEWALK:
|
||||
case SC_CLOAKINGEXCEED: case SC__INVISIBILITY: case SC_UTSUSEMI:
|
||||
case SC_MTF_ASPD2: case SC_MTF_RANGEATK2: case SC_MTF_MATK2:
|
||||
case SC_2011RWC_SCROLL: case SC_JP_EVENT04: case SC_MTF_MHP:
|
||||
case SC_MTF_MSP: case SC_MTF_PUMPKIN: case SC_MTF_HITFLEE:
|
||||
case SC_ATTHASTE_CASH: case SC_ARMOR_ELEMENT_WATER: case SC_REUSE_REFRESH:
|
||||
case SC_REUSE_LIMIT_A: case SC_REUSE_LIMIT_B: case SC_REUSE_LIMIT_C:
|
||||
case SC_REUSE_LIMIT_D: case SC_REUSE_LIMIT_E: case SC_REUSE_LIMIT_F:
|
||||
case SC_REUSE_LIMIT_G: case SC_REUSE_LIMIT_H: case SC_REUSE_LIMIT_MTF:
|
||||
case SC_REUSE_LIMIT_ASPD_POTION: case SC_REUSE_MILLENNIUMSHIELD: case SC_REUSE_CRUSHSTRIKE:
|
||||
case SC_REUSE_STORMBLAST: case SC_ALL_RIDING_REUSE_LIMIT:
|
||||
case SC_SPRITEMABLE: case SC_BITESCAR: case SC_CRUSHSTRIKE:
|
||||
case SC_QUEST_BUFF1: case SC_QUEST_BUFF2: case SC_QUEST_BUFF3:
|
||||
case SC_ARMOR_ELEMENT_EARTH: case SC_ARMOR_ELEMENT_FIRE: case SC_ARMOR_ELEMENT_WIND:
|
||||
case SC_ENTRY_QUEUE_APPLY_DELAY: case SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT:
|
||||
case SC_MADOGEAR:
|
||||
// Clans
|
||||
case SC_CLAN_INFO:
|
||||
case SC_SWORDCLAN:
|
||||
case SC_ARCWANDCLAN:
|
||||
case SC_GOLDENMACECLAN:
|
||||
case SC_CROSSBOWCLAN:
|
||||
case SC_JUMPINGCLAN:
|
||||
case SC_DAILYSENDMAILCNT:
|
||||
case SC_WEDDING: case SC_XMAS: case SC_SUMMER:
|
||||
case SC_DRESSUP: case SC_HANBOK: case SC_OKTOBERFEST:
|
||||
case SC_LHZ_DUN_N1: case SC_LHZ_DUN_N2: case SC_LHZ_DUN_N3: case SC_LHZ_DUN_N4:
|
||||
case SC_REUSE_LIMIT_LUXANIMA: case SC_LUXANIMA: case SC_SOULENERGY:
|
||||
case SC_EP16_2_BUFF_SS: case SC_EP16_2_BUFF_SC: case SC_EP16_2_BUFF_AC:
|
||||
case SC_EMERGENCY_MOVE: case SC_HOMUN_TIME:
|
||||
case SC_PACKING_ENVELOPE1: case SC_PACKING_ENVELOPE2: case SC_PACKING_ENVELOPE3:
|
||||
case SC_PACKING_ENVELOPE4: case SC_PACKING_ENVELOPE5: case SC_PACKING_ENVELOPE6:
|
||||
case SC_PACKING_ENVELOPE7: case SC_PACKING_ENVELOPE8: case SC_PACKING_ENVELOPE9: case SC_PACKING_ENVELOPE10:
|
||||
continue;
|
||||
case SC_WHISTLE:
|
||||
case SC_ASSNCROS:
|
||||
case SC_POEMBRAGI:
|
||||
case SC_APPLEIDUN:
|
||||
case SC_HUMMING:
|
||||
case SC_DONTFORGETME:
|
||||
case SC_FORTUNE:
|
||||
case SC_SERVICE4U:
|
||||
if (!battle_config.dispel_song || tsc->data[i]->val4 == 0)
|
||||
|
||||
if (it.second->flag[SCF_NODISPELL])
|
||||
continue;
|
||||
switch (status) {
|
||||
// bugreport:4888 these songs may only be dispelled if you're not in their song area anymore
|
||||
case SC_WHISTLE: case SC_ASSNCROS: case SC_POEMBRAGI:
|
||||
case SC_APPLEIDUN: case SC_HUMMING: case SC_DONTFORGETME:
|
||||
case SC_FORTUNE: case SC_SERVICE4U:
|
||||
if (!battle_config.dispel_song || tsc->data[status]->val4 == 0)
|
||||
continue; //If in song area don't end it, even if config enabled
|
||||
break;
|
||||
case SC_ASSUMPTIO:
|
||||
@ -9354,8 +9201,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if(i == SC_BERSERK) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0.
|
||||
status_change_end(bl, (sc_type)i, INVALID_TIMER);
|
||||
if (i == SC_BERSERK || i == SC_SATURDAYNIGHTFEVER)
|
||||
tsc->data[status]->val2 = 0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0.
|
||||
status_change_end(bl, status, INVALID_TIMER);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -10161,7 +10009,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
break;
|
||||
}
|
||||
if (tsc) {
|
||||
if (tsc->data[status_skill2sc(skill_id)]) { // Allow refreshing an already active soul link.
|
||||
if (tsc->data[skill_get_sc(skill_id)]) { // Allow refreshing an already active soul link.
|
||||
clif_skill_nodamage(src, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv)));
|
||||
break;
|
||||
} else if (tsc->data[SC_SPIRIT] || tsc->data[SC_SOULGOLEM] || tsc->data[SC_SOULSHADOW] || tsc->data[SC_SOULFALCON] || tsc->data[SC_SOULFAIRY]) { // Soul links from Soul Linker and Soul Reaper skills don't stack.
|
||||
@ -10190,7 +10038,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
if (tsce) {
|
||||
if(sd)
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
||||
status_change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,10000,8);
|
||||
status_change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,10000,SCSTART_NORATEDEF);
|
||||
status_change_end(bl, SC_SWOO, INVALID_TIMER);
|
||||
break;
|
||||
}
|
||||
@ -10825,106 +10673,32 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
|
||||
if(!tsc || !tsc->count)
|
||||
break;
|
||||
for( i = 0; i < SC_MAX; i++ ) {
|
||||
if (!tsc->data[i])
|
||||
|
||||
//Statuses change that can't be removed by Cleareance
|
||||
for (const auto &it : status_db) {
|
||||
sc_type status = static_cast<sc_type>(it.first);
|
||||
|
||||
if (!tsc->data[status])
|
||||
continue;
|
||||
switch (i) {
|
||||
case SC_WEIGHT50: case SC_WEIGHT90: case SC_HALLUCINATION:
|
||||
case SC_STRIPWEAPON: case SC_STRIPSHIELD: case SC_STRIPARMOR:
|
||||
case SC_STRIPHELM: case SC_CP_WEAPON: case SC_CP_SHIELD:
|
||||
case SC_CP_ARMOR: case SC_CP_HELM: case SC_COMBO:
|
||||
case SC_STRFOOD: case SC_AGIFOOD: case SC_VITFOOD:
|
||||
case SC_INTFOOD: case SC_DEXFOOD: case SC_LUKFOOD:
|
||||
case SC_HITFOOD: case SC_FLEEFOOD: case SC_BATKFOOD:
|
||||
case SC_WATKFOOD: case SC_MATKFOOD: case SC_CRIFOOD:
|
||||
case SC_DANCING: case SC_SPIRIT: case SC_AUTOBERSERK:
|
||||
case SC_CARTBOOST: case SC_MELTDOWN: case SC_SAFETYWALL:
|
||||
case SC_SMA: case SC_SPEEDUP0: case SC_NOCHAT:
|
||||
case SC_ANKLE: case SC_SPIDERWEB: case SC_JAILED:
|
||||
case SC_ITEMBOOST: case SC_EXPBOOST: case SC_LIFEINSURANCE:
|
||||
case SC_BOSSMAPINFO: case SC_PNEUMA: case SC_AUTOSPELL:
|
||||
case SC_INCHITRATE: case SC_INCATKRATE: case SC_NEN:
|
||||
case SC_READYSTORM: case SC_READYDOWN: case SC_READYTURN:
|
||||
case SC_READYCOUNTER: case SC_DODGE: case SC_WARM:
|
||||
/*case SC_SPEEDUP1:*/ case SC_AUTOTRADE: case SC_CRITICALWOUND:
|
||||
case SC_JEXPBOOST: case SC_INVINCIBLE: case SC_INVINCIBLEOFF:
|
||||
case SC_HELLPOWER: case SC_MANU_ATK: case SC_MANU_DEF:
|
||||
case SC_SPL_ATK: case SC_SPL_DEF: case SC_MANU_MATK:
|
||||
case SC_SPL_MATK: case SC_RICHMANKIM: case SC_ETERNALCHAOS:
|
||||
case SC_DRUMBATTLE: case SC_NIBELUNGEN: case SC_ROKISWEIL:
|
||||
case SC_INTOABYSS: case SC_SIEGFRIED: case SC_WHISTLE:
|
||||
case SC_ASSNCROS: case SC_POEMBRAGI: case SC_APPLEIDUN:
|
||||
case SC_HUMMING: case SC_DONTFORGETME: case SC_FORTUNE:
|
||||
case SC_SERVICE4U: case SC_FOOD_STR_CASH: case SC_FOOD_AGI_CASH:
|
||||
case SC_FOOD_VIT_CASH: case SC_FOOD_DEX_CASH: case SC_FOOD_INT_CASH:
|
||||
case SC_FOOD_LUK_CASH: case SC_ELECTRICSHOCKER: case SC_BITE:
|
||||
case SC__STRIPACCESSORY: case SC__ENERVATION: case SC__GROOMY:
|
||||
case SC__IGNORANCE: case SC__LAZINESS: case SC__UNLUCKY:
|
||||
case SC__WEAKNESS: case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD:
|
||||
case SC_MAGNETICFIELD: case SC_MINOR_BBQ: case SC_SIROMA_ICE_TEA:
|
||||
case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES: case SC_NEUTRALBARRIER_MASTER:
|
||||
case SC_NEUTRALBARRIER: case SC_STEALTHFIELD_MASTER: case SC_STEALTHFIELD:
|
||||
case SC_LEADERSHIP: case SC_GLORYWOUNDS: case SC_SOULCOLD:
|
||||
case SC_HAWKEYES: case SC_REGENERATION: case SC_SEVENWIND:
|
||||
case SC_MIRACLE: case SC_S_LIFEPOTION: case SC_L_LIFEPOTION:
|
||||
case SC_INCHEALRATE: case SC_PUSH_CART: case SC_PARTYFLEE:
|
||||
case SC_RAISINGDRAGON: case SC_GT_REVITALIZE: case SC_GT_ENERGYGAIN:
|
||||
case SC_GT_CHANGE: case SC_ANGEL_PROTECT: case SC_MONSTER_TRANSFORM:
|
||||
case SC_FULL_THROTTLE: case SC_REBOUND: case SC_TELEKINESIS_INTENSE:
|
||||
case SC_MOONSTAR: case SC_SUPER_STAR: case SC_ALL_RIDING:
|
||||
case SC_MTF_ASPD: case SC_MTF_RANGEATK: case SC_MTF_MATK:
|
||||
case SC_MTF_MLEATKED: case SC_MTF_CRIDAMAGE: case SC_HEAT_BARREL:
|
||||
case SC_P_ALTER: case SC_E_CHAIN:
|
||||
case SC_C_MARKER: case SC_B_TRAP: case SC_H_MINE:
|
||||
case SC_NEWMOON: case SC_FLASHKICK: case SC_DIMENSION:
|
||||
case SC_NOVAEXPLOSING:
|
||||
case SC_SOULUNITY: case SC_SOULSHADOW: case SC_SOULFAIRY:
|
||||
case SC_SOULFALCON: case SC_SOULGOLEM: case SC_USE_SKILL_SP_SPA:
|
||||
case SC_USE_SKILL_SP_SHA: case SC_SP_SHA:
|
||||
case SC_STRANGELIGHTS: case SC_DECORATION_OF_MUSIC: case SC_GN_CARTBOOST:
|
||||
case SC_RECOGNIZEDSPELL: case SC_CHASEWALK2: case SC_ACTIVE_MONSTER_TRANSFORM:
|
||||
case SC_SPORE_EXPLOSION:
|
||||
// 4th Jobs
|
||||
case SC_SERVANTWEAPON: case SC_SERVANT_SIGN: case SC_GUARD_STANCE:
|
||||
case SC_ATTACK_STANCE: case SC_PROTECTSHADOWEQUIP: case SC_SHADOW_STRIP:
|
||||
case SC_ABYSSFORCEWEAPON:
|
||||
#ifdef RENEWAL
|
||||
case SC_EXTREMITYFIST2:
|
||||
#endif
|
||||
case SC_HIDING: case SC_CLOAKING: case SC_CHASEWALK:
|
||||
case SC_CLOAKINGEXCEED: case SC__INVISIBILITY: case SC_UTSUSEMI:
|
||||
case SC_MTF_ASPD2: case SC_MTF_RANGEATK2: case SC_MTF_MATK2:
|
||||
case SC_2011RWC_SCROLL: case SC_JP_EVENT04: case SC_MTF_MHP:
|
||||
case SC_MTF_MSP: case SC_MTF_PUMPKIN: case SC_MTF_HITFLEE:
|
||||
case SC_ATTHASTE_CASH: case SC_REUSE_REFRESH:
|
||||
case SC_REUSE_LIMIT_A: case SC_REUSE_LIMIT_B: case SC_REUSE_LIMIT_C:
|
||||
case SC_REUSE_LIMIT_D: case SC_REUSE_LIMIT_E: case SC_REUSE_LIMIT_F:
|
||||
case SC_REUSE_LIMIT_G: case SC_REUSE_LIMIT_H: case SC_REUSE_LIMIT_MTF:
|
||||
case SC_REUSE_LIMIT_ASPD_POTION: case SC_REUSE_MILLENNIUMSHIELD: case SC_REUSE_CRUSHSTRIKE:
|
||||
case SC_REUSE_STORMBLAST: case SC_ALL_RIDING_REUSE_LIMIT:
|
||||
case SC_SPRITEMABLE: case SC_DORAM_BUF_01: case SC_DORAM_BUF_02:
|
||||
case SC_QUEST_BUFF1: case SC_QUEST_BUFF2: case SC_QUEST_BUFF3:
|
||||
case SC_CLAN_INFO: case SC_SWORDCLAN: case SC_ARCWANDCLAN:
|
||||
case SC_GOLDENMACECLAN: case SC_CROSSBOWCLAN:
|
||||
case SC_DAILYSENDMAILCNT:
|
||||
case SC_WEDDING: case SC_XMAS: case SC_SUMMER:
|
||||
case SC_DRESSUP: case SC_HANBOK: case SC_OKTOBERFEST:
|
||||
case SC_LHZ_DUN_N1: case SC_LHZ_DUN_N2: case SC_LHZ_DUN_N3: case SC_LHZ_DUN_N4:
|
||||
case SC_ENTRY_QUEUE_APPLY_DELAY: case SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT:
|
||||
case SC_REUSE_LIMIT_LUXANIMA: case SC_LUXANIMA: case SC_SOULENERGY:
|
||||
case SC_EP16_2_BUFF_SS: case SC_EP16_2_BUFF_SC: case SC_EP16_2_BUFF_AC:
|
||||
case SC_EMERGENCY_MOVE: case SC_MADOGEAR: case SC_HOMUN_TIME:
|
||||
case SC_PACKING_ENVELOPE1: case SC_PACKING_ENVELOPE2: case SC_PACKING_ENVELOPE3:
|
||||
case SC_PACKING_ENVELOPE4: case SC_PACKING_ENVELOPE5: case SC_PACKING_ENVELOPE6:
|
||||
case SC_PACKING_ENVELOPE7: case SC_PACKING_ENVELOPE8: case SC_PACKING_ENVELOPE9: case SC_PACKING_ENVELOPE10:
|
||||
|
||||
if (it.second->flag[SCF_NOCLEARANCE])
|
||||
continue;
|
||||
case SC_ASSUMPTIO:
|
||||
if( bl->type == BL_MOB )
|
||||
continue;
|
||||
break;
|
||||
|
||||
switch (status) {
|
||||
case SC_WHISTLE: case SC_ASSNCROS: case SC_POEMBRAGI:
|
||||
case SC_APPLEIDUN: case SC_HUMMING: case SC_DONTFORGETME:
|
||||
case SC_FORTUNE: case SC_SERVICE4U:
|
||||
if (!battle_config.dispel_song || tsc->data[status]->val4 == 0)
|
||||
continue; //If in song area don't end it, even if config enabled
|
||||
break;
|
||||
case SC_ASSUMPTIO:
|
||||
if (bl->type == BL_MOB)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if(i == SC_BERSERK) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0.
|
||||
status_change_end(bl,(sc_type)i,INVALID_TIMER);
|
||||
if (i == SC_BERSERK || i == SC_SATURDAYNIGHTFEVER)
|
||||
tsc->data[status]->val2 = 0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0.
|
||||
status_change_end(bl,status,INVALID_TIMER);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -11929,7 +11703,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
struct status_change *sc = status_get_sc(&ele->bl);
|
||||
|
||||
if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) {
|
||||
elemental_clean_single_effect(ele, skill_id);
|
||||
status_change_end(src,type,INVALID_TIMER);
|
||||
status_change_end(bl,type2,INVALID_TIMER);
|
||||
} else {
|
||||
clif_skill_nodamage(src,src,skill_id,skill_lv,1);
|
||||
if (!(skill_id >= EM_EL_FLAMETECHNIC && skill_id <= EM_EL_DEADLY_POISON))
|
||||
@ -11957,7 +11732,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
|
||||
clif_skill_nodamage(src,src,skill_id,skill_lv,1);
|
||||
if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) {
|
||||
elemental_clean_single_effect(ele, skill_id);
|
||||
status_change_end(bl,type,INVALID_TIMER);
|
||||
status_change_end(src,type2,INVALID_TIMER);
|
||||
} else {
|
||||
// This not heals at the end.
|
||||
clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, DMG_SINGLE);
|
||||
@ -13354,9 +13130,8 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
||||
sd = BL_CAST(BL_PC, src);
|
||||
|
||||
sc = status_get_sc(src);
|
||||
status_data *sstatus = status_get_status_data(src);
|
||||
type = status_skill2sc(skill_id);
|
||||
sce = (sc && type != -1)?sc->data[type]:NULL;
|
||||
type = skill_get_sc(skill_id);
|
||||
sce = (sc && type != SC_NONE)?sc->data[type]:NULL;
|
||||
|
||||
switch (skill_id) { //Skill effect.
|
||||
case WZ_METEOR:
|
||||
@ -13746,7 +13521,9 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
||||
// Final heal increased by HPlus.
|
||||
// Is this the right place for this??? [Rytech]
|
||||
// Can HPlus also affect SP recovery???
|
||||
if (sd && sstatus->hplus > 0) {
|
||||
status_data *sstatus = status_get_status_data(src);
|
||||
|
||||
if (sstatus && sstatus->hplus > 0) {
|
||||
potion_hp += potion_hp * sstatus->hplus / 100;
|
||||
potion_sp += potion_sp * sstatus->hplus / 100;
|
||||
}
|
||||
@ -14283,7 +14060,7 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( ( sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING ) || sd->sc.option&OPTION_HIDE ) {
|
||||
if( sd->sc.cant.cast ) {
|
||||
skill_failed(sd);
|
||||
return 0;
|
||||
}
|
||||
@ -15134,7 +14911,7 @@ static int skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, t_
|
||||
if (sc && sc->data[SC_HOVERING] && skill->inf2[INF2_IGNOREHOVERING])
|
||||
return 0; // Under Hovering characters are immune to select trap and ground target skills.
|
||||
|
||||
type = status_skill2sc(sg->skill_id);
|
||||
type = skill_get_sc(sg->skill_id);
|
||||
sce = (sc && type != SC_NONE) ? sc->data[type] : NULL;
|
||||
skill_id = sg->skill_id; //In case the group is deleted, we need to return the correct skill id, still.
|
||||
switch (sg->unit_id) {
|
||||
@ -15463,7 +15240,7 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, t_t
|
||||
tsc = status_get_sc(bl);
|
||||
sc = status_get_sc(ss);
|
||||
tstatus = status_get_status_data(bl);
|
||||
type = status_skill2sc(sg->skill_id);
|
||||
type = skill_get_sc(sg->skill_id);
|
||||
skill_id = sg->skill_id;
|
||||
|
||||
std::bitset<INF2_MAX> inf2 = skill_db.find(skill_id)->inf2;
|
||||
@ -16234,8 +16011,8 @@ int skill_unit_onout(struct skill_unit *src, struct block_list *bl, t_tick tick)
|
||||
return 0;
|
||||
|
||||
sc = status_get_sc(bl);
|
||||
type = status_skill2sc(sg->skill_id);
|
||||
sce = (sc && type != -1)?sc->data[type]:NULL;
|
||||
type = skill_get_sc(sg->skill_id);
|
||||
sce = (sc && type != SC_NONE)?sc->data[type]:NULL;
|
||||
|
||||
if (bl->prev == NULL || (status_isdead(bl) && sg->unit_id != UNT_ANKLESNARE)) //Need to delete the trap if the source died.
|
||||
return 0;
|
||||
@ -16265,8 +16042,8 @@ int skill_unit_onout(struct skill_unit *src, struct block_list *bl, t_tick tick)
|
||||
{
|
||||
for(uint16 i = BA_WHISTLE; i <= DC_SERVICEFORYOU; i++) {
|
||||
if(skill_get_inf2(i, INF2_ISSONG)) {
|
||||
type = status_skill2sc(i);
|
||||
sce = (sc && type != -1)?sc->data[type]:NULL;
|
||||
type = skill_get_sc(i);
|
||||
sce = (sc && type != SC_NONE)?sc->data[type]:NULL;
|
||||
if(sce)
|
||||
return i;
|
||||
}
|
||||
@ -16302,8 +16079,8 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, t_tick tick)
|
||||
if (sc && !sc->count)
|
||||
sc = NULL;
|
||||
|
||||
type = status_skill2sc(skill_id);
|
||||
sce = (sc && type != -1)?sc->data[type]:NULL;
|
||||
type = skill_get_sc(skill_id);
|
||||
sce = (sc && type != SC_NONE)?sc->data[type]:NULL;
|
||||
|
||||
switch (skill_id)
|
||||
{
|
||||
@ -16368,8 +16145,8 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, t_tick tick)
|
||||
{
|
||||
for(uint16 i = BA_WHISTLE; i <= DC_SERVICEFORYOU; i++){
|
||||
if(skill_get_inf2(i, INF2_ISSONG)){
|
||||
type = status_skill2sc(i);
|
||||
sce = (sc && type != -1)?sc->data[type]:NULL;
|
||||
type = skill_get_sc(i);
|
||||
sce = (sc && type != SC_NONE)?sc->data[type]:NULL;
|
||||
if(sce && !sce->val4){ //We don't want dissonance updating this anymore
|
||||
delete_timer(sce->timer, status_change_timer);
|
||||
sce->val4 = 1; //Store the fact that this is a "reduced" duration effect.
|
||||
@ -16560,7 +16337,7 @@ int skill_check_condition_char_sub (struct block_list *bl, va_list ap)
|
||||
if(pc_isdead(tsd))
|
||||
return 0;
|
||||
|
||||
if (tsd->sc.data[SC_SILENCE] || ( tsd->sc.opt1 && tsd->sc.opt1 != OPT1_BURNING ))
|
||||
if (tsd->sc.cant.cast)
|
||||
return 0;
|
||||
|
||||
if( is_chorus ) {
|
||||
@ -20299,10 +20076,9 @@ int skill_delunit(struct skill_unit* unit)
|
||||
case SC_ESCAPE:
|
||||
{
|
||||
struct block_list* target = map_id2bl(group->val2);
|
||||
enum sc_type type = status_skill2sc(group->skill_id);
|
||||
|
||||
if( target )
|
||||
status_change_end(target, type, INVALID_TIMER);
|
||||
status_change_end(target, SC_ANKLE, INVALID_TIMER);
|
||||
}
|
||||
break;
|
||||
case WZ_ICEWALL:
|
||||
@ -20529,15 +20305,21 @@ int skill_delunitgroup_(std::shared_ptr<s_skill_unit_group> group, const char* f
|
||||
break;
|
||||
case SG_SUN_WARM:
|
||||
case SG_MOON_WARM:
|
||||
case SG_STAR_WARM:
|
||||
case LG_BANDING:
|
||||
{
|
||||
case SG_STAR_WARM: {
|
||||
status_change *sc = status_get_sc(src);
|
||||
sc_type type = status_skill2sc(group->skill_id);
|
||||
|
||||
if (sc && sc->data[type]) {
|
||||
sc->data[type]->val4 = 0;
|
||||
status_change_end(src, type, INVALID_TIMER);
|
||||
if (sc && sc->data[SC_WARM]) {
|
||||
sc->data[SC_WARM]->val4 = 0;
|
||||
status_change_end(src, SC_WARM, INVALID_TIMER);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LG_BANDING: {
|
||||
status_change *sc = status_get_sc(src);
|
||||
|
||||
if (sc && sc->data[SC_BANDING]) {
|
||||
sc->data[SC_BANDING]->val4 = 0;
|
||||
status_change_end(src, SC_BANDING, INVALID_TIMER);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -22118,12 +21900,11 @@ void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id)
|
||||
status_change_end(bl, SC_MAGICPOWER, INVALID_TIMER);
|
||||
} else {
|
||||
sc->data[SC_MAGICPOWER]->val4 = 1;
|
||||
status_calc_bl(bl, status_sc2scb_flag(SC_MAGICPOWER));
|
||||
status_calc_bl(bl, status_db.getCalcFlag(SC_MAGICPOWER));
|
||||
if(bl->type == BL_PC){// update current display.
|
||||
clif_updatestatus(((TBL_PC *)bl),SP_MATK1);
|
||||
clif_updatestatus(((TBL_PC *)bl),SP_MATK2);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -23138,6 +22919,10 @@ int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) {
|
||||
*/
|
||||
int skill_disable_check(struct status_change *sc, uint16 skill_id)
|
||||
{
|
||||
enum sc_type type = skill_get_sc(skill_id);
|
||||
|
||||
if (type <= SC_NONE || type >= SC_MAX)
|
||||
return 0;
|
||||
switch( skill_id ) { //HP & SP Consumption Check
|
||||
case BS_MAXIMIZE:
|
||||
case NV_TRICKDEAD:
|
||||
@ -23168,11 +22953,11 @@ int skill_disable_check(struct status_change *sc, uint16 skill_id)
|
||||
case SP_SOULCOLLECT:
|
||||
case IG_GUARD_STANCE:
|
||||
case IG_ATTACK_STANCE:
|
||||
if( sc->data[status_skill2sc(skill_id)] )
|
||||
if( sc->data[type] )
|
||||
return 1;
|
||||
break;
|
||||
|
||||
// These 2 skills contain a master and are not correctly pulled using skill2sc
|
||||
// These 2 skills contain a master and are not correctly pulled using skill_get_sc
|
||||
case NC_NEUTRALBARRIER:
|
||||
if( sc->data[SC_NEUTRALBARRIER_MASTER] )
|
||||
return 1;
|
||||
@ -24226,6 +24011,31 @@ uint64 SkillDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
}
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "Status")) {
|
||||
std::string status;
|
||||
|
||||
if (!this->asString(node, "Status", status))
|
||||
return 0;
|
||||
|
||||
std::string status_constant = "SC_" + status;
|
||||
int64 constant;
|
||||
|
||||
if (!script_get_constant(status_constant.c_str(), &constant)) {
|
||||
this->invalidWarning(node["Status"], "Status %s is invalid.\n", status.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (constant < SC_NONE || constant >= SC_MAX) {
|
||||
this->invalidWarning(node["Status"], "Status %s is unknown. Defaulting to SC_NONE.\n", status.c_str());
|
||||
constant = SC_NONE;
|
||||
}
|
||||
|
||||
skill->sc = static_cast<sc_type>(constant);
|
||||
} else {
|
||||
if (!exists)
|
||||
skill->sc = SC_NONE;
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
this->put(skill_id, skill);
|
||||
this->skilldb_id2idx[skill_id] = this->skill_num;
|
||||
@ -24722,15 +24532,8 @@ static bool skill_parse_row_skilldamage(char* split[], int columns, int current)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*===============================
|
||||
* DB reading.
|
||||
* skill_db.yml
|
||||
* skill_nocast_db.txt
|
||||
* produce_db.txt
|
||||
* create_arrow_db.txt
|
||||
*------------------------------*/
|
||||
static void skill_readdb(void)
|
||||
{
|
||||
/** Reads skill database files */
|
||||
static void skill_readdb(void) {
|
||||
int i;
|
||||
const char* dbsubpath[] = {
|
||||
"",
|
||||
@ -24757,6 +24560,7 @@ static void skill_readdb(void)
|
||||
safesnprintf(dbsubpath1,n1,"%s%s",db_path,dbsubpath[i]);
|
||||
safesnprintf(dbsubpath2,n1,"%s%s",db_path,dbsubpath[i]);
|
||||
}
|
||||
|
||||
sv_readdb(dbsubpath2, "skill_nocast_db.txt" , ',', 2, 2, -1, skill_parse_row_nocastdb, i > 0);
|
||||
|
||||
sv_readdb(dbsubpath2, "produce_db.txt" , ',', 5, 5+2*MAX_PRODUCE_RESOURCE, MAX_SKILL_PRODUCE_DB, skill_parse_row_producedb, i > 0);
|
||||
@ -24784,7 +24588,6 @@ void skill_reload (void) {
|
||||
skill_arrow_db.clear();
|
||||
|
||||
skill_readdb();
|
||||
initChangeTables(); // Re-init Status Change tables
|
||||
|
||||
/* lets update all players skill tree : so that if any skill modes were changed they're properly updated */
|
||||
s_mapiterator *iter = mapit_getallusers();
|
||||
|
@ -306,6 +306,7 @@ struct s_skill_db {
|
||||
int32 abra_probability[MAX_SKILL_LEVEL];
|
||||
s_skill_spellbook reading_spellbook;
|
||||
uint16 improvisedsong_rate;
|
||||
sc_type sc; ///< Default SC for skill
|
||||
};
|
||||
|
||||
class SkillDatabase : public TypesafeCachedYamlDatabase <uint16, s_skill_db> {
|
||||
@ -2634,6 +2635,7 @@ int skill_is_combo(uint16 skill_id);
|
||||
void skill_combo_toggle_inf(struct block_list* bl, uint16 skill_id, int inf);
|
||||
void skill_combo(struct block_list* src,struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, t_tick tick);
|
||||
|
||||
enum sc_type skill_get_sc(int16 skill_id);
|
||||
void skill_reveal_trap_inarea(struct block_list *src, int range, int x, int y);
|
||||
int skill_get_time3(struct map_data *mapdata, uint16 skill_id, uint16 skill_lv);
|
||||
|
||||
|
5173
src/map/status.cpp
5173
src/map/status.cpp
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,10 @@
|
||||
#ifndef STATUS_HPP
|
||||
#define STATUS_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <bitset>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "../common/database.hpp"
|
||||
@ -11,6 +15,7 @@
|
||||
#include "../common/timer.hpp"
|
||||
|
||||
#include "map.hpp"
|
||||
#include "script.hpp"
|
||||
|
||||
enum e_race2 : uint8;
|
||||
struct block_list;
|
||||
@ -246,7 +251,7 @@ enum sc_type : int16 {
|
||||
SC_ARMOR,
|
||||
SC_ARMOR_ELEMENT_WATER,
|
||||
SC_NOCHAT,
|
||||
SC_BABY,
|
||||
SC_PROTECTEXP,
|
||||
SC_AURABLADE,
|
||||
SC_PARRYING,
|
||||
SC_CONCENTRATION, //110
|
||||
@ -1175,7 +1180,7 @@ enum sc_type : int16 {
|
||||
};
|
||||
|
||||
/// Official status change ids, used to display status icons on the client.
|
||||
enum efst_types : short{
|
||||
enum efst_type : short{
|
||||
/// Do not modify code below this, until the end of the API hook, since it will be automatically generated again
|
||||
/// @APIHOOK_START(EFST_ENUM)
|
||||
EFST_BLANK = -1,
|
||||
@ -2552,7 +2557,8 @@ extern short current_equip_opt_index;
|
||||
//who were not on your field of sight when it happened)
|
||||
|
||||
///opt1: (BODYSTATE_*) Non stackable status changes.
|
||||
enum sc_opt1 {
|
||||
enum e_sc_opt1 : uint16 {
|
||||
OPT1_NONE = 0,
|
||||
OPT1_STONE = 1, //Petrified
|
||||
OPT1_FREEZE,
|
||||
OPT1_STUN,
|
||||
@ -2561,10 +2567,12 @@ enum sc_opt1 {
|
||||
OPT1_STONEWAIT = 6, //Petrifying
|
||||
OPT1_BURNING,
|
||||
OPT1_IMPRISON,
|
||||
OPT1_MAX
|
||||
};
|
||||
|
||||
///opt2: (HEALTHSTATE_*) Stackable status changes.
|
||||
enum sc_opt2 {
|
||||
enum e_sc_opt2 : uint16 {
|
||||
OPT2_NONE = 0x0,
|
||||
OPT2_POISON = 0x0001,
|
||||
OPT2_CURSE = 0x0002,
|
||||
OPT2_SILENCE = 0x0004,
|
||||
@ -2574,11 +2582,12 @@ enum sc_opt2 {
|
||||
OPT2_BLEEDING = 0x0040,
|
||||
OPT2_DPOISON = 0x0080,
|
||||
OPT2_FEAR = 0x0100,
|
||||
OPT2_MAX
|
||||
};
|
||||
|
||||
///opt3: (SHOW_EFST_*)
|
||||
enum sc_opt3 {
|
||||
OPT3_NORMAL = 0x00000000,
|
||||
enum e_sc_opt3 : uint32 {
|
||||
OPT3_NORMAL = 0x0,
|
||||
OPT3_QUICKEN = 0x00000001,
|
||||
OPT3_OVERTHRUST = 0x00000002,
|
||||
OPT3_ENERGYCOAT = 0x00000004,
|
||||
@ -2597,11 +2606,12 @@ enum sc_opt3 {
|
||||
OPT3_SOULLINK = 0x00008000,
|
||||
OPT3_UNDEAD = 0x00010000,
|
||||
OPT3_CONTRACT = 0x00020000,
|
||||
OPT3_MAX
|
||||
};
|
||||
|
||||
///Option (EFFECTSTATE_*)
|
||||
enum e_option {
|
||||
OPTION_NOTHING = 0x00000000,
|
||||
enum e_option : uint32 {
|
||||
OPTION_NOTHING = 0x0,
|
||||
OPTION_SIGHT = 0x00000001,
|
||||
OPTION_HIDE = 0x00000002,
|
||||
OPTION_CLOAK = 0x00000004,
|
||||
@ -2632,6 +2642,7 @@ enum e_option {
|
||||
OPTION_HANBOK = 0x08000000,
|
||||
OPTION_OKTOBERFEST = 0x10000000,
|
||||
OPTION_SUMMER2 = 0x20000000,
|
||||
OPTION_MAX,
|
||||
|
||||
// compound constant for older carts
|
||||
OPTION_CART = OPTION_CART1|OPTION_CART2|OPTION_CART3|OPTION_CART4|OPTION_CART5,
|
||||
@ -2641,15 +2652,6 @@ enum e_option {
|
||||
OPTION_COSTUME = OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK|OPTION_OKTOBERFEST|OPTION_SUMMER2,
|
||||
};
|
||||
|
||||
enum e_option_change_flag : uint16 {
|
||||
OCF_NONE = 0x0,
|
||||
OCF_SEND_OPTION = 0x1,
|
||||
OCF_ONTOUCH = 0x2,
|
||||
OCF_UNIT_MOVE = 0x4,
|
||||
OCF_NON_PLAYER = 0x8,
|
||||
OCF_SEND_LOOK = 0x10,
|
||||
};
|
||||
|
||||
///Defines for the manner system [Skotlex]
|
||||
enum manner_flags
|
||||
{
|
||||
@ -2661,23 +2663,38 @@ enum manner_flags
|
||||
};
|
||||
|
||||
/// Status Change State Flags
|
||||
enum scs_flag {
|
||||
SCS_NOMOVECOND = 0x00000001, ///< cond flag for nomove
|
||||
SCS_NOMOVE = 0x00000002, ///< unit unable to move
|
||||
SCS_NOPICKITEMCOND = 0x00000004, ///< cond flag for nopickitem
|
||||
SCS_NOPICKITEM = 0x00000008, ///< player unable to pick up items
|
||||
SCS_NODROPITEMCOND = 0x00000010, ///< cond flag for nodropitem
|
||||
SCS_NODROPITEM = 0x00000020, ///< player unable to drop items
|
||||
SCS_NOCASTCOND = 0x00000040, ///< cond flag for nocast
|
||||
SCS_NOCAST = 0x00000080, ///< unit unable to cast skills
|
||||
SCS_NOCHAT = 0x00000100, ///< unit can't talk
|
||||
SCS_NOCHATCOND = 0x00000200, ///< cond flag for notalk
|
||||
enum e_scs_flag : uint8 {
|
||||
SCS_NONE = 0,
|
||||
SCS_NOMOVECOND, ///< cond flag for SCS_NOMOVE
|
||||
SCS_NOMOVE, ///< unit unable to move
|
||||
SCS_NOPICKITEMCOND, ///< cond flag for SCS_NOPICKITEM
|
||||
SCS_NOPICKITEM, ///< player unable to pick up items
|
||||
SCS_NODROPITEMCOND, ///< cond flag for SCS_NODROPITEM
|
||||
SCS_NODROPITEM, ///< player unable to drop items
|
||||
SCS_NOCASTCOND, ///< cond flag for SCS_NOCAST
|
||||
SCS_NOCAST, ///< unit unable to cast skills
|
||||
SCS_NOCHAT, ///< unit can't talk
|
||||
SCS_NOCHATCOND, ///< cond flag for SCS_NOCHAT
|
||||
SCS_NOEQUIPITEM, ///< player can't puts on equip
|
||||
SCS_NOEQUIPITEMCOND, ///< cond flag for SCS_NOEQUIPITEM
|
||||
SCS_NOUNEQUIPITEM, ///< player can't puts off equip
|
||||
SCS_NOUNEQUIPITEMCOND, ///< cond flag for SCS_NOUNEQUIPITEM
|
||||
SCS_NOCONSUMEITEM, ///< player can't consumes equip
|
||||
SCS_NOCONSUMEITEMCOND, ///< cond flag for SCS_NOCONSUMEITEM
|
||||
SCS_NOATTACK, ///< unit can't attack
|
||||
SCS_NOATTACKCOND, ///< cond flag for SCS_NOATTACK
|
||||
SCS_NOWARP, ///< unit can't warp
|
||||
SCS_NOWARPCOND, ///< cond flag for SCS_NOWARP
|
||||
SCS_NODEATHPENALTY, ///< player doesn't experience EXP loss
|
||||
SCS_NODEATHPENALTYCOND, ///< cond flag for SCS_NODEATHPENALTYCOND
|
||||
SCS_NOINTERACT, ///< player can't sit/stand/talk to NPC
|
||||
SCS_NOINTERACTCOND, ///< cond flag for SCS_NOINTERACT
|
||||
SCS_MAX
|
||||
};
|
||||
|
||||
///Define flags for the status_calc_bl function. [Skotlex]
|
||||
enum scb_flag : uint64
|
||||
{ // Main Flags
|
||||
SCB_NONE = 0x00000000,
|
||||
enum e_scb_flag : uint64 {
|
||||
SCB_NONE = 0x0,
|
||||
SCB_BASE = 0x00000001,
|
||||
SCB_MAXHP = 0x00000002,
|
||||
SCB_MAXSP = 0x00000004,
|
||||
@ -2729,19 +2746,20 @@ enum scb_flag : uint64
|
||||
SCB_DYE = 0x080000000000, // force cloth-dye change to 0 to avoid client crashes.
|
||||
|
||||
// Special flags for updating all stat/sub-stat stuff on request.
|
||||
SCB_BATTLE = 0x07FFFFFFFFFE,// All except BASE and extra flags.
|
||||
SCB_ALL = 0x07FFFFFFFFFF// All except extra flags.
|
||||
SCB_BATTLE = 0x07FFFFFFFFFE, // All except BASE and extra flags.
|
||||
SCB_ALL = 0x07FFFFFFFFFF, // All except extra flags.
|
||||
SCB_MAX = 0x0FFFFFFFFFFF,
|
||||
};
|
||||
|
||||
enum e_status_calc_opt {
|
||||
enum e_status_calc_opt : uint8 {
|
||||
SCO_NONE = 0x0,
|
||||
SCO_FIRST = 0x1, ///< Trigger the calculations that should take place only onspawn/once, process base status initialization code
|
||||
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,
|
||||
enum e_status_change_start_flags : int64 {
|
||||
SCSTART_NONE = 0x0,
|
||||
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
|
||||
@ -2750,7 +2768,7 @@ enum e_status_change_start_flags {
|
||||
};
|
||||
|
||||
/// Enum for status_change_clear_buffs
|
||||
enum e_status_change_clear_buffs_flags {
|
||||
enum e_status_change_clear_buffs_flags : int64 {
|
||||
SCCB_BUFFS = 0x01,
|
||||
SCCB_DEBUFFS = 0x02,
|
||||
SCCB_REFRESH = 0x04,
|
||||
@ -2759,7 +2777,7 @@ enum e_status_change_clear_buffs_flags {
|
||||
};
|
||||
|
||||
///Enum for bonus_script's flag [Cydh]
|
||||
enum e_bonus_script_flags {
|
||||
enum e_bonus_script_flags : uint32 {
|
||||
BSF_REM_ON_DEAD = 0x001, ///< Removed when dead
|
||||
BSF_REM_ON_DISPELL = 0x002, ///< Removed by Dispell
|
||||
BSF_REM_ON_CLEARANCE = 0x004, ///< Removed by Clearance
|
||||
@ -2787,6 +2805,102 @@ enum e_status_bonus {
|
||||
STATUS_BONUS_RATE = 1,
|
||||
};
|
||||
|
||||
///Enum of Status Change Flags [Cydh]
|
||||
enum e_status_change_flag : uint16 {
|
||||
SCF_NONE = 0,
|
||||
SCF_BLEFFECT,
|
||||
SCF_DISPLAYPC,
|
||||
SCF_NOCLEARBUFF,
|
||||
SCF_NOREMOVEONDEAD,
|
||||
SCF_NODISPELL,
|
||||
SCF_NOCLEARANCE,
|
||||
SCF_NOBANISHINGBUSTER,
|
||||
SCF_NOSAVE,
|
||||
SCF_NOSAVEINFINITE,
|
||||
SCF_REMOVEONDAMAGED,
|
||||
SCF_REMOVEONREFRESH,
|
||||
SCF_REMOVEONLUXANIMA,
|
||||
SCF_STOPATTACKING,
|
||||
SCF_STOPCASTING,
|
||||
SCF_STOPWALKING,
|
||||
SCF_BOSSRESIST,
|
||||
SCF_MVPRESIST,
|
||||
SCF_SETSTAND,
|
||||
SCF_FAILEDMADO,
|
||||
SCF_DEBUFF,
|
||||
SCF_REMOVEONCHANGEMAP,
|
||||
SCF_REMOVEONMAPWARP,
|
||||
SCF_REMOVECHEMICALPROTECT,
|
||||
SCF_OVERLAPFAIL,
|
||||
SCF_OVERLAPIGNORELEVEL,
|
||||
SCF_SENDOPTION,
|
||||
SCF_ONTOUCH,
|
||||
SCF_UNITMOVE,
|
||||
SCF_NONPLAYER,
|
||||
SCF_SENDLOOK,
|
||||
SCF_DISPLAYNPC,
|
||||
SCF_REQUIREWEAPON,
|
||||
SCF_REQUIRESHIELD,
|
||||
SCF_MOBLOSETARGET,
|
||||
SCF_REMOVEELEMENTALOPTION,
|
||||
SCF_SUPERNOVICEANGEL,
|
||||
SCF_TAEKWONANGEL,
|
||||
SCF_MADOCANCEL,
|
||||
SCF_MADOENDCANCEL,
|
||||
SCF_RESTARTONMAPWARP,
|
||||
SCF_SPREADEFFECT,
|
||||
SCF_SENDVAL1,
|
||||
SCF_SENDVAL2,
|
||||
SCF_SENDVAL3,
|
||||
SCF_MAX
|
||||
};
|
||||
|
||||
/// Struct of SC configs [Cydh]
|
||||
struct s_status_change_db {
|
||||
sc_type type; ///< SC_
|
||||
efst_type icon; ///< EFST_
|
||||
std::bitset<SCS_MAX> state; ///< SCS_
|
||||
uint64 calc_flag; ///< SCB_ flags
|
||||
uint16 opt1; ///< OPT1_
|
||||
uint16 opt2; ///< OPT2_
|
||||
uint32 opt3; ///< OPT3_
|
||||
uint32 look; ///, OPTION_ Changelook
|
||||
std::bitset<SCF_MAX> flag; ///< SCF_ Flags, enum e_status_change_flag
|
||||
bool display; ///< Display status effect/icon (for certain state)
|
||||
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> 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
|
||||
t_tick min_duration; ///< Minimum duration effect (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> {
|
||||
public:
|
||||
StatusDatabase() : TypesafeCachedYamlDatabase("STATUS_DB", 1) {
|
||||
|
||||
}
|
||||
|
||||
const std::string getDefaultLocation() override;
|
||||
uint64 parseBodyNode(const YAML::Node &node) override;
|
||||
void loadingFinished() override;
|
||||
|
||||
// Determine who will receive a clif_status_change packet for effects that require one to display correctly
|
||||
uint16 StatusRelevantBLTypes[EFST_MAX];
|
||||
|
||||
// Extras
|
||||
efst_type getIcon(sc_type type);
|
||||
uint64 getCalcFlag(sc_type type);
|
||||
std::vector<sc_type> getEnd(sc_type type);
|
||||
uint16 getSkill(sc_type type);
|
||||
bool hasSCF(status_change *sc, e_status_change_flag flag);
|
||||
void removeByStatusFlag(block_list *bl, std::vector<e_status_change_flag> flag);
|
||||
void changeSkillTree(map_session_data *sd, int32 class_ = 0);
|
||||
bool validateStatus(sc_type type);
|
||||
};
|
||||
|
||||
extern StatusDatabase status_db;
|
||||
|
||||
/// Enum for status_calc_weight and status_calc_cart_weight
|
||||
enum e_status_calc_weight_opt {
|
||||
CALCWT_NONE = 0x0,
|
||||
@ -2824,14 +2938,6 @@ struct weapon_atk {
|
||||
#endif
|
||||
};
|
||||
|
||||
extern sc_type SkillStatusChangeTable[MAX_SKILL]; /// skill -> status
|
||||
extern int StatusIconChangeTable[SC_MAX]; /// status -> "icon" (icon is a bit of a misnomer, since there exist values with no icon associated)
|
||||
extern uint64 StatusChangeFlagTable[SC_MAX]; /// status -> flags
|
||||
extern int StatusSkillChangeTable[SC_MAX]; /// status -> skill
|
||||
extern int StatusRelevantBLTypes[EFST_MAX]; /// "icon" -> enum bl_type (for clif->status_change to identify for which bl types to send packets)
|
||||
extern unsigned int StatusChangeStateTable[SC_MAX]; /// status -> flags
|
||||
extern unsigned int StatusDisplayType[SC_MAX];
|
||||
|
||||
///For holding basic status (which can be modified by status changes)
|
||||
struct status_data {
|
||||
unsigned int
|
||||
@ -2938,11 +3044,18 @@ struct status_change {
|
||||
unsigned char count;
|
||||
//! TODO: See if it is possible to implement the following SC's without requiring extra parameters while the SC is inactive.
|
||||
struct {
|
||||
unsigned char move;
|
||||
unsigned char pickup;
|
||||
unsigned char drop;
|
||||
unsigned char cast;
|
||||
unsigned char chat;
|
||||
uint8 move;
|
||||
uint8 pickup;
|
||||
uint8 drop;
|
||||
uint8 cast;
|
||||
uint8 chat;
|
||||
uint8 equip;
|
||||
uint8 unequip;
|
||||
uint8 consume;
|
||||
uint8 attack;
|
||||
uint8 warp;
|
||||
uint8 deathpenalty;
|
||||
uint8 interact;
|
||||
} cant;/* status change state flags */
|
||||
//int sg_id; //ID of the previous Storm gust that hit you
|
||||
short comet_x, comet_y; // Point where src casted Comet - required to calculate damage from this point
|
||||
@ -2955,25 +3068,6 @@ struct status_change {
|
||||
struct status_change_entry *data[SC_MAX];
|
||||
};
|
||||
|
||||
/// Statuses that are cancelled/disabled while on Madogear
|
||||
static const std::vector<sc_type> mado_statuses = {
|
||||
SC_LOUD,
|
||||
SC_CARTBOOST,
|
||||
SC_MELTDOWN,
|
||||
SC_ADRENALINE,
|
||||
SC_ADRENALINE2,
|
||||
SC_WEAPONPERFECTION,
|
||||
SC_MAXIMIZEPOWER,
|
||||
SC_OVERTHRUST,
|
||||
SC_MAXOVERTHRUST
|
||||
};
|
||||
|
||||
// for looking up associated data
|
||||
sc_type status_skill2sc(int skill);
|
||||
int status_sc2skill(sc_type sc);
|
||||
uint64 status_sc2scb_flag(sc_type sc);
|
||||
int status_type2relevant_bl_types(int type);
|
||||
|
||||
int status_damage( struct block_list *src, struct block_list *target, int64 dhp, int64 dsp, int64 dap, t_tick walkdelay, int flag, uint16 skill_id );
|
||||
static int status_damage( struct block_list *src, struct block_list *target, int64 dhp, int64 dsp, t_tick walkdelay, int flag, uint16 skill_id ){
|
||||
return status_damage( src, target, dhp, dsp, 0, walkdelay, flag, skill_id );
|
||||
@ -3123,7 +3217,7 @@ int status_change_clear(struct block_list* bl, int type);
|
||||
void status_change_clear_buffs(struct block_list* bl, uint8 type);
|
||||
void status_change_clear_onChangeMap(struct block_list *bl, struct status_change *sc);
|
||||
|
||||
#define status_calc_bl(bl, flag) status_calc_bl_(bl, (enum scb_flag)(flag), SCO_NONE)
|
||||
#define status_calc_bl(bl, flag) status_calc_bl_(bl, flag, SCO_NONE)
|
||||
#define status_calc_mob(md, opt) status_calc_bl_(&(md)->bl, SCB_ALL, opt)
|
||||
#define status_calc_pet(pd, opt) status_calc_bl_(&(pd)->bl, SCB_ALL, opt)
|
||||
#define status_calc_pc(sd, opt) status_calc_bl_(&(sd)->bl, SCB_ALL, opt)
|
||||
@ -3134,25 +3228,26 @@ void status_change_clear_onChangeMap(struct block_list *bl, struct status_change
|
||||
|
||||
bool status_calc_weight(struct map_session_data *sd, enum e_status_calc_weight_opt flag);
|
||||
bool status_calc_cart_weight(struct map_session_data *sd, enum e_status_calc_weight_opt flag);
|
||||
void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt);
|
||||
int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt);
|
||||
void status_calc_pet_(struct pet_data* pd, enum e_status_calc_opt opt);
|
||||
int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt);
|
||||
int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt);
|
||||
int status_calc_mercenary_(s_mercenary_data *md, e_status_calc_opt opt);
|
||||
int status_calc_elemental_(s_elemental_data *ed, e_status_calc_opt opt);
|
||||
int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt);
|
||||
void status_calc_bl_(struct block_list *bl, uint64 flag, uint8 opt);
|
||||
int status_calc_mob_(struct mob_data* md, uint8 opt);
|
||||
void status_calc_pet_(struct pet_data* pd, uint8 opt);
|
||||
int status_calc_pc_(struct map_session_data* sd, uint8 opt);
|
||||
int status_calc_homunculus_(struct homun_data *hd, uint8 opt);
|
||||
int status_calc_mercenary_(s_mercenary_data *md, uint8 opt);
|
||||
int status_calc_elemental_(s_elemental_data *ed, uint8 opt);
|
||||
int status_calc_npc_(struct npc_data *nd, uint8 opt);
|
||||
|
||||
void status_calc_misc(struct block_list *bl, struct status_data *status, int level);
|
||||
void status_calc_regen(struct block_list *bl, struct status_data *status, struct regen_data *regen);
|
||||
void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, struct status_change *sc);
|
||||
void status_calc_state(struct block_list *bl, struct status_change *sc, std::bitset<SCS_MAX> flag, bool start);
|
||||
|
||||
void status_calc_slave_mode(struct mob_data *md, struct mob_data *mmd);
|
||||
|
||||
bool status_check_skilluse(struct block_list *src, struct block_list *target, uint16 skill_id, int flag);
|
||||
int status_check_visibility(struct block_list *src, struct block_list *target);
|
||||
|
||||
int status_change_spread(struct block_list *src, struct block_list *bl, bool type);
|
||||
int status_change_spread(block_list *src, block_list *bl);
|
||||
|
||||
#ifndef RENEWAL
|
||||
unsigned short status_base_matk_min(const struct status_data* status);
|
||||
@ -3167,9 +3262,11 @@ unsigned short status_base_matk_max(struct block_list *bl, const struct status_d
|
||||
|
||||
unsigned short status_base_atk(const struct block_list *bl, const struct status_data *status, int level);
|
||||
|
||||
void initChangeTables(void);
|
||||
int status_readdb( bool reload = false );
|
||||
int do_init_status(void);
|
||||
// Status changes accessors for StatusChange database
|
||||
uint16 status_efst_get_bl_type(enum efst_type efst);
|
||||
|
||||
void status_readdb( bool reload = false );
|
||||
void do_init_status(void);
|
||||
void do_final_status(void);
|
||||
|
||||
#endif /* STATUS_HPP */
|
||||
|
135
src/map/unit.cpp
135
src/map/unit.cpp
@ -1449,9 +1449,9 @@ int unit_is_walking(struct block_list *bl)
|
||||
* Some statuses are still checked here due too specific variables
|
||||
* @author [Skotlex]
|
||||
* @param bl: Object to check
|
||||
* @return Can move(1); Can't move(0)
|
||||
* @return True - can move; False - can't move
|
||||
*/
|
||||
int unit_can_move(struct block_list *bl) {
|
||||
bool unit_can_move(struct block_list *bl) {
|
||||
struct map_session_data *sd;
|
||||
struct unit_data *ud;
|
||||
struct status_change *sc;
|
||||
@ -1463,37 +1463,20 @@ int unit_can_move(struct block_list *bl) {
|
||||
sd = BL_CAST(BL_PC, bl);
|
||||
|
||||
if (!ud)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (ud->skilltimer != INVALID_TIMER && ud->skill_id != LG_EXEEDBREAK && (!sd || !pc_checkskill(sd, SA_FREECAST) || skill_get_inf2(ud->skill_id, INF2_ISGUILD)))
|
||||
return 0; // Prevent moving while casting
|
||||
return false; // Prevent moving while casting
|
||||
|
||||
if (DIFF_TICK(ud->canmove_tick, gettick()) > 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if ((sd && (pc_issit(sd) || sd->state.vending || sd->state.buyingstore || (sd->state.block_action & PCBLOCK_MOVE) || sd->state.mail_writing)) || ud->state.blockedmove)
|
||||
return 0; // Can't move
|
||||
return false; // Can't move
|
||||
|
||||
// Status changes that block movement
|
||||
if (sc) {
|
||||
if( sc->cant.move // status placed here are ones that cannot be cached by sc->cant.move for they depend on other conditions other than their availability
|
||||
|| sc->data[SC_SPIDERWEB]
|
||||
|| (sc->data[SC_DANCING] && sc->data[SC_DANCING]->val4 && (
|
||||
#ifndef RENEWAL
|
||||
!sc->data[SC_LONGING] ||
|
||||
#endif
|
||||
(sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT ||
|
||||
(sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE
|
||||
) )
|
||||
)
|
||||
return 0;
|
||||
|
||||
if (sc->opt1 > 0 && sc->opt1 != OPT1_STONEWAIT && sc->opt1 != OPT1_BURNING)
|
||||
return 0;
|
||||
|
||||
if ((sc->option & OPTION_HIDE) && (!sd || pc_checkskill(sd, RG_TUNNELDRIVE) <= 0))
|
||||
return 0;
|
||||
}
|
||||
if (sc && sc->cant.move)
|
||||
return false;
|
||||
|
||||
// Icewall walk block special trapped monster mode
|
||||
if(bl->type == BL_MOB) {
|
||||
@ -1501,11 +1484,11 @@ int unit_can_move(struct block_list *bl) {
|
||||
if(md && ((status_has_mode(&md->status,MD_STATUSIMMUNE) && battle_config.boss_icewall_walk_block == 1 && map_getcell(bl->m,bl->x,bl->y,CELL_CHKICEWALL))
|
||||
|| (!status_has_mode(&md->status,MD_STATUSIMMUNE) && battle_config.mob_icewall_walk_block == 1 && map_getcell(bl->m,bl->x,bl->y,CELL_CHKICEWALL)))) {
|
||||
md->walktoxy_fail_count = 1; //Make sure rudeattacked skills are invoked
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1520,11 +1503,9 @@ TIMER_FUNC(unit_resume_running){
|
||||
TBL_PC *sd = map_id2sd(id);
|
||||
|
||||
if (sd && pc_isridingwug(sd))
|
||||
clif_skill_nodamage(ud->bl,ud->bl,RA_WUGDASH,ud->skill_lv,
|
||||
sc_start4(ud->bl,ud->bl,status_skill2sc(RA_WUGDASH),100,ud->skill_lv,unit_getdir(ud->bl),0,0,0));
|
||||
clif_skill_nodamage(ud->bl,ud->bl,RA_WUGDASH,ud->skill_lv,sc_start4(ud->bl,ud->bl,SC_WUGDASH,100,ud->skill_lv,unit_getdir(ud->bl),0,0,0));
|
||||
else
|
||||
clif_skill_nodamage(ud->bl,ud->bl,TK_RUN,ud->skill_lv,
|
||||
sc_start4(ud->bl,ud->bl,status_skill2sc(TK_RUN),100,ud->skill_lv,unit_getdir(ud->bl),0,0,0));
|
||||
clif_skill_nodamage(ud->bl,ud->bl,TK_RUN,ud->skill_lv,sc_start4(ud->bl,ud->bl,SC_RUN,100,ud->skill_lv,unit_getdir(ud->bl),0,0,0));
|
||||
|
||||
if (sd)
|
||||
clif_walkok(sd);
|
||||
@ -2404,23 +2385,6 @@ int unit_unattackable(struct block_list *bl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the unit can attack, returns yes if so.
|
||||
*/
|
||||
bool unit_can_attack(struct block_list *src, int target_id)
|
||||
{
|
||||
struct status_change *sc = status_get_sc(src);
|
||||
|
||||
if( sc != NULL ) {
|
||||
if( sc->data[SC__MANHOLE] )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( src->type == BL_PC )
|
||||
return pc_can_attack(BL_CAST(BL_PC, src), target_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests a unit to attack a target
|
||||
* @param src: Object initiating attack
|
||||
@ -2723,7 +2687,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, t_tick tick)
|
||||
#ifdef OFFICIAL_WALKPATH
|
||||
|| !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL)
|
||||
#endif
|
||||
|| (sd && !pc_can_attack(sd, target->id)) )
|
||||
|| !unit_can_attack(src, target->id) )
|
||||
return 0; // Can't attack under these conditions
|
||||
|
||||
if( src->m != target->m ) {
|
||||
@ -2870,6 +2834,35 @@ static TIMER_FUNC(unit_attack_timer){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a player can attack based on status changes
|
||||
* Why not use status_check_skilluse?
|
||||
* "src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack."
|
||||
* Even ground-based attacks should be blocked by these statuses
|
||||
* Called from unit_attack and unit_attack_timer_sub
|
||||
* @retval true Can attack
|
||||
**/
|
||||
bool unit_can_attack(struct block_list *bl, int target_id) {
|
||||
nullpo_retr(false, bl);
|
||||
|
||||
if (bl->type == BL_PC) {
|
||||
map_session_data *sd = ((TBL_PC *)bl);
|
||||
|
||||
if (sd && (sd->state.block_action & PCBLOCK_ATTACK))
|
||||
return false;
|
||||
}
|
||||
|
||||
struct status_change *sc;
|
||||
|
||||
if (!(sc = status_get_sc(bl)))
|
||||
return true;
|
||||
|
||||
if (sc->cant.attack || (sc->data[SC_VOICEOFSIREN] && sc->data[SC_VOICEOFSIREN]->val2 == target_id))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels a skill's cast
|
||||
* @param bl: Object to cancel cast
|
||||
@ -3059,50 +3052,20 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
|
||||
ud->attackabletime = ud->canmove_tick /*= ud->canact_tick*/ = gettick();
|
||||
|
||||
if(sc && sc->count ) { // map-change/warp dispells.
|
||||
status_change_end(bl, SC_BLADESTOP, INVALID_TIMER);
|
||||
#ifdef RENEWAL
|
||||
status_change_end(bl, SC_BASILICA_CELL, INVALID_TIMER);
|
||||
#else
|
||||
status_change_end(bl, SC_BASILICA, INVALID_TIMER);
|
||||
#endif
|
||||
status_change_end(bl, SC_ANKLE, INVALID_TIMER);
|
||||
status_change_end(bl, SC_TRICKDEAD, INVALID_TIMER);
|
||||
status_change_end(bl, SC_BLADESTOP_WAIT, INVALID_TIMER);
|
||||
status_change_end(bl, SC_RUN, INVALID_TIMER);
|
||||
status_change_end(bl, SC_DANCING, INVALID_TIMER);
|
||||
status_change_end(bl, SC_WARM, INVALID_TIMER);
|
||||
status_change_end(bl, SC_DEVOTION, INVALID_TIMER);
|
||||
status_change_end(bl, SC_MARIONETTE, INVALID_TIMER);
|
||||
status_change_end(bl, SC_MARIONETTE2, INVALID_TIMER);
|
||||
status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER);
|
||||
status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER);
|
||||
status_change_end(bl, SC_TINDER_BREAKER, INVALID_TIMER);
|
||||
status_change_end(bl, SC_TINDER_BREAKER2, INVALID_TIMER);
|
||||
status_change_end(bl, SC_FLASHKICK, INVALID_TIMER);
|
||||
status_change_end(bl, SC_SERVANT_SIGN, INVALID_TIMER);
|
||||
status_change_end(bl, SC_HIDING, INVALID_TIMER);
|
||||
if (sc->cant.warp)
|
||||
return 0;
|
||||
|
||||
status_db.removeByStatusFlag(bl, { SCF_REMOVEONCHANGEMAP });
|
||||
|
||||
// Ensure the bl is a PC; if so, we'll handle the removal of cloaking and cloaking exceed later
|
||||
if ( bl->type != BL_PC ) {
|
||||
status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
|
||||
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
|
||||
}
|
||||
status_change_end(bl, SC_CHASEWALK, INVALID_TIMER);
|
||||
if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF)
|
||||
status_change_end(bl, SC_GOSPEL, INVALID_TIMER);
|
||||
if (sc->data[SC_PROVOKE] && sc->data[SC_PROVOKE]->timer == INVALID_TIMER)
|
||||
if (sc->data[SC_PROVOKE] && sc->data[SC_PROVOKE]->val4 == 1)
|
||||
status_change_end(bl, SC_PROVOKE, INVALID_TIMER); //End infinite provoke to prevent exploit
|
||||
status_change_end(bl, SC_CHANGE, INVALID_TIMER);
|
||||
status_change_end(bl, SC_STOP, INVALID_TIMER);
|
||||
status_change_end(bl, SC_WUGDASH, INVALID_TIMER);
|
||||
status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER);
|
||||
status_change_end(bl, SC_NEUTRALBARRIER_MASTER, INVALID_TIMER);
|
||||
status_change_end(bl, SC_STEALTHFIELD_MASTER, INVALID_TIMER);
|
||||
status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
|
||||
status_change_end(bl, SC__MANHOLE, INVALID_TIMER);
|
||||
status_change_end(bl, SC_VACUUM_EXTREME, INVALID_TIMER);
|
||||
status_change_end(bl, SC_NEWMOON, INVALID_TIMER);
|
||||
status_change_end(bl, SC_CURSEDCIRCLE_ATKER, INVALID_TIMER); // callme before warp
|
||||
status_change_end(bl, SC_SUHIDE, INVALID_TIMER);
|
||||
}
|
||||
|
||||
switch( bl->type ) {
|
||||
@ -3583,7 +3546,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
|
||||
sd->status.hom_id = 0;
|
||||
|
||||
#ifdef RENEWAL
|
||||
status_change_end(&sd->bl, status_skill2sc(AM_CALLHOMUN), INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_HOMUN_TIME, INVALID_TIMER);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ TIMER_FUNC(unit_delay_walktobl_timer);
|
||||
|
||||
// Causes the target object to stop moving.
|
||||
int unit_stop_walking(struct block_list *bl,int type);
|
||||
int unit_can_move(struct block_list *bl);
|
||||
bool unit_can_move(struct block_list *bl);
|
||||
int unit_is_walking(struct block_list *bl);
|
||||
int unit_set_walkdelay(struct block_list *bl, t_tick tick, t_tick delay, int type);
|
||||
|
||||
@ -138,6 +138,7 @@ int unit_stopattack(struct block_list *bl, va_list ap);
|
||||
void unit_stop_attack(struct block_list *bl);
|
||||
int unit_attack(struct block_list *src,int target_id,int continuous);
|
||||
int unit_cancel_combo(struct block_list *bl);
|
||||
bool unit_can_attack(struct block_list *bl, int target_id);
|
||||
|
||||
// Cast on a unit
|
||||
int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv);
|
||||
|
Loading…
x
Reference in New Issue
Block a user