summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml73
-rw-r--r--.github/workflows/clang10_test.yml72
-rw-r--r--.github/workflows/gcc10_test.yml71
-rw-r--r--.github/workflows/gcc9_test.yml71
-rw-r--r--.github/workflows/mariadb.yml69
-rw-r--r--.github/workflows/mysql.yml69
-rw-r--r--conf/map/battle/pet.conf4
-rw-r--r--conf/map/battle/player.conf7
-rw-r--r--doc/constants.md6
-rw-r--r--doc/script_commands.txt16
-rw-r--r--src/char/int_party.c3
-rw-r--r--src/map/atcommand.c21
-rw-r--r--src/map/battle.c2
-rw-r--r--src/map/battle.h2
-rw-r--r--src/map/clif.c47
-rw-r--r--src/map/guild.c13
-rw-r--r--src/map/instance.c4
-rw-r--r--src/map/party.c6
-rw-r--r--src/map/pc.c6
-rw-r--r--src/map/pc.h9
-rw-r--r--src/map/pet.c131
-rw-r--r--src/map/pet.h2
-rw-r--r--src/map/script.c9
-rw-r--r--src/map/skill.c68
-rw-r--r--src/map/skill.h1
-rw-r--r--src/plugins/HPMHooking/HPMHooking.Defs.inc6
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc12
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc3
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc81
29 files changed, 793 insertions, 91 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 000000000..f136e1bdb
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,73 @@
+name: build
+
+on: [push, pull_request]
+
+env:
+ MYSQL_DATABASE: 'ragnarok'
+ MYSQL_USER: 'ragnarok'
+ MYSQL_PASSWORD: 'ragnarok'
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
+ DEBIAN_COMMON_PACKAGES: make zlib1g-dev libpcre3-dev git python
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ # gcc, clang-8, clang-9 removed for reduce number of jobs
+ CC: ["gcc-10", "clang-10"]
+ RENEWAL: [""]
+ CLIENT_TYPE: ["", "--enable-packetver-re", "--enable-packetver-zero"]
+ SANITIZER: [""]
+ PACKET_VERSION: ["--enable-packetver=20100105", "--enable-packetver=20171018"]
+ LTO: ["", "--enable-lto"]
+ exclude:
+ - PACKET_VERSION: "--enable-packetver=20100105"
+ CLIENT_TYPE: "--enable-packetver-zero"
+ - CC: "clang-10"
+ LTO: "--enable-lto"
+ container:
+ image: debian:unstable
+ services:
+ mariadb:
+ image: mariadb:latest
+ ports:
+ - 33306:3306
+ env:
+ MYSQL_DATABASE: 'ragnarok'
+ MYSQL_USER: 'ragnarok'
+ MYSQL_PASSWORD: 'ragnarok'
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
+ options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
+ env:
+ INSTALL_PACKAGES: ${{ matrix.CC }} mariadb-client libmariadbclient-dev-compat
+ SQLHOST: mariadb
+ CC: ${{ matrix.CC }}
+ CONFIGURE_FLAGS: CC=${{ matrix.CC }} --enable-debug --enable-Werror --enable-buildbot ${{ matrix.RENEWAL }} ${{ matrix.CLIENT_TYPE }} ${{ matrix.SANITIZER }} ${{ matrix.PACKET_VERSION }} --enable-epoll
+ steps:
+ - uses: actions/checkout@v1
+ with:
+ fetch-depth: 1
+
+ - name: info
+ run: |
+ uname -a
+
+ - name: install packages
+ run: |
+ ./tools/ci/retry.sh apt-get update
+ ./tools/ci/retry.sh apt-get install -y -qq $INSTALL_PACKAGES $DEBIAN_COMMON_PACKAGES
+
+ - name: init database
+ run: |
+ ./tools/ci/travis.sh importdb ragnarok ragnarok ragnarok $SQLHOST
+
+ - name: get plugins
+ run: |
+ ./tools/ci/travis.sh getplugins || true
+
+ - name: build
+ run: |
+ ./tools/ci/travis.sh build $CONFIGURE_FLAGS
+
+ # for run default config will show warnings
diff --git a/.github/workflows/clang10_test.yml b/.github/workflows/clang10_test.yml
new file mode 100644
index 000000000..28cb144f6
--- /dev/null
+++ b/.github/workflows/clang10_test.yml
@@ -0,0 +1,72 @@
+name: clang10_test
+
+on: [push, pull_request]
+
+env:
+ MYSQL_DATABASE: 'ragnarok'
+ MYSQL_USER: 'ragnarok'
+ MYSQL_PASSWORD: 'ragnarok'
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
+ DEBIAN_COMMON_PACKAGES: make zlib1g-dev libpcre3-dev git python
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ # clang-8, clang-9 removed for reduce number of jobs
+ CC: [clang-10]
+ RENEWAL: ["", "--disable-renewal"]
+ CLIENT_TYPE: ["", "--enable-packetver-re", "--enable-packetver-zero"]
+ SANITIZER: ["--disable-manager", "--disable-manager --enable-sanitize=full"]
+ PACKET_VERSION: ["--enable-packetver=20200304", "--enable-packetver=20130724"]
+ exclude:
+ - PACKET_VERSION: "--enable-packetver=20130724"
+ CLIENT_TYPE: "--enable-packetver-zero"
+ container:
+ image: debian:unstable
+ services:
+ mariadb:
+ image: mariadb:latest
+ ports:
+ - 33306:3306
+ env:
+ MYSQL_DATABASE: 'ragnarok'
+ MYSQL_USER: 'ragnarok'
+ MYSQL_PASSWORD: 'ragnarok'
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
+ options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
+ env:
+ INSTALL_PACKAGES: ${{ matrix.CC }} mariadb-client libmariadbclient-dev-compat
+ SQLHOST: mariadb
+ CC: ${{ matrix.CC }}
+ CONFIGURE_FLAGS: CC=${{ matrix.CC }} --enable-debug --enable-Werror --enable-buildbot ${{ matrix.RENEWAL }} ${{ matrix.CLIENT_TYPE }} ${{ matrix.SANITIZER }} ${{ matrix.PACKET_VERSION }}
+ steps:
+ - uses: actions/checkout@v1
+ with:
+ fetch-depth: 1
+
+ - name: info
+ run: |
+ uname -a
+
+ - name: install packages
+ run: |
+ ./tools/ci/retry.sh apt-get update
+ ./tools/ci/retry.sh apt-get install -y -qq $INSTALL_PACKAGES $DEBIAN_COMMON_PACKAGES
+
+ - name: init database
+ run: |
+ ./tools/ci/travis.sh importdb ragnarok ragnarok ragnarok $SQLHOST
+
+ - name: get plugins
+ run: |
+ ./tools/ci/travis.sh getplugins || true
+
+ - name: build
+ run: |
+ ./tools/ci/travis.sh build $CONFIGURE_FLAGS
+
+ - name: test
+ run: |
+ ./tools/ci/travis.sh test ragnarok ragnarok ragnarok $SQLHOST
diff --git a/.github/workflows/gcc10_test.yml b/.github/workflows/gcc10_test.yml
new file mode 100644
index 000000000..1b0909be8
--- /dev/null
+++ b/.github/workflows/gcc10_test.yml
@@ -0,0 +1,71 @@
+name: gcc10_test
+
+on: [push, pull_request]
+
+env:
+ MYSQL_DATABASE: 'ragnarok'
+ MYSQL_USER: 'ragnarok'
+ MYSQL_PASSWORD: 'ragnarok'
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
+ DEBIAN_COMMON_PACKAGES: make zlib1g-dev libpcre3-dev git python
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ CC: [gcc-10]
+ RENEWAL: ["", "--disable-renewal"]
+ CLIENT_TYPE: ["", "--enable-packetver-re", "--enable-packetver-zero"]
+ SANITIZER: ["--disable-manager", "--disable-manager --enable-sanitize=full"]
+ PACKET_VERSION: ["--enable-packetver=20200304", "--enable-packetver=20130724"]
+ exclude:
+ - PACKET_VERSION: "--enable-packetver=20130724"
+ CLIENT_TYPE: "--enable-packetver-zero"
+ container:
+ image: debian:unstable
+ services:
+ mariadb:
+ image: mariadb:latest
+ ports:
+ - 33306:3306
+ env:
+ MYSQL_DATABASE: 'ragnarok'
+ MYSQL_USER: 'ragnarok'
+ MYSQL_PASSWORD: 'ragnarok'
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
+ options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
+ env:
+ INSTALL_PACKAGES: ${{ matrix.CC }} mariadb-client libmariadbclient-dev-compat
+ SQLHOST: mariadb
+ CC: ${{ matrix.CC }}
+ CONFIGURE_FLAGS: CC=${{ matrix.CC }} --enable-debug --enable-Werror --enable-buildbot ${{ matrix.RENEWAL }} ${{ matrix.CLIENT_TYPE }} ${{ matrix.SANITIZER }} ${{ matrix.PACKET_VERSION }} --enable-lto
+ steps:
+ - uses: actions/checkout@v1
+ with:
+ fetch-depth: 1
+
+ - name: info
+ run: |
+ uname -a
+
+ - name: install packages
+ run: |
+ ./tools/ci/retry.sh apt-get update
+ ./tools/ci/retry.sh apt-get install -y -qq $INSTALL_PACKAGES $DEBIAN_COMMON_PACKAGES
+
+ - name: init database
+ run: |
+ ./tools/ci/travis.sh importdb ragnarok ragnarok ragnarok $SQLHOST
+
+ - name: get plugins
+ run: |
+ ./tools/ci/travis.sh getplugins || true
+
+ - name: build
+ run: |
+ ./tools/ci/travis.sh build $CONFIGURE_FLAGS
+
+ - name: test
+ run: |
+ ./tools/ci/travis.sh test ragnarok ragnarok ragnarok $SQLHOST
diff --git a/.github/workflows/gcc9_test.yml b/.github/workflows/gcc9_test.yml
new file mode 100644
index 000000000..4e9dc9bd9
--- /dev/null
+++ b/.github/workflows/gcc9_test.yml
@@ -0,0 +1,71 @@
+name: gcc9_test
+
+on: [push, pull_request]
+
+env:
+ MYSQL_DATABASE: 'ragnarok'
+ MYSQL_USER: 'ragnarok'
+ MYSQL_PASSWORD: 'ragnarok'
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
+ DEBIAN_COMMON_PACKAGES: make zlib1g-dev libpcre3-dev git python
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ CC: [gcc]
+ RENEWAL: ["", "--disable-renewal"]
+ CLIENT_TYPE: ["", "--enable-packetver-re", "--enable-packetver-zero"]
+ SANITIZER: ["--disable-manager", "--disable-manager --enable-sanitize=full"]
+ PACKET_VERSION: ["--enable-packetver=20200304", "--enable-packetver=20130724"]
+ exclude:
+ - PACKET_VERSION: "--enable-packetver=20130724"
+ CLIENT_TYPE: "--enable-packetver-zero"
+ container:
+ image: debian:unstable
+ services:
+ mariadb:
+ image: mariadb:latest
+ ports:
+ - 33306:3306
+ env:
+ MYSQL_DATABASE: 'ragnarok'
+ MYSQL_USER: 'ragnarok'
+ MYSQL_PASSWORD: 'ragnarok'
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
+ options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
+ env:
+ INSTALL_PACKAGES: ${{ matrix.CC }} mariadb-client libmariadbclient-dev-compat
+ SQLHOST: mariadb
+ CC: ${{ matrix.CC }}
+ CONFIGURE_FLAGS: CC=${{ matrix.CC }} --enable-debug --enable-Werror --enable-buildbot ${{ matrix.RENEWAL }} ${{ matrix.CLIENT_TYPE }} ${{ matrix.SANITIZER }} ${{ matrix.PACKET_VERSION }} --enable-lto
+ steps:
+ - uses: actions/checkout@v1
+ with:
+ fetch-depth: 1
+
+ - name: info
+ run: |
+ uname -a
+
+ - name: install packages
+ run: |
+ ./tools/ci/retry.sh apt-get update
+ ./tools/ci/retry.sh apt-get install -y -qq $INSTALL_PACKAGES $DEBIAN_COMMON_PACKAGES
+
+ - name: init database
+ run: |
+ ./tools/ci/travis.sh importdb ragnarok ragnarok ragnarok $SQLHOST
+
+ - name: get plugins
+ run: |
+ ./tools/ci/travis.sh getplugins || true
+
+ - name: build
+ run: |
+ ./tools/ci/travis.sh build $CONFIGURE_FLAGS
+
+ - name: test
+ run: |
+ ./tools/ci/travis.sh test ragnarok ragnarok ragnarok $SQLHOST
diff --git a/.github/workflows/mariadb.yml b/.github/workflows/mariadb.yml
new file mode 100644
index 000000000..4479e9e4d
--- /dev/null
+++ b/.github/workflows/mariadb.yml
@@ -0,0 +1,69 @@
+name: mariadb
+
+on: [push, pull_request]
+
+env:
+ MYSQL_DATABASE: 'ragnarok'
+ MYSQL_USER: 'ragnarok'
+ MYSQL_PASSWORD: 'ragnarok'
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
+ DEBIAN_COMMON_PACKAGES: make zlib1g-dev libpcre3-dev git python
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ CC: [gcc]
+ RENEWAL: [""]
+ CLIENT_TYPE: [""]
+ SANITIZER: ["--disable-manager", "--enable-sanitize=full"]
+ PACKET_VERSION: ["--enable-packetver=20200304"]
+ MYSQL: ["10.1", "10.5", "latest"]
+ container:
+ image: debian:unstable
+ services:
+ mysql:
+ image: mariadb:${{ matrix.MYSQL }}
+ ports:
+ - 33306:3306
+ env:
+ MYSQL_DATABASE: 'ragnarok'
+ MYSQL_USER: 'ragnarok'
+ MYSQL_PASSWORD: 'ragnarok'
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
+ options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
+ env:
+ INSTALL_PACKAGES: ${{ matrix.CC }} mariadb-client libmariadbclient-dev-compat
+ SQLHOST: mysql
+ CC: ${{ matrix.CC }}
+ CONFIGURE_FLAGS: CC=${{ matrix.CC }} --enable-debug --enable-Werror --enable-buildbot ${{ matrix.RENEWAL }} ${{ matrix.CLIENT_TYPE }} ${{ matrix.SANITIZER }} ${{ matrix.PACKET_VERSION }}
+ steps:
+ - uses: actions/checkout@v1
+ with:
+ fetch-depth: 1
+
+ - name: info
+ run: |
+ uname -a
+
+ - name: install packages
+ run: |
+ ./tools/ci/retry.sh apt-get update
+ ./tools/ci/retry.sh apt-get install -y -qq $INSTALL_PACKAGES $DEBIAN_COMMON_PACKAGES
+
+ - name: init database
+ run: |
+ ./tools/ci/travis.sh importdb ragnarok ragnarok ragnarok $SQLHOST
+
+ - name: get plugins
+ run: |
+ ./tools/ci/travis.sh getplugins || true
+
+ - name: build
+ run: |
+ ./tools/ci/travis.sh build $CONFIGURE_FLAGS
+
+ - name: test
+ run: |
+ ./tools/ci/travis.sh test ragnarok ragnarok ragnarok $SQLHOST
diff --git a/.github/workflows/mysql.yml b/.github/workflows/mysql.yml
new file mode 100644
index 000000000..98e760a87
--- /dev/null
+++ b/.github/workflows/mysql.yml
@@ -0,0 +1,69 @@
+name: mysql
+
+on: [push, pull_request]
+
+env:
+ MYSQL_DATABASE: 'ragnarok'
+ MYSQL_USER: 'ragnarok'
+ MYSQL_PASSWORD: 'ragnarok'
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
+ DEBIAN_COMMON_PACKAGES: make zlib1g-dev libpcre3-dev git python
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ CC: [gcc]
+ RENEWAL: [""]
+ CLIENT_TYPE: [""]
+ SANITIZER: ["--disable-manager", "--enable-sanitize=full"]
+ PACKET_VERSION: ["--enable-packetver=20200304"]
+ MYSQL: ["5.6", "5.7"]
+ container:
+ image: debian:unstable
+ services:
+ mysql:
+ image: mysql:${{ matrix.MYSQL }}
+ ports:
+ - 33306:3306
+ env:
+ MYSQL_DATABASE: 'ragnarok'
+ MYSQL_USER: 'ragnarok'
+ MYSQL_PASSWORD: 'ragnarok'
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
+ options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
+ env:
+ INSTALL_PACKAGES: ${{ matrix.CC }} mysql-client libmysqlclient-dev
+ SQLHOST: mysql
+ CC: ${{ matrix.CC }}
+ CONFIGURE_FLAGS: CC=${{ matrix.CC }} --enable-debug --enable-Werror --enable-buildbot ${{ matrix.RENEWAL }} ${{ matrix.CLIENT_TYPE }} ${{ matrix.SANITIZER }} ${{ matrix.PACKET_VERSION }}
+ steps:
+ - uses: actions/checkout@v1
+ with:
+ fetch-depth: 1
+
+ - name: info
+ run: |
+ uname -a
+
+ - name: install packages
+ run: |
+ ./tools/ci/retry.sh apt-get update
+ ./tools/ci/retry.sh apt-get install -y -qq $INSTALL_PACKAGES $DEBIAN_COMMON_PACKAGES
+
+ - name: init database
+ run: |
+ ./tools/ci/travis.sh importdb ragnarok ragnarok ragnarok $SQLHOST
+
+ - name: get plugins
+ run: |
+ ./tools/ci/travis.sh getplugins || true
+
+ - name: build
+ run: |
+ ./tools/ci/travis.sh build $CONFIGURE_FLAGS
+
+ - name: test
+ run: |
+ ./tools/ci/travis.sh test ragnarok ragnarok ragnarok $SQLHOST
diff --git a/conf/map/battle/pet.conf b/conf/map/battle/pet.conf
index 5797bb2a5..3060b6e64 100644
--- a/conf/map/battle/pet.conf
+++ b/conf/map/battle/pet.conf
@@ -99,3 +99,7 @@ pet_max_atk2: 1000
// If set to true, pets are automatically returned to egg when entering castles during WoE times
// and hatching is forbidden within as well.
pet_disable_in_gvg: false
+
+// Should the pet immediately be removed when its intimacy drops to 0? (Note 1)
+// If set to false the pet will randomly walk around the map before being removed.
+pet_remove_immediately: true
diff --git a/conf/map/battle/player.conf b/conf/map/battle/player.conf
index c25159717..e30c3c134 100644
--- a/conf/map/battle/player.conf
+++ b/conf/map/battle/player.conf
@@ -226,3 +226,10 @@ shadow_refine_atk: true
// Keep player facing direction after warping?
// Default: false (on official servers players always faces north)
player_warp_keep_direction: false
+
+// Can dead players do actions like trading, open a chat room, etc.?
+// 0x0 - Don't allow trading and open chat rooms.
+// 0x1 - Allow trading when dead.
+// 0x2 - Allow open chat room when dead.
+// default: 0x3 (Official)
+allowed_actions_when_dead: 0x3
diff --git a/doc/constants.md b/doc/constants.md
index c44654b71..dde1647b3 100644
--- a/doc/constants.md
+++ b/doc/constants.md
@@ -5154,6 +5154,12 @@
- `P_AIRSHIP_ITEM_NOT_ENOUGH`: 2
- `P_AIRSHIP_ITEM_INVALID`: 5
+### player allowed actions when dead
+
+- `PCALLOWACTION_NONE`: 0
+- `PCALLOWACTION_TRADE`: 1
+- `PCALLOWACTION_CHAT`: 2
+
### questinfo types
- `QINFO_JOB`: 0
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index 2fc6a95e5..db37ef284 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -9664,13 +9664,19 @@ For examples of usage, see /doc/sample/npc_rodex.txt
//=====================================
---------------------------------------
-*instance_create("<instance name>", <owner id>{, <optional owner_type>})
+*instance_create("<instance_name>", <owner_id>{, <owner_type>})
-Create an instance using the name "<instance name>" for the <owner_id> of
-owner_type (when not provided, defaults to IOT_PARTY). Most instance_*
+Creates an instance using the name "<instance_name>" for the <owner_id> of
+<owner_type> (when not provided, defaults to IOT_PARTY). Most instance_*
commands are used in conjunction with this command and depend on the
ID this command returns.
+Valid <owner_type> values:
+- IOT_NONE (0) - <owner_id> can be any arbitrary number.
+- IOT_CHAR (1) - <owner_id> is account ID.
+- IOT_PARTY (2) - <owner_id> is party ID.
+- IOT_GUILD (3) - <owner_id> is guild ID.
+
Example:
// Store the Party ID of the invoking character.
.@party_id = getcharid(CHAR_ID_PARTY);
@@ -9681,11 +9687,9 @@ Example:
// ...
} else if (.@id == -2) { // Invalid Party ID
// ...
- } else if (.@id == -3) { // No free instances (MAX_INSTANCE exceeded)
- // ...
} else if (.@id == -4) { // Already exists
// ...
- } else (.@id < 0) { // Unspecified error while queuing instance.
+ } else if (.@id < 0) { // Unspecified error while queuing instance.
// ...
}
diff --git a/src/char/int_party.c b/src/char/int_party.c
index c16eea34e..62633b4a8 100644
--- a/src/char/int_party.c
+++ b/src/char/int_party.c
@@ -67,6 +67,7 @@ static int inter_party_check_lv(struct party_data *p)
if (p->party.exp == 1 && inter_party->check_exp_share(p) == 0) {
p->party.exp = 0;
mapif->party_optionchanged(0, &p->party, 0, 0);
+ inter_party->tosql(&p->party, PS_BASIC, 0);
return 0;
}
@@ -577,9 +578,9 @@ static bool inter_party_leave(int party_id, int account_id, int char_id)
if (p->party.member[i].online == 1)
p->party.member[i].online = 0;
+ inter_party->tosql(&p->party, PS_DELMEMBER, i);
memset(&p->party.member[i], 0, sizeof(struct party_member));
inter_party->calc_state(p); /// Count online/offline members and check family state and even share range.
- inter_party->tosql(&p->party, PS_DELMEMBER, i);
if (inter_party->check_empty(p) == 0)
mapif->party_info(-1, &p->party, 0);
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 76448b237..9d5c601bf 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -2810,10 +2810,8 @@ ACMD(petfriendly)
return false;
}
- if (friendly != pd->pet.intimate) { // No need to update the pet's status if intimacy value won't change.
+ if (friendly != pd->pet.intimate) // No need to update the pet's status if intimacy value won't change.
pet->set_intimate(pd, friendly);
- clif->send_petstatus(sd);
- }
clif->message(fd, msg_fd(fd, 182)); // Pet intimacy changed. (Send message regardless of value has changed or not.)
@@ -2854,10 +2852,8 @@ ACMD(pethungry)
return false;
}
- if (hungry != pd->pet.hungry) { // No need to update the pet's status if hunger value won't change.
- pd->pet.hungry = hungry;
- clif->send_petstatus(sd);
- }
+ if (hungry != pd->pet.hungry) // No need to update the pet's status if hunger value won't change.
+ pet->set_hunger(pd, hungry);
clif->message(fd, msg_fd(fd, 185)); // Pet hunger changed. (Send message regardless of value has changed or not.)
@@ -2881,6 +2877,15 @@ ACMD(petrename)
}
pd->pet.rename_flag = 0;
+
+ int i;
+
+ ARR_FIND(0, sd->status.inventorySize, i, sd->status.inventory[i].card[0] == CARD0_PET
+ && pd->pet.pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2]));
+
+ if (i != sd->status.inventorySize)
+ sd->status.inventory[i].card[3] = pet->get_card4_value(pd->pet.rename_flag, pd->pet.intimate);
+
intif->save_petdata(sd->status.account_id, &pd->pet);
clif->send_petstatus(sd);
clif->message(fd, msg_fd(fd,187)); // You can now rename your pet.
@@ -8562,7 +8567,7 @@ ACMD(itemlist)
if( it->card[0] == CARD0_PET ) {
// pet egg
- if (it->card[3])
+ if ((it->card[3] & 1) != 0)
StrBuf->Printf(&buf, msg_fd(fd,1348), (unsigned int)MakeDWord(it->card[1], it->card[2])); // -> (pet egg, pet id: %u, named)
else
StrBuf->Printf(&buf, msg_fd(fd,1349), (unsigned int)MakeDWord(it->card[1], it->card[2])); // -> (pet egg, pet id: %u, unnamed)
diff --git a/src/map/battle.c b/src/map/battle.c
index 611154953..40a7c4b09 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -7101,6 +7101,7 @@ static const struct battle_data {
{ "pet_max_atk1", &battle_config.pet_max_atk1, 750, 0, INT_MAX, },
{ "pet_max_atk2", &battle_config.pet_max_atk2, 1000, 0, INT_MAX, },
{ "pet_disable_in_gvg", &battle_config.pet_no_gvg, 0, 0, 1, },
+ { "pet_remove_immediately", &battle_config.pet_remove_immediately, 1, 0, 1, },
{ "skill_min_damage", &battle_config.skill_min_damage, 2|4, 0, 1|2|4, },
{ "finger_offensive_type", &battle_config.finger_offensive_type, 0, 0, 1, },
{ "heal_exp", &battle_config.heal_exp, 0, 0, INT_MAX, },
@@ -7449,6 +7450,7 @@ static const struct battle_data {
{ "hit_max_limit", &battle_config.hit_max, SHRT_MAX, 1, INT_MAX, },
{ "autoloot_adjust", &battle_config.autoloot_adjust, 0, 0, 1, },
{ "hom_bonus_exp_from_master", &battle_config.hom_bonus_exp_from_master, 10, 0, 100, },
+ { "allowed_actions_when_dead", &battle_config.allowed_actions_when_dead, 0, 0, 3, },
};
static bool battle_set_value_sub(int index, int value)
diff --git a/src/map/battle.h b/src/map/battle.h
index 55ee32445..2db890a42 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -230,6 +230,7 @@ struct Battle_Config {
int pet_max_atk2; //[Skotlex]
int pet_no_gvg; //Disables pets in gvg. [Skotlex]
int pet_equip_required;
+ int pet_remove_immediately;
int skill_min_damage;
int finger_offensive_type;
@@ -609,6 +610,7 @@ struct Battle_Config {
int hit_max;
int autoloot_adjust;
+ int allowed_actions_when_dead;
};
/* criteria for battle_config.idletime_critera */
diff --git a/src/map/clif.c b/src/map/clif.c
index 649df3e33..345547ce5 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -2519,8 +2519,8 @@ static void clif_addcards(struct EQUIPSLOTINFO *buf, struct item *item)
if (item->card[0] == CARD0_PET) { //pet eggs
buf->card[0] = 0;
buf->card[1] = 0;
- buf->card[2] = 0;
- buf->card[3] = item->card[3]; //Pet renamed flag.
+ buf->card[2] = (item->card[3] >> 1); // Pet intimacy level.
+ buf->card[3] = (item->card[3] & 1); // Pet renamed flag.
return;
}
if (item->card[0] == CARD0_FORGE || item->card[0] == CARD0_CREATE) { //Forged/created items
@@ -10806,10 +10806,7 @@ static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd)
clif->message(sd->fd, msg_sd(sd, 866)); // "Pets are not allowed in Guild Wars."
pet->menu(sd, 3); // Option 3 is return to egg.
} else {
- map->addblock(&sd->pd->bl);
- clif->spawn(&sd->pd->bl);
- clif->send_petdata(sd,sd->pd, 0, 0);
- clif->send_petstatus(sd);
+ pet->spawn(sd, false);
}
}
@@ -11067,6 +11064,19 @@ static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd)
#if PACKETVER >= 20090218
quest->questinfo_refresh(sd); // NPC quest/event icon check. [Kisuka]
#endif
+
+ if (first_time) {
+ int i;
+
+ ARR_FIND(0, instance->instances, i, instance->list[i].owner_type == IOT_CHAR && instance->list[i].owner_id == sd->status.account_id);
+
+ if (i < instance->instances) {
+ sd->instances = 1;
+ CREATE(sd->instance, short, 1);
+ sd->instance[0] = instance->list[i].id;
+ clif->instance_join(sd->fd, instance->list[i].id);
+ }
+ }
}
/// Server's tick (ZC_NOTIFY_TIME).
@@ -12295,7 +12305,7 @@ static void clif_parse_CreateChatRoom(int fd, struct map_session_data *sd) __att
/// 1 = public
static void clif_parse_CreateChatRoom(int fd, struct map_session_data *sd)
{
- if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ if (sd->state.trading || (pc_isdead(sd) && (battle_config.allowed_actions_when_dead & PCALLOWACTION_CHAT) == 0) || pc_isvending(sd))
return;
int len = (int)RFIFOW(fd, 2) - 15;
@@ -12343,7 +12353,7 @@ static void clif_parse_ChatAddMember(int fd, struct map_session_data *sd) __attr
/// 00d9 <chat ID>.L <passwd>.8B
static void clif_parse_ChatAddMember(int fd, struct map_session_data *sd)
{
- if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ if (sd->state.trading || (pc_isdead(sd) && (battle_config.allowed_actions_when_dead & PCALLOWACTION_CHAT) == 0) || pc_isvending(sd))
return;
int chatid = RFIFOL(fd,2);
@@ -12360,7 +12370,7 @@ static void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data *sd)
/// 1 = public
static void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data *sd)
{
- if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ if (sd->state.trading || (pc_isdead(sd) && (battle_config.allowed_actions_when_dead & PCALLOWACTION_CHAT) == 0) || pc_isvending(sd))
return;
int len = (int)RFIFOW(fd, 2) - 15;
@@ -12395,7 +12405,7 @@ static void clif_parse_ChangeChatOwner(int fd, struct map_session_data *sd) __at
/// 1 = normal
static void clif_parse_ChangeChatOwner(int fd, struct map_session_data *sd)
{
- if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ if (sd->state.trading || (pc_isdead(sd) && (battle_config.allowed_actions_when_dead & PCALLOWACTION_CHAT) == 0) || pc_isvending(sd))
return;
chat->change_owner(sd, RFIFOP(fd,6)); // non null terminated
@@ -12406,7 +12416,7 @@ static void clif_parse_KickFromChat(int fd, struct map_session_data *sd) __attri
/// 00e2 <name>.24B
static void clif_parse_KickFromChat(int fd, struct map_session_data *sd)
{
- if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ if (sd->state.trading || (pc_isdead(sd) && (battle_config.allowed_actions_when_dead & PCALLOWACTION_CHAT) == 0) || pc_isvending(sd))
return;
chat->kick(sd, RFIFOP(fd,2)); // non null terminated
@@ -12417,7 +12427,7 @@ static void clif_parse_ChatLeave(int fd, struct map_session_data *sd) __attribut
/// 00e3
static void clif_parse_ChatLeave(int fd, struct map_session_data *sd)
{
- if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ if (sd->state.trading || (pc_isdead(sd) && (battle_config.allowed_actions_when_dead & PCALLOWACTION_CHAT) == 0) || pc_isvending(sd))
return;
chat->leave(sd, false);
@@ -12444,7 +12454,7 @@ static void clif_parse_TradeRequest(int fd, struct map_session_data *sd) __attri
/// 00e4 <account id>.L
static void clif_parse_TradeRequest(int fd, struct map_session_data *sd)
{
- if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ if (sd->state.trading || (pc_isdead(sd) && (battle_config.allowed_actions_when_dead & PCALLOWACTION_TRADE) == 0) || pc_isvending(sd))
return;
struct map_session_data *t_sd = map->id2sd(RFIFOL(fd, 2));
@@ -12474,7 +12484,7 @@ static void clif_parse_TradeAck(int fd, struct map_session_data *sd) __attribute
/// 4 = rejected
static void clif_parse_TradeAck(int fd, struct map_session_data *sd)
{
- if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ if (sd->state.trading || (pc_isdead(sd) && (battle_config.allowed_actions_when_dead & PCALLOWACTION_TRADE) == 0) || pc_isvending(sd))
return;
trade->ack(sd,RFIFOB(fd,2));
@@ -12485,7 +12495,7 @@ static void clif_parse_TradeAddItem(int fd, struct map_session_data *sd) __attri
/// 00e8 <index>.W <amount>.L
static void clif_parse_TradeAddItem(int fd, struct map_session_data *sd)
{
- if (!sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ if (sd->state.trading == 0 || (pc_isdead(sd) && (battle_config.allowed_actions_when_dead & PCALLOWACTION_TRADE) == 0) || pc_isvending(sd))
return;
short index = RFIFOW(fd,2);
@@ -12502,8 +12512,9 @@ static void clif_parse_TradeOk(int fd, struct map_session_data *sd) __attribute_
/// 00eb
static void clif_parse_TradeOk(int fd, struct map_session_data *sd)
{
- if (pc_isdead(sd) || pc_isvending(sd))
+ if ((pc_isdead(sd) && (battle_config.allowed_actions_when_dead & PCALLOWACTION_TRADE) == 0) || pc_isvending(sd))
return;
+
trade->ok(sd);
}
@@ -12512,7 +12523,7 @@ static void clif_parse_TradeCancel(int fd, struct map_session_data *sd) __attrib
/// 00ed
static void clif_parse_TradeCancel(int fd, struct map_session_data *sd)
{
- if (pc_isdead(sd) || pc_isvending(sd))
+ if ((pc_isdead(sd) && (battle_config.allowed_actions_when_dead & PCALLOWACTION_TRADE) == 0) || pc_isvending(sd))
return;
trade->cancel(sd);
@@ -12523,7 +12534,7 @@ static void clif_parse_TradeCommit(int fd, struct map_session_data *sd) __attrib
/// 00ef
static void clif_parse_TradeCommit(int fd, struct map_session_data *sd)
{
- if (pc_isdead(sd) || pc_isvending(sd))
+ if ((pc_isdead(sd) && (battle_config.allowed_actions_when_dead & PCALLOWACTION_TRADE) == 0) || pc_isvending(sd))
return;
trade->commit(sd);
diff --git a/src/map/guild.c b/src/map/guild.c
index 90f870f1c..a78ea169c 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -887,6 +887,12 @@ static void guild_member_joined(struct map_session_data *sd)
channel->join(g->channel, sd, "", true);
}
+ for (int j = 0; j < g->instances; j++) {
+ if (g->instance[j] >= 0) {
+ clif->instance_join(sd->fd, g->instance[j]);
+ break;
+ }
+ }
}
}
@@ -940,6 +946,13 @@ static int guild_member_added(int guild_id, int account_id, int char_id, int fla
channel->join(g->channel, sd, "", true);
}
+ for (int i = 0; i < g->instances; i++) {
+ if (g->instance[i] >= 0) {
+ clif->instance_join(sd->fd, g->instance[i]);
+ break;
+ }
+ }
+
return 0;
}
diff --git a/src/map/instance.c b/src/map/instance.c
index 1104b7e88..d2c0a229c 100644
--- a/src/map/instance.c
+++ b/src/map/instance.c
@@ -68,7 +68,7 @@ static bool instance_is_valid(int instance_id)
/*--------------------------------------
* name : instance name
* Return value could be
- * -4 = already exists | -3 = no free instances | -2 = owner not found | -1 = invalid type
+ * -4 = already exists | -2 = owner not found | -1 = invalid type
* On success return instance_id
*--------------------------------------*/
static int instance_create(int owner_id, const char *name, enum instance_owner_type type)
@@ -734,7 +734,7 @@ static void instance_force_destroy(struct map_session_data *sd)
switch (instance->list[i].owner_type) {
case IOT_CHAR:
{
- if (instance->list[i].owner_id != sd->status.char_id)
+ if (instance->list[i].owner_id != sd->status.account_id)
continue;
break;
}
diff --git a/src/map/party.c b/src/map/party.c
index 8eeae2215..a6f6b7774 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -353,8 +353,6 @@ static int party_recv_info(const struct party *sp, int char_id)
clif->party_info(p,NULL);
for( j = 0; j < p->instances; j++ ) {
if( p->instance[j] >= 0 ) {
- if( instance->list[p->instance[j]].idle_timer == INVALID_TIMER && instance->list[p->instance[j]].progress_timer == INVALID_TIMER )
- continue;
clif->instance_join(sd->fd, p->instance[j]);
break;
}
@@ -488,8 +486,6 @@ static void party_member_joined(struct map_session_data *sd)
p->data[i].sd = sd;
for( j = 0; j < p->instances; j++ ) {
if( p->instance[j] >= 0 ) {
- if( instance->list[p->instance[j]].idle_timer == INVALID_TIMER && instance->list[p->instance[j]].progress_timer == INVALID_TIMER )
- continue;
clif->instance_join(sd->fd, p->instance[j]);
break;
}
@@ -551,8 +547,6 @@ static int party_member_added(int party_id, int account_id, int char_id, int fla
for( j = 0; j < p->instances; j++ ) {
if( p->instance[j] >= 0 ) {
- if( instance->list[p->instance[j]].idle_timer == INVALID_TIMER && instance->list[p->instance[j]].progress_timer == INVALID_TIMER )
- continue;
clif->instance_join(sd->fd, p->instance[j]);
break;
}
diff --git a/src/map/pc.c b/src/map/pc.c
index c1261c839..ad669c0c8 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -8148,12 +8148,10 @@ static int pc_dead(struct map_session_data *sd, struct block_list *src)
if (sd->status.pet_id > 0 && sd->pd != NULL) {
struct pet_data *pd = sd->pd;
- if (map->list[sd->bl.m].flag.noexppenalty == 0) {
+ if (map->list[sd->bl.m].flag.noexppenalty == 0)
pet->set_intimate(pd, pd->pet.intimate - pd->petDB->die);
- clif->send_petdata(sd, sd->pd, 1, pd->pet.intimate);
- }
- if (sd->pd->target_id != 0) // Unlock all targets.
+ if (sd->pd != NULL && sd->pd->target_id != 0) // Unlock all targets.
pet->unlocktarget(sd->pd);
}
diff --git a/src/map/pc.h b/src/map/pc.h
index f2e911af3..6b83a7b91 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -727,6 +727,9 @@ END_ZEROED_BLOCK;
/// Rune Knight Dragon
#define pc_isridingdragon(sd) ( (sd)->sc.option&OPTION_DRAGON )
+// Check if character has a pet.
+#define pc_has_pet(sd) ( (sd)->status.pet_id != 0 && (sd)->pd != NULL && (sd)->pd->pet.intimate > PET_INTIMACY_NONE )
+
#define pc_stop_walking(sd, type) (unit->stop_walking(&(sd)->bl, (type)))
#define pc_stop_attack(sd) (unit->stop_attack(&(sd)->bl))
@@ -873,6 +876,12 @@ struct class_exp_tables {
struct class_exp_group *class_exp_table[CLASS_COUNT][2];
};
+enum player_actions_when_dead_flags {
+ PCALLOWACTION_NONE = 0x0, // Don't allow trading and open chat rooms.
+ PCALLOWACTION_TRADE = 0x1, // Allow trading when dead.
+ PCALLOWACTION_CHAT = 0x2, // Allow open chat room when dead.
+};
+
/*=====================================
* Interface : pc.h
* Generated by HerculesInterfaceMaker
diff --git a/src/map/pet.c b/src/map/pet.c
index 2a9831ed6..f10c55f57 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -94,8 +94,41 @@ static int pet_hungry_val(struct pet_data *pd)
static void pet_set_hunger(struct pet_data *pd, int value)
{
nullpo_retv(pd);
+ nullpo_retv(pd->msd);
pd->pet.hungry = cap_value(value, PET_HUNGER_STARVING, PET_HUNGER_STUFFED);
+
+ clif->send_petdata(pd->msd, pd, 2, pd->pet.hungry);
+}
+
+/**
+ * Calculates the value to store in a pet egg's 4th card slot
+ * based on the passed rename flag and intimacy value.
+ *
+ * @param rename_flag The pet's rename flag.
+ * @param intimacy The pet's intimacy value.
+ * @return The value to store in the pet egg's 4th card slot. (Defaults to 0 in case of error.)
+ *
+ **/
+static int pet_get_card4_value(int rename_flag, int intimacy)
+{
+ Assert_ret(rename_flag == 0 || rename_flag == 1);
+ Assert_ret(intimacy >= PET_INTIMACY_NONE && intimacy <= PET_INTIMACY_MAX);
+
+ int card4 = rename_flag;
+
+ if (intimacy <= PET_INTIMACY_SHY)
+ card4 |= (1 << 1);
+ else if (intimacy <= PET_INTIMACY_NEUTRAL)
+ card4 |= (2 << 1);
+ else if (intimacy <= PET_INTIMACY_CORDIAL)
+ card4 |= (3 << 1);
+ else if (intimacy <= PET_INTIMACY_LOYAL)
+ card4 |= (4 << 1);
+ else
+ card4 |= (5 << 1);
+
+ return card4;
}
/**
@@ -115,18 +148,24 @@ static void pet_set_intimate(struct pet_data *pd, int value)
struct map_session_data *sd = pd->msd;
- status_calc_pc(sd, SCO_NONE);
-
- if (pd->pet.intimate == PET_INTIMACY_NONE) { /// Pet is lost. Delete the egg.
+ if (pd->pet.intimate == PET_INTIMACY_NONE) { // Pet is lost, delete it.
int i;
ARR_FIND(0, sd->status.inventorySize, i, sd->status.inventory[i].card[0] == CARD0_PET
- && pd->pet.pet_id == MakeDWord(sd->status.inventory[i].card[1],
- sd->status.inventory[i].card[2]));
+ && pd->pet.pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2]));
if (i != sd->status.inventorySize)
pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_EGG);
+
+ if (battle_config.pet_remove_immediately != 0) {
+ pet_stop_attack(pd);
+ unit->remove_map(&pd->bl, CLR_OUTSIGHT, ALC_MARK);
+ }
+ } else {
+ clif->send_petdata(sd, pd, 1, pd->pet.intimate);
}
+
+ status_calc_pc(sd, SCO_NONE);
}
/**
@@ -312,17 +351,15 @@ static int pet_hungry(int tid, int64 tick, int id, intptr_t data)
pet_stop_attack(pd);
pet->set_intimate(pd, pd->pet.intimate - pd->petDB->starving_decrement);
- if (pd->pet.intimate == PET_INTIMACY_NONE)
- pd->status.speed = pd->db->status.speed;
+ if (sd->pd == NULL)
+ return 0;
status_calc_pet(pd, SCO_NONE);
- clif->send_petdata(sd, pd, 1, pd->pet.intimate);
if (pd->petDB->starving_delay > 0)
interval = pd->petDB->starving_delay;
}
- clif->send_petdata(sd, pd, 2, pd->pet.hungry);
interval = interval * battle_config.pet_hungry_delay_rate / 100;
pd->pet_hungry_timer = timer->add(tick + max(interval, 1), pet->hungry, sd->bl.id, 0);
@@ -404,7 +441,8 @@ static int pet_return_egg(struct map_session_data *sd, struct pet_data *pd)
if (i != sd->status.inventorySize) {
sd->status.inventory[i].attribute &= ~ATTR_BROKEN;
sd->status.inventory[i].bound = IBT_NONE;
- sd->status.inventory[i].card[3] = pd->pet.rename_flag;
+ sd->status.inventory[i].card[3] = pet->get_card4_value(pd->pet.rename_flag, pd->pet.intimate);
+ clif->inventoryList(sd);
} else {
// The pet egg wasn't found: it was probably hatched with the old system that deleted the egg.
struct item tmp_item = {0};
@@ -415,14 +453,13 @@ static int pet_return_egg(struct map_session_data *sd, struct pet_data *pd)
tmp_item.card[0] = CARD0_PET;
tmp_item.card[1] = GetWord(pd->pet.pet_id, 0);
tmp_item.card[2] = GetWord(pd->pet.pet_id, 1);
- tmp_item.card[3] = pd->pet.rename_flag;
+ tmp_item.card[3] = pet->get_card4_value(pd->pet.rename_flag, pd->pet.intimate);
if ((flag = pc->additem(sd, &tmp_item, 1, LOG_TYPE_EGG)) != 0) {
clif->additem(sd, 0, 0, flag);
map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
}
#if PACKETVER >= 20180704
- clif->inventoryList(sd);
clif->send_petdata(sd, pd, 6, 0);
#endif
pd->pet.incubate = 1;
@@ -511,6 +548,35 @@ static int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo)
return 0;
}
+/**
+ * Spawns a pet.
+ *
+ * @param sd The pet's master.
+ * @param birth_process Whether the pet is spawned during birth process.
+ * @return 1 on failure, 0 on success.
+ *
+ **/
+static int pet_spawn(struct map_session_data *sd, bool birth_process)
+{
+ nullpo_retr(1, sd);
+ nullpo_retr(1, sd->pd);
+
+ if (map->addblock(&sd->pd->bl) != 0 || !clif->spawn(&sd->pd->bl))
+ return 1;
+
+ clif->send_petdata(sd, sd->pd, 0, 0);
+ clif->send_petdata(sd, sd->pd, 5, battle_config.pet_hair_style);
+
+#if PACKETVER >= 20180704
+ if (birth_process)
+ clif->send_petdata(sd, sd->pd, 6, 1);
+#endif
+
+ clif->send_petstatus(sd);
+
+ return 0;
+}
+
static int pet_birth_process(struct map_session_data *sd, struct s_pet *petinfo)
{
nullpo_retr(1, sd);
@@ -535,17 +601,11 @@ static int pet_birth_process(struct map_session_data *sd, struct s_pet *petinfo)
if (map->save_settings&8)
chrif->save(sd,0); //is it REALLY Needed to save the char for hatching a pet? [Skotlex]
- if(sd->bl.prev != NULL) {
- map->addblock(&sd->pd->bl);
- clif->spawn(&sd->pd->bl);
- clif->send_petdata(sd,sd->pd, 0,0);
- clif->send_petdata(sd,sd->pd, 5,battle_config.pet_hair_style);
-#if PACKETVER >= 20180704
- clif->send_petdata(sd, sd->pd, 6, 1);
-#endif
- clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom);
- clif->send_petstatus(sd);
+ if (sd->pd != NULL && sd->bl.prev != NULL) {
+ if (pet->spawn(sd, true) != 0)
+ return 1;
}
+
Assert_retr(1, sd->status.pet_id == 0 || sd->pd == 0 || sd->pd->msd == sd);
return 0;
@@ -584,13 +644,9 @@ static int pet_recv_petdata(int account_id, struct s_pet *p, int flag)
}
} else {
pet->data_init(sd,p);
- if(sd->pd && sd->bl.prev != NULL) {
- map->addblock(&sd->pd->bl);
- clif->spawn(&sd->pd->bl);
- clif->send_petdata(sd,sd->pd,0,0);
- clif->send_petdata(sd,sd->pd,5,battle_config.pet_hair_style);
- clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom);
- clif->send_petstatus(sd);
+ if (sd->pd != NULL && sd->bl.prev != NULL) {
+ if (pet->spawn(sd, false) != 0)
+ return 1;
}
}
@@ -644,8 +700,6 @@ static int pet_catch_process2(struct map_session_data *sd, int target_id)
return 1;
}
- //FIXME: Delete taming item here, if this was an item-invoked capture and the item was flagged as delay-consume. [ultramage]
-
// catch_target_class == 0 is used for universal lures (except bosses for now). [Skotlex]
if (sd->catch_target_class == 0 && (md->status.mode & MD_BOSS) == 0)
sd->catch_target_class = md->class_;
@@ -729,7 +783,7 @@ static bool pet_get_egg(int account_id, int pet_class, int pet_id)
tmp_item.card[0] = CARD0_PET;
tmp_item.card[1] = GetWord(pet_id,0);
tmp_item.card[2] = GetWord(pet_id,1);
- tmp_item.card[3] = 0; //New pets are not named.
+ tmp_item.card[3] = pet->get_card4_value(0, pet->db[i].intimate);
if((ret = pc->additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER))) {
clif->additem(sd,0,0,ret);
map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
@@ -828,8 +882,6 @@ static int pet_change_name_ack(struct map_session_data *sd, const char *name, in
aFree(newname);
clif->blname_ack(0,&pd->bl);
pd->pet.rename_flag = 1;
- clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom);
- clif->send_petstatus(sd);
return 1;
}
@@ -920,6 +972,7 @@ static int pet_food(struct map_session_data *sd, struct pet_data *pd)
{
nullpo_retr(1, sd);
nullpo_retr(1, pd);
+ Assert_retr(1, sd->status.pet_id == pd->pet.pet_id);
int i = pc->search_inventory(sd, pd->petDB->FoodID);
@@ -948,15 +1001,11 @@ static int pet_food(struct map_session_data *sd, struct pet_data *pd)
intimacy = intimacy * battle_config.pet_friendly_rate / 100;
pet->set_intimate(pd, pd->pet.intimate + intimacy);
- if (pd->pet.intimate == PET_INTIMACY_NONE) {
- pet_stop_attack(pd);
- pd->status.speed = pd->db->status.speed;
- }
+ if (sd->pd == NULL)
+ return 0;
status_calc_pet(pd, SCO_NONE);
pet->set_hunger(pd, pd->pet.hungry + pd->petDB->fullness);
- clif->send_petdata(sd, pd, 2, pd->pet.hungry);
- clif->send_petdata(sd, pd, 1, pd->pet.intimate);
clif->pet_food(sd, pd->petDB->FoodID, 1);
return 0;
@@ -1799,6 +1848,7 @@ void pet_defaults(void)
pet->hungry_val = pet_hungry_val;
pet->set_hunger = pet_set_hunger;
+ pet->get_card4_value = pet_get_card4_value;
pet->set_intimate = pet_set_intimate;
pet->create_egg = pet_create_egg;
pet->unlocktarget = pet_unlocktarget;
@@ -1811,6 +1861,7 @@ void pet_defaults(void)
pet->performance = pet_performance;
pet->return_egg = pet_return_egg;
pet->data_init = pet_data_init;
+ pet->spawn = pet_spawn;
pet->birth_process = pet_birth_process;
pet->recv_petdata = pet_recv_petdata;
pet->select_egg = pet_select_egg;
diff --git a/src/map/pet.h b/src/map/pet.h
index fa37e896a..c57df9de3 100644
--- a/src/map/pet.h
+++ b/src/map/pet.h
@@ -147,6 +147,7 @@ struct pet_interface {
/* */
int (*hungry_val) (struct pet_data *pd);
void (*set_hunger) (struct pet_data *pd, int value);
+ int (*get_card4_value) (int rename_flag, int intimacy);
void (*set_intimate) (struct pet_data *pd, int value);
int (*create_egg) (struct map_session_data *sd, int item_id);
int (*unlocktarget) (struct pet_data *pd);
@@ -159,6 +160,7 @@ struct pet_interface {
int (*performance) (struct map_session_data *sd, struct pet_data *pd);
int (*return_egg) (struct map_session_data *sd, struct pet_data *pd);
int (*data_init) (struct map_session_data *sd, struct s_pet *petinfo);
+ int (*spawn) (struct map_session_data *sd, bool birth_process);
int (*birth_process) (struct map_session_data *sd, struct s_pet *petinfo);
int (*recv_petdata) (int account_id, struct s_pet *p, int flag);
int (*select_egg) (struct map_session_data *sd, int egg_index);
diff --git a/src/map/script.c b/src/map/script.c
index 743a1779a..a8fee9076 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -20518,6 +20518,8 @@ static BUILDIN(setunitdata)
break;
case UDT_LEVEL:
pd->pet.level = (short)val;
+ if (pd->msd != NULL)
+ clif->send_petstatus(pd->msd); // Send pet data.
break;
case UDT_HP:
status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
@@ -20629,7 +20631,6 @@ static BUILDIN(setunitdata)
break;
case UDT_INTIMACY:
pet->set_intimate(pd, val);
- clif->send_petdata(pd->msd, pd, 1, pd->pet.intimate);
break;
case UDT_HUNGER:
pet->set_hunger(pd, val);
@@ -20640,7 +20641,6 @@ static BUILDIN(setunitdata)
return false;
}
- clif->send_petstatus(pd->msd); // Send pet data.
break;
}
case BL_MER: {
@@ -28358,6 +28358,11 @@ static void script_hardcoded_constants(void)
script->set_constant("P_AIRSHIP_INVALID_END_MAP", P_AIRSHIP_INVALID_END_MAP, false, false);
script->set_constant("P_AIRSHIP_ITEM_NOT_ENOUGH", P_AIRSHIP_ITEM_NOT_ENOUGH, false, false);
script->set_constant("P_AIRSHIP_ITEM_INVALID", P_AIRSHIP_ITEM_INVALID, false, false);
+
+ script->constdb_comment("player allowed actions when dead");
+ script->set_constant("PCALLOWACTION_NONE", PCALLOWACTION_NONE, false, false);
+ script->set_constant("PCALLOWACTION_TRADE", PCALLOWACTION_TRADE, false, false);
+ script->set_constant("PCALLOWACTION_CHAT", PCALLOWACTION_CHAT, false, false);
script->constdb_comment("questinfo types");
script->set_constant("QINFO_JOB", QINFO_JOB, false, false);
diff --git a/src/map/skill.c b/src/map/skill.c
index 24fbe7892..ccc4264d9 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -370,6 +370,41 @@ static int skill_get_spiritball(int skill_id, int skill_lv)
}
/**
+ * Gets the index of the first required item for a skill at given level.
+ *
+ * @param skill_id The skill's ID.
+ * @param skill_lv The skill's level.
+ * @return The required item's index. Defaults to INDEX_NOT_FOUND (-1) in case of error or if no appropriate index was found.
+ *
+ **/
+static int skill_get_item_index(int skill_id, int skill_lv)
+{
+ if (skill_id == 0)
+ return INDEX_NOT_FOUND;
+
+ Assert_retr(INDEX_NOT_FOUND, skill_lv > 0);
+
+ int idx = skill->get_index(skill_id);
+
+ Assert_retr(INDEX_NOT_FOUND, idx != 0);
+
+ int item_index = INDEX_NOT_FOUND;
+ int level_index = skill_get_lvl_idx(skill_lv);
+
+ for (int i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++) {
+ if (skill->dbs->db[idx].req_items.item[i].id == 0)
+ continue;
+
+ if (skill->dbs->db[idx].req_items.item[i].amount[level_index] != -1) {
+ item_index = i;
+ break;
+ }
+ }
+
+ return item_index;
+}
+
+/**
* Gets a skill's required item's ID by the skill's ID and the item's index.
*
* @param skill_id The skill's ID.
@@ -7937,7 +7972,14 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
}
if( sd ) {
int bonus = 100, potion = min(500+skill_lv,505);
- int item_idx = (skill_lv - 1) % MAX_SKILL_ITEM_REQUIRE;
+ int item_idx = skill->get_item_index(skill_id, skill_lv);
+
+ if (item_idx == INDEX_NOT_FOUND) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
+ map->freeblock_unlock();
+ return 1;
+ }
+
int item_id = skill->get_itemid(skill_id, item_idx);
int inventory_idx = pc->search_inventory(sd, item_id);
if (inventory_idx == INDEX_NOT_FOUND || item_id <= 0) {
@@ -11797,7 +11839,13 @@ static int skill_castend_pos2(struct block_list *src, int x, int y, uint16 skill
// Slim Pitcher [Celest]
case CR_SLIMPITCHER:
if (sd) {
- int item_idx = (skill_lv - 1) % MAX_SKILL_ITEM_REQUIRE;
+ int item_idx = skill->get_item_index(skill_id, skill_lv);
+
+ if (item_idx == INDEX_NOT_FOUND) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
+ return 1;
+ }
+
int item_id = skill->get_itemid(skill_id, item_idx);
int inventory_idx = pc->search_inventory(sd, item_id);
int bonus;
@@ -11830,7 +11878,11 @@ static int skill_castend_pos2(struct block_list *src, int x, int y, uint16 skill
skill->castend_nodamage_id);
}
} else {
- int item_idx = (skill_lv - 1) % MAX_SKILL_ITEM_REQUIRE;
+ int item_idx = skill->get_item_index(skill_id, skill_lv);
+
+ if (item_idx == INDEX_NOT_FOUND)
+ return 1;
+
int item_id = skill->get_itemid(skill_id, item_idx);
struct item_data *item = itemdb->search(item_id);
int bonus;
@@ -17766,13 +17818,20 @@ static int skill_get_new_group_id(void)
static struct skill_unit_group *skill_initunitgroup(struct block_list *src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, int limit, int interval)
{
- struct unit_data* ud = unit->bl2ud( src );
struct skill_unit_group* group;
int i;
if(!(skill_id && skill_lv)) return 0;
nullpo_retr(NULL, src);
+
+ struct unit_data *ud;
+
+ if (src->type == BL_NPC)
+ ud = unit->bl2ud2(src);
+ else
+ ud = unit->bl2ud(src);
+
nullpo_retr(NULL, ud);
// find a free spot to store the new unit group
@@ -23937,6 +23996,7 @@ void skill_defaults(void)
skill->get_sp_rate = skill_get_sp_rate;
skill->get_state = skill_get_state;
skill->get_spiritball = skill_get_spiritball;
+ skill->get_item_index = skill_get_item_index;
skill->get_itemid = skill_get_itemid;
skill->get_itemqty = skill_get_itemqty;
skill->get_item_any_flag = skill_get_item_any_flag;
diff --git a/src/map/skill.h b/src/map/skill.h
index b505412b6..fdeaefe01 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -2007,6 +2007,7 @@ struct skill_interface {
int (*get_sp_rate) (int skill_id, int skill_lv);
int (*get_state) (int skill_id, int skill_lv);
int (*get_spiritball) (int skill_id, int skill_lv);
+ int (*get_item_index) (int skill_id, int skill_lv);
int (*get_itemid) (int skill_id, int item_idx);
int (*get_itemqty) (int skill_id, int item_idx, int skill_lv);
bool (*get_item_any_flag) (int skill_id, int skill_lv);
diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc
index c04eedb05..f8f760b48 100644
--- a/src/plugins/HPMHooking/HPMHooking.Defs.inc
+++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc
@@ -6540,6 +6540,8 @@ typedef int (*HPMHOOK_pre_pet_hungry_val) (struct pet_data **pd);
typedef int (*HPMHOOK_post_pet_hungry_val) (int retVal___, struct pet_data *pd);
typedef void (*HPMHOOK_pre_pet_set_hunger) (struct pet_data **pd, int *value);
typedef void (*HPMHOOK_post_pet_set_hunger) (struct pet_data *pd, int value);
+typedef int (*HPMHOOK_pre_pet_get_card4_value) (int *rename_flag, int *intimacy);
+typedef int (*HPMHOOK_post_pet_get_card4_value) (int retVal___, int rename_flag, int intimacy);
typedef void (*HPMHOOK_pre_pet_set_intimate) (struct pet_data **pd, int *value);
typedef void (*HPMHOOK_post_pet_set_intimate) (struct pet_data *pd, int value);
typedef int (*HPMHOOK_pre_pet_create_egg) (struct map_session_data **sd, int *item_id);
@@ -6564,6 +6566,8 @@ typedef int (*HPMHOOK_pre_pet_return_egg) (struct map_session_data **sd, struct
typedef int (*HPMHOOK_post_pet_return_egg) (int retVal___, struct map_session_data *sd, struct pet_data *pd);
typedef int (*HPMHOOK_pre_pet_data_init) (struct map_session_data **sd, struct s_pet **petinfo);
typedef int (*HPMHOOK_post_pet_data_init) (int retVal___, struct map_session_data *sd, struct s_pet *petinfo);
+typedef int (*HPMHOOK_pre_pet_spawn) (struct map_session_data **sd, bool *birth_process);
+typedef int (*HPMHOOK_post_pet_spawn) (int retVal___, struct map_session_data *sd, bool birth_process);
typedef int (*HPMHOOK_pre_pet_birth_process) (struct map_session_data **sd, struct s_pet **petinfo);
typedef int (*HPMHOOK_post_pet_birth_process) (int retVal___, struct map_session_data *sd, struct s_pet *petinfo);
typedef int (*HPMHOOK_pre_pet_recv_petdata) (int *account_id, struct s_pet **p, int *flag);
@@ -7264,6 +7268,8 @@ typedef int (*HPMHOOK_pre_skill_get_state) (int *skill_id, int *skill_lv);
typedef int (*HPMHOOK_post_skill_get_state) (int retVal___, int skill_id, int skill_lv);
typedef int (*HPMHOOK_pre_skill_get_spiritball) (int *skill_id, int *skill_lv);
typedef int (*HPMHOOK_post_skill_get_spiritball) (int retVal___, int skill_id, int skill_lv);
+typedef int (*HPMHOOK_pre_skill_get_item_index) (int *skill_id, int *skill_lv);
+typedef int (*HPMHOOK_post_skill_get_item_index) (int retVal___, int skill_id, int skill_lv);
typedef int (*HPMHOOK_pre_skill_get_itemid) (int *skill_id, int *item_idx);
typedef int (*HPMHOOK_post_skill_get_itemid) (int retVal___, int skill_id, int item_idx);
typedef int (*HPMHOOK_pre_skill_get_itemqty) (int *skill_id, int *item_idx, int *skill_lv);
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
index 60d8b7e20..acd65174c 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
@@ -5116,6 +5116,8 @@ struct {
struct HPMHookPoint *HP_pet_hungry_val_post;
struct HPMHookPoint *HP_pet_set_hunger_pre;
struct HPMHookPoint *HP_pet_set_hunger_post;
+ struct HPMHookPoint *HP_pet_get_card4_value_pre;
+ struct HPMHookPoint *HP_pet_get_card4_value_post;
struct HPMHookPoint *HP_pet_set_intimate_pre;
struct HPMHookPoint *HP_pet_set_intimate_post;
struct HPMHookPoint *HP_pet_create_egg_pre;
@@ -5140,6 +5142,8 @@ struct {
struct HPMHookPoint *HP_pet_return_egg_post;
struct HPMHookPoint *HP_pet_data_init_pre;
struct HPMHookPoint *HP_pet_data_init_post;
+ struct HPMHookPoint *HP_pet_spawn_pre;
+ struct HPMHookPoint *HP_pet_spawn_post;
struct HPMHookPoint *HP_pet_birth_process_pre;
struct HPMHookPoint *HP_pet_birth_process_post;
struct HPMHookPoint *HP_pet_recv_petdata_pre;
@@ -5788,6 +5792,8 @@ struct {
struct HPMHookPoint *HP_skill_get_state_post;
struct HPMHookPoint *HP_skill_get_spiritball_pre;
struct HPMHookPoint *HP_skill_get_spiritball_post;
+ struct HPMHookPoint *HP_skill_get_item_index_pre;
+ struct HPMHookPoint *HP_skill_get_item_index_post;
struct HPMHookPoint *HP_skill_get_itemid_pre;
struct HPMHookPoint *HP_skill_get_itemid_post;
struct HPMHookPoint *HP_skill_get_itemqty_pre;
@@ -12147,6 +12153,8 @@ struct {
int HP_pet_hungry_val_post;
int HP_pet_set_hunger_pre;
int HP_pet_set_hunger_post;
+ int HP_pet_get_card4_value_pre;
+ int HP_pet_get_card4_value_post;
int HP_pet_set_intimate_pre;
int HP_pet_set_intimate_post;
int HP_pet_create_egg_pre;
@@ -12171,6 +12179,8 @@ struct {
int HP_pet_return_egg_post;
int HP_pet_data_init_pre;
int HP_pet_data_init_post;
+ int HP_pet_spawn_pre;
+ int HP_pet_spawn_post;
int HP_pet_birth_process_pre;
int HP_pet_birth_process_post;
int HP_pet_recv_petdata_pre;
@@ -12819,6 +12829,8 @@ struct {
int HP_skill_get_state_post;
int HP_skill_get_spiritball_pre;
int HP_skill_get_spiritball_post;
+ int HP_skill_get_item_index_pre;
+ int HP_skill_get_item_index_post;
int HP_skill_get_itemid_pre;
int HP_skill_get_itemid_post;
int HP_skill_get_itemqty_pre;
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
index 899f443d1..4cd13c366 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
@@ -2618,6 +2618,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(pet->final, HP_pet_final) },
{ HP_POP(pet->hungry_val, HP_pet_hungry_val) },
{ HP_POP(pet->set_hunger, HP_pet_set_hunger) },
+ { HP_POP(pet->get_card4_value, HP_pet_get_card4_value) },
{ HP_POP(pet->set_intimate, HP_pet_set_intimate) },
{ HP_POP(pet->create_egg, HP_pet_create_egg) },
{ HP_POP(pet->unlocktarget, HP_pet_unlocktarget) },
@@ -2630,6 +2631,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(pet->performance, HP_pet_performance) },
{ HP_POP(pet->return_egg, HP_pet_return_egg) },
{ HP_POP(pet->data_init, HP_pet_data_init) },
+ { HP_POP(pet->spawn, HP_pet_spawn) },
{ HP_POP(pet->birth_process, HP_pet_birth_process) },
{ HP_POP(pet->recv_petdata, HP_pet_recv_petdata) },
{ HP_POP(pet->select_egg, HP_pet_select_egg) },
@@ -2963,6 +2965,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(skill->get_sp_rate, HP_skill_get_sp_rate) },
{ HP_POP(skill->get_state, HP_skill_get_state) },
{ HP_POP(skill->get_spiritball, HP_skill_get_spiritball) },
+ { HP_POP(skill->get_item_index, HP_skill_get_item_index) },
{ HP_POP(skill->get_itemid, HP_skill_get_itemid) },
{ HP_POP(skill->get_itemqty, HP_skill_get_itemqty) },
{ HP_POP(skill->get_item_any_flag, HP_skill_get_item_any_flag) },
diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
index f6f1b3839..5440d9f2a 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -68086,6 +68086,33 @@ void HP_pet_set_hunger(struct pet_data *pd, int value) {
}
return;
}
+int HP_pet_get_card4_value(int rename_flag, int intimacy) {
+ int hIndex = 0;
+ int retVal___ = 0;
+ if (HPMHooks.count.HP_pet_get_card4_value_pre > 0) {
+ int (*preHookFunc) (int *rename_flag, int *intimacy);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_get_card4_value_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_pet_get_card4_value_pre[hIndex].func;
+ retVal___ = preHookFunc(&rename_flag, &intimacy);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.pet.get_card4_value(rename_flag, intimacy);
+ }
+ if (HPMHooks.count.HP_pet_get_card4_value_post > 0) {
+ int (*postHookFunc) (int retVal___, int rename_flag, int intimacy);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_get_card4_value_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_pet_get_card4_value_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, rename_flag, intimacy);
+ }
+ }
+ return retVal___;
+}
void HP_pet_set_intimate(struct pet_data *pd, int value) {
int hIndex = 0;
if (HPMHooks.count.HP_pet_set_intimate_pre > 0) {
@@ -68409,6 +68436,33 @@ int HP_pet_data_init(struct map_session_data *sd, struct s_pet *petinfo) {
}
return retVal___;
}
+int HP_pet_spawn(struct map_session_data *sd, bool birth_process) {
+ int hIndex = 0;
+ int retVal___ = 0;
+ if (HPMHooks.count.HP_pet_spawn_pre > 0) {
+ int (*preHookFunc) (struct map_session_data **sd, bool *birth_process);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_spawn_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_pet_spawn_pre[hIndex].func;
+ retVal___ = preHookFunc(&sd, &birth_process);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.pet.spawn(sd, birth_process);
+ }
+ if (HPMHooks.count.HP_pet_spawn_post > 0) {
+ int (*postHookFunc) (int retVal___, struct map_session_data *sd, bool birth_process);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_spawn_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_pet_spawn_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, sd, birth_process);
+ }
+ }
+ return retVal___;
+}
int HP_pet_birth_process(struct map_session_data *sd, struct s_pet *petinfo) {
int hIndex = 0;
int retVal___ = 0;
@@ -77228,6 +77282,33 @@ int HP_skill_get_spiritball(int skill_id, int skill_lv) {
}
return retVal___;
}
+int HP_skill_get_item_index(int skill_id, int skill_lv) {
+ int hIndex = 0;
+ int retVal___ = 0;
+ if (HPMHooks.count.HP_skill_get_item_index_pre > 0) {
+ int (*preHookFunc) (int *skill_id, int *skill_lv);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_get_item_index_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_skill_get_item_index_pre[hIndex].func;
+ retVal___ = preHookFunc(&skill_id, &skill_lv);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.skill.get_item_index(skill_id, skill_lv);
+ }
+ if (HPMHooks.count.HP_skill_get_item_index_post > 0) {
+ int (*postHookFunc) (int retVal___, int skill_id, int skill_lv);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_get_item_index_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_skill_get_item_index_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, skill_id, skill_lv);
+ }
+ }
+ return retVal___;
+}
int HP_skill_get_itemid(int skill_id, int item_idx) {
int hIndex = 0;
int retVal___ = 0;