Compare commits

..

36 Commits

Author SHA1 Message Date
aleos
1ab4ebe576 Resolve some compile errors and warnings 2024-05-03 13:06:40 -04:00
Aleos
69635631c0 Merge branch 'master' into refactor/produce 2024-05-03 10:36:48 -04:00
Lemongrass3110
3ada0c11be Converted some banking packets to struct (#8297) 2024-05-03 13:35:20 +02:00
Kanin Temsrisuk
90b2b9cbbf Fix auto spell list on renewal (#8299)
Follow up to 9440869
2024-05-03 10:12:31 +02:00
Daegaladh
7ddd035442 Fixed clif type conversion warnings (#8294)
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
2024-05-03 09:26:02 +02:00
Lemongrass3110
38ca0998fd Cleaned up 2 size_t warnings in char.cpp (#8296) 2024-05-03 08:17:13 +02:00
Daegaladh
29a3c5263b Small optimization on change sex (#8281) 2024-05-03 00:46:40 +02:00
Lemongrass3110
827517f8cf Cleaned up a few TODOs from #7963 (#8254) 2024-05-02 22:44:31 +02:00
idk-whoami
6d2ef66bbb Script correction of Lux Anima Runestone IDs 22540 (#8258) 2024-05-02 21:35:49 +02:00
Lemongrass3110
7ebf47e31c Added GCC 12 and 13 to CI (#8293)
Follow up to d949740
2024-05-02 20:37:04 +02:00
Atemo
2ebdd50e08 Fixed warning about favorite item (#8290) 2024-05-02 15:35:00 +02:00
Jittapan Pluemsumran
d949740cd9 Moved battle_fix_damage definition to battle.cpp (#8292)
Fixes #8291
2024-05-02 13:56:20 +02:00
Playtester
16e9d52204 Database Cache Fix, Pre-Re Monster Cleanup (#8289)
- Fixed a problem that caused the DB cache to always be missing the last entry
- Removed renewal monsters from pre-re/mob_db.yml
2024-05-01 20:12:31 +02:00
Playtester
cad5cab976 Coma Rework, Exp Calc Type, Fiber Lock Range (#8287)
- Coma item bonus is no longer an additional effect / status change, but instead replaces the attack damage with setting HP/SP to 1
  * That means Coma attacks will never kill someone, even if the original attack would be lethal
  * When doing a Coma attack, the attack displays the original damage and this is also what counts towards the mob damage log
- Coma is checked for every single event that applies damage, including reflect damage, and for Provoke / Self Provoke
  * Some Renewal-only effects couldn't be tested and were left unchanged (e.g. damage from White Imprison)
- Coma now sets SP to 1 instead of 0
- bComaRace, bWeaponComaRace and bWeaponComaEle won't work on bosses, GVG and battlefield objects
- bComaClass and bWeaponComaClass no longer work on GVG and battlefield objects, but can work on bosses if you specify Class_Boss or Class_All
- Edge is now defined to only work on normal monster
- The default exp_calc_type 0 no longer counts the first attacker twice and instead works like on official servers
- Added a new exp_calc_type 2 that counts the first attacker twice as previously
- The damage logged will now include overkill damage on exp_calc_type 0 and 2, but not count Coma damage (it will count the damage you would have originally dealt instead)
- Fiber Lock now has a range of 9 instead of 7
- Fixes #8279
2024-05-01 08:58:51 +02:00
Playtester
9e959f7fd6 Renewal Offhand Damage, Left-hand Weapon Only Attack (#8285)
- Fixed renewal offhand damage being double as high as it should be
- You will now deal unarmed main hand damage if you equip a weapon only in your left hand
- Your offhand damage will now be the same regardless of whether you have a weapon in the main hand or not
- Fixes #8284
2024-04-27 15:55:41 +02:00
Playtester
0e434aa73b Grand Cross Damage and Trigger Rework (#8283)
- Grand Cross on target is now considered a full magic attack and no longer triggers drain and similar effects that only work with physical attacks
  * This problem as was introduced in d8a02e9 to fix Coma not working on Grand Cross, but the reason that Coma works on Grand Cross is because it can also trigger on Magic skills (this is already working)
- Grand Cross damage on self is still considered as "physical damage received" for reactive cards (e.g. Alarm Card), but no longer as "magical damage received" (e.g. Platinum Shield does not trigger)
- Grand Cross no longer channels through the whole "weapon attack" code and just calls the necessary parts directly (it only considers ATK, DEF/VIT_DEF and refine)
- Damage parts of Grand Cross can now go below 1 and reduce the other part (e.g. -5 physical damage and 15 magical damage now results in 10 damage instead of 16)
- Implemented the official renewal damage formula for Grand Cross:
   [((ATK+MATK)/2)*RATIO - DEF - VIT_DEF - MDEF - MDEF2]
- Fixed the order of damage processing for Grand Cross for fully accurate damage (there were a lot of rounding issues before)
- The attribute table is no longer applied twice on self damage (still applied twice on target)
- Cards that increase magic damage now work with Grand Cross (e.g. Skeggiold Card)
- Changed Grand Cross range to 9 as that's the official range (you never know when it matters)
- Fixes #1140
2024-04-27 10:22:50 +02:00
Playtester
2963e52fc6 Pre-Re Monster Stats, CSV2YAML Converter, Damage Inaccuracy Fix (#8278)
- Fixed several pre-re monster stats being 1 instead of 0
  * Issue was introduced in 05a17d8 as safety measure to prevent division by 0, but it results in wrong damage numbers
  * Players can get 0 on stats as well, so it's better to put such safety measures at the point where the division takes place
- Minimum stat for monsters is now 0 instead of 1
- Monsters that have 0 Luk after this change can no longer be cursed
- Improved csv2yaml converter to no longer lose the information whether a stat is 0 or 1
- Fixed an issue with converting Race2 in the csv2yaml converter
- Removed arbitrary "+1 MATK" bonus that was probably added due to people not figuring out why the damage was off by 1
- Fixed small damage inaccuracy issue in PVP
- Fixes #8277
2024-04-24 21:04:34 +02:00
Playtester
7c44390606 Fixed Monsters Randomly Targeting on Attack (#8274)
- Fixed immobile monsters targeting random bystanders with their spells even though they already have a target
- Fixed some Malaya Port enemies targeting randomly
- Fixes #8273
2024-04-24 11:46:45 +02:00
Kanin Temsrisuk
45b588c654 Corrected Cylinder Boots [1] item script (#8268) 2024-04-22 22:55:40 +02:00
idk-whoami
5124ddf575 Modes correction of Temple Of Demon God monsters (#8259)
Thanks to @Atemo
2024-04-22 22:54:41 +02:00
Chaos92
0f0bd685d9 Fix typo for macro_register (#8270) 2024-04-22 13:26:31 -04:00
Playtester
f15cb72f94 Monster AI Improvements, Clashing Spiral, Skid Trap, Throw Stone (#8269)
- Added config setting mob_unlock_time that defines how long a monster can be trapped (immobile) before it unlocks its target 
  * Default is 2000ms, which makes Clashing Spiral no longer cause monsters to drop their target, but Ankle Snare still will even at minimum duration 
- Monsters will now promptly use idle skills while trapped (there was a delay before)
- Increased the time the AI is still active when there are no players left on the map from 0ms to 5000ms
  * This fixes an issue that monsters never unlocked their target if it was the last player to leave the map
- Clashing Spiral now has a range of 4 instead of 5
- Skid Trap no longer has a stop effect in pre-re, but it will make monsters unlock their target and become idle
- Skid Trap still stops targets for 3 seconds in renewal, but will no longer activate on bosses
- Throw Stone now deals 30 damage when used by monsters
- Fixes #7846
2024-04-22 08:39:11 +02:00
Playtester
75f518859f Removed Basedamage Variable from Renewal (#8264)
- As this variable is unused and is very hard to calculate in renewal's structure, it was removed completely from renewal to make the renewal code cleaner
- In pre-re it still works exactly the same as before (used for the EDP and Magnum Break bonus - renewal uses weaponATK for this instead)
- Follow-up to b5e3e5e
2024-04-21 00:08:03 +02:00
munkrej
b5e3e5e69b Fixed wrong double damage calculation for skills in renewal mode (#8260)
Note by Playtester: In renewal the "battle_calc_skill_base_damage" function adds to the ATK values rather than resetting them, so calling it twice will cause the values to be doubled, so we can't easily use this system for renewal. Will do a follow-up cleanup later.
2024-04-20 15:50:27 +02:00
Playtester
3cbdcf999f Ankle Snare Status Rework (#8263)
- SC_ANKLE no longer has a natural resistance and minimum duration
- Glacier Fist, Clashing Spiral and Tarot Card of Fate now grant SC_ANKLE instead of SC_STOP (cannot teleport while under SC_ANKLE effect)
- Grand Cross now gives SC_ANKLE to self during the spell duration
- Ankle Snare now has a minimum duration of 3000+30*baselevel milliseconds
- Ankle Snare will no longer activate on bosses in renewal
- Fixed Ankle Snare stopping bosses in pre-renewal even if you didn't enable the config setting for it
- Glacier Fist now has a minimum duration of 1500+15*baselevel milliseconds rather than it being the maximum duration
- You can now define Glacier Fist's effective base duration in the YML file without worrying about it being halved in the source code (it is still getting reduced by Agi)
- Fixed some integer overflow issues
- Fixes #8253
2024-04-20 15:41:24 +02:00
Playtester
cd7341930e Fixed Capping of Values (#8257)
- Values that are added together will now be correctly capped to their max value
- Status resistance can no longer exceed 100% (made negative success rates become positive)
2024-04-18 17:55:41 +02:00
Playtester
25b98c87db NPC_INVINCIBLE and Spell Breaker (#8255)
- NPC_INVINCIBLE now grants SC_INVINCIBLE for 300s instead of unlimited
- NPC_INVINCIBLEOFF and MER_INVINCIBLEOFF2 now just end SC_INVINCIBLE instead of having their own status change
- SC_INVINCIBLE now works like plant mode instead of just setting incoming damage to 1
- SC_INVINCIBLE now increases ATKpercent by 100 instead of increasing all damage by 75%
- SC_INVINCIBLE no longer blocks skills
- SC_INVINCIBLE now increases movement speed by 50% instead of 75%
- SC_INVINCIBLE now increases ASPD strongly
- Quagmire can no longer prevent ASPD increase (it still ends various status changes and prevents them)
- If you counter Spell Breaker with Magic Rod you now receive 20% of the caster's MaxSP
- Spell Breaker will now only deal HP damage on level 5
- Spell Breaker now can deal damage to bosses to 10% in pre-re (cannot be reduced by SC_INVINCIBLE unless you enable the "invincible_nodamage" setting)
- Spell Breaker will no longer deal damage if it would be lethal
- Added missing animation of Spell Breaker's damage
- Fixes #8228
2024-04-17 16:28:04 +02:00
Atemo
5df7de2b15 Added missing sd check for clif_skill_fail (#7963)
Fixes #8239 

Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
2024-04-15 22:38:46 +02:00
Playtester
089c3056cf Updated/Simplified Damage Bonus Stacking (#8252)
- Freezing Trap, Sand Attack, Gunslinger Mine, Flip Tatami and Excruciating Palm no longer are affected by +% dmg cards
- The skills that ignore +% dmg cards are now exactly those skills that also ignore EDP and the EDP/Magnum Break elemental damage bonus
- Non-players are now always affected by ATKpercent
- Simplified the code accordingly
- Fixes #8250
2024-04-14 19:12:40 +02:00
Lemongrass3110
d05e11aecd Added .git-blame-ignore-revs file (#8245) 2024-04-14 19:09:36 +02:00
Playtester
310fcd6fa1 Throw skills (Shuriken, Kunai, Coins, Venom Knife) (#8249)
- Throw skills no longer consider arrow attack unless you have a ranged weapon equipped
- Throw Shuriken is no longer modified by +% damage cards
- Throw Shuriken/Kunai no longer ignore flee
- Throw Shuriken's damage bonus is now flee-ignoring and includes skill level(x4), dagger mastery(x3) and arrow attack
- Throw Kunai's damage bonus is now three times arrow attack per hit
- Throw Shuriken/Kunai's final damage is now applied as forced neutral damage
- Fixed range of Throw Coins (9 -> 7)
- Other code improvements
- Fixes #8206
2024-04-14 07:55:31 +02:00
Atemo
348803193c Extends the second roll Make/Amount 2023-06-18 17:47:17 +02:00
Atemo
62b0b12274 Apply suggestions from code review
Co-authored-by: Aleos <aleos89@users.noreply.github.com>
2023-06-17 17:41:14 +02:00
Atemo
4a7d2b45b5 Apply suggestions from code review
Co-authored-by: Vincent Stumpf <vincents.995@gmail.com>
2023-06-13 17:27:06 +02:00
Atemo
86fcc98081 Corrections from code review 2023-06-13 17:21:23 +02:00
Atemo
480cf26283 Converted produce_db and skill_changematerial_db into YAML 2023-05-17 21:35:33 +02:00
62 changed files with 10721 additions and 2488 deletions

9
.git-blame-ignore-revs Normal file
View File

@@ -0,0 +1,9 @@
# Massive EOL normalization & 'svn:eol-style native' flag setting for all txt/conf/h/c files.
# https://github.com/rathena/rathena/commit/637ae9a4dcde0d5885a18841d2f3875e06893c30
637ae9a4dcde0d5885a18841d2f3875e06893c30
# Applied AStyle code formating as discussed on tid:74602.
# https://github.com/rathena/rathena/commit/a7c32653f70bd420bdf5a621acdf3aea5c6e6002
a7c32653f70bd420bdf5a621acdf3aea5c6e6002
# Undid r16968: SVN Replaced with source:/trunk/src/@16966 (tid:74924).
# https://github.com/rathena/rathena/commit/a2bdc47dafb32f6d18ed350d8bbe79b8f679a049
a2bdc47dafb32f6d18ed350d8bbe79b8f679a049

View File

@@ -31,7 +31,7 @@ jobs:
# Available: ubuntu-22.04, ubuntu-20.04
os: [ubuntu-latest]
# Older versions of GCC are not available via unaltered aptitude repo lists.
gcc: ['9', '10', '11']
gcc: ['9', '10', '11', '12', '13']
steps:
- uses: actions/checkout@v2

View File

@@ -33,8 +33,7 @@ max_exp_gain_rate: 0
// Method of calculating earned experience when defeating a monster:
// 0 = uses damage given / total damage as damage ratio
// 1 = uses damage given / max_hp as damage ratio
// NOTE: Using type 1 disables the bonus where the first attacker gets
// his share of the exp doubled when multiple people attack the mob.
// 2 = 0 + first attacker counts twice
exp_calc_type: 0
// Experience increase per attacker. That is, every additional attacker to the

View File

@@ -79,10 +79,10 @@ monster_chase_refresh: 30
// 8: Enable mob-warping when standing on Dimensional Door
mob_warp: 0
// If these are set above 0, they define the time (in ms) during which monsters
// will have their 'AI' active after all players have left their vicinity.
mob_active_time: 0
boss_active_time: 0
// Defines the time (in ms) during which monsters will have their AI active
// after all players have left their vicinity.
mob_active_time: 5000
boss_active_time: 5000
// Mobs and Pets view-range adjustment (range2 column in the mob_db) (Note 2)
view_range_rate: 100
@@ -302,3 +302,8 @@ slave_stick_with_master: no
// Also used in delaying the spawning of guardians when a guild is not loaded.
// Default (Official): 1000
mob_respawn_time: 1000
// Defines the time (in ms) after which a monster unlocks its target when trapped.
// During this time monsters will still be in idle mode and use idle skills on random
// targets, but they continue chasing their original target when no longer trapped.
mob_unlock_time: 2000

View File

@@ -0,0 +1,45 @@
# This file is a part of rAthena.
# Copyright(C) 2023 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/>.
#
###########################################################################
# Item Produce Database
###########################################################################
#
# Item Produce Settings
#
###########################################################################
# - ItemLevel Number which determines what kind of a crafting window will pop-up.
# Recipe:
# - Product AegisName of the produced item.
# SkillName Skill name required. (Default: null)
# SkillLevel Skill level required. (Default: 1)
# Consumed: List of items consumed to produce the Product.
# - Item AegisName of the consumed item.
# Amount Amount required.
# Clear Remove the item with the given AegisName from Consumed. (Optional)
# NotConsumed: List of items not consumed to produce the Product. (Default: null)
# - Item AegisName of the unconsumed item.
# Clear Remove the item with the given AegisName from NotConsumed. (Optional)
# BaseRate Base rate (in n/10%) for Change Material (ItemLevel: 26). (Default: 1000)
# Make: List of item amounts with their individual rate produced by Change Material (ItemLevel: 26). (Default: null)
# - Amount Amount of item created (unique to the list) for Change Material (ItemLevel: 26).
# Rate Rate to create the Amount (in n/10%) for Change Material (ItemLevel: 26). (Default: 1000. 0 to remove on import)
###########################################################################
Header:
Type: PRODUCE_DB
Version: 1

View File

@@ -1,11 +0,0 @@
// Change Material Database
//
// Structure of Database:
// ID,ProductID,BaseRate,MakeAmount1,MakeAmountRate1...,MakeAmount5,MakeAmountRate5
//
// NOTE:
// - ID is used to identify item order that will be used for overwriting on db/import.
// Value is started from 0 until 74 (MAX_SKILL_CHANGEMATERIAL_DB-1). Use same ID on import file to overwrite original result & requirements
// - Up to 5 ID/Amount pairs can be specified.
// - Rate = n/10%

File diff suppressed because it is too large Load Diff

View File

@@ -102,7 +102,7 @@
1019,Peco Peco@NPC_EMOTION,chase,197,1,2000,0,5000,yes,self,always,0,6,,,,,,
1019,Peco Peco@NPC_FIREATTACK,attack,186,1,2000,0,5000,yes,target,always,0,,,,,,,
1019,Peco Peco@NPC_PROVOCATION,chase,194,1,200,0,5000,yes,target,always,0,,,,,,19,
1020,Mandragora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,randomtarget,always,0,,,,,,,
1020,Mandragora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,target,always,0,,,,,,,
1023,Orc Warrior@NPC_EMOTION,chase,197,1,2000,0,5000,yes,self,always,0,,,,,,,
1023,Orc Warrior@NPC_GROUNDATTACK,attack,185,2,500,500,5000,no,target,always,0,,,,,,6,
1023,Orc Warrior@NPC_EMOTION,chase,197,1,200,0,5000,yes,self,always,0,19,0x81,,,,,
@@ -349,7 +349,7 @@
1067,Cornutus@NPC_WATERATTACK,attack,184,2,500,500,5000,no,target,always,0,,,,,,6,
1067,Cornutus@CR_AUTOGUARD,attack,249,2,500,0,300000,yes,self,always,0,,,,,,,
1067,Cornutus@CR_AUTOGUARD,chase,249,2,2000,0,300000,yes,self,longrangeattacked,,,,,,,,
1068,Hydra@NPC_WATERATTACK,attack,184,2,500,500,5000,no,randomtarget,always,0,,,,,,,
1068,Hydra@NPC_WATERATTACK,attack,184,2,500,500,5000,no,target,always,0,,,,,,,
1069,Swordfish@NPC_WATERATTACK,attack,184,1,2000,0,5000,yes,target,always,0,,,,,,,
1069,Swordfish@WZ_WATERBALL,attack,86,3,500,1500,5000,yes,target,always,0,,,,,,,
1069,Swordfish@WZ_WATERBALL,chase,86,3,500,1500,5000,yes,target,always,0,,,,,,,
@@ -601,9 +601,9 @@
1117,Evil Druid@NPC_UNDEADATTACK,chase,347,3,500,500,5000,no,target,always,0,,,,,,9,
1117,Evil Druid@WZ_HEAVENDRIVE,attack,91,5,500,1200,5000,yes,target,always,0,,,,,,,
1117,Evil Druid@WZ_HEAVENDRIVE,chase,91,5,500,1200,5000,yes,target,always,0,,,,,,,
1118,Flora@NPC_BLOODDRAIN,attack,199,1,500,0,5000,yes,randomtarget,always,0,,,,,,,
1118,Flora@NPC_BLOODDRAIN,attack,199,1,500,0,5000,yes,target,always,0,,,,,,,
1118,Flora@NPC_EMOTION,idle,197,1,2000,0,5000,yes,self,always,0,2,,,,,,
1118,Flora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,randomtarget,always,0,,,,,,,
1118,Flora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,target,always,0,,,,,,,
1119,Frilldora@AS_CLOAKING,attack,135,1,2000,200,5000,yes,self,always,0,,,,,,,
1119,Frilldora@AS_CLOAKING,idle,135,1,2000,200,5000,yes,self,always,0,,,,,,,
1119,Frilldora@AS_CLOAKING,chase,135,1,2000,200,5000,yes,self,always,0,,,,,,,
@@ -1297,7 +1297,7 @@
1276,Raydric Archer@CR_AUTOGUARD,attack,249,2,500,0,300000,yes,self,always,0,,,,,,,
1277,Greatest General@NPC_BLINDATTACK,idle,177,3,10000,1500,5000,no,randomtarget,longrangeattacked,,,,,,,6,
1277,Greatest General@NPC_BLINDATTACK,idle,177,3,10000,1500,5000,no,randomtarget,casttargeted,,,,,,,6,
1277,Greatest General@NPC_FIREATTACK,attack,186,2,500,500,5000,no,randomtarget,always,0,,,,,,,
1277,Greatest General@NPC_FIREATTACK,attack,186,2,500,500,5000,no,target,always,0,,,,,,,
1277,Greatest General@WZ_EARTHSPIKE,idle,90,3,5000,1500,5000,no,randomtarget,longrangeattacked,,,,,,,6,
1277,Greatest General@WZ_EARTHSPIKE,idle,90,3,5000,1500,5000,no,randomtarget,casttargeted,,,,,,,6,
1278,Stalactite Golem@NPC_STUNATTACK,attack,179,4,500,1500,5000,no,target,always,0,,,,,,6,
@@ -1580,7 +1580,7 @@
1367,Blazer@WZ_SIGHTRASHER,attack,81,5,500,1000,5000,no,target,always,0,,,,,,6,
1368,Geographer@AL_HEAL,attack,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,60,,,,,,,
1368,Geographer@AL_HEAL,idle,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,60,,,,,,,
1368,Geographer@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,randomtarget,always,0,,,,,,,
1368,Geographer@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,target,always,0,,,,,,,
1369,Grand Peco@AS_SONICBLOW,attack,136,5,500,800,5000,no,target,always,0,,,,,,6,
1369,Grand Peco@NPC_FIREATTACK,attack,186,3,500,500,5000,no,target,always,0,,,,,,6,
1369,Grand Peco@NPC_EMOTION,chase,197,1,200,0,5000,yes,self,always,0,19,0x81,,,,,
@@ -2563,8 +2563,8 @@
1510,Hylozoist@MO_BODYRELOCATION,chase,264,1,2000,500,5000,no,target,always,0,,,,,,,
1511,Amon Ra@NPC_BLOODDRAIN,idle,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
1511,Amon Ra@NPC_BLOODDRAIN,idle,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,always,0,,,,,,29,
1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,always,0,,,,,,29,
1511,Amon Ra@NPC_SUMMONMONSTER,idle,209,5,5000,0,10000,no,self,longrangeattacked,0,1474,1477,1438,,,9,
1511,Amon Ra@NPC_SUMMONMONSTER,idle,209,5,5000,0,10000,no,self,casttargeted,0,1474,1477,1438,,,9,
1511,Amon Ra@NPC_SUMMONMONSTER,attack,209,5,5000,0,10000,no,self,longrangeattacked,0,1474,1477,1438,,,9,
@@ -2583,11 +2583,11 @@
1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,skillused,83,,,,,,9,
1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,longrangeattacked,,,,,,,9,
1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,casttargeted,,,,,,,9,
1511,Amon Ra@WZ_METEOR,attack,83,11,5000,0,3000,yes,randomtarget,always,0,,,,,,9,
1511,Amon Ra@WZ_METEOR,attack,83,11,5000,0,3000,yes,target,always,0,,,,,,9,
1511,Amon Ra@WZ_FIREPILLAR,idle,80,10,10000,0,2000,yes,around2,always,0,,,,,,,
1511,Amon Ra@WZ_FIREPILLAR,idle,80,10,10000,0,2000,yes,around2,always,0,,,,,,,
1511,Amon Ra@WZ_FIREPILLAR,attack,80,10,5000,0,2000,yes,around2,always,0,,,,,,,
1511,Amon Ra@NPC_DARKBLESSING,attack,203,1,5000,0,2000,no,randomtarget,always,0,,,,,,,
1511,Amon Ra@NPC_DARKBLESSING,attack,203,1,5000,0,2000,no,target,always,0,,,,,,,
1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,5000,yes,randomtarget,always,0,,,,,,9,
1511,Amon Ra@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
1511,Amon Ra@AL_TELEPORT,walk,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
@@ -3398,18 +3398,18 @@
1663,Laurell Weinder@NPC_EMOTION,idle,197,1,10000,0,5000,yes,self,skillused,28,15,,,,,,
1663,Laurell Weinder@NPC_EMOTION,attack,197,1,10000,0,5000,yes,self,skillused,28,15,,,,,,
1663,Laurell Weinder@NPC_EMOTION,chase,197,1,10000,0,5000,yes,self,skillused,28,15,,,,,,
1664,Photon Cannon@NPC_WINDATTACK,attack,187,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
1664,Photon Cannon@NPC_WINDATTACK,attack,187,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
1664,Photon Cannon@NPC_WINDATTACK,attack,187,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
1665,Photon Cannon@NPC_FIREATTACK,attack,186,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
1665,Photon Cannon@NPC_FIREATTACK,attack,186,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
1665,Photon Cannon@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
1666,Photon Cannon@NPC_WATERATTACK,attack,184,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
1666,Photon Cannon@NPC_WATERATTACK,attack,184,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
1666,Photon Cannon@NPC_WATERATTACK,attack,184,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
1664,Photon Cannon@NPC_WINDATTACK,attack,187,5,1000,1000,10000,yes,target,always,0,,,,,,,
1664,Photon Cannon@NPC_WINDATTACK,attack,187,3,2000,500,5000,yes,target,always,0,,,,,,,
1664,Photon Cannon@NPC_WINDATTACK,attack,187,1,10000,0,0,yes,target,always,0,,,,,,,
1665,Photon Cannon@NPC_FIREATTACK,attack,186,5,1000,1000,10000,yes,target,always,0,,,,,,,
1665,Photon Cannon@NPC_FIREATTACK,attack,186,3,2000,500,5000,yes,target,always,0,,,,,,,
1665,Photon Cannon@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,target,always,0,,,,,,,
1666,Photon Cannon@NPC_WATERATTACK,attack,184,5,1000,1000,10000,yes,target,always,0,,,,,,,
1666,Photon Cannon@NPC_WATERATTACK,attack,184,3,2000,500,5000,yes,target,always,0,,,,,,,
1666,Photon Cannon@NPC_WATERATTACK,attack,184,1,10000,0,0,yes,target,always,0,,,,,,,
1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,5,1000,1000,10000,yes,target,always,0,,,,,,,
1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,3,2000,500,5000,yes,target,always,0,,,,,,,
1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,1,10000,0,0,yes,target,always,0,,,,,,,
1668,Archdam@NPC_PIERCINGATT,attack,158,5,1000,0,5000,yes,target,always,0,,,,,,,
1668,Archdam@NPC_GUIDEDATTACK,attack,172,2,500,1000,20000,no,target,always,0,,,,,,29,
1668,Archdam@KN_SPEARSTAB,attack,58,5,500,800,5000,no,target,always,0,,,,,,,
@@ -3446,9 +3446,9 @@
1673,Dimik@NPC_COMBOATTACK,attack,171,4,500,700,5000,no,target,always,0,,,,,,,
1673,Dimik@NPC_COMBOATTACK,chase,171,4,500,700,5000,no,target,always,0,,,,,,,
1673,Dimik@NPC_FIREATTACK,attack,186,3,500,0,5000,yes,target,always,0,,,,,,,
1674,Monemus@NPC_FIREATTACK,attack,186,10,500,1000,30000,yes,randomtarget,always,0,,,,,,,
1674,Monemus@NPC_FIREATTACK,attack,186,3,1000,0,10000,yes,randomtarget,always,0,,,,,,,
1674,Monemus@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
1674,Monemus@NPC_FIREATTACK,attack,186,10,500,1000,30000,yes,target,always,0,,,,,,,
1674,Monemus@NPC_FIREATTACK,attack,186,3,1000,0,10000,yes,target,always,0,,,,,,,
1674,Monemus@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,target,always,0,,,,,,,
1675,Venatu@NPC_SILENCEATTACK,attack,178,3,500,700,5000,no,target,always,0,,,,,,,
1675,Venatu@NPC_GUIDEDATTACK,attack,172,3,500,1000,20000,no,target,always,0,,,,,,6,
1675,Venatu@NPC_STUNATTACK,attack,179,2,500,1500,5000,no,target,always,0,,,,,,11,
@@ -3524,11 +3524,11 @@
1688,Lady Tany@AL_TELEPORT,idle,26,1,1000,0,30000,yes,self,always,0,,,,,,,
1688,Lady Tany@AL_TELEPORT,attack,26,1,1000,0,30000,yes,self,always,0,,,,,,,
1688,Lady Tany@NPC_EXPULSION,attack,674,1,1000,1000,10000,no,target,myhpltmaxrate,60,,,,,,,
1688,Lady Tany@AC_CHARGEARROW,attack,148,1,2000,0,5000,yes,randomtarget,always,0,,,,,,6,
1688,Lady Tany@NPC_COMBOATTACK,attack,171,1,1000,0,5000,no,randomtarget,always,0,,,,,,,
1688,Lady Tany@NPC_CRITICALSLASH,attack,170,1,500,500,5000,no,randomtarget,always,0,,,,,,6,
1688,Lady Tany@NPC_GUIDEDATTACK,attack,172,5,500,0,20000,no,randomtarget,always,0,,,,,,,
1688,Lady Tany@NPC_STUNATTACK,attack,179,5,500,0,5000,no,randomtarget,always,0,,,,,,,
1688,Lady Tany@AC_CHARGEARROW,attack,148,1,2000,0,5000,yes,target,always,0,,,,,,6,
1688,Lady Tany@NPC_COMBOATTACK,attack,171,1,1000,0,5000,no,target,always,0,,,,,,,
1688,Lady Tany@NPC_CRITICALSLASH,attack,170,1,500,500,5000,no,target,always,0,,,,,,6,
1688,Lady Tany@NPC_GUIDEDATTACK,attack,172,5,500,0,20000,no,target,always,0,,,,,,,
1688,Lady Tany@NPC_STUNATTACK,attack,179,5,500,0,5000,no,target,always,0,,,,,,,
1688,Lady Tany@NPC_DEFENDER,attack,205,1,500,0,30000,yes,self,longrangeattacked,,,,,,,29,
1688,Lady Tany@NPC_POWERUP,attack,349,5,10000,0,30000,yes,self,myhpltmaxrate,30,,,,,,6,
1688,Lady Tany@NPC_SUMMONSLAVE,attack,196,5,10000,2000,5000,no,self,slavele,2,1691,,,,,,
@@ -4220,18 +4220,18 @@
1779,Ktullanux@NPC_AGIUP,attack,350,5,2000,0,100000,yes,self,always,0,,,,,,,
1779,Ktullanux@NPC_AGIUP,attack,350,5,10000,0,25000,yes,self,myhpltmaxrate,30,,,,,,,
1779,Ktullanux@AL_HEAL,idle,28,11,10000,0,10000,yes,self,myhpltmaxrate,50,,,,,,,
1780,Muscipular@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
1780,Muscipular@KN_SPEARSTAB,attack,58,5,500,800,5000,no,randomtarget,always,0,,,,,,6,
1780,Muscipular@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
1780,Muscipular@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,target,always,0,,,,,,,
1780,Muscipular@KN_SPEARSTAB,attack,58,5,500,800,5000,no,target,always,0,,,,,,6,
1780,Muscipular@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,target,always,0,,,,,,,
1780,Muscipular@AL_HEAL,attack,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,50,,,,,,,
1780,Muscipular@AL_HEAL,idle,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,50,,,,,,,
1780,Muscipular@NPC_PETRIFYATTACK,attack,180,5,500,0,5000,yes,randomtarget,always,0,,,,,,,
1781,Drosera@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
1781,Drosera@KN_PIERCE,attack,56,5,500,700,5000,no,randomtarget,always,0,,,,,,,
1781,Drosera@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
1780,Muscipular@NPC_PETRIFYATTACK,attack,180,5,500,0,5000,yes,target,always,0,,,,,,,
1781,Drosera@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,target,always,0,,,,,,,
1781,Drosera@KN_PIERCE,attack,56,5,500,700,5000,no,target,always,0,,,,,,,
1781,Drosera@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,target,always,0,,,,,,,
1781,Drosera@RG_CLOSECONFINE,attack,1005,1,1000,0,30000,yes,target,always,0,,,,,,,
1781,Drosera@NPC_GUIDEDATTACK,attack,172,3,500,1000,20000,no,randomtarget,always,0,,,,,,6,
1781,Drosera@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,randomtarget,always,0,,,,,,,
1781,Drosera@NPC_GUIDEDATTACK,attack,172,3,500,1000,20000,no,target,always,0,,,,,,6,
1781,Drosera@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,target,always,0,,,,,,,
1782,Roween@NPC_WINDATTACK,attack,187,2,500,500,5000,no,target,always,0,,,,,,,
1782,Roween@NPC_COMBOATTACK,attack,171,4,500,500,5000,no,target,always,0,,,,,,6,
1782,Roween@NPC_EMOTION,idle,197,1,2000,0,5000,yes,self,always,0,22,0x308D,,,,,

49
db/pre-re/produce_db.yml Normal file
View File

@@ -0,0 +1,49 @@
# This file is a part of rAthena.
# Copyright(C) 2023 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/>.
#
###########################################################################
# Item Produce Database
###########################################################################
#
# Item Produce Settings
#
###########################################################################
# - ItemLevel Number which determines what kind of a crafting window will pop-up.
# Recipe:
# - Product AegisName of the produced item.
# SkillName Skill name required. (Default: null)
# SkillLevel Skill level required. (Default: 1)
# Consumed: List of items consumed to produce the Product.
# - Item AegisName of the consumed item.
# Amount Amount required.
# Clear Remove the item with the given AegisName from Consumed. (Optional)
# NotConsumed: List of items not consumed to produce the Product. (Default: null)
# - Item AegisName of the unconsumed item.
# Clear Remove the item with the given AegisName from NotConsumed. (Optional)
# BaseRate Base rate (in n/10%) for Change Material (ItemLevel: 26). (Default: 1000)
# Make: List of item amounts with their individual rate produced by Change Material (ItemLevel: 26). (Default: null)
# - Amount Amount of item created (unique to the list) for Change Material (ItemLevel: 26).
# Rate Rate to create the Amount (in n/10%) for Change Material (ItemLevel: 26). (Default: 1000. 0 to remove on import)
###########################################################################
Header:
Type: PRODUCE_DB
Version: 1
Footer:
Imports:
- Path: db/pre-re/skill_produce_db.yml

View File

@@ -4153,7 +4153,6 @@ Body:
Time: 120000
- Level: 5
Time: 60000
Duration2: 3000
Requires:
SpCost: 10
ItemCost:
@@ -4408,6 +4407,7 @@ Body:
TargetType: Ground
DamageFlags:
Splash: true
IgnoreAtkCard: true
Flags:
IsTrap: true
AlterRangeResearchTrap: true
@@ -5184,6 +5184,8 @@ Body:
MaxLevel: 1
Type: Weapon
TargetType: Attack
DamageFlags:
IgnoreAtkCard: true
Flags:
IsQuest: true
Range: 1
@@ -6885,12 +6887,9 @@ Body:
MaxLevel: 10
Type: Magic
TargetType: Self
DamageFlags:
IgnoreAtkCard: true
IgnoreFlee: true
Flags:
TargetSelf: true
Range: 5
Range: 9
Hit: Single
HitCount: 1
Element: Holy
@@ -9999,15 +9998,15 @@ Body:
Element: Weapon
Duration1:
- Level: 1
Time: 4000
Time: 2000
- Level: 2
Time: 8000
Time: 4000
- Level: 3
Time: 12000
Time: 6000
- Level: 4
Time: 16000
Time: 8000
- Level: 5
Time: 24000
Time: 10000
CastDelayFlags:
IgnoreStatus: true
Requires:
@@ -10023,7 +10022,7 @@ Body:
- Level: 5
Amount: 12
SpiritSphereCost: 1
Status: Stop
Status: Ankle
- Id: 372
Name: CH_CHAINCRUSH
Description: Chain Crush Combo
@@ -10802,7 +10801,7 @@ Body:
IgnoreDefense: true
Flags:
TargetTrap: true
Range: 5
Range: 4
Hit: Multi_Hit
HitCount: 5
Element: Weapon
@@ -10844,7 +10843,7 @@ Body:
Weapon:
1hSpear: true
2hSpear: true
Status: Stop
Status: Ankle
- Id: 398
Name: LK_HEADCRUSH
Description: Traumatic Blow
@@ -11063,7 +11062,7 @@ Body:
TargetType: Attack
DamageFlags:
NoDamage: true
Range: 7
Range: 9
Hit: Single
HitCount: 1
ActiveInstance: 3
@@ -14295,6 +14294,7 @@ Body:
TargetType: Ground
DamageFlags:
Splash: true
IgnoreAtkCard: true
IgnoreFlee: true
Flags:
AlterRangeSnakeEye: true
@@ -14380,7 +14380,7 @@ Body:
Type: Weapon
TargetType: Attack
DamageFlags:
IgnoreFlee: true
IgnoreAtkCard: true
Range: 9
Hit: Single
HitCount: 1
@@ -14398,7 +14398,6 @@ Body:
TargetType: Attack
DamageFlags:
IgnoreAtkCard: true
IgnoreFlee: true
Range: 9
Hit: Multi_Hit
HitCount: 3
@@ -14474,7 +14473,7 @@ Body:
Flags:
IgnoreBgReduction: true
IgnoreGvgReduction: true
Range: 9
Range: 7
Hit: Single
HitCount: 1
CopyFlags:
@@ -14511,6 +14510,8 @@ Body:
MaxLevel: 5
Type: Weapon
TargetType: Self
DamageFlags:
IgnoreAtkCard: true
Hit: Single
HitCount: 1
Element: Weapon
@@ -16331,7 +16332,7 @@ Body:
Flags:
IsNpc: true
HitCount: 1
Duration1: -1
Duration1: 300000
Status: Invincible
- Id: 686
Name: NPC_INVINCIBLEOFF
@@ -16343,8 +16344,6 @@ Body:
Flags:
IsNpc: true
HitCount: 1
Duration1: 60000
Status: InvincibleOff
- Id: 687
Name: NPC_ALLHEAL
Description: Full Heal
@@ -17181,6 +17180,7 @@ Body:
TargetType: Attack
DamageFlags:
Splash: true
IgnoreAtkCard: true
Flags:
IsQuest: true
Range: -1
@@ -32585,6 +32585,7 @@ Body:
TargetType: Ground
DamageFlags:
Splash: true
IgnoreAtkCard: true
Flags:
IsTrap: true
AlterRangeResearchTrap: true
@@ -32751,7 +32752,7 @@ Body:
IgnoreDefense: true
Flags:
TargetTrap: true
Range: 5
Range: 4
Hit: Multi_Hit
HitCount: 5
Element: Weapon
@@ -32794,7 +32795,7 @@ Body:
Amount: 27
- Level: 5
Amount: 30
Status: Stop
Status: Ankle
- Id: 8219
Name: ML_DEFENDER
Description: Defending_Aura

File diff suppressed because it is too large Load Diff

View File

@@ -769,7 +769,6 @@ Body:
NoBanishingBuster: true
NoClearance: true
RemoveOnChangeMap: true
MinDuration: 5000
- Status: Keeping
DurationLookup: NPC_KEEPING
CalcFlags:
@@ -2824,23 +2823,12 @@ Body:
Icon: EFST_INVINCIBLE
DurationLookup: NPC_INVINCIBLE
CalcFlags:
Aspd: true
Speed: true
Flags:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
EndOnStart:
Invincibleoff: true
- Status: Invincibleoff
DurationLookup: NPC_INVINCIBLEOFF
CalcFlags:
Speed: true
Flags:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
EndOnStart:
Invincible: true
- Status: Manu_Atk
Icon: EFST_MANU_ATK
Flags:

53
db/produce_db.yml Normal file
View File

@@ -0,0 +1,53 @@
# This file is a part of rAthena.
# Copyright(C) 2023 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/>.
#
###########################################################################
# Item Produce Database
###########################################################################
#
# Item Produce Settings
#
###########################################################################
# - ItemLevel Number which determines what kind of a crafting window will pop-up.
# Recipe:
# - Product AegisName of the produced item.
# SkillName Skill name required. (Default: null)
# SkillLevel Skill level required. (Default: 1)
# Consumed: List of items consumed to produce the Product.
# - Item AegisName of the consumed item.
# Amount Amount required.
# Clear Remove the item with the given AegisName from Consumed. (Optional)
# NotConsumed: List of items not consumed to produce the Product. (Default: null)
# - Item AegisName of the unconsumed item.
# Clear Remove the item with the given AegisName from NotConsumed. (Optional)
# BaseRate Base rate (in n/10%) for Change Material (ItemLevel: 26). (Default: 1000)
# Make: List of item amounts with their individual rate produced by Change Material (ItemLevel: 26). (Default: null)
# - Amount Amount of item created (unique to the list) for Change Material (ItemLevel: 26).
# Rate Rate to create the Amount (in n/10%) for Change Material (ItemLevel: 26). (Default: 1000. 0 to remove on import)
###########################################################################
Header:
Type: PRODUCE_DB
Version: 1
Footer:
Imports:
- Path: db/pre-re/produce_db.yml
Mode: Prerenewal
- Path: db/re/produce_db.yml
Mode: Renewal
- Path: db/import/produce_db.yml

View File

@@ -948,7 +948,7 @@ Body:
Refineable: true
Script: |
bonus2 bAddEff,Eff_Curse,30;
bonus2 bComaClass,Class_All,10;
bonus2 bComaClass,Class_Normal,10;
- Id: 1133
AegisName: Fire_Brand
Name: Fireblend
@@ -185843,13 +185843,10 @@ Body:
Script: |
.@r = getrefine();
.@val = getskilllv("GN_CARTBOOST");
.@a = (.@r>= 7 ? 20 : (.@r>= 5 ? 10 : 3));
.@b = (.@r>= 7 ? 100 : (.@r>= 5 ? 50 : 0));
bonus bUnbreakableShoes;
bonus bMdef,10;
bonus bMaxHPrate,.@a;
bonus bMaxSPrate,.@a;
bonus2 bVariableCastrate,"GN_CARTCANNON",-.@b;
bonus bMaxHPrate,3;
bonus bMaxSPrate,3;
bonus bHit,20*.@val;
bonus bAspdRate,4*.@val;
bonus bAtkRate,4*getskilllv("GN_FIRE_EXPANSION");
@@ -185861,14 +185858,12 @@ Body:
bonus bMaxSPrate,7;
bonus2 bVariableCastrate,"GN_CARTCANNON",-50;
bonus2 bSkillAtk,"GN_CARTCANNON",BaseLevel/2;
bonus bAllStats,BaseLevel/2;
}
if (.@r>=7) {
bonus bMaxHPrate,10;
bonus bMaxSPrate,10;
bonus2 bVariableCastrate,"GN_CARTCANNON",-50;
bonus2 bSkillAtk,"GN_CARTCANNON",BaseLevel/2;
bonus bAllStats,BaseLevel/2;
}
- Id: 470062
AegisName: Lethargy_P_Shoes

View File

@@ -56781,7 +56781,8 @@ Body:
NoMail: true
NoAuction: true
Script: |
itemskill "RK_LUXANIMA",1;
if ((eaclass()&EAJ_THIRDMASK) == EAJ_RUNE_KNIGHT)
itemskill "RK_LUXANIMA",1;
- Id: 22541
AegisName: PCBang_Coupon_Box6
Name: PC Room Coupon Box VI

View File

@@ -78188,7 +78188,7 @@ Body:
AttackDelay: 1020
AttackMotion: 500
DamageMotion: 768
Ai: 10
Ai: 21
Class: Boss
Drops:
- Item: Brinaranea_Card
@@ -78220,7 +78220,7 @@ Body:
AttackDelay: 608
AttackMotion: 408
DamageMotion: 336
Ai: 10
Ai: 21
Class: Boss
Drops:
- Item: Muspellskoll_Card
@@ -78362,7 +78362,7 @@ Body:
AttackDelay: 750
AttackMotion: 510
DamageMotion: 500
Ai: 10
Ai: 21
Class: Boss
Drops:
- Item: M_Morocc_Card

View File

@@ -102,7 +102,7 @@
1019,Peco Peco@NPC_EMOTION,chase,197,1,2000,0,5000,yes,self,always,0,6,,,,,,
1019,Peco Peco@NPC_FIREATTACK,attack,186,1,2000,0,5000,yes,target,always,0,,,,,,,
1019,Peco Peco@NPC_PROVOCATION,chase,194,1,200,0,5000,yes,target,always,0,,,,,,19,
1020,Mandragora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,randomtarget,always,0,,,,,,,
1020,Mandragora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,target,always,0,,,,,,,
1023,Orc Warrior@NPC_EMOTION,chase,197,1,2000,0,5000,yes,self,always,0,,,,,,,
1023,Orc Warrior@NPC_GROUNDATTACK,attack,185,2,500,500,5000,no,target,always,0,,,,,,6,
1023,Orc Warrior@NPC_EMOTION,chase,197,1,200,0,5000,yes,self,always,0,19,0x81,,,,,
@@ -351,7 +351,7 @@
1067,Cornutus@NPC_WATERATTACK,attack,184,2,500,500,5000,no,target,always,0,,,,,,6,
1067,Cornutus@CR_AUTOGUARD,attack,249,2,500,0,300000,yes,self,always,0,,,,,,,
1067,Cornutus@CR_AUTOGUARD,chase,249,2,2000,0,300000,yes,self,longrangeattacked,,,,,,,,
1068,Hydra@NPC_WATERATTACK,attack,184,2,500,500,5000,no,randomtarget,always,0,,,,,,,
1068,Hydra@NPC_WATERATTACK,attack,184,2,500,500,5000,no,target,always,0,,,,,,,
1069,Swordfish@NPC_WATERATTACK,attack,184,1,2000,0,5000,yes,target,always,0,,,,,,,
1069,Swordfish@WZ_WATERBALL,attack,86,3,500,1500,5000,yes,target,always,0,,,,,,,
1069,Swordfish@WZ_WATERBALL,chase,86,3,500,1500,5000,yes,target,always,0,,,,,,,
@@ -603,9 +603,9 @@
1117,Evil Druid@NPC_UNDEADATTACK,chase,347,3,500,500,5000,no,target,always,0,,,,,,9,
1117,Evil Druid@WZ_HEAVENDRIVE,attack,91,5,500,1200,5000,yes,target,always,0,,,,,,,
1117,Evil Druid@WZ_HEAVENDRIVE,chase,91,5,500,1200,5000,yes,target,always,0,,,,,,,
1118,Flora@NPC_BLOODDRAIN,attack,199,1,500,0,5000,yes,randomtarget,always,0,,,,,,,
1118,Flora@NPC_BLOODDRAIN,attack,199,1,500,0,5000,yes,target,always,0,,,,,,,
1118,Flora@NPC_EMOTION,idle,197,1,2000,0,5000,yes,self,always,0,2,,,,,,
1118,Flora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,randomtarget,always,0,,,,,,,
1118,Flora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,target,always,0,,,,,,,
1119,Frilldora@AS_CLOAKING,attack,135,1,2000,200,5000,yes,self,always,0,,,,,,,
1119,Frilldora@AS_CLOAKING,idle,135,1,2000,200,5000,yes,self,always,0,,,,,,,
1119,Frilldora@AS_CLOAKING,chase,135,1,2000,200,5000,yes,self,always,0,,,,,,,
@@ -1301,7 +1301,7 @@
1276,Raydric Archer@CR_AUTOGUARD,attack,249,2,500,0,300000,yes,self,always,0,,,,,,,
1277,Greatest General@NPC_BLINDATTACK,idle,177,3,10000,1500,5000,no,randomtarget,longrangeattacked,,,,,,,6,
1277,Greatest General@NPC_BLINDATTACK,idle,177,3,10000,1500,5000,no,randomtarget,casttargeted,,,,,,,6,
1277,Greatest General@NPC_FIREATTACK,attack,186,2,500,500,5000,no,randomtarget,always,0,,,,,,,
1277,Greatest General@NPC_FIREATTACK,attack,186,2,500,500,5000,no,target,always,0,,,,,,,
1277,Greatest General@WZ_EARTHSPIKE,idle,90,3,5000,1500,5000,no,randomtarget,longrangeattacked,,,,,,,6,
1277,Greatest General@WZ_EARTHSPIKE,idle,90,3,5000,1500,5000,no,randomtarget,casttargeted,,,,,,,6,
1278,Stalactite Golem@NPC_STUNATTACK,attack,179,4,500,1500,5000,no,target,always,0,,,,,,6,
@@ -1584,7 +1584,7 @@
1367,Blazer@WZ_SIGHTRASHER,attack,81,5,500,1000,5000,no,target,always,0,,,,,,6,
1368,Geographer@AL_HEAL,attack,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,60,,,,,,,
1368,Geographer@AL_HEAL,idle,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,60,,,,,,,
1368,Geographer@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,randomtarget,always,0,,,,,,,
1368,Geographer@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,target,always,0,,,,,,,
1369,Grand Peco@AS_SONICBLOW,attack,136,5,500,800,5000,no,target,always,0,,,,,,6,
1369,Grand Peco@NPC_FIREATTACK,attack,186,3,500,500,5000,no,target,always,0,,,,,,6,
1369,Grand Peco@NPC_EMOTION,chase,197,1,200,0,5000,yes,self,always,0,19,0x81,,,,,
@@ -2569,8 +2569,8 @@
1510,Hylozoist@MO_BODYRELOCATION,chase,264,1,2000,500,5000,no,target,always,0,,,,,,,
1511,Amon Ra@NPC_BLOODDRAIN,idle,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
1511,Amon Ra@NPC_BLOODDRAIN,idle,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,always,0,,,,,,29,
1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,always,0,,,,,,29,
1511,Amon Ra@NPC_SUMMONMONSTER,idle,209,5,5000,0,10000,no,self,longrangeattacked,0,1474,1477,1438,,,9,
1511,Amon Ra@NPC_SUMMONMONSTER,idle,209,5,5000,0,10000,no,self,casttargeted,0,1474,1477,1438,,,9,
1511,Amon Ra@NPC_SUMMONMONSTER,attack,209,5,5000,0,10000,no,self,longrangeattacked,0,1474,1477,1438,,,9,
@@ -2589,11 +2589,11 @@
1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,skillused,83,,,,,,9,
1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,longrangeattacked,,,,,,,9,
1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,casttargeted,,,,,,,9,
1511,Amon Ra@WZ_METEOR,attack,83,11,5000,0,3000,yes,randomtarget,always,0,,,,,,9,
1511,Amon Ra@WZ_METEOR,attack,83,11,5000,0,3000,yes,target,always,0,,,,,,9,
1511,Amon Ra@WZ_FIREPILLAR,idle,80,10,10000,0,2000,yes,around2,always,0,,,,,,,
1511,Amon Ra@WZ_FIREPILLAR,idle,80,10,10000,0,2000,yes,around2,always,0,,,,,,,
1511,Amon Ra@WZ_FIREPILLAR,attack,80,10,5000,0,2000,yes,around2,always,0,,,,,,,
1511,Amon Ra@NPC_DARKBLESSING,attack,203,1,5000,0,2000,no,randomtarget,always,0,,,,,,,
1511,Amon Ra@NPC_DARKBLESSING,attack,203,1,5000,0,2000,no,target,always,0,,,,,,,
1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,5000,yes,randomtarget,always,0,,,,,,9,
1511,Amon Ra@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
1511,Amon Ra@AL_TELEPORT,walk,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
@@ -3405,18 +3405,18 @@
1663,Laurell Weinder@NPC_EMOTION,idle,197,1,10000,0,5000,yes,self,skillused,28,15,,,,,,
1663,Laurell Weinder@NPC_EMOTION,attack,197,1,10000,0,5000,yes,self,skillused,28,15,,,,,,
1663,Laurell Weinder@NPC_EMOTION,chase,197,1,10000,0,5000,yes,self,skillused,28,15,,,,,,
1664,Photon Cannon@NPC_WINDATTACK,attack,187,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
1664,Photon Cannon@NPC_WINDATTACK,attack,187,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
1664,Photon Cannon@NPC_WINDATTACK,attack,187,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
1665,Photon Cannon@NPC_FIREATTACK,attack,186,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
1665,Photon Cannon@NPC_FIREATTACK,attack,186,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
1665,Photon Cannon@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
1666,Photon Cannon@NPC_WATERATTACK,attack,184,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
1666,Photon Cannon@NPC_WATERATTACK,attack,184,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
1666,Photon Cannon@NPC_WATERATTACK,attack,184,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
1664,Photon Cannon@NPC_WINDATTACK,attack,187,5,1000,1000,10000,yes,target,always,0,,,,,,,
1664,Photon Cannon@NPC_WINDATTACK,attack,187,3,2000,500,5000,yes,target,always,0,,,,,,,
1664,Photon Cannon@NPC_WINDATTACK,attack,187,1,10000,0,0,yes,target,always,0,,,,,,,
1665,Photon Cannon@NPC_FIREATTACK,attack,186,5,1000,1000,10000,yes,target,always,0,,,,,,,
1665,Photon Cannon@NPC_FIREATTACK,attack,186,3,2000,500,5000,yes,target,always,0,,,,,,,
1665,Photon Cannon@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,target,always,0,,,,,,,
1666,Photon Cannon@NPC_WATERATTACK,attack,184,5,1000,1000,10000,yes,target,always,0,,,,,,,
1666,Photon Cannon@NPC_WATERATTACK,attack,184,3,2000,500,5000,yes,target,always,0,,,,,,,
1666,Photon Cannon@NPC_WATERATTACK,attack,184,1,10000,0,0,yes,target,always,0,,,,,,,
1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,5,1000,1000,10000,yes,target,always,0,,,,,,,
1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,3,2000,500,5000,yes,target,always,0,,,,,,,
1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,1,10000,0,0,yes,target,always,0,,,,,,,
1668,Archdam@NPC_PIERCINGATT,attack,158,5,1000,0,5000,yes,target,always,0,,,,,,,
1668,Archdam@NPC_GUIDEDATTACK,attack,172,2,500,1000,20000,no,target,always,0,,,,,,29,
1668,Archdam@KN_SPEARSTAB,attack,58,5,500,800,5000,no,target,always,0,,,,,,,
@@ -3453,9 +3453,9 @@
1673,Dimik@NPC_COMBOATTACK,attack,171,4,500,700,5000,no,target,always,0,,,,,,,
1673,Dimik@NPC_COMBOATTACK,chase,171,4,500,700,5000,no,target,always,0,,,,,,,
1673,Dimik@NPC_FIREATTACK,attack,186,3,500,0,5000,yes,target,always,0,,,,,,,
1674,Monemus@NPC_FIREATTACK,attack,186,10,500,1000,30000,yes,randomtarget,always,0,,,,,,,
1674,Monemus@NPC_FIREATTACK,attack,186,3,1000,0,10000,yes,randomtarget,always,0,,,,,,,
1674,Monemus@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
1674,Monemus@NPC_FIREATTACK,attack,186,10,500,1000,30000,yes,target,always,0,,,,,,,
1674,Monemus@NPC_FIREATTACK,attack,186,3,1000,0,10000,yes,target,always,0,,,,,,,
1674,Monemus@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,target,always,0,,,,,,,
1675,Venatu@NPC_SILENCEATTACK,attack,178,3,500,700,5000,no,target,always,0,,,,,,,
1675,Venatu@NPC_GUIDEDATTACK,attack,172,3,500,1000,20000,no,target,always,0,,,,,,6,
1675,Venatu@NPC_STUNATTACK,attack,179,2,500,1500,5000,no,target,always,0,,,,,,11,
@@ -3531,11 +3531,11 @@
1688,Lady Tany@AL_TELEPORT,idle,26,1,1000,0,30000,yes,self,always,0,,,,,,,
1688,Lady Tany@AL_TELEPORT,attack,26,1,1000,0,30000,yes,self,always,0,,,,,,,
1688,Lady Tany@NPC_EXPULSION,attack,674,1,1000,1000,10000,no,target,myhpltmaxrate,60,,,,,,,
1688,Lady Tany@AC_CHARGEARROW,attack,148,1,2000,0,5000,yes,randomtarget,always,0,,,,,,6,
1688,Lady Tany@NPC_COMBOATTACK,attack,171,1,1000,0,5000,no,randomtarget,always,0,,,,,,,
1688,Lady Tany@NPC_CRITICALSLASH,attack,170,1,500,500,5000,no,randomtarget,always,0,,,,,,6,
1688,Lady Tany@NPC_GUIDEDATTACK,attack,172,5,500,0,20000,no,randomtarget,always,0,,,,,,,
1688,Lady Tany@NPC_STUNATTACK,attack,179,5,500,0,5000,no,randomtarget,always,0,,,,,,,
1688,Lady Tany@AC_CHARGEARROW,attack,148,1,2000,0,5000,yes,target,always,0,,,,,,6,
1688,Lady Tany@NPC_COMBOATTACK,attack,171,1,1000,0,5000,no,target,always,0,,,,,,,
1688,Lady Tany@NPC_CRITICALSLASH,attack,170,1,500,500,5000,no,target,always,0,,,,,,6,
1688,Lady Tany@NPC_GUIDEDATTACK,attack,172,5,500,0,20000,no,target,always,0,,,,,,,
1688,Lady Tany@NPC_STUNATTACK,attack,179,5,500,0,5000,no,target,always,0,,,,,,,
1688,Lady Tany@NPC_DEFENDER,attack,205,1,500,0,30000,yes,self,longrangeattacked,,,,,,,29,
1688,Lady Tany@NPC_POWERUP,attack,349,5,10000,0,30000,yes,self,myhpltmaxrate,30,,,,,,6,
1688,Lady Tany@NPC_SUMMONSLAVE,attack,196,5,10000,2000,5000,no,self,slavele,2,1691,,,,,,
@@ -4228,18 +4228,18 @@
1779,Ktullanux@NPC_AGIUP,attack,350,5,2000,0,100000,yes,self,always,0,,,,,,,
1779,Ktullanux@NPC_AGIUP,attack,350,5,10000,0,25000,yes,self,myhpltmaxrate,30,,,,,,,
1779,Ktullanux@AL_HEAL,idle,28,11,10000,0,10000,yes,self,myhpltmaxrate,50,,,,,,,
1780,Muscipular@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
1780,Muscipular@KN_SPEARSTAB,attack,58,5,500,800,5000,no,randomtarget,always,0,,,,,,6,
1780,Muscipular@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
1780,Muscipular@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,target,always,0,,,,,,,
1780,Muscipular@KN_SPEARSTAB,attack,58,5,500,800,5000,no,target,always,0,,,,,,6,
1780,Muscipular@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,target,always,0,,,,,,,
1780,Muscipular@AL_HEAL,attack,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,50,,,,,,,
1780,Muscipular@AL_HEAL,idle,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,50,,,,,,,
1780,Muscipular@NPC_PETRIFYATTACK,attack,180,5,500,0,5000,yes,randomtarget,always,0,,,,,,,
1781,Drosera@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
1781,Drosera@KN_PIERCE,attack,56,5,500,700,5000,no,randomtarget,always,0,,,,,,,
1781,Drosera@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
1780,Muscipular@NPC_PETRIFYATTACK,attack,180,5,500,0,5000,yes,target,always,0,,,,,,,
1781,Drosera@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,target,always,0,,,,,,,
1781,Drosera@KN_PIERCE,attack,56,5,500,700,5000,no,target,always,0,,,,,,,
1781,Drosera@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,target,always,0,,,,,,,
1781,Drosera@RG_CLOSECONFINE,attack,1005,1,1000,0,30000,yes,target,always,0,,,,,,,
1781,Drosera@NPC_GUIDEDATTACK,attack,172,3,500,1000,20000,no,randomtarget,always,0,,,,,,6,
1781,Drosera@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,randomtarget,always,0,,,,,,,
1781,Drosera@NPC_GUIDEDATTACK,attack,172,3,500,1000,20000,no,target,always,0,,,,,,6,
1781,Drosera@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,target,always,0,,,,,,,
1782,Roween@NPC_WINDATTACK,attack,187,2,500,500,5000,no,target,always,0,,,,,,,
1782,Roween@NPC_COMBOATTACK,attack,171,4,500,500,5000,no,target,always,0,,,,,,6,
1782,Roween@NPC_EMOTION,idle,197,1,2000,0,5000,yes,self,always,0,22,0x308D,,,,,
@@ -7980,8 +7980,8 @@
2311,Manananggal@AL_TELEPORT,walk,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
2311,Manananggal@AL_TELEPORT,idle,26,1,1000,0,30000,yes,self,always,0,,,,,,,
2311,Manananggal@AL_TELEPORT,attack,26,1,100,0,30000,yes,self,always,0,,,,,,,
2311,Manananggal@NPC_BLOODDRAIN,chase,199,1,2000,0,5000,yes,randomtarget,myhpltmaxrate,50,,,,,,3,
2311,Manananggal@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,myhpltmaxrate,50,,,,,,3,
2311,Manananggal@NPC_BLOODDRAIN,chase,199,1,2000,0,5000,yes,target,myhpltmaxrate,50,,,,,,3,
2311,Manananggal@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,myhpltmaxrate,50,,,,,,3,
2311,Manananggal@NPC_COMBOATTACK,chase,171,5,1000,0,5000,yes,target,always,0,,,,,,7,
2311,Manananggal@NPC_COMBOATTACK,attack,171,5,1000,0,5000,yes,target,always,0,,,,,,7,
2312,Mangkukulam@AL_TELEPORT,idle,26,1,500,0,30000,yes,self,always,0,,,,,,,
@@ -8009,8 +8009,8 @@
2315,Wakwak@AL_TELEPORT,walk,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
2315,Wakwak@AL_TELEPORT,idle,26,1,500,0,30000,yes,self,always,0,,,,,,,
2315,Wakwak@AL_TELEPORT,attack,26,1,50,0,30000,yes,self,always,0,,,,,,,
2315,Wakwak@NPC_BLOODDRAIN,chase,199,1,2000,0,5000,yes,randomtarget,myhpltmaxrate,50,,,,,,3,
2315,Wakwak@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,myhpltmaxrate,50,,,,,,3,
2315,Wakwak@NPC_BLOODDRAIN,chase,199,1,2000,0,5000,yes,target,myhpltmaxrate,50,,,,,,3,
2315,Wakwak@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,myhpltmaxrate,50,,,,,,3,
2315,Wakwak@NPC_DARKTHUNDER,chase,341,3,1000,500,5000,yes,target,always,0,,,,,,29,
2315,Wakwak@NPC_DARKTHUNDER,attack,341,3,1000,500,5000,yes,target,always,0,,,,,,29,
2315,Wakwak@NPC_CURSEATTACK,attack,181,3,500,800,5000,no,target,always,0,,,,,,0,
@@ -8113,7 +8113,7 @@
2331,Seaweed@AL_HEAL,idle,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,100,,,,,,2,
2337,Hidden Mob@NPC_INVISIBLE,idle,353,1,10000,0,30000,yes,self,always,0,,,,,,,
2337,Hidden Mob@NPC_INVISIBLE,attack,353,1,10000,0,30000,yes,self,always,0,,,,,,,
2337,Hidden Mob@WZ_METEOR,attack,83,5,10000,0,1000,yes,randomtarget,always,0,,,,,,,
2337,Hidden Mob@WZ_METEOR,attack,83,5,10000,0,1000,yes,target,always,0,,,,,,,
2338,Bangungot Manananggal@AL_TELEPORT,idle,26,1,500,0,5000,yes,self,always,0,,,,,,,
2338,Bangungot Manananggal@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,no,target,always,0,,,,,,3,
2338,Bangungot Manananggal@NPC_COMBOATTACK,attack,171,5,500,700,5000,no,target,always,0,,,,,,1,
@@ -8129,11 +8129,11 @@
2339,Bangungot Mangkukulam@NPC_DARKSTRIKE,chase,340,9,500,700,5000,no,target,always,0,,,,,,29,
2339,Bangungot Mangkukulam@NPC_MENTALBREAKER,attack,159,3,500,800,5000,no,target,always,0,,,,,,14,
2339,Bangungot Mangkukulam@NPC_MENTALBREAKER,chase,159,3,500,800,5000,no,target,always,0,,,,,,14,
2340,Tiyanak@NPC_BLOODDRAIN,attack,199,1,500,0,5000,yes,randomtarget,always,0,,,,,,2,
2340,Tiyanak@NPC_BLOODDRAIN,attack,199,1,500,0,5000,yes,target,always,0,,,,,,2,
2340,Tiyanak@NPC_EMOTION,idle,197,1,2000,0,5000,yes,self,always,0,29,,,,,,
2340,Tiyanak@CR_AUTOGUARD,chase,249,2,2000,0,300000,yes,self,longrangeattacked,,,,,,,,
2340,Tiyanak@CR_AUTOGUARD,attack,249,2,500,0,300000,yes,self,always,0,,,,,,,
2340,Tiyanak@NPC_CRITICALSLASH,attack,170,1,500,500,5000,no,randomtarget,always,0,,,,,,6,
2340,Tiyanak@NPC_CRITICALSLASH,attack,170,1,500,500,5000,no,target,always,0,,,,,,6,
2340,Tiyanak@NPC_REBIRTH,dead,208,3,2000,0,10000,yes,self,always,0,,,,,,,
2341,RWC Boss@NPC_CALLSLAVE,attack,352,1,10000,0,30000,yes,self,always,0,,,,,,,
2341,RWC Boss@NPC_CALLSLAVE,idle,352,1,10000,0,30000,yes,self,always,0,,,,,,,
@@ -8162,7 +8162,7 @@
2341,RWC Boss@NPC_CRITICALWOUND,attack,673,4,2000,0,5000,yes,target,always,0,,,,,,,
2343,Hidden Mob@NPC_INVISIBLE,idle,353,1,10000,0,30000,yes,self,always,0,,,,,,,
2343,Hidden Mob@NPC_INVISIBLE,attack,353,1,10000,0,30000,yes,self,always,0,,,,,,,
2343,Hidden Mob@WZ_STORMGUST,attack,89,5,10000,0,1000,yes,randomtarget,always,0,,,,,,,
2343,Hidden Mob@WZ_STORMGUST,attack,89,5,10000,0,1000,yes,target,always,0,,,,,,,
// Nightmare Pyramids
2353,Nightmare Minorous@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
@@ -8198,8 +8198,8 @@
2360,Nightmare Ancient Mummy@NPC_DARKBREATH,attack,202,4,500,800,5000,no,target,always,0,,,,,,7,
2362,Nightmare Amon Ra@NPC_BLOODDRAIN,idle,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
2362,Nightmare Amon Ra@NPC_BLOODDRAIN,idle,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
2362,Nightmare Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
2362,Nightmare Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
2362,Nightmare Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,always,0,,,,,,29,
2362,Nightmare Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,always,0,,,,,,29,
2362,Nightmare Amon Ra@NPC_SUMMONMONSTER,idle,209,5,5000,0,10000,no,self,longrangeattacked,0,2357,2359,2361,,,9,
2362,Nightmare Amon Ra@NPC_SUMMONMONSTER,idle,209,5,5000,0,10000,no,self,casttargeted,0,1474,1477,1438,,,9,
2362,Nightmare Amon Ra@NPC_SUMMONMONSTER,attack,209,5,5000,0,10000,no,self,longrangeattacked,0,2357,2359,2361,,,9,
@@ -8218,11 +8218,11 @@
2362,Nightmare Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,skillused,83,,,,,,9,
2362,Nightmare Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,longrangeattacked,,,,,,,9,
2362,Nightmare Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,casttargeted,,,,,,,9,
2362,Nightmare Amon Ra@WZ_METEOR,attack,83,11,5000,0,3000,yes,randomtarget,always,0,,,,,,9,
2362,Nightmare Amon Ra@WZ_METEOR,attack,83,11,5000,0,3000,yes,target,always,0,,,,,,9,
2362,Nightmare Amon Ra@WZ_FIREPILLAR,idle,80,10,10000,0,2000,yes,around2,always,0,,,,,,,
2362,Nightmare Amon Ra@WZ_FIREPILLAR,idle,80,10,10000,0,2000,yes,around2,always,0,,,,,,,
2362,Nightmare Amon Ra@WZ_FIREPILLAR,attack,80,10,5000,0,2000,yes,around2,always,0,,,,,,,
2362,Nightmare Amon Ra@NPC_DARKBLESSING,attack,203,1,5000,0,2000,no,randomtarget,always,0,,,,,,,
2362,Nightmare Amon Ra@NPC_DARKBLESSING,attack,203,1,5000,0,2000,no,target,always,0,,,,,,,
2362,Nightmare Amon Ra@WZ_METEOR,idle,83,11,10000,0,5000,yes,randomtarget,always,0,,,,,,9,
2362,Nightmare Amon Ra@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
2362,Nightmare Amon Ra@AL_TELEPORT,walk,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,

50
db/re/produce_db.yml Normal file
View File

@@ -0,0 +1,50 @@
# This file is a part of rAthena.
# Copyright(C) 2023 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/>.
#
###########################################################################
# Item Produce Database
###########################################################################
#
# Item Produce Settings
#
###########################################################################
# - ItemLevel Number which determines what kind of a crafting window will pop-up.
# Recipe:
# - Product AegisName of the produced item.
# SkillName Skill name required. (Default: null)
# SkillLevel Skill level required. (Default: 1)
# Consumed: List of items consumed to produce the Product.
# - Item AegisName of the consumed item.
# Amount Amount required.
# Clear Remove the item with the given AegisName from Consumed. (Optional)
# NotConsumed: List of items not consumed to produce the Product. (Default: null)
# - Item AegisName of the unconsumed item.
# Clear Remove the item with the given AegisName from NotConsumed. (Optional)
# BaseRate Base rate (in n/10%) for Change Material (ItemLevel: 26). (Default: 1000)
# Make: List of item amounts with their individual rate produced by Change Material (ItemLevel: 26). (Default: null)
# - Amount Amount of item created (unique to the list) for Change Material (ItemLevel: 26).
# Rate Rate to create the Amount (in n/10%) for Change Material (ItemLevel: 26). (Default: 1000. 0 to remove on import)
###########################################################################
Header:
Type: PRODUCE_DB
Version: 1
Footer:
Imports:
- Path: db/re/skill_produce_db.yml
- Path: db/re/skill_changematerial_db.yml

View File

@@ -0,0 +1,911 @@
# This file is a part of rAthena.
# Copyright(C) 2023 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/>.
#
###########################################################################
# Item Produce Database
###########################################################################
#
# Item Produce Settings
#
###########################################################################
# - ItemLevel Number which determines what kind of a crafting window will pop-up.
# Recipe:
# - Product AegisName of the produced item.
# Skill: Skill requirement. (Default: null)
# Name Skill name required.
# Level Skill level required.
# Consumed: List of items consumed to produce the Product.
# - Item AegisName of the consumed item.
# Amount Amount required.
# Clear Remove the item with the given AegisName from Consumed. (Optional)
# NotConsumed: List of items not consumed to produce the Product. (Default: null)
# - Item AegisName of the unconsumed item.
# Clear Remove the item with the given AegisName from NotConsumed. (Optional)
# BaseRate Base rate (in n/10%) for Change Material (ItemLevel: 26). (Default: 1000)
# Make: List of item amounts with their individual rate produced by Change Material (ItemLevel: 26). (Default: null)
# - Amount Amount of item created (unique to the list) for Change Material (ItemLevel: 26).
# Rate Rate to create the Amount (in n/10%) for Change Material (ItemLevel: 26). (Default: 1000. 0 to remove on import)
###########################################################################
Header:
Type: PRODUCE_DB
Version: 1
Body:
- ItemLevel: 26
Recipe:
- Product: Sacred_Masque
BaseRate: 800
Make:
- Amount: 8
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Grasshopper's_Leg
Amount: 45
- Item: Yoyo_Tail
Amount: 35
- Product: Long_Hair
Make:
- Amount: 4
Rate: 800
- Amount: 6
Rate: 200
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Pencil_Case
Amount: 40
- Item: Tiger's_Skin
Amount: 5
- Product: Phracon
BaseRate: 800
Make:
- Amount: 8
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Glass_Bead
Amount: 40
- Item: Spawn
Amount: 45
- Product: Lantern
BaseRate: 800
Make:
- Amount: 3
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Blossom_Of_Maneater
Amount: 20
- Item: Solid_Shell
Amount: 10
- Product: Acorn
BaseRate: 800
Make:
- Amount: 4
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Cactus_Needle
Amount: 30
- Item: Snail's_Shell
Amount: 10
- Product: Frozen_Heart
BaseRate: 800
Make:
- Amount: 6
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Moth_Dust
Amount: 35
- Item: Raccoondog_Doll
Amount: 25
- Product: Horrendous_Mouth
BaseRate: 800
Make:
- Amount: 9
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Dragon_Scale
Amount: 45
- Item: Stem
Amount: 45
- Product: Detrimindexta
BaseRate: 800
Make:
- Amount: 5
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Chrysalis
Amount: 40
- Item: Flesh_Of_Clam
Amount: 10
- Product: Detonator
BaseRate: 800
Make:
- Amount: 7
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Feather_Of_Birds
Amount: 25
- Item: Nose_Ring
Amount: 45
- Product: Tweezer
BaseRate: 800
Make:
- Amount: 4
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Monkey_Doll
Amount: 5
- Item: Worm_Peelings
Amount: 40
- Product: Petite_DiablOfs_Horn
Make:
- Amount: 1
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Resin
Amount: 10
- Item: Stone_Heart
Amount: 5
- Product: Root_Of_Maneater
Make:
- Amount: 4
Rate: 800
- Amount: 6
Rate: 200
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Talon
Amount: 25
- Item: Tooth_Of_
Amount: 20
- Product: Conch
BaseRate: 800
Make:
- Amount: 3
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Gill
Amount: 5
- Item: Immortal_Heart
Amount: 25
- Product: Rotten_Scale
BaseRate: 800
Make:
- Amount: 7
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Shell
Amount: 20
- Item: Thin_N'_Long_Tongue
Amount: 50
- Product: Elder_Pixie's_Beard
Make:
- Amount: 8
Rate: 800
- Amount: 12
Rate: 200
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Bee_Sting
Amount: 35
- Item: Petite_DiablOfs_Wing
Amount: 45
- Product: Lizard_Scruff
BaseRate: 800
Make:
- Amount: 3
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Karvodailnirol
Amount: 15
- Item: Scale_Of_Snakes
Amount: 20
- Product: Emveretarcon
BaseRate: 800
Make:
- Amount: 4
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Grasshopper_Doll
Amount: 40
- Item: Heart_Of_Mermaid
Amount: 5
- Product: Chinese_Ink
BaseRate: 800
Make:
- Amount: 4
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Bear's_Foot
Amount: 20
- Item: Black_Ladle
Amount: 25
- Product: Spiderweb
BaseRate: 800
Make:
- Amount: 8
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Fin
Amount: 50
- Item: Slender_Snake
Amount: 35
- Product: Reins
BaseRate: 800
Make:
- Amount: 8
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Chonchon_Doll
Amount: 30
- Item: Stuffed_Doll
Amount: 50
- Product: Wooden_Block
BaseRate: 800
Make:
- Amount: 2
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Rotten_Bandage
Amount: 10
- Item: Single_Cell
Amount: 10
- Product: Tentacle
Make:
- Amount: 4
Rate: 800
- Amount: 6
Rate: 200
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Decayed_Nail
Amount: 40
- Item: Wild_Boar's_Mane
Amount: 5
- Product: Mixture
Make:
- Amount: 4
Rate: 800
- Amount: 6
Rate: 200
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Posionous_Canine
Amount: 15
- Item: Powder_Of_Butterfly
Amount: 30
- Product: Colorful_Shell
Make:
- Amount: 9
Rate: 800
- Amount: 13
Rate: 200
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Horn
Amount: 50
- Item: Zargon
Amount: 45
- Product: Wing_Of_Moth
BaseRate: 800
Make:
- Amount: 5
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Frozen_Rose
Amount: 20
- Item: Reptile_Tongue
Amount: 30
- Product: Nipper
Make:
- Amount: 6
Rate: 800
- Amount: 9
Rate: 200
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Earthworm_Peeling
Amount: 40
- Item: Sticky_Mucus
Amount: 25
- Product: Turtle_Shell
BaseRate: 800
Make:
- Amount: 4
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Fluff
Amount: 5
- Item: Poring_Doll
Amount: 40
- Product: Nail_Of_Orc
BaseRate: 800
Make:
- Amount: 6
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Garlet
Amount: 10
- Item: Raccoon_Leaf
Amount: 50
- Product: Dragon_Canine
Make:
- Amount: 8
Rate: 800
- Amount: 12
Rate: 200
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Osiris_Doll
Amount: 50
- Item: Sticky_Webfoot
Amount: 35
- Product: Skirt_Of_Virgin
BaseRate: 800
Make:
- Amount: 6
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Head_Of_Medusa
Amount: 35
- Item: Scales_Shell
Amount: 30
- Product: Dragon_Train
BaseRate: 800
Make:
- Amount: 6
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Sharpened_Cuspid
Amount: 35
- Item: Tooth_Of_Bat
Amount: 25
- Product: Dokkaebi_Horn
BaseRate: 800
Make:
- Amount: 4
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Lip_Of_Ancient_Fish
Amount: 25
- Item: Shining_Scales
Amount: 15
- Product: Grit
BaseRate: 800
Make:
- Amount: 8
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Crystal_Mirror
Amount: 35
- Item: Limb_Of_Mantis
Amount: 50
- Product: Sharp_Scale
BaseRate: 800
Make:
- Amount: 3
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Clam_Shell
Amount: 20
- Item: Horseshoe
Amount: 10
- Product: Short_Leg
BaseRate: 800
Make:
- Amount: 6
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Claw_Of_Wolves
Amount: 20
- Item: Scell
Amount: 45
- Product: Starsand_Of_Witch
BaseRate: 800
Make:
- Amount: 2
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Blue_Porcelain
Amount: 15
- Item: Insect_Feeler
Amount: 10
- Product: Fox_Tail
Make:
- Amount: 2
Rate: 800
- Amount: 3
Rate: 200
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Animal's_Skin
Amount: 10
- Item: Rouge
Amount: 15
- Product: Cobold_Hair
Make:
- Amount: 6
Rate: 800
- Amount: 9
Rate: 200
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Jellopy
Amount: 45
- Item: Wedding_Bouquet
Amount: 20
- Product: Jaws_Of_Ant
Make:
- Amount: 4
Rate: 800
- Amount: 6
Rate: 200
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Spore_Doll
Amount: 20
- Item: Witherless_Rose
Amount: 20
- Product: Voucher_Of_Orcish_Hero
BaseRate: 800
Make:
- Amount: 5
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Nail_Of_Mole
Amount: 45
- Item: Tree_Root
Amount: 5
- Product: Sacred_Marks
BaseRate: 800
Make:
- Amount: 4
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Pumpkin_Head
Amount: 30
- Item: Scorpion's_Tail
Amount: 10
- Product: Alchol
BaseRate: 800
Make:
- Amount: 9
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Orcish_Voucher
Amount: 50
- Item: Skel_Bone
Amount: 40
- Product: Crap_Shell
BaseRate: 800
Make:
- Amount: 8
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Baphomet_Doll
Amount: 50
- Item: Fish_Tail
Amount: 30
- Product: Tendon
BaseRate: 800
Make:
- Amount: 3
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Feather
Amount: 5
- Item: Orcish_Cuspid
Amount: 25
- Product: Tiger_Footskin
BaseRate: 800
Make:
- Amount: 2
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Pointed_Scale
Amount: 5
- Item: White_Platter
Amount: 20
- Product: Hinalle
Make:
- Amount: 2
Rate: 200
- Amount: 4
Rate: 800
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Bunch_Of_Flowers
Amount: 45
- Item: Moustache_Of_Mole
Amount: 40
- Product: Counteragent
BaseRate: 800
Make:
- Amount: 4
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Evil_Horn
Amount: 15
- Item: Mementos
Amount: 30
- Product: Tooth_Of_Ancient_Fish
Make:
- Amount: 6
Rate: 800
- Amount: 9
Rate: 200
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Bill_Of_Birds
Amount: 35
- Item: Transparent_Cloth
Amount: 30
- Product: Rat_Tail
Make:
- Amount: 7
Rate: 800
- Amount: 10
Rate: 200
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Golden_Hair
Amount: 40
- Item: Mushroom_Spore
Amount: 35
- Product: Coal
BaseRate: 500
Make:
- Amount: 1
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Guard
Amount: 1
- Product: Steel
Make:
- Amount: 10
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Tsurugi
Amount: 1
- Product: Cigar
Make:
- Amount: 1
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Orcish_Axe
Amount: 1
- Product: Bone_Wand
BaseRate: 200
Make:
- Amount: 1
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Broken_Farming_Utensil
Amount: 100
- Item: Clattering_Skull
Amount: 100
- Product: Cigar
Make:
- Amount: 1
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Orcish_Axe
Amount: 1
- Item: Orcish_Voucher
Amount: 100
- Product: Starsand_Of_Witch
BaseRate: 800
Make:
- Amount: 2
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Moth_Dust
Amount: 100
- Item: Scell
Amount: 100
- Product: Soft_Feather
Make:
- Amount: 1
Rate: 200
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Feather
Amount: 30
- Item: Feather_Of_Birds
Amount: 30
- Product: Wind_Of_Verdure
Make:
- Amount: 1
Rate: 500
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Ice_Piece
Amount: 100
- Product: Crystal_Blue
Make:
- Amount: 1
Rate: 500
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Claw_Of_Wolves
Amount: 100
- Product: Soft_Silk_Cloth
Make:
- Amount: 2
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Transparent_Cloth
Amount: 10
- Product: Transparent_Cloth
Make:
- Amount: 5
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Soft_Silk_Cloth
Amount: 2
- Product: Boost500_To_Throw
Make:
- Amount: 1
Rate: 100
- Amount: 2
Rate: 250
- Amount: 5
Rate: 500
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Boost500
Amount: 10
- Item: Empty_Potion
Amount: 10
- Item: Flexible_String
Amount: 10
- Product: Full_SwingK_To_Throw
Make:
- Amount: 1
Rate: 100
- Amount: 2
Rate: 250
- Amount: 5
Rate: 500
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Empty_Potion
Amount: 10
- Item: Flexible_String
Amount: 10
- Item: Full_SwingK
Amount: 10
- Product: Mana_Plus_To_Throw
Make:
- Amount: 1
Rate: 100
- Amount: 2
Rate: 250
- Amount: 5
Rate: 500
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Empty_Potion
Amount: 10
- Item: Flexible_String
Amount: 10
- Item: Mana_Plus
Amount: 10
- Product: Cure_Free_To_Throw
Make:
- Amount: 1
Rate: 100
- Amount: 2
Rate: 250
- Amount: 5
Rate: 500
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Cure_Free
Amount: 10
- Item: Empty_Potion
Amount: 10
- Item: Flexible_String
Amount: 10
- Product: Stamina_Up_M_To_Throw
Make:
- Amount: 1
Rate: 100
- Amount: 2
Rate: 250
- Amount: 5
Rate: 500
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Empty_Potion
Amount: 10
- Item: Flexible_String
Amount: 10
- Item: Stamina_Up_M
Amount: 10
- Product: Digestive_F_To_Throw
Make:
- Amount: 1
Rate: 100
- Amount: 2
Rate: 250
- Amount: 5
Rate: 500
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Digestive_F
Amount: 10
- Item: Empty_Potion
Amount: 10
- Item: Flexible_String
Amount: 10
- Product: HP_Inc_PotS_To_Throw
Make:
- Amount: 10
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Bottle_To_Throw
Amount: 10
- Item: HP_Increase_PotionS
Amount: 10
- Product: HP_Inc_PotM_To_Throw
Make:
- Amount: 10
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Bottle_To_Throw
Amount: 10
- Item: HP_Increase_PotionM
Amount: 10
- Product: HP_Inc_PotL_To_Throw
Make:
- Amount: 10
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Bottle_To_Throw
Amount: 10
- Item: HP_Increase_PotionL
Amount: 10
- Product: SP_Inc_PotS_To_Throw
Make:
- Amount: 10
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Bottle_To_Throw
Amount: 10
- Item: SP_Increase_PotionS
Amount: 10
- Product: SP_Inc_PotM_To_Throw
Make:
- Amount: 10
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Bottle_To_Throw
Amount: 10
- Item: SP_Increase_PotionM
Amount: 10
- Product: SP_Inc_PotL_To_Throw
Make:
- Amount: 10
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Bottle_To_Throw
Amount: 10
- Item: SP_Increase_PotionL
Amount: 10
- Product: En_White_PotZ_To_Throw
Make:
- Amount: 10
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Bottle_To_Throw
Amount: 10
- Item: Enrich_White_PotionZ
Amount: 10
- Product: Vitata500_To_Throw
Make:
- Amount: 10
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Bottle_To_Throw
Amount: 10
- Item: Vitata500
Amount: 10
- Product: En_Cel_Juice_To_Throw
Make:
- Amount: 10
SkillName: GN_CHANGEMATERIAL
SkillLevel: 1
Consumed:
- Item: Bottle_To_Throw
Amount: 10
- Item: Enrich_Celermine_Juice
Amount: 10

View File

@@ -7234,9 +7234,8 @@ Body:
Type: Magic
TargetType: Self
DamageFlags:
IgnoreAtkCard: true
IgnoreFlee: true
Range: 5
IgnoreDefense: true
Range: 9
Hit: Single
HitCount: 1
Element: Holy
@@ -10250,15 +10249,15 @@ Body:
Element: Weapon
Duration1:
- Level: 1
Time: 4000
Time: 2000
- Level: 2
Time: 8000
Time: 4000
- Level: 3
Time: 12000
Time: 6000
- Level: 4
Time: 16000
Time: 8000
- Level: 5
Time: 24000
Time: 10000
CastDelayFlags:
IgnoreStatus: true
Requires:
@@ -10274,7 +10273,7 @@ Body:
- Level: 5
Amount: 12
SpiritSphereCost: 1
Status: Stop
Status: Ankle
- Id: 372
Name: CH_CHAINCRUSH
Description: Chain Crush Combo
@@ -11048,7 +11047,7 @@ Body:
TargetType: Attack
Flags:
TargetTrap: true
Range: 5
Range: 4
Hit: Multi_Hit
HitCount: 5
Element: Weapon
@@ -11103,7 +11102,7 @@ Body:
2hSword: true
1hSpear: true
2hSpear: true
Status: Stop
Status: Ankle
- Id: 398
Name: LK_HEADCRUSH
Description: Traumatic Blow
@@ -11313,7 +11312,7 @@ Body:
TargetType: Attack
DamageFlags:
NoDamage: true
Range: 7
Range: 9
Hit: Single
HitCount: 1
ActiveInstance: 3
@@ -16709,7 +16708,7 @@ Body:
Flags:
IsNpc: true
HitCount: 1
Duration1: -1
Duration1: 300000
Status: Invincible
- Id: 686
Name: NPC_INVINCIBLEOFF
@@ -16721,8 +16720,6 @@ Body:
Flags:
IsNpc: true
HitCount: 1
Duration1: 60000
Status: InvincibleOff
- Id: 687
Name: NPC_ALLHEAL
Description: Full Heal
@@ -46224,7 +46221,7 @@ Body:
TargetType: Attack
Flags:
TargetTrap: true
Range: 5
Range: 4
Hit: Multi_Hit
HitCount: 5
Element: Weapon
@@ -46268,7 +46265,7 @@ Body:
Amount: 27
- Level: 5
Amount: 30
Status: Stop
Status: Ankle
- Id: 8219
Name: ML_DEFENDER
Description: Defending_Aura
@@ -46959,9 +46956,7 @@ Body:
Range: 2
Hit: Single
HitCount: 1
Duration1: 10000
Cooldown: 30000
Status: InvincibleOff
- Id: 8401
Name: EL_CIRCLE_OF_FIRE
Description: Circle of Fire

2531
db/re/skill_produce_db.yml Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -786,7 +786,6 @@ Body:
NoBanishingBuster: true
NoClearance: true
RemoveOnChangeMap: true
MinDuration: 5000
- Status: Keeping
DurationLookup: NPC_KEEPING
CalcFlags:
@@ -2928,23 +2927,12 @@ Body:
Icon: EFST_INVINCIBLE
DurationLookup: NPC_INVINCIBLE
CalcFlags:
Aspd: true
Speed: true
Flags:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
EndOnStart:
Invincibleoff: true
- Status: Invincibleoff
DurationLookup: NPC_INVINCIBLEOFF
CalcFlags:
Speed: true
Flags:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
EndOnStart:
Invincible: true
- Status: Manu_Atk
Icon: EFST_MANU_ATK
Flags:

View File

@@ -3,7 +3,7 @@
//===== By: ==================================================
//= rAthena Dev Team
//===== Last Updated: ========================================
//= 20130613
//= 20240414
//===== Description: =========================================
//= List of available permissions and their functions.
//============================================================
@@ -227,6 +227,6 @@ Allows player to use the client command /macro_detector.
*macro_register
Allows player to use the client commands /maco_register (used to add new captcha) and /macro_preview (used to preview captcha by ID).
Allows player to use the client commands /macro_register (used to add new captcha) and /macro_preview (used to preview captcha by ID).
---------------------------------------

View File

@@ -1,5 +1,5 @@
# This file is a part of rAthena.
# Copyright(C) 2023 rAthena Development Team
# Copyright(C) 2024 rAthena Development Team
# https://rathena.org - https://github.com/rathena
#
# This program is free software: you can redistribute it and/or modify

View File

@@ -0,0 +1,24 @@
###########################################################################
# Item Produce Database
###########################################################################
#
# Item Produce Settings
#
###########################################################################
# - ItemLevel Number which determines what kind of a crafting window will pop-up.
# Recipe:
# - Product AegisName of the produced item.
# SkillName Skill name required. (Default: null)
# SkillLevel Skill level required. (Default: 1)
# Consumed: List of items consumed to produce the Product.
# - Item AegisName of the consumed item.
# Amount Amount required.
# Clear Remove the item with the given AegisName from Consumed. (Optional)
# NotConsumed: List of items not consumed to produce the Product. (Default: null)
# - Item AegisName of the unconsumed item.
# Clear Remove the item with the given AegisName from NotConsumed. (Optional)
# BaseRate Base rate (in n/10%) for Change Material (ItemLevel: 26). (Default: 1000)
# Make: List of item amounts with their individual rate produced by Change Material (ItemLevel: 26). (Default: null)
# - Amount Amount of item created (unique to the list) for Change Material (ItemLevel: 26).
# Rate Rate to create the Amount (in n/10%) for Change Material (ItemLevel: 26). (Default: 1000. 0 to remove on import)
###########################################################################

File diff suppressed because it is too large Load Diff

View File

@@ -2820,7 +2820,8 @@ void char_set_defaults(){
*/
void char_config_split_startpoint( char* w1_value, char* w2_value, struct s_point_str start_point[MAX_STARTPOINT], short* count ){
char *lineitem, **fields;
int i = 0, fields_length = 3 + 1;
int i = 0;
size_t fields_length = 3 + 1;
(*count) = 0; // Reset to begin reading
@@ -2859,7 +2860,8 @@ void char_config_split_startpoint( char* w1_value, char* w2_value, struct s_poin
void char_config_split_startitem(char *w1_value, char *w2_value, struct startitem start_items[MAX_STARTITEM])
{
char *lineitem, **fields;
int i = 0, fields_length = 3 + 1;
int i = 0;
size_t fields_length = 3 + 1;
fields = (char **)aMalloc(fields_length * sizeof(char *));
if (fields == NULL)

View File

@@ -91,7 +91,7 @@ void chlogif_pincode_start(int fd, struct char_session_data* sd){
* @param tick : Scheduled tick
* @param id : GID linked to that timered call
* @param data : data transmited for delayed function
* @return
* @return
*/
TIMER_FUNC(chlogif_send_acc_tologin){
if ( chlogif_isconnected() ){
@@ -391,27 +391,70 @@ int chlogif_parse_keepalive(int fd){
*/
void chlogif_parse_change_sex_sub(int sex, int acc, int char_id, int class_, int guild_id)
{
// job modification //@TODO switch would be faster
if (class_ == JOB_BARD || class_ == JOB_DANCER)
class_ = (sex == SEX_MALE ? JOB_BARD : JOB_DANCER);
else if (class_ == JOB_CLOWN || class_ == JOB_GYPSY)
class_ = (sex == SEX_MALE ? JOB_CLOWN : JOB_GYPSY);
else if (class_ == JOB_BABY_BARD || class_ == JOB_BABY_DANCER)
class_ = (sex == SEX_MALE ? JOB_BABY_BARD : JOB_BABY_DANCER);
else if (class_ == JOB_MINSTREL || class_ == JOB_WANDERER)
class_ = (sex == SEX_MALE ? JOB_MINSTREL : JOB_WANDERER);
else if (class_ == JOB_MINSTREL_T || class_ == JOB_WANDERER_T)
class_ = (sex == SEX_MALE ? JOB_MINSTREL_T : JOB_WANDERER_T);
else if (class_ == JOB_BABY_MINSTREL || class_ == JOB_BABY_WANDERER)
class_ = (sex == SEX_MALE ? JOB_BABY_MINSTREL : JOB_BABY_WANDERER);
else if (class_ == JOB_KAGEROU || class_ == JOB_OBORO)
class_ = (sex == SEX_MALE ? JOB_KAGEROU : JOB_OBORO);
else if (class_ == JOB_BABY_KAGEROU || class_ == JOB_BABY_OBORO)
class_ = (sex == SEX_MALE ? JOB_BABY_KAGEROU : JOB_BABY_OBORO);
else if (class_ == JOB_TROUBADOUR || class_ == JOB_TROUVERE)
class_ = (sex == SEX_MALE ? JOB_TROUBADOUR : JOB_TROUVERE);
else if (class_ == JOB_SHINKIRO || class_ == JOB_SHIRANUI)
class_ = (sex == SEX_MALE ? JOB_SHINKIRO : JOB_SHIRANUI);
// job modification
switch (class_)
{
case JOB_BARD:
class_ = JOB_DANCER;
break;
case JOB_DANCER:
class_ = JOB_BARD;
break;
case JOB_CLOWN:
class_ = JOB_GYPSY;
break;
case JOB_GYPSY:
class_ = JOB_CLOWN;
break;
case JOB_BABY_BARD:
class_ = JOB_BABY_DANCER;
break;
case JOB_BABY_DANCER:
class_ = JOB_BABY_BARD;
break;
case JOB_MINSTREL:
class_ = JOB_WANDERER;
break;
case JOB_WANDERER:
class_ = JOB_MINSTREL;
break;
case JOB_MINSTREL_T:
class_ = JOB_WANDERER_T;
break;
case JOB_WANDERER_T:
class_ = JOB_MINSTREL_T;
break;
case JOB_BABY_MINSTREL:
class_ = JOB_BABY_WANDERER;
break;
case JOB_BABY_WANDERER:
class_ = JOB_BABY_MINSTREL;
break;
case JOB_KAGEROU:
class_ = JOB_OBORO;
break;
case JOB_OBORO:
class_ = JOB_KAGEROU;
break;
case JOB_BABY_KAGEROU:
class_ = JOB_BABY_OBORO;
break;
case JOB_BABY_OBORO:
class_ = JOB_BABY_KAGEROU;
break;
case JOB_TROUBADOUR:
class_ = JOB_TROUVERE;
break;
case JOB_TROUVERE:
class_ = JOB_TROUBADOUR;
break;
case JOB_SHINKIRO:
class_ = JOB_SHIRANUI;
break;
case JOB_SHIRANUI:
class_ = JOB_SHINKIRO;
break;
}
if (SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `equip` = '0' WHERE `char_id` = '%d'", schema_config.inventory_db, char_id))
Sql_ShowDebug(sql_handle);

View File

@@ -205,7 +205,7 @@ public:
}
// Resize to only fit all existing non null entries
this->cache.resize(max_key);
this->cache.resize(max_key + 1);
// Free the memory that was allocated too much
this->cache.shrink_to_fit();
this->loaded = true;

View File

@@ -278,9 +278,8 @@ namespace rathena {
if( rathena::util::safe_addition( a, b, result ) ){
return cap;
}else{
return result;
}
return std::min(result, cap);
}
template <typename T> void tolower( T& string ){

View File

@@ -34,6 +34,8 @@
#include "pc_groups.hpp"
#include "pet.hpp"
using namespace rathena;
struct Battle_Config battle_config;
static struct eri *delay_damage_ers; //For battle delay damage structures.
@@ -254,33 +256,42 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int
return bl_list[rnd()%c];
}
/*========================================== [Playtester]
/**
* Deals damage without delay, applies additional effects and triggers monster events
* This function is called from battle_delay_damage or battle_delay_damage_sub
* All other instances of battle damage should also go through this function (i.e. anything that displays a damage number)
* Consider calling this function or battle_fix_damage instead status_fix_damage directly
* @param src: Source of damage
* @param target: Target of damage
* @param damage: Damage to be dealt
* @param delay: Damage delay
* @param skill_lv: Level of skill used
* @param skill_id: ID o skill used
* @param skill_id: ID of skill used
* @param dmg_lv: State of the attack (miss, etc.)
* @param attack_type: Type of the attack (BF_NORMAL|BF_SKILL|BF_SHORT|BF_LONG|BF_WEAPON|BF_MAGIC|BF_MISC)
* @param additional_effects: Whether additional effect should be applied
* @param additional_effects: Whether additional effects should be applied (otherwise it's just damage+coma)
* @param isspdamage: If the damage is done to SP
* @param tick: Current tick
*------------------------------------------*/
void battle_damage(struct block_list *src, struct block_list *target, int64 damage, t_tick delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, t_tick tick, bool isspdamage) {
* @return HP+SP+AP (0 if HP/SP/AP remained unchanged)
*/
int battle_damage(struct block_list *src, struct block_list *target, int64 damage, t_tick delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, t_tick tick, bool isspdamage) {
int dmg_change;
map_session_data* sd = nullptr;
if (src)
sd = BL_CAST(BL_PC, src);
map_freeblock_lock();
if (isspdamage)
status_fix_spdamage(src, target, damage, delay, skill_id);
dmg_change = status_fix_spdamage(src, target, damage, delay, skill_id);
else if (sd && battle_check_coma(*sd, *target, (e_battle_flag)attack_type))
dmg_change = status_damage(src, target, damage, 0, delay, 16, skill_id); // Coma attack
else
status_fix_damage(src, target, damage, delay, skill_id); // We have to separate here between reflect damage and others [icescope]
dmg_change = status_fix_damage(src, target, damage, delay, skill_id);
if (attack_type && !status_isdead(target) && additional_effects)
skill_additional_effect(src, target, skill_id, skill_lv, attack_type, dmg_lv, tick);
if (dmg_lv > ATK_BLOCK && attack_type)
if (dmg_lv > ATK_BLOCK && attack_type && additional_effects)
skill_counter_additional_effect(src, target, skill_id, skill_lv, attack_type, tick);
// This is the last place where we have access to the actual damage type, so any monster events depending on type must be placed here
if (target->type == BL_MOB) {
if (target->type == BL_MOB && additional_effects) {
mob_data *md = BL_CAST(BL_MOB, target);
if (md != nullptr) {
@@ -298,6 +309,7 @@ void battle_damage(struct block_list *src, struct block_list *target, int64 dama
}
}
map_freeblock_unlock();
return dmg_change;
}
/// Damage Delayed Structure
@@ -331,9 +343,7 @@ TIMER_FUNC(battle_delay_damage_sub){
//Deal damage
battle_damage(src, target, dat->damage, dat->delay, dat->skill_lv, dat->skill_id, dat->dmg_lv, dat->attack_type, dat->additional_effects, tick, dat->isspdamage);
} else if( !src && dat->skill_id == CR_REFLECTSHIELD ) { // it was monster reflected damage, and the monster died, we pass the damage to the character as expected
map_freeblock_lock();
status_fix_damage(target, target, dat->damage, dat->delay, dat->skill_id);
map_freeblock_unlock();
battle_fix_damage(target, target, dat->damage, dat->delay, dat->skill_id);
}
}
@@ -412,6 +422,10 @@ int battle_delay_damage(t_tick tick, int amotion, struct block_list *src, struct
return 0;
}
int battle_fix_damage(struct block_list* src, struct block_list* target, int64 damage, t_tick walkdelay, uint16 skill_id) {
return battle_damage(src, target, damage, walkdelay, 0, skill_id, ATK_DEF, BF_MISC, false, gettick(), false);
}
/**
* Does attribute fix modifiers.
* Added passing of the chars so that the status changes can affect it. [Skotlex]
@@ -1548,11 +1562,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
return 0;
}
status_change* tsc = status_get_sc(bl); //check target status
if( tsc && tsc->getSCE(SC_INVINCIBLE) && !tsc->getSCE(SC_INVINCIBLEOFF) )
return 1;
switch (skill_id) {
#ifndef RENEWAL
case PA_PRESSURE:
@@ -1566,6 +1575,8 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
return damage; //These skills bypass everything else.
}
status_change* tsc = status_get_sc(bl); //check target status
// Nothing can reduce the damage, but Safety Wall and Millennium Shield can block it completely.
// So can defense sphere's but what the heck is that??? [Rytech]
if (skill_id == SJ_NOVAEXPLOSING && !(tsc && (tsc->getSCE(SC_SAFETYWALL) || tsc->getSCE(SC_MILLENNIUMSHIELD)))) {
@@ -1880,9 +1891,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
}
}
if( sc->getSCE(SC_INVINCIBLE) && !sc->getSCE(SC_INVINCIBLEOFF) )
damage += damage * 75 / 100;
if ((sce = sc->getSCE(SC_BLOODLUST)) && flag&BF_WEAPON && damage > 0 && rnd()%100 < sce->val3)
status_heal(src, damage * sce->val4 / 100, 0, 3);
@@ -2499,7 +2507,7 @@ static int64 battle_calc_base_damage(struct block_list *src, struct status_data
if (atkmin > atkmax)
atkmin = atkmax;
if(flag&BDMG_ARROW && !(flag&BDMG_THROW)) { //Bows
if(flag&BDMG_ARROW) { //Bows
atkmin = atkmin*atkmax/100;
if (atkmin > atkmax)
atkmax = atkmin;
@@ -2845,6 +2853,10 @@ bool is_infinite_defense(struct block_list *target, int flag)
if(status_has_mode(tstatus,MD_IGNOREMISC) && flag&(BF_MISC) )
return true;
status_change* tsc = status_get_sc(target);
if (tsc && tsc->getSCE(SC_INVINCIBLE))
return true;
return false;
}
@@ -3359,12 +3371,11 @@ static bool attack_ignores_def(struct Damage* wd, struct block_list *src, struct
/**
* This function lists which skills are unaffected by refine bonus, masteries, Star Crumbs and Spirit Spheres
* This function is also used to determine if atkpercent applies
* @param src: Source of the attack
* @param skill_id: Skill being used
* @param chk_flag: The bonus that is currently being checked for, see e_bonus_chk_flag
* @return true = bonus applies; false = bonus does not apply
*/
static bool battle_skill_stacks_masteries_vvs(struct block_list &src, uint16 skill_id, e_bonus_chk_flag chk_flag)
static bool battle_skill_stacks_masteries_vvs(uint16 skill_id, e_bonus_chk_flag chk_flag)
{
switch (skill_id) {
// PC skills that are unaffected
@@ -3381,41 +3392,9 @@ static bool battle_skill_stacks_masteries_vvs(struct block_list &src, uint16 ski
case LG_EARTHDRIVE:
case NPC_DRAGONBREATH:
return false;
case CR_GRANDCROSS:
case NPC_GRANDDARKNESS:
// Grand Cross is influenced by refine bonus but not by atkpercent / masteries / Star Crumbs / Spirit Spheres
if (chk_flag != BCHK_REFINE)
return false;
break;
case LK_SPIRALPIERCE:
// Spiral Pierce is influenced only by refine bonus and Star Crumbs for players
if (src.type == BL_PC && chk_flag != BCHK_REFINE && chk_flag != BCHK_STAR)
return false;
break;
}
return true;
}
/**
* This function lists which skills are unaffected by EDP and the elemental bonus from Magnum Break / EDP
* Unit skills (e.g. Bomb and Freezing Trap) are never affected.
* @param skill_id: Skill being used
* @return true = bonus applies; false = bonus does not apply
*/
static bool battle_skill_stacks_edp_element(uint16 skill_id)
{
switch (skill_id) {
case TF_SPRINKLESAND:
case AS_SPLASHER:
case ASC_METEORASSAULT:
case ASC_BREAKER:
case AS_VENOMKNIFE:
case AM_ACIDTERROR:
return false;
default:
//Unit skills
if (skill_get_unit_id(skill_id))
if (chk_flag != BCHK_REFINE && chk_flag != BCHK_STAR)
return false;
break;
}
@@ -3670,7 +3649,9 @@ int battle_get_misc_element(struct block_list* src, struct block_list* target, u
static void battle_min_damage(struct Damage &wd, struct block_list &src, uint16 skill_id, int64 min) {
if (is_attack_right_handed(&src, skill_id)) {
wd.damage = cap_value(wd.damage, min, INT64_MAX);
#ifndef RENEWAL
wd.basedamage = cap_value(wd.basedamage, min, INT64_MAX);
#endif
}
// Left-hand damage is always capped to 0
if (is_attack_left_handed(&src, skill_id)) {
@@ -3789,27 +3770,45 @@ static void battle_calc_element_damage(struct Damage* wd, struct block_list *src
// These mastery bonuses are non-elemental and should apply even if the attack misses
// They are still increased by the EDP/Magnum Break bonus damage (WATK_ELEMENT)
// In renewal these bonuses do not apply when the attack misses
if (sd && battle_skill_stacks_masteries_vvs(*src, skill_id, BCHK_STAR)) {
if (sd && battle_skill_stacks_masteries_vvs(skill_id, BCHK_STAR)) {
// Star Crumb bonus damage
ATK_ADD2(wd->damage, wd->damage2, sd->right_weapon.star, sd->left_weapon.star);
}
// Check if general mastery bonuses apply (above check is only for Star Crumb)
if (battle_skill_stacks_masteries_vvs(*src, skill_id, BCHK_ALL)) {
if (battle_skill_stacks_masteries_vvs(skill_id, BCHK_ALL)) {
// Spirit Sphere bonus damage
ATK_ADD(wd->damage, wd->damage2, battle_get_spiritball_damage(*wd, *src, skill_id));
// Skill-specific bonuses
if (skill_id == TF_POISON) {
ATK_ADD(wd->damage, wd->damage2, 15 * skill_lv);
// Envenom applies the attribute table to the base damage and then again to the final damage
wd->damage = battle_attr_fix(src, target, wd->damage, right_element, tstatus->def_ele, tstatus->ele_lv, 1);
switch(skill_id) {
case TF_POISON:
ATK_ADD(wd->damage, wd->damage2, 15 * skill_lv);
// Envenom applies the attribute table to the base damage and then again to the final damage
wd->damage = battle_attr_fix(src, target, wd->damage, right_element, tstatus->def_ele, tstatus->ele_lv, 1);
break;
case NJ_SYURIKEN:
ATK_ADD(wd->damage, wd->damage2, 4 * skill_lv);
if (sd) {
ATK_ADD(wd->damage, wd->damage2, 3 * pc_checkskill(sd, NJ_TOBIDOUGU));
ATK_ADD(wd->damage, wd->damage2, sd->bonus.arrow_atk);
}
// Applies attribute table on neutral element to the final damage
wd->damage = battle_attr_fix(src, target, wd->damage, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv, 1);
break;
case NJ_KUNAI:
if (sd) {
ATK_ADD(wd->damage, wd->damage2, 3 * sd->bonus.arrow_atk);
}
// Applies attribute table on neutral element to the final damage
wd->damage = battle_attr_fix(src, target, wd->damage, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv, 1);
break;
}
}
// These bonuses do not apply to skills that ignore element, unit skills and skills that have their own base damage formula
// These bonuses do not apply to skills that ignore +% damage cards
// If damage was reduced below 0 and was not increased again to a positive value through mastery bonuses, these bonuses are ignored
// Any of these are only applied to your right hand weapon in pre-renewal
if (!nk[NK_IGNOREELEMENT] && (wd->damage > 0 || wd->damage2 > 0) && sc && battle_skill_stacks_edp_element(skill_id)) {
if (!nk[NK_IGNOREELEMENT] && !nk[NK_IGNOREATKCARD] && (wd->damage > 0 || wd->damage2 > 0) && sc) {
// EDP bonus damage
// This has to be applied after mastery bonuses but still before the elemental extra damage
@@ -3850,12 +3849,14 @@ static void battle_calc_attack_masteries(struct Damage* wd, struct block_list *s
struct status_data *sstatus = status_get_status_data(src);
int t_class = status_get_class(target);
#ifndef RENEWAL
if (sd) {
wd->basedamage = battle_addmastery(sd, target, wd->basedamage, 0);
}
#endif
// Check if mastery damage applies to current skill
if (sd && battle_skill_stacks_masteries_vvs(*src, skill_id, BCHK_ALL))
if (sd && battle_skill_stacks_masteries_vvs(skill_id, BCHK_ALL))
{ //Add mastery damage
uint16 skill;
@@ -3880,14 +3881,12 @@ static void battle_calc_attack_masteries(struct Damage* wd, struct block_list *s
ATK_ADD2(wd->masteryAtk, wd->masteryAtk2, sd->right_weapon.star, sd->left_weapon.star);
// Spirit Sphere bonus damage
ATK_ADD(wd->masteryAtk, wd->masteryAtk2, battle_get_spiritball_damage(*wd, *src, skill_id));
#endif
if (skill_id == NJ_SYURIKEN && (skill = pc_checkskill(sd,NJ_TOBIDOUGU)) > 0) { // !TODO: Confirm new mastery formula
if (skill_id == NJ_SYURIKEN && (skill = pc_checkskill(sd,NJ_TOBIDOUGU)) > 0) {
ATK_ADD(wd->damage, wd->damage2, 3 * skill);
#ifdef RENEWAL
ATK_ADD(wd->masteryAtk, wd->masteryAtk2, 3 * skill);
#endif
}
#endif
switch(skill_id) {
case RA_WUGDASH:
@@ -3956,10 +3955,10 @@ static void battle_calc_damage_parts(struct Damage* wd, struct block_list *src,s
if (sd && sd->sc.getSCE(SC_SEVENWIND)) { // Mild Wind applies element to status ATK as well as weapon ATK [helvetica]
wd->statusAtk = battle_attr_fix(src, target, wd->statusAtk, right_element, tstatus->def_ele, tstatus->ele_lv);
wd->statusAtk2 = battle_attr_fix(src, target, wd->statusAtk, left_element, tstatus->def_ele, tstatus->ele_lv);
wd->statusAtk2 = battle_attr_fix(src, target, wd->statusAtk2, left_element, tstatus->def_ele, tstatus->ele_lv);
} else { // status atk is considered neutral on normal attacks [helvetica]
wd->statusAtk = battle_attr_fix(src, target, wd->statusAtk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
wd->statusAtk2 = battle_attr_fix(src, target, wd->statusAtk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
wd->statusAtk2 = battle_attr_fix(src, target, wd->statusAtk2, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
}
// Check critical
@@ -4178,8 +4177,9 @@ static void battle_calc_skill_base_damage(struct Damage* wd, struct block_list *
default:
// Flags that apply to both pre-renewal and renewal
bflag = (is_attack_critical(wd, src, target, skill_id, skill_lv, false) ? BDMG_CRIT : BDMG_NONE) |
(!skill_id && sc && sc->getSCE(SC_CHANGE) ? BDMG_MAGIC : BDMG_NONE);
bflag = BDMG_NONE;
if (is_attack_critical(wd, src, target, skill_id, skill_lv, false)) bflag |= BDMG_CRIT;
if (!skill_id && sc && sc->getSCE(SC_CHANGE)) bflag |= BDMG_MAGIC;
#ifdef RENEWAL
if (sd)
battle_calc_damage_parts(wd, src, target, skill_id, skill_lv);
@@ -4190,24 +4190,26 @@ static void battle_calc_skill_base_damage(struct Damage* wd, struct block_list *
}
#else
// Pre-renewal exclusive flags
if (is_skill_using_arrow(src, skill_id)) bflag |= BDMG_ARROW;
if (skill_id == HW_MAGICCRASHER) bflag |= BDMG_MAGIC;
if (sc && sc->getSCE(SC_WEAPONPERFECTION)) bflag |= BDMG_NOSIZE;
if (is_skill_using_arrow(src, skill_id) && sd) {
switch(sd->status.weapon) {
case W_BOW:
bflag |= BDMG_ARROW;
break;
case W_REVOLVER:
case W_RIFLE:
case W_GATLING:
case W_SHOTGUN:
case W_GRENADE:
if (bflag & BDMG_CRIT) {
bflag &= ~(BDMG_ARROW); // Criticals with any guns are calculated like melee criticals
// Criticals with any guns are calculated like melee criticals
if (!(bflag & BDMG_CRIT)) {
bflag |= BDMG_ARROW;
}
break;
default:
bflag |= BDMG_THROW; // for ex. shuriken must not be influenced by DEX
// Attacks that use ammo are calculated like melee attacks as long as no ranged weapon is equipped
// Some skills manually add arrow_atk as mastery bonus later (e.g. Throw Shuriken, Throw Kunai)
break;
}
}
@@ -4440,7 +4442,7 @@ static void battle_calc_multi_attack(struct Damage* wd, struct block_list *src,s
*/
static unsigned short battle_get_atkpercent(struct block_list& bl, uint16 skill_id, status_change& sc)
{
if (!battle_skill_stacks_masteries_vvs(bl, skill_id, BCHK_ALL))
if (bl.type == BL_PC && !battle_skill_stacks_masteries_vvs(skill_id, BCHK_ALL))
return 100;
int atkpercent = 100;
@@ -4467,10 +4469,11 @@ static unsigned short battle_get_atkpercent(struct block_list& bl, uint16 skill_
atkpercent += sc.getSCE(SC_BLOODLUST)->val2;
if (sc.getSCE(SC_FLEET))
atkpercent += sc.getSCE(SC_FLEET)->val3;
if (sc.getSCE(SC_INVINCIBLE))
atkpercent += sc.getSCE(SC_INVINCIBLE)->val2;
/* Only few selected skills should use this function, DO NOT ADD any that are not caused by the skills listed below
* TODO:
* NPC_INVINCIBLE (+100)
* GD_GUARDUP (2*skLevel+8)
* EL_WATERBARRIER (-3)
* SC_ENERVATION (-30/-40/-50)
@@ -6280,9 +6283,6 @@ static int64 battle_calc_skill_constant_addition(struct Damage* wd, struct block
else
atk = sstatus->matk_min;
break;
case NJ_SYURIKEN:
atk = 4 * skill_lv;
break;
#endif
#ifdef RENEWAL
case HT_FREEZINGTRAP:
@@ -6593,7 +6593,7 @@ static void battle_calc_defense_reduction(struct Damage* wd, struct block_list *
#ifndef RENEWAL
//Damage reduction: [VIT*0.3] + RND(0, [VIT^2/150] - [VIT*0.3] - 1) + [VIT*0.5]
vit_def = ((3 * def2) / 10);
vit_def += rnd_value(0, (def2 * def2) / 150 - ((3 * def2) / 10) - 1);
vit_def += rnd_value(0, max(0, (def2 * def2) / 150 - ((3 * def2) / 10) - 1));
vit_def += (def2 / 2);
#else
vit_def = def2;
@@ -6635,7 +6635,9 @@ static void battle_calc_defense_reduction(struct Damage* wd, struct block_list *
return;
if (is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_R) || is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_L))
return;
[[fallthrough]];
case CR_GRANDCROSS: // Grand Cross is marked as "IgnoreDefense" in renewal as it's applied at the end after already combining ATK and MATK
case NPC_GRANDDARKNESS:
// Defense reduction by flat value.
// This completely bypasses the normal RE DEF Reduction formula.
wd->damage -= (def1 + vit_def);
@@ -6693,7 +6695,7 @@ static void battle_calc_attack_post_defense(struct Damage* wd, struct block_list
#ifndef RENEWAL
//Refine bonus
if (sd) {
if (battle_skill_stacks_masteries_vvs(*src, skill_id, BCHK_REFINE)) {
if (battle_skill_stacks_masteries_vvs(skill_id, BCHK_REFINE)) {
ATK_ADD2(wd->damage, wd->damage2, sstatus->rhw.atk2, sstatus->lhw.atk2);
}
wd->basedamage += sstatus->rhw.atk2;
@@ -6814,18 +6816,16 @@ static void battle_calc_attack_left_right_hands(struct Damage* wd, struct block_
if (sd) {
int skill;
if (!is_attack_right_handed(src, skill_id) && is_attack_left_handed(src, skill_id)) {
wd->damage = wd->damage2;
wd->damage2 = 0;
} else if(sd->status.weapon == W_KATAR && !skill_id) { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2)
if(sd->status.weapon == W_KATAR && !skill_id) { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2)
skill = pc_checkskill(sd,TF_DOUBLE);
wd->damage2 = (int64)wd->damage * (1 + (skill * 2))/100;
#ifdef RENEWAL
} else if(is_attack_right_handed(src, skill_id) && is_attack_left_handed(src, skill_id) && sd->status.weapon != W_KATAR) { //Dual-wield
} else if(is_attack_left_handed(src, skill_id) && sd->status.weapon != W_KATAR) { //Dual-wield
#else
} else if(is_attack_right_handed(src, skill_id) && is_attack_left_handed(src, skill_id)) { //Dual-wield
} else if(is_attack_left_handed(src, skill_id)) { //Dual-wield
#endif
if (wd->damage) {
// If you only have a weapon in the left hand, then your main hand damage will be identical to an unarmed attack
if (is_attack_right_handed(src, skill_id) && wd->damage) {
if( (sd->class_&MAPID_BASEMASK) == MAPID_THIEF ) {
skill = pc_checkskill(sd,AS_RIGHT);
ATK_RATER(wd->damage, 50 + (skill * 10))
@@ -6837,6 +6837,7 @@ static void battle_calc_attack_left_right_hands(struct Damage* wd, struct block_
if(wd->damage < 1)
wd->damage = 1;
}
// Left hand damage will always be adjusted, even if you don't have a weapon in the main hand
if (wd->damage2) {
if( (sd->class_&MAPID_BASEMASK) == MAPID_THIEF) {
skill = pc_checkskill(sd,AS_LEFT);
@@ -6969,7 +6970,7 @@ static void battle_calc_weapon_final_atk_modifiers(struct Damage* wd, struct blo
{
ATK_RATER(wd->damage, 50)
clif_skill_nodamage(target,target,ST_REJECTSWORD, tsc->getSCE(SC_REJECTSWORD)->val1,1);
status_fix_damage(target,src,wd->damage,clif_damage(target,src,gettick(),0,0,wd->damage,0,DMG_NORMAL,0,false),ST_REJECTSWORD);
battle_fix_damage(target,src,wd->damage,clif_damage(target,src,gettick(),0,0,wd->damage,0,DMG_NORMAL,0,false),ST_REJECTSWORD);
if (status_isdead(target))
return;
if( --(tsc->getSCE(SC_REJECTSWORD)->val3) <= 0 )
@@ -6987,7 +6988,7 @@ static void battle_calc_weapon_final_atk_modifiers(struct Damage* wd, struct blo
clif_skill_damage(target, src, gettick(), status_get_amotion(src), 0, rdamage,
1, SR_CRESCENTELBOW_AUTOSPELL, tsc->getSCE(SC_CRESCENTELBOW)->val1, DMG_SINGLE); // This is how official does
clif_damage(src, target, gettick(), status_get_amotion(src)+1000, 0, rdamage/10, 1, DMG_NORMAL, 0, false);
status_damage(target, src, rdamage, 0, 0, 0, 0);
battle_fix_damage(target, src, rdamage, 0, SR_CRESCENTELBOW);
status_damage(src, target, rdamage/10, 0, 0, 1, 0);
status_change_end(target, SC_CRESCENTELBOW);
}
@@ -7066,10 +7067,12 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
wd.flag = BF_WEAPON; //Initial Flag
wd.flag |= (skill_id||wd.miscflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish]
wd.isspdamage = false;
wd.damage = wd.damage2 = wd.basedamage =
wd.damage = wd.damage2 =
#ifdef RENEWAL
wd.statusAtk = wd.statusAtk2 = wd.equipAtk = wd.equipAtk2 = wd.weaponAtk = wd.weaponAtk2 = wd.masteryAtk = wd.masteryAtk2 =
wd.percentAtk = wd.percentAtk2 =
#else
wd.basedamage =
#endif
0;
@@ -7347,11 +7350,13 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
wd.dmg_lv = ATK_FLEE;
else if(!(infdef = is_infinite_defense(target, wd.flag))) { //no need for math against plants
#ifndef RENEWAL
// First call function with skill_id 0 to get base damage of a normal attack
battle_calc_skill_base_damage(&wd, src, target, 0, 0); // base damage
wd.basedamage = wd.damage;
// Now get actual skill damage
if (skill_id != 0)
#endif
battle_calc_skill_base_damage(&wd, src, target, skill_id, skill_lv); // base skill damage
int64 ratio = 0;
@@ -7541,9 +7546,6 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
battle_calc_element_damage(&wd, src, target, skill_id, skill_lv);
if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS)
return wd; //Enough, rest is not needed.
#ifdef RENEWAL
if (is_attack_critical(&wd, src, target, skill_id, skill_lv, false)) {
if (sd) { //Check for player so we don't crash out, monsters don't have bonus crit rates [helvetica]
@@ -7559,11 +7561,6 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
#endif
switch (skill_id) {
#ifndef RENEWAL
case NJ_KUNAI:
ATK_ADD(wd.damage, wd.damage2, 90);
break;
#endif
case TK_DOWNKICK:
case TK_STORMKICK:
case TK_TURNKICK:
@@ -7719,7 +7716,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
return ad;
}
//Initial Values
ad.damage = 1;
ad.damage = 0;
ad.div_ = skill_get_num(skill_id,skill_lv);
ad.amotion = (skill_get_inf(skill_id)&INF_GROUND_SKILL ? 0 : sstatus->amotion); //Amotion should be 0 for ground skills.
ad.dmotion = tstatus->dmotion;
@@ -8821,6 +8818,46 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
ad.damage = ad.damage * (100-mdef)/100 - mdef2;
#endif
}
//Apply the physical part of the skill's damage. [Skotlex]
switch (skill_id) {
case CR_GRANDCROSS:
case NPC_GRANDDARKNESS: {
// Pre-re ATK = Take atk, apply def reduction and add refine bonus
// Final Damage = (ATK+MATK)*RATIO
// Renewal ATK = Take total atk
// Final Damage = ((ATK+MATK)/2)*RATIO - (tDEF + tMDEF)
// No need to go through the whole physical damage code
struct Damage wd = initialize_weapon_data(src, target, skill_id, skill_lv, mflag);
battle_calc_skill_base_damage(&wd, src, target, skill_id, skill_lv);
// Calculate ATK
#ifdef RENEWAL
if (sd)
wd.damage = wd.statusAtk + wd.weaponAtk + wd.equipAtk + wd.percentAtk;
#else
battle_calc_defense_reduction(&wd, src, target, skill_id, skill_lv);
if (sd) {
wd.damage += sstatus->rhw.atk2;
}
#endif
// Combine ATK and MATK
#ifdef RENEWAL
ad.damage = (wd.damage + ad.damage) / 2;
#else
ad.damage = std::max((int64)1, wd.damage + ad.damage);
#endif
// Ratio
skillratio += 40 * skill_lv;
MATK_RATE(skillratio);
#ifdef RENEWAL
// Total defense reduction (renewal only)
battle_calc_defense_reduction(&ad, src, target, skill_id, skill_lv);
ad.damage -= (tstatus->mdef + tstatus->mdef2);
#endif
}
break;
}
if(ad.damage<1)
ad.damage=1;
else if(sc) { //only applies when hit
@@ -8851,26 +8888,26 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
if (!nk[NK_IGNOREELEMENT])
ad.damage = battle_attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
//Apply the physical part of the skill's damage. [Skotlex]
switch(skill_id) {
case CR_GRANDCROSS:
case NPC_GRANDDARKNESS: {
struct Damage wd = battle_calc_weapon_attack(src,target,skill_id,skill_lv,mflag);
ad.damage = battle_attr_fix(src, target, wd.damage + ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv) * (100 + 40 * skill_lv) / 100;
if(src == target) {
if(src->type == BL_PC)
ad.damage = ad.damage / 2;
else
ad.damage = 0;
}
}
break;
}
#ifndef RENEWAL
ad.damage += battle_calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag);
#endif
switch (skill_id) {
case CR_GRANDCROSS:
case NPC_GRANDDARKNESS:
if (src == target) {
// Grand Cross on self first applies attr_fix, then cardfix and finally halves the damage
if (src->type == BL_PC)
ad.damage = ad.damage / 2;
else
ad.damage = 0;
}
else
// Grand Cross on target applies attr_fix, then cardfix and then attr_fix a second time
ad.damage = battle_attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
break;
}
} //Hint: Against plants damage will still be 1 at this point
//Apply DAMAGE_DIV_FIX and check for min damage
@@ -8949,7 +8986,10 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
switch (skill_id) {
case TF_THROWSTONE:
md.damage = 50;
if (sd)
md.damage = 50;
else
md.damage = 30;
md.flag |= BF_WEAPON;
break;
case NPC_KILLING_AURA:
@@ -9489,6 +9529,36 @@ int64 battle_calc_return_damage(struct block_list* tbl, struct block_list *src,
return cap_value(rdamage, 1, status_get_max_hp(tbl));
}
/** Check for Coma damage
* @param sd: Source player
* @param bl: Target
* @param attack_type: Attack type
* @return True if Coma applies, false if Coma does not apply
*/
bool battle_check_coma(map_session_data& sd, struct block_list& target, e_battle_flag attack_type)
{
struct status_data* tstatus = status_get_status_data(&target);
mob_data* dstmd = BL_CAST(BL_MOB, &target);
// Coma
if (sd.special_state.bonus_coma && (!dstmd || (!util::vector_exists(status_get_race2(&dstmd->bl), RC2_GVG) && status_get_class(&dstmd->bl) != CLASS_BATTLEFIELD))) {
int rate = 0;
rate += sd.indexed_bonus.coma_class[tstatus->class_] + sd.indexed_bonus.coma_class[CLASS_ALL];
if(!status_bl_has_mode(&target, MD_STATUSIMMUNE))
rate += sd.indexed_bonus.coma_race[tstatus->race] + sd.indexed_bonus.coma_race[RC_ALL];
if (attack_type&BF_WEAPON) {
rate += sd.indexed_bonus.weapon_coma_class[tstatus->class_] + sd.indexed_bonus.weapon_coma_class[CLASS_ALL];
if (!status_bl_has_mode(&target, MD_STATUSIMMUNE)) {
rate += sd.indexed_bonus.weapon_coma_ele[tstatus->def_ele] + sd.indexed_bonus.weapon_coma_ele[ELE_ALL];
rate += sd.indexed_bonus.weapon_coma_race[tstatus->race] + sd.indexed_bonus.weapon_coma_race[RC_ALL];
}
}
if (rate > 0 && rnd_chance(rate, 10000))
return true;
}
return false;
}
/**
* Calculate Vellum damage on a target
* @param sd: Player with vanish item
@@ -9623,7 +9693,7 @@ int battle_damage_area(struct block_list *bl, va_list ap) {
if( amotion )
battle_delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0,true,false);
else
status_fix_damage(src,bl,damage,0,LG_REFLECTDAMAGE);
battle_fix_damage(src,bl,damage,0,LG_REFLECTDAMAGE);
clif_damage(bl,bl,tick,amotion,dmotion,damage,1,DMG_ENDURE,0,false);
skill_additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
map_freeblock_unlock();
@@ -9716,7 +9786,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
short index = sd->equip_index[EQI_AMMO];
if (index < 0) {
if (sd->weapontype1 > W_KATAR && sd->weapontype1 < W_HUUMA)
clif_skill_fail(sd,0,USESKILL_FAIL_NEED_MORE_BULLET,0);
clif_skill_fail( *sd, 0, USESKILL_FAIL_NEED_MORE_BULLET );
else
clif_arrow_fail(sd,0);
return ATK_NONE;
@@ -9735,7 +9805,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
case W_GATLING:
case W_SHOTGUN:
if (sd->inventory_data[index]->subtype != AMMO_BULLET) {
clif_skill_fail(sd,0,USESKILL_FAIL_NEED_MORE_BULLET,0);
clif_skill_fail( *sd, 0, USESKILL_FAIL_NEED_MORE_BULLET );
return ATK_NONE;
}
break;
@@ -9746,7 +9816,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
#else
AMMO_GRENADE) {
#endif
clif_skill_fail(sd,0,USESKILL_FAIL_NEED_MORE_BULLET,0);
clif_skill_fail( *sd, 0, USESKILL_FAIL_NEED_MORE_BULLET );
return ATK_NONE;
}
break;
@@ -9990,7 +10060,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
devotion_damage -= devotion_damage * d_sc->getSCE(SC_REBOUND_S)->val2 / 100;
clif_damage(d_bl, d_bl, gettick(), wd.amotion, wd.dmotion, devotion_damage, 1, DMG_NORMAL, 0, false);
status_fix_damage(NULL, d_bl, devotion_damage, 0, CR_DEVOTION);
battle_fix_damage(src, d_bl, devotion_damage, 0, CR_DEVOTION);
}
}
else
@@ -10009,7 +10079,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
if (e_bl && !status_isdead(e_bl)) {
clif_damage(e_bl, e_bl, tick, 0, 0, damage, wd.div_, DMG_NORMAL, 0, false);
status_fix_damage(NULL, e_bl, damage, 0, EL_WATER_SCREEN);
battle_fix_damage(src, e_bl, damage, 0, EL_WATER_SCREEN);
}
}
}
@@ -10081,7 +10151,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
}
if( type != CAST_GROUND ){
clif_skill_fail(sd,r_skill,USESKILL_FAIL_LEVEL,0);
clif_skill_fail( *sd, r_skill );
map_freeblock_unlock();
return wd.dmg_lv;
}
@@ -11077,7 +11147,7 @@ static const struct _battle_data {
{ "skill_steal_random_options", &battle_config.skill_steal_random_options, 0, 0, 1, },
{ "motd_type", &battle_config.motd_type, 0, 0, 1, },
{ "finding_ore_rate", &battle_config.finding_ore_rate, 100, 0, INT_MAX, },
{ "exp_calc_type", &battle_config.exp_calc_type, 0, 0, 1, },
{ "exp_calc_type", &battle_config.exp_calc_type, 0, 0, 2, },
{ "exp_bonus_attacker", &battle_config.exp_bonus_attacker, 25, 0, INT_MAX, },
{ "exp_bonus_max_attacker", &battle_config.exp_bonus_max_attacker, 12, 2, INT_MAX, },
{ "min_skill_delay_limit", &battle_config.min_skill_delay_limit, 100, 10, INT_MAX, },
@@ -11135,8 +11205,8 @@ static const struct _battle_data {
{ "day_duration", &battle_config.day_duration, 0, 0, INT_MAX, },
{ "night_duration", &battle_config.night_duration, 0, 0, INT_MAX, },
{ "mob_remove_delay", &battle_config.mob_remove_delay, 60000, 1000, INT_MAX, },
{ "mob_active_time", &battle_config.mob_active_time, 0, 0, INT_MAX, },
{ "boss_active_time", &battle_config.boss_active_time, 0, 0, INT_MAX, },
{ "mob_active_time", &battle_config.mob_active_time, 5000, 0, INT_MAX, },
{ "boss_active_time", &battle_config.boss_active_time, 5000, 0, INT_MAX, },
{ "sg_miracle_skill_duration", &battle_config.sg_miracle_skill_duration, 3600000, 0, INT_MAX, },
{ "hvan_explosion_intimate", &battle_config.hvan_explosion_intimate, 45000, 0, 100000, },
{ "quest_exp_rate", &battle_config.quest_exp_rate, 100, 0, INT_MAX, },
@@ -11386,6 +11456,7 @@ static const struct _battle_data {
{ "feature.dynamicnpc_direction", &battle_config.feature_dynamicnpc_direction, 0, 0, 1, },
{ "mob_respawn_time", &battle_config.mob_respawn_time, 1000, 1000, INT_MAX, },
{ "mob_unlock_time", &battle_config.mob_unlock_time, 2000, 0, INT_MAX, },
{ "feature.stylist", &battle_config.feature_stylist, 1, 0, 1, },
{ "feature.banking_state_enforce", &battle_config.feature_banking_state_enforce, 0, 0, 1, },

View File

@@ -37,7 +37,6 @@ enum e_base_damage_flag : uint16 {
BDMG_ARROW = 0x0002, /// Add arrow attack and use ranged damage formula
BDMG_MAGIC = 0x0004, /// Use MATK for base damage (e.g. Magic Crasher)
BDMG_NOSIZE = 0x0008, /// Skip target size adjustment (e.g. Weapon Perfection)
BDMG_THROW = 0x0010, /// Arrow attack should use melee damage formula (e.g., shuriken, kunai and venom knives)
};
/// Flag of the final calculation
@@ -90,10 +89,11 @@ enum e_bonus_chk_flag : uint8 {
struct Damage {
#ifdef RENEWAL
int64 statusAtk, statusAtk2, weaponAtk, weaponAtk2, equipAtk, equipAtk2, masteryAtk, masteryAtk2, percentAtk, percentAtk2;
#else
int64 basedamage; /// Right hand damage that a normal attack would deal
#endif
int64 damage, /// Right hand damage
damage2, /// Left hand damage
basedamage; /// Right hand damage that a normal attack would deal
damage2; /// Left hand damage
enum e_damage_type type; /// Check clif_damage for type
short div_; /// Number of hit
int amotion,
@@ -122,8 +122,9 @@ int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64
int64 battle_calc_bg_damage(struct block_list *src,struct block_list *bl,int64 damage,uint16 skill_id,int flag);
int64 battle_calc_pk_damage(block_list &src, block_list &bl, int64 damage, uint16 skill_id, int flag);
void battle_damage(struct block_list *src, struct block_list *target, int64 damage, t_tick delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, t_tick tick, bool spdamage);
int battle_damage(struct block_list *src, struct block_list *target, int64 damage, t_tick delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, t_tick tick, bool spdamage);
int battle_delay_damage (t_tick tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, t_tick ddelay, bool additional_effects, bool spdamage);
int battle_fix_damage(struct block_list* src, struct block_list* target, int64 damage, t_tick walkdelay, uint16 skill_id);
int battle_calc_chorusbonus(map_session_data *sd);
@@ -140,6 +141,7 @@ uint16 battle_getcurrentskill(struct block_list *bl);
int battle_check_undead(int race,int element);
int battle_check_target(struct block_list *src, struct block_list *target,int flag);
bool battle_check_range(struct block_list *src,struct block_list *bl,int range);
bool battle_check_coma(map_session_data& sd, struct block_list& target, e_battle_flag attack_type);
void battle_consume_ammo(map_session_data* sd, int skill, int lv);
@@ -746,6 +748,7 @@ struct Battle_Config
int feature_dynamicnpc_direction;
int mob_respawn_time;
int mob_unlock_time;
int feature_stylist;
int feature_banking_state_enforce;

View File

@@ -720,7 +720,7 @@ int bg_team_get_id(struct block_list *bl)
* @param mes: Message
* @param len: Message length
*/
void bg_send_message(map_session_data *sd, const char *mes, int len)
void bg_send_message(map_session_data *sd, const char *mes, size_t len)
{
nullpo_retv(sd);

View File

@@ -153,7 +153,7 @@ bool bg_queue_on_ready(const char *name, std::shared_ptr<s_battleground_queue> q
void bg_queue_on_accept_invite(map_session_data *sd);
void bg_queue_start_battleground(std::shared_ptr<s_battleground_queue> queue);
bool bg_member_respawn(map_session_data *sd);
void bg_send_message(map_session_data *sd, const char *mes, int len);
void bg_send_message(map_session_data *sd, const char *mes, size_t len);
void do_init_battleground(void);
void do_final_battleground(void);

File diff suppressed because it is too large Load Diff

View File

@@ -702,7 +702,7 @@ void clif_divorced(map_session_data* sd, const char* name);
void clif_callpartner(map_session_data& sd);
void clif_playBGM( map_session_data& sd, const char* name );
void clif_soundeffect( struct block_list& bl, const char* name, int type, enum send_target target );
void clif_parse_ActionRequest_sub(map_session_data *sd, int action_type, int target_id, t_tick tick);
void clif_parse_ActionRequest_sub( map_session_data& sd, int action_type, int target_id, t_tick tick );
void clif_parse_LoadEndAck(int fd,map_session_data *sd);
void clif_hotkeys_send(map_session_data *sd, int tab);
@@ -738,7 +738,7 @@ void clif_deleteskill(map_session_data *sd, int skill_id, bool skip_infoblock =
void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, uint16 skill_id, uint16 skill_lv, int property, int casttime);
void clif_skillcastcancel(struct block_list* bl);
void clif_skill_fail(map_session_data *sd,uint16 skill_id,enum useskill_fail_cause cause,int btype, t_itemid itemId = 0);
void clif_skill_fail( map_session_data& sd, uint16 skill_id, enum useskill_fail_cause cause = USESKILL_FAIL_LEVEL, int btype = 0, t_itemid itemId = 0 );
void clif_skill_cooldown(map_session_data *sd, uint16 skill_id, t_tick tick);
int clif_skill_damage(struct block_list *src,struct block_list *dst,t_tick tick,int sdelay,int ddelay,int64 sdamage,int div,uint16 skill_id,uint16 skill_lv,enum e_damage_type type);
//int clif_skill_damage2(struct block_list *src,struct block_list *dst,t_tick tick,int sdelay,int ddelay,int damage,int div,uint16 skill_id,uint16 skill_lv,enum e_damage_type type);
@@ -774,7 +774,7 @@ void clif_status_change(struct block_list *bl, int type, int flag, t_tick tick,
void clif_efst_status_change(struct block_list *bl, int tid, enum send_target target, int type, t_tick tick, int val1, int val2, int val3);
void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl, enum send_target target);
void clif_wis_message(map_session_data* sd, const char* nick, const char* mes, int mes_len, int gmlvl);
void clif_wis_message(map_session_data* sd, const char* nick, const char* mes, size_t mes_len, int gmlvl);
void clif_wis_end(int fd, int result);
void clif_solved_charname(int fd, int charid, const char* name);
@@ -796,7 +796,7 @@ void clif_clearcart(int fd);
void clif_item_identify_list(map_session_data *sd);
void clif_item_identified(map_session_data *sd,int idx,int flag);
void clif_item_repair_list(map_session_data *sd, map_session_data *dstsd, int lv);
void clif_item_repair_list( map_session_data& sd, map_session_data& dstsd, uint16 lv );
void clif_item_repaireffect(map_session_data *sd, int idx, int flag);
void clif_item_damaged(map_session_data* sd, unsigned short position);
void clif_item_refine_list(map_session_data *sd);
@@ -830,7 +830,7 @@ void clif_party_invite( map_session_data& sd, map_session_data& tsd );
void clif_party_invite_reply( map_session_data& sd, const char* nick, enum e_party_invite_reply reply );
void clif_party_option(struct party_data *p,map_session_data *sd,int flag);
void clif_party_withdraw( map_session_data& sd, uint32 account_id, const char* name, enum e_party_member_withdraw result, enum send_target target );
void clif_party_message( struct party_data& party, uint32 account_id, const char* mes, int len );
void clif_party_message( struct party_data& party, uint32 account_id, const char* mes, size_t len );
void clif_party_xy( map_session_data& sd );
void clif_party_xy_single( map_session_data& sd, map_session_data& tsd );
void clif_party_hp( map_session_data& sd );
@@ -874,7 +874,7 @@ void clif_guild_castle_teleport_res(map_session_data& sd, enum e_siege_teleport_
void clif_bg_hp(map_session_data *sd);
void clif_bg_xy(map_session_data *sd);
void clif_bg_xy_remove(map_session_data *sd);
void clif_bg_message(struct s_battleground_data *bg, int src_id, const char *name, const char *mes, int len);
void clif_bg_message(struct s_battleground_data *bg, int src_id, const char *name, const char *mes, size_t len);
void clif_bg_updatescore(int16 m);
void clif_bg_updatescore_single(map_session_data *sd);
void clif_sendbgemblem_area(map_session_data *sd);
@@ -900,9 +900,9 @@ void clif_font(map_session_data *sd);
// atcommand
void clif_displaymessage(const int fd, const char* mes);
void clif_disp_message(struct block_list* src, const char* mes, int len, enum send_target target);
void clif_broadcast(struct block_list* bl, const char* mes, int len, int type, enum send_target target);
void clif_broadcast2(struct block_list* bl, const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target);
void clif_disp_message(struct block_list* src, const char* mes, size_t len, enum send_target target);
void clif_broadcast(struct block_list* bl, const char* mes, size_t len, int type, enum send_target target);
void clif_broadcast2(struct block_list* bl, const char* mes, size_t len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target);
void clif_heal(int fd,int type,int val);
void clif_resurrection(struct block_list *bl,int type);
void clif_map_property(struct block_list *bl, enum map_property property, enum send_target t);
@@ -1094,11 +1094,11 @@ void clif_elementalconverter_list(map_session_data *sd);
void clif_millenniumshield(struct block_list *bl, short shields);
void clif_magicdecoy_list(map_session_data *sd, uint16 skill_lv, short x, short y);
void clif_magicdecoy_list( map_session_data& sd, uint16 skill_lv, short x, short y );
void clif_poison_list(map_session_data *sd, uint16 skill_lv);
void clif_poison_list( map_session_data& sd, uint16 skill_lv );
int clif_autoshadowspell_list(map_session_data *sd);
void clif_autoshadowspell_list( map_session_data& sd );
int clif_skill_itemlistwindow( map_session_data *sd, uint16 skill_id, uint16 skill_lv );
void clif_elemental_info(map_session_data *sd);

View File

@@ -57,7 +57,6 @@
packet(0x0093,2);
parseable_packet(0x0094,6,clif_parse_GetCharNameRequest,2);
parseable_packet(0x0096,-1,clif_parse_WisMessage,2,4,28);
packet(0x0097,-1);
packet(0x0098,3);
parseable_packet(0x0099,-1,clif_parse_Broadcast,2,4);
packet(0x009a,-1);
@@ -1334,7 +1333,6 @@
// 2008-12-10aSakexe
#if PACKETVER >= 20081210
packet(0x0442,-1);
parseable_packet(0x0443,8,clif_parse_SkillSelectMenu,2,6);
#endif
@@ -1412,7 +1410,6 @@
packet(0x01a2,37);
//packet(0x0440,10);
//packet(0x0441,4);
//packet(0x0442,8);
//packet(0x0443,8);
#endif
@@ -2041,11 +2038,11 @@
// 2013-07-17Ragexe
#if PACKETVER >= 20130717
parseable_packet(0x09A7,10,clif_parse_BankDeposit,2,6);
parseable_packet(0x09A9,10,clif_parse_BankWithdraw,2,6);
parseable_packet(0x09AB,6,clif_parse_BankCheck,2);
parseable_packet(0x09B6,6,clif_parse_BankOpen,2);
parseable_packet(0x09B8,6,clif_parse_BankClose,2);
parseable_packet( HEADER_CZ_REQ_BANKING_DEPOSIT, sizeof( PACKET_CZ_REQ_BANKING_DEPOSIT ), clif_parse_BankDeposit, 0 );
parseable_packet( HEADER_CZ_REQ_BANKING_WITHDRAW, sizeof( PACKET_CZ_REQ_BANKING_WITHDRAW ), clif_parse_BankWithdraw, 0 );
parseable_packet( HEADER_CZ_REQ_BANKING_CHECK, sizeof( PACKET_CZ_REQ_BANKING_CHECK ), clif_parse_BankCheck, 0 );
parseable_packet( HEADER_CZ_REQ_OPEN_BANKING, sizeof( PACKET_CZ_REQ_OPEN_BANKING ), clif_parse_BankOpen, 0 );
parseable_packet( HEADER_CZ_REQ_CLOSE_BANKING, sizeof( PACKET_CZ_REQ_CLOSE_BANKING ), clif_parse_BankClose, 0 );
#endif
// 2013-07-31cRagexe

View File

@@ -316,7 +316,7 @@ int elemental_action(s_elemental_data *ed, block_list *bl, t_tick tick) {
uint16 skill_id = skill->id;
uint16 skill_lv = skill->lv;
if( elemental_skillnotok(skill_id, ed) )
if( elemental_skillnotok(skill_id, *ed) )
return 0;
if( ed->ud.skilltimer != INVALID_TIMER )
@@ -389,7 +389,7 @@ int elemental_change_mode_ack(s_elemental_data *ed, e_elemental_skillmode skill_
uint16 skill_id = skill->id;
uint16 skill_lv = skill->lv;
if( elemental_skillnotok(skill_id, ed) )
if( elemental_skillnotok(skill_id, *ed) )
return 0;
if( ed->ud.skilltimer != INVALID_TIMER )
@@ -460,10 +460,19 @@ int elemental_unlocktarget(s_elemental_data *ed) {
return 0;
}
bool elemental_skillnotok(uint16 skill_id, s_elemental_data *ed) {
bool elemental_skillnotok( uint16 skill_id, s_elemental_data& ed ){
uint16 idx = skill_get_index(skill_id);
nullpo_retr(1,ed);
return idx == 0 ? false : skill_isNotOk(skill_id,ed->master); // return false or check if it,s ok for master as well
if( idx == 0 ){
return false;
}
// Check if it's ok for master as well
if( ed.master != nullptr ){
return skill_isNotOk( skill_id, *ed.master );
}else{
return true;
}
}
struct s_skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv){

View File

@@ -123,7 +123,7 @@ void elemental_summon_stop(s_elemental_data *ed);
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);
bool elemental_skillnotok( uint16 skill_id, s_elemental_data& ed );
int elemental_set_target( map_session_data *sd, block_list *bl );
int elemental_clean_effect(s_elemental_data *ed);
int elemental_action(s_elemental_data *ed, block_list *bl, t_tick tick);

View File

@@ -1370,7 +1370,7 @@ int guild_recv_memberinfoshort(int guild_id,uint32 account_id,uint32 char_id,int
/*====================================================
* Send a message to whole guild
*---------------------------------------------------*/
int guild_send_message(map_session_data *sd,const char *mes,int len) {
int guild_send_message(map_session_data *sd, const char *mes, size_t len) {
nullpo_ret(sd);
if(sd->status.guild_id==0)
@@ -1481,13 +1481,11 @@ int guild_notice_changed(int guild_id,const char *mes1,const char *mes2) {
/*====================================================
* Check condition for changing guild emblem
*---------------------------------------------------*/
bool guild_check_emblem_change_condition(map_session_data *sd)
{
nullpo_ret(sd);
auto &g = sd->guild;
bool guild_check_emblem_change_condition( map_session_data& sd ){
auto &g = sd.guild;
if (battle_config.require_glory_guild && g != nullptr && guild_checkskill(g->guild, GD_GLORYGUILD) > 0) {
clif_skill_fail(sd, GD_GLORYGUILD, USESKILL_FAIL_LEVEL, 0);
clif_skill_fail( sd, GD_GLORYGUILD );
return false;
}
@@ -1497,28 +1495,23 @@ bool guild_check_emblem_change_condition(map_session_data *sd)
/*====================================================
* Change guild emblem
*---------------------------------------------------*/
int guild_change_emblem(map_session_data *sd,int len,const char *data) {
nullpo_ret(sd);
int guild_change_emblem( map_session_data& sd, int len, const char* data ){
if (!guild_check_emblem_change_condition(sd)) {
return 0;
}
return intif_guild_emblem(sd->status.guild_id,len,data);
return intif_guild_emblem( sd.status.guild_id, len, data );
}
/*====================================================
* Change guild emblem version
*---------------------------------------------------*/
int guild_change_emblem_version(map_session_data* sd, int version)
{
nullpo_ret(sd);
int guild_change_emblem_version( map_session_data& sd, int version ){
if (!guild_check_emblem_change_condition(sd)) {
return 0;
}
return intif_guild_emblem_version(sd->status.guild_id, version);
return intif_guild_emblem_version( sd.status.guild_id, version );
}
/*====================================================

View File

@@ -87,10 +87,10 @@ int guild_change_position(int guild_id,int idx,int mode,int exp_mode,const char
int guild_position_changed(int guild_id,int idx,struct guild_position *p);
int guild_change_notice(map_session_data *sd,int guild_id,const char *mes1,const char *mes2);
int guild_notice_changed(int guild_id,const char *mes1,const char *mes2);
int guild_change_emblem(map_session_data *sd,int len,const char *data);
int guild_change_emblem_version(map_session_data* sd, int version);
int guild_change_emblem( map_session_data& sd, int len, const char* data );
int guild_change_emblem_version( map_session_data& sd, int version );
int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data);
int guild_send_message(map_session_data *sd,const char *mes,int len);
int guild_send_message(map_session_data *sd, const char *mes, size_t len);
int guild_recv_message(int guild_id,uint32 account_id,const char *mes,int len);
int guild_send_dot_remove(map_session_data *sd);
int guild_skillupack(int guild_id,uint16 skill_id,uint32 account_id);

View File

@@ -310,7 +310,7 @@ int intif_main_message(map_session_data* sd, const char* message)
* @param mes_len : Size of message
* @return 0=Message not send, 1=Message send
*/
int intif_wis_message(map_session_data *sd, char *nick, char *mes, int mes_len)
int intif_wis_message(map_session_data *sd, char *nick, char *mes, size_t mes_len)
{
int headersize = 8 + 2 * NAME_LENGTH;
@@ -326,7 +326,7 @@ int intif_wis_message(map_session_data *sd, char *nick, char *mes, int mes_len)
WFIFOHEAD(inter_fd,mes_len + headersize);
WFIFOW(inter_fd,0) = 0x3001;
WFIFOW(inter_fd,2) = mes_len + headersize;
WFIFOW(inter_fd,2) = static_cast<int16>( mes_len + headersize);
WFIFOL(inter_fd,4) = pc_get_group_level(sd);
safestrncpy(WFIFOCP(inter_fd,8), sd->status.name, NAME_LENGTH);
safestrncpy(WFIFOCP(inter_fd,8+NAME_LENGTH), nick, NAME_LENGTH);
@@ -748,7 +748,7 @@ int intif_break_party(int party_id)
* @param len : Size of the message
* @return 0=error, 1=msg sent
*/
int intif_party_message(int party_id,uint32 account_id,const char *mes,int len)
int intif_party_message(int party_id, uint32 account_id, const char *mes, size_t len)
{
if (CheckForCharServer())
return 0;
@@ -758,7 +758,7 @@ int intif_party_message(int party_id,uint32 account_id,const char *mes,int len)
WFIFOHEAD(inter_fd,len + 12);
WFIFOW(inter_fd,0)=0x3027;
WFIFOW(inter_fd,2)=len+12;
WFIFOW(inter_fd,2)=static_cast<int16>( len + 12 );
WFIFOL(inter_fd,4)=party_id;
WFIFOL(inter_fd,8)=account_id;
safestrncpy(WFIFOCP(inter_fd,12),mes,len);
@@ -954,7 +954,7 @@ int intif_guild_break(int guild_id)
* @param len : Size of the message
* @return 0=error, 1=msg_sent
*/
int intif_guild_message(int guild_id,uint32 account_id,const char *mes,int len)
int intif_guild_message(int guild_id, uint32 account_id, const char *mes, size_t len)
{
if (CheckForCharServer())
return 0;
@@ -964,7 +964,7 @@ int intif_guild_message(int guild_id,uint32 account_id,const char *mes,int len)
WFIFOHEAD(inter_fd, len + 12);
WFIFOW(inter_fd,0)=0x3037;
WFIFOW(inter_fd,2)=len+12;
WFIFOW(inter_fd,2)=static_cast<int16>( len + 12 );
WFIFOL(inter_fd,4)=guild_id;
WFIFOL(inter_fd,8)=account_id;
safestrncpy(WFIFOCP(inter_fd,12),mes,len);

View File

@@ -29,7 +29,7 @@ int intif_broadcast_obtain_special_item(map_session_data *sd, t_itemid nameid, u
int intif_broadcast_obtain_special_item_npc(map_session_data *sd, t_itemid nameid);
int intif_main_message(map_session_data* sd, const char* message);
int intif_wis_message(map_session_data *sd,char *nick,char *mes,int mes_len);
int intif_wis_message(map_session_data *sd, char *nick, char *mes, size_t mes_len);
int intif_wis_message_to_gm(char *Wisp_name, int permission, char *mes);
int intif_saveregistry(map_session_data *sd);
@@ -46,7 +46,7 @@ int intif_party_changeoption(int party_id, uint32 account_id, int exp, int item)
int intif_party_leave(int party_id, uint32 account_id, uint32 char_id, const char *name, enum e_party_member_withdraw type);
int intif_party_changemap(map_session_data *sd, int online);
int intif_break_party(int party_id);
int intif_party_message(int party_id, uint32 account_id, const char *mes,int len);
int intif_party_message(int party_id, uint32 account_id, const char *mes, size_t len);
int intif_party_leaderchange(int party_id,uint32 account_id,uint32 char_id);
int intif_party_sharelvlupdate(unsigned int share_lvl);
@@ -56,7 +56,7 @@ int intif_guild_addmember(int guild_id, struct guild_member *m);
int intif_guild_leave(int guild_id, uint32 account_id, uint32 char_id, int flag, const char *mes);
int intif_guild_memberinfoshort(int guild_id, uint32 account_id, uint32 char_id, int online, int lv, int class_);
int intif_guild_break(int guild_id);
int intif_guild_message(int guild_id, uint32 account_id, const char *mes, int len);
int intif_guild_message(int guild_id, uint32 account_id, const char *mes, size_t len);
int intif_guild_change_gm(int guild_id, const char* name, int len);
int intif_guild_change_basicinfo(int guild_id, int type, const void *data, int len);
int intif_guild_change_memberinfo(int guild_id, uint32 account_id, uint32 char_id, int type, const void *data, int len);

View File

@@ -366,12 +366,11 @@
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mob_item_ratio.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mob_item_ratio.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mob_skill_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mob_skill_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\pet_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\pet_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\produce_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\produce_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\produce_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\produce_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\quest_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\quest_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\refine.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\refine.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\reputation.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\reputation.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\size_fix.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\size_fix.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_changematerial_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_changematerial_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_damage_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_damage_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_nocast_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_nocast_db.txt')" />

View File

@@ -1164,6 +1164,7 @@ int mob_spawn (struct mob_data *md)
md->last_linktime = tick;
md->dmgtick = tick - 5000;
md->last_pcneartime = 0;
md->last_canmove = tick;
t_tick c = tick - MOB_MAX_DELAY;
@@ -1720,6 +1721,8 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
mode = status_get_mode(&md->bl);
can_move = (mode&MD_CANMOVE) && unit_can_move(&md->bl);
if (can_move)
md->last_canmove = tick;
if (md->target_id)
{ //Check validity of current target. [Skotlex]
@@ -1956,13 +1959,21 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
&& mob_is_chasing(md->state.skillstate))
return true;
//Out of range...
if (!(mode&MD_CANMOVE) || (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0))
{ //Can't chase. Immobile and trapped mobs should unlock target and use an idle skill.
// Out of range
if (!(mode&MD_CANMOVE) || (!can_move && (md->sc.cant.move || DIFF_TICK(tick, md->ud.canmove_tick) > 0)))
{ // Can't chase. Immobile and trapped mobs will use idle skills and unlock their target after a while
if (md->ud.attacktimer == INVALID_TIMER)
{ //Only unlock target if no more attack delay left
//This handles triggering idle/walk skill.
mob_unlocktarget(md,tick);
{ // Only switch mode if no more attack delay left
if (DIFF_TICK(tick, md->last_canmove) > battle_config.mob_unlock_time) {
// Unlock target or use idle/walk skill
mob_unlocktarget(md, tick);
}
else {
// Use idle skill but keep target for now
md->state.skillstate = MSS_IDLE;
if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL))
mobskill_use(md, tick, -1);
}
}
return true;
}
@@ -2620,8 +2631,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
// determines if the monster was killed by mercenary damage only
merckillonly = (bool)((dmgbltypes & BL_MER) && !(dmgbltypes & ~BL_MER));
if(!battle_config.exp_calc_type && count > 1) { //Apply first-attacker 200% exp share bonus
//TODO: Determine if this should go before calculating the MVP player instead of after.
if(battle_config.exp_calc_type == 2 && count > 1) { //Apply first-attacker 200% exp share bonus
if (UINT_MAX - md->dmglog[0].dmg > md->tdmg) {
md->tdmg += md->dmglog[0].dmg;
md->dmglog[0].dmg *= 2;
@@ -2664,14 +2674,16 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
if (!tmpsd[i]) continue;
if (!battle_config.exp_calc_type && md->tdmg)
//jAthena's exp formula based on total damage.
per = (double)md->dmglog[i].dmg/(double)md->tdmg;
else {
//eAthena's exp formula based on max hp.
per = (double)md->dmglog[i].dmg/(double)status->max_hp;
if (per > 2) per = 2; // prevents unlimited exp gain
if (battle_config.exp_calc_type == 1 || md->tdmg == 0) {
// eAthena's exp formula based on max hp
per = (double)md->dmglog[i].dmg / (double)status->max_hp;
}
else {
// Aegis's exp formula based on total damage
per = (double)md->dmglog[i].dmg / (double)md->tdmg;
}
// To prevent exploits
if (per > 1) per = 1;
//Exclude rebirth tap from this calculation
count -= md->state.rebirth;
@@ -4106,7 +4118,7 @@ int mob_clone_spawn(map_session_data *sd, int16 m, int16 x, int16 y, const char
/**
* The clone should be able to cast the skill (e.g. have the required weapon) bugreport:5299)
**/
if( !skill_check_condition_castbegin(sd,skill_id,sd->status.skill[sk_idx].lv) )
if( !skill_check_condition_castbegin(*sd,skill_id,sd->status.skill[sk_idx].lv) )
continue;
std::shared_ptr<s_mob_skill> ms = std::make_shared<s_mob_skill>();
@@ -4581,7 +4593,7 @@ uint64 MobDatabase::parseBodyNode(const ryml::NodeRef& node) {
if (!this->asUInt16(node, "Str", stat))
return 0;
mob->status.str = max(1, stat);
mob->status.str = max(0, stat);
}
if (this->nodeExists(node, "Agi")) {
@@ -4590,7 +4602,7 @@ uint64 MobDatabase::parseBodyNode(const ryml::NodeRef& node) {
if (!this->asUInt16(node, "Agi", stat))
return 0;
mob->status.agi = max(1, stat);
mob->status.agi = max(0, stat);
}
if (this->nodeExists(node, "Vit")) {
@@ -4599,7 +4611,7 @@ uint64 MobDatabase::parseBodyNode(const ryml::NodeRef& node) {
if (!this->asUInt16(node, "Vit", stat))
return 0;
mob->status.vit = max(1, stat);
mob->status.vit = max(0, stat);
}
if (this->nodeExists(node, "Int")) {
@@ -4608,7 +4620,7 @@ uint64 MobDatabase::parseBodyNode(const ryml::NodeRef& node) {
if (!this->asUInt16(node, "Int", stat))
return 0;
mob->status.int_ = max(1, stat);
mob->status.int_ = max(0, stat);
}
if (this->nodeExists(node, "Dex")) {
@@ -4617,7 +4629,7 @@ uint64 MobDatabase::parseBodyNode(const ryml::NodeRef& node) {
if (!this->asUInt16(node, "Dex", stat))
return 0;
mob->status.dex = max(1, stat);
mob->status.dex = max(0, stat);
}
if (this->nodeExists(node, "Luk")) {
@@ -4626,7 +4638,7 @@ uint64 MobDatabase::parseBodyNode(const ryml::NodeRef& node) {
if (!this->asUInt16(node, "Luk", stat))
return 0;
mob->status.luk = max(1, stat);
mob->status.luk = max(0, stat);
}
if (this->nodeExists(node, "AttackRange")) {

View File

@@ -359,7 +359,7 @@ struct mob_data {
int areanpc_id; //Required in OnTouchNPC (to avoid multiple area touchs)
int bg_id; // BattleGround System
t_tick next_walktime,last_thinktime,last_linktime,last_pcneartime,dmgtick;
t_tick next_walktime,last_thinktime,last_linktime,last_pcneartime,dmgtick,last_canmove;
short move_fail_count;
short lootitem_count;
short min_chase;

View File

@@ -3161,7 +3161,7 @@ e_purchase_result npc_barter_purchase( map_session_data& sd, std::shared_ptr<s_n
}
// Server is configured to hide favorite items on selling
if( battle_config.hide_fav_sell && sd.inventory.u.items_inventory[j].favorite ){
if( battle_config.hide_fav_sell && sd.inventory.u.items_inventory[j].favorite != 0 ){
continue;
}
@@ -3205,7 +3205,7 @@ e_purchase_result npc_barter_purchase( map_session_data& sd, std::shared_ptr<s_n
}
// Server is configured to hide favorite items on selling
if( battle_config.hide_fav_sell && sd.inventory.u.items_inventory[j].favorite ){
if( battle_config.hide_fav_sell && sd.inventory.u.items_inventory[j].favorite != 0 ){
continue;
}
@@ -3250,7 +3250,7 @@ e_purchase_result npc_barter_purchase( map_session_data& sd, std::shared_ptr<s_n
}
// Server is configured to hide favorite items on selling
if( battle_config.hide_fav_sell && sd.inventory.u.items_inventory[j].favorite ){
if( battle_config.hide_fav_sell && sd.inventory.u.items_inventory[j].favorite != 0 ){
continue;
}

View File

@@ -427,6 +427,44 @@ struct PACKET_ZC_INVENTORY_TAB{
bool favorite;
} __attribute__((packed));
struct PACKET_ZC_SKILL_SELECT_REQUEST_sub{
int16 skill_id;
} __attribute__((packed));
struct PACKET_ZC_SKILL_SELECT_REQUEST{
int16 packetType;
int16 packetLength;
int32 why;
struct PACKET_ZC_SKILL_SELECT_REQUEST_sub skills[];
} __attribute__((packed));
struct PACKET_CZ_REQ_OPEN_BANKING{
int16 packetType;
uint32 AID;
} __attribute__((packed));
struct PACKET_CZ_REQ_CLOSE_BANKING{
int16 packetType;
uint32 AID;
} __attribute__((packed));
struct PACKET_CZ_REQ_BANKING_CHECK{
int16 packetType;
uint32 AID;
} __attribute__((packed));
struct PACKET_CZ_REQ_BANKING_DEPOSIT{
int16 packetType;
uint32 AID;
int32 zeny;
} __attribute__((packed));
struct PACKET_CZ_REQ_BANKING_WITHDRAW{
int16 packetType;
uint32 AID;
int32 zeny;
} __attribute__((packed));
// NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
#if !defined( sun ) && ( !defined( __NETBSD__ ) || __NetBSD_Version__ >= 600000000 )
#pragma pack( pop )
@@ -458,6 +496,7 @@ DEFINE_PACKET_HEADER(ZC_BOSS_INFO, 0x293)
DEFINE_PACKET_HEADER(ZC_CASH_TIME_COUNTER, 0x298)
DEFINE_PACKET_HEADER(ZC_CASH_ITEM_DELETE, 0x299)
DEFINE_PACKET_HEADER(ZC_NOTIFY_BIND_ON_EQUIP, 0x2d3)
DEFINE_PACKET_HEADER(ZC_SKILL_SELECT_REQUEST, 0x442)
DEFINE_PACKET_HEADER(ZC_FAILED_TRADE_BUYING_STORE_TO_SELLER, 0x824)
DEFINE_PACKET_HEADER(CZ_SSILIST_ITEM_CLICK, 0x83c)
DEFINE_PACKET_HEADER(CZ_REQ_SE_CASH_TAB_CODE, 0x846)
@@ -469,15 +508,20 @@ DEFINE_PACKET_HEADER(ZC_INVENTORY_TAB, 0x908)
DEFINE_PACKET_HEADER(ZC_ENTRY_QUEUE_INIT, 0x90e)
DEFINE_PACKET_HEADER(CZ_REQ_MERGE_ITEM, 0x96e)
DEFINE_PACKET_HEADER(ZC_BANKING_CHECK, 0x9a6)
DEFINE_PACKET_HEADER(CZ_REQ_BANKING_DEPOSIT, 0x9a7)
DEFINE_PACKET_HEADER(ZC_ACK_BANKING_DEPOSIT, 0x9a8)
DEFINE_PACKET_HEADER(CZ_REQ_BANKING_WITHDRAW, 0x9a9)
DEFINE_PACKET_HEADER(ZC_ACK_BANKING_WITHDRAW, 0x9aa)
DEFINE_PACKET_HEADER(CZ_REQ_BANKING_CHECK, 0x9ab)
DEFINE_PACKET_HEADER(CZ_REQ_CASH_BARGAIN_SALE_ITEM_INFO, 0x9ac)
DEFINE_PACKET_HEADER(ZC_ACK_CASH_BARGAIN_SALE_ITEM_INFO, 0x9ad)
DEFINE_PACKET_HEADER(CZ_REQ_APPLY_BARGAIN_SALE_ITEM, 0x9ae)
DEFINE_PACKET_HEADER(CZ_REQ_REMOVE_BARGAIN_SALE_ITEM, 0x9b0)
DEFINE_PACKET_HEADER(ZC_NOTIFY_BARGAIN_SALE_SELLING, 0x9b2)
DEFINE_PACKET_HEADER(ZC_NOTIFY_BARGAIN_SALE_CLOSE, 0x9b3)
DEFINE_PACKET_HEADER(CZ_REQ_OPEN_BANKING, 0x9b6)
DEFINE_PACKET_HEADER(ZC_ACK_OPEN_BANKING, 0x9b7)
DEFINE_PACKET_HEADER(CZ_REQ_CLOSE_BANKING, 0x9b8)
DEFINE_PACKET_HEADER(ZC_ACK_CLOSE_BANKING, 0x9b9)
DEFINE_PACKET_HEADER(ZC_ACK_COUNT_BARGAIN_SALE_ITEM, 0x9c4)
DEFINE_PACKET_HEADER(ZC_ACK_GUILDSTORAGE_LOG, 0x9da)

View File

@@ -1039,7 +1039,7 @@ int party_send_logout(map_session_data *sd)
return 1;
}
int party_send_message(map_session_data *sd,const char *mes,int len)
int party_send_message(map_session_data *sd,const char *mes, size_t len)
{
if(sd->status.party_id == 0)
return 0;

View File

@@ -88,7 +88,7 @@ int party_changeleader(map_session_data *sd, map_session_data *t_sd, struct part
void party_send_movemap(map_session_data *sd);
void party_send_levelup(map_session_data *sd);
int party_send_logout(map_session_data *sd);
int party_send_message(map_session_data *sd,const char *mes,int len);
int party_send_message(map_session_data *sd,const char *mes, size_t len);
int party_recv_message(int party_id,uint32 account_id,const char *mes,int len);
int party_skill_check(map_session_data *sd, int party_id, uint16 skill_id, uint16 skill_lv);
int party_send_xy_clear(struct party_data *p);

View File

@@ -1207,7 +1207,7 @@ bool pc_can_sell_item(map_session_data *sd, struct item *item, enum npc_subtype
if (item->equip > 0 || item->amount < 0)
return false;
if (battle_config.hide_fav_sell && item->favorite)
if (battle_config.hide_fav_sell && item->favorite != 0)
return false; //Cannot sell favs (optional config)
if (!battle_config.rental_transaction && item->expire_time)
@@ -5934,7 +5934,7 @@ enum e_additem_result pc_additem(map_session_data *sd,struct item *item,int amou
// clear equip and favorite fields first, just in case
if( item->equip )
sd->inventory.u.items_inventory[i].equip = 0;
if( item->favorite )
if( item->favorite != 0 )
sd->inventory.u.items_inventory[i].favorite = 0;
if( item->equipSwitch )
sd->inventory.u.items_inventory[i].equipSwitch = 0;
@@ -14598,7 +14598,7 @@ TIMER_FUNC(pc_autotrade_timer){
sd->autotrade_tid = INVALID_TIMER;
if (sd->state.autotrade&2)
vending_reopen(sd);
vending_reopen(*sd);
if (sd->state.autotrade&4)
buyingstore_reopen(sd);

View File

@@ -19867,7 +19867,7 @@ BUILDIN_FUNC(unitattack)
case BL_PC: {
map_session_data* sd = (map_session_data*)unit_bl;
clif_parse_ActionRequest_sub(sd, actiontype > 0 ? 0x07 : 0x00, target_bl->id, gettick());
clif_parse_ActionRequest_sub( *sd, actiontype > 0 ? 0x07 : 0x00, target_bl->id, gettick() );
script_pushint(st, sd->ud.target == target_bl->id);
return SCRIPT_CMD_SUCCESS;
}

View File

@@ -1258,7 +1258,7 @@
//export_constant(SC_IGNOREDEF);
export_constant(SC_HELLPOWER);
export_constant(SC_INVINCIBLE);
export_constant(SC_INVINCIBLEOFF);
//export_constant(SC_INVINCIBLEOFF);
export_constant(SC_MANU_ATK);
export_constant(SC_MANU_DEF);
export_constant(SC_SPL_ATK);

File diff suppressed because it is too large Load Diff

View File

@@ -28,8 +28,6 @@ struct s_skill_unit_group;
struct status_change_entry;
class status_change;
#define MAX_SKILL_PRODUCE_DB 300 /// Max Produce DB
#define MAX_PRODUCE_RESOURCE 12 /// Max Produce requirements
#define MAX_SKILL_LEVEL 13 /// Max Skill Level (for skill_db storage)
#define MAX_MOBSKILL_LEVEL 100 /// Max monster skill level (on skill usage)
#define MAX_SKILL_CRIMSON_MARKER 3 /// Max Crimson Marker targets (RL_C_MARKER)
@@ -444,15 +442,39 @@ enum e_skill_blown {
};
/// Create Database item
struct s_skill_produce_db {
struct s_skill_produce_db_entry {
t_itemid nameid; /// Product ID
unsigned short req_skill; /// Required Skill
unsigned char req_skill_lv, /// Required Skill Level
uint16 req_skill; /// Required Skill
uint16 req_skill_lv, /// Required Skill Level
itemlv; /// Item Level
t_itemid mat_id[MAX_PRODUCE_RESOURCE]; /// Materials needed
unsigned short mat_amount[MAX_PRODUCE_RESOURCE]; /// Amount of each materials
std::unordered_map<t_itemid, uint16> materials;
// additional rates/quantity data for skill_changematerial
uint16 baserate;
std::unordered_map<uint16, uint16> qty;
};
extern struct s_skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB];
struct s_skill_produce_db {
uint16 itemlv; /// Item Level
std::unordered_map<t_itemid, std::shared_ptr<s_skill_produce_db_entry>> data; /// item, entry
};
class SkillProduceDatabase : public TypesafeYamlDatabase<uint16, s_skill_produce_db> {
private:
uint16 total_id = 0;
public:
SkillProduceDatabase() : TypesafeYamlDatabase("PRODUCE_DB", 1) {
}
const std::string getDefaultLocation() override;
uint64 parseBodyNode(const ryml::NodeRef& node) override;
bool addItemConsumed(const ryml::NodeRef& node, std::shared_ptr<s_skill_produce_db_entry> &entry, bool isConsumed);
void loadingFinished() override;
};
extern SkillProduceDatabase skill_produce_db;
/// Creating database arrow
struct s_skill_arrow_db {
@@ -596,8 +618,8 @@ void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id);
int skill_check_bl_sc(struct block_list *target, va_list ap);
// Skill conditions check and remove [Inkfish]
bool skill_check_condition_castbegin(map_session_data *sd, uint16 skill_id, uint16 skill_lv);
bool skill_check_condition_castend(map_session_data *sd, uint16 skill_id, uint16 skill_lv);
bool skill_check_condition_castbegin( map_session_data& sd, uint16 skill_id, uint16 skill_lv );
bool skill_check_condition_castend( map_session_data& sd, uint16 skill_id, uint16 skill_lv );
int skill_check_condition_char_sub (struct block_list *bl, va_list ap);
void skill_consume_requirement(map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type);
struct s_skill_condition skill_get_requirement(map_session_data *sd, uint16 skill_id, uint16 skill_lv);
@@ -610,9 +632,9 @@ void skill_unit_move_unit_group( std::shared_ptr<s_skill_unit_group> group, int1
void skill_unit_move_unit(struct block_list *bl, int dx, int dy);
int skill_sit(map_session_data *sd, bool sitting);
void skill_repairweapon(map_session_data *sd, int idx);
void skill_repairweapon( map_session_data& sd, int idx );
void skill_identify(map_session_data *sd,int idx);
void skill_weaponrefine(map_session_data *sd,int idx); // [Celest]
void skill_weaponrefine( map_session_data& sd, int idx ); // [Celest]
int skill_autospell(map_session_data *md,uint16 skill_id);
int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, bool heal);
@@ -621,15 +643,15 @@ bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce
int8 skill_isCopyable(map_session_data *sd, uint16 skill_id);
// Abnormal status
bool skill_isNotOk(uint16 skill_id, map_session_data *sd);
bool skill_isNotOk( uint16 skill_id, map_session_data& sd );
bool skill_isNotOk_hom(struct homun_data *hd, uint16 skill_id, uint16 skill_lv);
bool skill_isNotOk_mercenary(uint16 skill_id, s_mercenary_data *md);
bool skill_isNotOk_mercenary( uint16 skill_id, s_mercenary_data& md);
bool skill_isNotOk_npcRange(struct block_list *src, uint16 skill_id, uint16 skill_lv, int pos_x, int pos_y);
// Item creation
short skill_can_produce_mix( map_session_data *sd, t_itemid nameid, int trigger, int qty);
bool skill_produce_mix( map_session_data *sd, uint16 skill_id, t_itemid nameid, int slot1, int slot2, int slot3, int qty, short produce_idx );
std::shared_ptr<s_skill_produce_db_entry> skill_can_produce_mix(map_session_data *sd, t_itemid nameid, int trigger, int qty);
bool skill_produce_mix( map_session_data *sd, uint16 skill_id, t_itemid nameid, int slot1, int slot2, int slot3, int qty, std::shared_ptr<s_skill_produce_db_entry> produce = nullptr );
bool skill_arrow_create( map_session_data *sd, t_itemid nameid);
@@ -2775,19 +2797,19 @@ bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *s
/**
* Mechanic
**/
int skill_magicdecoy(map_session_data *sd, t_itemid nameid);
void skill_magicdecoy( map_session_data& sd, t_itemid nameid );
/**
* Guiltoine Cross
**/
int skill_poisoningweapon( map_session_data *sd, t_itemid nameid);
void skill_poisoningweapon( map_session_data& sd, t_itemid nameid );
/**
* Auto Shadow Spell (Shadow Chaser)
**/
int skill_select_menu(map_session_data *sd,uint16 skill_id);
void skill_select_menu( map_session_data& sd, uint16 skill_id );
int skill_elementalanalysis(map_session_data *sd, int n, uint16 skill_lv, unsigned short *item_list); // Sorcerer Four Elemental Analisys.
int skill_elementalanalysis( map_session_data& sd, int n, uint16 skill_lv, unsigned short *item_list ); // Sorcerer Four Elemental Analisys.
int skill_changematerial(map_session_data *sd, int n, unsigned short *item_list); // Genetic Change Material.
int skill_get_elemental_type(uint16 skill_id, uint16 skill_lv);

View File

@@ -1408,6 +1408,7 @@ int64 status_charge(struct block_list* bl, int64 hp, int64 sp)
* flag&2: Fail if there is not enough to subtract
* flag&4: Mob does not give EXP/Loot if killed
* flag&8: Used to damage SP of a dead character
* flag&16: Coma damage - Log it as normal damage, but actually set HP/SP to 1
* @return hp+sp+ap
* Note: HP/SP/AP are integer values, not percentages. Values should be
* calculated either within function call or before
@@ -1475,7 +1476,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
flag |= 8;
sc = status_get_sc(target);
if( hp && battle_config.invincible_nodamage && src && sc && sc->getSCE(SC_INVINCIBLE) && !sc->getSCE(SC_INVINCIBLEOFF) )
if (hp && battle_config.invincible_nodamage && src && sc && sc->getSCE(SC_INVINCIBLE))
hp = 1;
if( hp && !(flag&1) ) {
@@ -1527,10 +1528,25 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
unit_skillcastcancel(target, 2);
}
// We need to log the real damage on exp_calc_type 1
if (battle_config.exp_calc_type == 1) {
dhp = hp;
// Coma real damage
if (flag&16)
dhp = status->hp - 1;
}
status->hp-= hp;
status->sp-= sp;
status->ap-= ap;
// Coma
if (flag&16) {
status->hp = 1;
status->sp = 1;
if (!sp) sp = 1; // To make sure the status bar is updated
}
if (sc && hp && status->hp) {
if (sc->getSCE(SC_AUTOBERSERK) &&
(!sc->getSCE(SC_PROVOKE) || !sc->getSCE(SC_PROVOKE)->val4) &&
@@ -1544,9 +1560,11 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
status_change_end(target, SC_SATURDAYNIGHTFEVER);
}
// Need to pass original HP damage for the mob damage log
dhp = cap_value(dhp, INT_MIN, INT_MAX);
switch (target->type) {
case BL_PC: pc_damage((TBL_PC*)target,src,hp,sp,ap); break;
case BL_MOB: mob_damage((TBL_MOB*)target, src, hp); break;
case BL_MOB: mob_damage((TBL_MOB*)target, src, (int)dhp); break;
case BL_HOM: hom_damage((TBL_HOM*)target); break;
case BL_MER: mercenary_heal((TBL_MER*)target,hp,sp); break;
case BL_ELEM: elemental_heal((TBL_ELEM*)target,hp,sp); break;
@@ -1983,7 +2001,7 @@ bool status_check_skilluse(struct block_list *src, struct block_list *target, ui
(sc->getSCE(SC_KYOMU) && rnd()%100 < 25) // Kyomu has a 25% chance of causing skills fail.
)) {
if (src->type == BL_PC)
clif_skill_fail((TBL_PC*)src,skill_id,USESKILL_FAIL_LEVEL,0);
clif_skill_fail( *((map_session_data*)src), skill_id );
return false;
}
@@ -2110,12 +2128,6 @@ bool status_check_skilluse(struct block_list *src, struct block_list *target, ui
return true;
if (tsc && tsc->count) {
/**
* Attacks in invincible are capped to 1 damage and handled in battle.cpp.
* Allow spell break and eske for sealed shrine GDB when in INVINCIBLE state.
**/
if( tsc->getSCE(SC_INVINCIBLE) && !tsc->getSCE(SC_INVINCIBLEOFF) && skill_id && !(skill_id&(SA_SPELLBREAKER|SL_SKE)) )
return false;
if(!skill_id && tsc->getSCE(SC_TRICKDEAD))
return false;
if((skill_id == WZ_STORMGUST || skill_id == WZ_FROSTNOVA || skill_id == NJ_HYOUSYOURAKU || skill_id == NPC_STORMGUST2)
@@ -8036,8 +8048,8 @@ static unsigned short status_calc_speed(struct block_list *bl, status_change *sc
val = max( val, 55 );
if( sc->getSCE(SC_AVOID) )
val = max( val, 10 * sc->getSCE(SC_AVOID)->val1 );
if( sc->getSCE(SC_INVINCIBLE) && !sc->getSCE(SC_INVINCIBLEOFF) )
val = max( val, 75 );
if (sc->getSCE(SC_INVINCIBLE))
val = max(val, sc->getSCE(SC_INVINCIBLE)->val3);
if( sc->getSCE(SC_CLOAKINGEXCEED) )
val = max( val, sc->getSCE(SC_CLOAKINGEXCEED)->val3);
if (sc->getSCE(SC_PARALYSE) && sc->getSCE(SC_PARALYSE)->val3 == 0)
@@ -8309,66 +8321,68 @@ static short status_calc_aspd_rate(struct block_list *bl, status_change *sc, int
if(!sc || !sc->count)
return cap_value(aspd_rate,0,SHRT_MAX);
if( !sc->getSCE(SC_QUAGMIRE) ) {
int max = 0;
if(sc->getSCE(SC_STAR_COMFORT))
max = sc->getSCE(SC_STAR_COMFORT)->val2;
int max = 0;
if (sc->getSCE(SC_STAR_COMFORT))
max = sc->getSCE(SC_STAR_COMFORT)->val2;
if(sc->getSCE(SC_TWOHANDQUICKEN) &&
max < sc->getSCE(SC_TWOHANDQUICKEN)->val2)
max = sc->getSCE(SC_TWOHANDQUICKEN)->val2;
if (sc->getSCE(SC_TWOHANDQUICKEN) &&
max < sc->getSCE(SC_TWOHANDQUICKEN)->val2)
max = sc->getSCE(SC_TWOHANDQUICKEN)->val2;
if(sc->getSCE(SC_ONEHAND) &&
max < sc->getSCE(SC_ONEHAND)->val2)
max = sc->getSCE(SC_ONEHAND)->val2;
if (sc->getSCE(SC_ONEHAND) &&
max < sc->getSCE(SC_ONEHAND)->val2)
max = sc->getSCE(SC_ONEHAND)->val2;
if(sc->getSCE(SC_MERC_QUICKEN) &&
max < sc->getSCE(SC_MERC_QUICKEN)->val2)
max = sc->getSCE(SC_MERC_QUICKEN)->val2;
if (sc->getSCE(SC_MERC_QUICKEN) &&
max < sc->getSCE(SC_MERC_QUICKEN)->val2)
max = sc->getSCE(SC_MERC_QUICKEN)->val2;
if(sc->getSCE(SC_ADRENALINE2) &&
max < sc->getSCE(SC_ADRENALINE2)->val3)
max = sc->getSCE(SC_ADRENALINE2)->val3;
if (sc->getSCE(SC_ADRENALINE2) &&
max < sc->getSCE(SC_ADRENALINE2)->val3)
max = sc->getSCE(SC_ADRENALINE2)->val3;
if(sc->getSCE(SC_ADRENALINE) &&
max < sc->getSCE(SC_ADRENALINE)->val3)
max = sc->getSCE(SC_ADRENALINE)->val3;
if (sc->getSCE(SC_ADRENALINE) &&
max < sc->getSCE(SC_ADRENALINE)->val3)
max = sc->getSCE(SC_ADRENALINE)->val3;
if(sc->getSCE(SC_SPEARQUICKEN) &&
max < sc->getSCE(SC_SPEARQUICKEN)->val2)
max = sc->getSCE(SC_SPEARQUICKEN)->val2;
if (sc->getSCE(SC_SPEARQUICKEN) &&
max < sc->getSCE(SC_SPEARQUICKEN)->val2)
max = sc->getSCE(SC_SPEARQUICKEN)->val2;
if(sc->getSCE(SC_GATLINGFEVER) &&
max < sc->getSCE(SC_GATLINGFEVER)->val2)
max = sc->getSCE(SC_GATLINGFEVER)->val2;
if (sc->getSCE(SC_GATLINGFEVER) &&
max < sc->getSCE(SC_GATLINGFEVER)->val2)
max = sc->getSCE(SC_GATLINGFEVER)->val2;
if(sc->getSCE(SC_FLEET) &&
max < sc->getSCE(SC_FLEET)->val2)
max = sc->getSCE(SC_FLEET)->val2;
if (sc->getSCE(SC_FLEET) &&
max < sc->getSCE(SC_FLEET)->val2)
max = sc->getSCE(SC_FLEET)->val2;
if(sc->getSCE(SC_ASSNCROS) && max < sc->getSCE(SC_ASSNCROS)->val2) {
if (bl->type!=BL_PC)
max = sc->getSCE(SC_ASSNCROS)->val2;
else
switch(((TBL_PC*)bl)->status.weapon) {
case W_BOW:
case W_REVOLVER:
case W_RIFLE:
case W_GATLING:
case W_SHOTGUN:
case W_GRENADE:
break;
default:
max = sc->getSCE(SC_ASSNCROS)->val2;
if (sc->getSCE(SC_INVINCIBLE) &&
max < sc->getSCE(SC_INVINCIBLE)->val4)
max = sc->getSCE(SC_INVINCIBLE)->val4;
if (sc->getSCE(SC_ASSNCROS) && max < sc->getSCE(SC_ASSNCROS)->val2) {
if (bl->type != BL_PC)
max = sc->getSCE(SC_ASSNCROS)->val2;
else
switch (((TBL_PC*)bl)->status.weapon) {
case W_BOW:
case W_REVOLVER:
case W_RIFLE:
case W_GATLING:
case W_SHOTGUN:
case W_GRENADE:
break;
default:
max = sc->getSCE(SC_ASSNCROS)->val2;
}
}
aspd_rate -= max;
if(sc->getSCE(SC_BERSERK))
aspd_rate -= 300;
else if(sc->getSCE(SC_MADNESSCANCEL))
aspd_rate -= 200;
}
aspd_rate -= max;
if (sc->getSCE(SC_BERSERK))
aspd_rate -= 300;
else if (sc->getSCE(SC_MADNESSCANCEL))
aspd_rate -= 200;
if( sc->getSCE(i=SC_ASPDPOTION3) ||
sc->getSCE(i=SC_ASPDPOTION2) ||
@@ -9609,11 +9623,6 @@ t_tick status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_
tick /= 2; // Half duration for players.
sc_def2 = status->mdef*100;
break;
case SC_ANKLE:
if(status_has_mode(status,MD_STATUSIMMUNE)) // Lasts 5 times less on bosses
tick /= 5;
sc_def = status->agi*50;
break;
case SC_JOINTBEAT:
tick_def2 = 1000 * ((status->luk / 2 + status->agi / 5) / 2); // (50 * LUK / 100 + 20 * AGI / 100) / 2
break;
@@ -11235,7 +11244,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
}
case SC_COMA: // Coma. Sends a char to 1HP. If val2, do not zap sp
status_zap(bl, status->hp-1, val2?0:status->sp);
status_zap(bl, status->hp-1, val2?0:status->sp-1);
return 1;
break;
case SC_CLOSECONFINE2:
@@ -11570,6 +11579,11 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
case SC_REBIRTH:
val2 = 20*val1; // % of life to be revived with
break;
case SC_INVINCIBLE:
val2 = 100; // ATKpercent increase
val3 = 50; // Speed increase
val4 = 700; // ASPD increase
break;
case SC_MANU_DEF:
case SC_MANU_ATK:
@@ -11584,7 +11598,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
/* General */
case SC_FEAR:
status_change_start(src,bl,SC_ANKLE,10000,val1,0,0,0,2000,SCSTART_NOAVOID|SCSTART_NOTICKDEF|SCSTART_NORATEDEF);
sc_start(src, bl, SC_ANKLE, 100, 0, 2000);
break;
/* Rune Knight */
@@ -12848,10 +12862,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
//SC that make stop walking
if (scdb->flag[SCF_STOPWALKING]) {
switch (type) {
case SC_ANKLE:
if (battle_config.skill_trap_type || !map_flag_gvg(bl->m))
unit_stop_walking(bl, 1);
break;
case SC__MANHOLE:
if (bl->type == BL_PC || !unit_blown_immune(bl,0x1))
unit_stop_walking(bl,1);

View File

@@ -499,8 +499,8 @@ enum sc_type : int16 {
//SC_IGNOREDEF,
SC_HELLPOWER = 294,
SC_INVINCIBLE, //295
SC_INVINCIBLEOFF,
SC_MANU_ATK,
//SC_INVINCIBLEOFF,
SC_MANU_ATK = 297,
SC_MANU_DEF,
SC_SPL_ATK,
SC_SPL_DEF, //300

View File

@@ -1646,7 +1646,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if (sc && sc->getSCE(SC_COMBO) &&
skill_is_combo(skill_id) &&
(sc->getSCE(SC_COMBO)->val1 == skill_id ||
(sd?skill_check_condition_castbegin(sd,skill_id,skill_lv):0) )) {
(sd?skill_check_condition_castbegin(*sd,skill_id,skill_lv):0) )) {
if (skill_is_combo(skill_id) == 2 && target_id == src->id && ud->target > 0)
target_id = ud->target;
else if (sc->getSCE(SC_COMBO)->val2)
@@ -1665,7 +1665,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if (sd) {
// Target_id checking.
if(skill_isNotOk(skill_id, sd))
if(skill_isNotOk(skill_id, *sd))
return 0;
switch(skill_id) { // Check for skills that auto-select target
@@ -1697,7 +1697,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
target = (struct block_list*)map_charid2sd(sd->status.partner_id);
if (!target) {
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
clif_skill_fail( *sd, skill_id );
return 0;
}
break;
@@ -1754,7 +1754,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
// Fail if the targetted skill is near NPC [Cydh]
if(skill->inf2[INF2_DISABLENEARNPC] && !ignore_range && skill_isNotOk_npcRange(src,skill_id,skill_lv,target->x,target->y)) {
if (sd)
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
clif_skill_fail( *sd, skill_id );
return 0;
}
@@ -1773,7 +1773,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
case BD_ENCORE:
// Prevent using the dance skill if you no longer have the skill in your tree.
if(!sd->skill_id_dance || pc_checkskill(sd,sd->skill_id_dance)<=0) {
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
clif_skill_fail( *sd, skill_id );
return 0;
}
@@ -1781,7 +1781,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
break;
case WL_WHITEIMPRISON:
if( battle_check_target(src,target,BCT_SELF|BCT_ENEMY) < 0 ) {
clif_skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0);
clif_skill_fail( *sd, skill_id, USESKILL_FAIL_TOTARGET );
return 0;
}
break;
@@ -1799,7 +1799,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if (i == count) {
ARR_FIND(0, count, i, sd->devotion[i] == 0);
if (i == count) { // No free slots, skill Fail
clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
clif_skill_fail( *sd, skill_id );
return 0;
}
}
@@ -1812,7 +1812,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if (i == MAX_SKILL_CRIMSON_MARKER) {
ARR_FIND(0, MAX_SKILL_CRIMSON_MARKER, i, sd->c_marker[i] == 0);
if (i == MAX_SKILL_CRIMSON_MARKER) { // No free slots, skill Fail
clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
clif_skill_fail( *sd, skill_id );
return 0;
}
}
@@ -1832,7 +1832,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
// No free slots
if( i == count ){
clif_skill_fail( sd, skill_id, USESKILL_FAIL_LEVEL, 0 );
clif_skill_fail( *sd, skill_id );
return 0;
}
}
@@ -1840,7 +1840,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
case TR_RETROSPECTION:
// Prevent using the song skill if you no longer have the skill in your tree.
if (!sd->skill_id_song || pc_checkskill(sd, sd->skill_id_song) <= 0) {
clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
clif_skill_fail( *sd, skill_id );
return 0;
}
@@ -1848,7 +1848,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
break;
}
if (!skill_check_condition_castbegin(sd, skill_id, skill_lv))
if (!skill_check_condition_castbegin(*sd, skill_id, skill_lv))
return 0;
}
@@ -1968,7 +1968,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
// Only allow to attack if the enemy has a sign mark given by the caster.
if( tsc == nullptr || tsc->getSCE(SC_SERVANT_SIGN) == nullptr || tsc->getSCE(SC_SERVANT_SIGN)->val1 != src->id ){
clif_skill_fail(sd, skill_id, USESKILL_FAIL, 0);
if (sd)
clif_skill_fail( *sd, skill_id, USESKILL_FAIL );
return 0;
}
}
@@ -2160,14 +2161,15 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
return 0;
if( sd ) {
if( skill_isNotOk(skill_id, sd) || !skill_check_condition_castbegin(sd, skill_id, skill_lv) )
if( skill_isNotOk(skill_id, *sd) || !skill_check_condition_castbegin(*sd, skill_id, skill_lv) )
return 0;
if (skill_id == MG_FIREWALL && !skill_pos_maxcount_check(src, skill_x, skill_y, skill_id, skill_lv, BL_PC, true))
return 0; // Special check for Firewall only
}
if( (skill_id >= SC_MANHOLE && skill_id <= SC_FEINTBOMB) && map_getcell(src->m, skill_x, skill_y, CELL_CHKMAELSTROM) ) {
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
if (sd)
clif_skill_fail( *sd, skill_id );
return 0;
}
@@ -2177,7 +2179,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
// Fail if the targetted skill is near NPC [Cydh]
if(skill_get_inf2(skill_id, INF2_DISABLENEARNPC) && !ignore_range && skill_isNotOk_npcRange(src,skill_id,skill_lv,skill_x,skill_y)) {
if (sd)
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
clif_skill_fail( *sd, skill_id );
return 0;
}
@@ -2724,7 +2726,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, t_tick tick)
// Attacking when under cast delay has restrictions:
if( tid == INVALID_TIMER ) { // Requested attack.
if(sd)
clif_skill_fail(sd,1,USESKILL_FAIL_SKILLINTERVAL,0);
clif_skill_fail( *sd, 1, USESKILL_FAIL_SKILLINTERVAL );
return 0;
}

View File

@@ -295,35 +295,32 @@ void vending_purchasereq(map_session_data* sd, int aid, int uid, const uint8* da
* @param at Autotrader info, or NULL if requetsed not from autotrade persistance
* @return 0 If success, 1 - Cannot open (die, not state.prevend, trading), 2 - No cart, 3 - Count issue, 4 - Cart data isn't saved yet, 5 - No valid item found
*/
int8 vending_openvending(map_session_data* sd, const char* message, const uint8* data, int count, struct s_autotrader *at)
{
int8 vending_openvending( map_session_data& sd, const char* message, const uint8* data, int count, struct s_autotrader *at ){
int i, j;
int vending_skill_lvl;
char message_sql[MESSAGE_SIZE*2];
StringBuf buf;
nullpo_retr(false,sd);
if ( pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd)) {
if ( pc_isdead(&sd) || !sd.state.prevend || pc_istrading(&sd)) {
return 1; // can't open vendings lying dead || didn't use via the skill (wpe/hack) || can't have 2 shops at once
}
vending_skill_lvl = pc_checkskill(sd, MC_VENDING);
vending_skill_lvl = pc_checkskill(&sd, MC_VENDING);
// skill level and cart check
if( !vending_skill_lvl || !pc_iscarton(sd) ) {
clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
if( !vending_skill_lvl || !pc_iscarton(&sd) ) {
clif_skill_fail( sd, MC_VENDING );
return 2;
}
// check number of items in shop
if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) { // invalid item count
clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
clif_skill_fail( sd, MC_VENDING );
return 3;
}
if (save_settings&CHARSAVE_VENDING) // Avoid invalid data from saving
chrif_save(sd, CSAVE_INVENTORY|CSAVE_CART);
chrif_save(&sd, CSAVE_INVENTORY|CSAVE_CART);
// filter out invalid items
i = 0;
@@ -335,51 +332,51 @@ int8 vending_openvending(map_session_data* sd, const char* message, const uint8*
index -= 2; // offset adjustment (client says that the first cart position is 2)
if( index < 0 || index >= MAX_CART // invalid position
|| pc_cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity
|| pc_cartitem_amount(&sd, index, amount) < 0 // invalid item or insufficient quantity
//NOTE: official server does not do any of the following checks!
|| !sd->cart.u.items_cart[index].identify // unidentified item
|| sd->cart.u.items_cart[index].attribute == 1 // broken item
|| sd->cart.u.items_cart[index].expire_time // It should not be in the cart but just in case
|| (sd->cart.u.items_cart[index].bound && !pc_can_give_bounded_items(sd)) // can't trade account bound items and has no permission
|| !itemdb_cantrade(&sd->cart.u.items_cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // untradeable item
|| !sd.cart.u.items_cart[index].identify // unidentified item
|| sd.cart.u.items_cart[index].attribute == 1 // broken item
|| sd.cart.u.items_cart[index].expire_time // It should not be in the cart but just in case
|| (sd.cart.u.items_cart[index].bound && !pc_can_give_bounded_items(&sd)) // can't trade account bound items and has no permission
|| !itemdb_cantrade(&sd.cart.u.items_cart[index], pc_get_group_level(&sd), pc_get_group_level(&sd)) ) // untradeable item
continue;
sd->vending[i].index = index;
sd->vending[i].amount = amount;
sd->vending[i].value = min(value, (unsigned int)battle_config.vending_max_value);
sd.vending[i].index = index;
sd.vending[i].amount = amount;
sd.vending[i].value = min(value, (unsigned int)battle_config.vending_max_value);
i++; // item successfully added
}
if (i != j) {
clif_displaymessage(sd->fd, msg_txt(sd, 266)); //"Some of your items cannot be vended and were removed from the shop."
clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet
clif_displaymessage(sd.fd, msg_txt(&sd, 266)); //"Some of your items cannot be vended and were removed from the shop."
clif_skill_fail( sd, MC_VENDING ); // custom reply packet
return 5;
}
if( i == 0 ) { // no valid item found
clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet
clif_skill_fail( sd, MC_VENDING ); // custom reply packet
return 5;
}
sd->state.prevend = 0;
sd->state.vending = true;
sd->state.workinprogress = WIP_DISABLE_NONE;
sd->vender_id = vending_getuid();
sd->vend_num = i;
safestrncpy(sd->message, message, MESSAGE_SIZE);
sd.state.prevend = 0;
sd.state.vending = true;
sd.state.workinprogress = WIP_DISABLE_NONE;
sd.vender_id = vending_getuid();
sd.vend_num = i;
safestrncpy(sd.message, message, MESSAGE_SIZE);
Sql_EscapeString( mmysql_handle, message_sql, sd->message );
Sql_EscapeString( mmysql_handle, message_sql, sd.message );
if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`id`, `account_id`, `char_id`, `sex`, `map`, `x`, `y`, `title`, `autotrade`, `body_direction`, `head_direction`, `sit`) "
"VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d, '%d', '%d', '%d' );",
vendings_table, sd->vender_id, sd->status.account_id, sd->status.char_id, sd->status.sex == SEX_FEMALE ? 'F' : 'M', map_getmapdata(sd->bl.m)->name, sd->bl.x, sd->bl.y, message_sql, sd->state.autotrade, at ? at->dir : sd->ud.dir, at ? at->head_dir : sd->head_dir, at ? at->sit : pc_issit(sd) ) != SQL_SUCCESS ) {
vendings_table, sd.vender_id, sd.status.account_id, sd.status.char_id, sd.status.sex == SEX_FEMALE ? 'F' : 'M', map_getmapdata(sd.bl.m)->name, sd.bl.x, sd.bl.y, message_sql, sd.state.autotrade, at ? at->dir : sd.ud.dir, at ? at->head_dir : sd.head_dir, at ? at->sit : pc_issit(&sd) ) != SQL_SUCCESS ) {
Sql_ShowDebug(mmysql_handle);
}
StringBuf_Init(&buf);
StringBuf_Printf(&buf, "INSERT INTO `%s`(`vending_id`,`index`,`cartinventory_id`,`amount`,`price`) VALUES", vending_items_table);
for (j = 0; j < i; j++) {
StringBuf_Printf(&buf, "(%d,%d,%d,%d,%d)", sd->vender_id, j, sd->cart.u.items_cart[sd->vending[j].index].id, sd->vending[j].amount, sd->vending[j].value);
StringBuf_Printf(&buf, "(%d,%d,%d,%d,%d)", sd.vender_id, j, sd.cart.u.items_cart[sd.vending[j].index].id, sd.vending[j].amount, sd.vending[j].value);
if (j < i-1)
StringBuf_AppendStr(&buf, ",");
}
@@ -387,10 +384,10 @@ int8 vending_openvending(map_session_data* sd, const char* message, const uint8*
Sql_ShowDebug(mmysql_handle);
StringBuf_Destroy(&buf);
clif_openvending(sd,sd->bl.id,sd->vending);
clif_showvendingboard( *sd );
clif_openvending(&sd,sd.bl.id,sd.vending);
clif_showvendingboard( sd );
idb_put(vending_db, sd->status.char_id, sd);
idb_put(vending_db, sd.status.char_id, &sd);
return 0;
}
@@ -494,15 +491,13 @@ bool vending_searchall(map_session_data* sd, const struct s_search_store_search*
* Open vending for Autotrader
* @param sd Player as autotrader
*/
void vending_reopen( map_session_data* sd )
void vending_reopen( map_session_data& sd )
{
struct s_autotrader *at = NULL;
int8 fail = -1;
nullpo_retv(sd);
// Open vending for this autotrader
if ((at = (struct s_autotrader *)uidb_get(vending_autotrader_db, sd->status.char_id)) && at->count && at->entries) {
if ((at = (struct s_autotrader *)uidb_get(vending_autotrader_db, sd.status.char_id)) && at->count && at->entries) {
uint8 *data, *p;
uint16 j, count;
@@ -516,7 +511,7 @@ void vending_reopen( map_session_data* sd )
uint32 *value = (uint32*)(p + 4);
// Find item position in cart
ARR_FIND(0, MAX_CART, entry->index, sd->cart.u.items_cart[entry->index].id == entry->cartinventory_id);
ARR_FIND(0, MAX_CART, entry->index, sd.cart.u.items_cart[entry->index].id == entry->cartinventory_id);
if (entry->index == MAX_CART) {
count--;
@@ -524,35 +519,35 @@ void vending_reopen( map_session_data* sd )
}
*index = entry->index + 2;
*amount = itemdb_isstackable(sd->cart.u.items_cart[entry->index].nameid) ? entry->amount : 1;
*amount = itemdb_isstackable(sd.cart.u.items_cart[entry->index].nameid) ? entry->amount : 1;
*value = entry->price;
p += 8;
}
sd->state.prevend = 1; // Set him into a hacked prevend state
sd->state.autotrade = 1;
sd.state.prevend = 1; // Set him into a hacked prevend state
sd.state.autotrade = 1;
// Make sure abort all NPCs
npc_event_dequeue(sd);
pc_cleareventtimer(sd);
npc_event_dequeue(&sd);
pc_cleareventtimer(&sd);
// Open the vending again
if( (fail = vending_openvending(sd, at->title, data, count, at)) == 0 ) {
// Make vendor look perfect
pc_setdir(sd, at->dir, at->head_dir);
clif_changed_dir(&sd->bl, AREA_WOS);
pc_setdir(&sd, at->dir, at->head_dir);
clif_changed_dir(&sd.bl, AREA_WOS);
if( at->sit ) {
pc_setsit(sd);
skill_sit(sd, 1);
clif_sitting(&sd->bl);
pc_setsit(&sd);
skill_sit(&sd, 1);
clif_sitting(&sd.bl);
}
// Immediate save
chrif_save(sd, CSAVE_AUTOTRADE);
chrif_save(&sd, CSAVE_AUTOTRADE);
ShowInfo("Vending loaded for '" CL_WHITE "%s" CL_RESET "' with '" CL_WHITE "%d" CL_RESET "' items at " CL_WHITE "%s (%d,%d)" CL_RESET "\n",
sd->status.name, count, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y);
sd.status.name, count, mapindex_id2name(sd.mapindex), sd.bl.x, sd.bl.y);
}
aFree(data);
}
@@ -564,8 +559,8 @@ void vending_reopen( map_session_data* sd )
}
if (fail != 0) {
ShowError("vending_reopen: (Error:%d) Load failed for autotrader '" CL_WHITE "%s" CL_RESET "' (CID=%d/AID=%d)\n", fail, sd->status.name, sd->status.char_id, sd->status.account_id);
map_quit(sd);
ShowError("vending_reopen: (Error:%d) Load failed for autotrader '" CL_WHITE "%s" CL_RESET "' (CID=%d/AID=%d)\n", fail, sd.status.name, sd.status.char_id, sd.status.account_id);
map_quit(&sd);
}
}

View File

@@ -23,9 +23,9 @@ void do_final_vending(void);
void do_init_vending(void);
void do_init_vending_autotrade( void );
void vending_reopen( map_session_data* sd );
void vending_reopen( map_session_data& sd );
void vending_closevending(map_session_data* sd);
int8 vending_openvending(map_session_data* sd, const char* message, const uint8* data, int count, struct s_autotrader *at);
int8 vending_openvending( map_session_data& sd, const char* message, const uint8* data, int count, struct s_autotrader *at );
void vending_vendinglistreq(map_session_data* sd, int id);
void vending_purchasereq(map_session_data* sd, int aid, int uid, const uint8* data, int count);
bool vending_search(map_session_data* sd, t_itemid nameid);

View File

@@ -156,6 +156,16 @@ static void skilltree_txt_data(const std::string &modePath, const std::string &f
sv_readdb(modePath.c_str(), "skill_tree.txt", ',', 3 + MAX_PC_SKILL_REQUIRE * 2, 5 + MAX_PC_SKILL_REQUIRE * 2, -1, pc_readdb_skilltree, false);
}
// Produce database data to memory
static void produce_txt_data(const std::string &modePath, const std::string &fixedPath) {
skill_produce.clear();
if (fileExists(modePath + "/produce_db.txt"))
sv_readdb(modePath.c_str(), "produce_db.txt", ',', 5, 5 + 2 * MAX_PRODUCE_RESOURCE, MAX_SKILL_PRODUCE_DB, skill_parse_row_producedb, false);
if (fileExists(fixedPath + "/skill_changematerial_db.txt"))
sv_readdb(fixedPath.c_str(), "skill_changematerial_db.txt", ',', 5, 5 + 2 * MAX_SKILL_CHANGEMATERIAL_SET, MAX_SKILL_CHANGEMATERIAL_DB, skill_parse_row_changematerialdb, false);
}
template<typename Func>
bool process( const std::string& type, uint32 version, const std::vector<std::string>& paths, const std::string& name, Func lambda, const std::string& rename = "" ){
for( const std::string& path : paths ){
@@ -241,6 +251,9 @@ bool Csv2YamlTool::initialize( int argc, char* argv[] ){
#define export_constant_npc(a) export_constant(a)
init_random_option_constants();
#include <map/script_constants.hpp>
// Constants that are deprecated but still needed for conversion
script_set_constant(QUOTE(RC2_GUARDIAN), RC2_GUARDIAN, false, false);
script_set_constant(QUOTE(RC2_BATTLEFIELD), RC2_BATTLEFIELD, false, false);
std::vector<std::string> root_paths = {
path_db,
@@ -560,13 +573,28 @@ bool Csv2YamlTool::initialize( int argc, char* argv[] ){
})) {
return 0;
}
produce_txt_data(path_db_mode, path_db);
if (!process("PRODUCE_DB", 1, { path_db_mode }, "produce_db", [](const std::string &path, const std::string &name_ext) -> bool {
return skill_producedb_yaml();
})) {
return 0;
}
produce_txt_data(path_db_import, path_db_import);
if (!process("PRODUCE_DB", 1, { path_db_import }, "produce_db", [](const std::string &path, const std::string &name_ext) -> bool {
return skill_producedb_yaml();
})) {
return 0;
}
// TODO: add implementations ;-)
homunculus_txt_data(path_db_import, path_db_import);
if (!process("HOMUNCULUS_DB", 1, { path_db_import }, "homunculus_db", [](const std::string& path, const std::string& name_ext) -> bool {
return sv_readdb(path.c_str(), name_ext.c_str(), ',', 50, 50, MAX_HOMUNCULUS_CLASS, read_homunculusdb, false);
})) {
return 0;
}
return 0;
}
// TODO: add implementations ;-)
@@ -3367,17 +3395,17 @@ static bool mob_readdb_sub( char *fields[], size_t columns, size_t current ){
body << YAML::Key << "Defense" << YAML::Value << cap_value(std::stoi(fields[12]), DEFTYPE_MIN, DEFTYPE_MAX);
if (strtol(fields[13], nullptr, 10) > 0)
body << YAML::Key << "MagicDefense" << YAML::Value << cap_value(std::stoi(fields[13]), DEFTYPE_MIN, DEFTYPE_MAX);
if (strtol(fields[14], nullptr, 10) > 1)
if (strtol(fields[14], nullptr, 10) != 1)
body << YAML::Key << "Str" << YAML::Value << fields[14];
if (strtol(fields[15], nullptr, 10) > 1)
if (strtol(fields[15], nullptr, 10) != 1)
body << YAML::Key << "Agi" << YAML::Value << fields[15];
if (strtol(fields[16], nullptr, 10) > 1)
if (strtol(fields[16], nullptr, 10) != 1)
body << YAML::Key << "Vit" << YAML::Value << fields[16];
if (strtol(fields[17], nullptr, 10) > 1)
if (strtol(fields[17], nullptr, 10) != 1)
body << YAML::Key << "Int" << YAML::Value << fields[17];
if (strtol(fields[18], nullptr, 10) > 1)
if (strtol(fields[18], nullptr, 10) != 1)
body << YAML::Key << "Dex" << YAML::Value << fields[18];
if (strtol(fields[19], nullptr, 10) > 1)
if (strtol(fields[19], nullptr, 10) != 1)
body << YAML::Key << "Luk" << YAML::Value << fields[19];
if (strtol(fields[9], nullptr, 10) > 0)
body << YAML::Key << "AttackRange" << YAML::Value << fields[9];
@@ -5268,6 +5296,169 @@ static bool read_homunculusdb( char* str[], size_t columns, size_t current ){
return true;
}
// Copied and adjusted from skill.cpp
static bool skill_parse_row_producedb(char* split[], size_t columns, size_t current) {
t_itemid nameid = static_cast<t_itemid>(strtoul(split[1], nullptr, 10));
if (nameid == 0) {
ShowError("skill_parse_row_producedb: Removing an item for this DB must be done manually. Skipping.\n");
return false;
}
std::string *item_name = util::umap_find(aegis_itemnames, nameid);
if (!item_name) {
ShowError("skill_parse_row_producedb: Invalid item %u.\n", nameid);
return false;
}
uint16 skill_id = static_cast<uint16>(strtoul(split[3], nullptr, 10));
std::string* skill_name = util::umap_find( aegis_skillnames, skill_id );
if (skill_id != 0 && skill_name == nullptr) {
ShowError( "Skill name for skill id %hu is not known.\n", skill_id );
return false;
}
s_skill_produce_db_csv entry = {};
uint32 skill_lv = strtoul(split[4], nullptr, 10);
uint32 itemlv = strtoul(split[2], nullptr, 10);
entry.produced_name = *item_name;
if (skill_name != nullptr) {
entry.req_skill_name = *skill_name;
entry.req_skill_lv = skill_lv;
}
for (size_t x = 5; x+1 < columns && split[x] && split[x+1]; x += 2) {
nameid = static_cast<t_itemid>(strtoul(split[x], nullptr, 10));
item_name = util::umap_find(aegis_itemnames, nameid);
if (!item_name) {
ShowError("skill_parse_row_producedb: Invalid item %u.\n", nameid);
return false;
}
uint32 amount = strtoul(split[x+1], nullptr, 10);
if (amount == 0)
entry.item_notconsumed.push_back(*item_name);
else
entry.item_consumed[ *item_name ] = amount;
}
const auto &exists = skill_produce.find(itemlv);
if (exists != skill_produce.end())
exists->second.push_back(entry);
else {
std::vector<s_skill_produce_db_csv> produce;
produce.push_back(entry);
skill_produce.insert({ itemlv, produce });
}
return true;
}
// Copied and adjusted from skill.cpp
static bool skill_parse_row_changematerialdb(char* split[], size_t columns, size_t current)
{
t_itemid nameid = static_cast<t_itemid>(strtoul(split[1], nullptr, 10));
// Import just for clearing/disabling from original data
// NOTE: If import for disabling, better disable list from produce_db instead of here, or creation just failed with deleting requirements.
if (nameid == 0) {
ShowError("skill_parse_row_changematerialdb: Removing an item for this DB must be done manually. Skipping.\n");
return false;
}
std::string *produced_name = util::umap_find(aegis_itemnames, nameid);
if (!produced_name) {
ShowError("skill_parse_row_changematerialdb: Invalid item %u.\n", nameid);
return false;
}
s_skill_changematerial_db_csv item = {};
item.baserate = static_cast<uint16>(strtoul(split[2], nullptr, 10));
for (size_t x = 3; x+1 < columns && split[x] && split[x+1]; x += 2) {
item.qty.insert({ static_cast<uint16>(strtoul(split[x], nullptr, 10)), static_cast<uint16>(strtoul(split[x+1], nullptr, 10)) });
}
skill_changematerial_db.insert({ *produced_name, item });
return true;
}
static bool skill_producedb_yaml(void) {
for (const auto &produceit : skill_produce) {
body << YAML::BeginMap;
body << YAML::Key << "ItemLevel" << YAML::Value << produceit.first;
body << YAML::Key << "Recipe";
body << YAML::BeginSeq;
for (const auto &it : produceit.second) {
body << YAML::BeginMap;
body << YAML::Key << "Product" << YAML::Value << it.produced_name;
// additional lines from skill_changematerial_db (which uses ItemLV 26)
if (produceit.first == 26) {
s_skill_changematerial_db_csv* changematerial = util::umap_find( skill_changematerial_db, it.produced_name );
if (changematerial != nullptr) {
if (changematerial->baserate != 1000)
body << YAML::Key << "BaseRate" << YAML::Value << changematerial->baserate;
if (!changematerial->qty.empty()) {
body << YAML::Key << "Make";
body << YAML::BeginSeq;
for (const auto &qit : changematerial->qty) {
body << YAML::BeginMap;
body << YAML::Key << "Amount" << YAML::Value << qit.first;
if (qit.second != 1000)
body << YAML::Key << "Rate" << YAML::Value << qit.second;
body << YAML::EndMap;
}
body << YAML::EndSeq;
}
}
}
if (it.req_skill_lv > 0) {
body << YAML::Key << "SkillName" << YAML::Value << it.req_skill_name;
body << YAML::Key << "SkillLevel" << YAML::Value << it.req_skill_lv;
}
if (!it.item_consumed.empty()) {
body << YAML::Key << "Consumed";
body << YAML::BeginSeq;
for (const auto &itemit : it.item_consumed) {
body << YAML::BeginMap;
body << YAML::Key << "Item" << YAML::Value << itemit.first;
body << YAML::Key << "Amount" << YAML::Value << itemit.second;
body << YAML::EndMap;
}
body << YAML::EndSeq;
}
if (!it.item_notconsumed.empty()) {
body << YAML::Key << "NotConsumed";
body << YAML::BeginSeq;
for (const auto &itemit : it.item_notconsumed) {
body << YAML::BeginMap;
body << YAML::Key << "Item" << YAML::Value << itemit;
body << YAML::EndMap;
}
body << YAML::EndSeq;
}
body << YAML::EndMap;
}
body << YAML::EndSeq;
body << YAML::EndMap;
}
return true;
}
int main( int argc, char *argv[] ){
return main_core<Csv2YamlTool>( argc, argv );
}

View File

@@ -42,6 +42,10 @@ namespace rathena{
///Maximum amount of items a combo may require
#define MAX_ITEMS_PER_COMBO 6
#define MAX_HOM_SKILL_REQUIRE 5
#define MAX_SKILL_CHANGEMATERIAL_DB 75
#define MAX_SKILL_CHANGEMATERIAL_SET 3
#define MAX_SKILL_PRODUCE_DB 300 /// Max Produce DB
#define MAX_PRODUCE_RESOURCE 12 /// Max Produce requirements
struct s_skill_tree_entry_csv {
std::string skill_name;
@@ -65,6 +69,23 @@ std::unordered_map<uint16, s_skill_db> skill_nearnpc;
std::unordered_map<int32, std::vector<s_homun_skill_tree_entry>> hom_skill_tree;
struct s_skill_produce_db_csv {
std::string produced_name,
req_skill_name;
uint32 req_skill_lv,
itemlv;
std::map<std::string, uint32> item_consumed;
std::vector<std::string> item_notconsumed;
};
std::map<uint32, std::vector<s_skill_produce_db_csv>> skill_produce;
struct s_skill_changematerial_db_csv {
uint16 baserate;
std::map<uint16, uint16> qty;
};
std::unordered_map<std::string, s_skill_changematerial_db_csv> skill_changematerial_db;
static unsigned int level_penalty[3][CLASS_MAX][MAX_LEVEL * 2 + 1];
struct s_item_flag_csv2yaml {
@@ -536,5 +557,9 @@ static bool itemdb_read_combos(const char* file);
static bool cashshop_parse_dbrow( char* fields[], size_t columns, size_t current );
static bool read_homunculus_skilldb( char* split[], size_t columns, size_t current );
static bool read_homunculusdb( char* str[], size_t columns, size_t current );
static bool skill_parse_row_producedb(char* fields[], size_t columns, size_t current);
static bool skill_producedb_yaml();
static bool skill_parse_row_producedb(char *split[], size_t columns, size_t current);
static bool skill_parse_row_changematerialdb(char* fields[], size_t columns, size_t current);
#endif /* CSV2YAML_HPP */