summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/HPMmap.c12
-rw-r--r--src/map/battle.c75
-rw-r--r--src/map/clif.c42
-rw-r--r--src/map/clif.h2
-rw-r--r--src/map/itemdb.c81
-rw-r--r--src/map/itemdb.h7
-rw-r--r--src/map/map.c47
-rw-r--r--src/map/map.h10
-rw-r--r--src/map/mob.c35
-rw-r--r--src/map/mob.h9
-rw-r--r--src/map/npc.c53
-rw-r--r--src/map/npc.h3
-rw-r--r--src/map/pc.c75
-rw-r--r--src/map/pc.h4
-rw-r--r--src/map/script.c368
-rw-r--r--src/map/script.h1
-rw-r--r--src/map/skill.c52
-rw-r--r--src/map/status.c36
-rw-r--r--src/map/unit.c22
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: