From e02ba8bd88c626baca4619bbb2dbaecd30c93f9b Mon Sep 17 00:00:00 2001 From: Seravy Date: Mon, 17 Feb 2020 21:34:29 +0100 Subject: [PATCH] Costume Feature --- conf/battle/battle.conf | 7 +++++++ npc/custom/costume.ser | 44 +++++++++++++++++++++++++++++++++++++++ npc/scripts_custom.conf | 1 + src/map/atcommand.cpp | 22 +++++++++++++++++++- src/map/battle.cpp | 1 + src/map/battle.hpp | 1 + src/map/map.cpp | 7 +++++++ src/map/pc.cpp | 16 +++++++++++++- src/map/script.cpp | 46 +++++++++++++++++++++++++++++++++++++++++ src/map/status.cpp | 2 +- 10 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 npc/custom/costume.ser diff --git a/conf/battle/battle.conf b/conf/battle/battle.conf index b112502e9f7..7e5dbf14e0f 100644 --- a/conf/battle/battle.conf +++ b/conf/battle/battle.conf @@ -167,3 +167,10 @@ 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 + +// Costume item edit +// Reserved Char ID for costume converted items. +// 0 = Disable +// If you change this later, then all converted/created costumeitem's will +// turn back to normal items with a 'Unknown's ...' name and no socket in it. +reserved_costume_id: 1 diff --git a/npc/custom/costume.ser b/npc/custom/costume.ser new file mode 100644 index 00000000000..a32319ae8e2 --- /dev/null +++ b/npc/custom/costume.ser @@ -0,0 +1,44 @@ +prontera,172,182,4 script Costumer#cs_0 646,{ + mes "[ "+strnpcinfo(1)+" ]"; + mes "I can convert your equipment into costumes!"; + mes "^ff0000Warning!^000000"; + mes "Converted item will lose all defense, refine, cards and abilities permanently!"; + mes "I also charge a modest service fee of 30 Karvodailnirol, 30 Detrimindexta and 1 million zeny."; + next; + setarray .@Position$[1],"Top","Mid","Low","Garment"; + setarray .@Position[1],EQI_HEAD_TOP , EQI_HEAD_MID,EQI_HEAD_LOW,EQI_GARMENT; + set .@Menu$,""; + for( set .@i, 1; .@i < 5; set .@i, .@i + 1 ) + { + if( getequipisequiped(.@Position[.@i]) ) + set .@Menu$, .@Menu$ + .@Position$[.@i] + "-" + "[" + getequipname(.@Position[.@i]) + "]"; + set .@Menu$, .@Menu$ + ":"; + } + set .@Part, .@Position[ select(.@Menu$) ]; + if( !getequipisequiped(.@Part) ) + { + mes "[ " + strnpcinfo(1) + " ]"; + mes "You are not wearing anything there..."; + close; + } + mes "[ "+strnpcinfo(1)+" ]"; + mes "You want to Costume your " + getitemname(getequipid(.@Part)) + "?"; + next; + if( select("Yes, proceed:No, I am sorry.") == 2 ) + { + mes "[ "+strnpcinfo(1)+" ]"; + mes "Need some time to think about it, huh?"; + mes "Alright, I can understand."; + close; + } + if (Zeny<1000000) { mes "You didn't bring enough money!"; close; } + if (Countitem(971)<30) { mes "You didn't bring enough Detrimindexta!"; close; } + if (Countitem(972)<30) { mes "You didn't bring enough Karvodailnirol!"; close; } + Zeny = Zeny - 1000000; + delitem 971,30; + delitem 972,30; + costume .@Part; // Convert the Headgear + mes "[ "+strnpcinfo(1)+" ]"; + mes "Done, enjoy your costume headgear."; + close; +} diff --git a/npc/scripts_custom.conf b/npc/scripts_custom.conf index caf15cc542a..e397dcef2ab 100644 --- a/npc/scripts_custom.conf +++ b/npc/scripts_custom.conf @@ -21,6 +21,7 @@ npc: npc/custom/quests/may_hats.ser npc: npc/custom/quests/dead_branch.ser npc: npc/custom/quests/jewel_case.ser npc: npc/custom/uneasy_cemetery.ser +npc: npc/custom/costume.ser // --------------------- Unofficial Scripts -------------------- // -- Custom quests from official Umbalian Quests diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 9269c400c1a..fda0f1e001f 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -1256,7 +1256,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; // Costume item edit char flag = 0; struct item item_tmp; struct item_data *item_data[10]; @@ -1295,6 +1295,25 @@ ACMD_FUNC(item) clif_displaymessage(fd, msg_txt(sd,19)); // Invalid item ID or name. return -1; } + // Costume item edit + if (!strcmpi(command + 1, "costumeitem")) { + if (!battle_config.reserved_costume_id) { + clif_displaymessage(fd, "Costume convertion is disabled."); + 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)) + { + clif_displaymessage(fd, "You cannot costume this item. Costume only work for headgears."); + return -1; + } + costume = 1; + } // end edit + itemlist = strtok(NULL, ":"); //next itemline j++; } @@ -10374,6 +10393,7 @@ void atcommand_basecommands(void) { ACMD_DEFR(channel,ATCMD_NOSCRIPT), ACMD_DEF(fontcolor), ACMD_DEF(langtype), + ACMD_DEF2("costumeitem", item), // Costume item edit #ifdef VIP_ENABLE ACMD_DEF(vip), ACMD_DEF(showrate), diff --git a/src/map/battle.cpp b/src/map/battle.cpp index d50c0398271..c53d0fafdfe 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -8504,6 +8504,7 @@ static const struct _battle_data { { "homunculus_evo_intimacy_need", &battle_config.homunculus_evo_intimacy_need, 91100, 0, INT_MAX, }, { "homunculus_evo_intimacy_reset", &battle_config.homunculus_evo_intimacy_reset, 1000, 0, INT_MAX, }, { "monster_loot_search_type", &battle_config.monster_loot_search_type, 1, 0, 1, }, + { "reserved_costume_id", &battle_config.reserved_costume_id, 1, 0, INT_MAX, }, // Costume item edit { "feature.roulette", &battle_config.feature_roulette, 1, 0, 1, }, { "monster_hp_bars_info", &battle_config.monster_hp_bars_info, 1, 0, 1, }, { "min_body_style", &battle_config.min_body_style, 0, 0, SHRT_MAX, }, diff --git a/src/map/battle.hpp b/src/map/battle.hpp index 483b9e236a9..36745e47d49 100644 --- a/src/map/battle.hpp +++ b/src/map/battle.hpp @@ -610,6 +610,7 @@ struct Battle_Config int homunculus_evo_intimacy_need; int homunculus_evo_intimacy_reset; int monster_loot_search_type; + int reserved_costume_id; // Costume item edit int feature_roulette; int monster_hp_bars_info; int min_body_style; diff --git a/src/map/map.cpp b/src/map/map.cpp index 447d2686bfa..e1fd0bc0b3b 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -1952,6 +1952,13 @@ void map_reqnickdb(struct map_session_data * sd, int charid) nullpo_retv(sd); + // Costume item edit + if (battle_config.reserved_costume_id && battle_config.reserved_costume_id == charid) + { + clif_solved_charname(sd->fd, charid, "Costume"); + return; + } //end + tsd = map_charid2sd(charid); if( tsd ) { diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 645fb2c5002..705a69f0a79 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -892,7 +892,21 @@ 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]); + int char_id = 0; + + // Costume item edit + if (battle_config.reserved_costume_id && + sd->inventory.u.items_inventory[n].card[0] == CARD0_CREATE && + (char_id = 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; } + } // End edit + + return ep; } /** diff --git a/src/map/script.cpp b/src/map/script.cpp index 16510a15ed2..32bcd6e2532 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -23216,6 +23216,51 @@ BUILDIN_FUNC(channel_create) { return SCRIPT_CMD_SUCCESS; } +/** + * Costume item edit + **/ +BUILDIN_FUNC(costume) { + int i = -1, num, ep; + TBL_PC *sd; + + num = script_getnum(st, 2); // Equip Slot + sd = map_id2sd(st->rid); + + if (sd == NULL) + return 0; + i = pc_checkequip(sd, equip_bitmask[num]); + if (i < 0) + return 0; + + ep = sd->inventory.u.items_inventory[i].equip; + if (!(ep&EQP_HEAD_LOW) && !(ep&EQP_HEAD_MID) && !(ep&EQP_HEAD_TOP) && !(ep&EQP_GARMENT)) + return 0; + + 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 0; +} + /** * Set channel option * channel_setopt "",