use this @monkeydluffy
diff --git a/conf/battle/battle.conf b/conf/battle/battle.conf
index 593d4e92f4..30251a4834 100644
--- a/conf/battle/battle.conf
+++ b/conf/battle/battle.conf
@@ -158,3 +158,9 @@ warg_can_falcon: no
// Should the target be able of dodging damage by snapping away to the edge of the screen?
// Official behavior is "no"
snap_dodge: no
+
+// ****************************************
+// Reserved Costume ID's
+// ****************************************
+// Reserved Char ID for costume converted items.
+reserved_costume_id: 999998
\ No newline at end of file
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index 70113c4145..d769b4364d 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -9633,6 +9633,25 @@ solution rather than sending the map and the monster_id.
---------------------------------------
+*costume <equipment position>;
+
+Converts equipment in <equipment position> to costume version that has no stats.
+
+Applicable positions are:
+ EQI_HEAD_TOP - Top Headgear
+ EQI_HEAD_MID - Middle Headgear
+ EQI_HEAD_LOW - Lower Headgear
+ EQI_GARMENT - Garment
+
+---------------------------------------
+
+*getcostumeitem <item id>;
+*getcostumeitem <"item name">;
+
+Spawn a costume version of an <item id> or <"item name"> in attached player's inventory.
+
+---------------------------------------
+
*hateffect(<Hat Effect ID>,<State>);
This will set a Hat Effect onto the player. The state field allows you to
diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp
index 43d6ad4d7d..e2897a48b5 100644
--- a/src/map/atcommand.cpp
+++ b/src/map/atcommand.cpp
@@ -1218,7 +1218,7 @@ ACMD_FUNC(heal)
ACMD_FUNC(item)
{
char item_name[100];
- int number = 0, bound = BOUND_NONE;
+ int number = 0, bound = BOUND_NONE, costume = 0;
char flag = 0;
struct item item_tmp;
struct item_data *item_data[10];
@@ -1267,6 +1267,27 @@ ACMD_FUNC(item)
for(j--; j>=0; j--){ //produce items in list
unsigned short item_id = item_data[j]->nameid;
+ if (!strcmpi(command + 1, "costumeitem"))
+ {
+ if (!battle_config.reserved_costume_id)
+ {
+ clif_displaymessage(fd, "Costume convertion is disable. Set a value for reserved_cosutme_id on your battle.conf file.");
+ return -1;
+ }
+ if (!(item_data[j]->equip&EQP_HEAD_LOW) &&
+ !(item_data[j]->equip&EQP_HEAD_MID) &&
+ !(item_data[j]->equip&EQP_HEAD_TOP) &&
+ !(item_data[j]->equip&EQP_COSTUME_HEAD_LOW) &&
+ !(item_data[j]->equip&EQP_COSTUME_HEAD_MID) &&
+ !(item_data[j]->equip&EQP_COSTUME_HEAD_TOP) &&
+ !(item_data[j]->equip&EQP_GARMENT) &&
+ !(item_data[j]->equip&EQP_COSTUME_GARMENT))
+ {
+ clif_displaymessage(fd, "You cannot costume this item. Costume only work for headgears.");
+ return -1;
+ }
+ costume = 1;
+ }
//Check if it's stackable.
if (!itemdb_isstackable2(item_data[j]))
get_count = 1;
@@ -1277,6 +1298,11 @@ ACMD_FUNC(item)
memset(&item_tmp, 0, sizeof(item_tmp));
item_tmp.nameid = item_id;
item_tmp.identify = 1;
+ if (costume == 1) { // Costume item
+ item_tmp.card[0] = CARD0_CREATE;
+ item_tmp.card[2] = GetWord(battle_config.reserved_costume_id, 0);
+ item_tmp.card[3] = GetWord(battle_config.reserved_costume_id, 1);
+ }
item_tmp.bound = bound;
if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND)))
clif_additem(sd, 0, 0, flag);
@@ -10282,6 +10308,7 @@ void atcommand_basecommands(void) {
ACMD_DEF(clonestat),
ACMD_DEF(bodystyle),
ACMD_DEF(adopt),
+ ACMD_DEF2("costumeitem", item),
ACMD_DEF(agitstart3),
ACMD_DEF(agitend3),
};
diff --git a/src/map/battle.cpp b/src/map/battle.cpp
index 839cfb5620..d28c5f0182 100644
--- a/src/map/battle.cpp
+++ b/src/map/battle.cpp
@@ -8482,6 +8482,7 @@ static const struct _battle_data {
{ "exp_cost_inspiration", &battle_config.exp_cost_inspiration, 1, 0, 100, },
{ "mvp_exp_reward_message", &battle_config.mvp_exp_reward_message, 0, 0, 1, },
{ "can_damage_skill", &battle_config.can_damage_skill, 1, 0, BL_ALL, },
+ { "reserved_costume_id", &battle_config.reserved_costume_id, 999998, 0, INT_MAX, },
{ "atcommand_levelup_events", &battle_config.atcommand_levelup_events, 0, 0, 1, },
{ "block_account_in_same_party", &battle_config.block_account_in_same_party, 1, 0, 1, },
{ "tarotcard_equal_chance", &battle_config.tarotcard_equal_chance, 0, 0, 1, },
diff --git a/src/map/battle.hpp b/src/map/battle.hpp
index ad13f69d53..b8f36aaf00 100644
--- a/src/map/battle.hpp
+++ b/src/map/battle.hpp
@@ -618,6 +618,7 @@ struct Battle_Config
int exp_cost_inspiration;
int mvp_exp_reward_message;
int can_damage_skill; //Which BL types can damage traps
+ int reserved_costume_id;
int atcommand_levelup_events;
int block_account_in_same_party;
int tarotcard_equal_chance; //Official or equal chance for each card
diff --git a/src/map/map.cpp b/src/map/map.cpp
index 8b70459939..3b06cd032c 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -1865,6 +1865,12 @@ void map_reqnickdb(struct map_session_data * sd, int charid)
nullpo_retv(sd);
+ if (battle_config.reserved_costume_id && battle_config.reserved_costume_id == charid)
+ {
+ clif_solved_charname(sd->fd, charid, "Costume");
+ return;
+ }
+
tsd = map_charid2sd(charid);
if( tsd )
{
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
index c0126b1597..015381e857 100755
--- a/src/map/pc.cpp
+++ b/src/map/pc.cpp
@@ -746,6 +746,7 @@ int pc_equippoint_sub(struct map_session_data *sd,struct item_data* id){
return EQP_SHADOW_ARMS;
}
}
+
return ep;
}
@@ -757,7 +758,18 @@ int pc_equippoint_sub(struct map_session_data *sd,struct item_data* id){
int pc_equippoint(struct map_session_data *sd,int n){
nullpo_ret(sd);
- return pc_equippoint_sub(sd,sd->inventory_data[n]);
+ int ep = pc_equippoint_sub(sd, sd->inventory_data[n]);
+
+ if (battle_config.reserved_costume_id &&
+ sd->inventory.u.items_inventory[n].card[0] == CARD0_CREATE &&
+ MakeDWord(sd->inventory.u.items_inventory[n].card[2], sd->inventory.u.items_inventory[n].card[3]) == battle_config.reserved_costume_id)
+ { // Costume Item - Converted
+ if (ep&EQP_HEAD_TOP) { ep &= ~EQP_HEAD_TOP; ep |= EQP_COSTUME_HEAD_TOP; }
+ if (ep&EQP_HEAD_LOW) { ep &= ~EQP_HEAD_LOW; ep |= EQP_COSTUME_HEAD_LOW; }
+ if (ep&EQP_HEAD_MID) { ep &= ~EQP_HEAD_MID; ep |= EQP_COSTUME_HEAD_MID; }
+ if (ep&EQP_GARMENT) { ep &= ~EQP_GARMENT; ep |= EQP_COSTUME_GARMENT; }
+ }
+ return ep;
}
/**
diff --git a/src/map/script.cpp b/src/map/script.cpp
index 0b2386c32d..70127734b0 100644
--- a/src/map/script.cpp
+++ b/src/map/script.cpp
@@ -22601,6 +22601,114 @@ BUILDIN_FUNC(getexp2) {
return SCRIPT_CMD_SUCCESS;
}
+/*==========================================
+* Costume Items
+*------------------------------------------*/
+BUILDIN_FUNC(costume)
+{
+ int i = -1, num, ep;
+ TBL_PC *sd;
+
+ num = script_getnum(st, 2); // Equip Slot
+
+ if (!script_rid2sd(sd))
+ return SCRIPT_CMD_FAILURE;
+
+ if (equip_index_check(num))
+ i = pc_checkequip(sd, equip_bitmask[num]);
+ if (i < 0)
+ return SCRIPT_CMD_FAILURE;
+
+ ep = sd->inventory.u.items_inventory[i].equip;
+ if (!(ep&EQP_HEAD_LOW) && !(ep&EQP_HEAD_MID) && !(ep&EQP_HEAD_TOP) && !(ep&EQP_GARMENT)) {
+ ShowError("buildin_costume: Attempted to convert non-cosmetic item to costume.");
+ return SCRIPT_CMD_FAILURE;
+ }
+ log_pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->inventory.u.items_inventory[i]);
+ pc_unequipitem(sd, i, 2);
+ clif_delitem(sd, i, 1, 3);
+ // --------------------------------------------------------------------
+ sd->inventory.u.items_inventory[i].refine = 0;
+ sd->inventory.u.items_inventory[i].attribute = 0;
+ sd->inventory.u.items_inventory[i].card[0] = CARD0_CREATE;
+ sd->inventory.u.items_inventory[i].card[1] = 0;
+ sd->inventory.u.items_inventory[i].card[2] = GetWord(battle_config.reserved_costume_id, 0);
+ sd->inventory.u.items_inventory[i].card[3] = GetWord(battle_config.reserved_costume_id, 1);
+
+ if (ep&EQP_HEAD_TOP) { ep &= ~EQP_HEAD_TOP; ep |= EQP_COSTUME_HEAD_TOP; }
+ if (ep&EQP_HEAD_LOW) { ep &= ~EQP_HEAD_LOW; ep |= EQP_COSTUME_HEAD_LOW; }
+ if (ep&EQP_HEAD_MID) { ep &= ~EQP_HEAD_MID; ep |= EQP_COSTUME_HEAD_MID; }
+ if (ep&EQP_GARMENT) { ep &= EQP_GARMENT; ep |= EQP_COSTUME_GARMENT; }
+ // --------------------------------------------------------------------
+ log_pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->inventory.u.items_inventory[i]);
+
+ clif_additem(sd, i, 1, 0);
+ pc_equipitem(sd, i, ep);
+ clif_misceffect(&sd->bl, 3);
+
+ return SCRIPT_CMD_SUCCESS;
+}
+
+/*===============================
+ * getcostumeitem <item id>;
+ * getcostumeitem <"item name">;
+ *===============================*/
+BUILDIN_FUNC(getcostumeitem)
+{
+ unsigned short nameid;
+ struct item item_tmp;
+ TBL_PC *sd;
+ struct script_data *data;
+
+ if (!script_rid2sd(sd))
+ { // No player attached.
+ script_pushint(st, 0);
+ return SCRIPT_CMD_SUCCESS;
+ }
+
+ data = script_getdata(st, 2);
+ get_val(st, data);
+ if (data_isstring(data)) {
+ int ep;
+ const char *name = conv_str(st, data);
+ struct item_data *item_data = itemdb_searchname(name);
+ if (item_data == NULL)
+ { //Failed
+ script_pushint(st, 0);
+ return SCRIPT_CMD_SUCCESS;
+ }
+ ep = item_data->equip;
+ if (!(ep&EQP_HEAD_LOW) && !(ep&EQP_HEAD_MID) && !(ep&EQP_HEAD_TOP) && !(ep&EQP_GARMENT)){
+ ShowError("buildin_getcostumeitem: Attempted to convert non-cosmetic item to costume.");
+ return SCRIPT_CMD_FAILURE;
+ }
+ nameid = item_data->nameid;
+ }
+ else
+ nameid = conv_num(st, data);
+
+ if (!itemdb_exists(nameid))
+ { // Item does not exist.
+ script_pushint(st, 0);
+ return SCRIPT_CMD_SUCCESS;
+ }
+
+ memset(&item_tmp, 0, sizeof(item_tmp));
+ item_tmp.nameid = nameid;
+ item_tmp.amount = 1;
+ item_tmp.identify = 1;
+ item_tmp.card[0] = CARD0_CREATE;
+ item_tmp.card[2] = GetWord(battle_config.reserved_costume_id, 0);
+ item_tmp.card[3] = GetWord(battle_config.reserved_costume_id, 1);
+ if (pc_additem(sd, &item_tmp, 1, LOG_TYPE_SCRIPT)) {
+ script_pushint(st, 0);
+ return SCRIPT_CMD_SUCCESS; //Failed to add item, we will not drop if they don't fit
+ }
+
+ script_pushint(st, 1);
+ return SCRIPT_CMD_SUCCESS;
+}
+
/**
* Force stat recalculation of sd
* recalculatestat;
@@ -24343,6 +24451,8 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(getguildalliance,"ii"),
BUILDIN_DEF(adopt,"vv"),
BUILDIN_DEF(getexp2,"ii?"),
+ BUILDIN_DEF(costume, "i"),
+ BUILDIN_DEF(getcostumeitem, "v"),
BUILDIN_DEF(recalculatestat,""),
BUILDIN_DEF(hateffect,"ii"),
BUILDIN_DEF(getrandomoptinfo, "i"),
diff --git a/src/map/status.cpp b/src/map/status.cpp
index af4c3afb00..a296f7b89e 100644
--- a/src/map/status.cpp
+++ b/src/map/status.cpp
@@ -3492,6 +3492,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
continue;
if (!sd->inventory_data[index])
continue;
+ if (sd->inventory.u.items_inventory[current_equip_item_index].card[0] == CARD0_CREATE && MakeDWord(sd->inventory.u.items_inventory[current_equip_item_index].card[2], sd->inventory.u.items_inventory[current_equip_item_index].card[3]) == battle_config.reserved_costume_id)
+ continue;
base_status->def += sd->inventory_data[index]->def;