From 67a0736c51678e453497660ef7df7bd601e57101 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Fri, 1 Jun 2012 18:42:35 +0000 Subject: performance improvement initial commit for status change state functionality, this first commit covers status that makes you unable to move. -- this cache the status changes into states saving dozens of checks whenever a unit moves/per cell. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@16209 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/status.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/map/status.h | 9 +++++++ src/map/unit.c | 36 +++----------------------- 3 files changed, 88 insertions(+), 36 deletions(-) diff --git a/src/map/status.c b/src/map/status.c index 74badf09e..91cb23df7 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -84,6 +84,8 @@ static int StatusIconChangeTable[SC_MAX]; // status -> "icon" (icon is 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) +static unsigned int StatusChangeStateTable[SC_MAX]; // status -> flags + /** * Returns the status change associated with a skill. @@ -172,18 +174,22 @@ static void set_sc(int skill, sc_type sc, int icon, unsigned int flag) SkillStatusChangeTable[sk] = sc; } -void initChangeTables(void) -{ +void initChangeTables(void) { int i; + for (i = 0; i < SC_MAX; i++) StatusIconChangeTable[i] = SI_BLANK; + for (i = 0; i < MAX_SKILL; i++) SkillStatusChangeTable[i] = SC_NONE; + for (i = 0; i < SI_MAX; i++) StatusRelevantBLTypes[i] = BL_PC; memset(StatusSkillChangeTable, 0, sizeof(StatusSkillChangeTable)); memset(StatusChangeFlagTable, 0, sizeof(StatusChangeFlagTable)); + memset(StatusChangeStateTable, 0, sizeof(StatusChangeStateTable)); + //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 ); @@ -934,6 +940,33 @@ void initChangeTables(void) if( !battle_config.display_hallucination ) //Disable Hallucination. StatusIconChangeTable[SC_HALLUCINATION] = SI_BLANK; + + /* StatusChangeState (SCS_) NOMOVE */ + StatusChangeStateTable[SC_ANKLE] |= SCS_NOMOVE; + StatusChangeStateTable[SC_AUTOCOUNTER] |= SCS_NOMOVE; + StatusChangeStateTable[SC_TRICKDEAD] |= SCS_NOMOVE; + StatusChangeStateTable[SC_BLADESTOP] |= SCS_NOMOVE; + StatusChangeStateTable[SC_BLADESTOP_WAIT] |= SCS_NOMOVE; + StatusChangeStateTable[SC_SPIDERWEB] |= SCS_NOMOVE|SCS_CONDITION; + StatusChangeStateTable[SC_DANCING] |= SCS_NOMOVE|SCS_CONDITION; + StatusChangeStateTable[SC_GOSPEL] |= SCS_NOMOVE|SCS_CONDITION; + StatusChangeStateTable[SC_BASILICA] |= SCS_NOMOVE|SCS_CONDITION; + StatusChangeStateTable[SC_STOP] |= SCS_NOMOVE; + StatusChangeStateTable[SC_CLOSECONFINE] |= SCS_NOMOVE; + StatusChangeStateTable[SC_CLOSECONFINE2] |= SCS_NOMOVE; + StatusChangeStateTable[SC_CLOAKING] |= SCS_NOMOVE|SCS_CONDITION; + StatusChangeStateTable[SC_MADNESSCANCEL] |= SCS_NOMOVE; + StatusChangeStateTable[SC_GRAVITATION] |= SCS_NOMOVE|SCS_CONDITION; + StatusChangeStateTable[SC_WHITEIMPRISON] |= SCS_NOMOVE; + StatusChangeStateTable[SC_ELECTRICSHOCKER] |= SCS_NOMOVE; + StatusChangeStateTable[SC_BITE] |= SCS_NOMOVE; + StatusChangeStateTable[SC_THORNSTRAP] |= SCS_NOMOVE; + StatusChangeStateTable[SC_MAGNETICFIELD] |= SCS_NOMOVE; + StatusChangeStateTable[SC__MANHOLE] |= SCS_NOMOVE; + StatusChangeStateTable[SC_VACUUM_EXTREME] |= SCS_NOMOVE; + StatusChangeStateTable[SC_FEAR] |= SCS_NOMOVE|SCS_CONDITION; + StatusChangeStateTable[SC_CURSEDCIRCLE_ATKER] |= SCS_NOMOVE; + StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET] |= SCS_NOMOVE; } static void initDummyData(void) @@ -3348,7 +3381,41 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str regen->flag&=~sce->val4; //Remove regen as specified by val4 } } - +void status_calc_state( struct block_list *bl, struct status_change *sc, enum scs_flag flag, bool start ) { + bool has_condition = ( flag&SCS_CONDITION ) ? true : false; + + /* no sc at all, we can zero without any extra weight over our conciousness */ + if( !sc->count ) { + memset(&sc->cant, 0, sizeof (sc->cant)); + return; + } + + + if( flag&SCS_NOMOVE ) { + if( !has_condition ) { + sc->cant.move += ( start ? 1 : -1 ); + } else if( + (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1) + || (sc->data[SC_DANCING] && sc->data[SC_DANCING]->val4 && ( + !sc->data[SC_LONGING] || + (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT || + (sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE + ) ) + || (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) // cannot move while gospel is in effect + || (sc->data[SC_BASILICA] && sc->data[SC_BASILICA]->val4 == bl->id) // Basilica caster cannot move + || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF) + || (sc->data[SC_CLOAKING] && //Need wall at level 1-2 + sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1)) + || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0) + ) { + sc->cant.move += ( start ? 1 : -1 ); + } + } + + /* others e.g. cant.cast, cant.pickup (check clif_parse_TakeItem) */ + + return; +} /// Recalculates parts of an object's battle status according to the specified flags. /// @param flag bitfield of values from enum scb_flag void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) @@ -8179,6 +8246,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if (calc_flag) status_calc_bl(bl,calc_flag); + if ( StatusChangeStateTable[type] ) /* non-zero */ + status_calc_state(bl,sc,( enum scs_flag ) StatusChangeStateTable[type],true); + if(sd && sd->pd) pet_sc_check(sd, type); //Skotlex: Pet Status Effect Healing @@ -8414,6 +8484,9 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } } + if ( StatusChangeStateTable[type] ) + status_calc_state(bl,sc,( enum scs_flag ) StatusChangeStateTable[type],false); + sc->data[type] = NULL; (sc->count)--; diff --git a/src/map/status.h b/src/map/status.h index 56a019682..5b6c2296a 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -1408,6 +1408,12 @@ enum manner_flags MANNER_NOROOM = 0x10, }; +/* Status Change State Flags */ +enum scs_flag { + SCS_CONDITION = 0x00000001, /* this implies the flag has a condition (if-checkin) */ + SCS_NOMOVE = 0x00000002, /* unit unable to move */ +}; + //Define flags for the status_calc_bl function. [Skotlex] enum scb_flag { @@ -1556,6 +1562,9 @@ struct status_change { unsigned char count; //TODO: See if it is possible to implement the following SC's without requiring extra parameters while the SC is inactive. unsigned char jb_flag; //Joint Beat type flag + struct { + unsigned char move; + } cant;/* status change state flags */ //int sg_id; //ID of the previous Storm gust that hit you short comet_x, comet_y; // Point where src casted Comet - required to calculate damage from this point /** diff --git a/src/map/unit.c b/src/map/unit.c index e58c003e9..47f9b5a39 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -886,45 +886,15 @@ int unit_can_move(struct block_list *bl) return 0; //Can't move if (sc) { + if( sc->cant.move ) + return 0; + if (sc->opt1 > 0 && sc->opt1 != OPT1_STONEWAIT && sc->opt1 != OPT1_BURNING) return 0; if ((sc->option & OPTION_HIDE) && (!sd || pc_checkskill(sd, RG_TUNNELDRIVE) <= 0)) return 0; - if (sc->count && ( - sc->data[SC_ANKLE] - || sc->data[SC_AUTOCOUNTER] - || sc->data[SC_TRICKDEAD] - || sc->data[SC_BLADESTOP] - || sc->data[SC_BLADESTOP_WAIT] - || (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1) - || (sc->data[SC_DANCING] && sc->data[SC_DANCING]->val4 && ( - !sc->data[SC_LONGING] || - (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT || - (sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE - )) - || (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) // cannot move while gospel is in effect - || (sc->data[SC_BASILICA] && sc->data[SC_BASILICA]->val4 == bl->id) // Basilica caster cannot move - || sc->data[SC_STOP] - || sc->data[SC_CLOSECONFINE] - || sc->data[SC_CLOSECONFINE2] - || (sc->data[SC_CLOAKING] && //Need wall at level 1-2 - sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1)) - || sc->data[SC_MADNESSCANCEL] - || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF) - || sc->data[SC_WHITEIMPRISON] - || sc->data[SC_ELECTRICSHOCKER] - || sc->data[SC_BITE] - || sc->data[SC_THORNSTRAP] - || sc->data[SC_MAGNETICFIELD] - || sc->data[SC__MANHOLE] - || sc->data[SC_VACUUM_EXTREME] - || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0) - || sc->data[SC_CURSEDCIRCLE_ATKER] - || sc->data[SC_CURSEDCIRCLE_TARGET] - )) - return 0; } return 1; } -- cgit v1.2.3-60-g2f50