From 45e91e2a3a54920159e39a1a944de5bbd44fc547 Mon Sep 17 00:00:00 2001 From: Lemongrass3110 Date: Fri, 30 Jun 2017 18:31:06 +0200 Subject: [PATCH] Added clan emblems to the NPCs (#2221) * Added clan emblems to the NPCs * Partial merge of/based on idathena/trunk@1f84c5d Thanks to @exneval --- npc/re/other/clans.txt | 32 ++++++ src/map/clif.c | 46 ++++++--- src/map/clif.h | 2 +- src/map/npc.c | 81 +++++++-------- src/map/npc.h | 5 + src/map/status.c | 226 ++++++++++++++++++++++++++--------------- src/map/status.h | 2 +- 7 files changed, 255 insertions(+), 139 deletions(-) diff --git a/npc/re/other/clans.txt b/npc/re/other/clans.txt index f0316fe6af..d8dba17dd4 100644 --- a/npc/re/other/clans.txt +++ b/npc/re/other/clans.txt @@ -7,8 +7,24 @@ //= 1.0 Initial release. [Lemongrass] //= 1.1 iRO translation. [RagnarokNova] //= 1.2 Dialogue cleanup. [Aleos] +//= 1.3 Added clan helper. [exneval] //============================================================ +prontera,138,183,7 script Clan Helper 703,{ + mes "[Clan Helper]"; + mes "Do you want to build connections without being in a guild?"; + next; + mes "[Clan Helper]"; + mes "Can't find the perfect guild for yourself?"; + next; + mes "[Clan Helper]"; + mes "You can join or leave clans freely! Just join!"; + next; + mes "[Clan Helper]"; + mes "Now, come on in and meet the masters of the Kingdom's best clans!"; + close; +} + prt_in,33,114,5 script Raffam Oranpere 10058,{ cutin "laperm01.bmp", 2; mes "[Raffam Oranpere]"; @@ -145,6 +161,10 @@ prt_in,33,114,5 script Raffam Oranpere 10058,{ close2; cutin "", 255; end; + +OnInit: + sc_start2 SC_SWORDCLAN, -1, 0, SWORDCLAN, 10000, SCSTART_NOAVOID, getnpcid(0); + end; } prt_in,35,114,5 script Devon Aire 10059,{ @@ -308,6 +328,10 @@ prt_in,35,114,5 script Devon Aire 10059,{ close2; cutin "", 255; end; + +OnInit: + sc_start2 SC_ARCWANDCLAN, -1, 0, ARCWANDCLAN, 10000, SCSTART_NOAVOID, getnpcid(0); + end; } prt_in,37,114,5 script Berman Aire 10060,{ @@ -448,6 +472,10 @@ prt_in,37,114,5 script Berman Aire 10060,{ close2; cutin "", 255; end; + +OnInit: + sc_start2 SC_GOLDENMACECLAN, -1, 0, GOLDENMACECLAN, 10000, SCSTART_NOAVOID, getnpcid(0); + end; } prt_in,39,114,5 script Shaam Rumi 10027,{ @@ -597,4 +625,8 @@ prt_in,39,114,5 script Shaam Rumi 10027,{ close2; cutin "", 255; end; + +OnInit: + sc_start2 SC_CROSSBOWCLAN, -1, 0, CROSSBOWCLAN, 10000, SCSTART_NOAVOID, getnpcid(0); + end; } diff --git a/src/map/clif.c b/src/map/clif.c index 7454cecd81..d982a9b4f4 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1484,7 +1484,7 @@ int clif_spawn(struct block_list *bl) clif_spiritcharm(sd); if (sd->status.robe) clif_refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA); - clif_efst_status_change_sub(sd, bl, AREA); + clif_efst_status_change_sub(bl, bl, AREA); clif_hat_effects(sd,bl,AREA); } break; @@ -1504,6 +1504,7 @@ int clif_spawn(struct block_list *bl) clif_specialeffect(&nd->bl,423,AREA); else if( nd->size == SZ_MEDIUM ) clif_specialeffect(&nd->bl,421,AREA); + clif_efst_status_change_sub(bl, bl, AREA); } break; case BL_PET: @@ -4660,7 +4661,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) clif_sendbgemblem_single(sd->fd,tsd); if ( tsd->status.robe ) clif_refreshlook(&sd->bl,bl->id,LOOK_ROBE,tsd->status.robe,SELF); - clif_efst_status_change_sub(sd, bl, SELF); + clif_efst_status_change_sub(&sd->bl, bl, SELF); clif_hat_effects(sd,bl,SELF); } break; @@ -4677,6 +4678,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) clif_specialeffect_single(bl,423,sd->fd); else if( nd->size == SZ_MEDIUM ) clif_specialeffect_single(bl,421,sd->fd); + clif_efst_status_change_sub(&sd->bl, bl, SELF); } break; case BL_MOB: @@ -6050,24 +6052,38 @@ void clif_status_change(struct block_list *bl, int type, int flag, int tick, int /** * Send any active EFST to those around. - * @param sd: Player to send the packet to + * @param tbl: Unit to send the packet to * @param bl: Objects walking into view * @param target: Client send type */ -void clif_efst_status_change_sub(struct map_session_data *sd, struct block_list *bl, enum send_target target) { - struct map_session_data *tsd = NULL; +void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl, enum send_target target) { unsigned char i; + struct sc_display_entry **sc_display; + unsigned char sc_display_count; - nullpo_retv(sd); nullpo_retv(bl); - if (target == SELF) - tsd = (TBL_PC *)bl; - else - tsd = sd; + switch( bl->type ){ + case BL_PC: { + struct map_session_data* sd = (struct map_session_data*)bl; - for (i = 0; i < tsd->sc_display_count; i++) { - enum sc_type type = tsd->sc_display[i]->type; + sc_display = sd->sc_display; + sc_display_count = sd->sc_display_count; + } + break; + case BL_NPC: { + struct npc_data* nd = (struct npc_data*)bl; + + sc_display = nd->sc_display; + sc_display_count = nd->sc_display_count; + } + break; + default: + return; + } + + for (i = 0; i < sc_display_count; i++) { + enum sc_type type = sc_display[i]->type; struct status_change *sc = status_get_sc(bl); const struct TimerData *td = (sc && sc->data[type] ? get_timer(sc->data[type]->timer) : NULL); int tick = 0; @@ -6075,9 +6091,9 @@ void clif_efst_status_change_sub(struct map_session_data *sd, struct block_list if (td) tick = DIFF_TICK(td->tick, gettick()); #if PACKETVER > 20120418 - clif_efst_status_change((target == SELF) ? &sd->bl : bl, bl->id, target, StatusIconChangeTable[type], tick, tsd->sc_display[i]->val1, tsd->sc_display[i]->val2, tsd->sc_display[i]->val3); + clif_efst_status_change(tbl, bl->id, target, StatusIconChangeTable[type], tick, sc_display[i]->val1, sc_display[i]->val2, sc_display[i]->val3); #else - clif_status_change_sub(&sd->bl, bl->id, StatusIconChangeTable[type], 1, tick, tsd->sc_display[i]->val1, tsd->sc_display[i]->val2, tsd->sc_display[i]->val3, target); + clif_status_change_sub(tbl, bl->id, StatusIconChangeTable[type], 1, tick, sc_display[i]->val1, sc_display[i]->val2, sc_display[i]->val3, target); #endif } } @@ -9393,7 +9409,7 @@ void clif_refresh(struct map_session_data *sd) clif_clearunit_single(sd->bl.id,CLR_DEAD,sd->fd); else clif_changed_dir(&sd->bl, SELF); - clif_efst_status_change_sub(sd,&sd->bl,SELF); + clif_efst_status_change_sub(&sd->bl,&sd->bl,SELF); //Issue #2143 //Cancel Trading State diff --git a/src/map/clif.h b/src/map/clif.h index d5f57dfc4e..11febee72d 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -676,7 +676,7 @@ void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_targe #define clif_status_load(bl, type, flag) clif_status_change((bl), (type), (flag), 0, 0, 0, 0) void clif_status_change(struct block_list *bl, int type, int flag, int tick, int val1, int val2, int val3); void clif_efst_status_change(struct block_list *bl, int tid, enum send_target target, int type, int tick, int val1, int val2, int val3); -void clif_efst_status_change_sub(struct map_session_data *sd, struct block_list *bl, enum send_target target); +void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl, enum send_target target); void clif_wis_message(int fd, const char* nick, const char* mes, int mes_len); void clif_wis_end(int fd, int result); diff --git a/src/map/npc.c b/src/map/npc.c index 8a84eb8097..1356de395e 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -2079,6 +2079,7 @@ void npc_unload_duplicates(struct npc_data* nd) int npc_unload(struct npc_data* nd, bool single) { nullpo_ret(nd); + status_change_clear(&nd->bl, 1); npc_remove_map(nd); map_deliddb(&nd->bl); if( single ) @@ -2160,6 +2161,15 @@ int npc_unload(struct npc_data* nd, bool single) { } if( nd->u.scr.guild_id ) guild_flag_remove(nd); + if( nd->sc_display_count ){ + unsigned char i; + + for( i = 0; i < nd->sc_display_count; i++ ) + ers_free(npc_sc_display_ers, nd->sc_display[i]); + nd->sc_display_count = 0; + aFree(nd->sc_display); + nd->sc_display = NULL; + } } script_stop_sleeptimers(nd->bl.id); @@ -2390,6 +2400,28 @@ bool npc_viewisid(const char * viewid) return true; } +/** + * Create a bare NPC object. + * @param m: Map ID + * @param x: X location + * @param y: Y location + * @return npc_data + */ +struct npc_data *npc_create_npc(int16 m, int16 x, int16 y){ + struct npc_data *nd; + + CREATE(nd, struct npc_data, 1); + nd->bl.id = npc_get_new_npc_id(); + nd->bl.prev = nd->bl.next = NULL; + nd->bl.m = m; + nd->bl.x = x; + nd->bl.y = y; + nd->sc_display = NULL; + nd->sc_display_count = 0; + + return nd; +} + /** * Add then display an npc warp on map * @param name : warp unique name @@ -2408,13 +2440,8 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short int i, flag = 0; struct npc_data *nd; - CREATE(nd, struct npc_data, 1); - nd->bl.id = npc_get_new_npc_id(); + nd = npc_create_npc(from_mapid, from_x, from_y); map_addnpc(from_mapid, nd); - nd->bl.prev = nd->bl.next = NULL; - nd->bl.m = from_mapid; - nd->bl.x = from_x; - nd->bl.y = from_y; safestrncpy(nd->exname, name, ARRAYLENGTH(nd->exname)); if (npc_name2id(nd->exname) != NULL) @@ -2495,14 +2522,8 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const ShowWarning("npc_parse_warp: coordinates %d/%d are out of bounds in map %s(%dx%d), in file '%s', line '%d'\n", x, y, map[m].name, map[m].xs, map[m].ys,filepath,strline(buffer,start-buffer)); } - CREATE(nd, struct npc_data, 1); - - nd->bl.id = npc_get_new_npc_id(); + nd = npc_create_npc(m, x, y); map_addnpc(m, nd); - nd->bl.prev = nd->bl.next = NULL; - nd->bl.m = m; - nd->bl.x = x; - nd->bl.y = y; npc_parsename(nd, w3, start, buffer, filepath); if (!battle_config.warp_point_debug) @@ -2645,8 +2666,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const break; } - CREATE(nd, struct npc_data, 1); - + nd = npc_create_npc(m, x, y); nd->u.shop.count = 0; while ( p ) { unsigned short nameid2, qty = 0; @@ -2740,11 +2760,6 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const nd->u.shop.discount = is_discount; } - nd->bl.prev = nd->bl.next = NULL; - nd->bl.m = m; - nd->bl.x = x; - nd->bl.y = y; - nd->bl.id = npc_get_new_npc_id(); npc_parsename(nd, w3, start, buffer, filepath); nd->class_ = m == -1 ? -1 : npc_parseview(w4, start, buffer, filepath); nd->speed = 200; @@ -2967,7 +2982,7 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons db_clear(label_db); // not needed anymore, so clear the db } - CREATE(nd, struct npc_data, 1); + nd = npc_create_npc(m, x, y); if( sscanf(w4, "%*[^,],%6hd,%6hd", &xs, &ys) == 2 ) {// OnTouch area defined @@ -2980,12 +2995,7 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons nd->u.scr.ys = -1; } - nd->bl.prev = nd->bl.next = NULL; - nd->bl.m = m; - nd->bl.x = x; - nd->bl.y = y; npc_parsename(nd, w3, start, buffer, filepath); - nd->bl.id = npc_get_new_npc_id(); nd->class_ = m == -1 ? -1 : npc_parseview(w4, start, buffer, filepath); nd->speed = 200; nd->u.scr.script = script; @@ -3112,14 +3122,8 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch return end;// next line, try to continue } - CREATE(nd, struct npc_data, 1); - - nd->bl.prev = nd->bl.next = NULL; - nd->bl.m = m; - nd->bl.x = x; - nd->bl.y = y; + nd = npc_create_npc(m, x, y); npc_parsename(nd, w3, start, buffer, filepath); - nd->bl.id = npc_get_new_npc_id(); nd->class_ = m == -1 ? -1 : npc_parseview(w4, start, buffer, filepath); nd->speed = 200; nd->src_id = src_id; @@ -3233,13 +3237,8 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) { return 1; } - CREATE(wnd, struct npc_data, 1); - wnd->bl.id = npc_get_new_npc_id(); + wnd = npc_create_npc(m, snd->bl.x, snd->bl.y); map_addnpc(m, wnd); - wnd->bl.prev = wnd->bl.next = NULL; - wnd->bl.m = m; - wnd->bl.x = snd->bl.x; - wnd->bl.y = snd->bl.y; safestrncpy(wnd->name, "", ARRAYLENGTH(wnd->name)); safestrncpy(wnd->exname, newname, ARRAYLENGTH(wnd->exname)); wnd->class_ = WARP_CLASS; @@ -4656,6 +4655,7 @@ void do_final_npc(void) { NPCMarketDB->destroy(NPCMarketDB, npc_market_free); #endif ers_destroy(timer_event_ers); + ers_destroy(npc_sc_display_ers); npc_clearsrcfile(); } @@ -4716,7 +4716,8 @@ void do_init_npc(void){ npc_market_fromsql(); #endif - timer_event_ers = ers_new(sizeof(struct timer_event_data),"clif.c::timer_event_ers",ERS_OPT_NONE); + timer_event_ers = ers_new(sizeof(struct timer_event_data),"npc.c::timer_event_ers",ERS_OPT_NONE); + npc_sc_display_ers = ers_new(sizeof(struct sc_display_entry), "npc.c:npc_sc_display_ers", ERS_OPT_NONE); // process all npc files ShowStatus("Loading NPCs...\r"); diff --git a/src/map/npc.h b/src/map/npc.h index c33c76c61c..2130f66419 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -96,8 +96,13 @@ struct npc_data { int spawn_timer; } tomb; } u; + + struct sc_display_entry **sc_display; + unsigned char sc_display_count; }; +struct eri *npc_sc_display_ers; + #define START_NPC_NUM 110000000 enum actor_classes diff --git a/src/map/status.c b/src/map/status.c index 0cff10451c..89e1d16c8b 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1278,61 +1278,61 @@ void initChangeTables(void) #endif /* StatusDisplayType Table [Ind] */ - StatusDisplayType[SC_ALL_RIDING] = true; - StatusDisplayType[SC_PUSH_CART] = true; - StatusDisplayType[SC_SPHERE_1] = true; - StatusDisplayType[SC_SPHERE_2] = true; - StatusDisplayType[SC_SPHERE_3] = true; - StatusDisplayType[SC_SPHERE_4] = true; - StatusDisplayType[SC_SPHERE_5] = true; - StatusDisplayType[SC_CAMOUFLAGE] = true; - StatusDisplayType[SC_STEALTHFIELD] = true; - StatusDisplayType[SC_DUPLELIGHT] = true; - StatusDisplayType[SC_ORATIO] = true; - StatusDisplayType[SC_FREEZING] = true; - StatusDisplayType[SC_VENOMIMPRESS] = true; - StatusDisplayType[SC_HALLUCINATIONWALK] = true; - StatusDisplayType[SC_ROLLINGCUTTER] = true; - StatusDisplayType[SC_BANDING] = true; - StatusDisplayType[SC_CRYSTALIZE] = true; - StatusDisplayType[SC_DEEPSLEEP] = true; - StatusDisplayType[SC_CURSEDCIRCLE_ATKER] = true; - StatusDisplayType[SC_CURSEDCIRCLE_TARGET] = true; - StatusDisplayType[SC_NETHERWORLD] = true; - StatusDisplayType[SC_VOICEOFSIREN] = true; - StatusDisplayType[SC_BLOODSUCKER] = true; - StatusDisplayType[SC__SHADOWFORM] = true; - StatusDisplayType[SC__MANHOLE] = true; - StatusDisplayType[SC_JYUMONJIKIRI] = true; - StatusDisplayType[SC_AKAITSUKI] = true; - StatusDisplayType[SC_MONSTER_TRANSFORM] = true; - StatusDisplayType[SC_ACTIVE_MONSTER_TRANSFORM] = true; - StatusDisplayType[SC_DARKCROW] = true; - StatusDisplayType[SC_OFFERTORIUM] = true; - StatusDisplayType[SC_TELEKINESIS_INTENSE] = true; - StatusDisplayType[SC_UNLIMIT] = true; - StatusDisplayType[SC_ILLUSIONDOPING] = true; - StatusDisplayType[SC_C_MARKER] = true; - StatusDisplayType[SC_ANTI_M_BLAST] = true; - StatusDisplayType[SC_SPRITEMABLE] = true; + StatusDisplayType[SC_ALL_RIDING] = BL_PC; + StatusDisplayType[SC_PUSH_CART] = BL_PC; + StatusDisplayType[SC_SPHERE_1] = BL_PC; + StatusDisplayType[SC_SPHERE_2] = BL_PC; + StatusDisplayType[SC_SPHERE_3] = BL_PC; + StatusDisplayType[SC_SPHERE_4] = BL_PC; + StatusDisplayType[SC_SPHERE_5] = BL_PC; + StatusDisplayType[SC_CAMOUFLAGE] = BL_PC; + StatusDisplayType[SC_STEALTHFIELD] = BL_PC; + StatusDisplayType[SC_DUPLELIGHT] = BL_PC; + StatusDisplayType[SC_ORATIO] = BL_PC; + StatusDisplayType[SC_FREEZING] = BL_PC; + StatusDisplayType[SC_VENOMIMPRESS] = BL_PC; + StatusDisplayType[SC_HALLUCINATIONWALK] = BL_PC; + StatusDisplayType[SC_ROLLINGCUTTER] = BL_PC; + StatusDisplayType[SC_BANDING] = BL_PC; + StatusDisplayType[SC_CRYSTALIZE] = BL_PC; + StatusDisplayType[SC_DEEPSLEEP] = BL_PC; + StatusDisplayType[SC_CURSEDCIRCLE_ATKER] = BL_PC; + StatusDisplayType[SC_CURSEDCIRCLE_TARGET] = BL_PC; + StatusDisplayType[SC_NETHERWORLD] = BL_PC; + StatusDisplayType[SC_VOICEOFSIREN] = BL_PC; + StatusDisplayType[SC_BLOODSUCKER] = BL_PC; + StatusDisplayType[SC__SHADOWFORM] = BL_PC; + StatusDisplayType[SC__MANHOLE] = BL_PC; + StatusDisplayType[SC_JYUMONJIKIRI] = BL_PC; + StatusDisplayType[SC_AKAITSUKI] = BL_PC; + StatusDisplayType[SC_MONSTER_TRANSFORM] = BL_PC; + StatusDisplayType[SC_ACTIVE_MONSTER_TRANSFORM] = BL_PC; + StatusDisplayType[SC_DARKCROW] = BL_PC; + StatusDisplayType[SC_OFFERTORIUM] = BL_PC; + StatusDisplayType[SC_TELEKINESIS_INTENSE] = BL_PC; + StatusDisplayType[SC_UNLIMIT] = BL_PC; + StatusDisplayType[SC_ILLUSIONDOPING] = BL_PC; + StatusDisplayType[SC_C_MARKER] = BL_PC; + StatusDisplayType[SC_ANTI_M_BLAST] = BL_PC; + StatusDisplayType[SC_SPRITEMABLE] = BL_PC; // Costumes - StatusDisplayType[SC_MOONSTAR] = true; - StatusDisplayType[SC_SUPER_STAR] = true; - StatusDisplayType[SC_STRANGELIGHTS] = true; - StatusDisplayType[SC_DECORATION_OF_MUSIC] = true; - StatusDisplayType[SC_LJOSALFAR] = true; - StatusDisplayType[SC_MERMAID_LONGING] = true; - StatusDisplayType[SC_HAT_EFFECT] = true; - StatusDisplayType[SC_FLOWERSMOKE] = true; - StatusDisplayType[SC_FSTONE] = true; - StatusDisplayType[SC_HAPPINESS_STAR] = true; - StatusDisplayType[SC_MAPLE_FALLS] = true; - StatusDisplayType[SC_TIME_ACCESSORY] = true; - StatusDisplayType[SC_MAGICAL_FEATHER] = true; + StatusDisplayType[SC_MOONSTAR] = BL_PC; + StatusDisplayType[SC_SUPER_STAR] = BL_PC; + StatusDisplayType[SC_STRANGELIGHTS] = BL_PC; + StatusDisplayType[SC_DECORATION_OF_MUSIC] = BL_PC; + StatusDisplayType[SC_LJOSALFAR] = BL_PC; + StatusDisplayType[SC_MERMAID_LONGING] = BL_PC; + StatusDisplayType[SC_HAT_EFFECT] = BL_PC; + StatusDisplayType[SC_FLOWERSMOKE] = BL_PC; + StatusDisplayType[SC_FSTONE] = BL_PC; + StatusDisplayType[SC_HAPPINESS_STAR] = BL_PC; + StatusDisplayType[SC_MAPLE_FALLS] = BL_PC; + StatusDisplayType[SC_TIME_ACCESSORY] = BL_PC; + StatusDisplayType[SC_MAGICAL_FEATHER] = BL_PC; // Clans - StatusDisplayType[SC_CLAN_INFO] = true; + StatusDisplayType[SC_CLAN_INFO] = BL_PC|BL_NPC; /* StatusChangeState (SCS_) NOMOVE */ StatusChangeStateTable[SC_ANKLE] |= SCS_NOMOVE; @@ -8077,74 +8077,135 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ } /** - * Applies SC effect to the player - * @param sd: Source to apply effect [PC] + * Applies SC effect + * @param bl: Source to apply effect * @param type: Status change (SC_*) * @param dval1~3: Depends on type of status change * Author: Ind */ -void status_display_add(struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3) { +void status_display_add(struct block_list *bl, enum sc_type type, int dval1, int dval2, int dval3) { + struct eri *eri; + struct sc_display_entry **sc_display; + struct sc_display_entry ***sc_display_ptr; struct sc_display_entry *entry; int i; + unsigned char sc_display_count; + unsigned char *sc_display_count_ptr; - for( i = 0; i < sd->sc_display_count; i++ ) { - if( sd->sc_display[i]->type == type ) + nullpo_retv(bl); + + switch( bl->type ){ + case BL_PC: { + struct map_session_data* sd = (struct map_session_data*)bl; + + sc_display_ptr = &sd->sc_display; + sc_display_count_ptr = &sd->sc_display_count; + eri = pc_sc_display_ers; + } break; + case BL_NPC: { + struct npc_data* nd = (struct npc_data*)bl; + + sc_display_ptr = &nd->sc_display; + sc_display_count_ptr = &nd->sc_display_count; + eri = npc_sc_display_ers; + } + break; + default: + return; } - if( i != sd->sc_display_count ) { - sd->sc_display[i]->val1 = dval1; - sd->sc_display[i]->val2 = dval2; - sd->sc_display[i]->val3 = dval3; + sc_display = *sc_display_ptr; + sc_display_count = *sc_display_count_ptr; + + ARR_FIND(0, sc_display_count, i, sc_display[i]->type == type); + + if( i != sc_display_count ) { + sc_display[i]->val1 = dval1; + sc_display[i]->val2 = dval2; + sc_display[i]->val3 = dval3; return; } - entry = ers_alloc(pc_sc_display_ers, struct sc_display_entry); + entry = ers_alloc(eri, struct sc_display_entry); entry->type = type; entry->val1 = dval1; entry->val2 = dval2; entry->val3 = dval3; - RECREATE(sd->sc_display, struct sc_display_entry *, ++sd->sc_display_count); - sd->sc_display[sd->sc_display_count - 1] = entry; + RECREATE(sc_display, struct sc_display_entry *, ++sc_display_count); + sc_display[sc_display_count - 1] = entry; + *sc_display_ptr = sc_display; + *sc_display_count_ptr = sc_display_count; } /** - * Removes SC effect of the player - * @param sd: Source to remove effect [PC] + * Removes SC effect + * @param bl: Source to remove effect * @param type: Status change (SC_*) * Author: Ind */ -void status_display_remove(struct map_session_data *sd, enum sc_type type) { +void status_display_remove(struct block_list *bl, enum sc_type type) { + struct eri *eri; + struct sc_display_entry **sc_display; + struct sc_display_entry ***sc_display_ptr; int i; + unsigned char sc_display_count; + unsigned char *sc_display_count_ptr; - for( i = 0; i < sd->sc_display_count; i++ ) { - if( sd->sc_display[i]->type == type ) + nullpo_retv(bl); + + switch( bl->type ){ + case BL_PC: { + struct map_session_data* sd = (struct map_session_data*)bl; + + sc_display_ptr = &sd->sc_display; + sc_display_count_ptr = &sd->sc_display_count; + eri = pc_sc_display_ers; + } break; + case BL_NPC: { + struct npc_data* nd = (struct npc_data*)bl; + + sc_display_ptr = &nd->sc_display; + sc_display_count_ptr = &nd->sc_display_count; + eri = npc_sc_display_ers; + } + break; + default: + return; } - if( i != sd->sc_display_count ) { + sc_display = *sc_display_ptr; + sc_display_count = *sc_display_count_ptr; + + ARR_FIND(0, sc_display_count, i, sc_display[i]->type == type); + + if( i != sc_display_count ) { int cursor; - ers_free(pc_sc_display_ers, sd->sc_display[i]); - sd->sc_display[i] = NULL; + ers_free(eri, sc_display[i]); + sc_display[i] = NULL; /* The all-mighty compact-o-matic */ - for( i = 0, cursor = 0; i < sd->sc_display_count; i++ ) { - if( sd->sc_display[i] == NULL ) + for( i = 0, cursor = 0; i < sc_display_count; i++ ) { + if( sc_display[i] == NULL ) continue; if( i != cursor ) - sd->sc_display[cursor] = sd->sc_display[i]; + sc_display[cursor] = sc_display[i]; cursor++; } - if( !(sd->sc_display_count = cursor) ) { - aFree(sd->sc_display); - sd->sc_display = NULL; + if( !(sc_display_count = cursor) ) { + aFree(sc_display); + sc_display = NULL; } + + *sc_display_ptr = sc_display; + *sc_display_count_ptr = sc_display_count; } } @@ -8181,7 +8242,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty if( !sc ) return 0; // Unable to receive status changes - if( status_isdead(bl) && ( type != SC_NOCHAT && type != SC_JAILED ) ) // SC_NOCHAT and SC_JAILED should work even on dead characters + if( bl->type != BL_NPC && status_isdead(bl) && ( type != SC_NOCHAT && type != SC_JAILED ) ) // SC_NOCHAT and SC_JAILED should work even on dead characters return 0; if (status_change_isDisabledOnMap(type, bl->m)) @@ -10946,7 +11007,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty } /* [Ind] */ - if (sd && StatusDisplayType[type]) { + if (StatusDisplayType[type]&bl->type) { int dval1 = 0, dval2 = 0, dval3 = 0; switch (type) { @@ -10962,7 +11023,8 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty dval1 = val1; break; } - status_display_add(sd,type,dval1,dval2,dval3); + status_display_add(bl,type,dval1,dval2,dval3); + clif_efst_status_change_sub(bl, bl, AREA); } // Those that make you stop attacking/walking.... @@ -11696,8 +11758,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const sc->data[type] = NULL; - if (sd && StatusDisplayType[type]) - status_display_remove(sd,type); + if (StatusDisplayType[type]&bl->type) + status_display_remove(bl,type); vd = status_get_viewdata(bl); calc_flag = StatusChangeFlagTable[type]; diff --git a/src/map/status.h b/src/map/status.h index f254f7f646..be00b1806a 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -2075,7 +2075,7 @@ unsigned int StatusChangeFlagTable[SC_MAX]; /// status -> flags int StatusSkillChangeTable[SC_MAX]; /// status -> skill int StatusRelevantBLTypes[SI_MAX]; /// "icon" -> enum bl_type (for clif->status_change to identify for which bl types to send packets) unsigned int StatusChangeStateTable[SC_MAX]; /// status -> flags -bool StatusDisplayType[SC_MAX]; +unsigned int StatusDisplayType[SC_MAX]; ///For holding basic status (which can be modified by status changes) struct status_data {