summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/int_party.c34
-rw-r--r--src/map/party.c42
-rw-r--r--src/map/pc.c1
-rw-r--r--src/map/script.c449
-rw-r--r--src/map/unit.c9
5 files changed, 304 insertions, 231 deletions
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/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/pc.c b/src/map/pc.c
index 2cf5d75b4..9ef7d084f 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -387,7 +387,6 @@ int pc_banding(struct map_session_data *sd, uint16 skill_lv) {
return c;
}
-// Increases a player's fame points and displays a notice to him
/**
* Increases a player's fame points and displays a notice to them.
*
diff --git a/src/map/script.c b/src/map/script.c
index a1886d043..48c377d24 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 = "";
@@ -2919,7 +2919,7 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
} else if( reference_toparam(data) ) {
data->u.num = pc->readparam(sd, reference_getparamtype(data));
} else {
- switch(prefix) {
+ switch (prefix) {
case '@':
if (data->ref) {
data->u.num = script->get_val_ref_num(st, data->ref, data);
@@ -2933,7 +2933,7 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
case '#':
if (data->ref) {
data->u.num = script->get_val_ref_num(st, data->ref, data);
- } else if(name[1] == '#') {
+ } 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
@@ -2960,7 +2960,6 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
break;
}
}
-
}
data->ref = NULL;
@@ -3133,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;
@@ -3317,7 +3321,7 @@ 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) {
@@ -3329,7 +3333,8 @@ int set_reg(struct script_state *st, struct map_session_data *sd, int64 num, con
}
return 1;
case '$':
- return mapreg->setregstr(num, str);
+ mapreg->setregstr(num, str);
+ return 1;
case '#':
if (ref) {
script->set_reg_ref_str(st, ref, num, name, str);
@@ -3364,16 +3369,17 @@ int set_reg(struct script_state *st, struct map_session_data *sd, int64 num, con
// 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;
}
@@ -3389,7 +3395,8 @@ int set_reg(struct script_state *st, struct map_session_data *sd, int64 num, con
}
return 1;
case '$':
- return mapreg->setreg(num, val);
+ mapreg->setreg(num, val);
+ return 1;
case '#':
if (ref) {
script->set_reg_ref_num(st, ref, num, name, val);
@@ -6665,61 +6672,67 @@ BUILDIN(warpparty)
}
/*==========================================
* Warpguild - [Fredzilla]
- * Syntax: warpguild "mapname",x,y,Guild_ID;
+ * Syntax: warpguild "mapname",x,y,Guild_ID,{"from_mapname"};
*------------------------------------------*/
BUILDIN(warpguild)
{
struct map_session_data *sd = NULL;
- struct map_session_data *pl_sd;
struct guild* g;
- struct s_mapiterator* iter;
int type;
+ int i;
+ int16 map_id = -1;
- const char* str = script_getstr(st,2);
- int x = script_getnum(st,3);
- int y = script_getnum(st,4);
- int gid = script_getnum(st,5);
+ const char *str = script_getstr(st, 2);
+ int x = script_getnum(st, 3);
+ int y = script_getnum(st, 4);
+ int gid = script_getnum(st, 5);
+
+ if (script_hasdata(st, 6)) {
+ map_id = map->mapname2mapid(script_getstr(st, 6));
+ }
g = guild->search(gid);
- if( g == NULL )
+ if (g == NULL)
return true;
- type = ( strcmp(str,"Random")==0 ) ? 0
- : ( strcmp(str,"SavePointAll")==0 ) ? 1
- : ( strcmp(str,"SavePoint")==0 ) ? 2
+ type = (strcmp(str, "Random") == 0) ? 0
+ : (strcmp(str, "SavePointAll") == 0) ? 1
+ : (strcmp(str, "SavePoint") == 0) ? 2
: 3;
- if( type == 2 && ( sd = script->rid2sd(st) ) == NULL )
+ if (type == 2 && (sd = script->rid2sd(st)) == NULL)
{// "SavePoint" uses save point of the currently attached player
return true;
}
- iter = mapit_getallusers();
- for (pl_sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); pl_sd = BL_UCAST(BL_PC, mapit->next(iter))) {
- if( pl_sd->status.guild_id != gid )
- continue;
+ for (i = 0; i < MAX_GUILD; i++) {
+ if (g->member[i].online && g->member[i].sd != NULL) {
+ struct map_session_data *pl_sd = g->member[i].sd;
- switch( type )
- {
+ if (map_id >= 0 && map_id != pl_sd->bl.m)
+ continue;
+
+ switch (type)
+ {
case 0: // Random
- if(!map->list[pl_sd->bl.m].flag.nowarp)
- pc->randomwarp(pl_sd,CLR_TELEPORT);
+ if (!map->list[pl_sd->bl.m].flag.nowarp)
+ pc->randomwarp(pl_sd, CLR_TELEPORT);
break;
case 1: // SavePointAll
- if(!map->list[pl_sd->bl.m].flag.noreturn)
- pc->setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT);
+ if (!map->list[pl_sd->bl.m].flag.noreturn)
+ pc->setpos(pl_sd, pl_sd->status.save_point.map, pl_sd->status.save_point.x, pl_sd->status.save_point.y, CLR_TELEPORT);
break;
case 2: // SavePoint
- if(!map->list[pl_sd->bl.m].flag.noreturn)
- pc->setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
+ if (!map->list[pl_sd->bl.m].flag.noreturn)
+ pc->setpos(pl_sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
break;
case 3: // m,x,y
- if(!map->list[pl_sd->bl.m].flag.noreturn && !map->list[pl_sd->bl.m].flag.nowarp)
- pc->setpos(pl_sd,script->mapindexname2id(st,str),x,y,CLR_TELEPORT);
+ if (!map->list[pl_sd->bl.m].flag.noreturn && !map->list[pl_sd->bl.m].flag.nowarp)
+ pc->setpos(pl_sd, script->mapindexname2id(st, str), x, y, CLR_TELEPORT);
break;
+ }
}
}
- mapit->free(iter);
return true;
}
@@ -8740,39 +8753,48 @@ BUILDIN(getguildmember)
*------------------------------------------*/
BUILDIN(strcharinfo)
{
- int num;
struct guild* g;
struct party_data* p;
- struct map_session_data *sd = script->rid2sd(st);
- if (sd == NULL) //Avoid crashing....
+ struct map_session_data *sd;
+
+ if (script_hasdata(st, 4))
+ sd = map->id2sd(script_getnum(st, 4));
+ else
+ sd = script->rid2sd(st);
+
+ if (sd == NULL) {
+ if(script_hasdata(st, 3)) {
+ script_pushcopy(st, 3);
+ } else {
+ script_pushconststr(st, "");
+ }
return true;
+ }
- num=script_getnum(st,2);
- switch(num) {
- case 0:
- script_pushstrcopy(st,sd->status.name);
- break;
- case 1:
- if( ( p = party->search(sd->status.party_id) ) != NULL ) {
- script_pushstrcopy(st,p->party.name);
- } else {
- script_pushconststr(st,"");
- }
- break;
- case 2:
- if( ( g = sd->guild ) != NULL ) {
- script_pushstrcopy(st,g->name);
- } else {
- script_pushconststr(st,"");
- }
- break;
- case 3:
- script_pushconststr(st,map->list[sd->bl.m].name);
- break;
- default:
- ShowWarning("buildin_strcharinfo: unknown parameter.\n");
- script_pushconststr(st,"");
- break;
+ switch (script_getnum(st, 2)) {
+ case 0:
+ script_pushstrcopy(st, sd->status.name);
+ break;
+ case 1:
+ if ((p = party->search(sd->status.party_id)) != NULL) {
+ script_pushstrcopy(st, p->party.name);
+ } else {
+ script_pushconststr(st, "");
+ }
+ break;
+ case 2:
+ if ((g = sd->guild) != NULL) {
+ script_pushstrcopy(st, g->name);
+ } else {
+ script_pushconststr(st, "");
+ }
+ break;
+ case 3:
+ script_pushconststr(st, map->list[sd->bl.m].name);
+ break;
+ default:
+ ShowWarning("script:strcharinfo: unknown parameter.\n");
+ script_pushconststr(st, "");
}
return true;
@@ -8789,41 +8811,51 @@ BUILDIN(strcharinfo)
*------------------------------------------*/
BUILDIN(strnpcinfo)
{
- int num;
char *buf,*name=NULL;
- struct npc_data *nd = map->id2nd(st->oid);
+ struct npc_data *nd;
+
+ if (script_hasdata(st, 4))
+ nd = map->id2nd(script_getnum(st, 4));
+ else
+ nd = map->id2nd(st->oid);
+
if (nd == NULL) {
- script_pushconststr(st, "");
+ if (script_hasdata(st, 3)) {
+ script_pushcopy(st, 3);
+ } else {
+ script_pushconststr(st, "");
+ }
return true;
}
- num = script_getnum(st,2);
- switch(num) {
- case 0: // display name
+ switch (script_getnum(st,2)) {
+ case 0: // display name
+ name = aStrdup(nd->name);
+ break;
+ case 1: // visible part of display name
+ if ((buf = strchr(nd->name,'#')) != NULL) {
name = aStrdup(nd->name);
- break;
- case 1: // visible part of display name
- if((buf = strchr(nd->name,'#')) != NULL)
- {
- name = aStrdup(nd->name);
- name[buf - nd->name] = 0;
- } else // Return the name, there is no '#' present
- name = aStrdup(nd->name);
- break;
- case 2: // # fragment
- if((buf = strchr(nd->name,'#')) != NULL)
- name = aStrdup(buf+1);
- break;
- case 3: // unique name
- name = aStrdup(nd->exname);
- break;
- case 4: // map name
- if( nd->bl.m >= 0 ) // Only valid map indexes allowed (issue:8034)
- name = aStrdup(map->list[nd->bl.m].name);
- break;
+ name[buf - nd->name] = 0;
+ } else { // Return the name, there is no '#' present
+ name = aStrdup(nd->name);
+ }
+ break;
+ case 2: // # fragment
+ if ((buf = strchr(nd->name,'#')) != NULL) {
+ name = aStrdup(buf+1);
+ }
+ break;
+ case 3: // unique name
+ name = aStrdup(nd->exname);
+ break;
+ case 4: // map name
+ if (nd->bl.m >= 0) { // Only valid map indexes allowed (issue:8034)
+ name = aStrdup(map->list[nd->bl.m].name);
+ }
+ break;
}
- if(name)
+ if (name)
script_pushstr(st, name);
else
script_pushconststr(st, "");
@@ -10759,19 +10791,29 @@ BUILDIN(donpcevent)
*------------------------------------------*/
BUILDIN(addtimer)
{
- int tick = script_getnum(st,2);
+ int tick = script_getnum(st, 2);
const char* event = script_getstr(st, 3);
struct map_session_data *sd;
script->check_event(st, event);
- sd = script->rid2sd(st);
- if( sd == NULL )
- return true;
- if (!pc->addeventtimer(sd,tick,event)) {
- ShowWarning("buildin_addtimer: Event timer is full, can't add new event timer. (cid:%d timer:%s)\n",sd->status.char_id,event);
+ if (script_hasdata(st, 4))
+ sd = map->id2sd(script_getnum(st, 4));
+ else
+ sd = script->rid2sd(st);
+
+ if (sd == NULL) {
+ script_pushint(st, 0);
+ return false;
+ }
+
+ if (!pc->addeventtimer(sd, tick, event)) {
+ ShowWarning("script:addtimer: Event timer is full, can't add new event timer. (cid:%d timer:%s)\n", sd->status.char_id, event);
+ script_pushint(st, 0);
return false;
}
+
+ script_pushint(st, 1);
return true;
}
/*==========================================
@@ -10782,12 +10824,17 @@ BUILDIN(deltimer)
struct map_session_data *sd;
event=script_getstr(st, 2);
- sd = script->rid2sd(st);
- if( sd == NULL )
+
+ if (script_hasdata(st, 3))
+ sd = map->id2sd(script_getnum(st, 3));
+ else
+ sd = script->rid2sd(st);
+
+ if (sd == NULL)
return true;
script->check_event(st, event);
- pc->deleventtimer(sd,event);
+ pc->deleventtimer(sd, event);
return true;
}
/*==========================================
@@ -10798,14 +10845,19 @@ BUILDIN(addtimercount)
int tick;
struct map_session_data *sd;
- event=script_getstr(st, 2);
- tick=script_getnum(st,3);
- sd = script->rid2sd(st);
- if( sd == NULL )
+ event = script_getstr(st, 2);
+ tick = script_getnum(st, 3);
+
+ if (script_hasdata(st, 4))
+ sd = map->id2sd(script_getnum(st, 4));
+ else
+ sd = script->rid2sd(st);
+
+ if (sd == NULL)
return true;
script->check_event(st, event);
- pc->addeventtimercount(sd,event,tick);
+ pc->addeventtimercount(sd, event, tick);
return true;
}
@@ -16549,11 +16601,7 @@ BUILDIN(escape_sql)
return true;
}
-BUILDIN(getd)
-{
- struct block_list *bl = NULL;
- struct map_session_data *sd;
- struct npc_data *nd;
+BUILDIN(getd) {
char varname[100];
const char *buffer;
int elem;
@@ -16563,63 +16611,8 @@ BUILDIN(getd)
if (sscanf(buffer, "%99[^[][%d]", varname, &elem) < 2)
elem = 0;
- if (strlen(varname) < 1) {
- ShowError("script:getd: variable cannot be empty\n");
- script->reportdata(script_getdata(st, 2));
- script_pushnil(st);
- st->state = END;
- return false;
- }
-
- if (script_hasdata(st, 3)) {
- bl = map->id2bl(script_getnum(st, 3));
-
- if (bl == NULL) {
- // being not found, push default value
- if (script_hasdata(st, 4)) {
- script_pushcopy(st, 4);
- } else if (varname[strlen(varname) - 1] == '$') {
- script_pushconststr(st, "");
- } else {
- script_pushint(st, 0);
- }
- return false;
- } else if (bl->type == BL_NPC && (varname[0] != '.' || varname[1] == '@')) {
- ShowError("script:getd: invalid scope (not npc variable)\n");
- script->reportdata(script_getdata(st, 2));
- script_pushnil(st);
- st->state = END;
- return false;
- } else if (bl->type == BL_PC && (varname[0] == '.' || varname[0] == '$' || varname[0] == '\'')) {
- ShowError("script:getd: invalid scope (not pc variable)\n");
- script->reportdata(script_getdata(st, 2));
- script_pushnil(st);
- st->state = END;
- return false;
- }
- }
-
// Push the 'pointer' so it's more flexible [Lance]
-
- if (bl != NULL) {
- switch (bl->type) {
- case BL_PC:
- sd = map->id2sd(bl->id);
- script->push_val(st->stack, C_NAME, reference_uid(script->add_str(varname), elem), &sd->regs);
- break;
- case BL_NPC:
- nd = map->id2nd(bl->id);
- script->push_val(st->stack, C_NAME, reference_uid(script->add_str(varname), elem), &nd->u.scr.script->local);
- break;
- default:
- ShowError("script:getd: invalid being type (not npc or pc)\n");
- script_pushnil(st);
- st->state = END;
- return false;
- }
- } else {
- script->push_val(st->stack, C_NAME, reference_uid(script->add_str(varname), elem), NULL);
- }
+ script->push_val(st->stack, C_NAME, reference_uid(script->add_str(varname), elem),NULL);
return true;
}
@@ -17646,6 +17639,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.
///
@@ -20965,7 +21007,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(areawarp,"siiiisii??"),
BUILDIN_DEF(warpchar,"siii"), // [LuzZza]
BUILDIN_DEF(warpparty,"siii?"), // [Fredzilla] [Paradox924X]
- BUILDIN_DEF(warpguild,"siii"), // [Fredzilla]
+ BUILDIN_DEF(warpguild,"siii?"), // [Fredzilla]
BUILDIN_DEF(setlook,"ii"),
BUILDIN_DEF(changelook,"ii"), // Simulates but don't Store it
BUILDIN_DEF2(__setr,"set","rv"),
@@ -21006,8 +21048,8 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getguildmaster,"i"),
BUILDIN_DEF(getguildmasterid,"i"),
BUILDIN_DEF(getguildmember,"i?"),
- BUILDIN_DEF(strcharinfo,"i"),
- BUILDIN_DEF(strnpcinfo,"i"),
+ BUILDIN_DEF(strcharinfo,"i??"),
+ BUILDIN_DEF(strnpcinfo,"i??"),
BUILDIN_DEF(charid2rid,"i"),
BUILDIN_DEF(getequipid,"i"),
BUILDIN_DEF(getequipname,"i"),
@@ -21070,9 +21112,9 @@ void script_parse_builtin(void) {
BUILDIN_DEF(clone,"siisi????"),
BUILDIN_DEF(doevent,"s"),
BUILDIN_DEF(donpcevent,"s"),
- BUILDIN_DEF(addtimer,"is"),
- BUILDIN_DEF(deltimer,"s"),
- BUILDIN_DEF(addtimercount,"si"),
+ BUILDIN_DEF(addtimer,"is?"),
+ BUILDIN_DEF(deltimer,"s?"),
+ BUILDIN_DEF(addtimercount,"si?"),
BUILDIN_DEF(initnpctimer,"??"),
BUILDIN_DEF(stopnpctimer,"??"),
BUILDIN_DEF(startnpctimer,"??"),
@@ -21257,7 +21299,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(md5,"s"),
BUILDIN_DEF(swap,"rr"),
// [zBuffer] List of dynamic var commands --->
- BUILDIN_DEF(getd,"s??"),
+ BUILDIN_DEF(getd,"s"),
BUILDIN_DEF(setd,"sv"),
// <--- [zBuffer] List of dynamic var commands
BUILDIN_DEF(petstat,"i"),
@@ -21305,6 +21347,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/map/unit.c b/src/map/unit.c
index feb11f89e..7d68bef66 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -668,11 +668,12 @@ void unit_run_hit(struct block_list *bl, struct status_change *sc, struct map_se
ud->state.running = 0;
status_change_end(bl, type, INVALID_TIMER);
- if( type == SC_RUN ) {
- skill->blown(bl,bl,skill->get_blewcount(TK_RUN,lv),unit->getdir(bl),0);
+ if (type == SC_RUN) {
+ if (lv > 0)
+ skill->blown(bl, bl, skill->get_blewcount(TK_RUN, lv), unit->getdir(bl), 0);
clif->fixpos(bl); //Why is a clif->slide (skill->blown) AND a fixpos needed? Ask Aegis.
- clif->sc_end(bl,bl->id,AREA,SI_TING);
- } else if( sd ) {
+ clif->sc_end(bl, bl->id, AREA, SI_TING);
+ } else if (sd) {
clif->fixpos(bl);
skill->castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, timer->gettick(), SD_LEVEL);
}