diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/HPMmap.c | 12 | ||||
-rw-r--r-- | src/map/battle.c | 75 | ||||
-rw-r--r-- | src/map/clif.c | 42 | ||||
-rw-r--r-- | src/map/clif.h | 2 | ||||
-rw-r--r-- | src/map/itemdb.c | 81 | ||||
-rw-r--r-- | src/map/itemdb.h | 7 | ||||
-rw-r--r-- | src/map/map.c | 47 | ||||
-rw-r--r-- | src/map/map.h | 10 | ||||
-rw-r--r-- | src/map/mob.c | 35 | ||||
-rw-r--r-- | src/map/mob.h | 9 | ||||
-rw-r--r-- | src/map/npc.c | 53 | ||||
-rw-r--r-- | src/map/npc.h | 3 | ||||
-rw-r--r-- | src/map/pc.c | 75 | ||||
-rw-r--r-- | src/map/pc.h | 4 | ||||
-rw-r--r-- | src/map/script.c | 368 | ||||
-rw-r--r-- | src/map/script.h | 1 | ||||
-rw-r--r-- | src/map/skill.c | 52 | ||||
-rw-r--r-- | src/map/status.c | 36 | ||||
-rw-r--r-- | src/map/unit.c | 22 |
19 files changed, 586 insertions, 348 deletions
diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c index a0701ae45..f1cdec538 100644 --- a/src/map/HPMmap.c +++ b/src/map/HPMmap.c @@ -101,6 +101,18 @@ bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataType ret->HPDataSRCPtr = (void**)(&((struct instance_data *)ptr)->hdata); ret->hdatac = &((struct instance_data *)ptr)->hdatac; break; + case HPDT_MOBDB: + ret->HPDataSRCPtr = (void**)(&((struct mob_db *)ptr)->hdata); + ret->hdatac = &((struct mob_db *)ptr)->hdatac; + break; + case HPDT_MOBDATA: + ret->HPDataSRCPtr = (void**)(&((struct mob_data *)ptr)->hdata); + ret->hdatac = &((struct mob_data *)ptr)->hdatac; + break; + case HPDT_ITEMDATA: + ret->HPDataSRCPtr = (void**)(&((struct item_data *)ptr)->hdata); + ret->hdatac = &((struct item_data *)ptr)->hdatac; + break; default: return false; } diff --git a/src/map/battle.c b/src/map/battle.c index 459af3a81..f740d6518 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -401,24 +401,7 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d break; } } //end tsc check - if( src && src->type == BL_PC ){ - struct map_session_data *sd = BL_CAST(BL_PC, src); - int s; - ARR_FIND(1, 6, s, sd->charm[s] > 0); - - if( s < 5 && atk_elem == s ) - ratio += sd->charm[s] * 2; // +2% custom value - } - if( target && target->type == BL_PC ) { - struct map_session_data *tsd = BL_CAST(BL_PC, target); - int t; - - ARR_FIND(1, 6, t, tsd->charm[t] > 0); - - if( t < 5 && atk_elem == t ) - damage -= damage * ( tsd->charm[t] * 3 ) / 100;// -3% custom value - } if( ratio < 100 ) return damage - (damage * (100 - ratio) / 100); else @@ -1251,14 +1234,16 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_ def2 = status->calc_def2(target, tsc, def2, false); // status def(RE) #endif - if( sd ){ - i = sd->ignore_def[is_boss(target)?RC_BOSS:RC_NONBOSS]; + if ( sd ) { + i = sd->ignore_def[is_boss(target) ? RC_BOSS : RC_NONBOSS]; i += sd->ignore_def[tstatus->race]; - if( i ){ - if( i > 100 ) i = 100; + if ( i ) { + if ( i > 100 ) i = 100; def1 -= def1 * i / 100; def2 -= def2 * i / 100; } + if ( sd->spiritcharm[SPIRITS_TYPE_CHARM_LAND] > 0 ) // hidden from status window + def1 += 10 * def1 * sd->spiritcharm[SPIRITS_TYPE_CHARM_LAND] / 100; } if( sc && sc->data[SC_EXPIATIO] ){ @@ -1497,20 +1482,38 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block break; case NJ_KOUENKA: skillratio -= 10; + if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE] > 0 ) + skillratio += 20 * sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE]; break; case NJ_KAENSIN: skillratio -= 50; + if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE] > 0 ) + skillratio += 10 * sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE]; break; case NJ_BAKUENRYU: - skillratio += 50 * (skill_lv-1); + skillratio += 50 * (skill_lv - 1); + if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE] > 0 ) + skillratio += 15 * sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE]; break; +#ifdef RENEWAL + case NJ_HYOUSENSOU: + skillratio -= 30; + if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WATER] > 0 ) + skillratio += 5 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WATER]; +#endif case NJ_HYOUSYOURAKU: skillratio += 50 * skill_lv; + if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WATER] > 0 ) + skillratio += 25 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WATER]; break; case NJ_RAIGEKISAI: skillratio += 60 + 40 * skill_lv; + if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND] > 0 ) + skillratio += 15 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND]; break; case NJ_KAMAITACHI: + if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND] > 0 ) + skillratio += 10 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND]; case NPC_ENERGYDRAIN: skillratio += 100 * skill_lv; break; @@ -1536,6 +1539,8 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block break; case NJ_HUUJIN: skillratio += 50; + if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND] > 0 ) + skillratio += 20 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND]; break; #else case WZ_VERMILION: @@ -1757,12 +1762,12 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block skillratio += 100 * skill_lv; break; case KO_KAIHOU: - if( sd ){ - ARR_FIND(1, 6, i, sd->charm[i] > 0); - if( i < 5 ){ - skillratio += -100 + 200 * sd->charm[i]; + if ( sd ) { + ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0); + if ( i < SPIRITS_TYPE_SPHERE ) { + skillratio += -100 + 200 * sd->spiritcharm[i]; RE_LVL_DMOD(100); - pc->del_charm(sd, sd->charm[i], i); + pc->del_charm(sd, sd->spiritcharm[i], i); } } break; @@ -3366,9 +3371,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list if (s_ele == -1){ // pl=-1 : the skill takes the weapon's element s_ele = sstatus->rhw.ele; - if( sd ){ //Summoning 10 charm will endow your weapon - ARR_FIND(1, 6, i, sd->charm[i] >= 10); - if( i < 5 ) s_ele = i; + if( sd ){ //Summoning 10 spiritcharm will endow your weapon + ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] >= MAX_SPIRITCHARM); + if( i < SPIRITS_TYPE_SPHERE ) s_ele = i; } }else if (s_ele == -2) //Use status element s_ele = status_get_attack_sc_element(src,status->get_sc(src)); @@ -3411,8 +3416,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list break; case KO_KAIHOU: if( sd ){ - ARR_FIND(1, 6, i, sd->charm[i] > 0); - if( i < 5 ) + ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0); + if( i < SPIRITS_TYPE_SPHERE ) s_ele = i; } break; @@ -4257,9 +4262,9 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list { //Take weapon's element s_ele = sstatus->rhw.ele; s_ele_ = sstatus->lhw.ele; - if( sd ){ //Summoning 10 charm will endow your weapon. - ARR_FIND(1, 6, i, sd->charm[i] >= 10); - if( i < 5 ) s_ele = s_ele_ = i; + if( sd ){ //Summoning 10 spiritcharm will endow your weapon. + ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] >= MAX_SPIRITCHARM); + if( i < SPIRITS_TYPE_SPHERE ) s_ele = s_ele_ = i; } if( flag.arrow && sd && sd->bonus.arrow_ele ) s_ele = sd->bonus.arrow_ele; diff --git a/src/map/clif.c b/src/map/clif.c index 5194a637a..d7b10f2f4 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1277,11 +1277,15 @@ void clif_spiritball_single(int fd, struct map_session_data *sd) { * Kagerou/Oboro amulet spirit *------------------------------------------*/ void clif_charm_single(int fd, struct map_session_data *sd, short type) { + + if ( type <= SPIRITS_TYPE_NONE || type >= SPIRITS_TYPE_SPHERE ) + return; + WFIFOHEAD(fd, packet_len(0x08cf)); WFIFOW(fd,0)=0x08cf; WFIFOL(fd,2)=sd->bl.id; WFIFOW(fd,6)=type; - WFIFOW(fd,8)=sd->charm[type]; + WFIFOW(fd,8)=sd->spiritcharm[type]; WFIFOSET(fd, packet_len(0x08cf)); } @@ -1367,10 +1371,8 @@ bool clif_spawn(struct block_list *bl) for( i = 0; i < sd->sc_display_count; i++ ) { clif->sc_load(&sd->bl, sd->bl.id,AREA,status->IconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3); } - for(i = 1; i < 5; i++){ - if( sd->charm[i] > 0 ) - clif->charm(sd, i); - } + ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0); + clif->spiritcharm(sd, i); if (sd->status.robe) clif->refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA); } @@ -4269,10 +4271,9 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds if(dstsd->spiritball > 0) clif->spiritball_single(sd->fd, dstsd); - for(i = 1; i < 5; i++){ - if( dstsd->charm[i] > 0 ) - clif->charm_single(sd->fd, dstsd, i); - } + ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0); + clif->charm_single(sd->fd, dstsd, i); + for( i = 0; i < dstsd->sc_display_count; i++ ) { clif->sc_load(&sd->bl,dstsd->bl.id,SELF,status->IconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3); } @@ -8489,10 +8490,9 @@ void clif_refresh(struct map_session_data *sd) clif->updatestatus(sd,SP_LUK); if (sd->spiritball) clif->spiritball_single(sd->fd, sd); - for(i = 1; i < 5; i++){ - if( sd->charm[i] > 0 ) - clif->charm_single(sd->fd, sd, i); - } + ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0); + clif->charm_single(sd->fd, sd, i); + if (sd->vd.cloth_color) clif->refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); if(homun_alive(sd->hd)) @@ -9597,7 +9597,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { if (map->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNPC)) npc->touch_areanpc(sd,sd->bl.m,sd->bl.x,sd->bl.y); else - sd->areanpc_id = 0; + npc->untouch_areanpc(sd, sd->bl.m, sd->bl.x, sd->bl.y); /* it broke at some point (e.g. during a crash), so we make it visibly dead again. */ if( !sd->status.hp && !pc_isdead(sd) && status->isdead(&sd->bl) ) @@ -11450,7 +11450,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) if( skill_lv != sd->skillitemlv ) skill_lv = sd->skillitemlv; if( !(tmp&INF_SELF_SKILL) ) - pc->delinvincibletimer(sd); // Target skills thru items cancel invincibility. [Inkfish] + pc->delinvincibletimer(sd); // Target skills through items cancel invincibility. [Inkfish] unit->skilluse_id(&sd->bl, target_id, skill_id, skill_lv); return; } @@ -17458,10 +17458,13 @@ void clif_charm(struct map_session_data *sd,short type) nullpo_retv(sd); + if ( type <= SPIRITS_TYPE_NONE || type >= SPIRITS_TYPE_SPHERE ) + return; + WBUFW(buf,0)=0x08cf; WBUFL(buf,2)=sd->bl.id; WBUFW(buf,6)=type; - WBUFW(buf,8)=sd->charm[type]; + WBUFW(buf,8)=sd->spiritcharm[type]; clif->send(buf,packet_len(0x08cf),&sd->bl,AREA); } /// Move Item from or to Personal Tab (CZ_WHATSOEVER) [FE] @@ -17749,7 +17752,10 @@ void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) { void clif_maptypeproperty2(struct block_list *bl,enum send_target t) { #if PACKETVER >= 20121010 struct packet_maptypeproperty2 p; - struct map_session_data *sd = BL_CAST(BL_PC, bl); + struct map_session_data *sd = NULL; + nullpo_retv(bl); + + sd = BL_CAST(BL_PC, bl); p.PacketType = maptypeproperty2Type; p.type = 0x28; @@ -19152,7 +19158,7 @@ void clif_defaults(void) { clif->specialeffect_single = clif_specialeffect_single; clif->specialeffect_value = clif_specialeffect_value; clif->millenniumshield = clif_millenniumshield; - clif->charm = clif_charm; + clif->spiritcharm = clif_charm; clif->charm_single = clif_charm_single; clif->snap = clif_snap; clif->weather_check = clif_weather_check; diff --git a/src/map/clif.h b/src/map/clif.h index 4d11fc281..4c90a3a28 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -820,7 +820,7 @@ struct clif_interface { void (*specialeffect_single) (struct block_list* bl, int type, int fd); void (*specialeffect_value) (struct block_list* bl, int effect_id, int num, send_target target); void (*millenniumshield) (struct block_list *bl, short shields ); - void (*charm) (struct map_session_data *sd, short type); + void (*spiritcharm) (struct map_session_data *sd, short type); void (*charm_single) (int fd, struct map_session_data *sd, short type); void (*snap) ( struct block_list *bl, short x, short y ); void (*weather_check) (struct map_session_data *sd); diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 508a0ccec..19cc02d21 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -16,6 +16,7 @@ #include "mob.h" // MAX_MOB_DB #include "pc.h" // W_MUSICAL, W_WHIP #include "script.h" // item script processing +#include "../common/HPM.h" #include "../common/conf.h" #include "../common/malloc.h" #include "../common/nullpo.h" @@ -1501,6 +1502,11 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) { return item->nameid; } +void itemdb_readdb_additional_fields(int itemid, config_setting_t *it, int n, const char *source) +{ + // do nothing. plugins can do own work +} + /** * Processes one itemdb entry from the sql backend, loading and inserting it * into the item database. @@ -1676,7 +1682,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) * OnUnequipScript: <" OnUnequip Script "> * Inherit: inherit or override */ - if( !libconfig->setting_lookup_int(it, "Id", &i32) ) { + if( !itemdb->lookup_const(it, "Id", &i32) ) { ShowWarning("itemdb_readdb_libconfig_sub: Invalid or missing id in \"%s\", entry #%d, skipping.\n", source, n); return 0; } @@ -1711,57 +1717,57 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) safestrncpy(id.jname, str, sizeof(id.jname)); } - if( libconfig->setting_lookup_int(it, "Type", &i32) ) + if( itemdb->lookup_const(it, "Type", &i32) ) id.type = i32; else if( !inherit ) id.type = IT_ETC; - if( libconfig->setting_lookup_int(it, "Buy", &i32) ) + if( itemdb->lookup_const(it, "Buy", &i32) ) id.value_buy = i32; else if( !inherit ) id.value_buy = -1; - if( libconfig->setting_lookup_int(it, "Sell", &i32) ) + if( itemdb->lookup_const(it, "Sell", &i32) ) id.value_sell = i32; else if( !inherit ) id.value_sell = -1; - if( libconfig->setting_lookup_int(it, "Weight", &i32) && i32 >= 0 ) + if( itemdb->lookup_const(it, "Weight", &i32) && i32 >= 0 ) id.weight = i32; - if( libconfig->setting_lookup_int(it, "Atk", &i32) && i32 >= 0 ) + if( itemdb->lookup_const(it, "Atk", &i32) && i32 >= 0 ) id.atk = i32; - if( libconfig->setting_lookup_int(it, "Matk", &i32) && i32 >= 0 ) + if( itemdb->lookup_const(it, "Matk", &i32) && i32 >= 0 ) id.matk = i32; - if( libconfig->setting_lookup_int(it, "Def", &i32) && i32 >= 0 ) + if( itemdb->lookup_const(it, "Def", &i32) && i32 >= 0 ) id.def = i32; - if( libconfig->setting_lookup_int(it, "Range", &i32) && i32 >= 0 ) + if( itemdb->lookup_const(it, "Range", &i32) && i32 >= 0 ) id.range = i32; - if( libconfig->setting_lookup_int(it, "Slots", &i32) && i32 >= 0 ) + if( itemdb->lookup_const(it, "Slots", &i32) && i32 >= 0 ) id.slot = i32; - if( libconfig->setting_lookup_int(it, "Job", &i32) ) // This is an unsigned value, do not check for >= 0 + if( itemdb->lookup_const(it, "Job", &i32) ) // This is an unsigned value, do not check for >= 0 itemdb->jobid2mapid(id.class_base, (unsigned int)i32); else if( !inherit ) itemdb->jobid2mapid(id.class_base, UINT_MAX); - if( libconfig->setting_lookup_int(it, "Upper", &i32) && i32 >= 0 ) + if( itemdb->lookup_const(it, "Upper", &i32) && i32 >= 0 ) id.class_upper = (unsigned int)i32; else if( !inherit ) id.class_upper = ITEMUPPER_ALL; - if( libconfig->setting_lookup_int(it, "Gender", &i32) && i32 >= 0 ) + if( itemdb->lookup_const(it, "Gender", &i32) && i32 >= 0 ) id.sex = i32; else if( !inherit ) id.sex = 2; - if( libconfig->setting_lookup_int(it, "Loc", &i32) && i32 >= 0 ) + if( itemdb->lookup_const(it, "Loc", &i32) && i32 >= 0 ) id.equip = i32; - if( libconfig->setting_lookup_int(it, "WeaponLv", &i32) && i32 >= 0 ) + if( itemdb->lookup_const(it, "WeaponLv", &i32) && i32 >= 0 ) id.wlv = i32; if( (t = libconfig->setting_get_member(it, "EquipLv")) ) { @@ -1778,7 +1784,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) if( (t = libconfig->setting_get_member(it, "Refine")) ) id.flag.no_refine = libconfig->setting_get_bool(t) ? 0 : 1; - if( libconfig->setting_lookup_int(it, "View", &i32) && i32 >= 0 ) + if( itemdb->lookup_const(it, "View", &i32) && i32 >= 0 ) id.look = i32; if( (t = libconfig->setting_get_member(it, "BindOnEquip")) ) @@ -1790,7 +1796,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) if ((t = libconfig->setting_get_member(it, "KeepAfterUse"))) id.flag.keepafteruse = libconfig->setting_get_bool(t) ? 1 : 0; - if (libconfig->setting_lookup_int(it, "Delay", &i32) && i32 >= 0) + if (itemdb->lookup_const(it, "Delay", &i32) && i32 >= 0) id.delay = i32; if ( (t = libconfig->setting_get_member(it, "Trade")) ) { @@ -1892,7 +1898,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) } } - if (libconfig->setting_lookup_int(it, "Sprite", &i32) && i32 >= 0) { + if (itemdb->lookup_const(it, "Sprite", &i32) && i32 >= 0) { id.flag.available = 1; id.view_id = i32; } @@ -1909,6 +1915,24 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) return itemdb->validate_entry(&id, n, source); } +bool itemdb_lookup_const(const config_setting_t *it, const char *name, int *value) +{ + if (libconfig->setting_lookup_int(it, name, value)) + { + return true; + } + else + { + const char *str = NULL; + if (libconfig->setting_lookup_string(it, name, &str)) + { + if (*str && script->get_constant(str, value)) + return true; + } + } + return false; +} + /** * Reads from a libconfig-formatted itemdb file and inserts the found entries into the * item database, overwriting duplicate ones (i.e. item_db2 overriding item_db.) @@ -1936,6 +1960,7 @@ int itemdb_readdb_libconfig(const char *filename) { if( !nameid ) continue; + itemdb->readdb_additional_fields(nameid, it, i - 1, filename); count++; if( duplicate[nameid] ) { @@ -2054,6 +2079,14 @@ struct item_combo * itemdb_id2combo( unsigned short id ) { return itemdb->combos[id]; } +/** + * check is item have usable type + **/ +bool itemdb_is_item_usable(struct item_data *item) +{ + return item->type == IT_HEALING || item->type == IT_USABLE || item->type == IT_CASH; +} + /*========================================== * Initialize / Finalize *------------------------------------------*/ @@ -2061,6 +2094,7 @@ struct item_combo * itemdb_id2combo( unsigned short id ) { /// Destroys the item_data. void destroy_item_data(struct item_data* self, int free_self) { + int v; if( self == NULL ) return; // free scripts @@ -2072,6 +2106,14 @@ void destroy_item_data(struct item_data* self, int free_self) script->free_code(self->unequip_script); if( self->combos ) aFree(self->combos); + for (v = 0; v < self->hdatac; v++ ) { + if (self->hdata[v]->flag.free ) { + aFree(self->hdata[v]->data); + } + aFree(self->hdata[v]); + } + if (self->hdata) + aFree(self->hdata); #if defined(DEBUG) // trash item memset(self, 0xDD, sizeof(struct item_data)); @@ -2327,6 +2369,7 @@ void itemdb_defaults(void) { itemdb->read_combos = itemdb_read_combos; itemdb->gendercheck = itemdb_gendercheck; itemdb->validate_entry = itemdb_validate_entry; + itemdb->readdb_additional_fields = itemdb_readdb_additional_fields; itemdb->readdb_sql_sub = itemdb_readdb_sql_sub; itemdb->readdb_libconfig_sub = itemdb_readdb_libconfig_sub; itemdb->readdb_libconfig = itemdb_readdb_libconfig; @@ -2337,4 +2380,6 @@ void itemdb_defaults(void) { itemdb->final_sub = itemdb_final_sub; itemdb->clear = itemdb_clear; itemdb->id2combo = itemdb_id2combo; + itemdb->is_item_usable = itemdb_is_item_usable; + itemdb->lookup_const = itemdb_lookup_const; } diff --git a/src/map/itemdb.h b/src/map/itemdb.h index 5504d72d9..902e6e5e9 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -434,6 +434,10 @@ struct item_data { /* TODO add a pointer to some sort of (struct extra) and gather all the not-common vals into it to save memory */ struct item_group *group; struct item_package *package; + + /* HPM Custom Struct */ + struct HPluginData **hdata; + unsigned int hdatac; }; struct item_combo { @@ -600,6 +604,7 @@ struct itemdb_interface { void (*read_combos) (); int (*gendercheck) (struct item_data *id); int (*validate_entry) (struct item_data *entry, int n, const char *source); + void (*readdb_additional_fields) (int itemid, config_setting_t *it, int n, const char *source); int (*readdb_sql_sub) (Sql *handle, int n, const char *source); int (*readdb_libconfig_sub) (config_setting_t *it, int n, const char *source); int (*readdb_libconfig) (const char *filename); @@ -610,6 +615,8 @@ struct itemdb_interface { int (*final_sub) (DBKey key, DBData *data, va_list ap); void (*clear) (bool total); struct item_combo * (*id2combo) (unsigned short id); + bool (*is_item_usable) (struct item_data *item); + bool (*lookup_const) (const config_setting_t *it, const char *name, int *value); }; struct itemdb_interface *itemdb; diff --git a/src/map/map.c b/src/map/map.c index 2c1495f32..e5574eaf7 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -397,6 +397,7 @@ int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) { * Counts specified number of objects on given cell. * flag: * 0x1 - only count standing units + * 0x2 - don't count invinsible units * TODO: merge with bl_getall_area *------------------------------------------*/ int map_count_oncell(int16 m, int16 x, int16 y, int type, int flag) { @@ -410,29 +411,41 @@ int map_count_oncell(int16 m, int16 x, int16 y, int type, int flag) { bx = x/BLOCK_SIZE; by = y/BLOCK_SIZE; - if (type&~BL_MOB) - for( bl = map->list[m].block[bx+by*map->list[m].bxs] ; bl != NULL ; bl = bl->next ) - if(bl->x == x && bl->y == y && bl->type&type) { - if(flag&1) { + if (type&~BL_MOB) { + for (bl = map->list[m].block[bx+by*map->list[m].bxs]; bl != NULL; bl = bl->next) { + if (bl->x == x && bl->y == y && bl->type&type) { + if (flag&0x2) { + struct status_change *sc = status->get_sc(bl); + if (sc && (sc->option&OPTION_INVISIBLE)) + continue; + } + if (flag&0x1) { struct unit_data *ud = unit->bl2ud(bl); - if(!ud || ud->walktimer == INVALID_TIMER) - count++; - } else { - count++; + if (ud && ud->walktimer != INVALID_TIMER) + continue; } + count++; } + } + } - if (type&BL_MOB) - for( bl = map->list[m].block_mob[bx+by*map->list[m].bxs] ; bl != NULL ; bl = bl->next ) - if(bl->x == x && bl->y == y) { - if(flag&1) { + if (type&BL_MOB) { + for (bl = map->list[m].block_mob[bx+by*map->list[m].bxs]; bl != NULL; bl = bl->next) { + if (bl->x == x && bl->y == y) { + if (flag&0x2) { + struct status_change *sc = status->get_sc(bl); + if (sc && (sc->option&OPTION_INVISIBLE)) + continue; + } + if (flag&0x1) { struct unit_data *ud = unit->bl2ud(bl); - if(!ud || ud->walktimer == INVALID_TIMER) - count++; - } else { - count++; + if (ud && ud->walktimer != INVALID_TIMER) + continue; } + count++; } + } + } return count; } @@ -5484,7 +5497,7 @@ void map_helpscreen(bool do_exit) ShowInfo(" scripts passed through --load-script.\n"); ShowInfo(" --load-script <file> Loads an additional script (can be repeated).\n"); ShowInfo(" --load-plugin <name> Loads an additional plugin (can be repeated).\n"); - HPM->arg_help();/* display help for commands implemented thru HPM */ + HPM->arg_help(); /* display help for commands implemented through HPM */ if( do_exit ) exit(EXIT_SUCCESS); } diff --git a/src/map/map.h b/src/map/map.h index bb6e43ac3..9a5fa8ba3 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -295,6 +295,16 @@ enum { ELE_MAX }; +enum { + SPIRITS_TYPE_NONE = 0, + SPIRITS_TYPE_CHARM_WATER, + SPIRITS_TYPE_CHARM_LAND, + SPIRITS_TYPE_CHARM_FIRE, + SPIRITS_TYPE_CHARM_WIND, + SPIRITS_TYPE_SPHERE, + SPIRITS_TYPE_END +}; + enum auto_trigger_flag { ATF_SELF=0x01, ATF_TARGET=0x02, diff --git a/src/map/mob.c b/src/map/mob.c index 629653c8d..8fe3e3cef 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -34,6 +34,7 @@ #include "script.h" #include "skill.h" #include "status.h" +#include "../common/HPM.h" #include "../common/cbasetypes.h" #include "../common/db.h" #include "../common/ers.h" @@ -3550,8 +3551,7 @@ int mob_clone_delete(struct mob_data *md) const int class_ = md->class_; if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END && mob->db_data[class_]!=NULL) { - aFree(mob->db_data[class_]); - mob->db_data[class_]=NULL; + mob->destroy_mob_db(class_); //Clear references to the db md->db = mob->dummy; md->vd = NULL; @@ -3574,8 +3574,7 @@ int mob_makedummymobdb(int class_) return 1; //Using the mob->dummy data already. [Skotlex] if (class_ > 0 && class_ <= MAX_MOB_DB) { //Remove the mob data so that it uses the dummy data instead. - aFree(mob->db_data[class_]); - mob->db_data[class_] = NULL; + mob->destroy_mob_db(class_); } return 0; } @@ -3715,7 +3714,12 @@ bool mob_parse_dbrow(char** str) { mstatus->int_ = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[17])); mstatus->dex = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[18])); mstatus->luk = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[19])); - + + /* + * Disabled for renewal since difference of 0 and 1 still has an impact in the formulas + * Just in case there is a mishandled division by zero please let us know. [malufett] + */ +#ifndef RENEWAL //All status should be min 1 to prevent divisions by zero from some skills. [Skotlex] if (mstatus->str < 1) mstatus->str = 1; if (mstatus->agi < 1) mstatus->agi = 1; @@ -3723,6 +3727,7 @@ bool mob_parse_dbrow(char** str) { if (mstatus->int_< 1) mstatus->int_= 1; if (mstatus->dex < 1) mstatus->dex = 1; if (mstatus->luk < 1) mstatus->luk = 1; +#endif //Tests showed that chase range is effectively 2 cells larger than expected [Playtester] if (db->range3 > 0) @@ -4695,6 +4700,22 @@ int do_init_mob(bool minimal) { return 0; } +void mob_destroy_mob_db(int index) +{ + struct mob_db *data = mob->db_data[index]; + int v; + for (v = 0; v < data->hdatac; v++ ) { + if (data->hdata[v]->flag.free ) { + aFree(data->hdata[v]->data); + } + aFree(data->hdata[v]); + } + if (data->hdata) + aFree(data->hdata); + aFree(data); + mob->db_data[index] = NULL; +} + /*========================================== * Clean memory usage. *------------------------------------------*/ @@ -4710,8 +4731,7 @@ int do_final_mob(void) { if (mob->db_data[i] != NULL) { - aFree(mob->db_data[i]); - mob->db_data[i] = NULL; + mob->destroy_mob_db(i); } } for (i = 0; i <= MAX_MOB_CHAT; i++) @@ -4846,4 +4866,5 @@ void mob_defaults(void) { mob->readdb_itemratio = mob_readdb_itemratio; mob->load = mob_load; mob->clear_spawninfo = mob_clear_spawninfo; + mob->destroy_mob_db = mob_destroy_mob_db; } diff --git a/src/map/mob.h b/src/map/mob.h index f79b33804..9aac2c664 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -126,6 +126,10 @@ struct mob_db { int maxskill; struct mob_skill skill[MAX_MOBSKILL]; struct spawn_info spawn[10]; + + /* HPM Custom Struct */ + struct HPluginData **hdata; + unsigned int hdatac; }; struct mob_data { @@ -197,6 +201,10 @@ struct mob_data { * MvP Tombstone NPC ID **/ int tomb_nid; + + /* HPM Custom Struct */ + struct HPluginData **hdata; + unsigned int hdatac; }; @@ -369,6 +377,7 @@ struct mob_interface { bool (*readdb_itemratio) (char *str[], int columns, int current); void (*load) (bool minimal); void (*clear_spawninfo) (); + void (*destroy_mob_db) (int index); }; struct mob_interface *mob; diff --git a/src/map/npc.c b/src/map/npc.c index 8c2f61d58..8b5bbc83e 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -139,11 +139,22 @@ int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd) { char name[EVENT_NAME_LENGTH]; - if( sd->areanpc_id == nd->bl.id ) + if (sd->areanpc_id == nd->bl.id) return 0; snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script->config.ontouch2_name); - return npc->event(sd,name,2); + return npc->event(sd, name, 2); +} + +int npc_onuntouch_event(struct map_session_data *sd, struct npc_data *nd) +{ + char name[EVENT_NAME_LENGTH]; + + if (sd->areanpc_id != nd->bl.id) + return 0; + + snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script->config.onuntouch_name); + return npc->event(sd, name, 2); } /*========================================== @@ -964,6 +975,23 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y) return 0; } +/*========================================== + * Exec OnUnTouch for player if out range of area event + *------------------------------------------*/ +int npc_untouch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y) +{ + struct npc_data *nd; + nullpo_retr(1, sd); + + if (!sd->areanpc_id) + return 0; + + nd = (struct npc_data *) map->id2bl(sd->areanpc_id); + npc->onuntouch_event(sd, nd); + sd->areanpc_id = 0; + return 0; +} + // OnTouch NPC or Warp for Mobs // Return 1 if Warped int npc_touch_areanpc2(struct mob_data *md) @@ -1086,22 +1114,28 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range) { struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* bl) { struct npc_data *nd; + int distance = AREA_SIZE + 1; nullpo_retr(NULL, sd); - if(bl == NULL) return NULL; - if(bl->type != BL_NPC) return NULL; + if (bl == NULL) return NULL; + if (bl->type != BL_NPC) return NULL; nd = (TBL_NPC*)bl; - if(sd->state.using_fake_npc && sd->npc_id == bl->id) + if (sd->npc_id == bl->id) return nd; if (nd->class_<0) //Class-less npc, enable click from anywhere. return nd; - if (bl->m!=sd->bl.m || - bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 || - bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1) + if (distance > nd->area_size) + distance = nd->area_size; + + if (bl->m != sd->bl.m || + bl->x < sd->bl.x - distance || bl->x > sd->bl.x + distance || + bl->y < sd->bl.y - distance || bl->y > sd->bl.y + distance) + { return NULL; + } return nd; } @@ -2505,6 +2539,7 @@ struct npc_data* npc_create_npc(int m, int x, int y) nd->bl.m = m; nd->bl.x = x; nd->bl.y = y; + nd->area_size = AREA_SIZE + 1; return nd; } @@ -4607,6 +4642,7 @@ void npc_defaults(void) { npc->isnear = npc_isnear; npc->ontouch_event = npc_ontouch_event; npc->ontouch2_event = npc_ontouch2_event; + npc->onuntouch_event = npc_onuntouch_event; npc->enable_sub = npc_enable_sub; npc->enable = npc_enable; npc->name2id = npc_name2id; @@ -4631,6 +4667,7 @@ void npc_defaults(void) { npc->touch_areanpc_sub = npc_touch_areanpc_sub; npc->touchnext_areanpc = npc_touchnext_areanpc; npc->touch_areanpc = npc_touch_areanpc; + npc->untouch_areanpc = npc_untouch_areanpc; npc->touch_areanpc2 = npc_touch_areanpc2; npc->check_areanpc = npc_check_areanpc; npc->checknear = npc_checknear; diff --git a/src/map/npc.h b/src/map/npc.h index fba14d485..a5a2b4676 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -61,6 +61,7 @@ struct npc_data { int touching_id; int64 next_walktime; uint8 dir; + uint8 area_size; unsigned size : 2; @@ -181,6 +182,7 @@ struct npc_interface { bool (*isnear) (struct block_list *bl); int (*ontouch_event) (struct map_session_data *sd, struct npc_data *nd); int (*ontouch2_event) (struct map_session_data *sd, struct npc_data *nd); + int (*onuntouch_event) (struct map_session_data *sd, struct npc_data *nd); int (*enable_sub) (struct block_list *bl, va_list ap); int (*enable) (const char *name, int flag); struct npc_data* (*name2id) (const char *name); @@ -205,6 +207,7 @@ struct npc_interface { int (*touch_areanpc_sub) (struct block_list *bl, va_list ap); int (*touchnext_areanpc) (struct map_session_data *sd, bool leavemap); int (*touch_areanpc) (struct map_session_data *sd, int16 m, int16 x, int16 y); + int (*untouch_areanpc) (struct map_session_data *sd, int16 m, int16 x, int16 y); int (*touch_areanpc2) (struct mob_data *md); int (*check_areanpc) (int flag, int16 m, int16 x, int16 y, int16 range); struct npc_data* (*checknear) (struct map_session_data *sd, struct block_list *bl); diff --git a/src/map/pc.c b/src/map/pc.c index b22c0d74e..e39ddbff2 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4238,7 +4238,7 @@ int pc_isUseitem(struct map_session_data *sd,int n) if( item == NULL ) return 0; //Not consumable item - if( item->type != IT_HEALING && item->type != IT_USABLE && item->type != IT_CASH ) + if (!itemdb->is_item_usable(item)) return 0; if( !item->script ) //if it has no script, you can't really consume it! return 0; @@ -6990,7 +6990,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { sd->st->state = END; } - /* e.g. not killed thru pc->damage */ + /* e.g. not killed through pc->damage */ if( pc_issit(sd) ) { clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_SIT); } @@ -7004,11 +7004,10 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { //Reset ticks. sd->hp_loss.tick = sd->sp_loss.tick = sd->hp_regen.tick = sd->sp_regen.tick = 0; - if ( sd && sd->spiritball ) - pc->delspiritball(sd,sd->spiritball,0); - - for(i = 1; i < 5; i++) - pc->del_charm(sd, sd->charm[i], i); + if ( sd->spiritball ) + pc->delspiritball(sd, sd->spiritball, 0); + for ( i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++ ) + pc->del_charm(sd, sd->spiritcharm[i], i); if (src) { switch (src->type) { @@ -9797,28 +9796,28 @@ int pc_charm_timer(int tid, int64 tick, int id, intptr_t data) { if( (sd=(struct map_session_data *)map->id2sd(id)) == NULL || sd->bl.type!=BL_PC ) return 1; - ARR_FIND(1, 5, type, sd->charm[type] > 0); + ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, type, sd->spiritcharm[type] > 0); - if( sd->charm[type] <= 0 ) + if( sd->spiritcharm[type] <= 0 ) { - ShowError("pc_charm_timer: %d charm's available. (aid=%d cid=%d tid=%d)\n", sd->charm[type], sd->status.account_id, sd->status.char_id, tid); - sd->charm[type] = 0; + ShowError("pc_charm_timer: %d spiritcharm's available. (aid=%d cid=%d tid=%d)\n", sd->spiritcharm[type], sd->status.account_id, sd->status.char_id, tid); + sd->spiritcharm[type] = 0; return 0; } - ARR_FIND(0, sd->charm[type], i, sd->charm_timer[type][i] == tid); - if( i == sd->charm[type] ) + ARR_FIND(0, sd->spiritcharm[type], i, sd->charm_timer[type][i] == tid); + if( i == sd->spiritcharm[type] ) { ShowError("pc_charm_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid); return 0; } - sd->charm[type]--; - if( i != sd->charm[type] ) - memmove(sd->charm_timer[type]+i, sd->charm_timer[type]+i+1, (sd->charm[type]-i)*sizeof(int)); - sd->charm_timer[type][sd->charm[type]] = INVALID_TIMER; + sd->spiritcharm[type]--; + if( i != sd->spiritcharm[type] ) + memmove(sd->charm_timer[type]+i, sd->charm_timer[type]+i+1, (sd->spiritcharm[type]-i)*sizeof(int)); + sd->charm_timer[type][sd->spiritcharm[type]] = INVALID_TIMER; - clif->charm(sd, type); + clif->spiritcharm(sd, type); return 0; } @@ -9831,27 +9830,27 @@ int pc_add_charm(struct map_session_data *sd,int interval,int max,int type) if(max > 10) max = 10; - if(sd->charm[type] < 0) - sd->charm[type] = 0; + if(sd->spiritcharm[type] < 0) + sd->spiritcharm[type] = 0; - if( sd->charm[type] && sd->charm[type] >= max ) + if( sd->spiritcharm[type] && sd->spiritcharm[type] >= max ) { if(sd->charm_timer[type][0] != INVALID_TIMER) timer->delete(sd->charm_timer[type][0],pc->charm_timer); - sd->charm[type]--; - if( sd->charm[type] != 0 ) - memmove(sd->charm_timer[type]+0, sd->charm_timer[type]+1, (sd->charm[type])*sizeof(int)); - sd->charm_timer[type][sd->charm[type]] = INVALID_TIMER; + sd->spiritcharm[type]--; + if( sd->spiritcharm[type] != 0 ) + memmove(sd->charm_timer[type]+0, sd->charm_timer[type]+1, (sd->spiritcharm[type])*sizeof(int)); + sd->charm_timer[type][sd->spiritcharm[type]] = INVALID_TIMER; } tid = timer->add(timer->gettick()+interval, pc->charm_timer, sd->bl.id, 0); - ARR_FIND(0, sd->charm[type], i, sd->charm_timer[type][i] == INVALID_TIMER || DIFF_TICK(timer->get(tid)->tick, timer->get(sd->charm_timer[type][i])->tick) < 0); - if( i != sd->charm[type] ) - memmove(sd->charm_timer[type]+i+1, sd->charm_timer[type]+i, (sd->charm[type]-i)*sizeof(int)); + ARR_FIND(0, sd->spiritcharm[type], i, sd->charm_timer[type][i] == INVALID_TIMER || DIFF_TICK(timer->get(tid)->tick, timer->get(sd->charm_timer[type][i])->tick) < 0); + if( i != sd->spiritcharm[type] ) + memmove(sd->charm_timer[type]+i+1, sd->charm_timer[type]+i, (sd->spiritcharm[type]-i)*sizeof(int)); sd->charm_timer[type][i] = tid; - sd->charm[type]++; + sd->spiritcharm[type]++; - clif->charm(sd, type); + clif->spiritcharm(sd, type); return 0; } @@ -9861,16 +9860,16 @@ int pc_del_charm(struct map_session_data *sd,int count,int type) nullpo_ret(sd); - if( sd->charm[type] <= 0 ) { - sd->charm[type] = 0; + if( sd->spiritcharm[type] <= 0 ) { + sd->spiritcharm[type] = 0; return 0; } if( count <= 0 ) return 0; - if( count > sd->charm[type] ) - count = sd->charm[type]; - sd->charm[type] -= count; + if( count > sd->spiritcharm[type] ) + count = sd->spiritcharm[type]; + sd->spiritcharm[type] -= count; if( count > 10 ) count = 10; @@ -9885,7 +9884,7 @@ int pc_del_charm(struct map_session_data *sd,int count,int type) sd->charm_timer[type][i] = INVALID_TIMER; } - clif->charm(sd, type); + clif->spiritcharm(sd, type); return 0; } /*========================================== @@ -10587,8 +10586,8 @@ int pc_expiration_timer(int tid, int64 tick, int id, intptr_t data) { return 0; } -/* this timer exists only when a character with a expire timer > 24h is online */ -/* it loops thru online players once an hour to check whether a new < 24h is available */ +/* This timer exists only when a character with an expire timer > 24h is online */ +/* It loops through online players once an hour to check whether a new < 24h is available */ int pc_global_expiration_timer(int tid, int64 tick, int id, intptr_t data) { struct s_mapiterator* iter; struct map_session_data* sd; diff --git a/src/map/pc.h b/src/map/pc.h index 0adb25a7b..8472eb34e 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -366,8 +366,8 @@ struct map_session_data { short catch_target_class; // pet catching, stores a pet class to catch (short now) [zzo] short spiritball, spiritball_old; int spirit_timer[MAX_SPIRITBALL]; - short charm[ELE_POISON+1]; // There are actually 5 charm Fire, Ice, Wind, Earth & Poison maybe because its color violet. - int charm_timer[ELE_POISON+1][10]; + short spiritcharm[SPIRITS_TYPE_END]; + int charm_timer[SPIRITS_TYPE_END][MAX_SPIRITCHARM]; unsigned char potion_success_counter; //Potion successes in row counter unsigned char mission_count; //Stores the bounty kill count for TK_MISSION short mission_mobid; //Stores the target mob_id for TK_MISSION diff --git a/src/map/script.c b/src/map/script.c index a458bab49..031dfc21b 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -8623,49 +8623,6 @@ BUILDIN(setfalcon) return true; } -/// Returns if the player is riding. -/// -/// checkriding() -> <bool> -/// -/// @author Valaris -BUILDIN(checkriding) -{ - TBL_PC* sd; - - sd = script->rid2sd(st); - if (sd == NULL) - return true; // no player attached, report source - - if (pc_hasmount(sd)) - script_pushint(st, 1); - else - script_pushint(st, 0); - - return true; -} - -/// Sets if the player is riding. -/// <flag> defaults to 1 -/// -/// setriding <flag>; -/// setriding; -BUILDIN(setriding) -{ - int flag = 1; - TBL_PC* sd; - - sd = script->rid2sd(st); - - if (sd == NULL) - return true;// no player attached, report source - - if (script_hasdata(st,2)) - flag = script_getnum(st,2); - pc->setridingpeco(sd, flag ? true : false); - - return true; -} - enum setmount_type { SETMOUNT_TYPE_AUTODETECT = -1, SETMOUNT_TYPE_NONE = 0, @@ -8816,47 +8773,6 @@ BUILDIN(checkwug) return true; } -/// Returns if the player is wearing MADO Gear. -/// -/// checkmadogear() -> <bool> -/// -BUILDIN(checkmadogear) -{ - TBL_PC* sd; - - sd = script->rid2sd(st); - if( sd == NULL ) - return true;// no player attached, report source - - if( pc_ismadogear(sd) ) - script_pushint(st, 1); - else - script_pushint(st, 0); - - return true; -} - -/// Sets if the player is riding MADO Gear. -/// <flag> defaults to 1 -/// -/// setmadogear <flag>; -/// setmadogear; -BUILDIN(setmadogear) -{ - bool flag = true; - TBL_PC* sd; - - sd = script->rid2sd(st); - if (sd == NULL) - return true;// no player attached, report source - - if (script_hasdata(st,2)) - flag = script_getnum(st,2) ? true : false; - pc->setmadogear(sd, flag); - - return true; -} - /// Sets the save point of the player. /// /// save "<map name>",<x>,<y> @@ -10091,22 +10007,62 @@ int buildin_getareausers_sub(struct block_list *bl,va_list ap) (*users)++; return 0; } + BUILDIN(getareausers) { - const char *str; - int16 m,x0,y0,x1,y1,users=0; //doubt we can have more then 32k users on - str=script_getstr(st,2); - x0=script_getnum(st,3); - y0=script_getnum(st,4); - x1=script_getnum(st,5); - y1=script_getnum(st,6); - if( (m=map->mapname2mapid(str))< 0) { - script_pushint(st,-1); - return true; + int16 m = -1, x0, y0, x1, y1; + int users = 0; + int idx = 2; + + if (script_hasdata(st, 2) && script_isstringtype(st, 2)) { + const char *str = script_getstr(st, 2); + if ((m = map->mapname2mapid(str)) < 0) { + script_pushint(st, -1); + return true; + } + idx = 3; + } else { + TBL_PC *sd = script->rid2sd(st); + if (!sd) { + script_pushint(st, -1); + return false; + } + m = sd->bl.m; + } + + if (script_hasdata(st, idx + 3)) { + x0 = script_getnum(st, idx + 0); + y0 = script_getnum(st, idx + 1); + x1 = script_getnum(st, idx + 2); + y1 = script_getnum(st, idx + 3); + } else if (st->oid) { + struct npc_data *nd = map->id2nd(st->oid); + if (!nd) { + script_pushint(st, -1); + return true; + } + if (script_hasdata(st, idx)) { + int range = script_getnum(st, idx); + x0 = nd->bl.x - range; + y0 = nd->bl.y - range; + x1 = nd->bl.x + range; + y1 = nd->bl.y + range; + } else if (nd->u.scr.xs != -1 && nd->u.scr.ys != -1) { + x0 = nd->bl.x - nd->u.scr.xs; + y0 = nd->bl.y - nd->u.scr.ys; + x1 = nd->bl.x + nd->u.scr.xs; + y1 = nd->bl.y + nd->u.scr.ys; + } else { + script_pushint(st, -1); + return true; + } + } else { + script_pushint(st, -1); + return false; } map->foreachinarea(script->buildin_getareausers_sub, - m,x0,y0,x1,y1,BL_PC,&users); - script_pushint(st,users); + m, x0, y0, x1, y1, BL_PC, &users); + script_pushint(st, users); return true; } @@ -10683,27 +10639,51 @@ BUILDIN(changebase) { return true; } +static TBL_PC *prepareChangeSex(struct script_state* st) +{ + int i; + TBL_PC *sd = script->rid2sd(st); + + if (sd == NULL) + return NULL; + + pc->resetskill(sd, 4); + // to avoid any problem with equipment and invalid sex, equipment is unequiped. + for (i=0; i<EQI_MAX; i++) + if (sd->equip_index[i] >= 0) pc->unequipitem(sd, sd->equip_index[i], 3); + return sd; +} + /*========================================== * Unequip all item and request for a changesex to char-serv *------------------------------------------*/ BUILDIN(changesex) { - int i; - TBL_PC *sd = NULL; - sd = script->rid2sd(st); - - if( sd == NULL ) + TBL_PC *sd = prepareChangeSex(st); + if (sd == NULL) return false; - - pc->resetskill(sd,4); - // to avoid any problem with equipment and invalid sex, equipment is unequiped. - for( i=0; i<EQI_MAX; i++ ) - if( sd->equip_index[i] >= 0 ) pc->unequipitem(sd, sd->equip_index[i], 3); chrif->changesex(sd); return true; } /*========================================== + * Unequip all items and change character sex [4144] + *------------------------------------------*/ +BUILDIN(changecharsex) +{ + TBL_PC *sd = prepareChangeSex(st); + if (sd == NULL) + return false; + if (sd->status.sex == 99) + sd->status.sex = 0; + sd->status.sex = sd->status.sex ? 0 : 1; + chrif->save(sd, 0); + if (sd->fd) + clif->authfail_fd(sd->fd, 15); + return true; +} + +/*========================================== * Works like 'announce' but outputs in the common chat window *------------------------------------------*/ BUILDIN(globalmes) { @@ -13311,6 +13291,112 @@ BUILDIN(npcstop) { return true; } +// set click npc distance [4144] +BUILDIN(setnpcdistance) { + struct npc_data *nd = (struct npc_data *) map->id2bl (st->oid); + if (!nd) + return false; + + nd->area_size = script_getnum(st, 2); + + return true; +} + +// return current npc direction [4144] +BUILDIN(getnpcdir) +{ + struct npc_data *nd = 0; + + if (script_hasdata(st, 2)) + { + nd = npc->name2id (script_getstr(st, 2)); + } + if (!nd && !st->oid) + { + script_pushint(st, -1); + return true; + } + + if (!nd) + nd = (struct npc_data *) map->id2bl (st->oid); + + if (!nd) + { + script_pushint(st, -1); + return true; + } + + script_pushint(st, (int)nd->dir); + + return true; +} + +// set npc direction [4144] +BUILDIN(setnpcdir) +{ + int newdir; + struct npc_data *nd = 0; + + if (script_hasdata(st, 3)) + { + nd = npc->name2id (script_getstr(st, 2)); + newdir = script_getnum(st, 3); + } + else if (script_hasdata(st, 2)) + { + if (!st->oid) + return false; + + nd = (struct npc_data *) map->id2bl (st->oid); + newdir = script_getnum(st, 2); + } + if (!nd) + return false; + + if (newdir < 0) + newdir = 0; + else if (newdir > 7) + newdir = 7; + + nd->dir = newdir; + if (nd->ud) + nd->ud->dir = newdir; + + clif->clearunit_area(&nd->bl, CLR_OUTSIGHT); + clif->spawn(&nd->bl); + + return true; +} + +// return npc class [4144] +BUILDIN(getnpcclass) +{ + struct npc_data *nd = 0; + + if (script_hasdata(st, 2)) + { + nd = npc->name2id (script_getstr(st, 2)); + } + if (!nd && !st->oid) + { + script_pushint(st, -1); + return false; + } + + if (!nd) + nd = (struct npc_data *) map->id2bl(st->oid); + + if (!nd) + { + script_pushint(st, -1); + return false; + } + + script_pushint(st, (int)nd->class_); + + return true; +} + /*========================================== * getlook char info. getlook(arg) @@ -17497,58 +17583,6 @@ BUILDIN(makerune) { sd->itemid = script_getnum(st,2); return true; } -/** - * checkdragon() returns 1 if mounting a dragon or 0 otherwise. - **/ -BUILDIN(checkdragon) { - TBL_PC* sd; - if( (sd = script->rid2sd(st)) == NULL ) - return true; - if( pc_isridingdragon(sd) ) - script_pushint(st,1); - else - script_pushint(st,0); - return true; -} -/** - * setdragon({optional Color}) returns 1 on success or 0 otherwise - * - Toggles the dragon on a RK if he can mount; - * @param Color - when not provided uses the green dragon; - * - 1 : Green Dragon - * - 2 : Brown Dragon - * - 3 : Gray Dragon - * - 4 : Blue Dragon - * - 5 : Red Dragon - **/ -BUILDIN(setdragon) { - TBL_PC* sd; - int color = script_hasdata(st,2) ? script_getnum(st,2) : 0; - - if( (sd = script->rid2sd(st)) == NULL ) - return true; - if( !pc->checkskill(sd,RK_DRAGONTRAINING) || (sd->class_&MAPID_THIRDMASK) != MAPID_RUNE_KNIGHT ) - script_pushint(st,0);//Doesn't have the skill or it's not a Rune Knight - else if ( pc_isridingdragon(sd) ) {//Is mounted; release - pc->setoption(sd, sd->sc.option&~OPTION_DRAGON); - script_pushint(st,1); - } else {//Not mounted; Mount now. - unsigned int option = OPTION_DRAGON1; - if( color ) { - option = ( color == 1 ? OPTION_DRAGON1 : - color == 2 ? OPTION_DRAGON2 : - color == 3 ? OPTION_DRAGON3 : - color == 4 ? OPTION_DRAGON4 : - color == 5 ? OPTION_DRAGON5 : 0); - if( !option ) { - ShowWarning("script_setdragon: Unknown Color %d used; changing to green (1)\n",color); - option = OPTION_DRAGON1; - } - } - pc->setoption(sd, sd->sc.option|option); - script_pushint(st,1); - } - return true; -} /** * hascashmount() returns 1 if mounting a cash mount or 0 otherwise @@ -19232,13 +19266,9 @@ void script_parse_builtin(void) { BUILDIN_DEF(checkcart,""), BUILDIN_DEF(setfalcon,"?"), BUILDIN_DEF(checkfalcon,""), - BUILDIN_DEF_DEPRECATED(setriding,"?"), // Deprecated 2014-10-30 [Haru] - BUILDIN_DEF_DEPRECATED(checkriding,""), // Deprecated 2014-10-30 [Haru] BUILDIN_DEF(setmount,"?"), BUILDIN_DEF(checkmount,""), BUILDIN_DEF(checkwug,""), - BUILDIN_DEF_DEPRECATED(checkmadogear,""), // Deprecated 2014-10-30 [Haru] - BUILDIN_DEF_DEPRECATED(setmadogear,"?"), // Deprecated 2014-10-30 [Haru] BUILDIN_DEF2_DEPRECATED(savepoint,"save","sii"), // Deprecated 2014-11-02 [Haru] BUILDIN_DEF(savepoint,"sii"), BUILDIN_DEF(gettimetick,"i"), @@ -19275,7 +19305,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(getusers,"i"), BUILDIN_DEF(getmapguildusers,"si"), BUILDIN_DEF(getmapusers,"s"), - BUILDIN_DEF(getareausers,"siiii"), + BUILDIN_DEF(getareausers,"*"), BUILDIN_DEF(getareadropitem,"siiiiv"), BUILDIN_DEF(enablenpc,"s"), BUILDIN_DEF(disablenpc,"s"), @@ -19296,6 +19326,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(skillpointcount,""), BUILDIN_DEF(changebase,"i?"), BUILDIN_DEF(changesex,""), + BUILDIN_DEF(changecharsex,""), // [4144] BUILDIN_DEF(waitingroom,"si?????"), BUILDIN_DEF(delwaitingroom,"?"), BUILDIN_DEF2(waitingroomkickall,"kickwaitingroomall","?"), @@ -19378,6 +19409,10 @@ void script_parse_builtin(void) { BUILDIN_DEF(npcspeed,"i"), // [Valaris] BUILDIN_DEF(npcwalkto,"ii"), // [Valaris] BUILDIN_DEF(npcstop,""), // [Valaris] + BUILDIN_DEF(setnpcdistance,"i"), // [4144] + BUILDIN_DEF(getnpcdir,"?"), // [4144] + BUILDIN_DEF(setnpcdir,"*"), // [4144] + BUILDIN_DEF(getnpcclass,"?"), // [4144] BUILDIN_DEF(getmapxy,"rrri?"), //by Lorky [Lupus] BUILDIN_DEF(checkoption1,"i"), BUILDIN_DEF(checkoption2,"i"), @@ -19562,8 +19597,6 @@ void script_parse_builtin(void) { * 3rd-related **/ BUILDIN_DEF(makerune,"i"), - BUILDIN_DEF_DEPRECATED(checkdragon,""), // Deprecated 2014-10-30 [Haru] - BUILDIN_DEF_DEPRECATED(setdragon,"?"), // Deprecated 2014-10-30 [Haru] BUILDIN_DEF(hascashmount,""),//[Ind] BUILDIN_DEF(setcashmount,""),//[Ind] BUILDIN_DEF(checkre,"i"), @@ -19970,8 +20003,9 @@ void script_defaults(void) { script->config.loadmap_event_name = "OnPCLoadMapEvent"; script->config.baselvup_event_name = "OnPCBaseLvUpEvent"; script->config.joblvup_event_name = "OnPCJobLvUpEvent"; - script->config.ontouch_name = "OnTouch_";//ontouch_name (runs on first visible char to enter area, picks another char if the first char leaves) - script->config.ontouch2_name = "OnTouch";//ontouch2_name (run whenever a char walks into the OnTouch area) + script->config.ontouch_name = "OnTouch_"; //ontouch_name (runs on first visible char to enter area, picks another char if the first char leaves) + script->config.ontouch2_name = "OnTouch"; //ontouch2_name (run whenever a char walks into the OnTouch area) + script->config.onuntouch_name = "OnUnTouch"; //onuntouch_name (run whenever a char walks from the OnTouch area) // for ENABLE_CASE_CHECK script->calc_hash_ci = calc_hash_ci; diff --git a/src/map/script.h b/src/map/script.h index e28abf970..548c0f261 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -343,6 +343,7 @@ struct Script_Config { const char* ontouch_name; const char* ontouch2_name; + const char* onuntouch_name; }; /** diff --git a/src/map/skill.c b/src/map/skill.c index c2022b0a6..6bfecf46f 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -6041,18 +6041,23 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case MO_ABSORBSPIRITS: { int sp = 0; - if (dstsd && dstsd->spiritball - && (sd == dstsd || map_flag_vs(src->m) || (sd->duel_group && sd->duel_group == dstsd->duel_group)) - && ((dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK)!=MAPID_REBELLION) - ) { + int i; + if ( dstsd && dstsd->spiritball + && (sd == dstsd || map_flag_vs(src->m) || (sd->duel_group && sd->duel_group == dstsd->duel_group)) + && ((dstsd->class_&MAPID_BASEMASK) != MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK) != MAPID_REBELLION) + ) { // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen] sp = dstsd->spiritball * 7; - pc->delspiritball(dstsd,dstsd->spiritball,0); - } else if (dstmd && !(tstatus->mode&MD_BOSS) && rnd() % 100 < 20) { + pc->delspiritball(dstsd, dstsd->spiritball, 0); + } else if ( dstmd && !(tstatus->mode&MD_BOSS) && rnd() % 100 < 20 ) { // check if target is a monster and not a Boss, for the 20% chance to absorb 2 SP per monster's level [Reddozen] sp = 2 * dstmd->level; mob->target(dstmd,src,0); } + if ( dstsd ) { + for (i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++) + pc->del_charm(dstsd, dstsd->spiritcharm[i], i); + } if (sp) status->heal(src, 0, sp, 3); clif->skill_nodamage(src,bl,skill_id,skill_lv,sp?1:0); } @@ -8917,6 +8922,11 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin pc->delspiritball(dstsd, dstsd->spiritball, 0); status_percent_heal(src, 0, sp); } + if ( dstsd ) { + int i; + for (i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++) + pc->del_charm(dstsd, dstsd->spiritcharm[i], i); + } clif->skill_nodamage(src, bl, skill_id, skill_lv, sp ? 1:0); } else { clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); @@ -9455,10 +9465,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin int i; int ttype = skill->get_ele(skill_id, skill_lv); clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); - ARR_FIND(1, 6, i, sd->charm[i] > 0 && ttype != i); - if( i < 6 ) - pc->del_charm(sd, sd->charm[i], i); // replace with a new one. - pc->add_charm(sd, skill->get_time(skill_id, skill_lv), 10, ttype); + ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0 && ttype != i); + if( i < SPIRITS_TYPE_SPHERE ) + pc->del_charm(sd, sd->spiritcharm[i], i); // replace with a new one. + pc->add_charm(sd, skill->get_time(skill_id, skill_lv), MAX_SPIRITCHARM, ttype); } break; @@ -10107,11 +10117,13 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui } case MG_SAFETYWALL: - if (map->foreachincell(skill->cell_overlap,src->m,x,y,BL_SKILL)) { - skill->unitsetting(src,skill_id,skill_lv,x,y,0); + { + int alive = 1; + if ( map->foreachincell(skill->cell_overlap, src->m, x, y, BL_SKILL, skill_id, &alive, src) ) { + skill->unitsetting(src, skill_id, skill_lv, x, y, 0); return 0; // Don't consume gems if cast on LP } - + } case MG_FIREWALL: case MG_THUNDERSTORM: @@ -11190,13 +11202,13 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ break; case KO_ZENKAI: if( sd ){ - ARR_FIND(1, 6, i, sd->charm[i] > 0); - if( i < 5 ){ - val1 = sd->charm[i]; // no. of aura + ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0); + if( i < SPIRITS_TYPE_SPHERE ){ + val1 = sd->spiritcharm[i]; // no. of aura val2 = i; // aura type limit += val1 * 1000; subunt = i - 1; - pc->del_charm(sd, sd->charm[i], i); + pc->del_charm(sd, sd->spiritcharm[i], i); } } break; @@ -13495,7 +13507,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case KO_DOHU_KOUKAI: { int ttype = skill->get_ele(skill_id, skill_lv); - if( sd->charm[ttype] >= 10 ){ + if( sd->spiritcharm[ttype] >= MAX_SPIRITCHARM ){ clif->skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON, 0); return 0; } @@ -13505,8 +13517,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case KO_ZENKAI: { int i; - ARR_FIND(1, 6, i, sd->charm[i] > 0); // FIXME: 4 or 6? - if( i > 4 ) { + ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0); + if( i >= SPIRITS_TYPE_SPHERE ) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0); return 0; } diff --git a/src/map/status.c b/src/map/status.c index 6d4b8d5fa..d3fa25aaa 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1138,7 +1138,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, struct status_change *sc; int hp,sp; - /* here onwards we consider it a 32-type, the client does not support higher and from here onwards the value doesn't get thru percentage modifiers */ + /* From here onwards, we consider it a 32-type as the client does not support higher and the value doesn't get through percentage modifiers */ hp = (int)cap_value(in_hp,INT_MIN,INT_MAX); sp = (int)cap_value(in_sp,INT_MIN,INT_MAX); @@ -1371,7 +1371,7 @@ int status_heal(struct block_list *bl,int64 in_hp,int64 in_sp, int flag) { if (st == &status->dummy || !st->hp) return 0; - /* here onwards we consider it a 32-type, the client does not support higher and from here onwards the value doesn't get thru percentage modifiers */ + /* From here onwards, we consider it a 32-type as the client does not support higher and the value doesn't get through percentage modifiers */ hp = (int)cap_value(in_hp,INT_MIN,INT_MAX); sp = (int)cap_value(in_sp,INT_MIN,INT_MAX); @@ -6959,7 +6959,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t return 0; //Overthrust can't take effect if under Max Overthrust. [Skotlex] case SC_OVERTHRUSTMAX: if( sc->option&OPTION_MADOGEAR ) - return 0;//Overthrust and Overthrust Max cannot be used on Mado Gear [Ind] + return 0; //Overthrust and Overthrust Max cannot be used on Mado Gear [Ind] break; case SC_ADRENALINE: if(sd && !pc_check_weapontype(sd,skill->get_weapontype(BS_ADRENALINE))) @@ -6995,7 +6995,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_CARTBOOST: case SC_ASSNCROS: if(sc->option&OPTION_MADOGEAR) - return 0;//Mado is immune to wind walk, cart boost, etc (others above) [Ind] + return 0; //Mado is immune to wind walk, cart boost, etc (others above) [Ind] case SC_INC_AGI: if (sc->data[SC_QUAGMIRE]) return 0; @@ -8635,7 +8635,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC__ENERVATION: val2 = 20 + 10 * val1; // ATK Reduction - if( sd ) pc->delspiritball(sd,sd->spiritball,0); + if ( sd ) { + int i; + pc->delspiritball(sd, sd->spiritball, 0); + for (i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++) + pc->del_charm(sd, sd->spiritcharm[i], i); + } break; case SC__GROOMY: val2 = 20 + 10 * val1; //ASPD. Need to confirm if Movement Speed reduction is the same. [Jobbie] @@ -10466,8 +10471,12 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if(opt_flag&4) //Out of hiding, invoke on place. skill->unit_move(bl,timer->gettick(),1); - if(opt_flag&2 && sd && map->getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) - npc->touch_areanpc(sd,bl->m,bl->x,bl->y); //Trigger on-touch event. + if (opt_flag & 2 && sd) { + if (map->getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) + npc->touch_areanpc(sd,bl->m,bl->x,bl->y); //Trigger on-touch event. + else + npc->untouch_areanpc(sd, bl->m, bl->x, bl->y); + } ers_free(status->data_ers, sce); return 1; @@ -11469,9 +11478,13 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl short index = sd->equip_index[EQI_HAND_R], refine; if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON && (refine = sd->status.inventory[index].refine) < 16 && refine ) { - int r = (rnd() % 100) % ((status->refine_info[watk->wlv].randombonus_max[refine + (4 - watk->wlv)] / 100)) + 1; - max += r / 10; + int r = status->refine_info[watk->wlv].randombonus_max[refine + (4 - watk->wlv)] / 100; + if ( r ) + max += (rnd() % 100) % r + 1; } + + if ( sd->spiritcharm[SPIRITS_TYPE_CHARM_LAND] > 0 ) + max += 10 * max * sd->spiritcharm[SPIRITS_TYPE_CHARM_LAND] / 100; } max = status->calc_watk(bl, sc, max, false); @@ -11560,8 +11573,9 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m short index = sd->equip_index[EQI_HAND_R], refine; if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON && (refine = sd->status.inventory[index].refine) < 16 && refine ) { - int r = (rnd() % 100) % ((status->refine_info[sd->inventory_data[index]->wlv].randombonus_max[refine + (4 - sd->inventory_data[index]->wlv)] / 100)) + 1; - st->matk_max += r / 10; + int r = status->refine_info[sd->inventory_data[index]->wlv].randombonus_max[refine + (4 - sd->inventory_data[index]->wlv)] / 100; + if ( r ) + st->matk_max += (rnd() % 100) % r + 1; } } #endif diff --git a/src/map/unit.c b/src/map/unit.c index 64885541f..a5bd282a9 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -309,7 +309,7 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { if (bl->prev == NULL) //Script could have warped char, abort remaining of the function. return 0; } else - sd->areanpc_id=0; + npc->untouch_areanpc(sd, bl->m, x, y); if( sd->md ) { // mercenary should be warped after being 3 seconds too far from the master [greenbox] if( !check_distance_bl(&sd->bl, &sd->md->bl, MAX_MER_DISTANCE) ) { @@ -685,7 +685,7 @@ bool unit_run( struct block_list *bl, struct map_session_data *sd, enum sc_type break; //if sprinting and there's a PC/Mob/NPC, block the path [Kevin] - if( map->count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC, 0) ) + if ( map->count_oncell(bl->m, to_x + dir_x, to_y + dir_y, BL_PC | BL_MOB | BL_NPC, 0x2) ) break; to_x += dir_x; @@ -767,7 +767,7 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool if (bl->prev == NULL) //Script could have warped char, abort remaining of the function. return 0; } else - sd->areanpc_id=0; + npc->untouch_areanpc(sd, bl->m, bl->x, bl->y); if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 ) { // Check if pet needs to be teleported. [Skotlex] @@ -867,7 +867,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag) if(map->getcell(bl->m, bl->x, bl->y, CELL_CHKNPC)) { npc->touch_areanpc(sd, bl->m, bl->x, bl->y); } else { - sd->areanpc_id = 0; + npc->untouch_areanpc(sd, bl->m, bl->x, bl->y);; } } } @@ -2619,8 +2619,8 @@ int unit_free(struct block_list *bl, clr_type clrtype) { pc->cleareventtimer(sd); pc->inventory_rental_clear(sd); pc->delspiritball(sd,sd->spiritball,1); - for(i = 1; i < 5; i++) - pc->del_charm(sd, sd->charm[i], i); + for(i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++) + pc->del_charm(sd, sd->spiritcharm[i], i); if( sd->st && sd->st->state != RUN ) {// free attached scripts that are waiting script->free_state(sd->st); @@ -2720,6 +2720,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) { } case BL_MOB: { + unsigned int k; struct mob_data *md = (struct mob_data*)bl; if( md->spawn_timer != INVALID_TIMER ) { @@ -2774,6 +2775,15 @@ int unit_free(struct block_list *bl, clr_type clrtype) { mob->clone_delete(md); if( md->tomb_nid ) mob->mvptomb_destroy(md); + + for (k = 0; k < md->hdatac; k++) { + if( md->hdata[k]->flag.free ) { + aFree(md->hdata[k]->data); + } + aFree(md->hdata[k]); + } + if (md->hdata) + aFree(md->hdata); break; } case BL_HOM: |