summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/map/battle.c41
-rw-r--r--src/map/clif.c44
-rw-r--r--src/map/clif.h2
-rw-r--r--src/map/map.c1
-rw-r--r--src/map/mob.h5
-rw-r--r--src/map/pc.c112
-rw-r--r--src/map/pc.h5
-rw-r--r--src/map/skill.c96
-rw-r--r--src/map/status.c65
-rw-r--r--src/map/unit.c3
10 files changed, 353 insertions, 21 deletions
diff --git a/src/map/battle.c b/src/map/battle.c
index 34946aec6..a4f5985bd 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -351,6 +351,19 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag
status_change_end(target, SC_CRYSTALIZE, INVALID_TIMER);
}
}
+ if( src->type == BL_PC || target->type == BL_PC ){
+ struct map_session_data *sd = BL_CAST(BL_PC, src);
+ struct map_session_data *tsd = BL_CAST(BL_PC, target);
+ int s, t;
+
+ ARR_FIND(1, 6, s, sd->talisman[s] > 0);
+ ARR_FIND(1, 6, t, tsd->talisman[t] > 0);
+
+ if( s < 5 && atk_elem == s )
+ ratio += sd->talisman[s] * 2; // +2% custom value
+ if( t < 5 && atk_elem == t )
+ damage -= damage * tsd->talisman[t] * 3 / 100; // -3% custom value
+ }
return damage*ratio/100;
}
@@ -705,6 +718,10 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
status_change_end(bl, SC_KYRIE, INVALID_TIMER);
}
+ if( sc->data[SC_MEIKYOUSISUI] && rand()%100 < 40 ) // custom value
+ damage = 0;
+
+
if (!damage) return 0;
if( (sce = sc->data[SC_LIGHTNINGWALK]) && flag&BF_LONG && rnd()%100 < sce->val1 ) {
@@ -1398,6 +1415,10 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
{ //Take weapon's element
s_ele = sstatus->rhw.ele;
s_ele_ = sstatus->lhw.ele;
+ if( sd ){ //Summoning 10 talisman will endow your weapon.
+ ARR_FIND(1, 6, i, sd->talisman[i] >= 10);
+ if( i < 5) s_ele = s_ele_ = i;
+ }
if( flag.arrow && sd && sd->bonus.arrow_ele )
s_ele = sd->bonus.arrow_ele;
if( battle_config.attack_attr_none&src->type )
@@ -3310,9 +3331,13 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
//Initialize variables that will be used afterwards
s_ele = skill_get_ele(skill_num, skill_lv);
- if (s_ele == -1) // pl=-1 : the skill takes the weapon's element
+ if (s_ele == -1){ // pl=-1 : the skill takes the weapon's element
s_ele = sstatus->rhw.ele;
- else if (s_ele == -2) //Use status element
+ if( sd ){ //Summoning 10 talisman will endow your weapon
+ ARR_FIND(1, 6, i, sd->talisman[i] > 0);
+ if( i < 5) s_ele = i;
+ }
+ }else if (s_ele == -2) //Use status element
s_ele = status_get_attack_sc_element(src,status_get_sc(src));
else if( s_ele == -3 ) //Use random element
s_ele = rnd()%ELE_MAX;
@@ -4173,6 +4198,9 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage -= totaldef;
}
break;
+ case KO_MAKIBISHI:
+ md.damage = 20 * skill_lv;
+ break;
}
if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets
@@ -4928,9 +4956,9 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
}
break;
case BL_MOB:
- if((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres
+ if(((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres
(((TBL_MOB*)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras
- s_bl->type == BL_PC && src->type != BL_MOB)
+ s_bl->type == BL_PC && src->type != BL_MOB) || ((TBL_MOB*)target)->special_state.ai == 4) //Zanzoe
{ //Targettable by players
state |= BCT_ENEMY;
strip_enemy = 0;
@@ -5094,8 +5122,9 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
return 0; // Disable guardians/emperium owned by Guilds on non-woe times.
if( !md->special_state.ai )
- { //Normal mobs.
- if( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai )
+ { //Normal mobs
+ if( (target->type == BL_MOB && t_bl->type == BL_PC && ((TBL_MOB*)target)->special_state.ai < 4) ||
+ ( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai ) )
state |= BCT_PARTY; //Normal mobs with no ai are friends.
else
state |= BCT_ENEMY; //However, all else are enemies.
diff --git a/src/map/clif.c b/src/map/clif.c
index 25b53686a..13d4ebe8f 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -1255,6 +1255,18 @@ static void clif_spiritball_single(int fd, struct map_session_data *sd)
WFIFOSET(fd, packet_len(0x1e1));
}
+/*==========================================
+ * Kagerou/Oboro amulet spirit
+ *------------------------------------------*/
+static void clif_talisman_single(int fd, struct map_session_data *sd, short type)
+{
+ WFIFOHEAD(fd, packet_len(0x08cf));
+ WFIFOW(fd,0)=0x08cf;
+ WFIFOL(fd,2)=sd->bl.id;
+ WFIFOW(fd,6)=type;
+ WFIFOW(fd,8)=sd->talisman[type];
+ WFIFOSET(fd, packet_len(0x08cf));
+}
/*==========================================
* Run when player changes map / refreshes
@@ -1348,6 +1360,7 @@ int clif_spawn(struct block_list *bl)
case BL_PC:
{
TBL_PC *sd = ((TBL_PC*)bl);
+ int i;
if (sd->spiritball > 0)
clif_spiritball(sd);
if(sd->state.size==2) // tiny/big players [Valaris]
@@ -1360,6 +1373,10 @@ int clif_spawn(struct block_list *bl)
//New Mounts are not complaint to the original method, so we gotta tell this guy that he is mounting.
clif_status_load_notick(&sd->bl,SI_ALL_RIDING,2,1,0,0);
}
+ for(i = 1; i < 5; i++){
+ if( sd->talisman[i] > 0 )
+ clif_talisman(sd, i);
+ }
#ifdef NEW_CARTS
if( sd->sc.data[SC_PUSH_CART] )
clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2, sd->sc.data[SC_PUSH_CART]->val1, 0, 0);
@@ -4031,6 +4048,10 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d
if(dstsd->spiritball > 0)
clif_spiritball_single(sd->fd, dstsd);
+ for(i = 1; i < 5; i++){
+ if( dstsd->talisman[i] > 0 )
+ clif_talisman_single(sd->fd, dstsd, i);
+ }
if( dstsd->sc.option&OPTION_MOUNTING ) {
//New Mounts are not complaint to the original method, so we gotta tell this guy that I'm mounting.
clif_status_load_single(sd->fd,dstsd->bl.id,SI_ALL_RIDING,2,1,0,0);
@@ -8195,6 +8216,7 @@ void clif_message(struct block_list* bl, const char* msg)
// refresh the client's screen, getting rid of any effects
void clif_refresh(struct map_session_data *sd)
{
+ int i;
nullpo_retv(sd);
clif_changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y);
@@ -8213,6 +8235,10 @@ 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->talisman[i] > 0 )
+ clif_talisman_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(merc_is_hom_active(sd->hd))
@@ -16123,7 +16149,21 @@ void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) {
skill_select_menu(sd,RFIFOL(fd,2),RFIFOW(fd,6));
clif_menuskill_clear(sd);
}
+/*==========================================
+ * Kagerou/Oboro amulet spirit
+ *------------------------------------------*/
+void clif_talisman(struct map_session_data *sd,short type)
+{
+ unsigned char buf[8];
+
+ nullpo_retv(sd);
+ WBUFW(buf,0)=0x08cf;
+ WBUFL(buf,2)=sd->bl.id;
+ WBUFW(buf,6)=type;
+ WBUFW(buf,8)=sd->talisman[type];
+ clif_send(buf,packet_len(0x08cf),&sd->bl,AREA);
+}
/// Move Item from or to Personal Tab (CZ_WHATSOEVER) [FE]
/// 0907 <index>.W
///
@@ -16549,7 +16589,7 @@ static int packetdb_readdb(void)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
//#0x08C0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -16557,7 +16597,7 @@ static int packetdb_readdb(void)
0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
struct {
void (*func)(int, struct map_session_data *);
diff --git a/src/map/clif.h b/src/map/clif.h
index b6993a46b..ef404cee5 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -736,6 +736,8 @@ int clif_skill_itemlistwindow( struct map_session_data *sd, int skill_id, int sk
void clif_elemental_info(struct map_session_data *sd);
void clif_elemental_updatestatus(struct map_session_data *sd, int type);
+void clif_talisman(struct map_session_data *sd, short type);
+
/**
* Color Table
**/
diff --git a/src/map/map.c b/src/map/map.c
index da2826c26..2239a2f23 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -1707,6 +1707,7 @@ int map_quit(struct map_session_data *sd) {
status_change_end(&sd->bl, SC_ENDURE, INVALID_TIMER); //No need to save infinite endure.
status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER);
status_change_end(&sd->bl, SC_WEIGHT90, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_KYOUGAKU, INVALID_TIMER);
if (battle_config.debuff_on_logout&1) {
status_change_end(&sd->bl, SC_ORCISH, INVALID_TIMER);
status_change_end(&sd->bl, SC_STRIPWEAPON, INVALID_TIMER);
diff --git a/src/map/mob.h b/src/map/mob.h
index 4a77a3abb..adbf65d5c 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -36,7 +36,7 @@
#define MOB_CLONE_END MAX_MOB_DB
//Used to determine default enemy type of mobs (for use in eachinrange calls)
-#define DEFAULT_ENEMY_TYPE(md) (md->special_state.ai?BL_CHAR:BL_PC|BL_HOM|BL_MER)
+#define DEFAULT_ENEMY_TYPE(md) (md->special_state.ai?BL_CHAR:BL_MOB|BL_PC|BL_HOM|BL_MER)
//Externals for the status effects. [Epoque]
extern const int mob_manuk[8];
@@ -121,11 +121,12 @@ struct mob_data {
char name[NAME_LENGTH];
struct {
unsigned int size : 2; //Small/Big monsters.
- unsigned int ai : 2; //Special ai for summoned monsters.
+ unsigned int ai : 3; //Special ai for summoned monsters.
//0: Normal mob.
//1: Standard summon, attacks mobs.
//2: Alchemist Marine Sphere
//3: Alchemist Summon Flora
+ //4: Summon Zanzou
unsigned int clone : 1;/* is clone? 1:0 */
} special_state; //Special mob information that does not needs to be zero'ed on mob respawn.
struct {
diff --git a/src/map/pc.c b/src/map/pc.c
index 0f04cc017..d7cfe66e1 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -878,6 +878,8 @@ int pc_isequip(struct map_session_data *sd,int n)
return 0;
if(item->equip & EQP_ACC && sd->sc.data[SC__STRIPACCESSORY])
return 0;
+ if(item->equip && sd->sc.data[SC_KYOUGAKU])
+ return 0;
if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SUPERNOVICE) {
//Spirit of Super Novice equip bonuses. [Skotlex]
@@ -6382,6 +6384,9 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
if ( sd && sd->spiritball )
pc_delspiritball(sd,sd->spiritball,0);
+ for(i = 1; i < 5; i++)
+ pc_del_talisman(sd, sd->talisman[i], i);
+
if (src)
switch (src->type) {
case BL_MOB:
@@ -8237,6 +8242,12 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag)
return 0;
}
+ if( !(flag&2) && sd->sc.count && sd->sc.data[SC_KYOUGAKU] )
+ {
+ clif_unequipitemack(sd,n,0,0);
+ return 0;
+ }
+
if(battle_config.battle_log)
ShowInfo("unequip %d %x:%x\n",n,pc_equippoint(sd,n),sd->status.inventory[n].equip);
@@ -8846,6 +8857,106 @@ bool pc_should_log_commands(struct map_session_data *sd)
return pc_group_should_log_commands(pc_get_group_id(sd));
}
+static int pc_talisman_timer(int tid, unsigned int tick, int id, intptr_t data)
+{
+ struct map_session_data *sd;
+ int i, type;
+
+ if( (sd=(struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type!=BL_PC )
+ return 1;
+
+ ARR_FIND(1, 5, type, sd->talisman[type] > 0);
+
+ if( sd->talisman[type] <= 0 )
+ {
+ ShowError("pc_talisman_timer: %d talisman's available. (aid=%d cid=%d tid=%d)\n", sd->talisman[type], sd->status.account_id, sd->status.char_id, tid);
+ sd->talisman[type] = 0;
+ return 0;
+ }
+
+ ARR_FIND(0, sd->talisman[type], i, sd->talisman_timer[type][i] == tid);
+ if( i == sd->talisman[type] )
+ {
+ ShowError("pc_talisman_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid);
+ return 0;
+ }
+
+ sd->talisman[type]--;
+ if( i != sd->talisman[type] )
+ memmove(sd->talisman_timer[type]+i, sd->talisman_timer[type]+i+1, (sd->talisman[type]-i)*sizeof(int));
+ sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER;
+
+ clif_talisman(sd, type);
+
+ return 0;
+}
+
+int pc_add_talisman(struct map_session_data *sd,int interval,int max,int type)
+{
+ int tid, i;
+
+ nullpo_ret(sd);
+
+ if(max > 10)
+ max = 10;
+ if(sd->talisman[type] < 0)
+ sd->talisman[type] = 0;
+
+ if( sd->talisman[type] && sd->talisman[type] >= max )
+ {
+ if(sd->talisman_timer[type][0] != INVALID_TIMER)
+ delete_timer(sd->talisman_timer[type][0],pc_talisman_timer);
+ sd->talisman[type]--;
+ if( sd->talisman[type] != 0 )
+ memmove(sd->talisman_timer[type]+0, sd->talisman_timer[type]+1, (sd->talisman[type])*sizeof(int));
+ sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER;
+ }
+
+ tid = add_timer(gettick()+interval, pc_talisman_timer, sd->bl.id, 0);
+ ARR_FIND(0, sd->talisman[type], i, sd->talisman_timer[type][i] == INVALID_TIMER || DIFF_TICK(get_timer(tid)->tick, get_timer(sd->talisman_timer[type][i])->tick) < 0);
+ if( i != sd->talisman[type] )
+ memmove(sd->talisman_timer[type]+i+1, sd->talisman_timer[type]+i, (sd->talisman[type]-i)*sizeof(int));
+ sd->talisman_timer[type][i] = tid;
+ sd->talisman[type]++;
+
+ clif_talisman(sd, type);
+ return 0;
+}
+
+int pc_del_talisman(struct map_session_data *sd,int count,int type)
+{
+ int i;
+
+ nullpo_ret(sd);
+
+ if( sd->talisman[type] <= 0 ) {
+ sd->talisman[type] = 0;
+ return 0;
+ }
+
+ if( count <= 0 )
+ return 0;
+ if( count > sd->talisman[type] )
+ count = sd->talisman[type];
+ sd->talisman[type] -= count;
+ if( count > 10 )
+ count = 10;
+
+ for(i = 0; i < count; i++) {
+ if(sd->talisman_timer[type][i] != INVALID_TIMER) {
+ delete_timer(sd->talisman_timer[type][i],pc_talisman_timer);
+ sd->talisman_timer[type][i] = INVALID_TIMER;
+ }
+ }
+ for(i = count; i < 10; i++) {
+ sd->talisman_timer[type][i-count] = sd->talisman_timer[type][i];
+ sd->talisman_timer[type][i] = INVALID_TIMER;
+ }
+
+ clif_talisman(sd, type);
+ return 0;
+}
+
int pc_split_str(char *str,char **val,int num)
{
int i;
@@ -9262,6 +9373,7 @@ int do_init_pc(void) {
add_timer_func_list(pc_spiritball_timer, "pc_spiritball_timer");
add_timer_func_list(pc_follow_timer, "pc_follow_timer");
add_timer_func_list(pc_endautobonus, "pc_endautobonus");
+ add_timer_func_list(pc_talisman_timer, "pc_talisman_timer");
add_timer(gettick() + autosave_interval, pc_autosave, 0, 0);
diff --git a/src/map/pc.h b/src/map/pc.h
index 269bc65dc..05ffb0c72 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -332,6 +332,8 @@ struct map_session_data {
short spiritball, spiritball_old;
int spirit_timer[MAX_SKILL_LEVEL];
+ short talisman[5];
+ int talisman_timer[5][10];
unsigned char potion_success_counter; //Potion successes in row counter
unsigned char mission_count; //Stores the bounty kill count for TK_MISSION
@@ -918,4 +920,7 @@ void pc_itemcd_do(struct map_session_data *sd, bool load);
int pc_load_combo(struct map_session_data *sd);
+int pc_add_talisman(struct map_session_data *sd,int interval,int max,int type);
+int pc_del_talisman(struct map_session_data *sd,int count,int type);
+
#endif /* _PC_H_ */
diff --git a/src/map/skill.c b/src/map/skill.c
index ce3d9df25..f93d5b772 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -953,6 +953,10 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
#ifdef RENEWAL
sc_start(bl,SC_RAID,100,7,5000);
+ break;
+
+ case RG_BACKSTAP:
+ sc_start(bl,SC_STUN,(5+2*skilllv),skilllv,skill_get_time(skillid,skilllv));
#endif
break;
@@ -1345,6 +1349,9 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
case KO_JYUMONJIKIRI: // needs more info
sc_start(bl,SC_JYUMONJIKIRI,25,skilllv,skill_get_time(skillid,skilllv));
break;
+ case KO_MAKIBISHI:
+ sc_start(bl, SC_STUN, 100, skilllv, skill_get_time2(skillid,skilllv));
+ break;
}
if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai)
@@ -3663,6 +3670,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
case MH_LAVA_SLIDE:
case KO_HAPPOKUNAI:
case KO_HUUMARANKA:
+ case KO_MUCHANAGE:
+ case KO_BAKURETSU:
if( flag&1 ) {//Recursive invocation
// skill_area_temp[0] holds number of targets in area
// skill_area_temp[1] holds the id of the original target
@@ -5163,7 +5172,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case SR_CRESCENTELBOW:
case SR_LIGHTNINGWALK:
case SR_GENTLETOUCH_ENERGYGAIN:
- case GN_CARTBOOST:
+ case GN_CARTBOOST:
+ case KO_MEIKYOUSISUI:
clif_skill_nodamage(src,bl,skillid,skilllv,
sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
break;
@@ -8660,7 +8670,57 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
}
}
break;
-
+
+ case KO_KAHU_ENTEN:
+ case KO_HYOUHU_HUBUKI:
+ case KO_KAZEHU_SEIRAN:
+ case KO_DOHU_KOUKAI:
+ if(sd) {
+ int ttype = skill_get_ele(skillid, skilllv);
+ clif_skill_nodamage(src, bl, skillid, skilllv, 1);
+ pc_add_talisman(sd, skill_get_time(skillid, skilllv), 10, ttype);
+ }
+ break;
+
+ case KO_ZANZOU:
+ if(sd){
+ struct mob_data *md;
+
+ md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), 2308, "");
+ if( md )
+ {
+ md->master_id = src->id;
+ md->special_state.ai = 4;
+ if( md->deletetimer != INVALID_TIMER )
+ delete_timer(md->deletetimer, mob_timer_delete);
+ md->deletetimer = add_timer (gettick() + skill_get_time(skillid, skilllv), mob_timer_delete, md->bl.id, 0);
+ mob_spawn( md );
+ pc_setinvincibletimer(sd,500);// unlock target lock
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),unit_getdir(bl),0);
+ }
+ }
+ break;
+
+ case KO_KYOUGAKU:
+ if( dstsd && tsc && !tsc->data[type] && rand()%100 < tstatus->int_/2 ){
+ clif_skill_nodamage(src,bl,skillid,skilllv,
+ sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
+ }else if( sd )
+ clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0);
+ break;
+
+ case KO_JYUSATSU:
+ if( dstsd && tsc && !tsc->data[type] && rand()%100 < tstatus->int_/2 ){
+ clif_skill_nodamage(src,bl,skillid,skilllv,
+ status_change_start(bl,type,10000,skilllv,0,0,0,skill_get_time(skillid,skilllv),1));
+ status_zap(bl, tstatus->max_hp*skilllv*5/100 , 0);
+ if( status_get_lv(bl) <= status_get_lv(src) )
+ status_change_start(bl,SC_COMA,10,skilllv,0,src->id,0,0,0);
+ }else if( sd )
+ clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0);
+ break;
+
default:
if( skillid >= HM_SKILLBASE && skillid <= HM_SKILLBASE + MAX_HOMUNSKILL ) {
if( src->type == BL_HOM && ((TBL_HOM*)src)->master->fd )
@@ -9383,6 +9443,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
case KO_HUUMARANKA:
case KO_MUCHANAGE:
case KO_BAKURETSU:
+ //case KO_MAKIBISHI:
flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete).
case GS_GROUNDDRIFT: //Ammo should be deleted right away.
skill_unitsetting(src,skillid,skilllv,x,y,0);
@@ -10961,8 +11022,6 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
default:
skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
}
- if( skill_get_unit_interval(sg->skill_id) >= skill_get_time(sg->skill_id,sg->skill_lv) )
- sg->unit_id = UNT_USED_TRAPS;
break;
case UNT_FIREPILLAR_WAITING:
@@ -11050,6 +11109,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
case UNT_FLASHER:
case UNT_FREEZINGTRAP:
case UNT_FIREPILLAR_ACTIVE:
+ case UNT_MAKIBISHI:
map_foreachinrange(skill_trap_splash,&src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick);
if (sg->unit_id != UNT_FIREPILLAR_ACTIVE)
clif_changetraplook(&src->bl, sg->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS);
@@ -11817,7 +11877,7 @@ static int skill_check_condition_mob_master_sub (struct block_list *bl, va_list
skill=va_arg(ap,int);
c=va_arg(ap,int *);
- if( md->master_id != src_id || md->special_state.ai != (unsigned)(skill == AM_SPHEREMINE?2:3) )
+ if( md->master_id != src_id || md->special_state.ai != (unsigned)(skill == AM_SPHEREMINE?2:skill == KO_ZANZOU?4:3) )
return 0; //Non alchemist summoned mobs have nothing to do here.
if(md->class_==mob_class)
@@ -12460,7 +12520,20 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0);
return 0;
}
- break;
+ break;
+ case KO_KAHU_ENTEN:
+ case KO_HYOUHU_HUBUKI:
+ case KO_KAZEHU_SEIRAN:
+ case KO_DOHU_KOUKAI:
+ {
+ int ttype = skill_get_ele(skill, lv);
+ ARR_FIND(1, 5, i, sd->talisman[i] > 0 && i != ttype);
+ if( (i < 5 && i != ttype) || sd->talisman[ttype] >= 10 ){
+ clif_skill_fail(sd, skill, USESKILL_FAIL_LEVEL, 0);
+ return 0;
+ }
+ }
+ break;
}
switch(require.state) {
@@ -12722,6 +12795,17 @@ int skill_check_condition_castend(struct map_session_data* sd, short skill, shor
}
}
break;
+ case KO_ZANZOU:
+ {
+ int c = 0;
+ i = map_foreachinmap(skill_check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, 2308, skill, &c);
+ if( c >= skill_get_maxcount(skill,lv) || c != i)
+ {
+ clif_skill_fail(sd , skill, USESKILL_FAIL_LEVEL, 0);
+ return 0;
+ }
+ }
+ break;
}
status = &sd->battle_status;
diff --git a/src/map/status.c b/src/map/status.c
index 5b401d87f..fbeb7214f 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -286,7 +286,10 @@ void initChangeTables(void) {
set_sc( NPC_HALLUCINATION , SC_HALLUCINATION , SI_HALLUCINATION , SCB_NONE );
add_sc( NPC_REBIRTH , SC_REBIRTH );
add_sc( RG_RAID , SC_STUN );
+#ifdef RENEWAL
add_sc( RG_RAID , SC_RAID );
+ add_sc( RG_BACKSTAP , SC_STUN );
+#endif
set_sc( RG_STRIPWEAPON , SC_STRIPWEAPON , SI_STRIPWEAPON , SCB_WATK );
set_sc( RG_STRIPSHIELD , SC_STRIPSHIELD , SI_STRIPSHIELD , SCB_DEF );
set_sc( RG_STRIPARMOR , SC_STRIPARMOR , SI_STRIPARMOR , SCB_VIT );
@@ -705,9 +708,14 @@ void initChangeTables(void) {
set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SI_UPHEAVAL_OPTION , SCB_NONE );
set_sc( EL_TIDAL_WEAPON , SC_TIDAL_WEAPON_OPTION , SI_TIDAL_WEAPON_OPTION , SCB_ALL );
set_sc( EL_ROCK_CRUSHER , SC_ROCK_CRUSHER , SI_ROCK_CRUSHER , SCB_DEF );
- set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED );
+ set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED );
+
add_sc( KO_YAMIKUMO , SC_HIDING );
set_sc( KO_JYUMONJIKIRI , SC_JYUMONJIKIRI , SI_KO_JYUMONJIKIRI , SCB_NONE );
+ add_sc( KO_MAKIBISHI , SC_STUN );
+ set_sc( KO_MEIKYOUSISUI , SC_MEIKYOUSISUI , SI_MEIKYOUSISUI , SCB_NONE );
+ set_sc( KO_KYOUGAKU , SC_KYOUGAKU , SI_KYOUGAKU , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
+ add_sc( KO_JYUSATSU , SC_CURSE );
add_sc( MH_STAHL_HORN , SC_STUN );
set_sc( MH_ANGRIFFS_MODUS , SC_ANGRIFFS_MODUS , SI_ANGRIFFS_MODUS , SCB_BATK|SCB_WATK|SCB_DEF|SCB_FLEE );
@@ -985,7 +993,8 @@ void initChangeTables(void) {
StatusChangeStateTable[SC_CRYSTALIZE] |= SCS_NOMOVE|SCS_NOMOVECOND;
StatusChangeStateTable[SC_NETHERWORLD] |= SCS_NOMOVE;
StatusChangeStateTable[SC_CAMOUFLAGE] |= SCS_NOMOVE|SCS_NOMOVECOND;
-
+ StatusChangeStateTable[SC_MEIKYOUSISUI] |= SCS_NOMOVE;
+
/* StatusChangeState (SCS_) NOPICKUPITEMS */
StatusChangeStateTable[SC_HIDING] |= SCS_NOPICKITEM;
StatusChangeStateTable[SC_CLOAKING] |= SCS_NOPICKITEM;
@@ -1895,7 +1904,7 @@ void status_calc_misc(struct block_list *bl, struct status_data *status, int lev
#ifdef RENEWAL // renewal formulas
status->hit += level + status->dex + status->luk/3 + 175; //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175
status->flee += level + status->agi + status->luk/5 + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100
- status->def2 += (int)(((float)level + status->vit)/2 + ((float)status->agi/5)); //base level + (every 2 agi = +1 def) + (every 5 agi = +1 def)
+ status->def2 += (int)(((float)level + status->vit)/2 + ((float)status->agi/5)); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def)
status->mdef2 += (int)(status->int_ + ((float)level/4) + ((float)status->dex/5) + ((float)status->vit/5)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef)
#else
status->hit += level + status->dex;
@@ -2009,6 +2018,8 @@ int status_calc_mob_(struct mob_data* md, bool first)
{ // different levels of HP according to skill level
if (ud->skillid == AM_SPHEREMINE) {
status->max_hp = 2000 + 400*ud->skilllv;
+ } else if(ud->skillid == KO_ZANZOU){
+ status->max_hp = 3000 + 3000 * ud->skilllv;
} else { //AM_CANNIBALIZE
status->max_hp = 1500 + 200*ud->skilllv + 10*status_get_lv(mbl);
status->mode|= MD_CANATTACK|MD_AGGRESSIVE;
@@ -4054,6 +4065,8 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang
str += sc->data[SC_INSPIRATION]->val3;
if(sc->data[SC_STOMACHACHE])
str -= sc->data[SC_STOMACHACHE]->val1;
+ if(sc->data[SC_KYOUGAKU])
+ str -= sc->data[SC_KYOUGAKU]->val2;
return (unsigned short)cap_value(str,0,USHRT_MAX);
}
@@ -4103,7 +4116,8 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang
agi += sc->data[SC_INSPIRATION]->val3;
if(sc->data[SC_STOMACHACHE])
agi -= sc->data[SC_STOMACHACHE]->val1;
-
+ if(sc->data[SC_KYOUGAKU])
+ agi -= sc->data[SC_KYOUGAKU]->val2;
return (unsigned short)cap_value(agi,0,USHRT_MAX);
}
@@ -4145,6 +4159,8 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang
vit += sc->data[SC_INSPIRATION]->val3;
if(sc->data[SC_STOMACHACHE])
vit -= sc->data[SC_STOMACHACHE]->val1;
+ if(sc->data[SC_KYOUGAKU])
+ vit -= sc->data[SC_KYOUGAKU]->val2;
return (unsigned short)cap_value(vit,0,USHRT_MAX);
}
@@ -4196,6 +4212,8 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang
int_ += sc->data[SC_INSPIRATION]->val3;
if(sc->data[SC_STOMACHACHE])
int_ -= sc->data[SC_STOMACHACHE]->val1;
+ if(sc->data[SC_KYOUGAKU])
+ int_ -= sc->data[SC_KYOUGAKU]->val2;
return (unsigned short)cap_value(int_,0,USHRT_MAX);
}
@@ -4247,6 +4265,8 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang
dex += sc->data[SC_INSPIRATION]->val3;
if(sc->data[SC_STOMACHACHE])
dex -= sc->data[SC_STOMACHACHE]->val1;
+ if(sc->data[SC_KYOUGAKU])
+ dex -= sc->data[SC_KYOUGAKU]->val2;
return (unsigned short)cap_value(dex,0,USHRT_MAX);
}
@@ -4290,7 +4310,8 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang
luk -= sc->data[SC_STOMACHACHE]->val1;
if(sc->data[SC_BANANA_BOMB])
luk -= luk * sc->data[SC_BANANA_BOMB]->val1 / 100;
-
+ if(sc->data[SC_KYOUGAKU])
+ luk -= sc->data[SC_KYOUGAKU]->val2;
return (unsigned short)cap_value(luk,0,USHRT_MAX);
}
@@ -4736,8 +4757,13 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change
return 0;
if(sc->data[SC_SUN_COMFORT])
def2 += sc->data[SC_SUN_COMFORT]->val2;
+
if(sc->data[SC_ANGELUS])
+#ifdef RENEWAL //in renewal only the VIT stat bonus is boosted by angelus
+ def2 += status_get_vit(bl) / 2 * sc->data[SC_ANGELUS]->val2/100;
+#else
def2 += def2 * sc->data[SC_ANGELUS]->val2/100;
+#endif
if(sc->data[SC_CONCENTRATION])
def2 -= def2 * sc->data[SC_CONCENTRATION]->val4/100;
if(sc->data[SC_POISON])
@@ -6063,6 +6089,9 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
case SC_MANDRAGORA:
sc_def = (status->vit+status->luk)/5;
break;
+ case SC_KYOUGAKU:
+ tick -= 30*status->int_;
+ break;
default:
//Effect that cannot be reduced? Likely a buff.
if (!(rnd()%10000 < rate))
@@ -6696,6 +6725,14 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_FIGHTINGSPIRIT:
status_change_end(bl, type, INVALID_TIMER); // Remove previous one.
break;
+ case SC_MARSHOFABYSS:
+ status_change_end(bl, SC_INCAGI, INVALID_TIMER);
+ status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
+ status_change_end(bl, SC_ASPDPOTION0, INVALID_TIMER);
+ status_change_end(bl, SC_ASPDPOTION1, INVALID_TIMER);
+ status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER);
+ status_change_end(bl, SC_ASPDPOTION3, INVALID_TIMER);
+ break;
case SC_SWINGDANCE:
case SC_SYMPHONYOFLOVER:
case SC_MOONLITSERENADE:
@@ -7847,6 +7884,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_ELECTRICSHOCKER:
case SC_CRYSTALIZE:
+ case SC_MEIKYOUSISUI:
val4 = tick / 1000;
if( val4 < 1 )
val4 = 1;
@@ -8219,6 +8257,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val4 = tick / 10000;
tick_time = 10000; // [GodLesZ] tick time
break;
+ case SC_KYOUGAKU:
+ val2 = 2*val1 + rand()%val1;
+ clif_status_change(bl,SI_ACTIVE_MONSTER_TRANSFORM,1,0,1002,0,0); // Temporarily shows Poring need official [malufett]
+ break;
default:
if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 )
@@ -8275,6 +8317,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_CURSEDCIRCLE_TARGET:
case SC_FEAR:
case SC_NETHERWORLD:
+ case SC_MEIKYOUSISUI:
unit_stop_walking(bl,1);
break;
case SC_HIDING:
@@ -9139,6 +9182,10 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
}
break;
+ case SC_KYOUGAKU:
+ clif_status_load(bl, SI_KYOUGAKU, 0); // Avoid client crash
+ clif_status_load(bl, SI_ACTIVE_MONSTER_TRANSFORM, 0);
+ break;
}
opt_flag = 1;
@@ -10142,6 +10189,14 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
/* they only end by status_change_end */
sc_timer_next(600000 + tick, status_change_timer, bl->id, data);
return 0;
+ case SC_MEIKYOUSISUI:
+ if( --(sce->val4) > 0 )
+ {
+ status_heal(bl, status->max_hp * (sce->val1+1) / 100, status->max_sp * sce->val1 / 100, 0);
+ sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+ return 0;
+ }
+ break;
}
// default for all non-handled control paths is to end the status
diff --git a/src/map/unit.c b/src/map/unit.c
index a65aafb97..26ff0f0fe 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -2231,6 +2231,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
case BL_PC:
{
struct map_session_data *sd = (struct map_session_data*)bl;
+ int i;
if( status_isdead(bl) )
pc_setrestartvalue(sd,2);
@@ -2253,6 +2254,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_talisman(sd, sd->talisman[i], i);
if( sd->reg ) { //Double logout already freed pointer fix... [Skotlex]
aFree(sd->reg);