Browse Source

Refurbished hat effects

Follow up to 5da49b8
Thanks to @cydh for the good base in #1465.

Renamed the function from itemeffect to hateffect.
The effects now get sent to other players as well.
You can enable or disable one effect at a time with the script command now.
Lemongrass3110 8 years ago
parent
commit
ede39b1730
7 changed files with 84 additions and 30 deletions
  1. 1 1
      doc/script_commands.txt
  2. 36 14
      src/map/clif.c
  3. 2 1
      src/map/clif.h
  4. 3 0
      src/map/pc.c
  5. 5 0
      src/map/pc.h
  6. 31 14
      src/map/script.c
  7. 6 0
      src/map/unit.c

+ 1 - 1
doc/script_commands.txt

@@ -9161,7 +9161,7 @@ solution rather than sending the map and the monster_id.
 
 ---------------------------------------
 
-*itemeffect(<State>,<Hat Effect ID>{, Hat Effect ID2, ... });
+*hateffect(<Hat Effect ID>,<State>);
 
 This will set a Hat Effect onto the player. The state field allows you to
 enable (true) or disable (false) the effect on the player.

+ 36 - 14
src/map/clif.c

@@ -1444,6 +1444,7 @@ int clif_spawn(struct block_list *bl)
 			if (sd->status.robe)
 				clif_refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA);
 			clif_efst_status_change_sub(sd, bl, AREA);
+			clif_hat_effects(sd,bl,AREA);
 		}
 		break;
 	case BL_MOB:
@@ -4548,6 +4549,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl)
 			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_hat_effects(sd,bl,SELF);
 		}
 		break;
 	case BL_MER: // Devotion Effects
