瀏覽代碼

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://svn.code.sf.net/p/rathena/svn/trunk@16209 54d463be-8e91-2dee-dedb-b68131a5f0ec

shennetsind 13 年之前
父節點
當前提交
c897ecdc25
共有 3 個文件被更改,包括 88 次插入36 次删除
  1. 76 3
      src/map/status.c
  2. 9 0
      src/map/status.h
  3. 3 33
      src/map/unit.c

+ 76 - 3
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)--;
 

+ 9 - 0
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
 /**

+ 3 - 33
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;
 }