summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE.md54
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md37
-rw-r--r--.gitlab-ci.yml12
-rw-r--r--db/pre-re/map_zone_db.conf2
-rw-r--r--db/pre-re/skill_db.conf3
-rw-r--r--db/re/map_zone_db.conf2
-rw-r--r--doc/script_commands.txt48
-rw-r--r--npc/other/Global_Functions.txt10
-rw-r--r--npc/quests/the_sign_quest.txt12
-rw-r--r--npc/re/merchants/shadow_refiner.txt2
-rw-r--r--npc/woe-se/agit_main_se.txt29
-rw-r--r--src/char/int_party.c34
-rw-r--r--src/map/clif.c8
-rw-r--r--src/map/clif.h2
-rw-r--r--src/map/mob.c2
-rw-r--r--src/map/party.c42
-rw-r--r--src/map/script.c391
-rw-r--r--src/plugins/HPMHooking/HPMHooking.Defs.inc4
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc12
19 files changed, 493 insertions, 213 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 000000000..c661cbd47
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,54 @@
+[//]: # (**********************************)
+[//]: # (** Fill in the following fields **)
+[//]: # (**********************************)
+
+[//]: # (Note: Lines beginning with syntax such as this one, are comments and will not be visible in your report!)
+
+### Issue Prelude
+
+[//]: # (Please complete these mandatory steps and check the following boxes by putting an `x` inside the brackets _before_ filing your issue)
+
+- [ ] I have not modified the source prior to reproducing this issue.
+- [ ] I am using the latest version of Hercules.
+- [ ] I am aware that this report will be closed or deleted if it becomes obvious that I am stating the false.
+
+### Description
+
+[//]: # (Description of the problem or issue at length.)
+[//]: # (Please specify any battle configuration related to the components of this issue that have been changed from the default values. This will allow quicker determination of the cause of the problem.)
+
+### Current Behavior
+
+[//]: # (Describe at length what you noticed during your analysis.)
+[//]: # (If this is a crash, post the core/stack-dump or crash-log to https://gist.github.com/)
+[//]: # (If you are referencing from sources such as iROwiki or ratemyserver.net, please quote specific information rather than providing the links alone.)
+
+### Expected Behavior
+
+[//]: # (Tell us what should happen instead.)
+
+### Steps To Reproduce The Issue
+
+1. Step 1
+2. Step 2
+3. Step 3
+
+**Branch(es):**
+- [ ] master
+- [ ] other
+
+**Hercules rev. hash/commit:**
+
+Git revision src:
+
+[//]: # (Copy the first 3 lines of the login-server, char-server or map-server startup.)
+[//]: # ( [Info]: Hercules 64-bit for Mac OS X )
+[//]: # ( [Info]: Git revision src: 'a5918b329ca0826b04dca32ede783586403f58db' )
+[//]: # ( [Info]: Git revision scripts: 'a5918b329ca0826b04dca32ede783586403f58db' )
+
+### Operating System
+
+[//]: # (Mac OS X 10.12.3 16D32 [x86_64])
+[//]: # (Thank you for adhering to this process! It ensures your issue is resolved quickly and that neither your nor our time is needlessly wasted.)
+[//]: # (This template is for problem reports. For other types of report, edit it accordingly.)
+[//]: # (For fixes please create a Pull Request.)
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 000000000..c62641f08
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,37 @@
+[//]: # (**********************************)
+[//]: # (** Fill in the following fields **)
+[//]: # (**********************************)
+
+[//]: # (Note: Lines beginning with syntax such as this one, are comments and will not be visible in your report!)
+
+### Pull Request Prelude
+
+[//]: # (Thank you for working on improving Hercules!)
+
+[//]: # (Please complete these steps and check the following boxes by putting an `x` inside the brackets _before_ filing your Pull Request.)
+
+- [ ] I have followed [proper Hercules code styling][code].
+- [ ] I have read and understood the [contribution guidelines][cont] before making this PR.
+- [ ] I am aware that this PR will be closed if the above-mentioned criteria are not fulfilled.
+
+### Changes Proposed
+
+[//]: # (Describe at length, the changes that this pull request makes.)
+
+**Affected Branches:**
+
+[//]: # (Master? Slave?)
+
+**Issues addressed:**
+
+[//]: # (Issue Tracker Number if any.)
+
+### Known Issues and TODO List
+
+[//]: # (Insert checklist here)
+[//]: # (Syntax: - [ ] Checkbox)
+
+[//]: # (**NOTE** Enable the setting "[√] Allow edits from maintainers." when creating your pull request if you have not already enabled it.)
+
+[cont]: https://github.com/HerculesWS/Hercules/blob/master/CONTRIBUTING.md
+[code]: https://github.com/HerculesWS/Hercules/wiki/Coding-Style
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 13d140fbc..8a3eb53c5 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -180,11 +180,11 @@ re:gcc-4.9:
pre_re:gcc-5:
<<: *branch_exceptions
<<: *prerequisites
- stage: primary
- image: debian:stretch
+ stage: secondary
+ image: debian:unstable
variables:
<<: *base_vars
- INSTALL_PACKAGES: gcc-5 mariadb-client libmariadbclient-dev-compat
+ INSTALL_PACKAGES: gcc-5 mysql-client libmysqlclient-dev
script:
- ./tools/ci/travis.sh build CC=gcc-5 --enable-debug --enable-Werror --enable-buildbot --disable-renewal
- ./tools/ci/travis.sh test ragnarok ragnarok ragnarok mysql
@@ -192,11 +192,11 @@ pre_re:gcc-5:
re:gcc-5:
<<: *branch_exceptions
<<: *prerequisites
- stage: primary
- image: debian:stretch
+ stage: secondary
+ image: debian:unstable
variables:
<<: *base_vars
- INSTALL_PACKAGES: gcc-5 mariadb-client libmariadbclient-dev-compat
+ INSTALL_PACKAGES: gcc-5 mysql-client libmysqlclient-dev
script:
- ./tools/ci/travis.sh build CC=gcc-5 --enable-debug --enable-Werror --enable-buildbot
- ./tools/ci/travis.sh test ragnarok ragnarok ragnarok mysql
diff --git a/db/pre-re/map_zone_db.conf b/db/pre-re/map_zone_db.conf
index cab00bbb9..a3d465c0a 100644
--- a/db/pre-re/map_zone_db.conf
+++ b/db/pre-re/map_zone_db.conf
@@ -66,7 +66,7 @@ zones: (
//heal: 70
}
skill_damage_cap: {
- //Exemple Below caps firebolt damage in maps within this zone to a maximum 50 damage,
+ //Example Below caps Cold Bolt damage in maps within this zone to a maximum 50 damage,
// (depends on HMAP_ZONE_DAMAGE_CAP_TYPE in src/config/core.h)
// when cast vs players and monsters.
//MG_COLDBOLT: (50,"PLAYER | MONSTER")
diff --git a/db/pre-re/skill_db.conf b/db/pre-re/skill_db.conf
index 95683a9e0..a5c27257f 100644
--- a/db/pre-re/skill_db.conf
+++ b/db/pre-re/skill_db.conf
@@ -14881,11 +14881,10 @@ skill_db: (
Range: -9
Hit: "BDT_MULTIHIT"
SkillType: {
- Self: true
+ Enemy: true
}
SkillInfo: {
Spirit: true
- NoCastSelf: true
}
AttackType: "Weapon"
Element: "Ele_Weapon"
diff --git a/db/re/map_zone_db.conf b/db/re/map_zone_db.conf
index 282a85abb..1dd4315b6 100644
--- a/db/re/map_zone_db.conf
+++ b/db/re/map_zone_db.conf
@@ -66,7 +66,7 @@ zones: (
//heal: 70
}
skill_damage_cap: {
- //Exemple Below caps firebolt damage in maps within this zone to a maximum 50 damage,
+ //Example Below caps Cold Bolt damage in maps within this zone to a maximum 50 damage,
// (depends on HMAP_ZONE_DAMAGE_CAP_TYPE in src/config/core.h)
// when cast vs players and monsters.
//MG_COLDBOLT: (50,"PLAYER | MONSTER")
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index fa86419a8..6df1f6e87 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -1409,6 +1409,27 @@ getvariableofnpc() should not be used on them.
---------------------------------------
+*getvariableofpc(<variable>, <account id>{, <default value>})
+
+Returns a reference to a PC variable from the target player.
+If <default value> is passed, it will return this value if the player is
+not found.
+
+Examples:
+
+//This will return the value of @var, note that this can't be used, since
+//the value isn't caught.
+ getvariableofpc(@var, getcharid(CHAR_ID_ACCOUNT, "player"));
+
+//This will set the .@v variable to the value of the player's @var
+//variable.
+ .@v = getvariableofpc(@var, getcharid(CHAR_ID_ACCOUNT, "player"));
+
+//This will set the @var variable of the player to 1.
+ set(getvariableofpc(@var, getcharid(CHAR_ID_ACCOUNT, "player")), 1);
+
+---------------------------------------
+
*goto(<label>)
This command will make the script jump to a label, usually used in
@@ -4515,26 +4536,17 @@ changebase(Class); // Changes player back to default sprite.
---------------------------------------
-*classchange(<view id>, <type>)
+*classchange(<view id>, <type> {, <char id>})
This command is very ancient, it's origins are clouded in mystery.
-It will send a 'display id change' packet to everyone in the immediate
-area of the NPC object, which will supposedly make the NPC look like a
-different sprite, an NPC sprite ID, or a monster ID. This effect is not
-stored anywhere and will not persist (Which is odd, cause it would be
-relatively easy to make it do so) and most importantly, will not work at
-all since this command was broken with the introduction of advanced
-classes. The code is written with the assumption that the lowest sprite
-IDs are the job sprites and the anything beyond them is monster and NPC
-sprites, but since the advanced classes rolled in, they got the ID numbers
-on the other end of the number pool where monster sprites float.
-
-As a result it is currently impossible to call this command with a valid
-view id. It will do nothing whatsoever if the view ID is below 4047.
-Getting it to run will actually just crash the client.
-
-It could be a real gem if it can be gotten to actually do what it's
-supposed to do, but this will only happen in a later Git revision.
+It will send a 'display id change' packet to player with given char ID
+or to everyone in the immediate area of the NPC object if char ID is 0 or
+not passed, which will make the NPC look like a different sprite, an NPC
+sprite ID, or a monster ID. This effect is not stored anywhere and will
+not persist.
+Note that you can't send a Job sprite ID
+
+type is not used and should always be 0.
---------------------------------------
diff --git a/npc/other/Global_Functions.txt b/npc/other/Global_Functions.txt
index f6068d598..544e3a672 100644
--- a/npc/other/Global_Functions.txt
+++ b/npc/other/Global_Functions.txt
@@ -156,16 +156,6 @@ function script F_Rand {
return getarg(rand(getargcount()));
}
-//== Function F_Sex ========================================
-// Returns 1st argument if female, 2nd argument otherwise
-// Example: mes callfunc("F_Sex","What a beautiful lady!","What a handsome man!");
-function script F_SexMes {
- if (Sex == SEX_MALE)
- return getarg(0);
- else
- return getarg(1);
-}
-
//== Function F_Hi =========================================
// Returns random HELLO message
function script F_Hi {
diff --git a/npc/quests/the_sign_quest.txt b/npc/quests/the_sign_quest.txt
index dd3750543..cf593eaae 100644
--- a/npc/quests/the_sign_quest.txt
+++ b/npc/quests/the_sign_quest.txt
@@ -12249,11 +12249,12 @@ OnInit:
end;
OnTouch:
- geffenia_warp = rand(1,4);
- if (geffenia_warp == 1) warp "gefenia01",58,169;
- else if (geffenia_warp == 2) warp "gefenia02",116,115;
- else if (geffenia_warp == 3) warp "gefenia03",130,206;
- else if (geffenia_warp == 4) warp "gefenia04",133,88;
+ callfunc("F_UpdateSignVars");
+ .@geffenia_warp = rand(1,4);
+ if (.@geffenia_warp == 1) warp "gefenia01",58,169;
+ else if (.@geffenia_warp == 2) warp "gefenia02",116,115;
+ else if (.@geffenia_warp == 3) warp "gefenia03",130,206;
+ else if (.@geffenia_warp == 4) warp "gefenia04",133,88;
else warp "geffen",116,115;
end;
@@ -12644,6 +12645,7 @@ function script F_UpdateSignVars {
Sign_Branch2B = 0;
serinring = 0;
signmetzhour = 0;
+ geffenia_warp = 0;
}
return;
}
diff --git a/npc/re/merchants/shadow_refiner.txt b/npc/re/merchants/shadow_refiner.txt
index 4e5049e5f..2f8984498 100644
--- a/npc/re/merchants/shadow_refiner.txt
+++ b/npc/re/merchants/shadow_refiner.txt
@@ -158,7 +158,7 @@ itemmall,31,76,3 script Shadow Blacksmith#nomal 4_F_JOB_BLACKSMITH,{
}
delitem .@choose,1;
Zeny -= 20000;
- if (getequippercentrefinery(.@SelectedPart) > rand(100) || getequippercentrefinery(.@SelectedPart) > rand(100)) {
+ if (getequippercentrefinery(.@SelectedPart) > rand(100) || ( .@option == 1 && getequippercentrefinery(.@SelectedPart) > rand(100))) {
successrefitem .@SelectedPart;
mes "[Shadow Blacksmith]";
mes "Refine was successful.";
diff --git a/npc/woe-se/agit_main_se.txt b/npc/woe-se/agit_main_se.txt
index c9b34f610..5f291e658 100644
--- a/npc/woe-se/agit_main_se.txt
+++ b/npc/woe-se/agit_main_se.txt
@@ -1681,6 +1681,10 @@ OnEnable:
if (.@num == 3) set getd(".MyMobCount_"+.@num+strnpcinfo(NPC_NAME_HIDDEN)),4;
else if (.@num) set getd(".MyMobCount_"+.@num+strnpcinfo(NPC_NAME_HIDDEN)),6;
setwall strnpcinfo(NPC_NAME_HIDDEN),.@wall[0],.@wall[1],.@wall[2],.@wall[3],.@wall[4],substr(strnpcinfo(NPC_NAME_HIDDEN),0,1)+substr(strnpcinfo(NPC_NAME_HIDDEN),8,9)+"_"+strnpcinfo(NPC_NAME_VISIBLE);
+ if (.@num == 0)
+ setcell(strnpcinfo(NPC_NAME_HIDDEN), .@x[0], .@y[0], .@x[getarraysize(.@x)-1], .@y[getarraysize(.@y)-1], cell_basilica, true);
+ if (.@num == 1 && (strnpcinfo(NPC_NAME_HIDDEN) == "schg_cas01" || strnpcinfo(NPC_NAME_HIDDEN) == "schg_cas04" || strnpcinfo(NPC_NAME_HIDDEN) == "schg_cas05"))
+ setcell(strnpcinfo(NPC_NAME_HIDDEN), .@x[0], .@y[0], .@x[5], .@y[5], cell_basilica, true);
.@j = (getd(".MyMobCount_"+.@num+strnpcinfo(NPC_NAME_HIDDEN)))?getd(".MyMobCount_"+.@num+strnpcinfo(NPC_NAME_HIDDEN)):getarraysize(.@x);
for (.@i = 0; .@i<.@j; ++.@i)
guardian strnpcinfo(NPC_NAME_HIDDEN),.@x[.@i],.@y[.@i]," ",1905,strnpcinfo(NPC_NAME)+"::OnBarrierDestroyed";
@@ -1700,6 +1704,31 @@ OnBarrierDestroyed:
end;
OnDisable:
+ if (compare(strnpcinfo(NPC_NAME_HIDDEN),"arug")) {
+ if (strnpcinfo(NPC_NAME_HIDDEN) == "arug_cas01") {
+ setarray(.@x[0], 239, 245);
+ setarray(.@y[0], 73, 73);
+ } else if (strnpcinfo(NPC_NAME_HIDDEN) == "arug_cas02") {
+ setarray(.@x[0], 137, 143);
+ setarray(.@y[0], 137, 137);
+ } else { // Castles 3, 4, 5 are identical.
+ setarray(.@x[0], 139, 145);
+ setarray(.@y[0], 111, 111);
+ }
+ } else {
+ if (strnpcinfo(NPC_NAME_HIDDEN) == "schg_cas02") {
+ setarray(.@x[0], 289, 289);
+ setarray(.@y[0], 98, 104);
+ } else if (strnpcinfo(NPC_NAME_HIDDEN) == "schg_cas03") {
+ setarray(.@x[0], 326, 330);
+ setarray(.@y[0], 300, 300);
+ } else { // Castles 1, 4, 5 are identical.
+ setarray(.@x[0], 115, 125);
+ setarray(.@y[0], 49, 49);
+ setcell(strnpcinfo(NPC_NAME_HIDDEN), 115, 50, 125, 50, cell_basilica, false);
+ }
+ }
+ setcell(strnpcinfo(NPC_NAME_HIDDEN), .@x[0], .@y[0], .@x[1], .@y[1], cell_basilica, false);
delwall substr(strnpcinfo(NPC_NAME_HIDDEN),0,1)+substr(strnpcinfo(NPC_NAME_HIDDEN),8,9)+"_"+strnpcinfo(NPC_NAME_VISIBLE);
killmonster strnpcinfo(NPC_NAME_HIDDEN),strnpcinfo(NPC_NAME)+"::OnBarrierDestroyed";
end;
diff --git a/src/char/int_party.c b/src/char/int_party.c
index 2fc39c328..921bf6d9d 100644
--- a/src/char/int_party.c
+++ b/src/char/int_party.c
@@ -633,31 +633,21 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id)
return 0; //Member not found?
mapif->party_withdraw(party_id, account_id, char_id);
-
- if (p->party.member[i].leader){
- p->party.member[i].account_id = 0;
- for (j = 0; j < MAX_PARTY; j++) {
- if (!p->party.member[j].account_id)
- continue;
- mapif->party_withdraw(party_id, p->party.member[j].account_id, p->party.member[j].char_id);
- p->party.member[j].account_id = 0;
- }
- //Party gets deleted on the check_empty call below.
- } else {
- inter_party->tosql(&p->party,PS_DELMEMBER,i);
- j = p->party.member[i].lv;
- if(p->party.member[i].online) p->party.count--;
- memset(&p->party.member[i], 0, sizeof(struct party_member));
- p->size--;
- if (j == p->min_lv || j == p->max_lv || p->family)
- {
- if(p->family) p->family = 0; //Family state broken.
- inter_party->check_lv(p);
- }
+
+ j = p->party.member[i].lv;
+ if (p->party.member[i].online > 0)
+ p->party.count--;
+ memset(&p->party.member[i], 0, sizeof(struct party_member));
+ p->size--;
+ if (j == p->min_lv || j == p->max_lv || p->family) {
+ if(p->family) p->family = 0; //Family state broken.
+ inter_party->check_lv(p);
}
- if (inter_party->check_empty(p) == 0)
+ if (inter_party->check_empty(p) == 0) {
+ inter_party->tosql(&p->party, PS_DELMEMBER, i);
mapif->party_info(-1, &p->party, 0);
+ }
return 0;
}
// When member goes to other map or levels up.
diff --git a/src/map/clif.c b/src/map/clif.c
index 674fbba1d..6897c357a 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -1352,7 +1352,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd,
/// 01b0 <id>.L <type>.B <value>.L
/// type:
/// unused
-void clif_class_change(struct block_list *bl, int class_, int type)
+void clif_class_change(struct block_list *bl, int class_, int type, struct map_session_data *sd)
{
nullpo_retv(bl);
@@ -1363,7 +1363,11 @@ void clif_class_change(struct block_list *bl, int class_, int type)
WBUFL(buf,2)=bl->id;
WBUFB(buf,6)=type;
WBUFL(buf,7)=class_;
- clif->send(buf,packet_len(0x1b0),bl,AREA);
+
+ if (sd == NULL)
+ clif->send(buf, packet_len(0x1b0), bl, AREA);
+ else
+ clif->send(buf, packet_len(0x1b0), &sd->bl, SELF);
}
}
diff --git a/src/map/clif.h b/src/map/clif.h
index b27adb5be..aefba5974 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -671,7 +671,7 @@ struct clif_interface {
void (*changetraplook) (struct block_list *bl,int val);
void (*refreshlook) (struct block_list *bl,int id,int type,int val,enum send_target target);
void (*sendlook) (struct block_list *bl, int id, int type, int val, int val2, enum send_target target);
- void (*class_change) (struct block_list *bl,int class_,int type);
+ void (*class_change) (struct block_list *bl,int class_,int type, struct map_session_data *sd);
void (*skill_delunit) (struct skill_unit *su);
void (*skillunit_update) (struct block_list* bl);
int (*clearunit_delayed_sub) (int tid, int64 tick, int id, intptr_t data);
diff --git a/src/map/mob.c b/src/map/mob.c
index d5932f195..74d25b805 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -2832,7 +2832,7 @@ int mob_class_change (struct mob_data *md, int class_) {
mob_stop_walking(md, STOPWALKING_FLAG_NONE);
unit->skillcastcancel(&md->bl, 0);
status->set_viewdata(&md->bl, class_);
- clif->class_change(&md->bl, md->vd->class, 1);
+ clif->class_change(&md->bl, md->vd->class, 1, NULL);
status_calc_mob(md, SCO_FIRST);
md->ud.state.speed_changed = 1; //Speed change update.
diff --git a/src/map/party.c b/src/map/party.c
index 3bf9542c7..26b4bae8b 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -274,6 +274,7 @@ int party_recv_info(const struct party *sp, int char_id)
int added_count = 0;
int j;
int member_id;
+ int leader_account_id = 0, leader_char_id = 0;
nullpo_ret(sp);
@@ -287,8 +288,12 @@ int party_recv_info(const struct party *sp, int char_id)
ARR_FIND(0, MAX_PARTY, i,
sp->member[i].account_id == member->account_id &&
sp->member[i].char_id == member->char_id);
- if (i == MAX_PARTY)
+ if (i == MAX_PARTY) {
removed[removed_count++] = member_id;
+ } else if (member->leader != 0) {
+ leader_account_id = member->account_id;
+ leader_char_id = member->char_id;
+ }
}
for (member_id = 0; member_id < MAX_PARTY; ++member_id) {
member = &sp->member[member_id];
@@ -316,6 +321,7 @@ int party_recv_info(const struct party *sp, int char_id)
continue;// not online
party->member_withdraw(sp->party_id, sd->status.account_id, sd->status.char_id);
}
+
memcpy(&p->party, sp, sizeof(struct party));
memset(&p->state, 0, sizeof(p->state));
memset(&p->data, 0, sizeof(p->data));
@@ -324,6 +330,8 @@ int party_recv_info(const struct party *sp, int char_id)
if ( member->char_id == 0 )
continue;// empty
p->data[member_id].sd = party->sd_check(sp->party_id, member->account_id, member->char_id);
+ if (member->account_id == leader_account_id && member->char_id == leader_char_id)
+ p->party.member[member_id].leader = 1;
}
party->check_state(p);
while( added_count > 0 ) { // new in party
@@ -591,11 +599,43 @@ int party_member_withdraw(int party_id, int account_id, int char_id)
int i;
ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == account_id && p->party.member[i].char_id == char_id );
if( i < MAX_PARTY ) {
+ bool was_leader = false;
+ int prev_leader_accountId = 0;
+ if (p->party.member[i].leader != 0) {
+ was_leader = true;
+ prev_leader_accountId = p->party.member[i].account_id;
+ }
+
clif->party_withdraw(p,sd,account_id,p->party.member[i].name,0x0);
memset(&p->party.member[i], 0, sizeof(p->party.member[0]));
memset(&p->data[i], 0, sizeof(p->data[0]));
p->party.count--;
party->check_state(p);
+
+ if (was_leader) {
+ int k;
+ // Member was party leader, try to pick a new leader from online members
+ ARR_FIND(0, MAX_PARTY, k, p->party.member[k].account_id != 0 && p->party.member[k].online == 1);
+
+ if (k == MAX_PARTY) {
+ // No online members, get an offline one
+ ARR_FIND(0, MAX_PARTY, k, p->party.member[k].account_id != 0);
+ }
+
+ if (k < MAX_PARTY) {
+ // Update party's leader
+ p->party.member[k].leader = 1;
+
+ if (p->data[k].sd != NULL) {
+ /** update members **/
+ clif->PartyLeaderChanged(p->data[k].sd, prev_leader_accountId, p->data[k].sd->status.account_id);
+ }
+
+ //Update info.
+ intif->party_leaderchange(p->party.party_id, p->party.member[k].account_id, p->party.member[k].char_id);
+ clif->party_info(p, NULL);
+ }
+ }
}
}
diff --git a/src/map/script.c b/src/map/script.c
index e8a645801..a7e27fc1b 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -2825,7 +2825,7 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
char postfix;
struct map_session_data *sd = NULL;
- if( !data_isreference(data) )
+ if (!data_isreference(data))
return data;// not a variable/constant
name = reference_getname(data);
@@ -2840,10 +2840,10 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
}
//##TODO use reference_tovariable(data) when it's confirmed that it works [FlavioJS]
- if( !reference_toconstant(data) && not_server_variable(prefix) ) {
+ if (!reference_toconstant(data) && not_server_variable(prefix) && reference_getref(data) == NULL) {
sd = script->rid2sd(st);
- if( sd == NULL ) {// needs player attached
- if( postfix == '$' ) {// string variable
+ if (sd == NULL) {// needs player attached
+ if (postfix == '$') {// string variable
ShowWarning("script_get_val: cannot access player variable '%s', defaulting to \"\"\n", name);
data->type = C_CONSTSTR;
data->u.str = "";
@@ -2861,32 +2861,44 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
const char *str = NULL;
switch (prefix) {
- case '@':
+ case '@':
+ if (data->ref) {
+ str = script->get_val_ref_str(st, data->ref, data);
+ } else {
str = pc->readregstr(sd, data->u.num);
- break;
- case '$':
- str = mapreg->readregstr(data->u.num);
- break;
- case '#':
- if (name[1] == '#')
- str = pc_readaccountreg2str(sd, data->u.num);// global
- else
- str = pc_readaccountregstr(sd, data->u.num);// local
- break;
- case '.':
- if (data->ref)
- str = script->get_val_ref_str(st, data->ref, data);
- else if (name[1] == '@')
- str = script->get_val_scope_str(st, &st->stack->scope, data);
- else
- str = script->get_val_npc_str(st, &st->script->local, data);
- break;
- case '\'':
- str = script->get_val_instance_str(st, name, data);
- break;
- default:
+ }
+ break;
+ case '$':
+ str = mapreg->readregstr(data->u.num);
+ break;
+ case '#':
+ if (data->ref) {
+ str = script->get_val_ref_str(st, data->ref, data);
+ } else if (name[1] == '#') {
+ str = pc_readaccountreg2str(sd, data->u.num);// global
+ } else {
+ str = pc_readaccountregstr(sd, data->u.num);// local
+ }
+ break;
+ case '.':
+ if (data->ref) {
+ str = script->get_val_ref_str(st, data->ref, data);
+ } else if (name[1] == '@') {
+ str = script->get_val_scope_str(st, &st->stack->scope, data);
+ } else {
+ str = script->get_val_npc_str(st, &st->script->local, data);
+ }
+ break;
+ case '\'':
+ str = script->get_val_instance_str(st, name, data);
+ break;
+ default:
+ if (data->ref) {
+ str = script->get_val_ref_str(st, data->ref, data);
+ } else {
str = pc_readglobalreg_str(sd, data->u.num);
- break;
+ }
+ break;
}
if (str == NULL || str[0] == '\0') {
@@ -2906,36 +2918,48 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
data->u.num = reference_getconstant(data);
} else if( reference_toparam(data) ) {
data->u.num = pc->readparam(sd, reference_getparamtype(data));
- } else
- switch( prefix ) {
- case '@':
+ } else {
+ switch (prefix) {
+ case '@':
+ if (data->ref) {
+ data->u.num = script->get_val_ref_num(st, data->ref, data);
+ } else {
data->u.num = pc->readreg(sd, data->u.num);
- break;
- case '$':
- data->u.num = mapreg->readreg(data->u.num);
- break;
- case '#':
- if( name[1] == '#' )
- data->u.num = pc_readaccountreg2(sd, data->u.num);// global
- else
- data->u.num = pc_readaccountreg(sd, data->u.num);// local
- break;
- case '.':
- if (data->ref)
- data->u.num = script->get_val_ref_num(st, data->ref, data);
- else if (name[1] == '@')
- data->u.num = script->get_val_scope_num(st, &st->stack->scope, data);
- else
- data->u.num = script->get_val_npc_num(st, &st->script->local, data);
- break;
- case '\'':
- data->u.num = script->get_val_instance_num(st, name, data);
- break;
- default:
+ }
+ break;
+ case '$':
+ data->u.num = mapreg->readreg(data->u.num);
+ break;
+ case '#':
+ if (data->ref) {
+ data->u.num = script->get_val_ref_num(st, data->ref, data);
+ } else if (name[1] == '#') {
+ data->u.num = pc_readaccountreg2(sd, data->u.num);// global
+ } else {
+ data->u.num = pc_readaccountreg(sd, data->u.num);// local
+ }
+ break;
+ case '.':
+ if (data->ref) {
+ data->u.num = script->get_val_ref_num(st, data->ref, data);
+ } else if (name[1] == '@') {
+ data->u.num = script->get_val_scope_num(st, &st->stack->scope, data);
+ } else {
+ data->u.num = script->get_val_npc_num(st, &st->script->local, data);
+ }
+ break;
+ case '\'':
+ data->u.num = script->get_val_instance_num(st, name, data);
+ break;
+ default:
+ if (data->ref) {
+ data->u.num = script->get_val_ref_num(st, data->ref, data);
+ } else {
data->u.num = pc_readglobalreg(sd, data->u.num);
- break;
+ }
+ break;
}
-
+ }
}
data->ref = NULL;
@@ -3108,38 +3132,43 @@ void script_array_add_member(struct script_array *sa, unsigned int idx) {
**/
struct reg_db *script_array_src(struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref) {
struct reg_db *src = NULL;
-
nullpo_retr(NULL, name);
- switch( name[0] ) {
+
+ switch (name[0]) {
/* from player */
- default: /* char reg */
- case '@':/* temp char reg */
- case '#':/* account reg */
+ default: /* char reg */
+ case '@':/* temp char reg */
+ case '#':/* account reg */
+ if (ref != NULL) {
+ src = ref;
+ } else {
nullpo_retr(NULL, sd);
src = &sd->regs;
- break;
- case '$':/* map reg */
- src = &mapreg->regs;
- break;
- case '.':/* npc/script */
- if (ref != NULL) {
- src = ref;
- } else {
- nullpo_retr(NULL, st);
- src = (name[1] == '@') ? &st->stack->scope : &st->script->local;
- }
- break;
- case '\'':/* instance */
+ }
+ break;
+ case '$':/* map reg */
+ src = &mapreg->regs;
+ break;
+ case '.':/* npc/script */
+ if (ref != NULL) {
+ src = ref;
+ } else {
nullpo_retr(NULL, st);
- if( st->instance_id >= 0 ) {
- src = &instance->list[st->instance_id].regs;
- }
- break;
+ src = (name[1] == '@') ? &st->stack->scope : &st->script->local;
+ }
+ break;
+ case '\'':/* instance */
+ nullpo_retr(NULL, st);
+ if (st->instance_id >= 0) {
+ src = &instance->list[st->instance_id].regs;
+ }
+ break;
}
- if( src ) {
- if( !src->arrays )
+ if (src) {
+ if (!src->arrays) {
src->arrays = idb_alloc(DB_OPT_BASE);
+ }
return src;
}
return NULL;
@@ -3292,48 +3321,65 @@ int set_reg(struct script_state *st, struct map_session_data *sd, int64 num, con
return 0;
}
- if( is_string_variable(name) ) {// string variable
+ if (is_string_variable(name)) {// string variable
const char *str = (const char*)value;
switch (prefix) {
- case '@':
+ case '@':
+ if (ref) {
+ script->set_reg_ref_str(st, ref, num, name, str);
+ } else {
pc->setregstr(sd, num, str);
- return 1;
- case '$':
- return mapreg->setregstr(num, str);
- case '#':
- return (name[1] == '#') ?
- pc_setaccountreg2str(sd, num, str) :
- pc_setaccountregstr(sd, num, str);
- case '.':
- if (ref)
- script->set_reg_ref_str(st, ref, num, name, str);
- else if (name[1] == '@')
- script->set_reg_scope_str(st, &st->stack->scope, num, name, str);
- else
- script->set_reg_npc_str(st, &st->script->local, num, name, str);
- return 1;
- case '\'':
- set_reg_instance_str(st, num, name, str);
- return 1;
- default:
- return pc_setglobalreg_str(sd, num, str);
+ }
+ return 1;
+ case '$':
+ mapreg->setregstr(num, str);
+ return 1;
+ case '#':
+ if (ref) {
+ script->set_reg_ref_str(st, ref, num, name, str);
+ } else if (name[1] == '#') {
+ pc_setaccountreg2str(sd, num, str);
+ } else {
+ pc_setaccountregstr(sd, num, str);
+ }
+ return 1;
+ case '.':
+ if (ref) {
+ script->set_reg_ref_str(st, ref, num, name, str);
+ } else if (name[1] == '@') {
+ script->set_reg_scope_str(st, &st->stack->scope, num, name, str);
+ } else {
+ script->set_reg_npc_str(st, &st->script->local, num, name, str);
+ }
+ return 1;
+ case '\'':
+ set_reg_instance_str(st, num, name, str);
+ return 1;
+ default:
+ if (ref) {
+ script->set_reg_ref_str(st, ref, num, name, str);
+ } else {
+ pc_setglobalreg_str(sd, num, str);
+ }
+ return 1;
}
} else {// integer variable
// FIXME: This isn't safe, in 32bits systems we're converting a 64bit pointer
// to a 32bit int, this will lead to overflows! [Panikon]
int val = (int)h64BPTRSIZE(value);
- if(script->str_data[script_getvarid(num)].type == C_PARAM) {
- if( pc->setparam(sd, script->str_data[script_getvarid(num)].val, val) == 0 ) {
- if( st != NULL ) {
+ if (script->str_data[script_getvarid(num)].type == C_PARAM) {
+ if (pc->setparam(sd, script->str_data[script_getvarid(num)].val, val) == 0) {
+ if (st != NULL) {
ShowError("script:set_reg: failed to set param '%s' to %d.\n", name, val);
script->reportsrc(st);
// Instead of just stop the script execution we let the character close
// the window if it was open.
st->state = (sd->state.dialog) ? CLOSE : END;
- if( st->state == CLOSE )
+ if(st->state == CLOSE) {
clif->scriptclose(sd, st->oid);
+ }
}
return 0;
}
@@ -3341,28 +3387,44 @@ int set_reg(struct script_state *st, struct map_session_data *sd, int64 num, con
}
switch (prefix) {
- case '@':
+ case '@':
+ if (ref) {
+ script->set_reg_ref_num(st, ref, num, name, val);
+ } else {
pc->setreg(sd, num, val);
- return 1;
- case '$':
- return mapreg->setreg(num, val);
- case '#':
- return (name[1] == '#') ?
- pc_setaccountreg2(sd, num, val) :
- pc_setaccountreg(sd, num, val);
- case '.':
- if (ref)
- script->set_reg_ref_num(st, ref, num, name, val);
- else if (name[1] == '@')
- script->set_reg_scope_num(st, &st->stack->scope, num, name, val);
- else
- script->set_reg_npc_num(st, &st->script->local, num, name, val);
- return 1;
- case '\'':
- set_reg_instance_num(st, num, name, val);
- return 1;
- default:
- return pc_setglobalreg(sd, num, val);
+ }
+ return 1;
+ case '$':
+ mapreg->setreg(num, val);
+ return 1;
+ case '#':
+ if (ref) {
+ script->set_reg_ref_num(st, ref, num, name, val);
+ } else if (name[1] == '#') {
+ pc_setaccountreg2(sd, num, val);
+ } else {
+ pc_setaccountreg(sd, num, val);
+ }
+ return 1;
+ case '.':
+ if (ref) {
+ script->set_reg_ref_num(st, ref, num, name, val);
+ } else if (name[1] == '@') {
+ script->set_reg_scope_num(st, &st->stack->scope, num, name, val);
+ } else {
+ script->set_reg_npc_num(st, &st->script->local, num, name, val);
+ }
+ return 1;
+ case '\'':
+ set_reg_instance_num(st, num, name, val);
+ return 1;
+ default:
+ if (ref) {
+ script->set_reg_ref_num(st, ref, num, name, val);
+ } else {
+ pc_setglobalreg(sd, num, val);
+ }
+ return 1;
}
}
}
@@ -13859,15 +13921,26 @@ BUILDIN(undisguise)
* Transform a bl to another class,
* @type unused
*------------------------------------------*/
-BUILDIN(classchange) {
- int class, type;
- struct block_list *bl=map->id2bl(st->oid);
+BUILDIN(classchange)
+{
+ int class, type, target;
+ struct block_list *bl = map->id2bl(st->oid);
+
+ if (bl == NULL)
+ return true;
- if(bl==NULL) return true;
+ class = script_getnum(st, 2);
+ type = script_getnum(st, 3);
+ target = script_hasdata(st, 4) ? script_getnum(st, 4) : 0;
- class = script_getnum(st,2);
- type=script_getnum(st,3);
- clif->class_change(bl, class, type);
+ if (target > 0) {
+ struct map_session_data *sd = script->charid2sd(st, target);
+ if (sd != NULL) {
+ clif->class_change(bl, class, type, sd);
+ }
+ } else {
+ clif->class_change(bl, class, type, NULL);
+ }
return true;
}
@@ -17540,6 +17613,55 @@ BUILDIN(getvariableofnpc)
return true;
}
+BUILDIN(getvariableofpc)
+{
+ const char* name;
+ struct script_data* data = script_getdata(st, 2);
+ struct map_session_data *sd = map->id2sd(script_getnum(st, 3));
+
+ if (!data_isreference(data)) {
+ ShowError("script:getvariableofpc: not a variable\n");
+ script->reportdata(data);
+ script_pushnil(st);
+ st->state = END;
+ return false;
+ }
+
+ name = reference_getname(data);
+
+ switch (*name)
+ {
+ case '#':
+ case '$':
+ case '.':
+ case '\'':
+ ShowError("script:getvariableofpc: illegal scope (not pc variable)\n");
+ script->reportdata(data);
+ script_pushnil(st);
+ st->state = END;
+ return false;
+ }
+
+ if (sd == NULL)
+ {
+ // player not found, return default value
+ if (script_hasdata(st, 4)) {
+ script_pushcopy(st, 4);
+ } else if (is_string_variable(name)) {
+ script_pushconststr(st, "");
+ } else {
+ script_pushint(st, 0);
+ }
+ return true;
+ }
+
+ if (!sd->regs.vars)
+ sd->regs.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
+
+ script->push_val(st->stack, C_NAME, reference_getuid(data), &sd->regs);
+ return true;
+}
+
/// Opens a warp portal.
/// Has no "portal opening" effect/sound, it opens the portal immediately.
///
@@ -21051,7 +21173,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getcartinventorylist,""),
BUILDIN_DEF(getskilllist,""),
BUILDIN_DEF(clearitem,""),
- BUILDIN_DEF(classchange,"ii"),
+ BUILDIN_DEF(classchange,"ii?"),
BUILDIN_DEF(misceffect,"i"),
BUILDIN_DEF(playbgm,"s"),
BUILDIN_DEF(playbgmall,"s?????"),
@@ -21199,6 +21321,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(sleep2,"i"),
BUILDIN_DEF(awake,"s"),
BUILDIN_DEF(getvariableofnpc,"rs"),
+ BUILDIN_DEF(getvariableofpc,"ri?"),
BUILDIN_DEF(warpportal,"iisii"),
BUILDIN_DEF2(homunculus_evolution,"homevolution",""), //[orn]
BUILDIN_DEF2(homunculus_mutate,"hommutate","?"),
diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc
index 57abf25e0..82d310832 100644
--- a/src/plugins/HPMHooking/HPMHooking.Defs.inc
+++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc
@@ -974,8 +974,8 @@ typedef void (*HPMHOOK_pre_clif_refreshlook) (struct block_list **bl, int *id, i
typedef void (*HPMHOOK_post_clif_refreshlook) (struct block_list *bl, int id, int type, int val, enum send_target target);
typedef void (*HPMHOOK_pre_clif_sendlook) (struct block_list **bl, int *id, int *type, int *val, int *val2, enum send_target *target);
typedef void (*HPMHOOK_post_clif_sendlook) (struct block_list *bl, int id, int type, int val, int val2, enum send_target target);
-typedef void (*HPMHOOK_pre_clif_class_change) (struct block_list **bl, int *class_, int *type);
-typedef void (*HPMHOOK_post_clif_class_change) (struct block_list *bl, int class_, int type);
+typedef void (*HPMHOOK_pre_clif_class_change) (struct block_list **bl, int *class_, int *type, struct map_session_data **sd);
+typedef void (*HPMHOOK_post_clif_class_change) (struct block_list *bl, int class_, int type, struct map_session_data *sd);
typedef void (*HPMHOOK_pre_clif_skill_delunit) (struct skill_unit **su);
typedef void (*HPMHOOK_post_clif_skill_delunit) (struct skill_unit *su);
typedef void (*HPMHOOK_pre_clif_skillunit_update) (struct block_list **bl);
diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
index 654c902d8..800fb8c76 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -7917,14 +7917,14 @@ void HP_clif_sendlook(struct block_list *bl, int id, int type, int val, int val2
}
return;
}
-void HP_clif_class_change(struct block_list *bl, int class_, int type) {
+void HP_clif_class_change(struct block_list *bl, int class_, int type, struct map_session_data *sd) {
int hIndex = 0;
if( HPMHooks.count.HP_clif_class_change_pre ) {
- void (*preHookFunc) (struct block_list **bl, int *class_, int *type);
+ void (*preHookFunc) (struct block_list **bl, int *class_, int *type, struct map_session_data **sd);
*HPMforce_return = false;
for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_class_change_pre; hIndex++ ) {
preHookFunc = HPMHooks.list.HP_clif_class_change_pre[hIndex].func;
- preHookFunc(&bl, &class_, &type);
+ preHookFunc(&bl, &class_, &type, &sd);
}
if( *HPMforce_return ) {
*HPMforce_return = false;
@@ -7932,13 +7932,13 @@ void HP_clif_class_change(struct block_list *bl, int class_, int type) {
}
}
{
- HPMHooks.source.clif.class_change(bl, class_, type);
+ HPMHooks.source.clif.class_change(bl, class_, type, sd);
}
if( HPMHooks.count.HP_clif_class_change_post ) {
- void (*postHookFunc) (struct block_list *bl, int class_, int type);
+ void (*postHookFunc) (struct block_list *bl, int class_, int type, struct map_session_data *sd);
for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_class_change_post; hIndex++ ) {
postHookFunc = HPMHooks.list.HP_clif_class_change_post[hIndex].func;
- postHookFunc(bl, class_, type);
+ postHookFunc(bl, class_, type, sd);
}
}
return;