@@ -18745,37 +18747,57 @@ void clif_navigateTo(struct map_session_data *sd, const char* mapname, uint16 x,
 
 /// Send hat effects to the client (ZC_HAT_EFFECT).
 /// 0A3B <Length>.W <AID>.L <Status>.B { <HatEffectId>.W }
-void clif_item_effects( struct block_list* bl, bool enable, short effects[], int count ){
+void clif_hat_effects( struct map_session_data* sd, struct block_list* bl, enum send_target target ){
 #if PACKETVER >= 20150513
 	unsigned char* buf;
 	int len,i;
+	struct map_session_data *tsd;
+	struct block_list* tbl;
 
-	nullpo_retv(bl);
+	if( target == SELF ){
+		tsd = BL_CAST(BL_PC,bl);
+		tbl = &sd->bl;
+	}else{
+		tsd = sd;
+		tbl = bl;
+	}
+
+	if( !tsd->hatEffectCount )
+		return;
 
-	len = 9 + count * 2;
+	len = 9 + tsd->hatEffectCount * 2;
 
 	buf = (unsigned char*)aMalloc( len );
 
 	WBUFW(buf,0) = 0xa3b;
 	WBUFW(buf,2) = len;
-	WBUFL(buf,4) = bl->id;
-	WBUFB(buf,8) = enable;
+	WBUFL(buf,4) = tsd->bl.id;
+	WBUFB(buf,8) = 1;
 
-	for( i = 0; i < count; i++ ){
-		WBUFW(buf,9+i*2) = effects[i];
+	for( i = 0; i < tsd->hatEffectCount; i++ ){
+		WBUFW(buf,9+i*2) = tsd->hatEffectIDs[i];
 	}
 
-	clif_send(buf, len,bl,SELF);
-
-	if( disguised(bl) ){
-		WBUFL(buf,4) = -bl->id;
-		clif_send(buf, len,bl,SELF);
-	}
+	clif_send(buf, len,tbl,target);
 
 	aFree(buf);
 #endif
 }
 
+void clif_hat_effect_single( struct map_session_data* sd, uint16 effectId, bool enable ){
+#if PACKETVER >= 20150513
+	unsigned char buf[13];
+
+	WBUFW(buf,0) = 0xa3b;
+	WBUFW(buf,2) = 13;
+	WBUFL(buf,4) = sd->bl.id;
+	WBUFB(buf,8) = enable;
+	WBUFL(buf,9) = effectId;
+
+	clif_send(buf,13,&sd->bl,AREA);
+#endif
+}
+
 /*==========================================
  * Main client packet processing function
  *------------------------------------------*/
@@ -19176,7 +19198,7 @@ void packetdb_readdb(bool reload)
 	  269,  0,  0,  2,  6, 48,  6,  9, 26, 45, 47, 47, 56, -1,  14,  0,
 #endif
 		-1,  0,  0, 26,  0,  0,  0,  0,  14,  2, 23,  2, -1,  2,  3,  2,
-	   21,  3,  5,  0, 66,  0,  0,  8,  3,  0,  0,  0,  0,  -1,  0,  0,
+	   21,  3,  5,  0, 66,  0,  0,  8,  3,  0,  0,  -1,  0,  -1,  0,  0,
  		0,  0,  0,  0,  0,  4,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	};
 	struct {

+ 2 - 1
src/map/clif.h

@@ -679,7 +679,8 @@ void clif_item_repair_list(struct map_session_data *sd, struct map_session_data
 void clif_item_repaireffect(struct map_session_data *sd, int idx, int flag);
 void clif_item_damaged(struct map_session_data* sd, unsigned short position);
 void clif_item_refine_list(struct map_session_data *sd);
-void clif_item_effects( struct block_list* bl, bool enable, short effects[], int count );
+void clif_hat_effects( struct map_session_data* sd, struct block_list* bl, enum send_target target );
+void clif_hat_effect_single( struct map_session_data* sd, uint16 effectId, bool enable );
 
 void clif_item_skill(struct map_session_data *sd,uint16 skill_id,uint16 skill_lv);
 

+ 3 - 0
src/map/pc.c

@@ -1269,6 +1269,9 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_
 	sd->bonus_script.head = NULL;
 	sd->bonus_script.count = 0;
 
+	sd->hatEffectIDs = NULL;
+	sd->hatEffectCount = 0;
+
 	// Check EXP overflow, since in previous revision EXP on Max Level can be more than 'official' Max EXP
 	if (pc_is_maxbaselv(sd) && sd->status.base_exp > MAX_LEVEL_BASE_EXP) {
 		sd->status.base_exp = MAX_LEVEL_BASE_EXP;

+ 5 - 0
src/map/pc.h

@@ -685,6 +685,11 @@ struct map_session_data {
 	} roulette;
 
 	unsigned short instance_id;
+
+#if PACKETVER >= 20150513
+	uint32* hatEffectIDs;
+	uint8 hatEffectCount;
+#endif
 };
 
 struct eri *pc_sc_display_ers; /// Player's SC display table

+ 31 - 14
src/map/script.c

@@ -21482,31 +21482,48 @@ BUILDIN_FUNC(recalculatestat) {
 	return SCRIPT_CMD_SUCCESS;
 }
 
-BUILDIN_FUNC(itemeffect){
+BUILDIN_FUNC(hateffect){
 #if PACKETVER >= 20150513
 	struct map_session_data* sd = script_rid2sd(st);
 	bool enable;
-	short *effects;
-	int i, count;
+	int i, effectID;
 
 	if( sd == NULL )
 		return SCRIPT_CMD_FAILURE;
 
-	enable = script_getnum(st,2) ? true : false;
+	effectID = script_getnum(st,2);
+	enable = script_getnum(st,3) ? true : false;
 
-	if( !script_hasdata(st,3) ){
-		ShowError( "buildin_itemeffect: You need to specify a hat effect id.\n" );
-		return SCRIPT_CMD_FAILURE;
-	}
+	ARR_FIND( 0, sd->hatEffectCount, i, sd->hatEffectIDs[i] == effectID );
 
-	count = st->end - 3;
-	effects = (short*)aMalloc(count*sizeof(short));
+	if( enable ){
+		if( i < sd->hatEffectCount ){
+			return SCRIPT_CMD_SUCCESS;
+		}
 
-	for( i = 0; i < count; i++ ){
-		effects[i] = script_getnum(st,3+i);
+		RECREATE(sd->hatEffectIDs,uint32,sd->hatEffectCount+1);
+		sd->hatEffectIDs[sd->hatEffectCount] = effectID;
+		sd->hatEffectCount++;
+	}else{
+		if( i == sd->hatEffectCount ){
+			return SCRIPT_CMD_SUCCESS;
+		}
+
+		for( ; i < sd->hatEffectCount - 1; i++ ){
+			sd->hatEffectIDs[i] = sd->hatEffectIDs[i+1];
+		}
+
+		sd->hatEffectCount--;
+
+		if( !sd->hatEffectCount ){
+			aFree(sd->hatEffectIDs);
+			sd->hatEffectIDs = NULL;
+		}
 	}
 
-	clif_item_effects( &sd->bl, enable, effects, count );
+	if( !sd->state.connect_new ){
+		clif_hat_effect_single( sd, effectID, enable );
+	}
 
 #endif
 	return SCRIPT_CMD_SUCCESS;
@@ -22090,7 +22107,7 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(adopt,"vv"),
 	BUILDIN_DEF(getexp2,"ii?"),
 	BUILDIN_DEF(recalculatestat,""),
-	BUILDIN_DEF(itemeffect,"ii*"),
+	BUILDIN_DEF(hateffect,"ii"),
 
 #include "../custom/script_def.inc"
 

+ 6 - 0
src/map/unit.c

@@ -3211,6 +3211,12 @@ int unit_free(struct block_list *bl, clr_type clrtype)
 			}
 			sd->qi_count = 0;
 
+			if( sd->hatEffectCount > 0 ){
+				aFree(sd->hatEffectIDs);
+				sd->hatEffectIDs = NULL;
+				sd->hatEffectCount = 0;
+			}
+
 			// Clearing...
 			if (sd->bonus_script.head)
 				pc_bonus_script_clear(sd, BSF_REM_ALL);