diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/battle.c | 1 | ||||
-rw-r--r-- | src/map/battle.h | 1 | ||||
-rw-r--r-- | src/map/clif.c | 144 | ||||
-rw-r--r-- | src/map/clif.h | 15 | ||||
-rw-r--r-- | src/map/packets.h | 2 | ||||
-rw-r--r-- | src/map/packets_struct.h | 12 | ||||
-rw-r--r-- | src/map/pet.c | 163 | ||||
-rw-r--r-- | src/map/pet.h | 15 | ||||
-rw-r--r-- | src/map/script.c | 101 | ||||
-rw-r--r-- | src/map/skill.c | 8 | ||||
-rw-r--r-- | src/map/skill.h | 2 |
11 files changed, 411 insertions, 53 deletions
diff --git a/src/map/battle.c b/src/map/battle.c index 6a961afeb..4d320704a 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -7319,6 +7319,7 @@ static const struct battle_data { { "features/rodex", &battle_config.feature_rodex, 1, 0, 1, }, { "features/rodex_use_accountmail", &battle_config.feature_rodex_use_accountmail, 0, 0, 1, }, { "features/enable_homun_autofeed", &battle_config.feature_enable_homun_autofeed, 1, 0, 1, }, + { "features/enable_pet_autofeed", &battle_config.feature_enable_pet_autofeed, 1, 0, 1, }, { "storage_use_item", &battle_config.storage_use_item, 0, 0, 1, }, { "features/enable_attendance_system", &battle_config.feature_enable_attendance_system,1, 0, 1, }, { "features/feature_attendance_endtime",&battle_config.feature_attendance_endtime, 1, 0, 99999999, }, diff --git a/src/map/battle.h b/src/map/battle.h index c325daf0d..f4176f142 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -563,6 +563,7 @@ struct Battle_Config { int feature_rodex_use_accountmail; int feature_enable_homun_autofeed; + int feature_enable_pet_autofeed; int storage_use_item; diff --git a/src/map/clif.c b/src/map/clif.c index aeaf03e43..c085c4fe4 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -9093,7 +9093,7 @@ void clif_feel_hate_reset(struct map_session_data *sd) /// value: /// 0 = disabled /// 1 = enabled -void clif_zc_config(struct map_session_data* sd, int type, int flag) +void clif_zc_config(struct map_session_data* sd, enum CZ_CONFIG type, int flag) { int fd; nullpo_retv(sd); @@ -13755,6 +13755,115 @@ void clif_parse_ChangePetName(int fd, struct map_session_data *sd) pet->change_name(sd, RFIFOP(fd,2)); } +void clif_parse_pet_evolution(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); +/// Request to Evolve the pet (CZ_PET_EVOLUTION) [Dastgir/Hercules] +/// 09fb <Length>.W <EvolvedPetEggID>.W {<index>.W <amount>.W}*items +void clif_parse_pet_evolution(int fd, struct map_session_data *sd) +{ + const struct PACKET_CZ_PET_EVOLUTION *p = RP2PTR(fd); + int i = 0, idx, petIndex; + + Assert_retv(p->PacketLength >= (uint16)sizeof(struct PACKET_CZ_PET_EVOLUTION)); + + if (sd->status.pet_id == 0) { + clif->petEvolutionResult(fd, PET_EVOL_NO_CALLPET); + return; + } + + ARR_FIND(0, MAX_INVENTORY, idx, sd->status.inventory[idx].card[0] == CARD0_PET && + sd->status.pet_id == MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); + + if (idx == MAX_INVENTORY) { + clif->petEvolutionResult(fd, PET_EVOL_NO_PETEGG); + return; + } + + // Not Loyal Yet + if (sd->pd == NULL || sd->pd->pet.intimate < 900) { + clif->petEvolutionResult(fd, PET_EVOL_RG_FAMILIAR); + return; + } + + ARR_FIND(0, MAX_PET_DB, petIndex, pet->db[petIndex].class_ == sd->pd->pet.class_); + + if (petIndex == MAX_PET_DB) { + // Which error? + clif->petEvolutionResult(fd, PET_EVOL_UNKNOWN); + return; + } + + // Client side validation is not done as it is insecure. + for (i = 0; i < VECTOR_LENGTH(pet->db[petIndex].evolve_data); i++) { + struct pet_evolve_data *ped = &VECTOR_INDEX(pet->db[petIndex].evolve_data, i); + if (ped->petEggId == p->EvolvedPetEggID) { + int j; + int pet_id; + + if (VECTOR_LENGTH(ped->items) == 0) { + clif->petEvolutionResult(fd, PET_EVOL_NO_RECIPE); + return; + } + for (j = 0; j < VECTOR_LENGTH(ped->items); j++) { + struct itemlist_entry *list = &VECTOR_INDEX(ped->items, j); + int n = pc->search_inventory(sd, list->id); + + if (n == INDEX_NOT_FOUND) { + clif->petEvolutionResult(fd, PET_EVOL_NO_MATERIAL); + return; + } + } + + for (j = 0; j < VECTOR_LENGTH(ped->items); j++) { + struct itemlist_entry *list = &VECTOR_INDEX(ped->items, j); + int n = pc->search_inventory(sd, list->id); + + if (pc->delitem(sd, n, list->amount, 0, DELITEM_NORMAL, LOG_TYPE_EGG) == 1) { + clif->petEvolutionResult(fd, PET_EVOL_NO_MATERIAL); + return; + } + } + + // Return to Egg + pet->return_egg(sd, sd->pd); + + if (pc->delitem(sd, idx, 1, 0, DELITEM_NORMAL, LOG_TYPE_EGG) == 1) { + clif->petEvolutionResult(fd, PET_EVOL_NO_PETEGG); + return; + } + + pet_id = pet->search_petDB_index(ped->petEggId, PET_EGG); + if (pet_id >= 0) { + sd->catch_target_class = pet->db[pet_id].class_; + + intif->create_pet( + sd->status.account_id, sd->status.char_id, + (short)pet->db[pet_id].class_, (short)mob->db(pet->db[pet_id].class_)->lv, + (short)pet->db[pet_id].EggID, 0, (short)pet->db[pet_id].intimate, + 100, 0, 1, pet->db[pet_id].jname); + clif->petEvolutionResult(fd, PET_EVOL_SUCCESS); + } else { + clif->petEvolutionResult(fd, PET_EVOL_UNKNOWN); + } + return; + } + } + + clif->petEvolutionResult(fd, PET_EVOL_UNKNOWN); +} + +/** + * Result of Pet Evolution (ZC_PET_EVOLUTION_RESULT) + * 0x9fc <Result>.L + */ +void clif_pet_evolution_result(int fd, enum pet_evolution_result result) { +#if PACKETVER >= 20140122 + WFIFOHEAD(fd, packet_len(0x9fc)); + WFIFOW(fd, 0) = 0x9fc; + WFIFOL(fd, 2) = result; + WFIFOSET(fd, packet_len(0x9fc)); +#endif +} + void clif_parse_GMKick(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /kill (CZ_DISCONNECT_CHARACTER). /// Request to disconnect a character. @@ -16154,24 +16263,38 @@ void clif_parse_cz_config(int fd, struct map_session_data *sd) __attribute__((no /// 02d8 <type>.L <value>.L /// type: /// 0 = open equip window +/// 2 = pet autofeeding /// 3 = homunculus autofeeding /// value: /// 0 = disabled /// 1 = enabled void clif_parse_cz_config(int fd, struct map_session_data *sd) { - int type = RFIFOL(fd, 2); + enum CZ_CONFIG type = RFIFOL(fd, 2); int flag = RFIFOL(fd, 6); - if (type == CZ_CONFIG_OPEN_EQUIPMENT_WINDOW) { + switch (type) { + case CZ_CONFIG_OPEN_EQUIPMENT_WINDOW: sd->status.show_equip = flag; - } else if (type == CZ_CONFIG_HOMUNCULUS_AUTOFEEDING) { - struct homun_data *hd; - hd = sd->hd; + break; + case CZ_CONFIG_PET_AUTOFEEDING: { + struct pet_data *pd = sd->pd; + nullpo_retv(pd); + if (pd->petDB->autofeed == 0) { + clif->message(fd, "Autofeed is disabled for this pet."); + return; + } + pd->pet.autofeed = flag; + break; + } + case CZ_CONFIG_HOMUNCULUS_AUTOFEEDING: { + struct homun_data *hd = sd->hd; nullpo_retv(hd); hd->homunculus.autofeed = flag; - } else { - ShowWarning("clif_parse_cz_config: Unsupported type has been received (%d).", type); + break; + } + default: + ShowWarning("clif_parse_cz_config: Unsupported type has been received (%u).\n", type); return; } clif->zc_config(sd, type, flag); @@ -21991,4 +22114,9 @@ void clif_defaults(void) { clif->pReqStyleChange = clif_parse_cz_req_style_change; clif->cz_req_style_change_sub = clif_cz_req_style_change_sub; clif->style_change_response = clif_style_change_response; + + // -- Pet Evolution + clif->pPetEvolution = clif_parse_pet_evolution; + clif->petEvolutionResult = clif_pet_evolution_result; + } diff --git a/src/map/clif.h b/src/map/clif.h index 4b625023f..eb9881533 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -592,6 +592,17 @@ enum private_airship { P_AIRSHIP_ITEM_INVALID }; +/** Pet Evolution Results */ +enum pet_evolution_result { + PET_EVOL_UNKNOWN = 0x0, + PET_EVOL_NO_CALLPET = 0x1, + PET_EVOL_NO_PETEGG = 0x2, + PET_EVOL_NO_RECIPE = 0x3, + PET_EVOL_NO_MATERIAL = 0x4, + PET_EVOL_RG_FAMILIAR = 0x5, + PET_EVOL_SUCCESS = 0x6, +}; + /** * Structures **/ @@ -834,7 +845,7 @@ struct clif_interface { void (*mission_info) (struct map_session_data *sd, int mob_id, unsigned char progress); void (*feel_hate_reset) (struct map_session_data *sd); void (*partytickack) (struct map_session_data* sd, bool flag); - void (*zc_config) (struct map_session_data *sd, int type, int flag); + void (*zc_config) (struct map_session_data *sd, enum CZ_CONFIG type, int flag); void (*viewequip_ack) (struct map_session_data* sd, struct map_session_data* tsd); void (*equpcheckbox) (struct map_session_data* sd); void (*displayexp) (struct map_session_data *sd, uint64 exp, char type, bool is_quest); @@ -1484,6 +1495,8 @@ struct clif_interface { void (*pReqStyleChange) (int fd, struct map_session_data *sd); void (*cz_req_style_change_sub) (struct map_session_data *sd, int type, int16 idx, bool isitem); void (*style_change_response) (struct map_session_data *sd, enum stylist_shop flag); + void (*pPetEvolution) (int fd, struct map_session_data *sd); + void (*petEvolutionResult) (int fd, enum pet_evolution_result result); }; #ifdef HERCULES_CORE diff --git a/src/map/packets.h b/src/map/packets.h index e5fda598d..ebd971005 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -3029,7 +3029,7 @@ packet(0x96e,-1,clif->ackmergeitems); // 2014-01-22aRagexeRE #if PACKETVER >= 20140122 // new packets - packet(0x09fb,-1,clif->pDull/*,XXX*/); // CZ_PET_EVOLUTION + packet(0x09fb,-1,clif->pPetEvolution); // CZ_PET_EVOLUTION packet(0x09fc,6); // ZC_PET_EVOLUTION_RESULT packet(0x09fd,-1); // ZC_NOTIFY_MOVEENTRY11 packet(0x09fe,-1); // ZC_NOTIFY_NEWENTRY11 diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index d152ffd2a..bcdf1061a 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -1762,6 +1762,18 @@ struct PACKET_ZC_STYLE_CHANGE_RES { int8 flag; } __attribute__((packed)); +struct pet_evolution_items { + int16 index; + int16 amount; +} __attribute__((packed)); + +struct PACKET_CZ_PET_EVOLUTION { + int16 PacketType; + uint16 PacketLength; + int16 EvolvedPetEggID; + // struct pet_evolution_items items[]; +} __attribute__((packed)); + #if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute #pragma pack(pop) #endif // not NetBSD < 6 / Solaris diff --git a/src/map/pet.c b/src/map/pet.c index 4bac79dc8..58c26d1ce 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -85,8 +85,21 @@ void pet_set_intimate(struct pet_data *pd, int value) sd = pd->msd; pd->pet.intimate = value; + if( (intimate >= battle_config.pet_equip_min_friendly && pd->pet.intimate < battle_config.pet_equip_min_friendly) || (intimate < battle_config.pet_equip_min_friendly && pd->pet.intimate >= battle_config.pet_equip_min_friendly) ) status_calc_pc(sd,SCO_NONE); + + /* Pet is lost, delete the egg */ + if (value <= 0) { + int i; + + ARR_FIND(0, MAX_INVENTORY, i, sd->status.inventory[i].card[0] == CARD0_PET && + pd->pet.pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2])); + + if (i != MAX_INVENTORY) { + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_EGG); + } + } } int pet_create_egg(struct map_session_data *sd, int item_id) @@ -233,6 +246,13 @@ int pet_hungry(int tid, int64 tick, int id, intptr_t data) { return 1; //You lost the pet already, the rest is irrelevant. pd->pet.hungry--; + /* Pet Autofeed */ + if (battle_config.feature_enable_homun_autofeed != 0) { + if (pd->petDB->autofeed == 1 && pd->pet.autofeed == 1 && pd->pet.hungry <= 25) { + pet->food(sd, pd); + } + } + if( pd->pet.hungry < 0 ) { pet_stop_attack(pd); @@ -311,23 +331,21 @@ int pet_performance(struct map_session_data *sd, struct pet_data *pd) int pet_return_egg(struct map_session_data *sd, struct pet_data *pd) { - struct item tmp_item; - int flag; + int i; nullpo_retr(1, sd); nullpo_retr(1, pd); pet->lootitem_drop(pd,sd); - memset(&tmp_item,0,sizeof(tmp_item)); - tmp_item.nameid = pd->petDB->EggID; - tmp_item.identify = 1; - tmp_item.card[0] = CARD0_PET; - tmp_item.card[1] = GetWord(pd->pet.pet_id,0); - tmp_item.card[2] = GetWord(pd->pet.pet_id,1); - tmp_item.card[3] = pd->pet.rename_flag; - if((flag = pc->additem(sd,&tmp_item,1,LOG_TYPE_EGG))) { - clif->additem(sd,0,0,flag); - map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false); + + // Pet Evolution + ARR_FIND(0, MAX_INVENTORY, i, sd->status.inventory[i].card[0] == CARD0_PET && + pd->pet.pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2])); + + if (i != MAX_INVENTORY) { + sd->status.inventory[i].identify = 1; + sd->status.inventory[i].bound = IBT_NONE; } + pd->pet.incubate = 1; unit->free(&pd->bl,CLR_OUTSIGHT); @@ -462,19 +480,23 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag) { } if(p->incubate == 1) { int i; - //Delete egg from inventory. [Skotlex] - for (i = 0; i < MAX_INVENTORY; i++) { - if(sd->status.inventory[i].card[0] == CARD0_PET && - p->pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2])) - break; - } - if(i >= MAX_INVENTORY) { + // Get Egg Index + ARR_FIND(0, MAX_INVENTORY, i, sd->status.inventory[i].card[0] == CARD0_PET && + p->pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2])); + + if(i == MAX_INVENTORY) { ShowError("pet_recv_petdata: Hatching pet (%d:%s) aborted, couldn't find egg in inventory for removal!\n",p->pet_id, p->name); sd->status.pet_id = 0; return 1; } - if (!pet->birth_process(sd,p)) //Pet hatched. Delete egg. - pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_EGG); + + + if (!pet->birth_process(sd,p)) { + // Pet Evolution, Hide the egg by setting identify to 0 [Dastgir/Hercules] + sd->status.inventory[i].identify = 0; + // bind the egg to the character to avoid moving it via forged packets [Asheraf] + sd->status.inventory[i].bound = IBT_CHARACTER; + } } else { pet->data_init(sd,p); if(sd->pd && sd->bl.prev != NULL) { @@ -1359,6 +1381,14 @@ int pet_read_db_sub(struct config_setting_t *it, int n, const char *source) if (libconfig->setting_lookup_int(it, "ChangeTargetRate", &i32)) pet->db[n].change_target_rate = i32; + // Pet Evolution + if ((t = libconfig->setting_get_member(it, "Evolve")) && config_setting_is_group(t)) { + pet->read_db_sub_evolution(t, n); + } + + if ((t = libconfig->setting_get_member(it, "AutoFeed")) && (i32 = libconfig->setting_get_bool(t))) + pet->db[n].autofeed = i32; + if (libconfig->setting_lookup_string(it, "PetScript", &str)) pet->db[n].pet_script = *str ? script->parse(str, source, -pet->db[n].class_, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; @@ -1368,6 +1398,81 @@ int pet_read_db_sub(struct config_setting_t *it, int n, const char *source) return pet->db[n].class_; } +/** + * Read Pet Evolution Database [Dastgir/Hercules] + * @param t libconfig setting + * @param n Pet DB Index + */ +void pet_read_db_sub_evolution(struct config_setting_t *t, int n) +{ + struct config_setting_t *pett; + int i = 0; + const char *str = NULL; + + nullpo_retv(t); + Assert_retv(n >= 0 && n < MAX_PET_DB); + + VECTOR_INIT(pet->db[n].evolve_data); + + while ((pett = libconfig->setting_get_elem(t, i))) { + if (config_setting_is_group(pett)) { + struct pet_evolve_data ped; + struct item_data *data; + struct config_setting_t *item; + int j = 0, i32 = 0; + + str = config_setting_name(pett); + + if (!(data = itemdb->name2id(str))) { + ShowWarning("pet_read_evolve_db_sub: Invalid Egg '%s' in Pet #%d, skipping.\n", str, pet->db[n].class_); + return; + } else { + ped.petEggId = data->nameid; + } + + VECTOR_INIT(ped.items); + + while ((item = libconfig->setting_get_elem(pett, j))) { + struct itemlist_entry list = { 0 }; + int quantity = 0; + + str = config_setting_name(item); + data = itemdb->search_name(str); + + if (!data) { + ShowWarning("pet_read_evolve_db_sub: required item %s not found in egg %d\n", str, ped.petEggId); + j++; + continue; + } + + list.id = data->nameid; + + if (mob->get_const(item, &i32) && i32 >= 0) { + quantity = i32; + } + + if (quantity <= 0) { + ShowWarning("pet_read_evolve_db_sub: invalid quantity %d for egg %d\n", quantity, ped.petEggId); + j++; + continue; + } + + list.amount = quantity; + + VECTOR_ENSURE(ped.items, 1, 1); + VECTOR_PUSH(ped.items, list); + + j++; + + } + + VECTOR_ENSURE(pet->db[n].evolve_data, 1, 1); + VECTOR_PUSH(pet->db[n].evolve_data, ped); + } + i++; + } +} + bool pet_read_db_sub_intimacy(int idx, struct config_setting_t *t) { int i32 = 0; @@ -1396,6 +1501,7 @@ void pet_read_db_clear(void) // Remove any previous scripts in case reloaddb was invoked. for (i = 0; i < MAX_PET_DB; i++) { + int j; if (pet->db[i].pet_script) { script->free_code(pet->db[i].pet_script); pet->db[i].pet_script = NULL; @@ -1404,6 +1510,11 @@ void pet_read_db_clear(void) script->free_code(pet->db[i].equip_script); pet->db[i].equip_script = NULL; } + + for (j = 0; j < VECTOR_LENGTH(pet->db[i].evolve_data); j++) { + VECTOR_CLEAR(VECTOR_INDEX(pet->db[i].evolve_data, j).items); + } + VECTOR_CLEAR(pet->db[i].evolve_data); } memset(pet->db, 0, sizeof(pet->db)); return; @@ -1437,6 +1548,7 @@ int do_final_pet(void) int i; for( i = 0; i < MAX_PET_DB; i++ ) { + int j; if( pet->db[i].pet_script ) { script->free_code(pet->db[i].pet_script); @@ -1447,9 +1559,16 @@ int do_final_pet(void) script->free_code(pet->db[i].equip_script); pet->db[i].equip_script = NULL; } + + /* Pet Evolution [Dastgir/Hercules] */ + for (j = 0; j < VECTOR_LENGTH(pet->db[i].evolve_data); j++) { + VECTOR_CLEAR(VECTOR_INDEX(pet->db[i].evolve_data, j).items); + } + VECTOR_CLEAR(pet->db[i].evolve_data); } ers_destroy(pet->item_drop_ers); ers_destroy(pet->item_drop_list_ers); + return 0; } void pet_defaults(void) { @@ -1503,4 +1622,6 @@ void pet_defaults(void) { pet->read_db_sub = pet_read_db_sub; pet->read_db_sub_intimacy = pet_read_db_sub_intimacy; pet->read_db_clear = pet_read_db_clear; + + pet->read_db_sub_evolution = pet_read_db_sub_evolution; } diff --git a/src/map/pet.h b/src/map/pet.h index d341be97c..b3a16c5d7 100644 --- a/src/map/pet.h +++ b/src/map/pet.h @@ -30,6 +30,12 @@ #define MAX_PET_DB 300 #define MAX_PETLOOT_SIZE 30 +/** Pet Evolution [Dastgir/Hercules] */ +struct pet_evolve_data { + int petEggId; + VECTOR_DECL(struct itemlist_entry) items; +}; + struct s_pet_db { short class_; char name[NAME_LENGTH],jname[NAME_LENGTH]; @@ -50,8 +56,12 @@ struct s_pet_db { int attack_rate; int defence_attack_rate; int change_target_rate; + int autofeed; struct script_code *equip_script; struct script_code *pet_script; + + /* Pet Evolution */ + VECTOR_DECL(struct pet_evolve_data) evolve_data; }; enum { PET_CLASS,PET_CATCH,PET_EGG,PET_EQUIP,PET_FOOD }; @@ -127,6 +137,7 @@ struct pet_interface { struct s_pet_db db[MAX_PET_DB]; struct eri *item_drop_ers; //For loot drops delay structures. struct eri *item_drop_list_ers; + /* */ int (*init) (bool minimal); int (*final) (void); @@ -172,6 +183,10 @@ struct pet_interface { int (*read_db_sub) (struct config_setting_t *it, int n, const char *source); bool (*read_db_sub_intimacy) (int idx, struct config_setting_t *t); void (*read_db_clear) (void); + + /* Pet Evolution [Dastgir/Hercules] */ + void (*read_db_sub_evolution) (struct config_setting_t *t, int n); + }; #ifdef HERCULES_CORE diff --git a/src/map/script.c b/src/map/script.c index 410a707f1..952496486 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -1428,8 +1428,8 @@ const char* script_parse_subexpr(const char* p,int limit) p=script->skip_space(p); while(( (op=C_OP3, opl=0, len=1,*p=='?') // ?: - || (op=C_ADD, opl=9, len=1,*p=='+') // + - || (op=C_SUB, opl=9, len=1,*p=='-') // - + || (op=C_ADD, opl=9, len=1,*p=='+' && p[1]!='+') // + + || (op=C_SUB, opl=9, len=1,*p=='-' && p[1]!='-') // - || (op=C_POW, opl=11,len=2,*p=='*' && p[1]=='*') // ** || (op=C_MUL, opl=10,len=1,*p=='*') // * || (op=C_DIV, opl=10,len=1,*p=='/') // / @@ -8597,7 +8597,8 @@ BUILDIN(disableitemuse) * return the basic stats of sd * chk pc->readparam for available type *------------------------------------------*/ -BUILDIN(readparam) { +BUILDIN(readparam) +{ int type; struct map_session_data *sd; struct script_data *data = script_getdata(st, 2); @@ -8609,7 +8610,11 @@ BUILDIN(readparam) { } if (script_hasdata(st, 3)) { - sd = script->nick2sd(st, script_getstr(st, 3)); + if (script_isstringtype(st, 3)) { + sd = script->nick2sd(st, script_getstr(st, 3)); + } else { + sd = script->id2sd(st, script_getnum(st, 3)); + } } else { sd = script->rid2sd(st); } @@ -8623,6 +8628,43 @@ BUILDIN(readparam) { return true; } +BUILDIN(setparam) +{ + int type; + struct map_session_data *sd; + struct script_data *data = script_getdata(st, 2); + int val = script_getnum(st, 3); + + if (data_isreference(data) && reference_toparam(data)) { + type = reference_getparamtype(data); + } else { + type = script->conv_num(st, data); + } + + if (script_hasdata(st, 4)) { + if (script_isstringtype(st, 4)) { + sd = script->nick2sd(st, script_getstr(st, 4)); + } else { + sd = script->id2sd(st, script_getnum(st, 4)); + } + } else { + sd = script->rid2sd(st); + } + + if (sd == NULL) { + script_pushint(st, 0); + return true; + } + + if (pc->setparam(sd, type, val) == 0) { + script_pushint(st, 0); + return false; + } + + script_pushint(st, 1); + return true; +} + /*========================================== * Return charid identification * return by @num : @@ -21160,6 +21202,7 @@ BUILDIN(instance_create) const char *name; int owner_id, res; int type = IOT_PARTY; + struct map_session_data *sd = map->id2sd(st->rid); name = script_getstr(st, 2); owner_id = script_getnum(st, 3); @@ -21172,22 +21215,43 @@ BUILDIN(instance_create) } res = instance->create(owner_id, name, (enum instance_owner_type) type); - if( res == -4 ) { // Already exists - script_pushint(st, -1); - return true; - } else if( res < 0 ) { + if (sd != NULL) { + switch (res) { + case -4: // Already exists + clif->msgtable_str(sd, MSG_MDUNGEON_SUBSCRIPTION_ERROR_DUPLICATE, name); + break; + case -3: // No free instances + clif->msgtable_str(sd, MSG_MDUNGEON_SUBSCRIPTION_ERROR_EXIST, name); + break; + case -2: // Invalid type + clif->msgtable_str(sd, MSG_MDUNGEON_SUBSCRIPTION_ERROR_RIGHT, name); + break; + case -1: // Unknown + clif->msgtable_str(sd, MSG_MDUNGEON_SUBSCRIPTION_ERROR_UNKNOWN, name); + break; + default: + if (res < 0) + ShowError("buildin_instance_create: failed to unknown reason [%d].\n", res); + } + } else { const char *err; - switch(res) { - case -3: err = "No free instances"; break; - case -2: err = "Invalid party ID"; break; - case -1: err = "Invalid type"; break; - default: err = "Unknown"; break; + switch (res) { + case -3: + err = "No free instances"; + break; + case -2: + err = "Invalid party ID"; + break; + case -1: + err = "Invalid type"; + break; + default: + err = "Unknown"; + break; } - ShowError("buildin_instance_create: %s [%d].\n", err, res); - script_pushint(st, -2); - return true; + if (res < 0) + ShowError("buildin_instance_create: %s [%d].\n", err, res); } - script_pushint(st, res); return true; } @@ -23860,7 +23924,7 @@ bool rodex_sendmail_sub(struct script_state* st, struct rodex_message *msg) { const char *sender_name, *title, *body; - if (!strcmp(script->getfuncname(st), "rodex_sendmail_acc2")) + if (strcmp(script->getfuncname(st), "rodex_sendmail_acc") == 0 || strcmp(script->getfuncname(st), "rodex_sendmail_acc2") == 0) msg->receiver_accountid = script_getnum(st, 2); else msg->receiver_id = script_getnum(st, 2); @@ -24390,6 +24454,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(checkweight,"vi*"), BUILDIN_DEF(checkweight2,"rr"), BUILDIN_DEF(readparam,"i?"), + BUILDIN_DEF(setparam,"ii?"), BUILDIN_DEF(getcharid,"i?"), BUILDIN_DEF(getnpcid,"i?"), BUILDIN_DEF(getpartyname,"i"), diff --git a/src/map/skill.c b/src/map/skill.c index 6eacde897..34c36d7f3 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -15027,8 +15027,9 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, } break; default: - skill->check_condition_castend_unknown(sd, &skill_id, &skill_lv); - break; + if (!skill->check_condition_castend_unknown(sd, &skill_id, &skill_lv)) + break; + return 0; } st = &sd->battle_status; @@ -15115,8 +15116,9 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, return 1; } -void skill_check_condition_castend_unknown(struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv) +bool skill_check_condition_castend_unknown(struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv) { + return false; } // type&2: consume items (after skill was used) diff --git a/src/map/skill.h b/src/map/skill.h index e16094eae..bd1dc3344 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -2172,7 +2172,7 @@ struct skill_interface { int (*check_condition_castbegin_mount_unknown) (struct status_change *sc, uint16 *skill_id); int (*check_condition_castbegin_madogear_unknown) (struct status_change *sc, uint16 *skill_id); int (*check_condition_castbegin_unknown) (struct status_change *sc, uint16 *skill_id); - void (*check_condition_castend_unknown) (struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv); + bool (*check_condition_castend_unknown) (struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv); bool (*get_requirement_off_unknown) (struct status_change *sc, uint16 *skill_id); bool (*get_requirement_item_unknown) (struct status_change *sc, struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv, uint16 *idx, int *i); void (*get_requirement_unknown) (struct status_change *sc, struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv, struct skill_condition *req); |