diff --git a/AUTHORS b/AUTHORS index 8fc78bfc3..863ae8379 100644 --- a/AUTHORS +++ b/AUTHORS @@ -93,6 +93,7 @@ linton-dawson LiYu louisplag <42522191+louisplag@users.noreply.github.com> Lucas Brito +Lucas Golino M45T3Ryu malufett maqc1 @@ -178,6 +179,7 @@ TungSinpei ultramage Unknown Victor +vietlubu Vincent Thibault Wolfie@HP-Laptop Wolf diff --git a/CHANGELOG.md b/CHANGELOG.md index c08932744..b9cf603f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,61 @@ If you are reading this in a text editor, simply ignore this section ### Removed --> +## [v2024.04] `April 2024` + +### Added + +- Implemented `skill->get_index_sub()`, allowing to prevent error reports on the console when a skill is not found, for testing whether a skill exists in places where its absence is not an error. (#3292) +- Implemented (m)atk/(m)def percent system: (#3290) + - Implemented percent atk/def/matk/mdef bonus calculation, matching the official behavior + - Added the `AtkPerc`, `DefPerc`, `MatkPerc`, `MdefPerc` calc flags to `sc_config.conf` to trigger recalculation of the respective stats + - Added atk percent bonus to the client's status window like on official servers (note: the matk percent bonus is not displayed) + - Added def percent bonus to the client's status window (included in the soft def) + - Implemented official behavior for skills/status changes that officially rely on this system (detailed below) +- Added the script command `getitemgroupitems()` to obtain a list (without duplicates) of all items contained in a given item group (#3275) +- Added support for the `ZC_SOULENERGY` packet for displaying soul balls, split from `ZC_SPIRITS` for new clients (#3291) + +### Changed + +- Converted handling of packets `ZC_SKILL_SELECT_REQUEST`, `CZ_SKILL_SELECT_RESPONSE` and `ZC_SPIRITS2` to the structure format. (#3292, #3291) +- Changed the Tarot Card of Fate (`CG_TAROTCARD`) Strength (atk), The Magician (matk), The Devil (atk, matk), The Sun (atk, matk, def) bonus calculation to use the newly implemented atk/def percent system. This includes the new SCs `SC_TAROTCARD_ATK_PERC`, `SC_TAROTCARD_MATK_PERC`, `SC_TAROTCARD_DEF_PERC`. (#3290) +- Changed the Gospel (`PA_GOSPEL`) bonus calculations to use the newly implemented atk/def percent system. This includes the new SC `SC_GOSPEL_ATK_PERC`. (#3290) +- Changed the Provoke (`SM_PROVOKE`, `MER_PROVOKE`) SC (`SC_PROVOKE`) to use the newly implemented atk/def percent system. (#3290) +- Changed the Concentration (`LK_CONCENTRATION`) SC (`SC_CONCENTRATION`) to use the newly implemented atk/def percent system. (#3290) +- Changed the Bloodlust (`HAMI_BLOODLUST`) SC (`SC_HAMI_BLOODLUST`) to use the newly implemented atk/def percent system. (#3290) +- Changed the Vital Strike (`LK_JOINTBEAT`) SC (`SC_JOINTBEAT`) to use the newly implemented atk/def percent system. (#3290) +- Changed the Eske (`SL_SKE`) SC (`SC_SKE`) to use the newly implemented atk/def percent system. (#3290) +- Changed the Fleeting Move (`HFLI_FLEET`) SC (`SC_HLIF_FLEET`) to use the newly implemented atk/def percent system. (#3290) +- Changed the Curse SC (`SC_CURSE`) to use the newly implemented atk/def percent system. (#3290) +- Changed `SC_INCATKRATE` to use the newly implemented atk/def percent system. (#3290) +- Changed the Divest Weapon (`RG_STRIPWEAPON`) SC (`SC_NOEQUIPWEAPON`) to use the newly implemented atk/def percent system. (#3290) +- Changed the Mind Breaker (`PF_MINDBREAKER`) SC (`SC_MINDBREAKER`) to use the newly implemented atk/def percent system. (#3290) +- Changed the Divest Shield (`RG_STRIPSHIELD`) SC (`SC_NOEQUIPSHIELD`) to use the newly implemented atk/def percent system. (#3290) +- Changed the Fling (`GS_FLING`) SC (`SC_FLING`) to use the newly implemented atk/def percent system. (#3290) +- Changed the Angelus (`AL_ANGELUS`) SC (`SC_ANGELUS`) to use the newly implemented atk/def percent system. (#3290) +- Changed Poison (`SC_POISON`) and Deadly Poison (`SC_DPOISON`) to use the newly implemented atk/def percent system. (#3290) +- Changed Asura Strike (`MO_EXTREMITYFIST`) to ignore atk percent bonuses. (#3290) +- Changed several functions to take or return `enum scb_flag` where appropriate. (#3290) +- Added a compatibility workaround for `enum scb_flag` (via typedef to `e_scb_flag` and `int64_t` constants) for pre-C23 MSVC versions that don't support enum values larger than 32 bit. This is only conditionally enabled on such compilers, and will be dropped when we'll be able to switch the C standard to C23. (#3290) +- Split handling of the spiritball clif function into `clif->spiritballs()` and `clif->soulball()`, with incompatible arguments to the old `clif->spiritball()` calls. Second argument is now the amount of spheres, instead of their type. (#3291) + +### Fixed + +- Fixed a memory leak when reloading the unit params db (#3288) +- Fixed an assertion failure in Auto Shadow Spell when the character has no cloned or reproduced skills. (#3292) +- Fixed Auto Shadow Spell's inability to switch to a skill with a lower skill id than the previously selected one. (#3292) +- Fixed an assertion failure when clicking "ok" with no skills selected or clicking "cancel" in Shadow Spell. (#3292, issue #3286) +- Fixed the value of the `flag` field of packet `ZC_SKILL_SELECT_REQUEST`, expected to be 1 (meaning auto shadow spell) rather than the amount of skills in the list. (#3292) +- Fixed soul balls not displaying correctly in clients from 2020 onwards. (#3291) + +### Deprecated + +- Support for C99 is deprecated and will be removed soon. C11 will be the required C standard since all the officially supported compilers implement that. This is a reminder that the mainstream support for VS2019 by Microsoft ended on Apr 9 2024, making VS2022 (version 17.4 and newer) the only version we currently support officially. + +### Other + +- Work on the rebalance patch is continuing on the `rebalance` branch. + ## [v2024.03] `March 2024` ### Added @@ -3035,6 +3090,7 @@ Note: everything included in this release is part of PR #3198 which consists of - New versioning scheme and project changelogs/release notes (#1853) [Unreleased]: https://github.com/HerculesWS/Hercules/compare/stable...master +[v2024.04]: https://github.com/HerculesWS/Hercules/compare/v2024.03...v2024.04 [v2024.03]: https://github.com/HerculesWS/Hercules/compare/v2024.02...v2024.03 [v2024.02]: https://github.com/HerculesWS/Hercules/compare/v2023.12...v2024.02 [v2023.12]: https://github.com/HerculesWS/Hercules/compare/v2023.11...v2023.12 diff --git a/db/constants.conf b/db/constants.conf index deef03175..eb16c1bbf 100644 --- a/db/constants.conf +++ b/db/constants.conf @@ -1307,6 +1307,10 @@ constants_db: { SC_SOULDIVISION: 716 SC_ACTIVE_MONSTER_TRANSFORM: 717 + SC_TAROTCARD_ATK_PERC: 719 + SC_TAROTCARD_MATK_PERC: 720 + SC_TAROTCARD_DEF_PERC: 721 + SC_GOSPEL_ATK_PERC: 722 comment__: "Emotes" e_gasp: 0 diff --git a/db/pre-re/sc_config.conf b/db/pre-re/sc_config.conf index 2589e6aa5..d0a3d39bd 100644 --- a/db/pre-re/sc_config.conf +++ b/db/pre-re/sc_config.conf @@ -80,6 +80,10 @@ SC_TYPE: { Range: (bool, defaults to false) Regen: (bool, defaults to false) Dye: (bool, defaults to false) + AtkPerc: (bool, defaults to false) + DefPerc: (bool, defaults to false) + MatkPerc: (bool, defaults to false) + MdefPerc: (bool, defaults to false) All: (bool, defaults to false) } Icon: (string, defaults to SI_BLANK) The status icon attached to the SC @@ -92,10 +96,8 @@ SC_PROVOKE: { NoBoss: true } CalcFlags: { - Batk: true - Watk: true - Def: true - Def2: true + AtkPerc: true + DefPerc: true } Icon: "SI_PROVOKE" Skill: "SM_PROVOKE" @@ -198,7 +200,7 @@ SC_ANGELUS: { Buff: true } CalcFlags: { - Def2: true + DefPerc: true } Icon: "SI_ANGELUS" Skill: "AL_ANGELUS" @@ -459,7 +461,7 @@ SC_NOEQUIPWEAPON: { Buff: true } CalcFlags: { - Watk: true + AtkPerc: true } Icon: "SI_NOEQUIPWEAPON" Skill: "RG_STRIPWEAPON" @@ -473,7 +475,7 @@ SC_NOEQUIPSHIELD: { Buff: true } CalcFlags: { - Def: true + DefPerc: true } Icon: "SI_NOEQUIPSHIELD" Skill: "RG_STRIPSHIELD" @@ -756,11 +758,9 @@ SC_LKCONCENTRATION: { Buff: true } CalcFlags: { - Batk: true - Watk: true Hit: true - Def: true - Def2: true + AtkPerc: true + DefPerc: true } Icon: "SI_LKCONCENTRATION" Skill: "LK_CONCENTRATION" @@ -980,8 +980,8 @@ SC_JOINTBEAT: { Debuff: true } CalcFlags: { - Batk: true - Def2: true + AtkPerc: true + DefPerc: true Speed: true Aspd: true } @@ -994,8 +994,8 @@ SC_MINDBREAKER: { Buff: true } CalcFlags: { - Matk: true - Mdef2: true + MatkPerc: true + MdefPerc: true } Skill: "PF_MINDBREAKER" } @@ -5389,7 +5389,7 @@ SC_MIRACLE: { } SC_POISON: { CalcFlags: { - Def2: true + DefPerc: true Regen: true } Icon: "SI_CLOUDKILL" @@ -5532,10 +5532,8 @@ SC_ALMIGHTY: { } SC_SKE: { CalcFlags: { - Batk: true - Watk: true - Def: true - Def2: true + AtkPerc: true + DefPerc: true } Icon: "SI_SKE" Skill: "SL_SKE" @@ -5568,8 +5566,7 @@ SC_SLEEP: { SC_CURSE: { CalcFlags: { Luk: true - Batk: true - Watk: true + AtkPerc: true Speed: true } Skill: "NPC_CURSEATTACK" @@ -5586,7 +5583,7 @@ SC_BLIND: { } SC_DPOISON: { CalcFlags: { - Def2: true + DefPerc: true Regen: true } Skill: "NPC_POISON" @@ -5723,8 +5720,7 @@ SC_KNOWLEDGE: { } SC_FLING: { CalcFlags: { - Def: true - Def2: true + DefPerc: true } Skill: "GS_FLING" } @@ -5743,15 +5739,13 @@ SC_HLIF_CHANGE: { } SC_HAMI_BLOODLUST: { CalcFlags: { - Batk: true - Watk: true + AtkPerc: true } Skill: "HAMI_BLOODLUST" } SC_HLIF_FLEET: { CalcFlags: { - Batk: true - Watk: true + AtkPerc: true Aspd: true } Skill: "HFLI_FLEET" @@ -5902,8 +5896,7 @@ SC_INCMSPRATE: { } SC_INCATKRATE: { CalcFlags: { - Batk: true - Watk: true + AtkPerc: true } } SC_INCMATKRATE: { @@ -6408,3 +6401,42 @@ SC_ACTIVE_MONSTER_TRANSFORM: { SC__FEINTBOMB_MASTER: { Skill: "SC_FEINTBOMB" } +SC_TAROTCARD_ATK_PERC: { + Flags: { + NoSave: true + NoClearanceReset: true + Debuff: true + } + CalcFlags: { + AtkPerc: true + } +} +SC_TAROTCARD_MATK_PERC: { + Flags: { + NoSave: true + NoClearanceReset: true + Debuff: true + } + CalcFlags: { + MatkPerc: true + } +} +SC_TAROTCARD_DEF_PERC: { + Flags: { + NoSave: true + NoClearanceReset: true + Debuff: true + } + CalcFlags: { + DefPerc: true + } +} +SC_GOSPEL_ATK_PERC: { + Flags: { + NoSave: true + Debuff: true + } + CalcFlags: { + AtkPerc: true + } +} diff --git a/db/re/sc_config.conf b/db/re/sc_config.conf index b2254b8c9..2f760d38f 100644 --- a/db/re/sc_config.conf +++ b/db/re/sc_config.conf @@ -80,6 +80,10 @@ SC_TYPE: { Range: (bool, defaults to false) Regen: (bool, defaults to false) Dye: (bool, defaults to false) + AtkPerc: (bool, defaults to false) + DefPerc: (bool, defaults to false) + MatkPerc: (bool, defaults to false) + MdefPerc: (bool, defaults to false) All: (bool, defaults to false) } Icon: (string, defaults to SI_BLANK) The status icon attached to the SC @@ -92,10 +96,8 @@ SC_PROVOKE: { NoBoss: true } CalcFlags: { - Batk: true - Watk: true - Def: true - Def2: true + AtkPerc: true + DefPerc: true } Icon: "SI_PROVOKE" Skill: "SM_PROVOKE" @@ -460,7 +462,7 @@ SC_NOEQUIPWEAPON: { Buff: true } CalcFlags: { - Watk: true + AtkPerc: true } Icon: "SI_NOEQUIPWEAPON" Skill: "RG_STRIPWEAPON" @@ -474,7 +476,7 @@ SC_NOEQUIPSHIELD: { Buff: true } CalcFlags: { - Def: true + DefPerc: true } Icon: "SI_NOEQUIPSHIELD" Skill: "RG_STRIPSHIELD" @@ -760,7 +762,8 @@ SC_LKCONCENTRATION: { } CalcFlags: { Hit: true - Def: true + AtkPerc: true + DefPerc: true } Icon: "SI_LKCONCENTRATION" Skill: "LK_CONCENTRATION" @@ -981,8 +984,8 @@ SC_JOINTBEAT: { Debuff: true } CalcFlags: { - Batk: true - Def2: true + AtkPerc: true + DefPerc: true Speed: true Aspd: true } @@ -995,8 +998,8 @@ SC_MINDBREAKER: { Buff: true } CalcFlags: { - Matk: true - Mdef2: true + MatkPerc: true + MdefPerc: true } Skill: "PF_MINDBREAKER" } @@ -5389,7 +5392,7 @@ SC_MIRACLE: { } SC_POISON: { CalcFlags: { - Def2: true + DefPerc: true Regen: true } Icon: "SI_CLOUDKILL" @@ -5532,10 +5535,8 @@ SC_ALMIGHTY: { } SC_SKE: { CalcFlags: { - Batk: true - Watk: true - Def: true - Def2: true + AtkPerc: true + DefPerc: true } Icon: "SI_SKE" Skill: "SL_SKE" @@ -5568,8 +5569,7 @@ SC_SLEEP: { SC_CURSE: { CalcFlags: { Luk: true - Batk: true - Watk: true + AtkPerc: true Speed: true } Skill: "NPC_CURSEATTACK" @@ -5586,7 +5586,7 @@ SC_BLIND: { } SC_DPOISON: { CalcFlags: { - Def2: true + DefPerc: true Regen: true } Skill: "NPC_POISON" @@ -5723,8 +5723,7 @@ SC_KNOWLEDGE: { } SC_FLING: { CalcFlags: { - Def: true - Def2: true + DefPerc: true } Skill: "GS_FLING" } @@ -5743,15 +5742,13 @@ SC_HLIF_CHANGE: { } SC_HAMI_BLOODLUST: { CalcFlags: { - Batk: true - Watk: true + AtkPerc: true } Skill: "HAMI_BLOODLUST" } SC_HLIF_FLEET: { CalcFlags: { - Batk: true - Watk: true + AtkPerc: true Aspd: true } Skill: "HFLI_FLEET" @@ -5902,8 +5899,7 @@ SC_INCMSPRATE: { } SC_INCATKRATE: { CalcFlags: { - Batk: true - Watk: true + AtkPerc: true } } SC_INCMATKRATE: { @@ -6410,3 +6406,42 @@ SC_ACTIVE_MONSTER_TRANSFORM: { SC__FEINTBOMB_MASTER: { Skill: "SC_FEINTBOMB" } +SC_TAROTCARD_ATK_PERC: { + Flags: { + NoSave: true + NoClearanceReset: true + Debuff: true + } + CalcFlags: { + AtkPerc: true + } +} +SC_TAROTCARD_MATK_PERC: { + Flags: { + NoSave: true + NoClearanceReset: true + Debuff: true + } + CalcFlags: { + MatkPerc: true + } +} +SC_TAROTCARD_DEF_PERC: { + Flags: { + NoSave: true + NoClearanceReset: true + Debuff: true + } + CalcFlags: { + DefPerc: true + } +} +SC_GOSPEL_ATK_PERC: { + Flags: { + NoSave: true + Debuff: true + } + CalcFlags: { + AtkPerc: true + } +} diff --git a/doc/constants_pre-re.md b/doc/constants_pre-re.md index a9947fd70..175f3d333 100644 --- a/doc/constants_pre-re.md +++ b/doc/constants_pre-re.md @@ -1231,6 +1231,10 @@ - `SC_SOULGOLEM`: 715 - `SC_SOULDIVISION`: 716 - `SC_ACTIVE_MONSTER_TRANSFORM`: 717 +- `SC_TAROTCARD_ATK_PERC`: 719 +- `SC_TAROTCARD_MATK_PERC`: 720 +- `SC_TAROTCARD_DEF_PERC`: 721 +- `SC_GOSPEL_ATK_PERC`: 722 ### Emotes @@ -4874,7 +4878,7 @@ ### Server defines - `PACKETVER`: 20190530 -- `HERCULES_VERSION`: 202403000 +- `HERCULES_VERSION`: 202404000 - `MAX_LEVEL`: 175 - `MAX_STORAGE`: 600 - `MAX_GUILD_STORAGE`: 500 diff --git a/doc/constants_re.md b/doc/constants_re.md index 69ae1d5f7..1df151f05 100644 --- a/doc/constants_re.md +++ b/doc/constants_re.md @@ -1231,6 +1231,10 @@ - `SC_SOULGOLEM`: 715 - `SC_SOULDIVISION`: 716 - `SC_ACTIVE_MONSTER_TRANSFORM`: 717 +- `SC_TAROTCARD_ATK_PERC`: 719 +- `SC_TAROTCARD_MATK_PERC`: 720 +- `SC_TAROTCARD_DEF_PERC`: 721 +- `SC_GOSPEL_ATK_PERC`: 722 ### Emotes @@ -4874,7 +4878,7 @@ ### Server defines - `PACKETVER`: 20190530 -- `HERCULES_VERSION`: 202403000 +- `HERCULES_VERSION`: 202404000 - `MAX_LEVEL`: 175 - `MAX_STORAGE`: 600 - `MAX_GUILD_STORAGE`: 500 diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 1eefdfcb0..afaa90afc 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -11136,3 +11136,23 @@ When is not provided, it defaults to -1, and the current played ti If keeping the GoldPC mode between sessions is desired, you may use OnPCLoginEvent. Check out some examples in `doc/sample/goldpc.txt`. + + +--------------------------------------- + +*getitemgroupitems(, ) + +Fills the array with the IDs of the items from the item group, without duplicates. + +Returns the amount of items inserted into the array. + +Note: The array will not be automatically cleared. It's recommended to use the returned value to loop over the array instead of relying on getarraysize. + +The possible values for can be found in `db/(pre-)re/item_group.conf` + +Example: + + .@count = getitemgroupitems(.@item_list[0], Old_Card_Album); + for (.@i = 0; .@i < .@count; ++.@i) { + mesf("^1E56BD\t%s^000000", getitemname(.@item_list[.@i])); + } diff --git a/src/common/HPMDataCheck.h b/src/common/HPMDataCheck.h index 716a94b78..a8d6f53ac 100644 --- a/src/common/HPMDataCheck.h +++ b/src/common/HPMDataCheck.h @@ -859,6 +859,7 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = { { "PACKET_CZ_SEARCH_STORE_INFO", sizeof(struct PACKET_CZ_SEARCH_STORE_INFO), SERVER_TYPE_MAP }, { "PACKET_CZ_SEARCH_STORE_INFO_item", sizeof(struct PACKET_CZ_SEARCH_STORE_INFO_item), SERVER_TYPE_MAP }, { "PACKET_CZ_SEND_MAIL", sizeof(struct PACKET_CZ_SEND_MAIL), SERVER_TYPE_MAP }, + { "PACKET_CZ_SKILL_SELECT_RESPONSE", sizeof(struct PACKET_CZ_SKILL_SELECT_RESPONSE), SERVER_TYPE_MAP }, { "PACKET_CZ_SSILIST_ITEM_CLICK", sizeof(struct PACKET_CZ_SSILIST_ITEM_CLICK), SERVER_TYPE_MAP }, { "PACKET_ZC_ACK_BAN_GUILD1", sizeof(struct PACKET_ZC_ACK_BAN_GUILD1), SERVER_TYPE_MAP }, { "PACKET_ZC_ACK_BAN_GUILD2", sizeof(struct PACKET_ZC_ACK_BAN_GUILD2), SERVER_TYPE_MAP }, @@ -967,10 +968,12 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = { { "PACKET_ZC_SAY_DIALOG2", sizeof(struct PACKET_ZC_SAY_DIALOG2), SERVER_TYPE_MAP }, { "PACKET_ZC_SHOW_IMAGE", sizeof(struct PACKET_ZC_SHOW_IMAGE), SERVER_TYPE_MAP }, { "PACKET_ZC_SKILL_SCALE", sizeof(struct PACKET_ZC_SKILL_SCALE), SERVER_TYPE_MAP }, + { "PACKET_ZC_SKILL_SELECT_REQUEST", sizeof(struct PACKET_ZC_SKILL_SELECT_REQUEST), SERVER_TYPE_MAP }, { "PACKET_ZC_SKILLINFO_LIST", sizeof(struct PACKET_ZC_SKILLINFO_LIST), SERVER_TYPE_MAP }, { "PACKET_ZC_SKILLINFO_UPDATE2", sizeof(struct PACKET_ZC_SKILLINFO_UPDATE2), SERVER_TYPE_MAP }, { "PACKET_ZC_SOUND", sizeof(struct PACKET_ZC_SOUND), SERVER_TYPE_MAP }, { "PACKET_ZC_SPIRITS", sizeof(struct PACKET_ZC_SPIRITS), SERVER_TYPE_MAP }, + { "PACKET_ZC_SPIRITS2", sizeof(struct PACKET_ZC_SPIRITS2), SERVER_TYPE_MAP }, { "PACKET_ZC_SPRITE_CHANGE", sizeof(struct PACKET_ZC_SPRITE_CHANGE), SERVER_TYPE_MAP }, { "PACKET_ZC_START_CAPTURE", sizeof(struct PACKET_ZC_START_CAPTURE), SERVER_TYPE_MAP }, { "PACKET_ZC_STATE_CHANGE", sizeof(struct PACKET_ZC_STATE_CHANGE), SERVER_TYPE_MAP }, diff --git a/src/config/core.h b/src/config/core.h index 143900175..4017b50b4 100644 --- a/src/config/core.h +++ b/src/config/core.h @@ -22,7 +22,7 @@ #define CONFIG_CORE_H /// Hercules version. From tag vYYYY.MM(+PPP) -> YYYYMMPPP -#define HERCULES_VERSION 202403000 +#define HERCULES_VERSION 202404000 /// Max number of items on @autolootid list #define AUTOLOOTITEM_SIZE 10 diff --git a/src/map/atcommand.c b/src/map/atcommand.c index bf3b04659..10528e797 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -3503,7 +3503,7 @@ ACMD(spiritball) if( sd->spiritball > 0 ) pc->delspiritball(sd, sd->spiritball, 1); sd->spiritball = number; - clif->spiritball(&sd->bl, BALL_TYPE_SPIRIT, AREA); + clif->spiritballs(&sd->bl, sd->spiritball, AREA); // no message, player can look the difference return true; diff --git a/src/map/battle.c b/src/map/battle.c index 265a24516..fb50c5524 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1533,6 +1533,7 @@ static int64 battle_calc_defense(int attack_type, struct block_list *src, struct #else vit_def = def2; #endif + vit_def = (vit_def * tstatus->def_percent) / 100; if((battle->check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_DEMON) && //This bonus already doesn't work vs players src->type == BL_MOB && (i=pc->checkskill(tsd,AL_DP)) > 0) vit_def += i*(int)(3 +(tsd->status.base_level+1)*0.04); // [orn] @@ -1548,6 +1549,8 @@ static int64 battle_calc_defense(int attack_type, struct block_list *src, struct #else vit_def = def2; #endif + vit_def = (vit_def * tstatus->def_percent) / 100; + def1 = (def1 * tstatus->def_percent) / 100; } if (battle_config.weapon_defense_type) { @@ -4058,6 +4061,10 @@ static struct Damage battle_calc_magic_attack(struct block_list *src, struct blo default: MATK_RATE(battle->calc_skillratio(BF_MAGIC, src, target, skill_id, skill_lv, skillratio, mflag)); } + + // Aegis: It seems like most percentual matk bonuses, besides matk_percent, are used additively. + MATK_RATE(sstatus->matk_percent); + //Constant/misc additions from skills if (skill_id == WZ_FIREPILLAR) MATK_ADD(100+50*skill_lv); @@ -5320,6 +5327,20 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill->get_name(skill_id)); } + bool skip_atk_rate_bonus; + switch (skill_id) { + case MO_EXTREMITYFIST: + skip_atk_rate_bonus = true; + break; + default: + skip_atk_rate_bonus = false; + break; + } + + if (skip_atk_rate_bonus) + break; + + int temp_atk_rate = sstatus->atk_percent; //Add any bonuses that modify the base baseatk+watk (pre-skills) if(sd) { #ifndef RENEWAL @@ -5331,13 +5352,13 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl if(flag.cri && sc && sc->data[SC_MTF_CRIDAMAGE]) ATK_ADDRATE(sc->data[SC_MTF_CRIDAMAGE]->val1);// temporary it should be 'bonus.crit_atk_rate' #ifndef RENEWAL - if(sd->status.party_id && (temp=pc->checkskill(sd,TK_POWER)) > 0){ if ((i = party->foreachsamemap(party->sub_count, sd, 0, sd->status.char_id)) > 0) - ATK_ADDRATE(2*temp*i); + temp_atk_rate += 2 * temp * i; } #endif } + ATK_RATE(temp_atk_rate); break; } //End default case } //End switch(skill_id) diff --git a/src/map/clif.c b/src/map/clif.c index 12e3116ae..09a3ec5d5 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1503,11 +1503,13 @@ static void clif_class_change(struct block_list *bl, int class_, int type, struc static void clif_spiritball_single(int fd, struct map_session_data *sd) { nullpo_retv(sd); - WFIFOHEAD(fd, packet_len(0x1e1)); - WFIFOW(fd,0)=0x1e1; - WFIFOL(fd,2)=sd->bl.id; - WFIFOW(fd,6)=sd->spiritball; - WFIFOSET(fd, packet_len(0x1e1)); + + struct PACKET_ZC_SPIRITS2 p = { 0 }; + + p.PacketType = HEADER_ZC_SPIRITS2; + p.AID = sd->bl.id; + p.num = sd->spiritball; + clif->send(&p, sizeof(p), &sd->bl, SELF); } /*========================================== @@ -1607,9 +1609,9 @@ static bool clif_spawn(struct block_list *bl) struct map_session_data *sd = BL_UCAST(BL_PC, bl); int i; if (sd->spiritball > 0) - clif->spiritball(&sd->bl, BALL_TYPE_SPIRIT, AREA); + clif->spiritballs(&sd->bl, sd->spiritball, AREA); if (sd->soulball > 0) - clif->spiritball(&sd->bl, BALL_TYPE_SOUL, AREA); + clif->soulballs(&sd->bl, sd->soulball, AREA); if (sd->state.size == SZ_BIG) // tiny/big players [Valaris] clif->specialeffect(bl,423,AREA); else if (sd->state.size == SZ_MEDIUM) @@ -4959,7 +4961,7 @@ static void clif_getareachar_pc(struct map_session_data *sd, struct map_session_ if (dstsd->charm_type != CHARM_TYPE_NONE && dstsd->charm_count > 0) clif->charm_single(sd->fd, dstsd); if (dstsd->soulball > 0) - clif->spiritball(&sd->bl, BALL_TYPE_SOUL, AREA); + clif->soulballs(&sd->bl, sd->soulball, AREA); for( i = 0; i < dstsd->sc_display_count; i++ ) { clif->sc_continue(&sd->bl, dstsd->bl.id, SELF, status->get_sc_icon(dstsd->sc_display[i]->type), dstsd->sc_display[i]->val1, dstsd->sc_display[i]->val2, dstsd->sc_display[i]->val3); } @@ -8106,65 +8108,53 @@ static void clif_devotion(struct block_list *src, struct map_session_data *tsd) clif->send(buf, packet_len(0x1cf), src, AREA); } - /** - * Server tells clients nearby 'sd' (and itself) to display spirits spheres - * Notifies clients in an area or self of an object's spirits. - * 01d0 .L .W (ZC_SPIRITS) - * 01e1 .L .W (ZC_SPIRITS2) - * - * @param bl Source block list. - * @param spirit Type of spirit data from sd. - * @param target Either target is AREA or SELF. - */ -static void clif_spiritball(struct block_list *bl, enum spirit_ball_types spirit, enum send_target target) +/** + * Server tells clients nearby 'sd' (and itself) to display soulballs. + * Notifies clients in an area or self of an object's soulballs. + * 01d0 .L .W (ZC_SPIRITS) + * 0b73 .L .W (ZC_SOULENERGY) + * + * @param bl Source block list. + * @param soulballs amount of soulballs + * @param target Either target is AREA or SELF. + */ +static void clif_soulball(struct block_list *bl, int soulballs, enum send_target target) { nullpo_retv(bl); +#if PACKETVER_MAIN_NUM >= 20200414 || PACKETVER_RE_NUM >= 20200723 || PACKETVER_ZERO_NUM >= 20200506 + struct PACKET_ZC_SOULENERGY p = { 0 }; + p.PacketType = HEADER_ZC_SOULENERGY; +#else struct PACKET_ZC_SPIRITS p = { 0 }; - p.PacketType = HEADER_ZC_SPIRITS; +#endif + p.AID = bl->id; - p.num = 0; - switch (bl->type) { - case BL_PC: - { - struct map_session_data *sd = BL_CAST(BL_PC, bl); - nullpo_retv(sd); + p.num = soulballs; + clif->send(&p, sizeof(p), bl, target); +} - switch (spirit) { - case BALL_TYPE_SPIRIT: - p.num = sd->spiritball; - break; - case BALL_TYPE_SOUL: - p.AID = sd->bl.id; - p.num = sd->soulball; - break; - case BALL_TYPE_NONE: - break; - } - clif->send(&p, sizeof(struct PACKET_ZC_SPIRITS), ((bl == NULL && spirit == BALL_TYPE_SOUL) ? &sd->bl : bl), (spirit == BALL_TYPE_SPIRIT ? AREA : target)); - break; - } - case BL_HOM: - { - struct homun_data *hd = BL_CAST(BL_HOM, bl); - nullpo_retv(hd); - p.num = hd->homunculus.spiritball; - } - FALLTHROUGH - case BL_NUL: - case BL_ITEM: - case BL_NPC: - case BL_ELEM: - case BL_SKILL: - case BL_CHAT: - case BL_MOB: - case BL_PET: - case BL_MER: - case BL_ALL: - clif->send(&p, sizeof(struct PACKET_ZC_SPIRITS), bl, AREA); - break; - } +/** + * Server tells clients nearby 'sd' (and itself) to display spirits spheres + * Notifies clients in an area or self of an object's spirits. + * 01d0 .L .W (ZC_SPIRITS) + * 01e1 .L .W (ZC_SPIRITS2) + * + * @param bl Source block list. + * @param spiritballs Number of spirit spheres + * @param target Either target is AREA or SELF. + */ +static void clif_spiritballs(struct block_list *bl, int spiritballs, enum send_target target) +{ + nullpo_retv(bl); + + struct PACKET_ZC_SPIRITS p = { 0 }; + + p.PacketType = HEADER_ZC_SPIRITS; + p.AID = bl->id; + p.num = spiritballs; + clif->send(&p, sizeof(struct PACKET_ZC_SPIRITS), bl, target); } /// Notifies clients in area of a character's combo delay (ZC_COMBODELAY). @@ -9768,7 +9758,7 @@ static void clif_refresh(struct map_session_data *sd) if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0) clif->charm_single(sd->fd, sd); if (sd->soulball > 0) - clif->spiritball(&sd->bl, BALL_TYPE_SOUL, SELF); + clif->soulballs(&sd->bl, sd->soulball, SELF); if (sd->vd.cloth_color) clif->refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); @@ -20836,32 +20826,49 @@ static int clif_poison_list(struct map_session_data *sd, uint16 skill_lv) return 1; } + static int clif_autoshadowspell_list(struct map_session_data *sd) { - int fd, i, c; nullpo_ret(sd); - fd = sd->fd; - if( !fd ) return 0; - if( sd->menuskill_id == SC_AUTOSHADOWSPELL ) + int fd = sd->fd; + if (fd == 0) + return 0; + + if (sd->menuskill_id == SC_AUTOSHADOWSPELL) return 0; - WFIFOHEAD(fd, 2 * 6 + 4); - WFIFOW(fd,0) = 0x442; - for (i = 0, c = 0; i < MAX_SKILL_DB; i++) + // Max number of skills shown. This number should never go above 2, but let's leave some space for customization. + const int max_count = 10; + + struct PACKET_ZC_SKILL_SELECT_REQUEST *p; + int len = max_count * sizeof(*p->skillIds); + WFIFOHEAD(fd, len); + p = WFIFOP(fd, 0); + p->packetType = HEADER_ZC_SKILL_SELECT_REQUEST; + + int c = 0; + for (int i = 0; i < MAX_SKILL_DB && c < max_count; i++) { if (sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].id > 0 && sd->status.skill[i].id < GS_GLITTERING && skill->get_type(sd->status.skill[i].id, sd->status.skill[i].lv) == BF_MAGIC) { // Can't auto cast both Extended class and 3rd class skills. - WFIFOW(fd,8+c*2) = sd->status.skill[i].id; + p->skillIds[c] = sd->status.skill[i].id; c++; } + } - if( c > 0 ) { - WFIFOW(fd,2) = 8 + c * 2; - WFIFOL(fd,4) = c; - WFIFOSET(fd,WFIFOW(fd,2)); + if (c == max_count) + ShowError("%s: max_count shadow spells was reached, some skills may not be shown.\n", __func__); + + if (c > 0) { sd->menuskill_id = SC_AUTOSHADOWSPELL; sd->menuskill_val = c; + + len = c * sizeof(*p->skillIds) + sizeof(*p); + p->packetLength = len; + p->flag = 1; // 1 = auto shadow spell + + WFIFOSET(fd, len); } else { status_change_end(&sd->bl,SC_STOP,INVALID_TIMER); clif->skill_fail(sd, SC_AUTOSHADOWSPELL, USESKILL_FAIL_IMITATION_SKILL_NONE, 0, 0); @@ -20869,6 +20876,7 @@ static int clif_autoshadowspell_list(struct map_session_data *sd) return 1; } + /*=========================================== * Skill list for Four Elemental Analysis * and Change Material skills. @@ -20918,7 +20926,21 @@ static void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) return; } - skill->select_menu(sd,RFIFOW(fd,6)); + const struct PACKET_CZ_SKILL_SELECT_RESPONSE *p = RP2PTR(fd); + + /* selectedSkillId is 0 when cancel is clicked. + * + * Some clients (observed in PACKETVER < 2020) sends random skill ids if you click "ok" + * without selecting a skill. This check prevents the skill logic from running and generating bad reports. + */ + if (p->selectedSkillId == 0 || skill->get_index_sub(p->selectedSkillId, false) == 0) { + status_change_end(&sd->bl, SC_STOP, INVALID_TIMER); + clif->skill_fail(sd, sd->ud.skill_id, 0, 0, 0); + clif_menuskill_clear(sd); + return; + } + + skill->select_menu(sd, p->selectedSkillId); clif_menuskill_clear(sd); } @@ -26704,7 +26726,8 @@ void clif_defaults(void) clif->useskill = clif_useskill; clif->produce_effect = clif_produceeffect; clif->devotion = clif_devotion; - clif->spiritball = clif_spiritball; + clif->soulballs = clif_soulball; + clif->spiritballs = clif_spiritballs; clif->spiritball_single = clif_spiritball_single; clif->bladestop = clif_bladestop; clif->mvp_effect = clif_mvp_effect; diff --git a/src/map/clif.h b/src/map/clif.h index 02207bddb..d77b51abb 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -1209,7 +1209,8 @@ struct clif_interface { void (*useskill) (struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, uint16 skill_id, uint16 skill_lv, int casttime); void (*produce_effect) (struct map_session_data* sd,int flag,int nameid); void (*devotion) (struct block_list *src, struct map_session_data *tsd); - void (*spiritball) (struct block_list *bl, enum spirit_ball_types spirit, enum send_target target); + void (*soulballs) (struct block_list *bl, int soulballs, enum send_target target); + void (*spiritballs) (struct block_list *bl, int spiritballs, enum send_target target); void (*spiritball_single) (int fd, struct map_session_data *sd); void (*bladestop) (struct block_list *src, int dst_id, int active); void (*mvp_effect) (struct map_session_data *sd); diff --git a/src/map/homunculus.c b/src/map/homunculus.c index 467163eb4..c0fb79645 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -124,7 +124,7 @@ static void homunculus_addspiritball(struct homun_data *hd, int max) else hd->homunculus.spiritball++; - clif->spiritball(&hd->bl, BALL_TYPE_NONE, AREA); + clif->spiritballs(&hd->bl, hd->homunculus.spiritball, AREA); } static void homunculus_delspiritball(struct homun_data *hd, int count, int type) @@ -144,7 +144,7 @@ static void homunculus_delspiritball(struct homun_data *hd, int count, int type) hd->homunculus.spiritball -= count; if (!type) - clif->spiritball(&hd->bl, BALL_TYPE_NONE, AREA); + clif->spiritballs(&hd->bl, hd->homunculus.spiritball, AREA); } static void homunculus_damaged(struct homun_data *hd) diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 0e2237859..364030d7e 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -347,6 +347,22 @@ static bool itemdb_in_group(struct item_group *group, int nameid) return false; } +/** + * Search for an item group. + * + * @param nameid item group id to search + * @return A pointer to the group + * @retval NULL if the group was not found + */ +static const struct item_group *itemdb_search_group(int nameid) +{ + int i; + ARR_FIND(0, itemdb->group_count, i, itemdb->groups[i].id == nameid); + if (i != itemdb->group_count) + return &itemdb->groups[i]; + return NULL; +} + /// Searches for the item_data. /// Returns the item_data or NULL if it does not exist. static struct item_data *itemdb_exists(int nameid) @@ -3357,6 +3373,7 @@ void itemdb_defaults(void) itemdb->option_exists = itemdb_option_exists; itemdb->reform_exists = itemdb_reform_exists; itemdb->in_group = itemdb_in_group; + itemdb->search_group = itemdb_search_group; itemdb->group_item = itemdb_searchrandomid; itemdb->chain_item = itemdb_chain_item; itemdb->package_item = itemdb_package_item; diff --git a/src/map/itemdb.h b/src/map/itemdb.h index 404bfc63b..725886d0b 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -708,6 +708,7 @@ struct itemdb_interface { struct itemdb_option* (*option_exists) (int idx); struct item_reform* (*reform_exists) (int idx); bool (*in_group) (struct item_group *group, int nameid); + const struct item_group *(*search_group) (int nameid); int (*group_item) (struct item_group *group); int (*chain_item) (unsigned short chain_id, int *rate); void (*package_item) (struct map_session_data *sd, struct item_package *package); diff --git a/src/map/map.h b/src/map/map.h index 42508d9d5..e2814f75c 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -439,16 +439,6 @@ enum elements { ELE_ALL = 0xFF }; -/** - * Types of Ball Types - * Used by clif_spiritball [KeiKun] - */ -enum spirit_ball_types { - BALL_TYPE_NONE = 0, - BALL_TYPE_SPIRIT, - BALL_TYPE_SOUL -}; - /** * Types of spirit charms. * diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index 7b43e821e..698401d6d 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -3319,6 +3319,20 @@ struct PACKET_ZC_MAKINGARROW_LIST { } __attribute__((packed)); DEFINE_PACKET_HEADER(ZC_MAKINGARROW_LIST, 0x01ad); +struct PACKET_ZC_SKILL_SELECT_REQUEST { + int16 packetType; + int16 packetLength; + int32 flag; //< 0 = old code compatibility; 1 = Auto Shadow Spell; same value is received in CZ_SKILL_SELECT_RESPONSE + int16 skillIds[]; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_SKILL_SELECT_REQUEST, 0x0442); + +struct PACKET_CZ_SKILL_SELECT_RESPONSE { + int16 packetType; + int32 flag; //< currently unused, matches ZC_SKILL_SELECT_REQUEST.flag + int16 selectedSkillId; +} __attribute__((packed)); + #if PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200723 || PACKETVER_ZERO_NUM >= 20221024 #define REPAIRITEM_INFO REPAIRITEM_INFO2 struct PACKET_ZC_REPAIRITEMLIST { @@ -4768,7 +4782,7 @@ struct PACKET_ZC_NOTIFY_SKILL { int8 action; } __attribute__((packed)); DEFINE_PACKET_HEADER(ZC_NOTIFY_SKILL, 0x01de); -#endif +#endif #if PACKETVER_MAIN_NUM >= 20130731 || PACKETVER_RE_NUM >= 20130724 || defined(PACKETVER_ZERO) struct PACKET_ZC_USE_SKILL { @@ -5558,6 +5572,22 @@ struct PACKET_ZC_SPIRITS { } __attribute__((packed)); DEFINE_PACKET_HEADER(ZC_SPIRITS, 0x01d0) +struct PACKET_ZC_SPIRITS2 { + int16 PacketType; + uint32 AID; + int16 num; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_SPIRITS2, 0x01e1) + +#if PACKETVER_MAIN_NUM >= 20200414 || PACKETVER_RE_NUM >= 20200723 || PACKETVER_ZERO_NUM >= 20200506 +struct PACKET_ZC_SOULENERGY { + int16 PacketType; + uint32 AID; + uint16 num; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_SOULENERGY, 0x0b73) +#endif + struct PACKET_ZC_SAY_DIALOG { int16 PacketType; int16 PacketLength; diff --git a/src/map/pc.c b/src/map/pc.c index f0f51c62a..e2fd8d871 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -203,7 +203,7 @@ static int pc_spiritball_timer(int tid, int64 tick, int id, intptr_t data) memmove(sd->spirit_timer+i, sd->spirit_timer+i+1, (sd->spiritball-i)*sizeof(int)); sd->spirit_timer[sd->spiritball] = INVALID_TIMER; - clif->spiritball(&sd->bl, BALL_TYPE_SPIRIT, AREA); + clif->spiritballs(&sd->bl, sd->spiritball, AREA); return 0; } @@ -268,7 +268,7 @@ static int pc_addspiritball_sub(struct map_session_data *sd) if ((sd->job & MAPID_THIRDMASK) == MAPID_ROYAL_GUARD) clif->millenniumshield(&sd->bl,sd->spiritball); else - clif->spiritball(&sd->bl, BALL_TYPE_SPIRIT, AREA); + clif->spiritballs(&sd->bl, sd->spiritball, AREA); return 0; } @@ -314,7 +314,7 @@ static int pc_delspiritball_sub(struct map_session_data *sd) if ((sd->job & MAPID_THIRDMASK) == MAPID_ROYAL_GUARD) clif->millenniumshield(&sd->bl,sd->spiritball); else - clif->spiritball(&sd->bl, BALL_TYPE_SPIRIT, AREA); + clif->spiritballs(&sd->bl, sd->spiritball, AREA); return 0; } @@ -340,7 +340,7 @@ static void pc_addsoulball(struct map_session_data *sd, int max) sd->soulball = cap_value(sd->soulball + 1, 0, max); sc_start(&sd->bl, &sd->bl, SC_SOULENERGY, 100, sd->soulball, skill->get_time2(SP_SOULCOLLECT, 1), 0); - clif->spiritball(&sd->bl, BALL_TYPE_SOUL, AREA); + clif->soulballs(&sd->bl, sd->soulball, AREA); } /** @@ -370,7 +370,7 @@ static void pc_delsoulball(struct map_session_data *sd, int count, bool type) } if (type == 0) - clif->spiritball(&sd->bl, BALL_TYPE_SOUL, AREA); + clif->soulballs(&sd->bl, sd->soulball, AREA); } static int pc_check_banding(struct block_list *bl, va_list ap) diff --git a/src/map/pc.h b/src/map/pc.h index 9ca106297..04a369524 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -791,10 +791,13 @@ END_ZEROED_BLOCK; #define pc_leftside_matk(sd) (status->base_matk(&(sd)->bl, status->get_status_data(&(sd)->bl), (sd)->status.base_level)) #define pc_rightside_matk(sd) ((sd)->battle_status.rhw.matk+(sd)->battle_status.lhw.matk+(sd)->bonus.ematk) #else - #define pc_leftside_atk(sd) ((sd)->battle_status.batk + (sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk) + #define pc_leftside_atk(sd) (\ + (((sd)->battle_status.batk + (sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk)\ + * (sd)->battle_status.atk_percent) / 100\ + ) #define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2) #define pc_leftside_def(sd) ((sd)->battle_status.def) - #define pc_rightside_def(sd) ((sd)->battle_status.def2) + #define pc_rightside_def(sd) (((sd)->battle_status.def2 * (sd)->battle_status.def_percent) / 100) #define pc_leftside_mdef(sd) ((sd)->battle_status.mdef) #define pc_rightside_mdef(sd) ( (sd)->battle_status.mdef2 - ((sd)->battle_status.vit>>1) ) #define pc_leftside_matk(sd) (\ diff --git a/src/map/script.c b/src/map/script.c index 409364415..9f04bf934 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -9133,6 +9133,74 @@ static BUILDIN(grouprandomitem) return true; } +/*========================================== + * getitemgroupitems , ; + *------------------------------------------*/ +static BUILDIN(getitemgroupitems) +{ + struct script_data* data = script_getdata(st, 2); + + if (!data_isreference(data)) { + ShowError("buildin_getitemgroupitems: not a variable\n"); + script->reportdata(data); + script_pushnil(st); + st->state = END; + return false;// not a variable + } + + int32 idata = reference_getindex(data); + int32 dataid = reference_getid(data); + const char *data_name = reference_getname(data); + + if (not_server_variable(*data_name)) { + if (script->rid2sd(st) == NULL) { + // no player attached + script_pushint(st, 0); + return false; + } + } + + if (is_string_variable(data_name)) { + // string array + ShowError("buildin_getitemgroupitems: not an integer array reference\n"); + script->reportdata(data); + st->state = END; + return false; + } + + int nameid = script_getnum(st, 3); + struct item_data *item = itemdb->exists(nameid); + if (item == NULL) { + ShowError("buildin_getitemgroupitems: invalid item %d\n", nameid); + script_pushint(st, 0); + return false; + } + + const struct item_group *group = itemdb->search_group(item->nameid); + if (group == NULL) { + ShowWarning("buildin_getitemgroupitems: item group not found\n"); + script_pushint(st, 0); + return false; + } + + int count = 0; + for (int i = 0; i < group->qty; i++) { + int id = group->nameid[i]; + int j = 0; + ARR_FIND(0, i, j, group->nameid[i] == group->nameid[j]); + if (i != j) { + // Already encountered - skip duplicates + continue; + } + const void *v = (const void *)h64BPTRSIZE(id); + script->set_reg(st, NULL, reference_uid(dataid, idata + count), data_name, v, reference_getref(data)); + count++; + } + + script_pushint(st, count); + return true; +} + /*========================================== * makeitem , , "", , {, }}; *------------------------------------------*/ @@ -28652,6 +28720,7 @@ static void script_parse_builtin(void) BUILDIN_DEF(getitem2,"viiiiiiii?"), BUILDIN_DEF(getnameditem,"vv"), BUILDIN_DEF2(grouprandomitem,"groupranditem","i"), + BUILDIN_DEF(getitemgroupitems, "ri"), BUILDIN_DEF(makeitem,"visii?"), BUILDIN_DEF(makeitem2,"viiiiiiii?????"), BUILDIN_DEF(delitem,"vi?"), diff --git a/src/map/skill.c b/src/map/skill.c index fc11e0bcf..c0bd2612a 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -124,16 +124,23 @@ static int skill_name2id(const char *name) return strdb_iget(skill->name2id_db, name); } -/// Maps skill ids to skill db offsets. -/// Returns the skill's array index, or 0 (Unknown Skill). -static int skill_get_index(int skill_id) +/** + * Maps skill ids to skill db offsets. + * + * @param skill_id skill to search + * @param report_errors if the skill is not found, report an error to help solving it? + * @return Returns the skill's array index, or 0 (Unknown Skill). + */ +static int skill_get_index_sub(int skill_id, bool report_errors) { int length = ARRAYLENGTH(skill_idx_ranges); if (skill_id < skill_idx_ranges[0].start || skill_id > skill_idx_ranges[length - 1].end) { - ShowWarning("skill_get_index: skill id '%d' is not being handled!\n", skill_id); - Assert_report(0); + if (report_errors) { + ShowWarning("skill_get_index: skill id '%d' is not being handled!\n", skill_id); + Assert_report(0); + } return 0; } @@ -152,19 +159,35 @@ static int skill_get_index(int skill_id) } if (!found) { - ShowWarning("skill_get_index: skill id '%d' (idx: %d) is not handled as it lies outside the defined ranges!\n", skill_id, skill_idx); - Assert_report(0); + if (report_errors) { + ShowWarning("skill_get_index: skill id '%d' (idx: %d) is not handled as it lies outside the defined ranges!\n", skill_id, skill_idx); + Assert_report(0); + } return 0; } if (skill_idx >= MAX_SKILL_DB) { - ShowWarning("skill_get_index: skill id '%d'(idx: %d) is not being handled as it exceeds MAX_SKILL_DB!\n", skill_id, skill_idx); - Assert_report(0); + if (report_errors) { + ShowWarning("skill_get_index: skill id '%d'(idx: %d) is not being handled as it exceeds MAX_SKILL_DB!\n", skill_id, skill_idx); + Assert_report(0); + } return 0; } return skill_idx; } +/** + * Maps skill ids to skill db offsets. + * If something goes wrong, errors will be reported to console. + * + * @param skill_id skill to search not found, report an error to help solving it? + * @return Returns the skill's array index, or 0 (Unknown Skill). + */ +static int skill_get_index(int skill_id) +{ + return skill->get_index_sub(skill_id, true); +} + static const char *skill_get_name(int skill_id) { return skill->dbs->db[skill->get_index(skill_id)].name; @@ -5094,7 +5117,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl } clif->slide(src, src->x, src->y); clif->fixpos(src); - clif->spiritball(src, BALL_TYPE_SPIRIT, AREA); + clif->spiritballs(src, status->get_spiritballs(src), AREA); } } break; @@ -6638,7 +6661,7 @@ static int skill_castend_id(int tid, int64 tick, int id, intptr_t data) if (unit->move_pos(src, src->x + x, src->y + y, 1, true) == 0) { //Display movement + animation. clif->slide(src, src->x, src->y); - clif->spiritball(src, BALL_TYPE_SPIRIT, AREA); + clif->spiritballs(src, status->get_spiritballs(src), AREA); } // "Skill Failed" message was already shown when checking that target is invalid //clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0, 0); @@ -9363,7 +9386,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * status_percent_damage(src, bl, 0, 100, false); break; case 1: // matk halved - sc_start(src, bl, SC_INCMATKRATE, 100, -50, skill->get_time2(skill_id, skill_lv), skill_id); + sc_start(src, bl, SC_TAROTCARD_MATK_PERC, 100, -50, skill->get_time2(skill_id, skill_lv), skill_id); break; case 2: // all buffs removed status->change_clear_buffs(bl,1); @@ -9379,7 +9402,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * } break; case 4: // atk halved - sc_start(src, bl, SC_INCATKRATE, 100, -50, skill->get_time2(skill_id, skill_lv), skill_id); + sc_start(src, bl, SC_TAROTCARD_ATK_PERC, 100, -50, skill->get_time2(skill_id, skill_lv), skill_id); break; case 5: // 2000HP heal, random teleported status->heal(src, 2000, 0, STATUS_HEAL_DEFAULT); @@ -9409,8 +9432,8 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * case 10: // 6666 damage, atk matk halved, cursed status_fix_damage(src, bl, 6666, 0); clif->damage(src,bl,0,0,6666,0,BDT_NORMAL,0); - sc_start(src, bl, SC_INCATKRATE, 100, -50, skill->get_time2(skill_id, skill_lv), skill_id); - sc_start(src, bl, SC_INCMATKRATE, 100, -50, skill->get_time2(skill_id, skill_lv), skill_id); + sc_start(src, bl, SC_TAROTCARD_ATK_PERC, 100, -50, skill->get_time2(skill_id, skill_lv), skill_id); + sc_start(src, bl, SC_TAROTCARD_MATK_PERC, 100, -50, skill->get_time2(skill_id, skill_lv), skill_id); sc_start(src, bl, SC_CURSE, skill_lv, 100, skill->get_time2(skill_id, skill_lv), skill_id); break; case 11: // 4444 damage @@ -9421,11 +9444,11 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * sc_start(src, bl, SC_STUN, 100, skill_lv, 5000, skill_id); break; case 13: // atk,matk,hit,flee,def reduced - sc_start(src, bl, SC_INCATKRATE, 100, -20, skill->get_time2(skill_id, skill_lv), skill_id); - sc_start(src, bl, SC_INCMATKRATE, 100, -20, skill->get_time2(skill_id, skill_lv), skill_id); + sc_start(src, bl, SC_TAROTCARD_ATK_PERC, 100, -20, skill->get_time2(skill_id, skill_lv), skill_id); + sc_start(src, bl, SC_TAROTCARD_MATK_PERC, 100, -20, skill->get_time2(skill_id, skill_lv), skill_id); sc_start(src, bl, SC_INCHITRATE, 100, -20, skill->get_time2(skill_id, skill_lv), skill_id); sc_start(src, bl, SC_INCFLEERATE, 100, -20, skill->get_time2(skill_id, skill_lv), skill_id); - sc_start(src, bl, SC_INCDEFRATE, 100, -20, skill->get_time2(skill_id, skill_lv), skill_id); + sc_start(src, bl, SC_TAROTCARD_DEF_PERC, 100, -20, skill->get_time2(skill_id, skill_lv), skill_id); sc_start(src, bl, type, 100, skill_lv, skill->get_time2(skill_id, skill_lv), skill_id); break; default: @@ -10476,17 +10499,19 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * } break; case SC_AUTOSHADOWSPELL: - if (sd) { - int idx1 = sd->reproduceskill_id != 0 ? skill->get_index(sd->reproduceskill_id) : 0; - int idx2 = sd->cloneskill_id != 0 ? skill->get_index(sd->cloneskill_id) : 0; + if (sd != NULL) { + int reproduceIdx = sd->reproduceskill_id > 0 ? skill->get_index(sd->reproduceskill_id) : -1; + int cloneIdx = sd->cloneskill_id > 0 ? skill->get_index(sd->cloneskill_id) : -1; - if ((idx1 != 0 && sd->status.skill[idx1].id) || (idx2 != 0 && sd->status.skill[idx2].id)) { + bool hasReproduceSkill = reproduceIdx >= 0 && sd->status.skill[reproduceIdx].id != 0; + bool hasCloneSkill = cloneIdx >= 0 && sd->status.skill[cloneIdx].id != 0; + if (hasReproduceSkill || hasCloneSkill) { sc_start(src, src, SC_STOP, 100, skill_lv, INFINITE_DURATION, skill_id); // The skill_lv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax] clif->autoshadowspell_list(sd); - clif->skill_nodamage(src,bl,skill_id,1,1); - } - else + clif->skill_nodamage(src, bl, skill_id, 1, 1); + } else { clif->skill_fail(sd, skill_id, USESKILL_FAIL_IMITATION_SKILL_NONE, 0, 0); + } } break; @@ -14347,7 +14372,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b if (tsd) clif->gospel_info(tsd, 0x1e); break; case 11: // ATK +100% - sc_start(ss, bl, SC_INCATKRATE, 100, 100, time, skill_id); + sc_start(ss, bl, SC_GOSPEL_ATK_PERC, 100, 100, time, skill_id); if (tsd) clif->gospel_info(tsd, 0x1f); break; case 12: // HIT/Flee +50 @@ -14376,13 +14401,16 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b sc_start(ss, bl, SC_POISON, 100, 1, time, skill_id); break; case 4: // Level 10 Provoke + // TODO: [Aegis] while this does apply the status effect of provoke, it manually sets the atk / def percentage changes... + // this means you could be affected by gospel provoke as well as normal provoke, since provoke also manually applies the atk / def changes in Aegis. + // We're not doing that here. sc_start(ss, bl, SC_PROVOKE, 100, 10, time, skill_id); break; case 5: // DEF -100% sc_start(ss, bl, SC_INCDEFRATE, 100, -100, time, skill_id); break; case 6: // ATK -100% - sc_start(ss, bl, SC_INCATKRATE, 100, -100, time, skill_id); + sc_start(ss, bl, SC_GOSPEL_ATK_PERC, 100, -100, time, skill_id); break; case 7: // Flee -100% sc_start(ss, bl, SC_INCFLEERATE, 100, -100, time, skill_id); @@ -25230,6 +25258,7 @@ void skill_defaults(void) skill->unit_timer_tid = 0; /* accessors */ skill->get_index = skill_get_index; + skill->get_index_sub = skill_get_index_sub; skill->get_type = skill_get_type; skill->get_hit = skill_get_hit; skill->get_inf = skill_get_inf; diff --git a/src/map/skill.h b/src/map/skill.h index d09e24115..dfb1c4e35 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -143,7 +143,7 @@ enum e_skill_inf2 { INF2_HIDDEN_TRAP = 0x00080000, ///< Traps that are hidden (based on trap_visiblity battle conf) INF2_IS_COMBO_SKILL = 0x00100000, ///< Sets whether a skill can be used in combos or not INF2_NO_STASIS = 0x00200000, - INF2_NO_KAGEHUMI = 0x00400000, + INF2_NO_KAGEHUMI = 0x00400000, INF2_RANGE_VULTURE = 0x00800000, ///< Range is modified by AC_VULTURE INF2_RANGE_SNAKEEYE = 0x01000000, ///< Range is modified by GS_SNAKEEYE INF2_RANGE_SHADOWJUMP = 0x02000000, ///< Range is modified by NJ_SHADOWJUMP @@ -2068,6 +2068,7 @@ struct skill_interface { int unit_timer_tid; /* accesssors */ int (*get_index) (int skill_id); + int (*get_index_sub) (int skill_id, bool report_errors); int (*get_type) (int skill_id, int skill_lv); int (*get_hit) (int skill_id, int skill_lv); int (*get_inf) (int skill_id); diff --git a/src/map/status.c b/src/map/status.c index be8f0dc93..26aae93ec 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -87,9 +87,9 @@ static int status_sc2skill(sc_type sc) /** * Returns the status calculation flag associated with a given status change. * @param sc The status to look up - * @return The scb_flag registered for this status (see enum scb_flag) + * @return The scb_flag registered for this status (see e_scb_flag) */ -static unsigned int status_sc2scb_flag(sc_type sc) +static e_scb_flag status_sc2scb_flag(sc_type sc) { if( sc < 0 || sc >= SC_MAX ) { ShowError("status_sc2scb_flag: Unsupported status change id %d\n", sc); @@ -2991,8 +2991,8 @@ static void status_calc_regen_rate(struct block_list *bl, struct regen_data *reg #define status_get_homluk(st, hd) ((st)->luk + (hd)->homunculus.luk_value) /// Recalculates parts of an object's battle status according to the specified flags. -/// @param flag bitfield of values from enum scb_flag -static void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) +/// @param flag bitfield of values from e_scb_flag +static void status_calc_bl_main(struct block_list *bl, e_scb_flag flag) { const struct status_data *bst = status->get_base_status(bl); struct status_data *st = status->get_status_data(bl); @@ -3083,6 +3083,28 @@ static void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag ; } + if ((flag & SCB_ATK_PERC) != 0) { + int prev_atk_percent = st->atk_percent; + st->atk_percent = status->calc_atk_percent(bl, sc); + if (prev_atk_percent != st->atk_percent) + clif->updatestatus(sd, SP_ATK1); + } + + if ((flag & SCB_MATK_PERC) != 0) + st->matk_percent = status->calc_matk_percent(bl, sc); + + if ((flag & SCB_DEF_PERC) != 0) { + int prev_def_percent = st->def_percent; + st->def_percent = status->calc_def_percent(bl, sc); + if (prev_def_percent != st->def_percent) + clif->updatestatus(sd, SP_DEF2); + } + + if ((flag & SCB_MDEF_PERC) != 0) { + st->mdef_percent = status->calc_mdef_percent(bl, sc); + flag |= SCB_MDEF; + } + if(flag&SCB_BATK && bst->batk) { st->batk = status->base_atk(bl,st); temp = bst->batk - status->base_atk(bl,bst); @@ -3392,9 +3414,9 @@ static void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag /// Recalculates parts of an object's base status and battle status according to the specified flags. /// Also sends updates to the client wherever applicable. -/// @param flag bitfield of values from enum scb_flag +/// @param flag bitfield of values from e_scb_flag /// @param first if true, will cause status_calc_* functions to run their base status initialization code -static void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt) +static void status_calc_bl_(struct block_list *bl, e_scb_flag flag, enum e_status_calc_opt opt) { struct status_data bst; // previous battle status struct status_data *st; // pointer to current battle status @@ -3475,7 +3497,7 @@ static void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_st if(bst.batk != st->batk #ifndef RENEWAL - || bst.rhw.atk != st->rhw.atk || bst.lhw.atk != st->lhw.atk + || bst.rhw.atk != st->rhw.atk || bst.lhw.atk != st->lhw.atk || bst.atk_percent != st->atk_percent #endif ) clif->updatestatus(sd,SP_ATK1); @@ -4296,6 +4318,160 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang return (unsigned short)cap_value(luk, 0, USHRT_MAX); } +/** + * Adds up the granted ATK percent bonuses. + * + * @param bl the object who's ATK percent we're calculating. + * @param sc the status change data of our object. + * @return the calculated ATK percent. + */ +static int status_calc_atk_percent(struct block_list *bl, struct status_change *sc) +{ + nullpo_ret(bl); + int atk_percent = 100; // [Aegis] by default we have 100% of our atk. + + if (sc == NULL || sc->count == 0) + return cap_value(atk_percent, 0, USHRT_MAX); + + // Add/Subtract additively according to status changes. + if (sc->data[SC_TAROTCARD_ATK_PERC] != NULL) + atk_percent += sc->data[SC_TAROTCARD_ATK_PERC]->val1; + + if (sc->data[SC_GOSPEL_ATK_PERC] != NULL) + atk_percent += sc->data[SC_GOSPEL_ATK_PERC]->val1; + + if (sc->data[SC_PROVOKE] != NULL) + atk_percent += sc->data[SC_PROVOKE]->val3; + + if (sc->data[SC_LKCONCENTRATION] != NULL) + atk_percent += sc->data[SC_LKCONCENTRATION]->val2; + + if (sc->data[SC_HAMI_BLOODLUST] != NULL) + atk_percent += sc->data[SC_HAMI_BLOODLUST]->val2; + + if (sc->data[SC_JOINTBEAT] != NULL && (sc->data[SC_JOINTBEAT]->val2 & BREAK_WAIST) != 0) + atk_percent -= 25; + + if (sc->data[SC_SKE] != NULL) + atk_percent += 300; + + if (sc->data[SC_HLIF_FLEET] != NULL) + atk_percent += sc->data[SC_HLIF_FLEET]->val3; + + if (sc->data[SC_CURSE] != NULL) + atk_percent -= 25; + + if (sc->data[SC_INCATKRATE] != NULL) // should be used by NPC_POWERUP only + atk_percent += sc->data[SC_INCATKRATE]->val1; + + if (sc->data[SC_NOEQUIPWEAPON] != NULL && bl->type != BL_PC) + atk_percent -= sc->data[SC_NOEQUIPWEAPON]->val2; + + return cap_value(atk_percent, 0, USHRT_MAX); +} + +/** + * Adds up the granted MATK percent bonuses. + * + * @param bl the object who's MATK percent we're calculating. + * @param sc the status change data of our object. + * @return the calculated MATK percent. + */ +static int status_calc_matk_percent(struct block_list *bl, struct status_change *sc) +{ + nullpo_ret(bl); + int matk_percent = 100; // [Aegis] by default we have 100% of our matk. + + if (sc == NULL || sc->count == 0) + return cap_value(matk_percent, 0, USHRT_MAX); + + // Add/Subtract additively according to status changes. + if (sc->data[SC_TAROTCARD_MATK_PERC] != NULL) + matk_percent += sc->data[SC_TAROTCARD_MATK_PERC]->val1; + + if (sc->data[SC_MINDBREAKER] != NULL) + matk_percent += sc->data[SC_MINDBREAKER]->val2; + + return cap_value(matk_percent, 0, USHRT_MAX); +} + +/** + * Adds up the granted DEF percent bonuses. + * + * @param bl the object who's DEF percent we're calculating. + * @param sc the status change data of our object. + * @return the calculated DEF percent. + */ +static int status_calc_def_percent(struct block_list *bl, struct status_change *sc) +{ + nullpo_ret(bl); + int def_percent = 100; // [Aegis] by default we have 100% of our def. + + if (sc == NULL || sc->count == 0) + return cap_value(def_percent, 0, USHRT_MAX); + + // Add/Subtract additively according to status changes. + if (sc->data[SC_TAROTCARD_DEF_PERC] != NULL) + def_percent += sc->data[SC_TAROTCARD_DEF_PERC]->val1; + + if (sc->data[SC_PROVOKE] != NULL) + def_percent -= sc->data[SC_PROVOKE]->val4; // passed as absolute value. + + if (sc->data[SC_LKCONCENTRATION] != NULL) + def_percent -= sc->data[SC_LKCONCENTRATION]->val4; // passed as absolute value. + + if (sc->data[SC_JOINTBEAT]) { + // [Aegis] General (m)atk/m(def) percentage buffs/debuffs take the stronger one, as in max(abs(fst_perc), abs(snd_perc)). + // This is done individually for def, mdef, atk, def. And compared is only with same-skill originating changes. + if ((sc->data[SC_JOINTBEAT]->val2 & BREAK_SHOULDER) != 0) + def_percent -= 50; + else if ((sc->data[SC_JOINTBEAT]->val2 & BREAK_WAIST) != 0) + def_percent -= 25; + } + + if (sc->data[SC_SKE] != NULL) + def_percent -= 50; + + if (sc->data[SC_NOEQUIPSHIELD] != NULL) + def_percent -= sc->data[SC_NOEQUIPSHIELD]->val2; + + if (sc->data[SC_FLING] != NULL) + def_percent -= sc->data[SC_FLING]->val2; + +#ifndef RENEWAL + if (sc->data[SC_ANGELUS] != NULL) + def_percent += sc->data[SC_ANGELUS]->val2; +#endif + + // [Aegis] These can't stack. + if (sc->data[SC_POISON] != NULL || sc->data[SC_DPOISON] != NULL) + def_percent -= 25; + + return cap_value(def_percent, 0, USHRT_MAX); +} + +/** + * Adds up the granted MDEF percent bonuses. + * + * @param bl the object who's MDEF percent we're calculating. + * @param sc the status change data of our object. + * @return the calculated MDEF percent. + */ +static int status_calc_mdef_percent(struct block_list *bl, struct status_change *sc) +{ + nullpo_ret(bl); + int mdef_percent = 100; // [Aegis] by default we have 100% of our mdef. + + if (sc == NULL || sc->count == 0) + return cap_value(mdef_percent, 0, USHRT_MAX); + + // Add/Subtract additively according to status changes. + if (sc->data[SC_MINDBREAKER] != NULL) + mdef_percent -= sc->data[SC_MINDBREAKER]->val3; + + return cap_value(mdef_percent, 0, USHRT_MAX); +} + static int status_calc_batk(struct block_list *bl, struct status_change *sc, int batk, bool viewable) { nullpo_ret(bl); @@ -4342,30 +4518,12 @@ static int status_calc_batk(struct block_list *bl, struct status_change *sc, int if (sc->data[SC_ANGRIFFS_MODUS]) batk += sc->data[SC_ANGRIFFS_MODUS]->val2; - if(sc->data[SC_INCATKRATE]) - batk += batk * sc->data[SC_INCATKRATE]->val1/100; - if(sc->data[SC_PROVOKE]) - batk += batk * sc->data[SC_PROVOKE]->val3/100; -#ifndef RENEWAL - if(sc->data[SC_LKCONCENTRATION]) - batk += batk * sc->data[SC_LKCONCENTRATION]->val2/100; -#endif - if(sc->data[SC_SKE]) - batk += batk * 3; - if(sc->data[SC_HAMI_BLOODLUST]) - batk += batk * sc->data[SC_HAMI_BLOODLUST]->val2/100; - if(sc->data[SC_JOINTBEAT] && sc->data[SC_JOINTBEAT]->val2&BREAK_WAIST) - batk -= batk * 25/100; - if(sc->data[SC_CURSE]) - batk -= batk * 25/100; if( sc->data[SC_ZANGETSU] ) batk += sc->data[SC_ZANGETSU]->val2; #if 0 //Curse shouldn't effect on this? <- Curse OR Bleeding?? if(sc->data[SC_BLOODING]) batk -= batk * 25/100; #endif // 0 - if(sc->data[SC_HLIF_FLEET]) - batk += batk * sc->data[SC_HLIF_FLEET]->val3/100; if(sc->data[SC__ENERVATION]) batk -= batk * sc->data[SC__ENERVATION]->val2 / 100; if(sc->data[SC_SATURDAY_NIGHT_FEVER]) @@ -4454,21 +4612,7 @@ static int status_calc_watk(struct block_list *bl, struct status_change *sc, int watk += sc->data[SC_NIBELUNGEN]->val2; } } - if(sc->data[SC_LKCONCENTRATION]) - watk += watk * sc->data[SC_LKCONCENTRATION]->val2/100; #endif - if(sc->data[SC_INCATKRATE]) - watk += watk * sc->data[SC_INCATKRATE]->val1/100; - if(sc->data[SC_PROVOKE]) - watk += watk * sc->data[SC_PROVOKE]->val3/100; - if(sc->data[SC_SKE]) - watk += watk * 3; - if(sc->data[SC_HLIF_FLEET]) - watk += watk * sc->data[SC_HLIF_FLEET]->val3/100; - if(sc->data[SC_CURSE]) - watk -= watk * 25/100; - if(sc->data[SC_NOEQUIPWEAPON] && bl->type != BL_PC) - watk -= watk * sc->data[SC_NOEQUIPWEAPON]->val2/100; if(sc->data[SC__ENERVATION]) watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; if(sc->data[SC_RUSH_WINDMILL]) @@ -4539,8 +4683,6 @@ static int status_calc_matk(struct block_list *bl, struct status_change *sc, int if (!viewable) { /* some statuses that are hidden in the status window */ - if (sc->data[SC_MINDBREAKER]) - matk += matk * sc->data[SC_MINDBREAKER]->val2 / 100; if (sc->data[SC_POPECOOKIE] != NULL) matk += matk * sc->data[SC_POPECOOKIE]->val2 / 100; if (sc->data[SC_VITALIZE_POTION] != NULL) @@ -4573,7 +4715,7 @@ static int status_calc_matk(struct block_list *bl, struct status_change *sc, int matk += sc->data[SC_ZANGETSU]->val3; if (sc->data[SC_MAGICPOWER] && sc->data[SC_MAGICPOWER]->val4) matk += matk * sc->data[SC_MAGICPOWER]->val3 / 100; - if (sc->data[SC_INCMATKRATE]) + if (sc->data[SC_INCMATKRATE]) // Apparently nothing in Hercules uses this. Why does this exist? matk += matk * sc->data[SC_INCMATKRATE]->val1 / 100; if (sc->data[SC_MOONLIT_SERENADE]) matk += matk * sc->data[SC_MOONLIT_SERENADE]->val2 / 100; @@ -4893,16 +5035,6 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc, def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1; if (sc->data[SC_CRUCIS]) def -= def * sc->data[SC_CRUCIS]->val2/100; - if (sc->data[SC_LKCONCENTRATION]) - def -= def * sc->data[SC_LKCONCENTRATION]->val4/100; - if (sc->data[SC_SKE]) - def >>=1; - if (sc->data[SC_PROVOKE] && bl->type != BL_PC) // Provoke doesn't alter player defense-> - def -= def * sc->data[SC_PROVOKE]->val4/100; - if (sc->data[SC_NOEQUIPSHIELD]) - def -= def * sc->data[SC_NOEQUIPSHIELD]->val2/100; - if (sc->data[SC_FLING]) - def -= def * (sc->data[SC_FLING]->val2)/100; if (sc->data[SC_ANALYZE]) def -= def * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100; if (sc->data[SC_SATURDAY_NIGHT_FEVER]) @@ -4975,27 +5107,10 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change def2 += sc->data[SC_SUN_COMFORT]->val2; if (sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1) def2 += (5 + sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2); - if (sc->data[SC_ANGELUS]) #ifdef RENEWAL //in renewal only the VIT stat bonus is boosted by angelus + if (sc->data[SC_ANGELUS]) def2 += status_get_vit(bl) / 2 * sc->data[SC_ANGELUS]->val2/100; -#else - def2 += def2 * sc->data[SC_ANGELUS]->val2/100; - if (sc->data[SC_LKCONCENTRATION]) - def2 -= def2 * sc->data[SC_LKCONCENTRATION]->val4/100; #endif - if (sc->data[SC_POISON]) - def2 -= def2 * 25/100; - if (sc->data[SC_DPOISON]) - def2 -= def2 * 25/100; - if (sc->data[SC_SKE]) - def2 -= def2 * 50/100; - if (sc->data[SC_PROVOKE]) - def2 -= def2 * sc->data[SC_PROVOKE]->val4/100; - if (sc->data[SC_JOINTBEAT]) - def2 -= def2 * ((sc->data[SC_JOINTBEAT]->val2&BREAK_SHOULDER) ? 50 : 0) / 100 - + def2 * ((sc->data[SC_JOINTBEAT]->val2&BREAK_WAIST) ? 25 : 0) / 100; - if (sc->data[SC_FLING]) - def2 -= def2 * (sc->data[SC_FLING]->val3)/100; if (sc->data[SC_ANALYZE]) def2 -= def2 * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100; if (sc->data[SC_ECHOSONG]) @@ -5008,6 +5123,7 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change def2 -= def2 * sc->data[SC_NEEDLE_OF_PARALYZE]->val2 / 100; if (sc->data[SC_UNLIMIT]) return 1; + #ifdef RENEWAL return (short)cap_value(def2,SHRT_MIN,SHRT_MAX); #else @@ -5040,7 +5156,7 @@ static defType status_calc_mdef(struct block_list *bl, struct status_change *sc, return 90; #endif - if(sc->data[SC_STONESKIN]) + if(sc->data[SC_STONESKIN]) // [Aegis] Technically this uses MDEFPercent/DEFPercent + sth else mdef += sc->data[SC_STONESKIN]->val3; if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3) mdef += 50; @@ -5087,8 +5203,6 @@ static signed short status_calc_mdef2(struct block_list *bl, struct status_chang /* some statuses that are hidden in the status window */ if(sc->data[SC_MDEFSET]) return sc->data[SC_MDEFSET]->val1; - if(sc->data[SC_MINDBREAKER]) - mdef2 -= mdef2 * sc->data[SC_MINDBREAKER]->val3/100; #ifdef RENEWAL if (sc->data[SC_ASSUMPTIO]) mdef2 <<= 1; @@ -5106,6 +5220,11 @@ static signed short status_calc_mdef2(struct block_list *bl, struct status_chang mdef2 -= mdef2 * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100; if (sc->data[SC_UNLIMIT]) return 1; + + struct status_data *sstatus = status->get_status_data(bl); + if (sstatus != NULL) // may be NULL on first call + mdef2 = (mdef2 * sstatus->mdef_percent) / 100; + #ifdef RENEWAL return (short)cap_value(mdef2,SHRT_MIN,SHRT_MAX); #else @@ -5964,6 +6083,33 @@ static int status_get_lv(const struct block_list *bl) return 1; } +/** + * Get the number of spirit balls of bl + * @param bl unit to get spirit balls from + * @returns number of spirit balls. block_list that doesn't hold spirit balls always returns 0. + */ +static int status_get_spiritballs(const struct block_list *bl) +{ + nullpo_ret(bl); + + switch (bl->type) { + case BL_PC: return BL_UCCAST(BL_PC, bl)->spiritball; + case BL_HOM: return BL_UCCAST(BL_HOM, bl)->homunculus.spiritball; + case BL_MOB: + case BL_PET: + case BL_MER: + case BL_ELEM: + case BL_NPC: + case BL_NUL: + case BL_CHAT: + case BL_SKILL: + case BL_ITEM: + case BL_ALL: + break; + } + return 0; +} + static struct regen_data *status_get_regen_data(struct block_list *bl) { nullpo_retr(NULL, bl); @@ -6974,7 +7120,8 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl struct status_change_entry* sce; struct status_data *st; struct view_data *vd; - int opt_flag, calc_flag, undead_flag, val_flag = 0, tick_time = 0; + int opt_flag, undead_flag, val_flag = 0, tick_time = 0; + e_scb_flag calc_flag = SCB_NONE; nullpo_ret(bl); sc = status->get_sc(bl); @@ -7420,6 +7567,7 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl case SC_RESIST_PROPERTY_WIND: case SC_FLASHKICK: case SC_SOULUNITY: + case SC__AUTOSHADOWSPELL: // otherwise you can't change your shadow spell to a lower skill_id break; case SC_GOSPEL: //Must not override a casting gospel char. @@ -7462,6 +7610,14 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl if( sce->val4 && !val4 )//you cannot override master guild aura return 0; break; + case SC_TAROTCARD_ATK_PERC: + case SC_TAROTCARD_MATK_PERC: + case SC_TAROTCARD_DEF_PERC: + case SC_GOSPEL_ATK_PERC: + // [Aegis] Don't override stronger (m)atk & m(def) percentage based buffs. + if (abs(val1) < abs(sce->val1)) + return 1; + break; case SC_JOINTBEAT: val2 |= sce->val2; // stackable ailments FALLTHROUGH @@ -7613,11 +7769,11 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl } break; case SC_NOEQUIPWEAPON: - if (!sd) //Watk reduction + if (sd == NULL) // ATK% reduction val2 = 25; break; case SC_NOEQUIPSHIELD: - if (!sd) //Def reduction + if (sd == NULL) // DEF% reduction val2 = 15; break; case SC_NOEQUIPARMOR: @@ -8163,13 +8319,13 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl total_tick += total_tick / 10; break; case SC_LKCONCENTRATION: - val2 = 5*val1; //Batk/Watk Increase + val2 = 5 * val1; // ATK% Increase val3 = 10*val1; //Hit Increase - val4 = 5*val1; //Def reduction + val4 = 5 * val1; // Def% reduction sc_start(src, bl, SC_ENDURE, 100, 1, total_tick, skill_id); // Endure effect break; case SC_ANGELUS: - val2 = 5*val1; //def increase + val2 = 5*val1; // DEF% increase break; case SC_IMPOSITIO: val2 = 5*val1; //watk increase @@ -8205,11 +8361,7 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl break; case SC_FLING: - if (bl->type == BL_PC) - val2 = 0; //No armor reduction to players. - else - val2 = 5*val1; //Def reduction - val3 = 5*val1; //Def2 reduction + val2 = 5*val1; // DEF% reduction break; case SC_PROVOKE: //val2 signals autoprovoke. @@ -8229,11 +8381,11 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl break; case SC_HLIF_FLEET: val2 = 30*val1; //Aspd change - val3 = 5+5*val1; //bAtk/wAtk rate change + val3 = 5+5*val1; // ATK% change break; case SC_MINDBREAKER: - val2 = 20*val1; //matk increase. - val3 = 12*val1; //mdef2 reduction. + val2 = 20 * val1; // MATK% increase. + val3 = 12 * val1; // MDEF% reduction. break; case SC_SKA: val2 = total_tick/1000; @@ -9668,7 +9820,7 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl return 1; } -static bool status_change_start_unknown_sc(struct block_list *src, struct block_list *bl, enum sc_type type, int calc_flag, int rate, int val1, int val2, int val3, int val4, int total_tick, int flag) +static bool status_change_start_unknown_sc(struct block_list *src, struct block_list *bl, enum sc_type type, e_scb_flag calc_flag, int rate, int val1, int val2, int val3, int val4, int total_tick, int flag) { Assert_retr(false, type >= SC_NONE && type < SC_MAX); if (calc_flag == SCB_NONE && status->dbs->SkillChangeTable[type] == 0 && status->get_sc_icon(type) == SI_BLANK) { @@ -10695,8 +10847,9 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid) struct status_change_entry *sce; struct status_data *st; struct view_data *vd; - int opt_flag=0, calc_flag; + int opt_flag=0; bool invisible = false; + e_scb_flag calc_flag = SCB_NONE; nullpo_ret(bl); @@ -13998,7 +14151,7 @@ static bool status_read_scdb_libconfig_sub_calcflag(struct config_setting_t *it, struct { const char *name; - enum scb_flag value; + e_scb_flag value; } flags[] = { { "None", SCB_NONE }, { "Base", SCB_BASE }, @@ -14032,6 +14185,10 @@ static bool status_read_scdb_libconfig_sub_calcflag(struct config_setting_t *it, { "Range", SCB_RANGE }, { "Regen", SCB_REGEN }, { "Dye", SCB_DYE }, + { "AtkPerc", SCB_ATK_PERC }, + { "DefPerc", SCB_DEF_PERC }, + { "MatkPerc", SCB_MATK_PERC }, + { "MdefPerc", SCB_MDEF_PERC }, { "All", SCB_ALL }, }; @@ -14225,7 +14382,7 @@ static bool status_read_unit_params_db_sub(const char *name, struct config_setti safestrncpy(entry.name, name, sizeof(entry.name)); if (!status->read_unit_params_db_maxhp(&entry, inherited, group, source)) { - status->unit_params_destroy(&entry); + status->unit_params_destroy_entry(&entry); return false; } @@ -14280,7 +14437,7 @@ static bool status_read_unit_params_db_sub(const char *name, struct config_setti } if (!status->read_unit_params_db_additional(&entry, inherited, group, source)) { - status->unit_params_destroy(&entry); + status->unit_params_destroy_entry(&entry); return false; } @@ -14295,8 +14452,6 @@ static bool status_read_unit_params_db_sub(const char *name, struct config_setti */ static void status_read_unit_params_db(void) { - VECTOR_INIT(status->unit_params_groups); - char config_filename[256]; libconfig->format_db_path(DBPATH"unit_parameters_db.conf", config_filename, sizeof(config_filename)); @@ -14325,7 +14480,7 @@ static void status_read_unit_params_db(void) * Perform the required cleanup inside a unit parameters db entry. * @param entry the entry to have its internal content cleared */ -static void status_unit_params_destroy(struct s_unit_params *entry) +static void status_unit_params_destroy_entry(struct s_unit_params *entry) { nullpo_retv(entry); @@ -14336,6 +14491,17 @@ static void status_unit_params_destroy(struct s_unit_params *entry) } } +/** + * Perform the required cleanup of the unit parameters db + */ +static void status_unit_params_clear_db(void) +{ + for (int i = 0; i < VECTOR_LENGTH(status->unit_params_groups); ++i) + status->unit_params_destroy_entry(&VECTOR_INDEX(status->unit_params_groups, i)); + + VECTOR_CLEAR(status->unit_params_groups); +} + /** * Read status db * job1.txt @@ -14357,6 +14523,8 @@ static int status_readdb(void) memset(status->dbs->SP_table, 0, sizeof(status->dbs->SP_table)); // reset job_db2.txt data memset(status->dbs->job_bonus,0,sizeof(status->dbs->job_bonus)); // Job-specific stats bonus + // resets unit_params_db.conf data + status->unit_params_clear_db(); } for ( i = 0; i < CLASS_COUNT; i++ ) { for ( j = 0; j < MAX_SINGLE_WEAPON_TYPE; j++ ) @@ -14392,6 +14560,8 @@ static int do_init_status(bool minimal) if (minimal) return 0; + VECTOR_INIT(status->unit_params_groups); + timer->add_func_list(status->change_timer,"status_change_timer"); timer->add_func_list(status->kaahi_heal_timer,"status_kaahi_heal_timer"); timer->add_func_list(status->natural_heal_timer,"status_natural_heal_timer"); @@ -14408,11 +14578,8 @@ static void do_final_status(void) { ers_destroy(status->data_ers); - status->unit_params_destroy(&status->dummy_unit_params); - for (int i = 0; i < VECTOR_LENGTH(status->unit_params_groups); ++i) - status->unit_params_destroy(&VECTOR_INDEX(status->unit_params_groups, i)); - - VECTOR_CLEAR(status->unit_params_groups); + status->unit_params_destroy_entry(&status->dummy_unit_params); + status->unit_params_clear_db(); } /*===================================== @@ -14463,6 +14630,7 @@ void status_defaults(void) status->get_name = status_get_name; status->get_class = status_get_class; status->get_lv = status_get_lv; + status->get_spiritballs = status_get_spiritballs; status->get_def = status_get_def; status->get_speed = status_get_speed; status->calc_attack_element = status_calc_attack_element; @@ -14557,6 +14725,10 @@ void status_defaults(void) status->calc_int = status_calc_int; status->calc_dex = status_calc_dex; status->calc_luk = status_calc_luk; + status->calc_atk_percent = status_calc_atk_percent; + status->calc_matk_percent = status_calc_matk_percent; + status->calc_def_percent = status_calc_def_percent; + status->calc_mdef_percent = status_calc_mdef_percent; status->calc_watk = status_calc_watk; status->calc_matk = status_calc_matk; status->calc_hit = status_calc_hit; @@ -14597,7 +14769,8 @@ void status_defaults(void) status->maxhp_entry_compare = status_maxhp_entry_compare; status->read_unit_params_db_maxhp = status_read_unit_params_db_maxhp; status->read_unit_params_db_additional = status_read_unit_params_db_additional; - status->unit_params_destroy = status_unit_params_destroy; + status->unit_params_destroy_entry = status_unit_params_destroy_entry; + status->unit_params_clear_db = status_unit_params_clear_db; status->copy = status_copy; status->base_matk_min = status_base_matk_min; status->base_matk_max = status_base_matk_max; diff --git a/src/map/status.h b/src/map/status.h index cb1915e49..a4b15011d 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -914,6 +914,10 @@ typedef enum sc_type { SC_FIRE_EXPANSION_TEAR_GAS_SOB, + SC_TAROTCARD_ATK_PERC, + SC_TAROTCARD_MATK_PERC, + SC_TAROTCARD_DEF_PERC, + SC_GOSPEL_ATK_PERC, #ifndef SC_MAX SC_MAX, //Automatically updated max, used in for's to check we are within bounds. #endif @@ -1030,48 +1034,75 @@ enum manner_flags MANNER_NOROOM = 0x10, }; +#ifndef _MSC_VER +#define CONST_OR_ENUMVAL(_const_, _val_) _const_ = _val_, +#else +#define CONST_OR_ENUMVAL(_const_, _val_) static const uint64_t _const_ = _val_; +#endif + +#ifndef _MSC_VER //Define flags for the status_calc_bl function. [Skotlex] -enum scb_flag +enum _scb_flag { - SCB_NONE = 0x00000000, - SCB_BASE = 0x00000001, - SCB_MAXHP = 0x00000002, - SCB_MAXSP = 0x00000004, - SCB_STR = 0x00000008, - SCB_AGI = 0x00000010, - SCB_VIT = 0x00000020, - SCB_INT = 0x00000040, - SCB_DEX = 0x00000080, - SCB_LUK = 0x00000100, - SCB_BATK = 0x00000200, - SCB_WATK = 0x00000400, - SCB_MATK = 0x00000800, - SCB_HIT = 0x00001000, - SCB_FLEE = 0x00002000, - SCB_DEF = 0x00004000, - SCB_DEF2 = 0x00008000, - SCB_MDEF = 0x00010000, - SCB_MDEF2 = 0x00020000, - SCB_SPEED = 0x00040000, - SCB_ASPD = 0x00080000, - SCB_DSPD = 0x00100000, - SCB_CRI = 0x00200000, - SCB_FLEE2 = 0x00400000, - SCB_ATK_ELE = 0x00800000, - SCB_DEF_ELE = 0x01000000, - SCB_MODE = 0x02000000, - SCB_SIZE = 0x04000000, - SCB_RACE = 0x08000000, - SCB_RANGE = 0x10000000, - SCB_REGEN = 0x20000000, - SCB_DYE = 0x40000000, // force cloth-dye change to 0 to avoid client crashes. +#endif + CONST_OR_ENUMVAL(SCB_NONE, 0x00000000) + CONST_OR_ENUMVAL(SCB_BASE, 0x00000001) + CONST_OR_ENUMVAL(SCB_MAXHP, 0x00000002) + CONST_OR_ENUMVAL(SCB_MAXSP, 0x00000004) + CONST_OR_ENUMVAL(SCB_STR, 0x00000008) + CONST_OR_ENUMVAL(SCB_AGI, 0x00000010) + CONST_OR_ENUMVAL(SCB_VIT, 0x00000020) + CONST_OR_ENUMVAL(SCB_INT, 0x00000040) + CONST_OR_ENUMVAL(SCB_DEX, 0x00000080) + CONST_OR_ENUMVAL(SCB_LUK, 0x00000100) + CONST_OR_ENUMVAL(SCB_BATK, 0x00000200) + CONST_OR_ENUMVAL(SCB_WATK, 0x00000400) + CONST_OR_ENUMVAL(SCB_MATK, 0x00000800) + CONST_OR_ENUMVAL(SCB_HIT, 0x00001000) + CONST_OR_ENUMVAL(SCB_FLEE, 0x00002000) + CONST_OR_ENUMVAL(SCB_DEF, 0x00004000) + CONST_OR_ENUMVAL(SCB_DEF2, 0x00008000) + CONST_OR_ENUMVAL(SCB_MDEF, 0x00010000) + CONST_OR_ENUMVAL(SCB_MDEF2, 0x00020000) + CONST_OR_ENUMVAL(SCB_SPEED, 0x00040000) + CONST_OR_ENUMVAL(SCB_ASPD, 0x00080000) + CONST_OR_ENUMVAL(SCB_DSPD, 0x00100000) + CONST_OR_ENUMVAL(SCB_CRI, 0x00200000) + CONST_OR_ENUMVAL(SCB_FLEE2, 0x00400000) + CONST_OR_ENUMVAL(SCB_ATK_ELE, 0x00800000) + CONST_OR_ENUMVAL(SCB_DEF_ELE, 0x01000000) + CONST_OR_ENUMVAL(SCB_MODE, 0x02000000) + CONST_OR_ENUMVAL(SCB_SIZE, 0x04000000) + CONST_OR_ENUMVAL(SCB_RACE, 0x08000000) + CONST_OR_ENUMVAL(SCB_RANGE, 0x10000000) + CONST_OR_ENUMVAL(SCB_REGEN, 0x20000000) + CONST_OR_ENUMVAL(SCB_DYE, 0x40000000) // force cloth-dye change to 0 to avoid client crashes. #if 0 // Currently No SC use it. Also, when this will be implemented, there will be need to change to 64bit variable - SCB_BODY = 0x80000000, // Force bodysStyle change to 0 + CONST_OR_ENUMVAL(SCB_BODY, 0x80000000) // Force bodysStyle change to 0 #endif - - SCB_BATTLE = 0x3FFFFFFE, - SCB_ALL = 0x3FFFFFFF + CONST_OR_ENUMVAL(SCB_ATK_PERC, 0x100000000) + CONST_OR_ENUMVAL(SCB_MATK_PERC, 0x200000000) + CONST_OR_ENUMVAL(SCB_DEF_PERC, 0x400000000) + CONST_OR_ENUMVAL(SCB_MDEF_PERC, 0x800000000) + + CONST_OR_ENUMVAL(SCB_BATTLE, 0xF3FFFFFFE) + CONST_OR_ENUMVAL(SCB_ALL, 0xF3FFFFFFF) +#ifndef _MSC_VER }; +#endif + +#ifndef _MSC_VER + typedef enum _scb_flag e_scb_flag; +#else + typedef uint64_t e_scb_flag; +#endif +#undef CONST_OR_ENUMVAL + +STATIC_ASSERT(sizeof(e_scb_flag) > 4, "e_scb_flag values need to be larger than 32 bits."); +STATIC_ASSERT(sizeof(SCB_ATK_PERC) > 4, "e_scb_flag values need to be larger than 32 bits."); +STATIC_ASSERT(sizeof(SCB_MATK_PERC) > 4, "e_scb_flag values need to be larger than 32 bits."); +STATIC_ASSERT(sizeof(SCB_DEF_PERC) > 4, "e_scb_flag values need to be larger than 32 bits."); +STATIC_ASSERT(sizeof(SCB_MDEF_PERC) > 4, "e_scb_flag values need to be larger than 32 bits."); //Regen related flags. enum e_regen { @@ -1113,6 +1144,10 @@ struct status_data { hp, sp, // see status_cpy before adding members before hp and sp max_hp, max_sp; uint16 str, agi, vit, int_, dex, luk; + int atk_percent; + int matk_percent; + int def_percent; + int mdef_percent; uint32 batk, matk_min, matk_max, @@ -1277,7 +1312,7 @@ struct status_change { #define status_change_end(bl,type,tid) (status->change_end_((bl),(type),(tid))) -#define status_calc_bl(bl, flag) (status->calc_bl_((bl), (enum scb_flag)(flag), SCO_NONE)) +#define status_calc_bl(bl, flag) (status->calc_bl_((bl), (e_scb_flag)(flag), SCO_NONE)) #define status_calc_mob(md, opt) (status->calc_bl_(&(md)->bl, SCB_ALL, (opt))) #define status_calc_pet(pd, opt) (status->calc_bl_(&(pd)->bl, SCB_ALL, (opt))) #define status_calc_pc(sd, opt) (status->calc_bl_(&(sd)->bl, SCB_ALL, (opt))) @@ -1314,7 +1349,7 @@ BEGIN_ZEROED_BLOCK; /* Everything within this block will be memset to 0 when sta int id; int relevant_bl_types; } IconChangeTable[SC_MAX]; - unsigned int ChangeFlagTable[SC_MAX]; // status -> flags + e_scb_flag ChangeFlagTable[SC_MAX]; // status -> flags int SkillChangeTable[SC_MAX]; // status -> skill bool DisplayType[SC_MAX]; /* */ @@ -1350,7 +1385,7 @@ struct status_interface { /* funcs */ // for looking up associated data int (*sc2skill) (sc_type sc); - unsigned int (*sc2scb_flag) (sc_type sc); + e_scb_flag (*sc2scb_flag) (sc_type sc); int (*get_sc_relevant_bl_types) (sc_type type); int (*get_sc_type) (sc_type idx); int (*get_sc_icon) (sc_type type); @@ -1370,6 +1405,7 @@ struct status_interface { const char *(*get_name) (const struct block_list *bl); int (*get_class) (const struct block_list *bl); int (*get_lv) (const struct block_list *bl); + int (*get_spiritballs) (const struct block_list *bl); defType (*get_def) (struct block_list *bl); unsigned short (*get_speed) (struct block_list *bl); unsigned char (*calc_attack_element) (struct block_list *bl, struct status_change *sc, int element); @@ -1395,13 +1431,13 @@ struct status_interface { int (*change_start_set_option) (struct block_list *bl, struct status_change* sc, enum sc_type type, int val1, int val2, int val3, int val4); int (*get_val_flag) (enum sc_type type); void (*change_start_display) (struct map_session_data *sd, enum sc_type type, int val1, int val2, int val3, int val4); - bool (*change_start_unknown_sc) (struct block_list *src, struct block_list *bl, enum sc_type type, int calc_flag, int rate, int val1, int val2, int val3, int val4, int total_tick, int flag); + bool (*change_start_unknown_sc) (struct block_list *src, struct block_list *bl, enum sc_type type, e_scb_flag calc_flag, int rate, int val1, int val2, int val3, int val4, int total_tick, int flag); int (*kaahi_heal_timer) (int tid, int64 tick, int id, intptr_t data); int (*change_timer) (int tid, int64 tick, int id, intptr_t data); int (*change_timer_sub) (struct block_list* bl, va_list ap); int (*change_clear) (struct block_list* bl, int type); int (*change_clear_buffs) (struct block_list* bl, int type); - void (*calc_bl_) (struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt); + void (*calc_bl_) (struct block_list *bl, e_scb_flag flag, enum e_status_calc_opt opt); int (*calc_mob_) (struct mob_data* md, enum e_status_calc_opt opt); int (*calc_pet_) (struct pet_data* pd, enum e_status_calc_opt opt); int (*calc_pc_) (struct map_session_data* sd, enum e_status_calc_opt opt); @@ -1453,6 +1489,10 @@ struct status_interface { unsigned short (*calc_int) (struct block_list *bl, struct status_change *sc, int int_); unsigned short (*calc_dex) (struct block_list *bl, struct status_change *sc, int dex); unsigned short (*calc_luk) (struct block_list *bl, struct status_change *sc, int luk); + int (*calc_atk_percent) (struct block_list *bl, struct status_change *sc); + int (*calc_matk_percent) (struct block_list *bl, struct status_change *sc); + int (*calc_def_percent) (struct block_list *bl, struct status_change *sc); + int (*calc_mdef_percent) (struct block_list *bl, struct status_change *sc); int (*calc_watk) (struct block_list *bl, struct status_change *sc, int watk, bool viewable); int (*calc_matk) (struct block_list *bl, struct status_change *sc, int matk, bool viewable); signed int (*calc_hit) (struct block_list *bl, struct status_change *sc, int hit, bool viewable); @@ -1470,7 +1510,7 @@ struct status_interface { unsigned char (*calc_element_lv) (struct block_list *bl, struct status_change *sc, int lv); uint32 (*calc_mode) (const struct block_list *bl, const struct status_change *sc, uint32 mode); int (*calc_ematk) (struct block_list *bl, struct status_change *sc, int matk); - void (*calc_bl_main) (struct block_list *bl, int flag); + void (*calc_bl_main) (struct block_list *bl, e_scb_flag flag); void (*display_add) (struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3); void (*display_remove) (struct map_session_data *sd, enum sc_type type); int (*natural_heal) (struct block_list *bl, va_list args); @@ -1491,7 +1531,8 @@ struct status_interface { bool (*read_unit_params_db_maxhp) (struct s_unit_params *entry, struct s_unit_params *inherited, struct config_setting_t *group, const char *source); int (*maxhp_entry_compare) (const void *entry1, const void *entry2); bool (*read_unit_params_db_additional) (struct s_unit_params *entry, struct s_unit_params *inherited, struct config_setting_t *group, const char *source); - void (*unit_params_destroy) (struct s_unit_params *entry); + void (*unit_params_destroy_entry) (struct s_unit_params *entry); + void (*unit_params_clear_db) (void); void (*copy) (struct status_data *a, const struct status_data *b); int (*base_matk_min) (const struct status_data *st); int (*base_matk_max) (const struct status_data *st); diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc index 32b799600..73b139233 100644 --- a/src/plugins/HPMHooking/HPMHooking.Defs.inc +++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc @@ -1802,8 +1802,10 @@ typedef void (*HPMHOOK_pre_clif_produce_effect) (struct map_session_data **sd, i typedef void (*HPMHOOK_post_clif_produce_effect) (struct map_session_data *sd, int flag, int nameid); typedef void (*HPMHOOK_pre_clif_devotion) (struct block_list **src, struct map_session_data **tsd); typedef void (*HPMHOOK_post_clif_devotion) (struct block_list *src, struct map_session_data *tsd); -typedef void (*HPMHOOK_pre_clif_spiritball) (struct block_list **bl, enum spirit_ball_types *spirit, enum send_target *target); -typedef void (*HPMHOOK_post_clif_spiritball) (struct block_list *bl, enum spirit_ball_types spirit, enum send_target target); +typedef void (*HPMHOOK_pre_clif_soulballs) (struct block_list **bl, int *soulballs, enum send_target *target); +typedef void (*HPMHOOK_post_clif_soulballs) (struct block_list *bl, int soulballs, enum send_target target); +typedef void (*HPMHOOK_pre_clif_spiritballs) (struct block_list **bl, int *spiritballs, enum send_target *target); +typedef void (*HPMHOOK_post_clif_spiritballs) (struct block_list *bl, int spiritballs, enum send_target target); typedef void (*HPMHOOK_pre_clif_spiritball_single) (int *fd, struct map_session_data **sd); typedef void (*HPMHOOK_post_clif_spiritball_single) (int fd, struct map_session_data *sd); typedef void (*HPMHOOK_pre_clif_bladestop) (struct block_list **src, int *dst_id, int *active); @@ -4802,6 +4804,8 @@ typedef struct item_reform* (*HPMHOOK_pre_itemdb_reform_exists) (int *idx); typedef struct item_reform* (*HPMHOOK_post_itemdb_reform_exists) (struct item_reform* retVal___, int idx); typedef bool (*HPMHOOK_pre_itemdb_in_group) (struct item_group **group, int *nameid); typedef bool (*HPMHOOK_post_itemdb_in_group) (bool retVal___, struct item_group *group, int nameid); +typedef const struct item_group* (*HPMHOOK_pre_itemdb_search_group) (int *nameid); +typedef const struct item_group* (*HPMHOOK_post_itemdb_search_group) (const struct item_group* retVal___, int nameid); typedef int (*HPMHOOK_pre_itemdb_group_item) (struct item_group **group); typedef int (*HPMHOOK_post_itemdb_group_item) (int retVal___, struct item_group *group); typedef int (*HPMHOOK_pre_itemdb_chain_item) (unsigned short *chain_id, int **rate); @@ -8282,6 +8286,8 @@ typedef void (*HPMHOOK_pre_skill_read_db) (bool *minimal); typedef void (*HPMHOOK_post_skill_read_db) (bool minimal); typedef int (*HPMHOOK_pre_skill_get_index) (int *skill_id); typedef int (*HPMHOOK_post_skill_get_index) (int retVal___, int skill_id); +typedef int (*HPMHOOK_pre_skill_get_index_sub) (int *skill_id, bool *report_errors); +typedef int (*HPMHOOK_post_skill_get_index_sub) (int retVal___, int skill_id, bool report_errors); typedef int (*HPMHOOK_pre_skill_get_type) (int *skill_id, int *skill_lv); typedef int (*HPMHOOK_post_skill_get_type) (int retVal___, int skill_id, int skill_lv); typedef int (*HPMHOOK_pre_skill_get_hit) (int *skill_id, int *skill_lv); @@ -9040,8 +9046,8 @@ typedef void (*HPMHOOK_pre_status_final) (void); typedef void (*HPMHOOK_post_status_final) (void); typedef int (*HPMHOOK_pre_status_sc2skill) (sc_type *sc); typedef int (*HPMHOOK_post_status_sc2skill) (int retVal___, sc_type sc); -typedef unsigned int (*HPMHOOK_pre_status_sc2scb_flag) (sc_type *sc); -typedef unsigned int (*HPMHOOK_post_status_sc2scb_flag) (unsigned int retVal___, sc_type sc); +typedef e_scb_flag (*HPMHOOK_pre_status_sc2scb_flag) (sc_type *sc); +typedef e_scb_flag (*HPMHOOK_post_status_sc2scb_flag) (e_scb_flag retVal___, sc_type sc); typedef int (*HPMHOOK_pre_status_get_sc_relevant_bl_types) (sc_type *type); typedef int (*HPMHOOK_post_status_get_sc_relevant_bl_types) (int retVal___, sc_type type); typedef int (*HPMHOOK_pre_status_get_sc_type) (sc_type *idx); @@ -9076,6 +9082,8 @@ typedef int (*HPMHOOK_pre_status_get_class) (const struct block_list **bl); typedef int (*HPMHOOK_post_status_get_class) (int retVal___, const struct block_list *bl); typedef int (*HPMHOOK_pre_status_get_lv) (const struct block_list **bl); typedef int (*HPMHOOK_post_status_get_lv) (int retVal___, const struct block_list *bl); +typedef int (*HPMHOOK_pre_status_get_spiritballs) (const struct block_list **bl); +typedef int (*HPMHOOK_post_status_get_spiritballs) (int retVal___, const struct block_list *bl); typedef defType (*HPMHOOK_pre_status_get_def) (struct block_list **bl); typedef defType (*HPMHOOK_post_status_get_def) (defType retVal___, struct block_list *bl); typedef unsigned short (*HPMHOOK_pre_status_get_speed) (struct block_list **bl); @@ -9126,8 +9134,8 @@ typedef int (*HPMHOOK_pre_status_get_val_flag) (enum sc_type *type); typedef int (*HPMHOOK_post_status_get_val_flag) (int retVal___, enum sc_type type); typedef void (*HPMHOOK_pre_status_change_start_display) (struct map_session_data **sd, enum sc_type *type, int *val1, int *val2, int *val3, int *val4); typedef void (*HPMHOOK_post_status_change_start_display) (struct map_session_data *sd, enum sc_type type, int val1, int val2, int val3, int val4); -typedef bool (*HPMHOOK_pre_status_change_start_unknown_sc) (struct block_list **src, struct block_list **bl, enum sc_type *type, int *calc_flag, int *rate, int *val1, int *val2, int *val3, int *val4, int *total_tick, int *flag); -typedef bool (*HPMHOOK_post_status_change_start_unknown_sc) (bool retVal___, struct block_list *src, struct block_list *bl, enum sc_type type, int calc_flag, int rate, int val1, int val2, int val3, int val4, int total_tick, int flag); +typedef bool (*HPMHOOK_pre_status_change_start_unknown_sc) (struct block_list **src, struct block_list **bl, enum sc_type *type, e_scb_flag *calc_flag, int *rate, int *val1, int *val2, int *val3, int *val4, int *total_tick, int *flag); +typedef bool (*HPMHOOK_post_status_change_start_unknown_sc) (bool retVal___, struct block_list *src, struct block_list *bl, enum sc_type type, e_scb_flag calc_flag, int rate, int val1, int val2, int val3, int val4, int total_tick, int flag); typedef int (*HPMHOOK_pre_status_kaahi_heal_timer) (int *tid, int64 *tick, int *id, intptr_t *data); typedef int (*HPMHOOK_post_status_kaahi_heal_timer) (int retVal___, int tid, int64 tick, int id, intptr_t data); typedef int (*HPMHOOK_pre_status_change_timer) (int *tid, int64 *tick, int *id, intptr_t *data); @@ -9138,8 +9146,8 @@ typedef int (*HPMHOOK_pre_status_change_clear) (struct block_list **bl, int *typ typedef int (*HPMHOOK_post_status_change_clear) (int retVal___, struct block_list *bl, int type); typedef int (*HPMHOOK_pre_status_change_clear_buffs) (struct block_list **bl, int *type); typedef int (*HPMHOOK_post_status_change_clear_buffs) (int retVal___, struct block_list *bl, int type); -typedef void (*HPMHOOK_pre_status_calc_bl_) (struct block_list **bl, enum scb_flag *flag, enum e_status_calc_opt *opt); -typedef void (*HPMHOOK_post_status_calc_bl_) (struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt); +typedef void (*HPMHOOK_pre_status_calc_bl_) (struct block_list **bl, e_scb_flag *flag, enum e_status_calc_opt *opt); +typedef void (*HPMHOOK_post_status_calc_bl_) (struct block_list *bl, e_scb_flag flag, enum e_status_calc_opt opt); typedef int (*HPMHOOK_pre_status_calc_mob_) (struct mob_data **md, enum e_status_calc_opt *opt); typedef int (*HPMHOOK_post_status_calc_mob_) (int retVal___, struct mob_data *md, enum e_status_calc_opt opt); typedef int (*HPMHOOK_pre_status_calc_pet_) (struct pet_data **pd, enum e_status_calc_opt *opt); @@ -9240,6 +9248,14 @@ typedef unsigned short (*HPMHOOK_pre_status_calc_dex) (struct block_list **bl, s typedef unsigned short (*HPMHOOK_post_status_calc_dex) (unsigned short retVal___, struct block_list *bl, struct status_change *sc, int dex); typedef unsigned short (*HPMHOOK_pre_status_calc_luk) (struct block_list **bl, struct status_change **sc, int *luk); typedef unsigned short (*HPMHOOK_post_status_calc_luk) (unsigned short retVal___, struct block_list *bl, struct status_change *sc, int luk); +typedef int (*HPMHOOK_pre_status_calc_atk_percent) (struct block_list **bl, struct status_change **sc); +typedef int (*HPMHOOK_post_status_calc_atk_percent) (int retVal___, struct block_list *bl, struct status_change *sc); +typedef int (*HPMHOOK_pre_status_calc_matk_percent) (struct block_list **bl, struct status_change **sc); +typedef int (*HPMHOOK_post_status_calc_matk_percent) (int retVal___, struct block_list *bl, struct status_change *sc); +typedef int (*HPMHOOK_pre_status_calc_def_percent) (struct block_list **bl, struct status_change **sc); +typedef int (*HPMHOOK_post_status_calc_def_percent) (int retVal___, struct block_list *bl, struct status_change *sc); +typedef int (*HPMHOOK_pre_status_calc_mdef_percent) (struct block_list **bl, struct status_change **sc); +typedef int (*HPMHOOK_post_status_calc_mdef_percent) (int retVal___, struct block_list *bl, struct status_change *sc); typedef int (*HPMHOOK_pre_status_calc_watk) (struct block_list **bl, struct status_change **sc, int *watk, bool *viewable); typedef int (*HPMHOOK_post_status_calc_watk) (int retVal___, struct block_list *bl, struct status_change *sc, int watk, bool viewable); typedef int (*HPMHOOK_pre_status_calc_matk) (struct block_list **bl, struct status_change **sc, int *matk, bool *viewable); @@ -9274,8 +9290,8 @@ typedef uint32 (*HPMHOOK_pre_status_calc_mode) (const struct block_list **bl, co typedef uint32 (*HPMHOOK_post_status_calc_mode) (uint32 retVal___, const struct block_list *bl, const struct status_change *sc, uint32 mode); typedef int (*HPMHOOK_pre_status_calc_ematk) (struct block_list **bl, struct status_change **sc, int *matk); typedef int (*HPMHOOK_post_status_calc_ematk) (int retVal___, struct block_list *bl, struct status_change *sc, int matk); -typedef void (*HPMHOOK_pre_status_calc_bl_main) (struct block_list **bl, int *flag); -typedef void (*HPMHOOK_post_status_calc_bl_main) (struct block_list *bl, int flag); +typedef void (*HPMHOOK_pre_status_calc_bl_main) (struct block_list **bl, e_scb_flag *flag); +typedef void (*HPMHOOK_post_status_calc_bl_main) (struct block_list *bl, e_scb_flag flag); typedef void (*HPMHOOK_pre_status_display_add) (struct map_session_data **sd, enum sc_type *type, int *dval1, int *dval2, int *dval3); typedef void (*HPMHOOK_post_status_display_add) (struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3); typedef void (*HPMHOOK_pre_status_display_remove) (struct map_session_data **sd, enum sc_type *type); @@ -9316,8 +9332,10 @@ typedef int (*HPMHOOK_pre_status_maxhp_entry_compare) (const void **entry1, cons typedef int (*HPMHOOK_post_status_maxhp_entry_compare) (int retVal___, const void *entry1, const void *entry2); typedef bool (*HPMHOOK_pre_status_read_unit_params_db_additional) (struct s_unit_params **entry, struct s_unit_params **inherited, struct config_setting_t **group, const char **source); typedef bool (*HPMHOOK_post_status_read_unit_params_db_additional) (bool retVal___, struct s_unit_params *entry, struct s_unit_params *inherited, struct config_setting_t *group, const char *source); -typedef void (*HPMHOOK_pre_status_unit_params_destroy) (struct s_unit_params **entry); -typedef void (*HPMHOOK_post_status_unit_params_destroy) (struct s_unit_params *entry); +typedef void (*HPMHOOK_pre_status_unit_params_destroy_entry) (struct s_unit_params **entry); +typedef void (*HPMHOOK_post_status_unit_params_destroy_entry) (struct s_unit_params *entry); +typedef void (*HPMHOOK_pre_status_unit_params_clear_db) (void); +typedef void (*HPMHOOK_post_status_unit_params_clear_db) (void); typedef void (*HPMHOOK_pre_status_copy) (struct status_data **a, const struct status_data **b); typedef void (*HPMHOOK_post_status_copy) (struct status_data *a, const struct status_data *b); typedef int (*HPMHOOK_pre_status_base_matk_min) (const struct status_data **st); diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc index 85ac30768..758e57d1c 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc @@ -1160,8 +1160,10 @@ struct { struct HPMHookPoint *HP_clif_produce_effect_post; struct HPMHookPoint *HP_clif_devotion_pre; struct HPMHookPoint *HP_clif_devotion_post; - struct HPMHookPoint *HP_clif_spiritball_pre; - struct HPMHookPoint *HP_clif_spiritball_post; + struct HPMHookPoint *HP_clif_soulballs_pre; + struct HPMHookPoint *HP_clif_soulballs_post; + struct HPMHookPoint *HP_clif_spiritballs_pre; + struct HPMHookPoint *HP_clif_spiritballs_post; struct HPMHookPoint *HP_clif_spiritball_single_pre; struct HPMHookPoint *HP_clif_spiritball_single_post; struct HPMHookPoint *HP_clif_bladestop_pre; @@ -3528,6 +3530,8 @@ struct { struct HPMHookPoint *HP_itemdb_reform_exists_post; struct HPMHookPoint *HP_itemdb_in_group_pre; struct HPMHookPoint *HP_itemdb_in_group_post; + struct HPMHookPoint *HP_itemdb_search_group_pre; + struct HPMHookPoint *HP_itemdb_search_group_post; struct HPMHookPoint *HP_itemdb_group_item_pre; struct HPMHookPoint *HP_itemdb_group_item_post; struct HPMHookPoint *HP_itemdb_chain_item_pre; @@ -6204,6 +6208,8 @@ struct { struct HPMHookPoint *HP_skill_read_db_post; struct HPMHookPoint *HP_skill_get_index_pre; struct HPMHookPoint *HP_skill_get_index_post; + struct HPMHookPoint *HP_skill_get_index_sub_pre; + struct HPMHookPoint *HP_skill_get_index_sub_post; struct HPMHookPoint *HP_skill_get_type_pre; struct HPMHookPoint *HP_skill_get_type_post; struct HPMHookPoint *HP_skill_get_hit_pre; @@ -6992,6 +6998,8 @@ struct { struct HPMHookPoint *HP_status_get_class_post; struct HPMHookPoint *HP_status_get_lv_pre; struct HPMHookPoint *HP_status_get_lv_post; + struct HPMHookPoint *HP_status_get_spiritballs_pre; + struct HPMHookPoint *HP_status_get_spiritballs_post; struct HPMHookPoint *HP_status_get_def_pre; struct HPMHookPoint *HP_status_get_def_post; struct HPMHookPoint *HP_status_get_speed_pre; @@ -7156,6 +7164,14 @@ struct { struct HPMHookPoint *HP_status_calc_dex_post; struct HPMHookPoint *HP_status_calc_luk_pre; struct HPMHookPoint *HP_status_calc_luk_post; + struct HPMHookPoint *HP_status_calc_atk_percent_pre; + struct HPMHookPoint *HP_status_calc_atk_percent_post; + struct HPMHookPoint *HP_status_calc_matk_percent_pre; + struct HPMHookPoint *HP_status_calc_matk_percent_post; + struct HPMHookPoint *HP_status_calc_def_percent_pre; + struct HPMHookPoint *HP_status_calc_def_percent_post; + struct HPMHookPoint *HP_status_calc_mdef_percent_pre; + struct HPMHookPoint *HP_status_calc_mdef_percent_post; struct HPMHookPoint *HP_status_calc_watk_pre; struct HPMHookPoint *HP_status_calc_watk_post; struct HPMHookPoint *HP_status_calc_matk_pre; @@ -7232,8 +7248,10 @@ struct { struct HPMHookPoint *HP_status_maxhp_entry_compare_post; struct HPMHookPoint *HP_status_read_unit_params_db_additional_pre; struct HPMHookPoint *HP_status_read_unit_params_db_additional_post; - struct HPMHookPoint *HP_status_unit_params_destroy_pre; - struct HPMHookPoint *HP_status_unit_params_destroy_post; + struct HPMHookPoint *HP_status_unit_params_destroy_entry_pre; + struct HPMHookPoint *HP_status_unit_params_destroy_entry_post; + struct HPMHookPoint *HP_status_unit_params_clear_db_pre; + struct HPMHookPoint *HP_status_unit_params_clear_db_post; struct HPMHookPoint *HP_status_copy_pre; struct HPMHookPoint *HP_status_copy_post; struct HPMHookPoint *HP_status_base_matk_min_pre; @@ -8721,8 +8739,10 @@ struct { int HP_clif_produce_effect_post; int HP_clif_devotion_pre; int HP_clif_devotion_post; - int HP_clif_spiritball_pre; - int HP_clif_spiritball_post; + int HP_clif_soulballs_pre; + int HP_clif_soulballs_post; + int HP_clif_spiritballs_pre; + int HP_clif_spiritballs_post; int HP_clif_spiritball_single_pre; int HP_clif_spiritball_single_post; int HP_clif_bladestop_pre; @@ -11089,6 +11109,8 @@ struct { int HP_itemdb_reform_exists_post; int HP_itemdb_in_group_pre; int HP_itemdb_in_group_post; + int HP_itemdb_search_group_pre; + int HP_itemdb_search_group_post; int HP_itemdb_group_item_pre; int HP_itemdb_group_item_post; int HP_itemdb_chain_item_pre; @@ -13765,6 +13787,8 @@ struct { int HP_skill_read_db_post; int HP_skill_get_index_pre; int HP_skill_get_index_post; + int HP_skill_get_index_sub_pre; + int HP_skill_get_index_sub_post; int HP_skill_get_type_pre; int HP_skill_get_type_post; int HP_skill_get_hit_pre; @@ -14553,6 +14577,8 @@ struct { int HP_status_get_class_post; int HP_status_get_lv_pre; int HP_status_get_lv_post; + int HP_status_get_spiritballs_pre; + int HP_status_get_spiritballs_post; int HP_status_get_def_pre; int HP_status_get_def_post; int HP_status_get_speed_pre; @@ -14717,6 +14743,14 @@ struct { int HP_status_calc_dex_post; int HP_status_calc_luk_pre; int HP_status_calc_luk_post; + int HP_status_calc_atk_percent_pre; + int HP_status_calc_atk_percent_post; + int HP_status_calc_matk_percent_pre; + int HP_status_calc_matk_percent_post; + int HP_status_calc_def_percent_pre; + int HP_status_calc_def_percent_post; + int HP_status_calc_mdef_percent_pre; + int HP_status_calc_mdef_percent_post; int HP_status_calc_watk_pre; int HP_status_calc_watk_post; int HP_status_calc_matk_pre; @@ -14793,8 +14827,10 @@ struct { int HP_status_maxhp_entry_compare_post; int HP_status_read_unit_params_db_additional_pre; int HP_status_read_unit_params_db_additional_post; - int HP_status_unit_params_destroy_pre; - int HP_status_unit_params_destroy_post; + int HP_status_unit_params_destroy_entry_pre; + int HP_status_unit_params_destroy_entry_post; + int HP_status_unit_params_clear_db_pre; + int HP_status_unit_params_clear_db_post; int HP_status_copy_pre; int HP_status_copy_post; int HP_status_base_matk_min_pre; diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc index e81225a45..a9ee53e0c 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc @@ -605,7 +605,8 @@ struct HookingPointData HookingPoints[] = { { HP_POP(clif->useskill, HP_clif_useskill) }, { HP_POP(clif->produce_effect, HP_clif_produce_effect) }, { HP_POP(clif->devotion, HP_clif_devotion) }, - { HP_POP(clif->spiritball, HP_clif_spiritball) }, + { HP_POP(clif->soulballs, HP_clif_soulballs) }, + { HP_POP(clif->spiritballs, HP_clif_spiritballs) }, { HP_POP(clif->spiritball_single, HP_clif_spiritball_single) }, { HP_POP(clif->bladestop, HP_clif_bladestop) }, { HP_POP(clif->mvp_effect, HP_clif_mvp_effect) }, @@ -1808,6 +1809,7 @@ struct HookingPointData HookingPoints[] = { { HP_POP(itemdb->option_exists, HP_itemdb_option_exists) }, { HP_POP(itemdb->reform_exists, HP_itemdb_reform_exists) }, { HP_POP(itemdb->in_group, HP_itemdb_in_group) }, + { HP_POP(itemdb->search_group, HP_itemdb_search_group) }, { HP_POP(itemdb->group_item, HP_itemdb_group_item) }, { HP_POP(itemdb->chain_item, HP_itemdb_chain_item) }, { HP_POP(itemdb->package_item, HP_itemdb_package_item) }, @@ -3178,6 +3180,7 @@ struct HookingPointData HookingPoints[] = { { HP_POP(skill->reload, HP_skill_reload) }, { HP_POP(skill->read_db, HP_skill_read_db) }, { HP_POP(skill->get_index, HP_skill_get_index) }, + { HP_POP(skill->get_index_sub, HP_skill_get_index_sub) }, { HP_POP(skill->get_type, HP_skill_get_type) }, { HP_POP(skill->get_hit, HP_skill_get_hit) }, { HP_POP(skill->get_inf, HP_skill_get_inf) }, @@ -3575,6 +3578,7 @@ struct HookingPointData HookingPoints[] = { { HP_POP(status->get_name, HP_status_get_name) }, { HP_POP(status->get_class, HP_status_get_class) }, { HP_POP(status->get_lv, HP_status_get_lv) }, + { HP_POP(status->get_spiritballs, HP_status_get_spiritballs) }, { HP_POP(status->get_def, HP_status_get_def) }, { HP_POP(status->get_speed, HP_status_get_speed) }, { HP_POP(status->calc_attack_element, HP_status_calc_attack_element) }, @@ -3657,6 +3661,10 @@ struct HookingPointData HookingPoints[] = { { HP_POP(status->calc_int, HP_status_calc_int) }, { HP_POP(status->calc_dex, HP_status_calc_dex) }, { HP_POP(status->calc_luk, HP_status_calc_luk) }, + { HP_POP(status->calc_atk_percent, HP_status_calc_atk_percent) }, + { HP_POP(status->calc_matk_percent, HP_status_calc_matk_percent) }, + { HP_POP(status->calc_def_percent, HP_status_calc_def_percent) }, + { HP_POP(status->calc_mdef_percent, HP_status_calc_mdef_percent) }, { HP_POP(status->calc_watk, HP_status_calc_watk) }, { HP_POP(status->calc_matk, HP_status_calc_matk) }, { HP_POP(status->calc_hit, HP_status_calc_hit) }, @@ -3695,7 +3703,8 @@ struct HookingPointData HookingPoints[] = { { HP_POP(status->read_unit_params_db_maxhp, HP_status_read_unit_params_db_maxhp) }, { HP_POP(status->maxhp_entry_compare, HP_status_maxhp_entry_compare) }, { HP_POP(status->read_unit_params_db_additional, HP_status_read_unit_params_db_additional) }, - { HP_POP(status->unit_params_destroy, HP_status_unit_params_destroy) }, + { HP_POP(status->unit_params_destroy_entry, HP_status_unit_params_destroy_entry) }, + { HP_POP(status->unit_params_clear_db, HP_status_unit_params_clear_db) }, { HP_POP(status->copy, HP_status_copy) }, { HP_POP(status->base_matk_min, HP_status_base_matk_min) }, { HP_POP(status->base_matk_max, HP_status_base_matk_max) }, diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc index 34691ca08..7d55789c5 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc @@ -15135,14 +15135,14 @@ void HP_clif_devotion(struct block_list *src, struct map_session_data *tsd) { } return; } -void HP_clif_spiritball(struct block_list *bl, enum spirit_ball_types spirit, enum send_target target) { +void HP_clif_soulballs(struct block_list *bl, int soulballs, enum send_target target) { int hIndex = 0; - if (HPMHooks.count.HP_clif_spiritball_pre > 0) { - void (*preHookFunc) (struct block_list **bl, enum spirit_ball_types *spirit, enum send_target *target); + if (HPMHooks.count.HP_clif_soulballs_pre > 0) { + void (*preHookFunc) (struct block_list **bl, int *soulballs, enum send_target *target); *HPMforce_return = false; - for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_spiritball_pre; hIndex++) { - preHookFunc = HPMHooks.list.HP_clif_spiritball_pre[hIndex].func; - preHookFunc(&bl, &spirit, &target); + for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_soulballs_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_clif_soulballs_pre[hIndex].func; + preHookFunc(&bl, &soulballs, &target); } if (*HPMforce_return) { *HPMforce_return = false; @@ -15150,13 +15150,39 @@ void HP_clif_spiritball(struct block_list *bl, enum spirit_ball_types spirit, en } } { - HPMHooks.source.clif.spiritball(bl, spirit, target); + HPMHooks.source.clif.soulballs(bl, soulballs, target); } - if (HPMHooks.count.HP_clif_spiritball_post > 0) { - void (*postHookFunc) (struct block_list *bl, enum spirit_ball_types spirit, enum send_target target); - for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_spiritball_post; hIndex++) { - postHookFunc = HPMHooks.list.HP_clif_spiritball_post[hIndex].func; - postHookFunc(bl, spirit, target); + if (HPMHooks.count.HP_clif_soulballs_post > 0) { + void (*postHookFunc) (struct block_list *bl, int soulballs, enum send_target target); + for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_soulballs_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_clif_soulballs_post[hIndex].func; + postHookFunc(bl, soulballs, target); + } + } + return; +} +void HP_clif_spiritballs(struct block_list *bl, int spiritballs, enum send_target target) { + int hIndex = 0; + if (HPMHooks.count.HP_clif_spiritballs_pre > 0) { + void (*preHookFunc) (struct block_list **bl, int *spiritballs, enum send_target *target); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_spiritballs_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_clif_spiritballs_pre[hIndex].func; + preHookFunc(&bl, &spiritballs, &target); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.clif.spiritballs(bl, spiritballs, target); + } + if (HPMHooks.count.HP_clif_spiritballs_post > 0) { + void (*postHookFunc) (struct block_list *bl, int spiritballs, enum send_target target); + for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_spiritballs_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_clif_spiritballs_post[hIndex].func; + postHookFunc(bl, spiritballs, target); } } return; @@ -46399,6 +46425,33 @@ bool HP_itemdb_in_group(struct item_group *group, int nameid) { } return retVal___; } +const struct item_group* HP_itemdb_search_group(int nameid) { + int hIndex = 0; + const struct item_group* retVal___ = NULL; + if (HPMHooks.count.HP_itemdb_search_group_pre > 0) { + const struct item_group* (*preHookFunc) (int *nameid); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_itemdb_search_group_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_itemdb_search_group_pre[hIndex].func; + retVal___ = preHookFunc(&nameid); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.itemdb.search_group(nameid); + } + if (HPMHooks.count.HP_itemdb_search_group_post > 0) { + const struct item_group* (*postHookFunc) (const struct item_group* retVal___, int nameid); + for (hIndex = 0; hIndex < HPMHooks.count.HP_itemdb_search_group_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_itemdb_search_group_post[hIndex].func; + retVal___ = postHookFunc(retVal___, nameid); + } + } + return retVal___; +} int HP_itemdb_group_item(struct item_group *group) { int hIndex = 0; int retVal___ = 0; @@ -82749,6 +82802,33 @@ int HP_skill_get_index(int skill_id) { } return retVal___; } +int HP_skill_get_index_sub(int skill_id, bool report_errors) { + int hIndex = 0; + int retVal___ = 0; + if (HPMHooks.count.HP_skill_get_index_sub_pre > 0) { + int (*preHookFunc) (int *skill_id, bool *report_errors); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_get_index_sub_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_skill_get_index_sub_pre[hIndex].func; + retVal___ = preHookFunc(&skill_id, &report_errors); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.skill.get_index_sub(skill_id, report_errors); + } + if (HPMHooks.count.HP_skill_get_index_sub_post > 0) { + int (*postHookFunc) (int retVal___, int skill_id, bool report_errors); + for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_get_index_sub_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_skill_get_index_sub_post[hIndex].func; + retVal___ = postHookFunc(retVal___, skill_id, report_errors); + } + } + return retVal___; +} int HP_skill_get_type(int skill_id, int skill_lv) { int hIndex = 0; int retVal___ = 0; @@ -92961,11 +93041,11 @@ int HP_status_sc2skill(sc_type sc) { } return retVal___; } -unsigned int HP_status_sc2scb_flag(sc_type sc) { +e_scb_flag HP_status_sc2scb_flag(sc_type sc) { int hIndex = 0; - unsigned int retVal___ = 0; + e_scb_flag retVal___ = SCB_NONE; if (HPMHooks.count.HP_status_sc2scb_flag_pre > 0) { - unsigned int (*preHookFunc) (sc_type *sc); + e_scb_flag (*preHookFunc) (sc_type *sc); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_status_sc2scb_flag_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_status_sc2scb_flag_pre[hIndex].func; @@ -92980,7 +93060,7 @@ unsigned int HP_status_sc2scb_flag(sc_type sc) { retVal___ = HPMHooks.source.status.sc2scb_flag(sc); } if (HPMHooks.count.HP_status_sc2scb_flag_post > 0) { - unsigned int (*postHookFunc) (unsigned int retVal___, sc_type sc); + e_scb_flag (*postHookFunc) (e_scb_flag retVal___, sc_type sc); for (hIndex = 0; hIndex < HPMHooks.count.HP_status_sc2scb_flag_post; hIndex++) { postHookFunc = HPMHooks.list.HP_status_sc2scb_flag_post[hIndex].func; retVal___ = postHookFunc(retVal___, sc); @@ -93447,6 +93527,33 @@ int HP_status_get_lv(const struct block_list *bl) { } return retVal___; } +int HP_status_get_spiritballs(const struct block_list *bl) { + int hIndex = 0; + int retVal___ = 0; + if (HPMHooks.count.HP_status_get_spiritballs_pre > 0) { + int (*preHookFunc) (const struct block_list **bl); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_get_spiritballs_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_status_get_spiritballs_pre[hIndex].func; + retVal___ = preHookFunc(&bl); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.status.get_spiritballs(bl); + } + if (HPMHooks.count.HP_status_get_spiritballs_post > 0) { + int (*postHookFunc) (int retVal___, const struct block_list *bl); + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_get_spiritballs_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_status_get_spiritballs_post[hIndex].func; + retVal___ = postHookFunc(retVal___, bl); + } + } + return retVal___; +} defType HP_status_get_def(struct block_list *bl) { int hIndex = 0; defType retVal___ = 0; @@ -94118,11 +94225,11 @@ void HP_status_change_start_display(struct map_session_data *sd, enum sc_type ty } return; } -bool HP_status_change_start_unknown_sc(struct block_list *src, struct block_list *bl, enum sc_type type, int calc_flag, int rate, int val1, int val2, int val3, int val4, int total_tick, int flag) { +bool HP_status_change_start_unknown_sc(struct block_list *src, struct block_list *bl, enum sc_type type, e_scb_flag calc_flag, int rate, int val1, int val2, int val3, int val4, int total_tick, int flag) { int hIndex = 0; bool retVal___ = false; if (HPMHooks.count.HP_status_change_start_unknown_sc_pre > 0) { - bool (*preHookFunc) (struct block_list **src, struct block_list **bl, enum sc_type *type, int *calc_flag, int *rate, int *val1, int *val2, int *val3, int *val4, int *total_tick, int *flag); + bool (*preHookFunc) (struct block_list **src, struct block_list **bl, enum sc_type *type, e_scb_flag *calc_flag, int *rate, int *val1, int *val2, int *val3, int *val4, int *total_tick, int *flag); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_status_change_start_unknown_sc_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_status_change_start_unknown_sc_pre[hIndex].func; @@ -94137,7 +94244,7 @@ bool HP_status_change_start_unknown_sc(struct block_list *src, struct block_list retVal___ = HPMHooks.source.status.change_start_unknown_sc(src, bl, type, calc_flag, rate, val1, val2, val3, val4, total_tick, flag); } if (HPMHooks.count.HP_status_change_start_unknown_sc_post > 0) { - bool (*postHookFunc) (bool retVal___, struct block_list *src, struct block_list *bl, enum sc_type type, int calc_flag, int rate, int val1, int val2, int val3, int val4, int total_tick, int flag); + bool (*postHookFunc) (bool retVal___, struct block_list *src, struct block_list *bl, enum sc_type type, e_scb_flag calc_flag, int rate, int val1, int val2, int val3, int val4, int total_tick, int flag); for (hIndex = 0; hIndex < HPMHooks.count.HP_status_change_start_unknown_sc_post; hIndex++) { postHookFunc = HPMHooks.list.HP_status_change_start_unknown_sc_post[hIndex].func; retVal___ = postHookFunc(retVal___, src, bl, type, calc_flag, rate, val1, val2, val3, val4, total_tick, flag); @@ -94286,10 +94393,10 @@ int HP_status_change_clear_buffs(struct block_list *bl, int type) { } return retVal___; } -void HP_status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt) { +void HP_status_calc_bl_(struct block_list *bl, e_scb_flag flag, enum e_status_calc_opt opt) { int hIndex = 0; if (HPMHooks.count.HP_status_calc_bl__pre > 0) { - void (*preHookFunc) (struct block_list **bl, enum scb_flag *flag, enum e_status_calc_opt *opt); + void (*preHookFunc) (struct block_list **bl, e_scb_flag *flag, enum e_status_calc_opt *opt); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_status_calc_bl__pre; hIndex++) { preHookFunc = HPMHooks.list.HP_status_calc_bl__pre[hIndex].func; @@ -94304,7 +94411,7 @@ void HP_status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status HPMHooks.source.status.calc_bl_(bl, flag, opt); } if (HPMHooks.count.HP_status_calc_bl__post > 0) { - void (*postHookFunc) (struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt); + void (*postHookFunc) (struct block_list *bl, e_scb_flag flag, enum e_status_calc_opt opt); for (hIndex = 0; hIndex < HPMHooks.count.HP_status_calc_bl__post; hIndex++) { postHookFunc = HPMHooks.list.HP_status_calc_bl__post[hIndex].func; postHookFunc(bl, flag, opt); @@ -95647,6 +95754,114 @@ unsigned short HP_status_calc_luk(struct block_list *bl, struct status_change *s } return retVal___; } +int HP_status_calc_atk_percent(struct block_list *bl, struct status_change *sc) { + int hIndex = 0; + int retVal___ = 0; + if (HPMHooks.count.HP_status_calc_atk_percent_pre > 0) { + int (*preHookFunc) (struct block_list **bl, struct status_change **sc); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_calc_atk_percent_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_status_calc_atk_percent_pre[hIndex].func; + retVal___ = preHookFunc(&bl, &sc); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.status.calc_atk_percent(bl, sc); + } + if (HPMHooks.count.HP_status_calc_atk_percent_post > 0) { + int (*postHookFunc) (int retVal___, struct block_list *bl, struct status_change *sc); + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_calc_atk_percent_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_status_calc_atk_percent_post[hIndex].func; + retVal___ = postHookFunc(retVal___, bl, sc); + } + } + return retVal___; +} +int HP_status_calc_matk_percent(struct block_list *bl, struct status_change *sc) { + int hIndex = 0; + int retVal___ = 0; + if (HPMHooks.count.HP_status_calc_matk_percent_pre > 0) { + int (*preHookFunc) (struct block_list **bl, struct status_change **sc); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_calc_matk_percent_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_status_calc_matk_percent_pre[hIndex].func; + retVal___ = preHookFunc(&bl, &sc); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.status.calc_matk_percent(bl, sc); + } + if (HPMHooks.count.HP_status_calc_matk_percent_post > 0) { + int (*postHookFunc) (int retVal___, struct block_list *bl, struct status_change *sc); + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_calc_matk_percent_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_status_calc_matk_percent_post[hIndex].func; + retVal___ = postHookFunc(retVal___, bl, sc); + } + } + return retVal___; +} +int HP_status_calc_def_percent(struct block_list *bl, struct status_change *sc) { + int hIndex = 0; + int retVal___ = 0; + if (HPMHooks.count.HP_status_calc_def_percent_pre > 0) { + int (*preHookFunc) (struct block_list **bl, struct status_change **sc); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_calc_def_percent_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_status_calc_def_percent_pre[hIndex].func; + retVal___ = preHookFunc(&bl, &sc); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.status.calc_def_percent(bl, sc); + } + if (HPMHooks.count.HP_status_calc_def_percent_post > 0) { + int (*postHookFunc) (int retVal___, struct block_list *bl, struct status_change *sc); + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_calc_def_percent_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_status_calc_def_percent_post[hIndex].func; + retVal___ = postHookFunc(retVal___, bl, sc); + } + } + return retVal___; +} +int HP_status_calc_mdef_percent(struct block_list *bl, struct status_change *sc) { + int hIndex = 0; + int retVal___ = 0; + if (HPMHooks.count.HP_status_calc_mdef_percent_pre > 0) { + int (*preHookFunc) (struct block_list **bl, struct status_change **sc); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_calc_mdef_percent_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_status_calc_mdef_percent_pre[hIndex].func; + retVal___ = preHookFunc(&bl, &sc); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.status.calc_mdef_percent(bl, sc); + } + if (HPMHooks.count.HP_status_calc_mdef_percent_post > 0) { + int (*postHookFunc) (int retVal___, struct block_list *bl, struct status_change *sc); + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_calc_mdef_percent_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_status_calc_mdef_percent_post[hIndex].func; + retVal___ = postHookFunc(retVal___, bl, sc); + } + } + return retVal___; +} int HP_status_calc_watk(struct block_list *bl, struct status_change *sc, int watk, bool viewable) { int hIndex = 0; int retVal___ = 0; @@ -96106,10 +96321,10 @@ int HP_status_calc_ematk(struct block_list *bl, struct status_change *sc, int ma } return retVal___; } -void HP_status_calc_bl_main(struct block_list *bl, int flag) { +void HP_status_calc_bl_main(struct block_list *bl, e_scb_flag flag) { int hIndex = 0; if (HPMHooks.count.HP_status_calc_bl_main_pre > 0) { - void (*preHookFunc) (struct block_list **bl, int *flag); + void (*preHookFunc) (struct block_list **bl, e_scb_flag *flag); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_status_calc_bl_main_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_status_calc_bl_main_pre[hIndex].func; @@ -96124,7 +96339,7 @@ void HP_status_calc_bl_main(struct block_list *bl, int flag) { HPMHooks.source.status.calc_bl_main(bl, flag); } if (HPMHooks.count.HP_status_calc_bl_main_post > 0) { - void (*postHookFunc) (struct block_list *bl, int flag); + void (*postHookFunc) (struct block_list *bl, e_scb_flag flag); for (hIndex = 0; hIndex < HPMHooks.count.HP_status_calc_bl_main_post; hIndex++) { postHookFunc = HPMHooks.list.HP_status_calc_bl_main_post[hIndex].func; postHookFunc(bl, flag); @@ -96673,13 +96888,13 @@ bool HP_status_read_unit_params_db_additional(struct s_unit_params *entry, struc } return retVal___; } -void HP_status_unit_params_destroy(struct s_unit_params *entry) { +void HP_status_unit_params_destroy_entry(struct s_unit_params *entry) { int hIndex = 0; - if (HPMHooks.count.HP_status_unit_params_destroy_pre > 0) { + if (HPMHooks.count.HP_status_unit_params_destroy_entry_pre > 0) { void (*preHookFunc) (struct s_unit_params **entry); *HPMforce_return = false; - for (hIndex = 0; hIndex < HPMHooks.count.HP_status_unit_params_destroy_pre; hIndex++) { - preHookFunc = HPMHooks.list.HP_status_unit_params_destroy_pre[hIndex].func; + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_unit_params_destroy_entry_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_status_unit_params_destroy_entry_pre[hIndex].func; preHookFunc(&entry); } if (*HPMforce_return) { @@ -96688,17 +96903,43 @@ void HP_status_unit_params_destroy(struct s_unit_params *entry) { } } { - HPMHooks.source.status.unit_params_destroy(entry); + HPMHooks.source.status.unit_params_destroy_entry(entry); } - if (HPMHooks.count.HP_status_unit_params_destroy_post > 0) { + if (HPMHooks.count.HP_status_unit_params_destroy_entry_post > 0) { void (*postHookFunc) (struct s_unit_params *entry); - for (hIndex = 0; hIndex < HPMHooks.count.HP_status_unit_params_destroy_post; hIndex++) { - postHookFunc = HPMHooks.list.HP_status_unit_params_destroy_post[hIndex].func; + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_unit_params_destroy_entry_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_status_unit_params_destroy_entry_post[hIndex].func; postHookFunc(entry); } } return; } +void HP_status_unit_params_clear_db(void) { + int hIndex = 0; + if (HPMHooks.count.HP_status_unit_params_clear_db_pre > 0) { + void (*preHookFunc) (void); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_unit_params_clear_db_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_status_unit_params_clear_db_pre[hIndex].func; + preHookFunc(); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.status.unit_params_clear_db(); + } + if (HPMHooks.count.HP_status_unit_params_clear_db_post > 0) { + void (*postHookFunc) (void); + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_unit_params_clear_db_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_status_unit_params_clear_db_post[hIndex].func; + postHookFunc(); + } + } + return; +} void HP_status_copy(struct status_data *a, const struct status_data *b) { int hIndex = 0; if (HPMHooks.count.HP_status_copy_pre > 0) { diff --git a/tools/HPMHookGen/HPMHookGen.pl b/tools/HPMHookGen/HPMHookGen.pl index a1aa9ef1c..49f9cc6c0 100755 --- a/tools/HPMHookGen/HPMHookGen.pl +++ b/tools/HPMHookGen/HPMHookGen.pl @@ -250,6 +250,8 @@ ($$) $rtinit = ' = UNIT_DIR_UNDEFINED'; } elsif ($x =~ /^enum\s+quest_mobtype$/) { # Known enum quest_mobtype $rtinit = ' = QMT_RC_DEMIHUMAN'; + } elsif ($x =~ /^e_scb_flag$/) { # Known typedef e_scb_flag + $rtinit = ' = SCB_NONE'; } elsif ($x eq 'DBComparator' or $x eq 'DBHasher' or $x eq 'DBReleaser') { # DB function pointers $rtinit = ' = NULL'; } elsif ($x =~ /^(?:struct|union)\s+.*$/) { # Structs and unions