diff options
author | malufett <malufett.eat.my.binaries@gmail.com> | 2014-12-20 00:13:35 +0800 |
---|---|---|
committer | malufett <malufett.eat.my.binaries@gmail.com> | 2014-12-20 00:13:35 +0800 |
commit | c4456ddbebccaca51ab040c60e3c586ed2cc0a10 (patch) | |
tree | 53d3e23baab08d63d88fdc055f6880f884aac640 /src/map | |
parent | 772cb2b111973c0c749e505ffd2685bb67e887bd (diff) | |
parent | 68f0fee76a73612263984da5d9de1e32b7ffe7da (diff) | |
download | hercules-c4456ddbebccaca51ab040c60e3c586ed2cc0a10.tar.gz hercules-c4456ddbebccaca51ab040c60e3c586ed2cc0a10.tar.bz2 hercules-c4456ddbebccaca51ab040c60e3c586ed2cc0a10.tar.xz hercules-c4456ddbebccaca51ab040c60e3c586ed2cc0a10.zip |
Merge branch 'master' of https://github.com/HerculesWS/Hercules
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/clif.c | 7 | ||||
-rw-r--r-- | src/map/itemdb.c | 9 | ||||
-rw-r--r-- | src/map/itemdb.h | 1 | ||||
-rw-r--r-- | src/map/npc.c | 53 | ||||
-rw-r--r-- | src/map/npc.h | 3 | ||||
-rw-r--r-- | src/map/pc.c | 2 | ||||
-rw-r--r-- | src/map/script.c | 181 | ||||
-rw-r--r-- | src/map/script.h | 1 | ||||
-rw-r--r-- | src/map/status.c | 8 | ||||
-rw-r--r-- | src/map/unit.c | 6 |
10 files changed, 240 insertions, 31 deletions
diff --git a/src/map/clif.c b/src/map/clif.c index 173175260..eff41422c 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -9597,7 +9597,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { if (map->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNPC)) npc->touch_areanpc(sd,sd->bl.m,sd->bl.x,sd->bl.y); else - sd->areanpc_id = 0; + npc->untouch_areanpc(sd, sd->bl.m, sd->bl.x, sd->bl.y); /* it broke at some point (e.g. during a crash), so we make it visibly dead again. */ if( !sd->status.hp && !pc_isdead(sd) && status->isdead(&sd->bl) ) @@ -17749,7 +17749,10 @@ void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) { void clif_maptypeproperty2(struct block_list *bl,enum send_target t) { #if PACKETVER >= 20121010 struct packet_maptypeproperty2 p; - struct map_session_data *sd = BL_CAST(BL_PC, bl); + struct map_session_data *sd = NULL; + nullpo_retv(bl); + + sd = BL_CAST(BL_PC, bl); p.PacketType = maptypeproperty2Type; p.type = 0x28; diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 508a0ccec..545ce9ba0 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -2054,6 +2054,14 @@ struct item_combo * itemdb_id2combo( unsigned short id ) { return itemdb->combos[id]; } +/** + * check is item have usable type + **/ +bool itemdb_is_item_usable(struct item_data *item) +{ + return item->type == IT_HEALING || item->type == IT_USABLE || item->type == IT_CASH; +} + /*========================================== * Initialize / Finalize *------------------------------------------*/ @@ -2337,4 +2345,5 @@ void itemdb_defaults(void) { itemdb->final_sub = itemdb_final_sub; itemdb->clear = itemdb_clear; itemdb->id2combo = itemdb_id2combo; + itemdb->is_item_usable = itemdb_is_item_usable; } diff --git a/src/map/itemdb.h b/src/map/itemdb.h index 5504d72d9..23339790e 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -610,6 +610,7 @@ struct itemdb_interface { int (*final_sub) (DBKey key, DBData *data, va_list ap); void (*clear) (bool total); struct item_combo * (*id2combo) (unsigned short id); + bool (*is_item_usable) (struct item_data *item); }; struct itemdb_interface *itemdb; diff --git a/src/map/npc.c b/src/map/npc.c index 8c2f61d58..8b5bbc83e 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -139,11 +139,22 @@ int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd) { char name[EVENT_NAME_LENGTH]; - if( sd->areanpc_id == nd->bl.id ) + if (sd->areanpc_id == nd->bl.id) return 0; snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script->config.ontouch2_name); - return npc->event(sd,name,2); + return npc->event(sd, name, 2); +} + +int npc_onuntouch_event(struct map_session_data *sd, struct npc_data *nd) +{ + char name[EVENT_NAME_LENGTH]; + + if (sd->areanpc_id != nd->bl.id) + return 0; + + snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script->config.onuntouch_name); + return npc->event(sd, name, 2); } /*========================================== @@ -964,6 +975,23 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y) return 0; } +/*========================================== + * Exec OnUnTouch for player if out range of area event + *------------------------------------------*/ +int npc_untouch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y) +{ + struct npc_data *nd; + nullpo_retr(1, sd); + + if (!sd->areanpc_id) + return 0; + + nd = (struct npc_data *) map->id2bl(sd->areanpc_id); + npc->onuntouch_event(sd, nd); + sd->areanpc_id = 0; + return 0; +} + // OnTouch NPC or Warp for Mobs // Return 1 if Warped int npc_touch_areanpc2(struct mob_data *md) @@ -1086,22 +1114,28 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range) { struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* bl) { struct npc_data *nd; + int distance = AREA_SIZE + 1; nullpo_retr(NULL, sd); - if(bl == NULL) return NULL; - if(bl->type != BL_NPC) return NULL; + if (bl == NULL) return NULL; + if (bl->type != BL_NPC) return NULL; nd = (TBL_NPC*)bl; - if(sd->state.using_fake_npc && sd->npc_id == bl->id) + if (sd->npc_id == bl->id) return nd; if (nd->class_<0) //Class-less npc, enable click from anywhere. return nd; - if (bl->m!=sd->bl.m || - bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 || - bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1) + if (distance > nd->area_size) + distance = nd->area_size; + + if (bl->m != sd->bl.m || + bl->x < sd->bl.x - distance || bl->x > sd->bl.x + distance || + bl->y < sd->bl.y - distance || bl->y > sd->bl.y + distance) + { return NULL; + } return nd; } @@ -2505,6 +2539,7 @@ struct npc_data* npc_create_npc(int m, int x, int y) nd->bl.m = m; nd->bl.x = x; nd->bl.y = y; + nd->area_size = AREA_SIZE + 1; return nd; } @@ -4607,6 +4642,7 @@ void npc_defaults(void) { npc->isnear = npc_isnear; npc->ontouch_event = npc_ontouch_event; npc->ontouch2_event = npc_ontouch2_event; + npc->onuntouch_event = npc_onuntouch_event; npc->enable_sub = npc_enable_sub; npc->enable = npc_enable; npc->name2id = npc_name2id; @@ -4631,6 +4667,7 @@ void npc_defaults(void) { npc->touch_areanpc_sub = npc_touch_areanpc_sub; npc->touchnext_areanpc = npc_touchnext_areanpc; npc->touch_areanpc = npc_touch_areanpc; + npc->untouch_areanpc = npc_untouch_areanpc; npc->touch_areanpc2 = npc_touch_areanpc2; npc->check_areanpc = npc_check_areanpc; npc->checknear = npc_checknear; diff --git a/src/map/npc.h b/src/map/npc.h index fba14d485..a5a2b4676 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -61,6 +61,7 @@ struct npc_data { int touching_id; int64 next_walktime; uint8 dir; + uint8 area_size; unsigned size : 2; @@ -181,6 +182,7 @@ struct npc_interface { bool (*isnear) (struct block_list *bl); int (*ontouch_event) (struct map_session_data *sd, struct npc_data *nd); int (*ontouch2_event) (struct map_session_data *sd, struct npc_data *nd); + int (*onuntouch_event) (struct map_session_data *sd, struct npc_data *nd); int (*enable_sub) (struct block_list *bl, va_list ap); int (*enable) (const char *name, int flag); struct npc_data* (*name2id) (const char *name); @@ -205,6 +207,7 @@ struct npc_interface { int (*touch_areanpc_sub) (struct block_list *bl, va_list ap); int (*touchnext_areanpc) (struct map_session_data *sd, bool leavemap); int (*touch_areanpc) (struct map_session_data *sd, int16 m, int16 x, int16 y); + int (*untouch_areanpc) (struct map_session_data *sd, int16 m, int16 x, int16 y); int (*touch_areanpc2) (struct mob_data *md); int (*check_areanpc) (int flag, int16 m, int16 x, int16 y, int16 range); struct npc_data* (*checknear) (struct map_session_data *sd, struct block_list *bl); diff --git a/src/map/pc.c b/src/map/pc.c index 5c6cac6e9..6c3a32152 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4238,7 +4238,7 @@ int pc_isUseitem(struct map_session_data *sd,int n) if( item == NULL ) return 0; //Not consumable item - if( item->type != IT_HEALING && item->type != IT_USABLE && item->type != IT_CASH ) + if (!itemdb->is_item_usable(item)) return 0; if( !item->script ) //if it has no script, you can't really consume it! return 0; diff --git a/src/map/script.c b/src/map/script.c index a458bab49..be73fe5b2 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -10091,22 +10091,62 @@ int buildin_getareausers_sub(struct block_list *bl,va_list ap) (*users)++; return 0; } + BUILDIN(getareausers) { - const char *str; - int16 m,x0,y0,x1,y1,users=0; //doubt we can have more then 32k users on - str=script_getstr(st,2); - x0=script_getnum(st,3); - y0=script_getnum(st,4); - x1=script_getnum(st,5); - y1=script_getnum(st,6); - if( (m=map->mapname2mapid(str))< 0) { - script_pushint(st,-1); - return true; + int16 m = -1, x0, y0, x1, y1; + int users = 0; + int idx = 2; + + if (script_hasdata(st, 2) && script_isstringtype(st, 2)) { + const char *str = script_getstr(st, 2); + if ((m = map->mapname2mapid(str)) < 0) { + script_pushint(st, -1); + return true; + } + idx = 3; + } else { + TBL_PC *sd = script->rid2sd(st); + if (!sd) { + script_pushint(st, -1); + return false; + } + m = sd->bl.m; + } + + if (script_hasdata(st, idx + 3)) { + x0 = script_getnum(st, idx + 0); + y0 = script_getnum(st, idx + 1); + x1 = script_getnum(st, idx + 2); + y1 = script_getnum(st, idx + 3); + } else if (st->oid) { + struct npc_data *nd = map->id2nd(st->oid); + if (!nd) { + script_pushint(st, -1); + return true; + } + if (script_hasdata(st, idx)) { + int range = script_getnum(st, idx); + x0 = nd->bl.x - range; + y0 = nd->bl.y - range; + x1 = nd->bl.x + range; + y1 = nd->bl.y + range; + } else if (nd->u.scr.xs != -1 && nd->u.scr.ys != -1) { + x0 = nd->bl.x - nd->u.scr.xs; + y0 = nd->bl.y - nd->u.scr.ys; + x1 = nd->bl.x + nd->u.scr.xs; + y1 = nd->bl.y + nd->u.scr.ys; + } else { + script_pushint(st, -1); + return true; + } + } else { + script_pushint(st, -1); + return false; } map->foreachinarea(script->buildin_getareausers_sub, - m,x0,y0,x1,y1,BL_PC,&users); - script_pushint(st,users); + m, x0, y0, x1, y1, BL_PC, &users); + script_pushint(st, users); return true; } @@ -13311,6 +13351,112 @@ BUILDIN(npcstop) { return true; } +// set click npc distance [4144] +BUILDIN(setnpcdistance) { + struct npc_data *nd = (struct npc_data *) map->id2bl (st->oid); + if (!nd) + return false; + + nd->area_size = script_getnum(st, 2); + + return true; +} + +// return current npc direction [4144] +BUILDIN(getnpcdir) +{ + struct npc_data *nd = 0; + + if (script_hasdata(st, 2)) + { + nd = npc->name2id (script_getstr(st, 2)); + } + if (!nd && !st->oid) + { + script_pushint(st, -1); + return true; + } + + if (!nd) + nd = (struct npc_data *) map->id2bl (st->oid); + + if (!nd) + { + script_pushint(st, -1); + return true; + } + + script_pushint(st, (int)nd->dir); + + return true; +} + +// set npc direction [4144] +BUILDIN(setnpcdir) +{ + int newdir; + struct npc_data *nd = 0; + + if (script_hasdata(st, 3)) + { + nd = npc->name2id (script_getstr(st, 2)); + newdir = script_getnum(st, 3); + } + else if (script_hasdata(st, 2)) + { + if (!st->oid) + return false; + + nd = (struct npc_data *) map->id2bl (st->oid); + newdir = script_getnum(st, 2); + } + if (!nd) + return false; + + if (newdir < 0) + newdir = 0; + else if (newdir > 7) + newdir = 7; + + nd->dir = newdir; + if (nd->ud) + nd->ud->dir = newdir; + + clif->clearunit_area(&nd->bl, CLR_OUTSIGHT); + clif->spawn(&nd->bl); + + return true; +} + +// return npc class [4144] +BUILDIN(getnpcclass) +{ + struct npc_data *nd = 0; + + if (script_hasdata(st, 2)) + { + nd = npc->name2id (script_getstr(st, 2)); + } + if (!nd && !st->oid) + { + script_pushint(st, -1); + return false; + } + + if (!nd) + nd = (struct npc_data *) map->id2bl(st->oid); + + if (!nd) + { + script_pushint(st, -1); + return false; + } + + script_pushint(st, (int)nd->class_); + + return true; +} + /*========================================== * getlook char info. getlook(arg) @@ -19275,7 +19421,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(getusers,"i"), BUILDIN_DEF(getmapguildusers,"si"), BUILDIN_DEF(getmapusers,"s"), - BUILDIN_DEF(getareausers,"siiii"), + BUILDIN_DEF(getareausers,"*"), BUILDIN_DEF(getareadropitem,"siiiiv"), BUILDIN_DEF(enablenpc,"s"), BUILDIN_DEF(disablenpc,"s"), @@ -19378,6 +19524,10 @@ void script_parse_builtin(void) { BUILDIN_DEF(npcspeed,"i"), // [Valaris] BUILDIN_DEF(npcwalkto,"ii"), // [Valaris] BUILDIN_DEF(npcstop,""), // [Valaris] + BUILDIN_DEF(setnpcdistance,"i"), // [4144] + BUILDIN_DEF(getnpcdir,"?"), // [4144] + BUILDIN_DEF(setnpcdir,"*"), // [4144] + BUILDIN_DEF(getnpcclass,"?"), // [4144] BUILDIN_DEF(getmapxy,"rrri?"), //by Lorky [Lupus] BUILDIN_DEF(checkoption1,"i"), BUILDIN_DEF(checkoption2,"i"), @@ -19970,8 +20120,9 @@ void script_defaults(void) { script->config.loadmap_event_name = "OnPCLoadMapEvent"; script->config.baselvup_event_name = "OnPCBaseLvUpEvent"; script->config.joblvup_event_name = "OnPCJobLvUpEvent"; - script->config.ontouch_name = "OnTouch_";//ontouch_name (runs on first visible char to enter area, picks another char if the first char leaves) - script->config.ontouch2_name = "OnTouch";//ontouch2_name (run whenever a char walks into the OnTouch area) + script->config.ontouch_name = "OnTouch_"; //ontouch_name (runs on first visible char to enter area, picks another char if the first char leaves) + script->config.ontouch2_name = "OnTouch"; //ontouch2_name (run whenever a char walks into the OnTouch area) + script->config.onuntouch_name = "OnUnTouch"; //onuntouch_name (run whenever a char walks from the OnTouch area) // for ENABLE_CASE_CHECK script->calc_hash_ci = calc_hash_ci; diff --git a/src/map/script.h b/src/map/script.h index e28abf970..548c0f261 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -343,6 +343,7 @@ struct Script_Config { const char* ontouch_name; const char* ontouch2_name; + const char* onuntouch_name; }; /** diff --git a/src/map/status.c b/src/map/status.c index 53672fccf..b1c86cc67 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -10466,8 +10466,12 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if(opt_flag&4) //Out of hiding, invoke on place. skill->unit_move(bl,timer->gettick(),1); - if(opt_flag&2 && sd && map->getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) - npc->touch_areanpc(sd,bl->m,bl->x,bl->y); //Trigger on-touch event. + if (opt_flag & 2 && sd) { + if (map->getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) + npc->touch_areanpc(sd,bl->m,bl->x,bl->y); //Trigger on-touch event. + else + npc->untouch_areanpc(sd, bl->m, bl->x, bl->y); + } ers_free(status->data_ers, sce); return 1; diff --git a/src/map/unit.c b/src/map/unit.c index 64885541f..0924e6cf2 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -309,7 +309,7 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { if (bl->prev == NULL) //Script could have warped char, abort remaining of the function. return 0; } else - sd->areanpc_id=0; + npc->untouch_areanpc(sd, bl->m, x, y); if( sd->md ) { // mercenary should be warped after being 3 seconds too far from the master [greenbox] if( !check_distance_bl(&sd->bl, &sd->md->bl, MAX_MER_DISTANCE) ) { @@ -767,7 +767,7 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool if (bl->prev == NULL) //Script could have warped char, abort remaining of the function. return 0; } else - sd->areanpc_id=0; + npc->untouch_areanpc(sd, bl->m, bl->x, bl->y); if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 ) { // Check if pet needs to be teleported. [Skotlex] @@ -867,7 +867,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag) if(map->getcell(bl->m, bl->x, bl->y, CELL_CHKNPC)) { npc->touch_areanpc(sd, bl->m, bl->x, bl->y); } else { - sd->areanpc_id = 0; + npc->untouch_areanpc(sd, bl->m, bl->x, bl->y);; } } } |