-Add Homon-S skills, 1st implementation (all done except Eleanors)
--Upd Skill conf to set land-limit for homonculus by default (ground skill limit) --Mv MH_HEILIGE_STANGE and MH_ANGRIFFS_MODUS skill from Eleanor to Bayeri -Enforce all zeny transaction to use pc_payzeny and pc_getzeny handlers, (auto log and clif) git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@16914 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
e1a327c223
commit
752776e4cc
@ -144,7 +144,7 @@ player_cloak_check_type: 1
|
||||
monster_cloak_check_type: 4
|
||||
|
||||
// Can't place unlimited land skills at the same time (Note 3)
|
||||
land_skill_limit: 1
|
||||
land_skill_limit: 9
|
||||
|
||||
//Determines which kind of skill-failed messages should be sent:
|
||||
// 1 - Disable all skill-failed messages.
|
||||
|
@ -95,6 +95,8 @@
|
||||
6049,8031,5,0,0,0,0,0,0,0,0,0,0 //MH_STAHL_HORN
|
||||
6049,8032,5,0,0,0,0,0,0,0,0,0,0 //MH_GOLDENE_FERSE
|
||||
6049,8033,5,0,0,0,0,0,0,0,0,0,0 //MH_STEINWAND
|
||||
6049,8034,5,0,0,0,0,0,0,0,0,0,0 //MH_HEILIGE_STANGE
|
||||
6049,8035,5,0,0,0,0,0,0,0,0,0,0 //MH_ANGRIFFS_MODUS
|
||||
//Sera
|
||||
6050,8018,5,0,0,0,0,0,0,0,0,0,0 //MH_SUMMON_LEGION
|
||||
6050,8019,5,0,0,0,0,0,0,0,0,0,0 //MH_NEEDLE_OF_PARALYZE
|
||||
@ -111,8 +113,6 @@
|
||||
6052,8028,5,0,0,0,0,0,0,0,0,0,0 //MH_SONIC_CRAW
|
||||
6052,8029,5,0,0,0,0,0,0,0,0,0,0 //MH_SILVERVEIN_RUSH
|
||||
6052,8030,5,0,0,0,0,0,0,0,0,0,0 //MH_MIDNIGHT_FRENZY
|
||||
6052,8034,5,0,0,0,0,0,0,0,0,0,0 //MH_HEILIGE_STANGE
|
||||
6052,8035,5,0,0,0,0,0,0,0,0,0,0 //MH_ANGRIFFS_MODUS
|
||||
6052,8036,5,0,0,0,0,0,0,0,0,0,0 //MH_TINDER_BREAKER
|
||||
6052,8037,5,0,0,0,0,0,0,0,0,0,0 //MH_CBC
|
||||
6052,8038,5,0,0,0,0,0,0,0,0,0,0 //MH_EQC
|
@ -1722,23 +1722,23 @@
|
||||
//==========================================
|
||||
|
||||
//-- MH_SUMMON_LEGION
|
||||
8018,2000,0,0,0,20000:30000:40000:50000:60000,0,400:600:800:1000:1200
|
||||
8018,1600:1400:1200:1000:800,0,0,20000:30000:40000:50000:60000,0,0,400:600:800:1000:1200
|
||||
//-- MH_NEEDLE_OF_PARALYZE
|
||||
8019,1500,0,0,0,0,0,500:400:300:200:100
|
||||
8019,1000:1100:1200:1300:1400,0,0,12000:14000:16000:18000:20000,0,0,500:400:300:200:100
|
||||
//-- MH_POISON_MIST
|
||||
8020,1000:1200:1400:1600:1800,0,0,0,12000:14000:16000:18000:20000,0,500
|
||||
8020,500:700:900:1100:1300,0,0,12000:14000:16000:18000:20000,4000:6000:8000:10000:12000,0,500
|
||||
//-- MH_PAIN_KILLER
|
||||
8021,2000,0,0,0,20000:30000:40000:50000:60000,0,1000:800:600:400:200
|
||||
8021,1000:1200:1400:1600:1800,0,0,20000:30000:40000:50000:60000,0,0,1000:800:600:400:200
|
||||
//-- MH_LIGHT_OF_REGENE
|
||||
8022,1600:1400:1200:1000:800,0,0,0,360000:420000:480000:540000:600000,0,1600:1400:1200:1000:800
|
||||
8022,1600:1400:1200:1000:800,0,0,360000:420000:480000:540000:600000,0,0,1600:1400:1200:1000:800
|
||||
//-- MH_OVERED_BOOST
|
||||
8023,1000,0,0,0,30000:45000:60000:75000:90000,0,200:300:400:500:600
|
||||
8023,800:700:600:500:400,0,0,30000:45000:60000:75000:90000,0,0,200:300:400:500:600
|
||||
//-- MH_ERASER_CUTTER
|
||||
8024,1000:1500:2000:2500:3000,0,0,0,0,0,0
|
||||
8024,1000:1500:2000:2500:3000,0,0,0,0,0,-1
|
||||
//-- MH_XENO_SLASHER
|
||||
8025,2000:3000:4000:5000:6000,0,0,0,500,0,500
|
||||
8025,1500:2500:3500:4500:5500,0,0,500,0,0,500
|
||||
//-- MH_SILENT_BREEZE
|
||||
8026,2000,0,0,0,9000:12000:15000:18000:21000,0,1000:800:600:400:200
|
||||
8026,2000,0,0,9000:12000:15000:18000:21000,0,0,1000:800:600:400:200
|
||||
//-- MH_STYLE_CHANGE
|
||||
//8027,0,0,0,0,0,0,0
|
||||
//-- MH_SONIC_CRAW
|
||||
@ -1748,15 +1748,15 @@
|
||||
//-- MH_MIDNIGHT_FRENZY
|
||||
//8030,0,0,0,0,0,0,0
|
||||
//-- MH_STAHL_HORN
|
||||
8031,1000,0,0,0,0,0,200:400:600:800:1000
|
||||
8031,800:600:400:200:0,0,0,5000,0,0,200:400:600:800:1000
|
||||
//-- MH_GOLDENE_FERSE
|
||||
8032,1000:1200:1400:1600:1800,0,0,0,30000:45000:60000:75000:90000,0,0
|
||||
8032,1000:1200:1400:1600:1800,0,0,30000:45000:60000:75000:90000,0,0,-1
|
||||
//-- MH_STEINWAND
|
||||
8033,1000,0,0,0,30000:45000:60000:75000:90000,0,0
|
||||
8033,1000,0,0,30000:45000:60000:75000:90000,0,0,-1
|
||||
//-- MH_HEILIGE_STANGE
|
||||
8034,2000,0,0,0,0,0,1800:1600:1400:1200:1000
|
||||
//-- MH_ANGRIFFS_MODUS
|
||||
8035,200:400:600:800:1000,0,0,0,30000:45000:60000:75000:90000,0,0
|
||||
8035,200:400:600:800:1000,0,0,30000:45000:60000:75000:90000,0,0,-1
|
||||
//-- MH_TINDER_BREAKER
|
||||
//8036,0,0,0,0,0,0,0
|
||||
//-- MH_CBC
|
||||
@ -1764,15 +1764,15 @@
|
||||
//-- MH_EQC
|
||||
//8038,0,0,0,0,0,0,0
|
||||
//-- MH_MAGMA_FLOW
|
||||
8039,4000,0,0,0,30000:45000:60000:75000:90000,0,2000:1500:1000:500:0
|
||||
8039,2000:2500:3000:3500:4000,0,0,30000:45000:60000:75000:90000,0,0,2000:1500:1000:500:-1
|
||||
//-- MH_GRANITIC_ARMOR
|
||||
8040,6000:5500:5000:4500:4000,0,0,0,0,0,1000
|
||||
8040,6000:5500:5000:4500:4000,0,0,60000,0,0,1000
|
||||
//-- MH_LAVA_SLIDE
|
||||
8041,6000:5500:5000:4500:4000,0,0,0,12000:14000:16000:18000:20000,0,1000
|
||||
8041,6000:5500:5000:4500:4000,0,0,12000:14000:16000:18000:20000,0,0,1000
|
||||
//-- MH_PYROCLASTIC
|
||||
8042,6000:5500:5000:4500:4000,0,0,0,60000:90000:120000:150000:180000,0,1000
|
||||
8042,5000:4500:4000:3500:3000,0,0,60000:90000:120000:150000:180000,0,0,1000
|
||||
//-- MH_VOLCANIC_ASH
|
||||
8043,5000:4500:4000:3500:3000,0,0,0,12000:14000:16000:18000:20000,0,1000
|
||||
8043,5000:4500:4000:3500:3000,0,0,12000:14000:16000:18000:20000,0,0,1000
|
||||
|
||||
//===== Mercenary Skills ===================
|
||||
//-- MS_MAGNUM
|
||||
|
@ -1075,30 +1075,30 @@
|
||||
8015,0,0,0,0,0x1,0,5,0,no,0,0,0,none,0, HVAN_INSTRUCT,Instruct
|
||||
8016,4,6,4,-1,0xD2,4,3,1,no,0,0,0,misc,0, HVAN_EXPLOSION,Bio Explosion
|
||||
//
|
||||
8018,9,6,1,0,0x1,0,5,1,no,0,0,0,none,0, MH_SUMMON_LEGION,Summon Legion
|
||||
8018,9,6,4,0,0x1,0,5,1,no,0,0,0,none,0, MH_SUMMON_LEGION,Summon Legion
|
||||
8019,5,6,1,5,0,0,5,1,no,0,0,0,weapon,0, MH_NEEDLE_OF_PARALYZE,Needle of Paralyze
|
||||
8020,5,6,2,5,0,0,5,1,no,0,0,1,weapon,0, MH_POISON_MIST,Nevoa Venenosa
|
||||
8020,5,6,2,5,0,0,5,1,no,0,0,1,weapon,0, MH_POISON_MIST,Poison Mist
|
||||
8021,1,6,1,0,0x1,0,5,1,no,0,0,0,none,0, MH_PAIN_KILLER,Pain Killer
|
||||
8022,0,6,4,0,0,0x1,5,1,no,0,0,0,none,0, MH_LIGHT_OF_REGENE,Light of Regene
|
||||
8023,0,6,4,0,0,0x1,5,1,no,0,0,0,none,0, MH_OVERED_BOOST,Overed Boost
|
||||
8024,7,6,1,4:0:4:0:4,0,0,5,1,no,0,0,0,magic,0, MH_ERASER_CUTTER,Corte Ilusório
|
||||
8024,7,6,1,4:0:4:0:4,0,0,5,1,no,0,0,0,magic,0, MH_ERASER_CUTTER,Eraser Cutter
|
||||
8025,7,6,2,4:0:4:0:4,0,0,5,1,no,0,0,0,magic,0, MH_XENO_SLASHER,Xeno Slasher
|
||||
8026,5:5:7:7:9,6,16,0,0x1,0,5,1,no,0,0,0,magic,0, MH_SILENT_BREEZE,Silent Breeze
|
||||
8027,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, MH_STYLE_CHANGE,Style Change
|
||||
8028,1,8,1,0,0,0,5,1,no,0,0,0,weapon,0, MH_SONIC_CRAW,Sonic Claw
|
||||
8029,1,6,4,0,0,0,5,1,no,0,0x200,0,weapon,0, MH_SILVERVEIN_RUSH,Silver Bain Rush
|
||||
8030,1,6,4,0,0,0,5,1,no,0,0x200,0,weapon,0, MH_MIDNIGHT_FRENZY,Midnight Frenzy
|
||||
8031,5:6:7:8:9,6,1,0,0,0,5,1,no,0,0,0,weapon,3, MH_STAHL_HORN,Chifre de Aço
|
||||
8032,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, MH_GOLDENE_FERSE,Ferraduras de Ouro
|
||||
8031,5:6:7:8:9,6,1,0,0,0,5,1,no,0,0,0,weapon,3, MH_STAHL_HORN,Steel Horn
|
||||
8032,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, MH_GOLDENE_FERSE,Golden Heel
|
||||
8033,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, MH_STEINWAND,Stone Wall
|
||||
8034,9,6,1,6,0x2,1:1:1:1:2,5,1,no,0,0,0,magic,0, MH_HEILIGE_STANGE,Holy Pole
|
||||
8035,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, MH_ANGRIFFS_MODUS,Modo de Ataque
|
||||
8035,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, MH_ANGRIFFS_MODUS,Attack Mode
|
||||
8036,3:4:5:6:7,6,1,0,0,0,5,1,no,0,0,0,weapon,0, MH_TINDER_BREAKER,Tinder Breaker
|
||||
8037,1,6,4,0,0,0,5,1,no,0,0x200,0,weapon,0, MH_CBC,Continual Break Combo
|
||||
8038,1,6,4,0,0,0,5,1,no,0,0x200,0,weapon,0, MH_EQC,Eternal Quick Combo
|
||||
8039,0,6,4,3,0x2,1:1:1:2:2,5,1,no,0,0,0,weapon,0, MH_MAGMA_FLOW,Magma Flow
|
||||
8040,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, MH_GRANITIC_ARMOR,Granitic Armor
|
||||
8041,7,6,2,3,0x2,0,5,1,no,0,0,1,weapon,0, MH_LAVA_SLIDE,Deslizamento de Lava
|
||||
8041,7,6,2,3,0x2,0,5,1,no,0,0,1,weapon,0, MH_LAVA_SLIDE,Lava Slide
|
||||
8042,0,6,4,3,0x1,0,5,1,no,0,0,0,none,0, MH_PYROCLASTIC,Pyroclastic
|
||||
8043,7,6,2,0,0x1,0,5,1,no,0,0,3,none,0, MH_VOLCANIC_ASH,Volcanic Ash
|
||||
|
||||
|
@ -163,8 +163,8 @@
|
||||
8020,0xf5, , 0, 3,2300:2100:1900:1700:1500,enemy, 0x018 //MH_POISON_MIST
|
||||
8033,0x7e, , 0, 0, -1,all, 0x003 //MH_STEINWAND
|
||||
8025,0x86, , 0, 2:2:3:3:4,1000,enemy, 0x018 //MH_XENO_SLASHER
|
||||
8041,0xf6, , 1:1:2:2:3, 0,1000,enemy, 0x018 //MH_LAVA_SLIDE
|
||||
8043,0xf7, , 0, 1,1000,enemy, 0x018 //MH_VOLCANIC_ASH
|
||||
8041,0xf6, , 1:1:2:2:3, 0,2000,enemy, 0x01A //MH_LAVA_SLIDE
|
||||
8043,0xf7, , 1, 0,-1,enemy, 0x2018 //MH_VOLCANIC_ASH
|
||||
|
||||
8208,0x86, , 0, 2,1000,enemy, 0x080 //MA_SHOWER
|
||||
8209,0x90, , 0, 1,1000,enemy, 0x006 //MA_SKIDTRAP
|
||||
|
@ -2196,7 +2196,7 @@ ACMD_FUNC(killmonster)
|
||||
if ((map_id = map_mapname2mapid(map_name)) < 0)
|
||||
map_id = sd->bl.m;
|
||||
}
|
||||
|
||||
|
||||
drop_flag = strcmp(command+1, "killmonster2");
|
||||
|
||||
map_foreachinmap(atkillmonster_sub, map_id, BL_MOB, -drop_flag);
|
||||
@ -2533,25 +2533,7 @@ ACMD_FUNC(zeny)
|
||||
clif_displaymessage(fd, msg_txt(1012)); // Please enter an amount (usage: @zeny <amount>).
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_zeny = sd->status.zeny + zeny;
|
||||
if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY)) // fix positiv overflow
|
||||
new_zeny = MAX_ZENY;
|
||||
else if (zeny < 0 && (zeny < -MAX_ZENY || new_zeny < 0)) // fix negativ overflow
|
||||
new_zeny = 0;
|
||||
|
||||
if (new_zeny != sd->status.zeny) {
|
||||
sd->status.zeny = new_zeny;
|
||||
clif_updatestatus(sd, SP_ZENY);
|
||||
clif_displaymessage(fd, msg_txt(176)); // Current amount of zeny changed.
|
||||
} else {
|
||||
if (zeny < 0)
|
||||
clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value.
|
||||
else
|
||||
clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value.
|
||||
return -1;
|
||||
}
|
||||
|
||||
pc_getzeny(sd,zeny,LOG_TYPE_COMMAND,NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3393,7 +3375,7 @@ ACMD_FUNC(spiritball)
|
||||
if( sd->spiritball > 0 )
|
||||
pc_delspiritball(sd, sd->spiritball, 1);
|
||||
sd->spiritball = number;
|
||||
clif_spiritball(sd);
|
||||
clif_spiritball(&sd->bl);
|
||||
// no message, player can look the difference
|
||||
|
||||
return 0;
|
||||
|
@ -367,6 +367,7 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag
|
||||
if( tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB)
|
||||
status_change_end(target, SC_CRYSTALIZE, INVALID_TIMER);
|
||||
if( tsc->data[SC_EARTH_INSIGNIA]) damage += damage/2;
|
||||
if( tsc->data[SC_ASH]) damage += damage/2; //150%
|
||||
break;
|
||||
case ELE_HOLY:
|
||||
if( tsc->data[SC_ORATIO]) ratio += tsc->data[SC_ORATIO]->val1 * 2;
|
||||
@ -482,7 +483,14 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
|
||||
if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT )
|
||||
{
|
||||
struct skill_unit_group* group = skill_id2group(sc->data[SC_SAFETYWALL]->val3);
|
||||
int skill_id = sc->data[SC_SAFETYWALL]->val2;
|
||||
if (group) {
|
||||
if(skill_id == MH_STEINWAND){
|
||||
if (--group->val2<=0)
|
||||
skill_delunitgroup(group);
|
||||
d->dmg_lv = ATK_BLOCK;
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* in RE, SW possesses a lifetime equal to 3 times the caster's health
|
||||
**/
|
||||
@ -730,6 +738,16 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
|
||||
//Reduction: 6% + 6% every 20%
|
||||
damage -= damage * 6 * (1+per) / 100;
|
||||
}
|
||||
if(sc->data[SC_GRANITIC_ARMOR]){
|
||||
damage -= damage * sc->data[SC_GRANITIC_ARMOR]->val2/100;
|
||||
}
|
||||
if(sc->data[SC_PAIN_KILLER]){
|
||||
damage -= damage * sc->data[SC_PAIN_KILLER]->val3/100;
|
||||
}
|
||||
if((sce=sc->data[SC_MAGMA_FLOW]) && (rnd()%100 <= sce->val2) ){
|
||||
skill_castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,gettick(),0);
|
||||
}
|
||||
|
||||
/**
|
||||
* In renewal steel body reduces all incoming damage by 1/10
|
||||
**/
|
||||
@ -787,6 +805,10 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
|
||||
|
||||
if( sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rnd()%100 < sce->val2 )
|
||||
pc_addspiritball(sd,skill_get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3);
|
||||
if (sc->data[SC_STYLE_CHANGE] && rnd() % 100 < 50) {
|
||||
TBL_HOM *hd = BL_CAST(BL_HOM,bl);
|
||||
if (hd) hom_addspiritball(hd, 10); //add a sphere
|
||||
}
|
||||
|
||||
if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 )
|
||||
status_change_spread(bl, src); // Deadly infect attacked side
|
||||
@ -846,6 +868,10 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
|
||||
sc_start(bl,sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1));
|
||||
if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 )
|
||||
status_change_spread(src, bl);
|
||||
if (sc->data[SC_STYLE_CHANGE] && rnd() % 100 < 50) {
|
||||
TBL_HOM *hd = BL_CAST(BL_HOM,bl);
|
||||
if (hd) hom_addspiritball(hd, 10);
|
||||
}
|
||||
}
|
||||
|
||||
if (battle_config.pk_mode && sd && bl->type == BL_PC && damage && map[bl->m].flag.pvp)
|
||||
@ -1480,6 +1506,14 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(nk & NK_NO_ELEFIX) && !n_ele)
|
||||
if (src->type == BL_HOM)
|
||||
n_ele = true; //skill is "not elemental"
|
||||
if (sc && sc->data[SC_GOLDENE_FERSE] && ((!skill_num && (rnd() % 100 < sc->data[SC_GOLDENE_FERSE]->val4)) || skill_num == MH_STAHL_HORN)) {
|
||||
s_ele = s_ele_ = ELE_HOLY;
|
||||
n_ele = false;
|
||||
}
|
||||
|
||||
if(!skill_num)
|
||||
{ //Skills ALWAYS use ONLY your right-hand weapon (tested on Aegis 10.2)
|
||||
if (sd && sd->weapontype1 == 0 && sd->weapontype2 > 0)
|
||||
@ -1818,7 +1852,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
|
||||
skillratio += sc->data[SC_OVERTHRUST]->val3;
|
||||
if(sc->data[SC_MAXOVERTHRUST])
|
||||
skillratio += sc->data[SC_MAXOVERTHRUST]->val2;
|
||||
if(sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])
|
||||
if (sc->data[SC_BERSERK] || sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC__BLOODYLUST])
|
||||
skillratio += 100;
|
||||
if(sc->data[SC_ZENKAI] && sstatus->rhw.ele == sc->data[SC_ZENKAI]->val2 )
|
||||
skillratio += sc->data[SC_ZENKAI]->val1 * 2;
|
||||
@ -2564,12 +2598,18 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
|
||||
case KO_BAKURETSU:
|
||||
skillratio = 50 * skill_lv * (sd?pc_checkskill(sd,NJ_TOBIDOUGU):10);
|
||||
break;
|
||||
case MH_NEEDLE_OF_PARALYZE:
|
||||
skillratio += 600 + 100 * skill_lv;
|
||||
break;
|
||||
case MH_STAHL_HORN:
|
||||
skillratio += 500 + 100 * skill_lv;
|
||||
skillratio += 400 + 100 * skill_lv;
|
||||
break;
|
||||
case MH_LAVA_SLIDE:
|
||||
skillratio = 70 * skill_lv;
|
||||
break;
|
||||
case MH_MAGMA_FLOW:
|
||||
skillratio += -100 + 100 * skill_lv;
|
||||
break;
|
||||
}
|
||||
|
||||
ATK_RATE(skillratio);
|
||||
@ -2686,6 +2726,11 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
|
||||
ATK_ADDRATE(sc->data[SC_EDP]->val3);
|
||||
}
|
||||
}
|
||||
if(sc->data[SC_STYLE_CHANGE]){
|
||||
TBL_HOM *hd = BL_CAST(BL_HOM,src);
|
||||
if (hd) ATK_ADD(hd->spiritball * 3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch (skill_num) {
|
||||
@ -3890,10 +3935,19 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
skillratio += 1100;
|
||||
break;
|
||||
case MH_ERASER_CUTTER:
|
||||
if (skill_lv >= 3)
|
||||
skillratio += 800 + 200 * skill_lv ;
|
||||
else
|
||||
skillratio += 500 + 400 * skill_lv;
|
||||
if(skill_lv%2) skillratio += 400; //600:800:1000
|
||||
else skillratio += 700; //1000:1200
|
||||
skillratio += 100 * skill_lv;
|
||||
break;
|
||||
case MH_XENO_SLASHER:
|
||||
if(skill_lv%2) skillratio += 350 + 50 * skill_lv; //500:600:700
|
||||
else skillratio += 400 + 100 * skill_lv; //700:900
|
||||
break;
|
||||
case MH_HEILIGE_STANGE:
|
||||
skillratio += 400 + 250 * skill_lv;
|
||||
break;
|
||||
case MH_POISON_MIST:
|
||||
skillratio += 100 * skill_lv;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4403,7 +4457,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
|
||||
if( sd ) {
|
||||
if ( md.damage > sd->status.zeny )
|
||||
md.damage = sd->status.zeny;
|
||||
pc_payzeny(sd, md.damage);
|
||||
pc_payzeny(sd, md.damage,LOG_TYPE_STEAL,NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -366,17 +366,14 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
|
||||
ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid );
|
||||
zeny = amount*pl_sd->buyingstore.items[listidx].price;
|
||||
|
||||
// log
|
||||
log_zeny(sd, LOG_TYPE_BUYING_STORE, pl_sd, zeny);
|
||||
|
||||
// move item
|
||||
pc_additem(pl_sd, &sd->status.inventory[index], amount, LOG_TYPE_BUYING_STORE);
|
||||
pc_delitem(sd, index, amount, 1, 0, LOG_TYPE_BUYING_STORE);
|
||||
pl_sd->buyingstore.items[listidx].amount-= amount;
|
||||
|
||||
// pay up
|
||||
pc_payzeny(pl_sd, zeny);
|
||||
pc_getzeny(sd, zeny);
|
||||
pc_payzeny(pl_sd, zeny, LOG_TYPE_BUYING_STORE, sd);
|
||||
pc_getzeny(sd, zeny, LOG_TYPE_BUYING_STORE, pl_sd);
|
||||
pl_sd->buyingstore.zenylimit-= zeny;
|
||||
|
||||
// notify clients
|
||||
|
@ -1356,7 +1356,7 @@ int clif_spawn(struct block_list *bl)
|
||||
TBL_PC *sd = ((TBL_PC*)bl);
|
||||
int i;
|
||||
if (sd->spiritball > 0)
|
||||
clif_spiritball(sd);
|
||||
clif_spiritball(&sd->bl);
|
||||
if(sd->state.size==SZ_BIG) // tiny/big players [Valaris]
|
||||
clif_specialeffect(bl,423,AREA);
|
||||
else if(sd->state.size==SZ_MEDIUM)
|
||||
@ -5440,12 +5440,12 @@ void clif_GlobalMessage(struct block_list* bl, const char* message) {
|
||||
char buf[100];
|
||||
int len;
|
||||
nullpo_retv(bl);
|
||||
|
||||
|
||||
if(!message)
|
||||
return;
|
||||
|
||||
|
||||
len = strlen(message)+1;
|
||||
|
||||
|
||||
if( len > sizeof(buf)-8 ) {
|
||||
ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%d).\n", message, len);
|
||||
len = sizeof(buf)-8;
|
||||
@ -5465,7 +5465,7 @@ void clif_GlobalMessage(struct block_list* bl, const char* message) {
|
||||
void clif_MainChatMessage(const char* message) {
|
||||
uint8 buf[200];
|
||||
int len;
|
||||
|
||||
|
||||
if(!message)
|
||||
return;
|
||||
|
||||
@ -6896,20 +6896,27 @@ void clif_devotion(struct block_list *src, struct map_session_data *tsd)
|
||||
clif_send(buf, packet_len(0x1cf), src, AREA);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Server tells clients nearby 'sd' (and himself) to display 'sd->spiritball' number of spiritballs on 'sd'
|
||||
* Notifies clients in an area of an object's spirits.
|
||||
* 01d0 <id>.L <amount>.W (ZC_SPIRITS)
|
||||
* 01e1 <id>.L <amount>.W (ZC_SPIRITS2)
|
||||
*------------------------------------------*/
|
||||
void clif_spiritball(struct block_list *bl) {
|
||||
unsigned char buf[16];
|
||||
TBL_PC *sd = BL_CAST(BL_PC,bl);
|
||||
TBL_HOM *hd = BL_CAST(BL_HOM,bl);
|
||||
|
||||
/// Notifies clients in an area of an object's spirits.
|
||||
/// 01d0 <id>.L <amount>.W (ZC_SPIRITS)
|
||||
/// 01e1 <id>.L <amount>.W (ZC_SPIRITS2)
|
||||
void clif_spiritball(struct map_session_data *sd)
|
||||
{
|
||||
unsigned char buf[8];
|
||||
nullpo_retv(bl);
|
||||
|
||||
nullpo_retv(sd);
|
||||
|
||||
WBUFW(buf,0)=0x1d0;
|
||||
WBUFL(buf,2)=sd->bl.id;
|
||||
WBUFW(buf,6)=sd->spiritball;
|
||||
clif_send(buf,packet_len(0x1d0),&sd->bl,AREA);
|
||||
WBUFW(buf, 0) = 0x1d0;
|
||||
WBUFL(buf, 2) = bl->id;
|
||||
WBUFW(buf, 6) = 0; //init to 0
|
||||
switch(bl->type){
|
||||
case BL_PC: WBUFW(buf, 6) = sd->spiritball; break;
|
||||
case BL_HOM: WBUFW(buf, 6) = hd->spiritball; break;
|
||||
}
|
||||
clif_send(buf, packet_len(0x1d0), bl, AREA);
|
||||
}
|
||||
|
||||
|
||||
@ -8205,7 +8212,7 @@ void clif_message(struct block_list* bl, const char* msg) {
|
||||
unsigned short msg_len = strlen(msg) + 1;
|
||||
uint8 buf[256];
|
||||
nullpo_retv(bl);
|
||||
|
||||
|
||||
if( msg_len > sizeof(buf)-8 ) {
|
||||
ShowWarning("clif_message: Truncating too long message '%s' (len=%u).\n", msg, msg_len);
|
||||
msg_len = sizeof(buf)-8;
|
||||
@ -8215,7 +8222,7 @@ void clif_message(struct block_list* bl, const char* msg) {
|
||||
WBUFW(buf,2) = msg_len + 8;
|
||||
WBUFL(buf,4) = bl->id;
|
||||
safestrncpy((char*)WBUFP(buf,8), msg, msg_len);
|
||||
|
||||
|
||||
clif_send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC);
|
||||
}
|
||||
|
||||
@ -14220,8 +14227,7 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd)
|
||||
pc_delitem(sd, sd->auction.index, sd->auction.amount, 1, 6, LOG_TYPE_AUCTION);
|
||||
sd->auction.amount = 0;
|
||||
|
||||
log_zeny(sd, LOG_TYPE_AUCTION, sd, -zeny);
|
||||
pc_payzeny(sd, zeny);
|
||||
pc_payzeny(sd, zeny, LOG_TYPE_AUCTION, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -14265,8 +14271,7 @@ void clif_parse_Auction_bid(int fd, struct map_session_data *sd)
|
||||
else if ( CheckForCharServer() ) // char server is down (bugreport:1138)
|
||||
clif_Auction_message(fd, 0); // You have failed to bid into the auction
|
||||
else {
|
||||
log_zeny(sd, LOG_TYPE_AUCTION, sd, -bid);
|
||||
pc_payzeny(sd, bid);
|
||||
pc_payzeny(sd, bid, LOG_TYPE_AUCTION, NULL);
|
||||
intif_Auction_bid(sd->status.char_id, sd->status.name, auction_id, bid);
|
||||
}
|
||||
}
|
||||
|
@ -454,7 +454,7 @@ void clif_skillunit_update(struct block_list* bl);
|
||||
|
||||
void clif_autospell(struct map_session_data *sd,int skilllv);
|
||||
void clif_devotion(struct block_list *src, struct map_session_data *tsd);
|
||||
void clif_spiritball(struct map_session_data *sd);
|
||||
void clif_spiritball(struct block_list *bl);
|
||||
void clif_combo_delay(struct block_list *bl,int wait);
|
||||
void clif_bladestop(struct block_list *src, int dst_id, int active);
|
||||
void clif_changemapcell(int fd, int m, int x, int y, int type, enum send_target target);
|
||||
|
@ -408,7 +408,7 @@ int guild_created(int account_id,int guild_id)
|
||||
sd->status.guild_id=guild_id;
|
||||
clif_guild_created(sd,0);
|
||||
if(battle_config.guild_emperium_check)
|
||||
pc_delitem(sd,pc_search_inventory(sd,714),1,0,0,LOG_TYPE_CONSUME); // <20>G<EFBFBD><47><EFBFBD>y<EFBFBD><79><EFBFBD>E<EFBFBD><45><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
pc_delitem(sd,pc_search_inventory(sd,ITEMID_EMPERIUM),1,0,0,LOG_TYPE_CONSUME); //emperium consumption
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -81,6 +81,46 @@ int hom_class2mapid(int hom_class)
|
||||
}
|
||||
}
|
||||
|
||||
int hom_addspiritball(TBL_HOM *hd, int max) {
|
||||
nullpo_ret(hd);
|
||||
|
||||
if (max > MAX_SKILL_LEVEL)
|
||||
max = MAX_SKILL_LEVEL;
|
||||
if (hd->spiritball < 0)
|
||||
hd->spiritball = 0;
|
||||
|
||||
if (hd->spiritball && hd->spiritball >= max) {
|
||||
hd->spiritball = max;
|
||||
}
|
||||
else
|
||||
hd->spiritball++;
|
||||
|
||||
clif_spiritball(&hd->bl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hom_delspiritball(TBL_HOM *hd, int count, int type) {
|
||||
nullpo_ret(hd);
|
||||
|
||||
if (hd->spiritball <= 0) {
|
||||
hd->spiritball = 0;
|
||||
return 0;
|
||||
}
|
||||
if (count <= 0)
|
||||
return 0;
|
||||
if (count > MAX_SKILL_LEVEL)
|
||||
count = MAX_SKILL_LEVEL;
|
||||
if (count > hd->spiritball)
|
||||
count = hd->spiritball;
|
||||
|
||||
hd->spiritball -= count;
|
||||
if (!type)
|
||||
clif_spiritball(&hd->bl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void merc_damage(struct homun_data *hd) {
|
||||
clif_hominfo(hd->master,hd,0);
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ struct homun_data {
|
||||
int hungry_timer; //[orn]
|
||||
unsigned int exp_next;
|
||||
char blockskill[MAX_SKILL]; // [orn]
|
||||
|
||||
int spiritball; //for homun S [lighta]
|
||||
};
|
||||
|
||||
#define HOM_EVO 0x100 //256
|
||||
@ -112,4 +114,7 @@ void merc_hom_init_timers(struct homun_data * hd);
|
||||
void merc_skill_reload(void);
|
||||
void merc_reload(void);
|
||||
|
||||
int hom_addspiritball(TBL_HOM *hd, int max);
|
||||
int hom_delspiritball(TBL_HOM *hd, int count, int type);
|
||||
|
||||
#endif /* _HOMUNCULUS_H_ */
|
||||
|
@ -50,7 +50,7 @@ extern int char_fd; // inter server Fd used for char_fd
|
||||
#define inter_fd char_fd // alias
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Send to inter server
|
||||
// Send to inter server
|
||||
|
||||
int CheckForCharServer(void)
|
||||
{
|
||||
@ -417,7 +417,7 @@ int intif_request_partyinfo(int party_id, int char_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Request to add a member to party
|
||||
// Request to add a member to party
|
||||
int intif_party_addmember(int party_id,struct party_member *member)
|
||||
{
|
||||
if (CheckForCharServer())
|
||||
@ -460,11 +460,11 @@ int intif_party_leave(int party_id,int account_id, int char_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Request keeping party for new map ??
|
||||
// Request keeping party for new map ??
|
||||
int intif_party_changemap(struct map_session_data *sd,int online)
|
||||
{
|
||||
int m, mapindex;
|
||||
|
||||
|
||||
if (CheckForCharServer())
|
||||
return 0;
|
||||
if(!sd)
|
||||
@ -487,7 +487,7 @@ int intif_party_changemap(struct map_session_data *sd,int online)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Request breaking party
|
||||
// Request breaking party
|
||||
int intif_break_party(int party_id)
|
||||
{
|
||||
if (CheckForCharServer())
|
||||
@ -687,7 +687,7 @@ int intif_guild_change_memberinfo(int guild_id,int account_id,int char_id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Request a change of Guild title
|
||||
// Request a change of Guild title
|
||||
int intif_guild_position(int guild_id,int idx,struct guild_position *p)
|
||||
{
|
||||
if (CheckForCharServer())
|
||||
@ -702,7 +702,7 @@ int intif_guild_position(int guild_id,int idx,struct guild_position *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Request an update of Guildskill skillnum
|
||||
// Request an update of Guildskill skillnum
|
||||
int intif_guild_skillup(int guild_id, int skill_num, int account_id, int max)
|
||||
{
|
||||
if( CheckForCharServer() )
|
||||
@ -857,7 +857,7 @@ int intif_homunculus_requestdelete(int homun_id)
|
||||
|
||||
// Wisp/Page reception // rewritten by [Yor]
|
||||
int intif_parse_WisMessage(int fd)
|
||||
{
|
||||
{
|
||||
struct map_session_data* sd;
|
||||
char *wisp_source;
|
||||
char name[NAME_LENGTH];
|
||||
@ -881,7 +881,7 @@ int intif_parse_WisMessage(int fd)
|
||||
sd->ignore[i].name[0] != '\0' &&
|
||||
strcmp(sd->ignore[i].name, wisp_source) != 0
|
||||
; i++);
|
||||
|
||||
|
||||
if (i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0')
|
||||
{ //Ignored
|
||||
intif_wis_replay(id, 2);
|
||||
@ -913,7 +913,7 @@ static int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va)
|
||||
char *wisp_name;
|
||||
char *message;
|
||||
int len;
|
||||
|
||||
|
||||
if (!pc_has_permission(sd, permission))
|
||||
return 0;
|
||||
wisp_name = va_arg(va, char*);
|
||||
@ -1006,7 +1006,7 @@ int intif_parse_LoadGuildStorage(int fd)
|
||||
struct guild_storage *gstor;
|
||||
struct map_session_data *sd;
|
||||
int guild_id;
|
||||
|
||||
|
||||
guild_id = RFIFOL(fd,8);
|
||||
if(guild_id <= 0)
|
||||
return 1;
|
||||
@ -1426,7 +1426,7 @@ int intif_parse_questlog(int fd)
|
||||
sd->quest_index[i] = quest_search_db(sd->quest_log[i].quest_id);
|
||||
|
||||
if( sd->quest_index[i] < 0 )
|
||||
{
|
||||
{
|
||||
ShowError("intif_parse_questlog: quest %d not found in DB.\n",sd->quest_log[i].quest_id);
|
||||
sd->avail_quests--;
|
||||
sd->num_quests--;
|
||||
@ -1786,7 +1786,7 @@ static void intif_parse_Auction_results(int fd)
|
||||
int intif_Auction_register(struct auction_data *auction)
|
||||
{
|
||||
int len = sizeof(struct auction_data) + 4;
|
||||
|
||||
|
||||
if( CheckForCharServer() )
|
||||
return 0;
|
||||
|
||||
@ -1795,7 +1795,7 @@ int intif_Auction_register(struct auction_data *auction)
|
||||
WFIFOW(inter_fd,2) = len;
|
||||
memcpy(WFIFOP(inter_fd,4), auction, sizeof(struct auction_data));
|
||||
WFIFOSET(inter_fd,len);
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1827,8 +1827,7 @@ static void intif_parse_Auction_register(int fd)
|
||||
clif_Auction_message(sd->fd, 4);
|
||||
pc_additem(sd, &auction.item, auction.item.amount, LOG_TYPE_AUCTION);
|
||||
|
||||
log_zeny(sd, LOG_TYPE_AUCTION, sd, zeny);
|
||||
pc_getzeny(sd, zeny);
|
||||
pc_getzeny(sd, zeny, LOG_TYPE_AUCTION,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1925,8 +1924,7 @@ static void intif_parse_Auction_bid(int fd)
|
||||
clif_Auction_message(sd->fd, result);
|
||||
if( bid > 0 )
|
||||
{
|
||||
log_zeny(sd, LOG_TYPE_AUCTION, sd, bid);
|
||||
pc_getzeny(sd, bid);
|
||||
pc_getzeny(sd, bid, LOG_TYPE_AUCTION,NULL);
|
||||
}
|
||||
if( result == 1 )
|
||||
{ // To update the list, display your buy list
|
||||
@ -2041,10 +2039,10 @@ int intif_parse_mercenary_saved(int fd)
|
||||
int intif_elemental_create(struct s_elemental *ele)
|
||||
{
|
||||
int size = sizeof(struct s_elemental) + 4;
|
||||
|
||||
|
||||
if( CheckForCharServer() )
|
||||
return 0;
|
||||
|
||||
|
||||
WFIFOHEAD(inter_fd,size);
|
||||
WFIFOW(inter_fd,0) = 0x307c;
|
||||
WFIFOW(inter_fd,2) = size;
|
||||
@ -2062,7 +2060,7 @@ int intif_parse_elemental_received(int fd)
|
||||
ShowError("intif: create elemental data size error %d != %d\n", sizeof(struct s_elemental), len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
elemental_data_received((struct s_elemental*)RFIFOP(fd,5), RFIFOB(fd,4));
|
||||
return 0;
|
||||
}
|
||||
@ -2071,7 +2069,7 @@ int intif_elemental_request(int ele_id, int char_id)
|
||||
{
|
||||
if (CheckForCharServer())
|
||||
return 0;
|
||||
|
||||
|
||||
WFIFOHEAD(inter_fd,10);
|
||||
WFIFOW(inter_fd,0) = 0x307d;
|
||||
WFIFOL(inter_fd,2) = ele_id;
|
||||
@ -2084,7 +2082,7 @@ int intif_elemental_delete(int ele_id)
|
||||
{
|
||||
if (CheckForCharServer())
|
||||
return 0;
|
||||
|
||||
|
||||
WFIFOHEAD(inter_fd,6);
|
||||
WFIFOW(inter_fd,0) = 0x307e;
|
||||
WFIFOL(inter_fd,2) = ele_id;
|
||||
@ -2096,17 +2094,17 @@ int intif_parse_elemental_deleted(int fd)
|
||||
{
|
||||
if( RFIFOB(fd,2) != 1 )
|
||||
ShowError("Elemental data delete failure\n");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int intif_elemental_save(struct s_elemental *ele)
|
||||
{
|
||||
int size = sizeof(struct s_elemental) + 4;
|
||||
|
||||
|
||||
if( CheckForCharServer() )
|
||||
return 0;
|
||||
|
||||
|
||||
WFIFOHEAD(inter_fd,size);
|
||||
WFIFOW(inter_fd,0) = 0x307f;
|
||||
WFIFOW(inter_fd,2) = size;
|
||||
@ -2119,7 +2117,7 @@ int intif_parse_elemental_saved(int fd)
|
||||
{
|
||||
if( RFIFOB(fd,2) != 1 )
|
||||
ShowError("Elemental data save failure\n");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2127,18 +2125,18 @@ void intif_request_accinfo( int u_fd, int aid, int group_id, char* query ) {
|
||||
|
||||
|
||||
WFIFOHEAD(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH);
|
||||
|
||||
|
||||
WFIFOW(inter_fd,0) = 0x3007;
|
||||
WFIFOL(inter_fd,2) = u_fd;
|
||||
WFIFOL(inter_fd,6) = aid;
|
||||
WFIFOL(inter_fd,10) = group_id;
|
||||
safestrncpy(WFIFOP(inter_fd,14), query, NAME_LENGTH);
|
||||
|
||||
|
||||
WFIFOSET(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void intif_parse_MessageToFD(int fd) {
|
||||
int u_fd = RFIFOL(fd,4);
|
||||
|
||||
@ -2151,9 +2149,9 @@ void intif_parse_MessageToFD(int fd) {
|
||||
safestrncpy(msg, (char*)RFIFOP(fd,12), RFIFOW(fd,2) - 12);
|
||||
clif_displaymessage(u_fd,msg);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2250,7 +2248,7 @@ int intif_parse(int fd)
|
||||
case 0x387c: intif_parse_elemental_received(fd); break;
|
||||
case 0x387d: intif_parse_elemental_deleted(fd); break;
|
||||
case 0x387e: intif_parse_elemental_saved(fd); break;
|
||||
|
||||
|
||||
case 0x3880: intif_parse_CreatePet(fd); break;
|
||||
case 0x3881: intif_parse_RecvPetData(fd); break;
|
||||
case 0x3882: intif_parse_SavePetOk(fd); break;
|
||||
|
@ -48,9 +48,7 @@ int mail_removezeny(struct map_session_data *sd, short flag)
|
||||
|
||||
if (flag && sd->mail.zeny > 0)
|
||||
{ //Zeny send
|
||||
log_zeny(sd, LOG_TYPE_MAIL, sd, -sd->mail.zeny);
|
||||
|
||||
sd->status.zeny -= sd->mail.zeny;
|
||||
pc_payzeny(sd,sd->mail.zeny,LOG_TYPE_MAIL, NULL);
|
||||
}
|
||||
sd->mail.zeny = 0;
|
||||
clif_updatestatus(sd, SP_ZENY);
|
||||
@ -59,10 +57,10 @@ int mail_removezeny(struct map_session_data *sd, short flag)
|
||||
}
|
||||
|
||||
unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) {
|
||||
|
||||
|
||||
if( pc_istrading(sd) )
|
||||
return 1;
|
||||
|
||||
|
||||
if( idx == 0 ) { // Zeny Transfer
|
||||
if( amount < 0 || !pc_can_give_items(sd) )
|
||||
return 1;
|
||||
@ -88,7 +86,7 @@ unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) {
|
||||
sd->mail.index = idx;
|
||||
sd->mail.nameid = sd->status.inventory[idx].nameid;
|
||||
sd->mail.amount = amount;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -96,7 +94,7 @@ unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) {
|
||||
bool mail_setattachment(struct map_session_data *sd, struct mail_message *msg)
|
||||
{
|
||||
int n;
|
||||
|
||||
|
||||
nullpo_retr(false,sd);
|
||||
nullpo_retr(false,msg);
|
||||
|
||||
@ -140,8 +138,7 @@ void mail_getattachment(struct map_session_data* sd, int zeny, struct item* item
|
||||
|
||||
if( zeny > 0 )
|
||||
{ //Zeny receive
|
||||
log_zeny(sd, LOG_TYPE_MAIL, sd, zeny);
|
||||
pc_getzeny(sd, zeny);
|
||||
pc_getzeny(sd, zeny,LOG_TYPE_MAIL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,13 +167,9 @@ void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg)
|
||||
|
||||
if( msg->zeny > 0 )
|
||||
{
|
||||
//Zeny receive (due to failure)
|
||||
log_zeny(sd, LOG_TYPE_MAIL, sd, msg->zeny);
|
||||
|
||||
sd->status.zeny += msg->zeny;
|
||||
clif_updatestatus(sd, SP_ZENY);
|
||||
pc_getzeny(sd,msg->zeny,LOG_TYPE_MAIL, NULL); //Zeny receive (due to failure)
|
||||
}
|
||||
|
||||
|
||||
clif_Mail_send(sd->fd, true);
|
||||
}
|
||||
|
||||
|
@ -2290,7 +2290,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
|
||||
}
|
||||
}
|
||||
if(zeny) // zeny from mobs [Valaris]
|
||||
pc_getzeny(tmpsd[i], zeny);
|
||||
pc_getzeny(tmpsd[i], zeny, LOG_TYPE_PICKDROP_MONSTER, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2430,7 +2430,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
|
||||
if( sd->bonus.get_zeny_num && rnd()%100 < sd->bonus.get_zeny_rate ) {
|
||||
i = sd->bonus.get_zeny_num > 0 ? sd->bonus.get_zeny_num : -md->level * sd->bonus.get_zeny_num;
|
||||
if (!i) i = 1;
|
||||
pc_getzeny(sd, 1+rnd()%i);
|
||||
pc_getzeny(sd, 1+rnd()%i, LOG_TYPE_OTHER, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
140
src/map/npc.c
140
src/map/npc.c
@ -199,7 +199,7 @@ int npc_enable(const char* name, int flag)
|
||||
} else
|
||||
clif_changeoption(&nd->bl);
|
||||
|
||||
if( flag&3 && (nd->u.scr.xs >= 0 || nd->u.scr.ys >= 0) ) //check if player standing on a OnTouchArea
|
||||
if( flag&3 && (nd->u.scr.xs >= 0 || nd->u.scr.ys >= 0) ) //check if player standing on a OnTouchArea
|
||||
map_foreachinarea( npc_enable_sub, nd->bl.m, nd->bl.x-nd->u.scr.xs, nd->bl.y-nd->u.scr.ys, nd->bl.x+nd->u.scr.xs, nd->bl.y+nd->u.scr.ys, BL_PC, nd );
|
||||
|
||||
return 0;
|
||||
@ -302,7 +302,7 @@ int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char
|
||||
|
||||
/**
|
||||
* Exec name (NPC events) on player or global
|
||||
* Do on all NPC when called with foreach
|
||||
* Do on all NPC when called with foreach
|
||||
* @see DBApply
|
||||
*/
|
||||
int npc_event_doall_sub(DBKey key, DBData *data, va_list ap)
|
||||
@ -411,22 +411,22 @@ int npc_event_do_clock(int tid, unsigned int tick, int id, intptr_t data)
|
||||
case 6: day = "Sat"; break;
|
||||
default:day = ""; break;
|
||||
}
|
||||
|
||||
|
||||
sprintf(buf,"OnMinute%02d",t->tm_min);
|
||||
c += npc_event_doall(buf);
|
||||
|
||||
|
||||
sprintf(buf,"OnClock%02d%02d",t->tm_hour,t->tm_min);
|
||||
c += npc_event_doall(buf);
|
||||
|
||||
|
||||
sprintf(buf,"On%s%02d%02d",day,t->tm_hour,t->tm_min);
|
||||
c += npc_event_doall(buf);
|
||||
}
|
||||
|
||||
|
||||
if (t->tm_hour != ev_tm_b.tm_hour) {
|
||||
sprintf(buf,"OnHour%02d",t->tm_hour);
|
||||
c += npc_event_doall(buf);
|
||||
}
|
||||
|
||||
|
||||
if (t->tm_mday != ev_tm_b.tm_mday) {
|
||||
sprintf(buf,"OnDay%02d%02d",t->tm_mon+1,t->tm_mday);
|
||||
c += npc_event_doall(buf);
|
||||
@ -539,13 +539,13 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data)
|
||||
sd->npc_timer_id = INVALID_TIMER;
|
||||
else
|
||||
nd->u.scr.timerid = INVALID_TIMER;
|
||||
|
||||
|
||||
ers_free(timer_event_ers, ted);
|
||||
}
|
||||
|
||||
// Run the script
|
||||
run_script(nd->u.scr.script,te->pos,nd->u.scr.rid,nd->bl.id);
|
||||
|
||||
|
||||
nd->u.scr.rid = old_rid; // Attached-rid should be restored anyway.
|
||||
if( sd )
|
||||
{ // Restore previous data, only if this timer is a player-attached one.
|
||||
@ -564,7 +564,7 @@ int npc_timerevent_start(struct npc_data* nd, int rid)
|
||||
unsigned int tick = gettick();
|
||||
struct map_session_data *sd = NULL; //Player to whom script is attached.
|
||||
struct timer_event_data *ted;
|
||||
|
||||
|
||||
nullpo_ret(nd);
|
||||
|
||||
// Check if there is an OnTimer Event
|
||||
@ -584,7 +584,7 @@ int npc_timerevent_start(struct npc_data* nd, int rid)
|
||||
}
|
||||
else if( nd->u.scr.timerid != INVALID_TIMER || nd->u.scr.timertick )
|
||||
return 0;
|
||||
|
||||
|
||||
if (j < nd->u.scr.timeramount)
|
||||
{
|
||||
// Arrange for the next event
|
||||
@ -606,7 +606,7 @@ int npc_timerevent_start(struct npc_data* nd, int rid)
|
||||
}
|
||||
else if (!sd)
|
||||
{
|
||||
nd->u.scr.timertick = tick;
|
||||
nd->u.scr.timertick = tick;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -627,7 +627,7 @@ int npc_timerevent_stop(struct npc_data* nd)
|
||||
ShowError("npc_timerevent_stop: Attached player not found!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
tid = sd?&sd->npc_timer_id:&nd->u.scr.timerid;
|
||||
if( *tid == INVALID_TIMER && (sd || !nd->u.scr.timertick) ) // Nothing to stop
|
||||
return 0;
|
||||
@ -700,7 +700,7 @@ void npc_timerevent_quit(struct map_session_data* sd)
|
||||
nd->u.scr.rid = sd->bl.id;
|
||||
nd->u.scr.timertick = gettick();
|
||||
nd->u.scr.timer = ted->time;
|
||||
|
||||
|
||||
//Execute label
|
||||
run_script(nd->u.scr.script,ev->pos,sd->bl.id,nd->bl.id);
|
||||
|
||||
@ -855,7 +855,7 @@ int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap)
|
||||
xs = nd->u.scr.xs;
|
||||
ys = nd->u.scr.ys;
|
||||
|
||||
if( sd->bl.m != nd->bl.m ||
|
||||
if( sd->bl.m != nd->bl.m ||
|
||||
sd->bl.x < nd->bl.x - xs || sd->bl.x > nd->bl.x + xs ||
|
||||
sd->bl.y < nd->bl.y - ys || sd->bl.y > nd->bl.y + ys ||
|
||||
pc_ishiding(sd) || leavemap )
|
||||
@ -1012,7 +1012,7 @@ int npc_check_areanpc(int flag, int m, int x, int y, int range)
|
||||
y0 = max(y-range, 0);
|
||||
x1 = min(x+range, map[m].xs-1);
|
||||
y1 = min(y+range, map[m].ys-1);
|
||||
|
||||
|
||||
//First check for npc_cells on the range given
|
||||
i = 0;
|
||||
for (ys = y0; ys <= y1 && !i; ys++) {
|
||||
@ -1106,7 +1106,7 @@ void run_tomb(struct map_session_data* sd, struct npc_data* nd)
|
||||
{
|
||||
char buffer[200];
|
||||
char time[10];
|
||||
|
||||
|
||||
strftime(time, sizeof(time), "%H:%M", localtime(&nd->u.tomb.kill_time));
|
||||
|
||||
// TODO: Find exact color?
|
||||
@ -1117,7 +1117,7 @@ void run_tomb(struct map_session_data* sd, struct npc_data* nd)
|
||||
|
||||
snprintf(buffer, sizeof(buffer), msg_txt(659), time);
|
||||
clif_scriptmes(sd, nd->bl.id, buffer);
|
||||
|
||||
|
||||
clif_scriptmes(sd, nd->bl.id, msg_txt(660));
|
||||
|
||||
snprintf(buffer, sizeof(buffer), msg_txt(661), nd->u.tomb.killer_name[0] ? nd->u.tomb.killer_name : "Unknown");
|
||||
@ -1128,7 +1128,7 @@ void run_tomb(struct map_session_data* sd, struct npc_data* nd)
|
||||
|
||||
/*==========================================
|
||||
* NPC 1st call when clicking on npc
|
||||
* Do specific action for NPC type (openshop, run scripts...)
|
||||
* Do specific action for NPC type (openshop, run scripts...)
|
||||
*------------------------------------------*/
|
||||
int npc_click(struct map_session_data* sd, struct npc_data* nd)
|
||||
{
|
||||
@ -1179,7 +1179,7 @@ int npc_scriptcont(struct map_session_data* sd, int id)
|
||||
nd?(char*)nd->name:"'Unknown NPC'", (int)id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if(id != fake_nd->bl.id) { // Not item script
|
||||
if ((npc_checknear(sd,map_id2bl(id))) == NULL){
|
||||
ShowWarning("npc_scriptcont: failed npc_checknear test.\n");
|
||||
@ -1218,7 +1218,7 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type)
|
||||
|
||||
if ((nd = npc_checknear(sd,map_id2bl(id))) == NULL)
|
||||
return 1;
|
||||
|
||||
|
||||
if (nd->subtype!=SHOP) {
|
||||
ShowError("no such shop npc : %d\n",id);
|
||||
if (sd->npc_id == id)
|
||||
@ -1459,7 +1459,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
|
||||
int nameid, amount, value;
|
||||
|
||||
// find this entry in the shop's sell list
|
||||
ARR_FIND( 0, nd->u.shop.count, j,
|
||||
ARR_FIND( 0, nd->u.shop.count, j,
|
||||
item_list[i*2+1] == nd->u.shop.shop_item[j].nameid || //Normal items
|
||||
item_list[i*2+1] == itemdb_viewid(nd->u.shop.shop_item[j].nameid) //item_avail replacement
|
||||
);
|
||||
@ -1515,11 +1515,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
|
||||
if( pc_inventoryblank(sd) < new_ )
|
||||
return 3; // Not enough space to store items
|
||||
|
||||
//Logs (S)hopping Zeny [Lupus]
|
||||
log_zeny(sd, LOG_TYPE_NPC, sd, -(int)z);
|
||||
//Logs
|
||||
|
||||
pc_payzeny(sd,(int)z);
|
||||
pc_payzeny(sd,(int)z,LOG_TYPE_NPC, NULL);
|
||||
|
||||
for( i = 0; i < n; ++i )
|
||||
{
|
||||
@ -1584,7 +1580,7 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short*
|
||||
snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1);
|
||||
script_cleararray_pc(sd, card_slot, (void*)0);
|
||||
}
|
||||
|
||||
|
||||
// save list of to be sold items
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
@ -1598,7 +1594,7 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short*
|
||||
script_setarray_pc(sd, "@sold_refine", i, (void*)(intptr_t)sd->status.inventory[idx].refine, &key_refine);
|
||||
script_setarray_pc(sd, "@sold_attribute", i, (void*)(intptr_t)sd->status.inventory[idx].attribute, &key_attribute);
|
||||
script_setarray_pc(sd, "@sold_identify", i, (void*)(intptr_t)sd->status.inventory[idx].identify, &key_identify);
|
||||
|
||||
|
||||
for( j = 0; j < MAX_SLOTS; j++ )
|
||||
{// store each of the cards from the equipment in the array
|
||||
snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1);
|
||||
@ -1691,11 +1687,7 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list)
|
||||
if( z > MAX_ZENY )
|
||||
z = MAX_ZENY;
|
||||
|
||||
//Logs (S)hopping Zeny [Lupus]
|
||||
log_zeny(sd, LOG_TYPE_NPC, sd, (int)z);
|
||||
//Logs
|
||||
|
||||
pc_getzeny(sd, (int)z);
|
||||
pc_getzeny(sd, (int)z, LOG_TYPE_NPC, NULL);
|
||||
|
||||
// custom merchant shop exp bonus
|
||||
if( battle_config.shop_exp > 0 && z > 0 && ( skill = pc_checkskill(sd,MC_OVERCHARGE) ) > 0)
|
||||
@ -1793,13 +1785,13 @@ int npc_unload(struct npc_data* nd, bool single) {
|
||||
if( nd->path && nd->path != npc_last_ref ) {
|
||||
npd = strdb_get(npc_path_db, nd->path);
|
||||
}
|
||||
|
||||
|
||||
if( npd && --npd->references == 0 ) {
|
||||
strdb_remove(npc_path_db, nd->path);/* remove from db */
|
||||
aFree(nd->path);/* remove now that no other instances exist */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( (nd->subtype == SHOP || nd->subtype == CASHSHOP) && nd->src_id == 0) //src check for duplicate shops [Orcao]
|
||||
aFree(nd->u.shop.shop_item);
|
||||
else if( nd->subtype == SCRIPT ) {
|
||||
@ -1809,7 +1801,7 @@ int npc_unload(struct npc_data* nd, bool single) {
|
||||
if( single )
|
||||
ev_db->foreach(ev_db,npc_unload_ev,nd->exname); //Clean up all events related
|
||||
|
||||
iter = mapit_geteachpc();
|
||||
iter = mapit_geteachpc();
|
||||
for( bl = (struct block_list*)mapit_first(iter); mapit_exists(iter); bl = (struct block_list*)mapit_next(iter) ) {
|
||||
struct map_session_data *sd = ((TBL_PC*)bl);
|
||||
if( sd && sd->npc_timer_id != INVALID_TIMER ) {
|
||||
@ -1823,13 +1815,13 @@ int npc_unload(struct npc_data* nd, bool single) {
|
||||
delete_timer(sd->npc_timer_id, npc_timerevent);
|
||||
sd->npc_timer_id = INVALID_TIMER;
|
||||
}
|
||||
}
|
||||
}
|
||||
mapit_free(iter);
|
||||
|
||||
if (nd->u.scr.timerid != INVALID_TIMER) {
|
||||
const struct TimerData *td = NULL;
|
||||
td = get_timer(nd->u.scr.timerid);
|
||||
if (td && td->data)
|
||||
if (td && td->data)
|
||||
ers_free(timer_event_ers, (void*)td->data);
|
||||
delete_timer(nd->u.scr.timerid, npc_timerevent);
|
||||
}
|
||||
@ -1988,20 +1980,20 @@ static void npc_parsename(struct npc_data* nd, const char* name, const char* sta
|
||||
ShowDebug("other npc in '%s' :\n display name '%s'\n unique name '%s'\n map=%s, x=%d, y=%d\n",dnd->path, dnd->name, dnd->exname, other_mapname, dnd->bl.x, dnd->bl.y);
|
||||
safestrncpy(nd->exname, newname, sizeof(nd->exname));
|
||||
}
|
||||
|
||||
|
||||
if( npc_last_path != filepath ) {
|
||||
struct npc_path_data * npd = NULL;
|
||||
|
||||
|
||||
if( !(npd = strdb_get(npc_path_db,filepath) ) ) {
|
||||
CREATE(npd, struct npc_path_data, 1);
|
||||
strdb_put(npc_path_db, filepath, npd);
|
||||
|
||||
|
||||
CREATE(npd->path, char, strlen(filepath)+1);
|
||||
safestrncpy(npd->path, filepath, strlen(filepath)+1);
|
||||
|
||||
|
||||
npd->references = 0;
|
||||
}
|
||||
|
||||
|
||||
nd->path = npd->path;
|
||||
npd->references++;
|
||||
|
||||
@ -2122,7 +2114,7 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const
|
||||
/// Parses a shop/cashshop npc.
|
||||
static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
|
||||
{
|
||||
//TODO: could be rewritten to NOT need this temp array [ultramage]
|
||||
//TODO: could be rewritten to NOT need this temp array [ultramage]
|
||||
#define MAX_SHOPITEM 100
|
||||
struct npc_item_list items[MAX_SHOPITEM];
|
||||
char *p;
|
||||
@ -2144,7 +2136,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
|
||||
ShowError("npc_parse_shop: Invalid shop definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
|
||||
return strchr(start,'\n');// skip and continue
|
||||
}
|
||||
|
||||
|
||||
m = map_mapname2mapid(mapname);
|
||||
}
|
||||
|
||||
@ -2464,17 +2456,17 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons
|
||||
if( runOnInit ) {
|
||||
char evname[EVENT_NAME_LENGTH];
|
||||
struct event_data *ev;
|
||||
|
||||
|
||||
snprintf(evname, ARRAYLENGTH(evname), "%s::OnInit", nd->exname);
|
||||
|
||||
|
||||
if( ( ev = (struct event_data*)strdb_get(ev_db, evname) ) ) {
|
||||
|
||||
|
||||
//Execute OnInit
|
||||
run_script(nd->u.scr.script,ev->pos,0,nd->bl.id);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
@ -2630,7 +2622,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
|
||||
|
||||
int npc_duplicate4instance(struct npc_data *snd, int m) {
|
||||
char newname[NAME_LENGTH];
|
||||
|
||||
|
||||
if( map[m].instance_id == 0 )
|
||||
return 1;
|
||||
|
||||
@ -2858,9 +2850,9 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
|
||||
// split atcmd parameters based on spaces
|
||||
i = 0;
|
||||
j = 0;
|
||||
|
||||
|
||||
temp = (char*)aMalloc(strlen(message) + 1);
|
||||
|
||||
|
||||
while( message[i] != '\0' ) {
|
||||
if( message[i] == ' ' && k < 127 ) {
|
||||
temp[j] = '\0';
|
||||
@ -3108,7 +3100,7 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con
|
||||
|
||||
if (w4 && !strcmpi(w4, "off"))
|
||||
state = 0; //Disable mapflag rather than enable it. [Skotlex]
|
||||
|
||||
|
||||
if (!strcmpi(w3, "nosave")) {
|
||||
char savemap[32];
|
||||
int savex, savey;
|
||||
@ -3556,7 +3548,7 @@ void npc_read_event_script(void)
|
||||
ShowWarning("npc_read_event_script: too many occurences of event '%s'!\n", config[i].event_name);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if( (p=strchr(p,':')) && p && strcmpi(name,p)==0 )
|
||||
{
|
||||
script_event[i].event[count] = ed;
|
||||
@ -3576,14 +3568,14 @@ void npc_read_event_script(void)
|
||||
|
||||
void npc_clear_pathlist(void) {
|
||||
struct npc_path_data *npd = NULL;
|
||||
DBIterator *path_list = db_iterator(npc_path_db);
|
||||
|
||||
DBIterator *path_list = db_iterator(npc_path_db);
|
||||
|
||||
/* free all npc_path_data filepaths */
|
||||
for( npd = dbi_first(path_list); dbi_exists(path_list); npd = dbi_next(path_list) ) {
|
||||
if( npd->path )
|
||||
aFree(npd->path);
|
||||
}
|
||||
|
||||
|
||||
dbi_destroy(path_list);
|
||||
}
|
||||
|
||||
@ -3596,12 +3588,12 @@ int npc_reload(void) {
|
||||
struct block_list* bl;
|
||||
|
||||
npc_clear_pathlist();
|
||||
|
||||
|
||||
db_clear(npc_path_db);
|
||||
|
||||
db_clear(npcname_db);
|
||||
db_clear(ev_db);
|
||||
|
||||
|
||||
//Remove all npcs/mobs. [Skotlex]
|
||||
|
||||
iter = mapit_geteachiddb();
|
||||
@ -3662,20 +3654,20 @@ int npc_reload(void) {
|
||||
npc_id - npc_new_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
|
||||
|
||||
do_final_instance();
|
||||
|
||||
|
||||
for( i = 0; i < ARRAYLENGTH(instance); ++i )
|
||||
instance_init(instance[i].instance_id);
|
||||
|
||||
//Re-read the NPC Script Events cache.
|
||||
npc_read_event_script();
|
||||
|
||||
|
||||
/* refresh guild castle flags on both woe setups */
|
||||
npc_event_doall("OnAgitInit");
|
||||
npc_event_doall("OnAgitInit2");
|
||||
|
||||
|
||||
//Execute the OnInit event for freshly loaded npcs. [Skotlex]
|
||||
ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n",npc_event_doall("OnInit"));
|
||||
|
||||
|
||||
// Execute rest of the startup events if connected to char-server. [Lance]
|
||||
if(!CheckForCharServer()){
|
||||
ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInit"));
|
||||
@ -3689,7 +3681,7 @@ bool npc_unloadfile( const char* path ) {
|
||||
DBIterator * iter = db_iterator(npcname_db);
|
||||
struct npc_data* nd = NULL;
|
||||
bool found = false;
|
||||
|
||||
|
||||
for( nd = dbi_first(iter); dbi_exists(iter); nd = dbi_next(iter) ) {
|
||||
if( nd->path && strcasecmp(nd->path,path) == 0 ) {
|
||||
found = true;
|
||||
@ -3697,12 +3689,12 @@ bool npc_unloadfile( const char* path ) {
|
||||
npc_unload(nd, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dbi_destroy(iter);
|
||||
|
||||
|
||||
if( found ) /* refresh event cache */
|
||||
npc_read_event_script();
|
||||
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
@ -3712,7 +3704,7 @@ void do_clear_npc(void) {
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Destructor
|
||||
* Destructor
|
||||
*------------------------------------------*/
|
||||
int do_final_npc(void) {
|
||||
npc_clear_pathlist();
|
||||
@ -3770,15 +3762,15 @@ int do_init_npc(void)
|
||||
//Stock view data for normal npcs.
|
||||
memset(&npc_viewdb, 0, sizeof(npc_viewdb));
|
||||
npc_viewdb[0].class_ = INVISIBLE_CLASS; //Invisible class is stored here.
|
||||
for( i = 1; i < MAX_NPC_CLASS; i++ )
|
||||
for( i = 1; i < MAX_NPC_CLASS; i++ )
|
||||
npc_viewdb[i].class_ = i;
|
||||
|
||||
ev_db = strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA),2*NAME_LENGTH+2+1);
|
||||
npcname_db = strdb_alloc(DB_OPT_BASE,NAME_LENGTH);
|
||||
npc_path_db = strdb_alloc(DB_OPT_BASE|DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,80);
|
||||
|
||||
|
||||
timer_event_ers = ers_new(sizeof(struct timer_event_data),"clif.c::timer_event_ers",ERS_OPT_NONE);
|
||||
|
||||
|
||||
// process all npc files
|
||||
ShowStatus("Loading NPCs...\r");
|
||||
for( file = npc_src_files; file != NULL; file = file->next ) {
|
||||
@ -3822,6 +3814,6 @@ int do_init_npc(void)
|
||||
fake_nd->u.scr.timerid = INVALID_TIMER;
|
||||
map_addiddb(&fake_nd->bl);
|
||||
// End of initialization
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ static unsigned long party_booking_nextid = 1;
|
||||
int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data);
|
||||
|
||||
/*==========================================
|
||||
* Fills the given party_member structure according to the sd provided.
|
||||
* Fills the given party_member structure according to the sd provided.
|
||||
* Used when creating/adding people to a party. [Skotlex]
|
||||
*------------------------------------------*/
|
||||
static void party_fill_member(struct party_member* member, struct map_session_data* sd, unsigned int leader)
|
||||
@ -254,7 +254,7 @@ int party_recv_info(struct party* sp, int char_id)
|
||||
int added_count = 0;
|
||||
int i;
|
||||
int member_id;
|
||||
|
||||
|
||||
nullpo_ret(sp);
|
||||
|
||||
p = (struct party_data*)idb_get(party_db, sp->party_id);
|
||||
@ -336,7 +336,7 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
|
||||
{
|
||||
struct party_data *p;
|
||||
int i;
|
||||
|
||||
|
||||
nullpo_ret(sd);
|
||||
|
||||
if( ( p = party_search(sd->status.party_id) ) == NULL )
|
||||
@ -357,7 +357,7 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
|
||||
clif_party_inviteack(sd, (tsd?tsd->status.name:""), 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// confirm whether the account has the ability to invite before checking the player
|
||||
if( !pc_has_permission(sd, PC_PERM_PARTY) || (tsd && !pc_has_permission(tsd, PC_PERM_PARTY)) ) {
|
||||
clif_displaymessage(sd->fd, msg_txt(81)); // "Your GM level doesn't authorize you to preform this action on the specified player."
|
||||
@ -386,7 +386,7 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
|
||||
clif_party_inviteack(sd,tsd->status.name,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
tsd->party_invite=sd->status.party_id;
|
||||
tsd->party_invite_account=sd->status.account_id;
|
||||
|
||||
@ -588,7 +588,7 @@ int party_broken(int party_id)
|
||||
p = party_search(party_id);
|
||||
if( p == NULL )
|
||||
return 0;
|
||||
|
||||
|
||||
if( p->instance_id )
|
||||
{
|
||||
instance[p->instance_id].party_id = 0;
|
||||
@ -650,7 +650,7 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts
|
||||
}
|
||||
|
||||
if( map[sd->bl.m].flag.partylock )
|
||||
{
|
||||
{
|
||||
clif_displaymessage(sd->fd, msg_txt(287));
|
||||
return false;
|
||||
}
|
||||
@ -714,7 +714,7 @@ int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short m
|
||||
m->lv = lv;
|
||||
//Check if they still exist on this map server
|
||||
p->data[i].sd = party_sd_check(party_id, account_id, char_id);
|
||||
|
||||
|
||||
clif_party_info(p,NULL);
|
||||
return 0;
|
||||
}
|
||||
@ -741,7 +741,7 @@ void party_send_movemap(struct map_session_data *sd)
|
||||
|
||||
if (sd->fd) { // synchronize minimap positions with the rest of the party
|
||||
for(i=0; i < MAX_PARTY; i++) {
|
||||
if (p->data[i].sd &&
|
||||
if (p->data[i].sd &&
|
||||
p->data[i].sd != sd &&
|
||||
p->data[i].sd->bl.m == sd->bl.m)
|
||||
{
|
||||
@ -765,7 +765,7 @@ int party_send_logout(struct map_session_data *sd)
|
||||
|
||||
if(!sd->status.party_id)
|
||||
return 0;
|
||||
|
||||
|
||||
intif_party_changemap(sd,0);
|
||||
p=party_search(sd->status.party_id);
|
||||
if(!p) return 0;
|
||||
@ -775,7 +775,7 @@ int party_send_logout(struct map_session_data *sd)
|
||||
memset(&p->data[i], 0, sizeof(p->data[0]));
|
||||
else
|
||||
ShowError("party_send_logout: Failed to locate member %d:%d in party %d!\n", sd->status.account_id, sd->status.char_id, p->party.party_id);
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -823,7 +823,7 @@ int party_skill_check(struct map_session_data *sd, int party_id, int skillid, in
|
||||
default:
|
||||
return 0; //Unknown case?
|
||||
}
|
||||
|
||||
|
||||
for(i=0;i<MAX_PARTY;i++){
|
||||
if ((p_sd = p->data[i].sd) == NULL)
|
||||
continue;
|
||||
@ -949,7 +949,7 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b
|
||||
pc_gainexp(sd[i], src, base_exp, job_exp, false);
|
||||
|
||||
if (zeny) // zeny from mobs [Valaris]
|
||||
pc_getzeny(sd[i],zeny);
|
||||
pc_getzeny(sd[i],zeny,LOG_TYPE_OTHER,NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -973,7 +973,7 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i
|
||||
|
||||
if( (psd = p->data[i].sd) == NULL || sd->bl.m != psd->bl.m || pc_isdead(psd) || (battle_config.idle_no_share && pc_isidle(psd)) )
|
||||
continue;
|
||||
|
||||
|
||||
if (pc_additem(psd,item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER))
|
||||
continue; //Chosen char can't pick up loot.
|
||||
|
||||
@ -1008,7 +1008,7 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i
|
||||
}
|
||||
}
|
||||
|
||||
if (!target) {
|
||||
if (!target) {
|
||||
target = sd; //Give it to the char that picked it up
|
||||
if ((i=pc_additem(sd,item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER)))
|
||||
return i;
|
||||
@ -1036,7 +1036,7 @@ int party_sub_count(struct block_list *bl, va_list ap)
|
||||
|
||||
if (sd->state.autotrade)
|
||||
return 0;
|
||||
|
||||
|
||||
if (battle_config.idle_no_share && pc_isidle(sd))
|
||||
return 0;
|
||||
|
||||
@ -1052,9 +1052,9 @@ int party_foreachsamemap(int (*func)(struct block_list*,va_list),struct map_sess
|
||||
struct block_list *list[MAX_PARTY];
|
||||
int blockcount=0;
|
||||
int total = 0; //Return value.
|
||||
|
||||
|
||||
nullpo_ret(sd);
|
||||
|
||||
|
||||
if((p=party_search(sd->status.party_id))==NULL)
|
||||
return 0;
|
||||
|
||||
@ -1073,11 +1073,11 @@ int party_foreachsamemap(int (*func)(struct block_list*,va_list),struct map_sess
|
||||
(psd->bl.x<x0 || psd->bl.y<y0 ||
|
||||
psd->bl.x>x1 || psd->bl.y>y1 ) )
|
||||
continue;
|
||||
list[blockcount++]=&psd->bl;
|
||||
list[blockcount++]=&psd->bl;
|
||||
}
|
||||
|
||||
map_freeblock_lock();
|
||||
|
||||
|
||||
for(i=0;i<blockcount;i++)
|
||||
{
|
||||
va_list ap;
|
||||
@ -1120,7 +1120,7 @@ void party_booking_register(struct map_session_data *sd, short level, short mapi
|
||||
clif_PartyBookingRegisterAck(sd, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
memcpy(pb_ad->charname,sd->status.name,NAME_LENGTH);
|
||||
pb_ad->starttime = (int)time(NULL);
|
||||
pb_ad->p_detail.level = level;
|
||||
@ -1141,10 +1141,10 @@ void party_booking_update(struct map_session_data *sd, short* job)
|
||||
struct party_booking_ad_info *pb_ad;
|
||||
|
||||
pb_ad = (struct party_booking_ad_info*)idb_get(party_booking_db, sd->status.char_id);
|
||||
|
||||
|
||||
if( pb_ad == NULL )
|
||||
return;
|
||||
|
||||
|
||||
pb_ad->starttime = (int)time(NULL);// Update time.
|
||||
|
||||
for(i=0;i<PARTY_BOOKING_JOBS;i++)
|
||||
@ -1162,9 +1162,9 @@ void party_booking_search(struct map_session_data *sd, short level, short mapid,
|
||||
struct party_booking_ad_info* result_list[PARTY_BOOKING_RESULTS];
|
||||
bool more_result = false;
|
||||
DBIterator* iter = db_iterator(party_booking_db);
|
||||
|
||||
|
||||
memset(result_list, 0, sizeof(result_list));
|
||||
|
||||
|
||||
for( pb_ad = dbi_first(iter); dbi_exists(iter); pb_ad = dbi_next(iter) )
|
||||
{
|
||||
if (pb_ad->index < lastindex || (level && (pb_ad->p_detail.level < level-15 || pb_ad->p_detail.level > level)))
|
||||
|
26
src/map/pc.c
26
src/map/pc.c
@ -171,7 +171,7 @@ static int pc_spiritball_timer(int tid, unsigned int tick, int id, intptr_t data
|
||||
memmove(sd->spirit_timer+i, sd->spirit_timer+i+1, (sd->spiritball-i)*sizeof(int));
|
||||
sd->spirit_timer[sd->spiritball] = INVALID_TIMER;
|
||||
|
||||
clif_spiritball(sd);
|
||||
clif_spiritball(&sd->bl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -206,7 +206,7 @@ int pc_addspiritball(struct map_session_data *sd,int interval,int max)
|
||||
if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
|
||||
clif_millenniumshield(sd,sd->spiritball);
|
||||
else
|
||||
clif_spiritball(sd);
|
||||
clif_spiritball(&sd->bl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -245,7 +245,7 @@ int pc_delspiritball(struct map_session_data *sd,int count,int type)
|
||||
if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
|
||||
clif_millenniumshield(sd,sd->spiritball);
|
||||
else
|
||||
clif_spiritball(sd);
|
||||
clif_spiritball(&sd->bl);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -3586,7 +3586,7 @@ int pc_inventoryblank(struct map_session_data *sd)
|
||||
/*==========================================
|
||||
* attempts to remove zeny from player (sd)
|
||||
*------------------------------------------*/
|
||||
int pc_payzeny(struct map_session_data *sd,int zeny)
|
||||
int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd)
|
||||
{
|
||||
nullpo_ret(sd);
|
||||
|
||||
@ -3602,6 +3602,8 @@ int pc_payzeny(struct map_session_data *sd,int zeny)
|
||||
sd->status.zeny -= zeny;
|
||||
clif_updatestatus(sd,SP_ZENY);
|
||||
|
||||
if(!tsd) tsd = sd;
|
||||
log_zeny(sd, type, tsd, -zeny);
|
||||
if( zeny > 0 && sd->state.showzeny ) {
|
||||
char output[255];
|
||||
sprintf(output, "Removed %dz.", zeny);
|
||||
@ -3700,8 +3702,9 @@ void pc_getcash(struct map_session_data *sd, int cash, int points)
|
||||
|
||||
/*==========================================
|
||||
* Attempts to give zeny to player (sd)
|
||||
* tsd (optional) from who for log (if null take sd)
|
||||
*------------------------------------------*/
|
||||
int pc_getzeny(struct map_session_data *sd,int zeny)
|
||||
int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd)
|
||||
{
|
||||
nullpo_ret(sd);
|
||||
|
||||
@ -3717,6 +3720,8 @@ int pc_getzeny(struct map_session_data *sd,int zeny)
|
||||
sd->status.zeny += zeny;
|
||||
clif_updatestatus(sd,SP_ZENY);
|
||||
|
||||
if(!sd) tsd = sd;
|
||||
log_zeny(sd, type, tsd, zeny);
|
||||
if( zeny > 0 && sd->state.showzeny ) {
|
||||
char output[255];
|
||||
sprintf(output, "Gained %dz.", zeny);
|
||||
@ -4569,8 +4574,7 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *target)
|
||||
{
|
||||
int amount = md->level*10 + rnd()%100;
|
||||
|
||||
log_zeny(sd, LOG_TYPE_STEAL, sd, amount);
|
||||
pc_getzeny(sd, amount);
|
||||
pc_getzeny(sd, amount, LOG_TYPE_STEAL, NULL);
|
||||
md->state.steal_coin_flag = 1;
|
||||
return 1;
|
||||
}
|
||||
@ -6449,8 +6453,10 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
|
||||
pet_unlocktarget(sd->pd);
|
||||
}
|
||||
|
||||
if( sd->status.hom_id > 0 && battle_config.homunculus_auto_vapor )
|
||||
merc_hom_vaporize(sd, 0);
|
||||
if (sd->status.hom_id > 0){
|
||||
if(battle_config.homunculus_auto_vapor && sd->hd && !sd->hd->sc.data[SC_LIGHT_OF_REGENE])
|
||||
merc_hom_vaporize(sd, 0);
|
||||
}
|
||||
|
||||
if( sd->md )
|
||||
merc_delete(sd->md, 3); // Your mercenary soldier has ran away.
|
||||
@ -6646,7 +6652,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
|
||||
{
|
||||
base_penalty = (unsigned int)((double)sd->status.zeny * (double)battle_config.zeny_penalty / 10000.);
|
||||
if(base_penalty)
|
||||
pc_payzeny(sd, base_penalty);
|
||||
pc_payzeny(sd, base_penalty, LOG_TYPE_OTHER, NULL); //@TODO that type suck
|
||||
}
|
||||
}
|
||||
|
||||
|
24
src/map/pc.h
24
src/map/pc.h
@ -74,7 +74,7 @@ struct s_addeffectonskill {
|
||||
unsigned char target;
|
||||
};
|
||||
|
||||
struct s_add_drop {
|
||||
struct s_add_drop {
|
||||
short id, group;
|
||||
int race, rate;
|
||||
};
|
||||
@ -165,7 +165,7 @@ struct map_session_data {
|
||||
int packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 ... 18
|
||||
struct mmo_charstatus status;
|
||||
struct registry save_reg;
|
||||
|
||||
|
||||
struct item_data* inventory_data[MAX_INVENTORY]; // direct pointers to itemdb entries (faster than doing item_id lookups)
|
||||
short equip_index[14];
|
||||
unsigned int weight,max_weight;
|
||||
@ -216,7 +216,7 @@ struct map_session_data {
|
||||
unsigned int cansendmail_tick; // [Mail System Flood Protection]
|
||||
unsigned int ks_floodprotect_tick; // [Kill Steal Protection]
|
||||
unsigned int bloodylust_tick; // bloodylust player timer [out/in re full-heal protection]
|
||||
|
||||
|
||||
struct {
|
||||
short nameid;
|
||||
unsigned int tick;
|
||||
@ -226,7 +226,7 @@ struct map_session_data {
|
||||
short disguise; // [Valaris]
|
||||
|
||||
struct weapon_data right_weapon, left_weapon;
|
||||
|
||||
|
||||
// here start arrays to be globally zeroed at the beginning of status_calc_pc()
|
||||
int param_bonus[6],param_equip[6]; //Stores card/equipment bonuses.
|
||||
int subele[ELE_MAX];
|
||||
@ -350,7 +350,7 @@ struct map_session_data {
|
||||
struct script_regstr *regstr;
|
||||
|
||||
int trade_partner;
|
||||
struct {
|
||||
struct {
|
||||
struct {
|
||||
short index, amount;
|
||||
} item[10];
|
||||
@ -464,7 +464,7 @@ struct map_session_data {
|
||||
unsigned short *id;/* array of combo ids */
|
||||
unsigned char count;
|
||||
} combos;
|
||||
|
||||
|
||||
/**
|
||||
* Guarantees your friend request is legit (for bugreport:4629)
|
||||
**/
|
||||
@ -533,7 +533,7 @@ enum ammo_type {
|
||||
|
||||
//Equip position constants
|
||||
enum equip_pos {
|
||||
EQP_HEAD_LOW = 0x0001,
|
||||
EQP_HEAD_LOW = 0x0001,
|
||||
EQP_HEAD_MID = 0x0200, //512
|
||||
EQP_HEAD_TOP = 0x0100, //256
|
||||
EQP_HAND_R = 0x0002,
|
||||
@ -559,7 +559,7 @@ enum equip_pos {
|
||||
/// Equip positions that use a visible sprite
|
||||
#if PACKETVER < 20110111
|
||||
#define EQP_VISIBLE EQP_HELM
|
||||
#else
|
||||
#else
|
||||
#define EQP_VISIBLE (EQP_HELM|EQP_GARMENT|EQP_COSTUME)
|
||||
#endif
|
||||
|
||||
@ -608,7 +608,7 @@ enum equip_index {
|
||||
#define pc_is50overweight(sd) ( (sd)->weight*100 >= (sd)->max_weight*battle_config.natural_heal_weight_rate )
|
||||
#define pc_is90overweight(sd) ( (sd)->weight*10 >= (sd)->max_weight*9 )
|
||||
#define pc_maxparameter(sd) ( ((((sd)->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO) || (sd)->class_&JOBL_THIRD ? ((sd)->class_&JOBL_BABY ? battle_config.max_baby_third_parameter : battle_config.max_third_parameter) : ((sd)->class_&JOBL_BABY ? battle_config.max_baby_parameter : battle_config.max_parameter)) )
|
||||
/**
|
||||
/**
|
||||
* Ranger
|
||||
**/
|
||||
#define pc_iswug(sd) ( (sd)->sc.option&OPTION_WUG )
|
||||
@ -649,7 +649,7 @@ enum equip_index {
|
||||
#define pc_leftside_atk(sd) ((sd)->battle_status.batk + (sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk)
|
||||
#define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2)
|
||||
#define pc_leftside_def(sd) ((sd)->battle_status.def)
|
||||
#define pc_rightside_def(sd) ((sd)->battle_status.def2)
|
||||
#define pc_rightside_def(sd) ((sd)->battle_status.def2)
|
||||
#define pc_leftside_mdef(sd) ((sd)->battle_status.mdef)
|
||||
#define pc_rightside_mdef(sd) ( (sd)->battle_status.mdef2 - ((sd)->battle_status.vit>>1) )
|
||||
#endif
|
||||
@ -695,9 +695,9 @@ int pc_memo(struct map_session_data* sd, int pos);
|
||||
int pc_checkadditem(struct map_session_data*,int,int);
|
||||
int pc_inventoryblank(struct map_session_data*);
|
||||
int pc_search_inventory(struct map_session_data *sd,int item_id);
|
||||
int pc_payzeny(struct map_session_data*,int);
|
||||
int pc_payzeny(struct map_session_data*,int, enum e_log_pick_type type, struct map_session_data*);
|
||||
int pc_additem(struct map_session_data*,struct item*,int,e_log_pick_type);
|
||||
int pc_getzeny(struct map_session_data*,int);
|
||||
int pc_getzeny(struct map_session_data*,int, enum e_log_pick_type, struct map_session_data*);
|
||||
int pc_delitem(struct map_session_data*,int,int,int,short,e_log_pick_type);
|
||||
|
||||
// Special Shop System
|
||||
|
830
src/map/script.c
830
src/map/script.c
File diff suppressed because it is too large
Load Diff
222
src/map/skill.c
222
src/map/skill.c
@ -615,6 +615,22 @@ int skillnotok_hom(int skillid, struct homun_data *hd)
|
||||
|
||||
if (hd->blockskill[i] > 0)
|
||||
return 1;
|
||||
switch(skillid){
|
||||
case MH_LIGHT_OF_REGENE:
|
||||
if(hd->homunculus.intimacy <= 750) //if not cordial
|
||||
return 1;
|
||||
break;
|
||||
case MH_OVERED_BOOST:
|
||||
if(hd->homunculus.hunger <= 1) //if we starving
|
||||
return 1;
|
||||
case MH_GOLDENE_FERSE: //can be used with angriff
|
||||
if(hd->sc.data[SC_ANGRIFFS_MODUS])
|
||||
return 1;
|
||||
case MH_ANGRIFFS_MODUS:
|
||||
if(hd->sc.data[SC_GOLDENE_FERSE])
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
|
||||
//Use master's criteria.
|
||||
return skillnotok(skillid, hd->master);
|
||||
@ -796,17 +812,18 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
|
||||
sc_start(src,SC_COMBO, 15, TK_TURNKICK,
|
||||
(2000 - 4*sstatus->agi - 2*sstatus->dex)))
|
||||
; //Stance triggered
|
||||
else if(sc->data[SC_READYCOUNTER])
|
||||
{ //additional chance from SG_FRIEND [Komurka]
|
||||
else if (sc->data[SC_READYCOUNTER]) { //additional chance from SG_FRIEND [Komurka]
|
||||
rate = 20;
|
||||
if (sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == TK_COUNTER) {
|
||||
rate += rate*sc->data[SC_SKILLRATE_UP]->val2/100;
|
||||
status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER);
|
||||
}
|
||||
sc_start4(src,SC_COMBO, rate, TK_COUNTER, bl->id,0,0,
|
||||
sc_start2(src, SC_COMBO, rate, TK_COUNTER, bl->id,
|
||||
(2000 - 4*sstatus->agi - 2*sstatus->dex));
|
||||
}
|
||||
}
|
||||
if(sc && sc->data[SC_PYROCLASTIC] && (rnd() % 1000 <= sstatus->luk * 10 / 3 + 1) )
|
||||
skill_castend_pos2(src, bl->x, bl->y, BS_HAMMERFALL,sc->data[SC_PYROCLASTIC]->val1, tick, 0);
|
||||
}
|
||||
|
||||
if (sc) {
|
||||
@ -1350,18 +1367,21 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
|
||||
case EL_TYPOON_MIS:
|
||||
sc_start(bl,SC_SILENCE,10*skilllv,skilllv,skill_get_time(skillid,skilllv));
|
||||
break;
|
||||
case MH_LAVA_SLIDE:
|
||||
sc_start4(bl,SC_BURNING,10*skilllv,skilllv,1000,src->id,0,skill_get_time(skillid,skilllv));
|
||||
break;
|
||||
case MH_STAHL_HORN:
|
||||
sc_start(bl,SC_STUN,(20 + 4 * skilllv),skilllv,skill_get_time2(skillid,skilllv));
|
||||
break;
|
||||
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;
|
||||
case MH_LAVA_SLIDE:
|
||||
if (tsc && !tsc->data[SC_BURNING]) sc_start4(bl, SC_BURNING, 10 * skilllv, skilllv, 1000, src->id, 0, skill_get_time(skillid, skilllv));
|
||||
break;
|
||||
case MH_STAHL_HORN:
|
||||
sc_start(bl, SC_STUN, (20 + 4 * (skilllv-1)), skilllv, skill_get_time(skillid, skilllv));
|
||||
break;
|
||||
case MH_NEEDLE_OF_PARALYZE:
|
||||
sc_start(bl, SC_PARALYSIS, 40 + (5*skilllv), skilllv, skill_get_time(skillid, skilllv));
|
||||
break;
|
||||
}
|
||||
|
||||
if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai)
|
||||
@ -2787,10 +2807,11 @@ static int skill_check_unit_range_sub (struct block_list *bl, va_list ap)
|
||||
g_skillid = unit->group->skill_id;
|
||||
|
||||
switch (skillid) {
|
||||
case MH_STEINWAND:
|
||||
case MG_SAFETYWALL:
|
||||
case AL_PNEUMA:
|
||||
case SC_MAELSTROM:
|
||||
if(g_skillid != MG_SAFETYWALL && g_skillid != AL_PNEUMA && g_skillid != SC_MAELSTROM)
|
||||
if(g_skillid != MH_STEINWAND && g_skillid != MG_SAFETYWALL && g_skillid != AL_PNEUMA && g_skillid != SC_MAELSTROM)
|
||||
return 0;
|
||||
break;
|
||||
case AL_WARP:
|
||||
@ -3483,7 +3504,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
|
||||
case WM_SEVERE_RAINSTORM_MELEE:
|
||||
case WM_GREAT_ECHO:
|
||||
case GN_SLINGITEM_RANGEMELEEATK:
|
||||
case MH_STAHL_HORN:
|
||||
case KO_JYUMONJIKIRI:
|
||||
case KO_SETSUDAN:
|
||||
case KO_KAIHOU:
|
||||
@ -3720,7 +3740,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
|
||||
case SO_VARETYR_SPEAR:
|
||||
case GN_CART_TORNADO:
|
||||
case GN_CARTCANNON:
|
||||
case MH_LAVA_SLIDE:
|
||||
case KO_HAPPOKUNAI:
|
||||
case KO_HUUMARANKA:
|
||||
case KO_MUCHANAGE:
|
||||
@ -4528,6 +4547,21 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
|
||||
break;
|
||||
|
||||
|
||||
//recursive homon skill
|
||||
case MH_MAGMA_FLOW:
|
||||
case MH_XENO_SLASHER:
|
||||
case MH_HEILIGE_STANGE:
|
||||
if(flag & 1)
|
||||
skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag);
|
||||
else {
|
||||
map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill_castend_damage_id);
|
||||
}
|
||||
break;
|
||||
case MH_STAHL_HORN:
|
||||
case MH_NEEDLE_OF_PARALYZE:
|
||||
skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag);
|
||||
break;
|
||||
|
||||
case 0:/* no skill - basic/normal attack */
|
||||
if(sd) {
|
||||
if (flag & 3){
|
||||
@ -4545,11 +4579,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
|
||||
break;
|
||||
|
||||
default:
|
||||
if( skillid >= HM_SKILLBASE && skillid <= HM_SKILLBASE + MAX_HOMUNSKILL ) {
|
||||
if( src->type == BL_HOM && ((TBL_HOM*)src)->master->fd )
|
||||
clif_colormes(((TBL_HOM*)src)->master, COLOR_RED, "This skill is not yet supported");
|
||||
} else /* temporary until all the homun-s skills are supported otherwise console would fill up with pointless warnings */
|
||||
ShowWarning("skill_castend_damage_id: Unknown skill used:%d\n",skillid);
|
||||
ShowWarning("skill_castend_damage_id: Unknown skill used:%d\n",skillid);
|
||||
clif_skill_damage(src, bl, tick, status_get_amotion(src), tstatus->dmotion,
|
||||
0, abs(skill_get_num(skillid, skilllv)),
|
||||
skillid, skilllv, skill_get_hit(skillid));
|
||||
@ -4660,6 +4690,18 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
break;
|
||||
case NPC_SMOKING: //Since it is a self skill, this one ends here rather than in damage_id. [Skotlex]
|
||||
return skill_castend_damage_id (src, bl, skillid, skilllv, tick, flag);
|
||||
case MH_STEINWAND: {
|
||||
struct block_list *s_src = battle_get_master(src);
|
||||
short ret;
|
||||
if(!skill_check_unit_range(src, src->x, src->y, skillid, skilllv)) //prevent reiteration
|
||||
ret = skill_castend_pos2(src,src->x,src->y,skillid,skilllv,tick,flag); //cast on homon
|
||||
if(s_src && !skill_check_unit_range(s_src, s_src->x, s_src->y, skillid, skilllv))
|
||||
ret |= skill_castend_pos2(s_src,s_src->x,s_src->y,skillid,skilllv,tick,flag); //cast on master
|
||||
if (hd)
|
||||
skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv));
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//Skill is actually ground placed.
|
||||
if (src == bl && skill_get_unit_id(skillid,0))
|
||||
@ -4961,7 +5003,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
break;
|
||||
case SA_FORTUNE:
|
||||
clif_skill_nodamage(src,bl,skillid,skilllv,1);
|
||||
if(sd) pc_getzeny(sd,status_get_lv(bl)*100);
|
||||
if(sd) pc_getzeny(sd,status_get_lv(bl)*100,LOG_TYPE_OTHER,NULL);
|
||||
break;
|
||||
case SA_TAMINGMONSTER:
|
||||
clif_skill_nodamage(src,bl,skillid,skilllv,1);
|
||||
@ -7213,12 +7255,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0);
|
||||
}
|
||||
break;
|
||||
case MH_STAHL_HORN:
|
||||
if (sd) {
|
||||
if( skillid == MH_GOLDENE_FERSE )
|
||||
clif_skill_fail(sd,skillid,USESKILL_FAIL_CONDITION,0);
|
||||
}
|
||||
break;
|
||||
|
||||
case HAMI_CASTLE: //[orn]
|
||||
if(rnd()%100 < 20*skilllv && src != bl)
|
||||
{
|
||||
@ -7370,7 +7407,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
break;
|
||||
case RK_IGNITIONBREAK:
|
||||
case LG_EARTHDRIVE:
|
||||
case MH_LAVA_SLIDE:
|
||||
clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6);
|
||||
i = skill_get_splash(skillid,skilllv);
|
||||
if( skillid == LG_EARTHDRIVE ) {
|
||||
@ -8830,12 +8866,98 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_nodamage_id);
|
||||
}
|
||||
break;
|
||||
|
||||
case MH_SILENT_BREEZE: {
|
||||
struct status_change *ssc = status_get_sc(src);
|
||||
struct block_list *m_bl = battle_get_master(src);
|
||||
const enum sc_type scs[] = {
|
||||
SC_MANDRAGORA, SC_HARMONIZE, SC_DEEPSLEEP, SC_VOICEOFSIREN, SC_SLEEP, SC_CONFUSION, SC_HALLUCINATION
|
||||
};
|
||||
int heal;
|
||||
if(tsc){
|
||||
for (i = 0; i < ARRAYLENGTH(scs); i++) {
|
||||
if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER);
|
||||
}
|
||||
if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target
|
||||
status_change_start(bl, SC_SILENCE, 100, skilllv, 0,0,0, skill_get_time(skillid, skilllv),1|2|8);
|
||||
}
|
||||
heal = status_get_matk_min(src)*4;
|
||||
status_heal(bl, heal, 0, 7);
|
||||
|
||||
//now inflict silence on everyone
|
||||
if(ssc && !ssc->data[SC_SILENCE]) //put inavoidable silence on homun
|
||||
status_change_start(src, SC_SILENCE, 100, skilllv, 0,0,0, skill_get_time(skillid, skilllv),1|2|8);
|
||||
if(m_bl){
|
||||
struct status_change *msc = status_get_sc(m_bl);
|
||||
if(msc && !msc->data[SC_SILENCE]) //put inavoidable silence on master
|
||||
status_change_start(m_bl, SC_SILENCE, 100, skilllv, 0,0,0, skill_get_time(skillid, skilllv),1|2|8);
|
||||
}
|
||||
if (hd)
|
||||
skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv));
|
||||
}
|
||||
break;
|
||||
case MH_OVERED_BOOST:
|
||||
if (hd){
|
||||
struct block_list *s_bl = battle_get_master(src);
|
||||
if(hd->homunculus.hunger>50) //reduce hunger
|
||||
hd->homunculus.hunger = hd->homunculus.hunger/2;
|
||||
else
|
||||
hd->homunculus.hunger = min(1,hd->homunculus.hunger);
|
||||
if(s_bl && s_bl->type==BL_PC){
|
||||
status_set_sp(s_bl,status_get_max_sp(s_bl)/2,0); //master drain 50% sp
|
||||
clif_send_homdata(((TBL_PC *)s_bl), SP_HUNGRY, hd->homunculus.hunger); //refresh hunger info
|
||||
sc_start(s_bl, type, 100, skilllv, skill_get_time(skillid, skilllv)); //gene bonus
|
||||
}
|
||||
sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv));
|
||||
skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv));
|
||||
}
|
||||
break;
|
||||
case MH_GRANITIC_ARMOR:
|
||||
case MH_PYROCLASTIC: {
|
||||
struct block_list *s_bl = battle_get_master(src);
|
||||
if(s_bl) sc_start2(s_bl, type, 100, skilllv, hd->homunculus.level, skill_get_time(skillid, skilllv)); //start on master
|
||||
sc_start2(bl, type, 100, skilllv, hd->homunculus.level, skill_get_time(skillid, skilllv));
|
||||
if (hd) skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv));
|
||||
}
|
||||
break;
|
||||
|
||||
case MH_LIGHT_OF_REGENE:
|
||||
if(hd){
|
||||
hd->homunculus.intimacy = 251; //change to neutral (can't be cast if < 750)
|
||||
if(sd) clif_send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy); //refresh intimacy info
|
||||
}
|
||||
//don't break need to start status and start block timer
|
||||
case MH_STYLE_CHANGE:
|
||||
case MH_MAGMA_FLOW:
|
||||
case MH_PAIN_KILLER:
|
||||
sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv));
|
||||
if (hd)
|
||||
skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv));
|
||||
break;
|
||||
case MH_SUMMON_LEGION:
|
||||
{
|
||||
int summons[5] = {1004, 1303, 1303, 1994, 1994};
|
||||
int qty[5] = {3 , 3 , 4 , 4 , 5};
|
||||
struct mob_data *md;
|
||||
int i;
|
||||
|
||||
for(i=0; i<qty[skilllv - 1]; i++){ //easy way
|
||||
md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), summons[skilllv - 1], "", SZ_SMALL, AI_ATTACK);
|
||||
if (md) {
|
||||
md->master_id = src->id;
|
||||
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); //Now it is ready for spawning.
|
||||
sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_ASSIST, 0, 60000);
|
||||
}
|
||||
}
|
||||
if (hd)
|
||||
skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if( skillid >= HM_SKILLBASE && skillid <= HM_SKILLBASE + MAX_HOMUNSKILL ) {
|
||||
if( src->type == BL_HOM && ((TBL_HOM*)src)->master->fd )
|
||||
clif_colormes(((TBL_HOM*)src)->master, COLOR_RED, "This skill is not yet supported");
|
||||
} else /* temporary until all the homun-s skills are supported otherwise console would fill up with pointless warnings */
|
||||
ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skillid);
|
||||
ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skillid);
|
||||
clif_skill_nodamage(src,bl,skillid,skilllv,1);
|
||||
map_freeblock_unlock();
|
||||
return 1;
|
||||
@ -9548,11 +9670,15 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
|
||||
case SO_WATER_INSIGNIA:
|
||||
case SO_WIND_INSIGNIA:
|
||||
case SO_EARTH_INSIGNIA:
|
||||
case MH_POISON_MIST:
|
||||
case KO_HUUMARANKA:
|
||||
case KO_MUCHANAGE:
|
||||
case KO_BAKURETSU:
|
||||
case KO_ZENKAI:
|
||||
case MH_LAVA_SLIDE:
|
||||
case MH_VOLCANIC_ASH:
|
||||
case MH_POISON_MIST:
|
||||
case MH_STEINWAND:
|
||||
case MH_XENO_SLASHER:
|
||||
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);
|
||||
@ -10018,15 +10144,12 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
|
||||
for( i = 0; i < (skilllv+2); i++ ) {
|
||||
x = src->x - 1 + rnd()%3;
|
||||
y = src->y - 1 + rnd()%3;
|
||||
skill_unitsetting(src,skillid,skilllv,x,y,0);
|
||||
skill_unitsetting(src,skillid,skilllv,x,y,0);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if( skillid >= HM_SKILLBASE && skillid <= HM_SKILLBASE + MAX_HOMUNSKILL ) {
|
||||
if( src->type == BL_HOM && ((TBL_HOM*)src)->master->fd )
|
||||
clif_colormes(((TBL_HOM*)src)->master, COLOR_RED, "This skill is not yet supported");
|
||||
} else /* temporary until all the homun-s skills are supported otherwise console would fill up with pointless warnings */
|
||||
ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skillid);
|
||||
ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skillid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -10335,6 +10458,9 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
|
||||
sc = status_get_sc(src); // for traps, firewall and fogwall - celest
|
||||
|
||||
switch( skillid ) {
|
||||
case MH_STEINWAND:
|
||||
val2 = 4 + skilllv; //nb of attack blocked
|
||||
break;
|
||||
case MG_SAFETYWALL:
|
||||
#ifdef RENEWAL
|
||||
/**
|
||||
@ -10841,7 +10967,7 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
|
||||
break;
|
||||
case UNT_SAFETYWALL:
|
||||
if (!sce)
|
||||
sc_start4(bl,type,100,sg->skill_lv,sg->group_id,sg->group_id,0,sg->limit);
|
||||
sc_start4(bl,type,100,sg->skill_lv,sg->skill_id,sg->group_id,0,sg->limit);
|
||||
break;
|
||||
|
||||
case UNT_PNEUMA:
|
||||
@ -10991,6 +11117,11 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
|
||||
skill_attack(skill_get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
|
||||
break;
|
||||
|
||||
case UNT_VOLCANIC_ASH:
|
||||
if (!sce)
|
||||
sc_start(bl, SC_ASH, 50, sg->skill_lv, skill_get_time(MH_VOLCANIC_ASH, sg->skill_lv)); //50% chance
|
||||
break;
|
||||
|
||||
case UNT_GD_LEADERSHIP:
|
||||
case UNT_GD_GLORYWOUNDS:
|
||||
case UNT_GD_SOULCOLD:
|
||||
@ -11703,6 +11834,16 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
sg->limit = DIFF_TICK(tick, sg->tick);
|
||||
sg->unit_id = UNT_USED_TRAPS;
|
||||
break;
|
||||
|
||||
case UNT_LAVA_SLIDE:
|
||||
skill_attack(BF_WEAPON, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
|
||||
if(++sg->val1 > 4) //after 5 stop hit and destroy me
|
||||
sg->limit = DIFF_TICK(tick, sg->tick);
|
||||
break;
|
||||
case UNT_POISON_MIST:
|
||||
skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
|
||||
status_change_start(bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill_get_time2(sg->skill_id, sg->skill_lv), 2|8);
|
||||
break;
|
||||
}
|
||||
|
||||
if (bl->type == BL_MOB && ss != bl)
|
||||
@ -11807,6 +11948,7 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int
|
||||
//your own. Let's pray that scenario is pretty unlikely and noone will complain too much about it.
|
||||
status_change_end(bl, SC_DANCING, INVALID_TIMER);
|
||||
}
|
||||
case MH_STEINWAND:
|
||||
case MG_SAFETYWALL:
|
||||
case AL_PNEUMA:
|
||||
case SA_VOLCANO:
|
||||
@ -13139,7 +13281,7 @@ int skill_consume_requirement( struct map_session_data *sd, short skill, short l
|
||||
req.zeny = 0; //Zeny is reduced on skill_attack.
|
||||
if( sd->status.zeny < req.zeny )
|
||||
req.zeny = sd->status.zeny;
|
||||
pc_payzeny(sd,req.zeny);
|
||||
pc_payzeny(sd,req.zeny,LOG_TYPE_OTHER,NULL); //@Need proper type
|
||||
}
|
||||
}
|
||||
|
||||
@ -13489,6 +13631,8 @@ int skill_castfix_sc (struct block_list *bl, int time)
|
||||
if (sc && sc->count) {
|
||||
if (sc->data[SC_SLOWCAST])
|
||||
time += time * sc->data[SC_SLOWCAST]->val2 / 100;
|
||||
if (sc->data[SC_PARALYSIS])
|
||||
time += sc->data[SC_PARALYSIS]->val3;
|
||||
if (sc->data[SC_SUFFRAGIUM]) {
|
||||
time -= time * sc->data[SC_SUFFRAGIUM]->val2 / 100;
|
||||
status_change_end(bl, SC_SUFFRAGIUM, INVALID_TIMER);
|
||||
|
216
src/map/status.c
216
src/map/status.c
@ -491,6 +491,26 @@ void initChangeTables(void) {
|
||||
set_sc( HAMI_DEFENCE , SC_DEFENCE , SI_BLANK , SCB_DEF );
|
||||
set_sc( HAMI_BLOODLUST , SC_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK );
|
||||
|
||||
// Homunculus S
|
||||
add_sc(MH_STAHL_HORN, SC_STUN);
|
||||
set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SI_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP);
|
||||
set_sc(MH_GOLDENE_FERSE, SC_GOLDENE_FERSE, SI_GOLDENE_FERSE, SCB_ASPD|SCB_MAXHP);
|
||||
add_sc( MH_STEINWAND, SC_SAFETYWALL );
|
||||
add_sc(MH_ERASER_CUTTER, SC_ERASER_CUTTER);
|
||||
set_sc(MH_OVERED_BOOST, SC_OVERED_BOOST, SI_BLANK, SCB_FLEE|SCB_ASPD);
|
||||
add_sc(MH_LIGHT_OF_REGENE, SC_LIGHT_OF_REGENE);
|
||||
set_sc(MH_VOLCANIC_ASH, SC_ASH, SI_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE);
|
||||
set_sc(MH_GRANITIC_ARMOR, SC_GRANITIC_ARMOR, SI_GRANITIC_ARMOR, SCB_NONE);
|
||||
set_sc(MH_MAGMA_FLOW, SC_MAGMA_FLOW, SI_MAGMA_FLOW, SCB_NONE);
|
||||
set_sc(MH_PYROCLASTIC, SC_PYROCLASTIC, SI_PYROCLASTIC, SCB_BATK|SCB_ATK_ELE);
|
||||
add_sc(MH_LAVA_SLIDE, SC_BURNING);
|
||||
set_sc(MH_NEEDLE_OF_PARALYZE, SC_PARALYSIS, SI_NEEDLE_OF_PARALYZE, SCB_DEF2);
|
||||
add_sc(MH_POISON_MIST, SC_BLIND);
|
||||
set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SI_PAIN_KILLER, SCB_ASPD);
|
||||
|
||||
add_sc(MH_STYLE_CHANGE, SC_STYLE_CHANGE);
|
||||
|
||||
|
||||
add_sc( MER_CRASH , SC_STUN );
|
||||
set_sc( MER_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
|
||||
add_sc( MS_MAGNUM , SC_WATK_ELEMENT );
|
||||
@ -728,13 +748,6 @@ void initChangeTables(void) {
|
||||
set_sc_with_vfx( OB_AKAITSUKI , SC_AKAITSUKI , SI_AKAITSUKI , SCB_NONE );
|
||||
set_sc( OB_OBOROGENSOU , SC_GENSOU , SI_GENSOU , SCB_NONE );
|
||||
|
||||
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 );
|
||||
set_sc( MH_GOLDENE_FERSE , SC_GOLDENE_FERSE , SI_GOLDENE_FERSE , SCB_SPEED|SCB_FLEE|SCB_ATK_ELE );
|
||||
add_sc( MH_LAVA_SLIDE , SC_BURNING );
|
||||
add_sc( MH_POISON_MIST , SC_BLIND );
|
||||
set_sc( MH_ERASER_CUTTER , SC_ERASER_CUTTER , SI_BLANK , SCB_NONE );
|
||||
|
||||
// Storing the target job rather than simply SC_SPIRIT simplifies code later on.
|
||||
SkillStatusChangeTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST,
|
||||
SkillStatusChangeTable[SL_MONK] = (sc_type)MAPID_MONK,
|
||||
@ -1034,6 +1047,9 @@ void initChangeTables(void) {
|
||||
StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET] |= SCS_NOCAST;
|
||||
StatusChangeStateTable[SC_SILENCE] |= SCS_NOCAST;
|
||||
|
||||
//Homon S
|
||||
StatusChangeStateTable[SC_PARALYSIS] |= SCS_NOMOVE;
|
||||
|
||||
}
|
||||
|
||||
static void initDummyData(void)
|
||||
@ -1294,9 +1310,17 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
|
||||
|
||||
return hp+sp;
|
||||
}
|
||||
|
||||
if( target->type == BL_MOB && sc && sc->data[SC_REBIRTH] && !((TBL_MOB*)target)->state.rebirth )
|
||||
{// Ensure the monster has not already rebirthed before doing so.
|
||||
if(target->type == BL_PC){
|
||||
TBL_PC *sd = BL_CAST(BL_PC,target);
|
||||
TBL_HOM *hd = sd->hd;
|
||||
if(hd && hd->sc.data[SC_LIGHT_OF_REGENE]){
|
||||
clif_skillcasting(&hd->bl, hd->bl.id, target->id, 0,0, MH_LIGHT_OF_REGENE, skill_get_ele(MH_LIGHT_OF_REGENE, 1), 10); //just to display usage
|
||||
clif_skill_nodamage(&sd->bl, target, ALL_RESURRECTION, 1, status_revive(&sd->bl,10*hd->sc.data[SC_LIGHT_OF_REGENE]->val1,0));
|
||||
status_change_end(&sd->hd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER);
|
||||
return hp + sp;
|
||||
}
|
||||
}
|
||||
if (target->type == BL_MOB && sc && sc->data[SC_REBIRTH] && !((TBL_MOB*) target)->state.rebirth) {// Ensure the monster has not already rebirthed before doing so.
|
||||
status_revive(target, sc->data[SC_REBIRTH]->val2, 0);
|
||||
status_change_clear(target,0);
|
||||
((TBL_MOB*)target)->state.rebirth = 1;
|
||||
@ -3254,6 +3278,7 @@ static unsigned short status_calc_dmotion(struct block_list *bl, struct status_c
|
||||
#ifdef RENEWAL_ASPD
|
||||
static short status_calc_aspd(struct block_list *bl, struct status_change *sc, short flag);
|
||||
#endif
|
||||
static short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int);
|
||||
static unsigned int status_calc_maxhp(struct block_list *,struct status_change *,unsigned int);
|
||||
static unsigned int status_calc_maxsp(struct block_list *,struct status_change *,unsigned int);
|
||||
static unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element);
|
||||
@ -3809,10 +3834,10 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
|
||||
if(status->aspd_rate != 1000) // absolute percentage modifier
|
||||
amotion = ( 200 - (200-amotion/10) * status->aspd_rate / 1000 ) * 10;
|
||||
#endif
|
||||
//fixed value added
|
||||
//@TODO move FIGHTINGSPIRIT in fix_aspd
|
||||
if( sc && sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 )
|
||||
amotion -= (sd?pc_checkskill(sd, RK_RUNEMASTERY):10) / 10 * 40;
|
||||
|
||||
amotion = status_calc_fix_aspd(bl, sc, amotion);
|
||||
status->amotion = cap_value(amotion,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000);
|
||||
|
||||
status->adelay = 2*status->amotion;
|
||||
@ -3826,6 +3851,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
|
||||
if(status->aspd_rate != 1000)
|
||||
amotion = amotion*status->aspd_rate/1000;
|
||||
|
||||
amotion = status_calc_fix_aspd(bl, sc, amotion);
|
||||
status->amotion = cap_value(amotion,battle_config.max_aspd,2000);
|
||||
|
||||
status->adelay = status->amotion;
|
||||
@ -3838,6 +3864,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
|
||||
if(status->aspd_rate != 1000)
|
||||
amotion = amotion*status->aspd_rate/1000;
|
||||
|
||||
amotion = status_calc_fix_aspd(bl, sc, amotion);
|
||||
status->amotion = cap_value(amotion, battle_config.monster_max_aspd, 2000);
|
||||
|
||||
temp = b_status->adelay*status->aspd_rate/1000;
|
||||
@ -4407,10 +4434,17 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan
|
||||
batk += sc->data[SC_FULL_SWING_K]->val1;
|
||||
if(sc->data[SC_ODINS_POWER])
|
||||
batk += 70;
|
||||
if(sc->data[SC_ANGRIFFS_MODUS])
|
||||
batk += batk * sc->data[SC_ANGRIFFS_MODUS]->val2/100;
|
||||
if( sc->data[SC_ZANGETSU] )
|
||||
batk += batk * sc->data[SC_ZANGETSU]->val2 / 100;
|
||||
if(sc->data[SC_ASH] && (bl->type==BL_MOB)){
|
||||
if(status_get_element(bl) == ELE_WATER) //water type
|
||||
batk /= 2;
|
||||
}
|
||||
if(sc->data[SC_PYROCLASTIC])
|
||||
batk += sc->data[SC_PYROCLASTIC]->val2;
|
||||
if (sc->data[SC_ANGRIFFS_MODUS])
|
||||
batk += sc->data[SC_ANGRIFFS_MODUS]->val2;
|
||||
|
||||
return (unsigned short)cap_value(batk,0,USHRT_MAX);
|
||||
}
|
||||
|
||||
@ -4597,6 +4631,8 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change
|
||||
hit -= hit * 20 / 100;
|
||||
if(sc->data[SC_INSPIRATION])
|
||||
hit += 5 * sc->data[SC_INSPIRATION]->val1;
|
||||
if (sc->data[SC_ASH])
|
||||
hit /= 2;
|
||||
|
||||
return (short)cap_value(hit,1,SHRT_MAX);
|
||||
}
|
||||
@ -4668,14 +4704,18 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
|
||||
flee += flee * sc->data[SC_ZEPHYR]->val2 / 100;
|
||||
if( sc->data[SC_MARSHOFABYSS] )
|
||||
flee -= (9 * sc->data[SC_MARSHOFABYSS]->val3 / 10 + sc->data[SC_MARSHOFABYSS]->val2 / 10) * (bl->type == BL_MOB ? 2 : 1);
|
||||
if( sc->data[SC_ANGRIFFS_MODUS] )
|
||||
flee -= flee * sc->data[SC_ANGRIFFS_MODUS]->val3 / 100;
|
||||
if( sc->data[SC_GOLDENE_FERSE ] )
|
||||
flee -= flee * sc->data[SC_GOLDENE_FERSE ]->val2 / 100;
|
||||
#ifdef RENEWAL
|
||||
if( sc->data[SC_SPEARQUICKEN] )
|
||||
flee += 2 * sc->data[SC_SPEARQUICKEN]->val1;
|
||||
#endif
|
||||
if (sc->data[SC_ANGRIFFS_MODUS])
|
||||
flee -= sc->data[SC_ANGRIFFS_MODUS]->val3;
|
||||
if (sc->data[SC_OVERED_BOOST])
|
||||
flee = max(flee,sc->data[SC_OVERED_BOOST]->val2);
|
||||
if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ //mob
|
||||
if(status_get_element(bl) == ELE_WATER) //water type
|
||||
flee /= 2;
|
||||
}
|
||||
|
||||
return (short)cap_value(flee,1,SHRT_MAX);
|
||||
}
|
||||
@ -4765,7 +4805,11 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc,
|
||||
if(sc->data[SC_ODINS_POWER])
|
||||
def -= 20;
|
||||
if( sc->data[SC_ANGRIFFS_MODUS] )
|
||||
def -= def * sc->data[SC_ANGRIFFS_MODUS]->val4 / 100;
|
||||
def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1;
|
||||
if(sc->data[SC_ASH] && (bl->type==BL_MOB)){
|
||||
if(status_get_race(bl)==RC_PLANT)
|
||||
def /= 2;
|
||||
}
|
||||
|
||||
return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX);;
|
||||
}
|
||||
@ -4823,6 +4867,12 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change
|
||||
def2 += (5 + sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2);
|
||||
if( sc->data[SC_GT_REVITALIZE] && sc->data[SC_GT_REVITALIZE]->val4)
|
||||
def2 += def2 * sc->data[SC_GT_REVITALIZE]->val4 / 100;
|
||||
if(sc->data[SC_ASH] && (bl->type==BL_MOB)){
|
||||
if(status_get_race(bl)==RC_PLANT)
|
||||
def2 /= 2;
|
||||
}
|
||||
if (sc->data[SC_PARALYSIS])
|
||||
def2 -= def2 * sc->data[SC_PARALYSIS]->val2 / 100;
|
||||
|
||||
#ifdef RENEWAL
|
||||
return (short)cap_value(def2,SHRT_MIN,SHRT_MAX);
|
||||
@ -5212,6 +5262,28 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s
|
||||
}
|
||||
#endif
|
||||
|
||||
static short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int aspd) {
|
||||
if (!sc || !sc->count)
|
||||
return cap_value(aspd, 0, 2000);
|
||||
|
||||
if (!sc->data[SC_QUAGMIRE]) {
|
||||
if (sc->data[SC_FIGHTINGSPIRIT])
|
||||
aspd += sc->data[SC_FIGHTINGSPIRIT]->val3;
|
||||
if ((sc->data[SC_GUST_OPTION]
|
||||
|| sc->data[SC_BLAST_OPTION]
|
||||
|| sc->data[SC_WILD_STORM_OPTION])
|
||||
)
|
||||
aspd -= 50; // ventus passive = +5 ASPD
|
||||
if (sc->data[SC_OVERED_BOOST]){
|
||||
aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3*10;
|
||||
}
|
||||
// if(sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 )
|
||||
// aspd -= (sd?pc_checkskill(sd, RK_RUNEMASTERY):10) * 4;
|
||||
}
|
||||
|
||||
return cap_value(aspd, 0, 2000); // will be recap for proper bl anyway
|
||||
}
|
||||
|
||||
/// Calculates an object's ASPD modifier (alters the base amotion value).
|
||||
/// Note that the scale of aspd_rate is 1000 = 100%.
|
||||
static short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int aspd_rate)
|
||||
@ -5258,9 +5330,6 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
|
||||
max < sc->data[SC_FLEET]->val2)
|
||||
max = sc->data[SC_FLEET]->val2;
|
||||
|
||||
if( sc->data[SC_GOLDENE_FERSE] && max < sc->data[SC_GOLDENE_FERSE]->val3 )
|
||||
max = sc->data[SC_GOLDENE_FERSE]->val3;
|
||||
|
||||
if(sc->data[SC_ASSNCROS] &&
|
||||
max < sc->data[SC_ASSNCROS]->val2)
|
||||
{
|
||||
@ -5346,6 +5415,10 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
|
||||
aspd_rate -= sc->data[SC_EXTRACT_SALAMINE_JUICE]->val1 * 10;
|
||||
if( sc->data[SC_INCASPDRATE] )
|
||||
aspd_rate -= sc->data[SC_INCASPDRATE]->val1 * 10;
|
||||
if( sc->data[SC_PAIN_KILLER])
|
||||
aspd_rate += sc->data[SC_PAIN_KILLER]->val2 * 10;
|
||||
if( sc->data[SC_GOLDENE_FERSE])
|
||||
aspd_rate -= sc->data[SC_GOLDENE_FERSE]->val3 * 10;
|
||||
|
||||
return (short)cap_value(aspd_rate,0,SHRT_MAX);
|
||||
}
|
||||
@ -5416,6 +5489,10 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang
|
||||
maxhp -= sc->data[SC_MYSTERIOUS_POWDER]->val1 / 100;
|
||||
if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2)
|
||||
maxhp += 500;
|
||||
if (sc->data[SC_ANGRIFFS_MODUS])
|
||||
maxhp += maxhp * 5 * sc->data[SC_ANGRIFFS_MODUS]->val1 /100;
|
||||
if (sc->data[SC_GOLDENE_FERSE])
|
||||
maxhp += (maxhp * sc->data[SC_GOLDENE_FERSE]->val2) / 100;
|
||||
|
||||
return cap_value(maxhp,1,UINT_MAX);
|
||||
}
|
||||
@ -5516,8 +5593,8 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch
|
||||
return ELE_GHOST;
|
||||
if(sc->data[SC_TIDAL_WEAPON_OPTION] || sc->data[SC_TIDAL_WEAPON] )
|
||||
return ELE_WATER;
|
||||
if(sc->data[SC_GOLDENE_FERSE] && rand()%100 < sc->data[SC_GOLDENE_FERSE]->val4)
|
||||
return ELE_HOLY;
|
||||
if(sc->data[SC_PYROCLASTIC])
|
||||
return ELE_FIRE;
|
||||
return (unsigned char)cap_value(element,0,UCHAR_MAX);
|
||||
}
|
||||
|
||||
@ -6118,6 +6195,9 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
|
||||
case SC_KYOUGAKU:
|
||||
tick -= 30*status->int_;
|
||||
break;
|
||||
case SC_PARALYSIS:
|
||||
tick -= 50 * (status->vit + status->luk); //(1000/20);
|
||||
break;
|
||||
default:
|
||||
//Effect that cannot be reduced? Likely a buff.
|
||||
if (!(rnd()%10000 < rate))
|
||||
@ -6306,6 +6386,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
undead_flag = battle_check_undead(status->race,status->def_ele);
|
||||
//Check for inmunities / sc fails
|
||||
switch (type) {
|
||||
case SC_ANGRIFFS_MODUS:
|
||||
case SC_GOLDENE_FERSE:
|
||||
if ((type==SC_GOLDENE_FERSE && sc->data[SC_ANGRIFFS_MODUS])
|
||||
|| (type==SC_ANGRIFFS_MODUS && sc->data[SC_GOLDENE_FERSE])
|
||||
)
|
||||
return 0;
|
||||
case SC_STONE:
|
||||
if(sc->data[SC_POWER_OF_GAIA])
|
||||
return 0;
|
||||
@ -6609,6 +6695,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
case SC_BURNING: // Place here until we have info about its behavior on Boss-monsters. [pakpil]
|
||||
case SC_MARSHOFABYSS:
|
||||
case SC_ADORAMUS:
|
||||
case SC_PARALYSIS:
|
||||
|
||||
// Exploit prevention - kRO Fix
|
||||
case SC_PYREXIA:
|
||||
@ -7654,16 +7741,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
val3 = 3*val1; //Leech chance
|
||||
val4 = 20; //Leech percent
|
||||
break;
|
||||
case SC_ANGRIFFS_MODUS:
|
||||
val2 = 70 + 30*val1; //atk
|
||||
val3 = 50 + 20*val1; //flee
|
||||
val4 = 60 + 20*val1; //def
|
||||
break;
|
||||
case SC_GOLDENE_FERSE:
|
||||
val2 = 20 + 10*val1; //flee
|
||||
val3 = 10 + 4*val1; //aspd
|
||||
val4 = 2 + 2*val1; //chance to issue holy-ele attack
|
||||
break;
|
||||
case SC_FLEET:
|
||||
val2 = 30*val1; //Aspd change
|
||||
val3 = 5+5*val1; //bAtk/wAtk rate change
|
||||
@ -8318,7 +8395,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
break;
|
||||
case SC_KYOUGAKU:
|
||||
val2 = 2*val1 + rand()%val1;
|
||||
clif_status_change(bl,SI_ACTIVE_MONSTER_TRANSFORM,1,0,1002,0,0);
|
||||
clif_status_change(bl,SI_ACTIVE_MONSTER_TRANSFORM,1,0,1002,0,0);
|
||||
break;
|
||||
case SC_KAGEMUSYA:
|
||||
val3 = val1 * 2;
|
||||
@ -8351,6 +8428,41 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
status_zap(bl, hp * (lv*4) / 100, status_get_sp(bl) * (lv*3) / 100);
|
||||
}
|
||||
break;
|
||||
case SC_ANGRIFFS_MODUS:
|
||||
val2 = 50 + 20 * val1; //atk bonus
|
||||
val3 = 40 + 20 * val1; // Flee reduction.
|
||||
val4 = tick/1000; // hp/sp reduction timer
|
||||
tick_time = 1000;
|
||||
break;
|
||||
case SC_GOLDENE_FERSE:
|
||||
val2 = 10 + 10*val1; //max hp bonus
|
||||
val3 = 6 + 4 * val1; // Aspd Bonus
|
||||
val4 = 2 + 2 * val1; // Chance of holy attack
|
||||
break;
|
||||
case SC_OVERED_BOOST:
|
||||
val2 = 300 + 40*val1; //flee bonus
|
||||
val3 = 179 + 2*val1; //aspd bonus
|
||||
break;
|
||||
case SC_GRANITIC_ARMOR:
|
||||
val2 = 2*val1; //dmg reduction
|
||||
val3 = 6*val1; //dmg on status end
|
||||
break;
|
||||
case SC_MAGMA_FLOW:
|
||||
val2 = 3*val1; //activation chance
|
||||
break;
|
||||
case SC_PYROCLASTIC:
|
||||
val2 += 10*val1; //atk bonus
|
||||
break;
|
||||
case SC_PARALYSIS: //[Lighta] need real info
|
||||
val2 = 2*val1; //def reduction
|
||||
val3 = 500*val1; //varcast augmentation
|
||||
break;
|
||||
case SC_PAIN_KILLER: //[Lighta] need real info
|
||||
val2 = 2*val1; //aspd reduction %
|
||||
val3 = 2*val1; //dmg reduction %
|
||||
if(sc->data[SC_PARALYSIS])
|
||||
sc_start(bl, SC_ENDURE, 100, val1, tick); //start endure for same duration
|
||||
break;
|
||||
default:
|
||||
if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 )
|
||||
{ //Status change with no calc, no icon, and no skill associated...?
|
||||
@ -8407,6 +8519,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
case SC_NETHERWORLD:
|
||||
case SC_MEIKYOUSISUI:
|
||||
case SC_KYOUGAKU:
|
||||
case SC_PARALYSIS:
|
||||
unit_stop_walking(bl,1);
|
||||
break;
|
||||
case SC_HIDING:
|
||||
@ -8877,6 +8990,17 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
|
||||
vd = status_get_viewdata(bl);
|
||||
calc_flag = StatusChangeFlagTable[type];
|
||||
switch(type){
|
||||
case SC_GRANITIC_ARMOR:{
|
||||
int dammage = status->max_hp*sce->val3/100;
|
||||
if(status->hp < dammage) //to not kill him
|
||||
dammage = status->hp-1;
|
||||
status_damage(NULL, bl, dammage,0,0,1);
|
||||
break;
|
||||
}
|
||||
case SC_PYROCLASTIC:
|
||||
if(bl->type == BL_PC)
|
||||
skill_break_equip(bl,EQP_WEAPON,10000,BCT_SELF);
|
||||
break;
|
||||
case SC_WEDDING:
|
||||
case SC_XMAS:
|
||||
case SC_SUMMER:
|
||||
@ -10274,8 +10398,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
case SC_WIND_STEP:
|
||||
case SC_STONE_SHIELD:
|
||||
case SC_SOLID_SKIN:
|
||||
if( !status_charge(bl,0,sce->val2) )
|
||||
{
|
||||
if( !status_charge(bl,0,sce->val2) ){
|
||||
struct block_list *s_bl = battle_get_master(bl);
|
||||
if( s_bl )
|
||||
status_change_end(s_bl,type+1,INVALID_TIMER);
|
||||
@ -10286,8 +10409,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
return 0;
|
||||
|
||||
case SC_STOMACHACHE:
|
||||
if( --(sce->val4) > 0 )
|
||||
{
|
||||
if( --(sce->val4) > 0 ){
|
||||
status_charge(bl,0,sce->val2); // Reduce 8 every 10 seconds.
|
||||
if( sd && !pc_issit(sd) ) // Force to sit every 10 seconds.
|
||||
{
|
||||
@ -10308,8 +10430,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
sc_timer_next(600000 + tick, status_change_timer, bl->id, data);
|
||||
return 0;
|
||||
case SC_MEIKYOUSISUI:
|
||||
if( --(sce->val4) > 0 )
|
||||
{
|
||||
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;
|
||||
@ -10317,12 +10438,17 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
break;
|
||||
case SC_IZAYOI:
|
||||
case SC_KAGEMUSYA:
|
||||
if( --(sce->val2) > 0 )
|
||||
{
|
||||
if(!status_charge(bl, 0, 1))
|
||||
break;
|
||||
if( --(sce->val2) > 0 ){
|
||||
if(!status_charge(bl, 0, 1)) break;
|
||||
sc_timer_next(1000+tick, status_change_timer, bl->id, data);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case SC_ANGRIFFS_MODUS:
|
||||
if(--(sce->val4) >= 0) { //drain hp/sp
|
||||
if( !status_charge(bl,100,20) ) break;
|
||||
sc_timer_next(1000+tick,status_change_timer,bl->id, data);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -613,10 +613,6 @@ typedef enum sc_type {
|
||||
* To increase the maximum value just add another status type before SC_MAXSPELLBOOK (ex. SC_SPELLBOOK7, SC_SPELLBOOK8 and so on)
|
||||
**/
|
||||
SC_MAXSPELLBOOK,
|
||||
/* homun-s */
|
||||
SC_ANGRIFFS_MODUS,
|
||||
SC_GOLDENE_FERSE,
|
||||
SC_ERASER_CUTTER,
|
||||
/* Max HP & SP */
|
||||
SC_INCMHP,
|
||||
SC_INCMSP,
|
||||
@ -635,6 +631,21 @@ typedef enum sc_type {
|
||||
SC_ZANGETSU,
|
||||
SC_GENSOU,
|
||||
SC_AKAITSUKI,
|
||||
|
||||
//homon S
|
||||
SC_STYLE_CHANGE,
|
||||
SC_GOLDENE_FERSE,
|
||||
SC_ANGRIFFS_MODUS,
|
||||
SC_ERASER_CUTTER,
|
||||
SC_OVERED_BOOST,
|
||||
SC_LIGHT_OF_REGENE,
|
||||
SC_ASH,
|
||||
SC_GRANITIC_ARMOR,
|
||||
SC_MAGMA_FLOW,
|
||||
SC_PYROCLASTIC,
|
||||
SC_PARALYSIS,
|
||||
SC_PAIN_KILLER,
|
||||
|
||||
#ifdef RENEWAL
|
||||
SC_EXTREMITYFIST2,
|
||||
#endif
|
||||
|
@ -74,15 +74,15 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
|
||||
clif_displaymessage(sd->fd, msg_txt(246));
|
||||
clif_tradestart(sd, 2); // GM is not allowed to trade
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Players can not request trade from far away, unless they are allowed to use @trade.
|
||||
if (!pc_can_use_command(sd, "trade", COMMAND_ATCOMMAND) &&
|
||||
(sd->bl.m != target_sd->bl.m || !check_distance_bl(&sd->bl, &target_sd->bl, TRADE_DISTANCE))) {
|
||||
clif_tradestart(sd, 0); // too far
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
target_sd->trade_partner = sd->status.account_id;
|
||||
sd->trade_partner = target_sd->status.account_id;
|
||||
clif_traderequest(target_sd, sd->status.name);
|
||||
@ -106,7 +106,7 @@ void trade_tradeack(struct map_session_data *sd, int type)
|
||||
|
||||
if (sd->state.trading || !sd->trade_partner)
|
||||
return; //Already trading or no partner set.
|
||||
|
||||
|
||||
if ((tsd = map_id2sd(sd->trade_partner)) == NULL) {
|
||||
clif_tradestart(sd, 1); // character does not exist
|
||||
sd->trade_partner=0;
|
||||
@ -177,7 +177,7 @@ int impossible_trade_check(struct map_session_data *sd)
|
||||
int i, index;
|
||||
|
||||
nullpo_retr(1, sd);
|
||||
|
||||
|
||||
if(sd->deal.zeny > sd->status.zeny)
|
||||
{
|
||||
pc_setglobalreg(sd,"ZENY_HACKER",1);
|
||||
@ -220,7 +220,7 @@ int impossible_trade_check(struct map_session_data *sd)
|
||||
} else
|
||||
// message about the ban
|
||||
strcpy(message_to_gm, msg_txt(508)); // This player hasn't been banned (Ban option is disabled).
|
||||
|
||||
|
||||
intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
|
||||
return 1;
|
||||
}
|
||||
@ -257,7 +257,7 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
|
||||
n = sd->deal.item[trade_i].index;
|
||||
if (amount > inventory[n].amount)
|
||||
return 0; //qty Exploit?
|
||||
|
||||
|
||||
data = itemdb_search(inventory[n].nameid);
|
||||
i = MAX_INVENTORY;
|
||||
if (itemdb_isstackable2(data)) { //Stackable item.
|
||||
@ -272,7 +272,7 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (i == MAX_INVENTORY) {// look for an empty slot.
|
||||
for(i = 0; i < MAX_INVENTORY && inventory2[i].nameid; i++);
|
||||
if (i == MAX_INVENTORY)
|
||||
@ -439,7 +439,7 @@ void trade_tradeok(struct map_session_data *sd)
|
||||
|
||||
if(sd->state.deal_locked || !sd->state.trading)
|
||||
return;
|
||||
|
||||
|
||||
if ((target_sd = map_id2sd(sd->trade_partner)) == NULL) {
|
||||
trade_tradecancel(sd);
|
||||
return;
|
||||
@ -470,7 +470,7 @@ void trade_tradecancel(struct map_session_data *sd)
|
||||
clif_tradecancelled(sd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for(trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual)
|
||||
if (!sd->deal.item[trade_i].amount)
|
||||
continue;
|
||||
@ -498,7 +498,7 @@ void trade_tradecancel(struct map_session_data *sd)
|
||||
target_sd->deal.item[trade_i].index = 0;
|
||||
target_sd->deal.item[trade_i].amount = 0;
|
||||
}
|
||||
|
||||
|
||||
if (target_sd->deal.zeny) {
|
||||
clif_updatestatus(target_sd, SP_ZENY);
|
||||
target_sd->deal.zeny = 0;
|
||||
@ -525,9 +525,9 @@ void trade_tradecommit(struct map_session_data *sd)
|
||||
trade_tradecancel(sd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
sd->state.deal_locked = 2;
|
||||
|
||||
|
||||
if (tsd->state.deal_locked < 2)
|
||||
return; //Not yet time for trading.
|
||||
|
||||
@ -547,7 +547,7 @@ void trade_tradecommit(struct map_session_data *sd)
|
||||
trade_tradecancel(sd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// trade is accepted and correct.
|
||||
for( trade_i = 0; trade_i < 10; trade_i++ )
|
||||
{
|
||||
@ -580,37 +580,28 @@ void trade_tradecommit(struct map_session_data *sd)
|
||||
|
||||
if( sd->deal.zeny || tsd->deal.zeny )
|
||||
{
|
||||
sd->status.zeny += tsd->deal.zeny - sd->deal.zeny;
|
||||
tsd->status.zeny += sd->deal.zeny - tsd->deal.zeny;
|
||||
|
||||
//Logs Zeny (T)rade [Lupus]
|
||||
if( sd->deal.zeny )
|
||||
log_zeny(tsd, LOG_TYPE_TRADE, sd, sd->deal.zeny);
|
||||
if( tsd->deal.zeny )
|
||||
log_zeny(sd, LOG_TYPE_TRADE, tsd, tsd->deal.zeny);
|
||||
pc_getzeny(sd,tsd->deal.zeny - sd->deal.zeny,LOG_TYPE_TRADE, tsd);
|
||||
pc_getzeny(tsd,sd->deal.zeny - tsd->deal.zeny,LOG_TYPE_TRADE, sd);
|
||||
|
||||
sd->deal.zeny = 0;
|
||||
tsd->deal.zeny = 0;
|
||||
|
||||
clif_updatestatus(sd, SP_ZENY);
|
||||
clif_updatestatus(tsd, SP_ZENY);
|
||||
}
|
||||
|
||||
|
||||
sd->state.deal_locked = 0;
|
||||
sd->trade_partner = 0;
|
||||
sd->state.trading = 0;
|
||||
|
||||
|
||||
tsd->state.deal_locked = 0;
|
||||
tsd->trade_partner = 0;
|
||||
tsd->state.trading = 0;
|
||||
|
||||
|
||||
clif_tradecompleted(sd, 0);
|
||||
clif_tradecompleted(tsd, 0);
|
||||
|
||||
// save both player to avoid crash: they always have no advantage/disadvantage between the 2 players
|
||||
if (save_settings&1)
|
||||
{
|
||||
chrif_save(sd,0);
|
||||
chrif_save(sd,0);
|
||||
chrif_save(tsd,0);
|
||||
}
|
||||
}
|
||||
|
@ -1249,6 +1249,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
|
||||
case RA_WUGDASH:
|
||||
if (sc && sc->data[SC_WUGDASH])
|
||||
casttime = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
// moved here to prevent Suffragium from ending if skill fails
|
||||
|
@ -59,7 +59,7 @@ void vending_vendinglistreq(struct map_session_data* sd, int id)
|
||||
{ // GM is not allowed to trade
|
||||
clif_displaymessage(sd->fd, msg_txt(246));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sd->vended_id = vsd->vender_id; // register vending uid
|
||||
|
||||
@ -139,11 +139,11 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
|
||||
clif_buyvending(sd, idx, amount, 2); // you can not buy, because overweight
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//Check to see if cart/vend info is in sync.
|
||||
if( vending[j].amount > vsd->status.cart[idx].amount )
|
||||
vending[j].amount = vsd->status.cart[idx].amount;
|
||||
|
||||
|
||||
// if they try to add packets (example: get twice or more 2 apples if marchand has only 3 apples).
|
||||
// here, we check cumulative amounts
|
||||
if( vending[j].amount < amount )
|
||||
@ -152,7 +152,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
|
||||
clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // not enough quantity
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
vending[j].amount -= amount;
|
||||
|
||||
switch( pc_checkadditem(sd, vsd->status.cart[idx].nameid, amount) ) {
|
||||
@ -168,13 +168,10 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
|
||||
}
|
||||
}
|
||||
|
||||
//Logs (V)ending Zeny [Lupus]
|
||||
log_zeny(vsd, LOG_TYPE_VENDING, sd, (int)z);
|
||||
|
||||
pc_payzeny(sd, (int)z);
|
||||
pc_payzeny(sd, (int)z, LOG_TYPE_VENDING, vsd);
|
||||
if( battle_config.vending_tax )
|
||||
z -= z * (battle_config.vending_tax/10000.);
|
||||
pc_getzeny(vsd, (int)z);
|
||||
pc_getzeny(vsd, (int)z, LOG_TYPE_VENDING, sd);
|
||||
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
@ -202,7 +199,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
|
||||
{
|
||||
if( vsd->vending[i].amount == 0 )
|
||||
continue;
|
||||
|
||||
|
||||
if( cursor != i ) // speedup
|
||||
{
|
||||
vsd->vending[cursor].index = vsd->vending[i].index;
|
||||
@ -236,18 +233,18 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
|
||||
}
|
||||
static int vending_checknearnpc_sub(struct block_list* bl, va_list args) {
|
||||
struct npc_data *nd = (struct npc_data*)bl;
|
||||
|
||||
|
||||
if( nd->sc.option & (OPTION_HIDE|OPTION_INVISIBLE) )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
bool vending_checknearnpc(struct block_list * bl) {
|
||||
|
||||
|
||||
if( battle_config.min_npc_vending_distance > 0 &&
|
||||
map_foreachinrange(vending_checknearnpc_sub,bl, battle_config.min_npc_vending_distance, BL_NPC) )
|
||||
return true;
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
/*==========================================
|
||||
@ -287,8 +284,8 @@ void vending_openvending(struct map_session_data* sd, const char* message, bool
|
||||
clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// filter out invalid items
|
||||
i = 0;
|
||||
for( j = 0; j < count; j++ )
|
||||
|
Loading…
x
Reference in New Issue
Block a user