diff options
author | Haru <haru@dotalux.com> | 2013-07-19 17:10:09 +0200 |
---|---|---|
committer | Haru <haru@dotalux.com> | 2013-07-21 18:45:31 +0200 |
commit | 5f7320cda31036120ab11d9f719b34bf2809cbb4 (patch) | |
tree | 273a3ca6ae1c597c7eb70e8da8c6f91e79bf89e9 | |
parent | 9bcb1423969870a6b60819e6f3846fe0235e28a9 (diff) | |
download | hercules-5f7320cda31036120ab11d9f719b34bf2809cbb4.tar.gz hercules-5f7320cda31036120ab11d9f719b34bf2809cbb4.tar.bz2 hercules-5f7320cda31036120ab11d9f719b34bf2809cbb4.tar.xz hercules-5f7320cda31036120ab11d9f719b34bf2809cbb4.zip |
Fixed various unit* script commands to work with NPCs (issue #7548)
http://hercules.ws/board/tracker/issue-7548-unitwalk-do-not-work/
Follow-up to 20bdc01.
Thanks to Ind for his support and suggestions.
Signed-off-by: Haru <haru@dotalux.com>
-rw-r--r-- | src/map/script.c | 59 | ||||
-rw-r--r-- | src/map/unit.c | 26 | ||||
-rw-r--r-- | src/map/unit.h | 1 |
3 files changed, 50 insertions, 36 deletions
diff --git a/src/map/script.c b/src/map/script.c index 27368a174..04d834f74 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -12619,20 +12619,15 @@ BUILDIN(npctalk) } // change npc walkspeed [Valaris] -BUILDIN(npcspeed) -{ +BUILDIN(npcspeed) { struct npc_data* nd; int speed; speed = script_getnum(st,2); - nd =(struct npc_data *)iMap->id2bl(st->oid); + nd = (struct npc_data *)iMap->id2bl(st->oid); if( nd ) { - if( nd->ud == &npc_base_ud ) { - nd->ud = NULL; - CREATE(nd->ud, struct unit_data, 1); - unit_dataset(&nd->bl); - } + unit_bl2ud2(&nd->bl); // ensure nd->ud is safe to edit nd->speed = speed; nd->ud->state.speed_changed = 1; } @@ -12647,13 +12642,8 @@ BUILDIN(npcwalkto) { x=script_getnum(st,2); y=script_getnum(st,3); - if(nd) { - if( nd->ud == &npc_base_ud ) { - nd->ud = NULL; - CREATE(nd->ud, struct unit_data, 1); - unit_dataset(&nd->bl); - } - + if( nd ) { + unit_bl2ud2(&nd->bl); // ensure nd->ud is safe to edit if (!nd->status.hp) { status_calc_npc(nd, true); } else { @@ -12665,11 +12655,11 @@ BUILDIN(npcwalkto) { return true; } // stop an npc's movement [Valaris] -BUILDIN(npcstop) -{ - struct npc_data *nd=(struct npc_data *)iMap->id2bl(st->oid); +BUILDIN(npcstop) { + struct npc_data *nd = (struct npc_data *)iMap->id2bl(st->oid); - if(nd) { + if( nd ) { + unit_bl2ud2(&nd->bl); // ensure nd->ud is safe to edit unit_stop_walking(&nd->bl,1|4); } @@ -14910,23 +14900,23 @@ BUILDIN(pcstopfollow) /// /// unitwalk(<unit_id>,<x>,<y>) -> <bool> /// unitwalk(<unit_id>,<map_id>) -> <bool> -BUILDIN(unitwalk) -{ +BUILDIN(unitwalk) { struct block_list* bl; bl = iMap->id2bl(script_getnum(st,2)); - if( bl == NULL ) - { + if( bl == NULL ) { script_pushint(st, 0); + return true; } - else if( script_hasdata(st,4) ) - { + + if( bl->type == BL_NPC ) { + unit_bl2ud2(bl); // ensure the ((TBL_NPC*)bl)->ud is safe to edit + } + if( script_hasdata(st,4) ) { int x = script_getnum(st,3); int y = script_getnum(st,4); script_pushint(st, unit_walktoxy(bl,x,y,0));// We'll use harder calculations. - } - else - { + } else { int map_id = script_getnum(st,3); script_pushint(st, unit_walktobl(bl,iMap->id2bl(map_id),65025,1)); } @@ -14950,8 +14940,7 @@ BUILDIN(unitkill) /// Returns if it was successfull /// /// unitwarp(<unit_id>,"<map name>",<x>,<y>) -> <bool> -BUILDIN(unitwarp) -{ +BUILDIN(unitwarp) { int unit_id; int map; short x; @@ -14974,10 +14963,12 @@ BUILDIN(unitwarp) else map = iMap->mapname2mapid(mapname); - if( map >= 0 && bl != NULL ) + if( map >= 0 && bl != NULL ) { + unit_bl2ud2(bl); // ensure ((TBL_NPC*)bl)->ud is safe to edit script_pushint(st, unit_warp(bl,map,x,y,CLR_OUTSIGHT)); - else + } else { script_pushint(st, 0); + } return true; } @@ -15047,8 +15038,7 @@ BUILDIN(unitattack) /// Makes the unit stop attacking and moving /// /// unitstop <unit_id>; -BUILDIN(unitstop) -{ +BUILDIN(unitstop) { int unit_id; struct block_list* bl; @@ -15057,6 +15047,7 @@ BUILDIN(unitstop) bl = iMap->id2bl(unit_id); if( bl != NULL ) { + unit_bl2ud2(bl); // ensure ((TBL_NPC*)bl)->ud is safe to edit unit_stop_attack(bl); unit_stop_walking(bl,4); if( bl->type == BL_MOB ) diff --git a/src/map/unit.c b/src/map/unit.c index ce097dda0..4a8a87920 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -44,8 +44,13 @@ const short dirx[8]={0,-1,-1,-1,0,1,1,1}; const short diry[8]={1,1,0,-1,-1,-1,0,1}; -struct unit_data* unit_bl2ud(struct block_list *bl) -{ +/** + * Returns the unit_data for the given block_list. If the object is using + * shared unit_data (i.e. in case of BL_NPC), it returns the shared data. + * @param bl block_list to process + * @return a pointer to the given object's unit_data + **/ +struct unit_data* unit_bl2ud(struct block_list *bl) { if( bl == NULL) return NULL; if( bl->type == BL_PC) return &((struct map_session_data*)bl)->ud; if( bl->type == BL_MOB) return &((struct mob_data*)bl)->ud; @@ -57,6 +62,23 @@ struct unit_data* unit_bl2ud(struct block_list *bl) return NULL; } +/** + * Returns the unit_data for the given block_list. If the object is using + * shared unit_data (i.e. in case of BL_NPC), it recreates a copy of the + * data so that it's safe to modify. + * @param bl block_list to process + * @return a pointer to the given object's unit_data + */ +struct unit_data* unit_bl2ud2(struct block_list *bl) { + if( bl && bl->type == BL_NPC && ((struct npc_data*)bl)->ud == &npc_base_ud ) { + struct npc_data *nd = (struct npc_data *)bl; + nd->ud = NULL; + CREATE(nd->ud, struct unit_data, 1); + unit_dataset(&nd->bl); + } + return unit_bl2ud(bl); +} + static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data); static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data); diff --git a/src/map/unit.h b/src/map/unit.h index 9d1c02a31..a4c7fc0cc 100644 --- a/src/map/unit.h +++ b/src/map/unit.h @@ -124,6 +124,7 @@ void unit_dataset(struct block_list *bl); int unit_fixdamage(struct block_list *src,struct block_list *target,unsigned int tick,int sdelay,int ddelay,int damage,int div,int type,int damage2); // ‚»‚Ì‘¼ struct unit_data* unit_bl2ud(struct block_list *bl); +struct unit_data* unit_bl2ud2(struct block_list *bl); void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype); void unit_free_pc(struct map_session_data *sd); #define unit_remove_map(bl,clrtype) unit_remove_map_(bl,clrtype,__FILE__,__LINE__,__func__) |