diff --git a/src/map/clif.c b/src/map/clif.c index 2210c307234..5626122cb3d 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1354,18 +1354,13 @@ int clif_spawn(struct block_list *bl) clif->specialeffect(bl,421,AREA); if( sd->bg_id && map[sd->bl.m].flag.battleground ) clif->sendbgemblem_area(sd); - if( sd->sc.data[SC_ALL_RIDING] ) { - //New Mounts are not complaint to the original method, so we gotta tell this guy that he is mounting. - clif->sc_notick(&sd->bl,SI_ALL_RIDING,2,1,0,0); + for( i = 0; i < sd->sc_display_count; i++ ) { + clif->sc_load(&sd->bl, sd->bl.id,AREA,StatusIconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3); } for(i = 1; i < 5; i++){ if( sd->talisman[i] > 0 ) clif->talisman(sd, i); } - #ifdef NEW_CARTS - if( sd->sc.data[SC_PUSH_CART] ) - clif->sc_notick(&sd->bl, SI_ON_PUSH_CART, 2, sd->sc.data[SC_PUSH_CART]->val1, 0, 0); - #endif if (sd->status.robe) clif->refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA); } @@ -4306,14 +4301,9 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds if( dstsd->talisman[i] > 0 ) clif->talisman_single(sd->fd, dstsd, i); } - if( dstsd->sc.data[SC_ALL_RIDING] ) { - //New Mounts are not complaint to the original method, so we gotta tell this guy that I'm mounting. - clif->sc_single(sd->fd,dstsd->bl.id,SI_ALL_RIDING,2,1,0,0); + for( i = 0; i < dstsd->sc_display_count; i++ ) { + clif->sc_load(&sd->bl,dstsd->bl.id,SELF,StatusIconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3); } -#ifdef NEW_CARTS - if( dstsd->sc.data[SC_PUSH_CART] ) - clif->sc_single(sd->fd, dstsd->bl.id, SI_ON_PUSH_CART, 2, dstsd->sc.data[SC_PUSH_CART]->val1, 0, 0); -#endif if( (sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting. (sd->bg_id && sd->bg_id == dstsd->bg_id) || //BattleGround pc_has_permission(sd, PC_PERM_VIEW_HPMETER) @@ -16455,40 +16445,6 @@ int clif_skill_itemlistwindow( struct map_session_data *sd, uint16 skill_id, uin return 1; } -/** - * Sends a new status without a tick (currently used by the new mounts) - **/ -int clif_status_load_notick(struct block_list *bl,int type,int flag,int val1, int val2, int val3) { - unsigned char buf[32]; - - nullpo_ret(bl); - - WBUFW(buf,0)=0x043f; - WBUFW(buf,2)=type; - WBUFL(buf,4)=bl->id; - WBUFB(buf,8)=flag; - WBUFL(buf,9) = 0; - WBUFL(buf,13) = val1; - WBUFL(buf,17) = val2; - WBUFL(buf,21) = val3; - - clif->send(buf,packet_len(0x043f),bl,AREA); - return 0; -} -//Notifies FD of ID's type -int clif_status_load_single(int fd, int id,int type,int flag,int val1, int val2, int val3) { - WFIFOHEAD(fd, packet_len(0x043f)); - WFIFOW(fd,0)=0x043f; - WFIFOW(fd,2)=type; - WFIFOL(fd,4)=id; - WFIFOB(fd,8)=flag; - WFIFOL(fd,9) = 0; - WFIFOL(fd,13) = val1; - WFIFOL(fd,17) = val2; - WFIFOL(fd,21) = val3; - WFIFOSET(fd, packet_len(0x043f)); - return 0; -} // msgstringtable.txt // 0x291 .W void clif_msgtable(int fd, int line) { @@ -16818,6 +16774,21 @@ void clif_maptypeproperty2(struct block_list *bl,enum send_target t) { #endif } +void clif_status_change2(struct block_list *bl, int tid, enum send_target target, int type, int val1, int val2, int val3) { + struct packet_status_change2 p; + + p.PacketType = status_change2Type; + p.index = type; + p.AID = tid; + p.state = 1; + p.Left = -1;// officially its 9999 but -1 is a explicit "no-duration" which behaves best [Ind/Hercules] + p.val1 = val1; + p.val2 = val2; + p.val3 = val3; + + clif->send(&p,sizeof(p), bl, target); +} + void clif_partytickack(struct map_session_data* sd, bool flag) { WFIFOHEAD(sd->fd, packet_len(0x2c9)); @@ -17227,8 +17198,7 @@ void clif_defaults(void) { clif->poison_list = clif_poison_list; clif->autoshadowspell_list = clif_autoshadowspell_list; clif->skill_itemlistwindow = clif_skill_itemlistwindow; - clif->sc_notick = clif_status_load_notick; - clif->sc_single = clif_status_load_single; + clif->sc_load = clif_status_change2; clif->initialstatus = clif_initialstatus; /* player-unit-specific-related */ clif->updatestatus = clif_updatestatus; diff --git a/src/map/clif.h b/src/map/clif.h index b981cc5354a..e8882d4f9d1 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -596,8 +596,7 @@ struct clif_interface { int (*poison_list) (struct map_session_data *sd, uint16 skill_lv); int (*autoshadowspell_list) (struct map_session_data *sd); int (*skill_itemlistwindow) ( struct map_session_data *sd, uint16 skill_id, uint16 skill_lv ); - int (*sc_notick) (struct block_list *bl,int type,int flag,int val1, int val2, int val3); - int (*sc_single) (int fd, int id,int type,int flag,int val1, int val2, int val3); + void (*sc_load) (struct block_list *bl, int tid, enum send_target target, int type, int val1, int val2, int val3); void (*initialstatus) (struct map_session_data *sd); /* player-unit-specific-related */ void (*updatestatus) (struct map_session_data *sd,int type); diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index 94450facbe1..1ab296d4005 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -50,6 +50,7 @@ enum packet_headers { #else status_changeType = sc_notickType,/* 0x196 */ #endif + status_change2Type = 0x43f, #if PACKETVER < 4 spawn_unitType = 0x79, #elif PACKETVER < 7 @@ -352,6 +353,17 @@ struct packet_status_change { #endif } __attribute__((packed)); +struct packet_status_change2 { + short PacketType; + short index; + unsigned int AID; + unsigned char state; + unsigned int Left; + int val1; + int val2; + int val3; +} __attribute__((packed)); + struct packet_maptypeproperty2 { short PacketType; short type; diff --git a/src/map/pc.c b/src/map/pc.c index 59b1c74430f..d5d5efb3b29 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1096,7 +1096,11 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim * Check if player have any item cooldowns on **/ pc_itemcd_do(sd,true); - + + /* [Ind/Hercules] */ + sd->sc_display = NULL; + sd->sc_display_count = 0; + // Request all registries (auth is considered completed whence they arrive) intif_request_registry(sd,7); return true; @@ -1572,16 +1576,11 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd) pc_setglobalreg (sd, "jobchange_level", sd->change_level_2nd); } - if (skill_point < novice_skills + (sd->change_level_2nd - 1)) - { + if (skill_point < novice_skills + (sd->change_level_2nd - 1)) { c &= MAPID_BASEMASK; - } - // limit 3rd class to 2nd class/trans job levels - else if(sd->class_&JOBL_THIRD) - { + } else if(sd->class_&JOBL_THIRD) { // limit 3rd class to 2nd class/trans job levels // regenerate change_level_3rd - if (!sd->change_level_3rd) - { + if (!sd->change_level_3rd) { sd->change_level_3rd = 1 + skill_point + sd->status.skill_point - (sd->status.job_level - 1) - (sd->change_level_2nd - 1) @@ -7718,7 +7717,7 @@ int pc_setcart(struct map_session_data *sd,int type) { clif->cartlist(sd); clif->updatestatus(sd, SP_CARTINFO); sc_start(&sd->bl, SC_PUSH_CART, 100, type, 0); - clif->sc_notick(&sd->bl, SI_ON_PUSH_CART, 2 , type, 0, 0); + clif->sc_load(&sd->bl, sd->bl.id, AREA, SI_ON_PUSH_CART, type, 0, 0); if( sd->sc.data[SC_PUSH_CART] )/* forcefully update */ sd->sc.data[SC_PUSH_CART]->val1 = type; break; @@ -9822,6 +9821,8 @@ void do_final_pc(void) { db_destroy(itemcd_db); do_final_pc_groups(); + + ers_destroy(pc_sc_display_ers); return; } @@ -9859,6 +9860,8 @@ int do_init_pc(void) { } do_init_pc_groups(); + + pc_sc_display_ers = ers_new(sizeof(struct sc_display_entry), "pc.c:pc_sc_display_ers", ERS_OPT_NONE); return 0; } diff --git a/src/map/pc.h b/src/map/pc.h index 4f421f7c219..10891f6b4ff 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -6,6 +6,7 @@ #define _PC_H_ #include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus +#include "../common/ers.h" #include "../common/timer.h" // INVALID_TIMER #include "atcommand.h" // AtCommandType #include "battle.h" // battle_config @@ -513,12 +514,18 @@ struct map_session_data { unsigned char fontcolor; unsigned int hchsysch_tick; + /* [Ind/Hercules] */ + struct sc_display_entry **sc_display; + unsigned char sc_display_count; + // temporary debugging of bug #3504 const char* delunit_prevfile; int delunit_prevline; }; +struct eri *pc_sc_display_ers; + //Update this max as necessary. 55 is the value needed for Super Baby currently //Raised to 84 since Expanded Super Novice needs it. #define MAX_SKILL_TREE 84 diff --git a/src/map/status.c b/src/map/status.c index fec23cb55f7..3524430e506 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -55,9 +55,9 @@ static int hp_coefficient2[CLASS_COUNT]; static int hp_sigma_val[CLASS_COUNT][MAX_LEVEL+1]; static int sp_coefficient[CLASS_COUNT]; #ifdef RENEWAL_ASPD -static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE+1]; + static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE+1]; #else -static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE]; //[blackhole89] + static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE]; //[blackhole89] #endif // bonus values and upgrade chances for refining equipment @@ -78,13 +78,6 @@ int current_equip_card_id; //To prevent card-stacking (from jA) [Skotlex] //we need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only //to avoid cards exploits -static sc_type SkillStatusChangeTable[MAX_SKILL]; // skill -> status -static int StatusIconChangeTable[SC_MAX]; // status -> "icon" (icon is a bit of a misnomer, since there exist values with no icon associated) -static unsigned int StatusChangeFlagTable[SC_MAX]; // status -> flags -static int StatusSkillChangeTable[SC_MAX]; // status -> skill -static int StatusRelevantBLTypes[SI_MAX]; // "icon" -> enum bl_type (for clif->status_change to identify for which bl types to send packets) - - /** * Returns the status change associated with a skill. * @param skill The skill to look up @@ -184,7 +177,7 @@ void initChangeTables(void) { memset(StatusSkillChangeTable, 0, sizeof(StatusSkillChangeTable)); memset(StatusChangeFlagTable, 0, sizeof(StatusChangeFlagTable)); - + memset(StatusDisplayType, 0, sizeof(StatusDisplayType)); //First we define the skill for common ailments. These are used in skill_additional_effect through sc cards. [Skotlex] set_sc( NPC_PETRIFYATTACK , SC_STONE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF ); @@ -988,6 +981,30 @@ void initChangeTables(void) { StatusChangeFlagTable[SC_ALL_RIDING] = SCB_SPEED; + /* StatusDisplayType Table [Ind/Hercules] */ + 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_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_BLOODSUCKER] = true; + StatusDisplayType[SC__SHADOWFORM] = true; + StatusDisplayType[SC__MANHOLE] = true; + #ifdef RENEWAL_EDP // renewal EDP increases your weapon atk StatusChangeFlagTable[SC_EDP] |= SCB_WATK; @@ -6350,7 +6367,50 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti return tick; } - +/* [Ind/Hercules] fast-checkin sc-display array */ +void status_display_add(struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3) { + struct sc_display_entry *entry = ers_alloc(pc_sc_display_ers, 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; +} +void status_display_remove(struct map_session_data *sd, enum sc_type type) { + int i; + + for( i = 0; i < sd->sc_display_count; i++ ) { + if( sd->sc_display[i]->type == type ) + break; + } + + if( i != sd->sc_display_count ) { + int cursor; + + ers_free(pc_sc_display_ers, sd->sc_display[i]); + sd->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 ) + continue; + + if( i != cursor ) { + sd->sc_display[cursor] = sd->sc_display[i]; + } + + cursor++; + } + + if( !(sd->sc_display_count = cursor) ) { + aFree(sd->sc_display); + sd->sc_display = NULL; + } + } +} /*========================================== * Starts a status change. * 'type' = type, 'val1~4' depend on the type. @@ -6362,8 +6422,7 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti * &4: sc_data loaded, no value has to be altered. * &8: rate should not be reduced *------------------------------------------*/ -int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag) -{ +int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag) { struct map_session_data *sd = NULL; struct status_change* sc; struct status_change_entry* sce; @@ -8562,6 +8621,42 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; } } + + /* [Ind/Hercules] */ + if( sd && StatusDisplayType[type] ) { + int dval1 = 0, dval2 = 0, dval3 = 0; + switch( type ) { + case SC_ALL_RIDING: + dval1 = 1; + break; + case SC_SPHERE_1: + case SC_SPHERE_2: + case SC_SPHERE_3: + case SC_SPHERE_4: + case SC_SPHERE_5: + case SC_PUSH_CART: + case SC_CAMOUFLAGE: + case SC_DUPLELIGHT: + case SC_ORATIO: + case SC_FREEZING: + case SC_VENOMIMPRESS: + case SC_HALLUCINATIONWALK: + case SC_ROLLINGCUTTER: + case SC_BANDING: + case SC_CRYSTALIZE: + case SC_DEEPSLEEP: + case SC_CURSEDCIRCLE_ATKER: + case SC_CURSEDCIRCLE_TARGET: + case SC_BLOODSUCKER: + case SC__SHADOWFORM: + case SC__MANHOLE: + dval1 = val1; + break; + /* handle */ + default: break; + } + status_display_add(sd,type,dval1,dval2,dval3); + } //Those that make you stop attacking/walking.... switch (type) { @@ -8797,7 +8892,8 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val calc_flag&=~SCB_DYE; } - clif->status_change(bl,StatusIconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); + if( !(flag&4 && StatusDisplayType[type]) ) + clif->status_change(bl,StatusIconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); /** * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first. @@ -9025,8 +9121,7 @@ int status_change_clear(struct block_list* bl, int type) { /*========================================== * Special condition we want to effectuate, check before ending a status. *------------------------------------------*/ -int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line) -{ +int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line) { struct map_session_data *sd; struct status_change *sc; struct status_change_entry *sce; @@ -9078,6 +9173,10 @@ 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); + } + vd = status_get_viewdata(bl); calc_flag = StatusChangeFlagTable[type]; switch(type){ diff --git a/src/map/status.h b/src/map/status.h index eeac01e7020..4a7af884e00 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -16,9 +16,9 @@ struct status_change; * Changing this limit requires edits to refine_db.txt **/ #ifdef RENEWAL -# define MAX_REFINE 20 + #define MAX_REFINE 20 #else -# define MAX_REFINE 10 + #define MAX_REFINE 10 #endif enum refine_type { @@ -1563,6 +1563,13 @@ struct weapon_atk { #endif }; +sc_type SkillStatusChangeTable[MAX_SKILL]; // skill -> status +int StatusIconChangeTable[SC_MAX]; // status -> "icon" (icon is a bit of a misnomer, since there exist values with no icon associated) +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) +bool StatusDisplayType[SC_MAX]; + //For holding basic status (which can be modified by status changes) struct status_data { @@ -1639,6 +1646,11 @@ struct regen_data { struct regen_data_sub *sregen, *ssregen; }; +struct sc_display_entry { + enum sc_type type; + int val1,val2,val3; +}; + struct status_change_entry { int timer; int val1,val2,val3,val4; diff --git a/src/map/unit.c b/src/map/unit.c index 952b1a20eaa..f614d2fa0f1 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2294,8 +2294,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) if( bl->prev ) //Players are supposed to logout with a "warp" effect. unit_remove_map(bl, clrtype); - switch( bl->type ) - { + switch( bl->type ) { case BL_PC: { struct map_session_data *sd = (struct map_session_data*)bl; @@ -2331,7 +2330,6 @@ int unit_free(struct block_list *bl, clr_type clrtype) sd->reg_num = 0; } if( sd->regstr ) { - int i; for( i = 0; i < sd->regstr_num; ++i ) if( sd->regstr[i].data ) aFree(sd->regstr[i].data); @@ -2349,6 +2347,15 @@ int unit_free(struct block_list *bl, clr_type clrtype) aFree(sd->combos.id); sd->combos.count = 0; } + /* [Ind/Hercules] */ + if( sd->sc_display_count ) { + for(i = 0; i < sd->sc_display_count; i++) { + ers_free(pc_sc_display_ers, sd->sc_display[i]); + } + sd->sc_display_count = 0; + aFree(sd->sc_display); + sd->sc_display = NULL; + } break; } case BL_PET: