Merge branch 'master' of https://github.com/rathena/rathena
This commit is contained in:
commit
4ffe723d8c
@ -306,3 +306,6 @@ teleport_on_portal: no
|
||||
// Is the knockback direction for Cart Revolution always West? (Note 1)
|
||||
// On official servers it will knock the target always to the West. If disabled it will knock the target backwards.
|
||||
cart_revo_knockback: yes
|
||||
|
||||
// On official servers, Arrow Shower blow direction always rely on skill placed location to target instead of caster to target
|
||||
arrow_shower_knockback: yes
|
||||
|
@ -97,7 +97,7 @@ log_mvpdrop: no
|
||||
log_commands: yes
|
||||
|
||||
// Log NPC 'logmes' commands (Note 1)
|
||||
log_npc: no
|
||||
log_npc: yes
|
||||
|
||||
// Log CHAT (Global, Whisper, Party, Guild, Main chat) (Note 3)
|
||||
// LOGGING FILTERS
|
||||
|
@ -8,7 +8,7 @@
|
||||
1506,DISGUISE,Disguise,55,7543,180,2,279,546,18,29,0,72,45,35,48,65,10,12,1,6,82,147,516,768,384
|
||||
1275,ALICE,Alice,62,10000,221,2,550,700,5,5,64,64,42,85,100,130,10,12,1,7,60,200,502,2304,480
|
||||
1965,M_WILD_ROSE,Wild Rose,38,2980,130,2,315,360,0,15,65,85,15,35,65,80,10,12,0,2,24,100,964,864,288
|
||||
1966,M_DOPPELGANGER,Doppelganger,72,249000,200,2,1340,1590,60,35,88,90,30,35,125,65,10,12,1,6,67,100,480,480,288
|
||||
1966,M_DOPPELGANGER,Doppelganger,72,7800,200,2,1340,1590,60,35,88,90,30,35,125,65,10,12,1,6,67,100,480,480,288
|
||||
1967,M_YGNIZEM,Egnigem Cenia,58,11200,320,2,823,1212,35,8,60,35,52,18,79,20,10,12,1,7,43,145,576,432,288
|
||||
2000,M_GAMEMASTER,[GM] Game Master,50,7000,250,2,100,50,6,17,1,109,1,60,215,111,10,0,0,7,20,150,450,432,300
|
||||
2001,F_GAMEMASTER,[GM] Game Master,50,7000,250,2,100,50,6,17,1,109,1,60,215,111,10,0,0,7,20,150,450,432,300
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Skill Unit Database
|
||||
//
|
||||
// Structure of Database:
|
||||
// ID,unit ID,unit ID 2,layout,range,interval,target,flag
|
||||
// Skill ID,Unit ID,Unit ID 2,Layout,Range,Interval,Target,Flag
|
||||
//
|
||||
// layout = -1:special, 0:1*1, 1:3*3, 2:5*5, up to 5:11*11
|
||||
// target = friend (party +guildmates +neutral players) / party / guild
|
||||
@ -151,7 +151,7 @@
|
||||
2468,0xf4, , 0, 1,1000,all, 0x010 //SO_EARTH_INSIGNIA
|
||||
|
||||
2479,0xe5, , 0, 1,1000,enemy, 0xC006 //GN_THORNS_TRAP
|
||||
2482,0xe6,0x7f, 0, 1, 100,all, 0xD000 //GN_WALLOFTHORN
|
||||
2482,0xe6,0x7f, -1, 1, 300,enemy, 0xD000 //GN_WALLOFTHORN
|
||||
2484,0x86, , 0, 1, 100,enemy, 0x080 //GN_CRAZYWEED_ATK
|
||||
2485,0xe7, , 0, 2,2000,enemy, 0x8098 //GN_DEMONIC_FIRE
|
||||
2487,0xe8, , 2, 0, -1,enemy, 0x2000 //GN_FIRE_EXPANSION_SMOKE_POWDER
|
||||
|
@ -6990,7 +6990,7 @@
|
||||
13310,P_Huuma_Suriken1,P.Huuma Suriken I,5,0,,0,170,,1,0,0x02000000,63,2,34,3,60,0,22,{ bonus bMatk,50; },{},{}
|
||||
13311,Huuma_Shadow,Sword Huuma Shuriken,5,5000,,1500,170,,1,0,0x02000000,63,2,34,3,99,1,22,{ bonus bStr,3; },{},{}
|
||||
13312,Huuma_Job_Test,Prototype Huuma Shuriken,5,0,,3000,0,,1,0,0x02000000,63,2,34,4,99,1,22,{},{},{}
|
||||
13313,Huuma_Swirling_Petal,Flower Huuma Shuriken,5,100000,,1500,150,,1,2,0x02000000,63,2,34,3,110,1,22,{ bonus bMatk,50; bonus bAtkEle,Ele_Fire; bonus2 bSkillAtk,"KO_HUUMARANKA",20; },{},{}
|
||||
13313,Huuma_Swirling_Petal,Flower Huuma Shuriken,5,100000,,1500,150,,1,2,0x02000000,63,2,34,3,110,1,22,{ bonus bMatk,50; bonus2 bSkillAtk,"KO_HUUMARANKA",20; },{},{}
|
||||
13314,Huuma_Fluttering_Snow,Wave Huuma Shuriken,5,100000,,1500,200,,1,0,0x02000000,63,2,34,4,110,1,22,{ bonus bMatk,50; bonus bAtkEle,Ele_Water; bonus3 bAutoSpell,"NJ_HYOUSYOURAKU",(getskilllv("NJ_HYOUSYOURAKU")?getskilllv("NJ_HYOUSYOURAKU"):1),30; },{},{}
|
||||
13315,Huuma_Thunderstorm,Thunderstorm Huuma Shuriken,5,100000,,1500,200,,1,0,0x02000000,63,2,34,4,110,1,22,{ bonus bMatk,50; bonus bAtkEle,Ele_Wind; bonus3 bAutoSpell,"NJ_RAIGEKISAI",(getskilllv("NJ_RAIGEKISAI")?getskilllv("NJ_RAIGEKISAI"):1),30; },{},{}
|
||||
13316,Upg_Huuma_Shuriken,Upg Huuma Shuriken,5,20,,1500,55,,1,1,0x02000000,63,2,34,3,1,1,22,{ bonus bBaseAtk,(getrefine()*10); bonus bMatk,(getrefine()*5); bonus bLongAtkRate,(getrefine()); if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*5); },{},{}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Skill Unit Database
|
||||
//
|
||||
// Structure of Database:
|
||||
// ID,unit ID,unit ID 2,layout,range,interval,target,flag
|
||||
// Skill ID,Unit ID,Unit ID 2,Layout,Range,Interval,Target,Flag
|
||||
//
|
||||
// layout = -1:special, 0:1*1, 1:3*3, 2:5*5, up to 5:11*11
|
||||
// target = friend (party +guildmates +neutral players) / party / guild
|
||||
@ -153,7 +153,7 @@
|
||||
2468,0xf4, , 0, 1,1000,all, 0x010 //SO_EARTH_INSIGNIA
|
||||
|
||||
2479,0xe5, , 0, 1,1000,enemy, 0xC006 //GN_THORNS_TRAP
|
||||
2482,0xe6,0x7f, 0, 1, 100,all, 0xD000 //GN_WALLOFTHORN
|
||||
2482,0xe6,0x7f, -1, 1, 300,enemy, 0xD000 //GN_WALLOFTHORN
|
||||
2484,0x86, , 0, 1, 100,enemy, 0x080 //GN_CRAZYWEED_ATK
|
||||
2485,0xe7, , 0, 2,2000,enemy, 0x8098 //GN_DEMONIC_FIRE
|
||||
2487,0xe8, , 2, 0, -1,enemy, 0x2000 //GN_FIRE_EXPANSION_SMOKE_POWDER
|
||||
|
@ -125,7 +125,7 @@ geffen,147,26,0 script Ralphie 97,{
|
||||
}
|
||||
|
||||
geffen,111,48,0 script Stacey 101,{
|
||||
if (getequipid(1) == 2299) {
|
||||
if (getequipid(EQI_HEAD_TOP) == 2299) {
|
||||
mes "[Stacey]";
|
||||
mes "Oh...!";
|
||||
mes "Is that an Orc Helm you're wearing?! That's so cool! Wow...";
|
||||
@ -141,7 +141,7 @@ geffen,111,48,0 script Stacey 101,{
|
||||
}
|
||||
close;
|
||||
}
|
||||
else if (getequipid(1) == 5094) {
|
||||
else if (getequipid(EQI_HEAD_TOP) == 5094) {
|
||||
mes "[Stacey]";
|
||||
mes "Oh...";
|
||||
mes "Wow...";
|
||||
|
@ -394,19 +394,19 @@ OnTimer55000:
|
||||
|
||||
//Subfunction: Checks that the groom/bride is still wearing their stuff.
|
||||
function SF_equip_check {
|
||||
if (Sex && getequipid(2) != 7170) {
|
||||
if (Sex && getequipid(EQI_ARMOR) != 7170) {
|
||||
mes "["+@name$+"]";
|
||||
mes "Child, what did you do with your "+getitemname(7170)+"?";
|
||||
emotion e_dots;
|
||||
return 0;
|
||||
}
|
||||
if (Sex == 0 && getequipid(2) != 2338) {
|
||||
if (Sex == 0 && getequipid(EQI_ARMOR) != 2338) {
|
||||
mes "["+@name$+"]";
|
||||
mes "Child, you are supposed to wear a "+getitemname(2338)+" at all times during the ceremony...";
|
||||
emotion e_dots;
|
||||
return 0;
|
||||
}
|
||||
if (Sex == 0 && $@wed_veil && getequipid(1) != 2206) {
|
||||
if (Sex == 0 && $@wed_veil && getequipid(EQI_HEAD_TOP) != 2206) {
|
||||
mes "["+@name$+"]";
|
||||
mes "Child, you can't take off your "+getitemname(2206)+" yet....";
|
||||
emotion e_dots;
|
||||
@ -692,12 +692,12 @@ function SF_TryRegister {
|
||||
else
|
||||
set @item, 2338;
|
||||
|
||||
if (getequipid(2) != @item) {
|
||||
if (getequipid(EQI_ARMOR) != @item) {
|
||||
mes "["+@name$+"]";
|
||||
mes "You should be wearing a "+getitemname(@item)+" if you want to get married.";
|
||||
close;
|
||||
}
|
||||
if (Sex == 0 && $@wed_veil && getequipid(1) != 2206) {
|
||||
if (Sex == 0 && $@wed_veil && getequipid(EQI_HEAD_TOP) != 2206) {
|
||||
mes "["+@name$+"]";
|
||||
mes "Where is your "+getitemname(2206)+"? It's a necessary complement to your dress.";
|
||||
close;
|
||||
|
@ -119,7 +119,7 @@ prt_in,24,61,7 script Perchik 47,{
|
||||
if (!countitem2(.@id,1,.@ref,0,.@slot[0],.@slot[1],.@slot[2],.@slot[3])) {
|
||||
mes "Where is "+getitemname(@id)+"...?";
|
||||
npctalk "You're a snoozy cheater!";
|
||||
logmes "CHEATER: Tried to sign an item not having it: "+getitemname(@id);
|
||||
logmes "Hack: Tried to sign an item not having it: "+getitemname(@id);
|
||||
emotion e_wah;
|
||||
close;
|
||||
}
|
||||
|
@ -67,6 +67,11 @@ prontera,147,61,3 script Driller#pron 87,{
|
||||
mes "This item has already been enchanted. I can't work on this as it is against the rules.";
|
||||
close;
|
||||
}
|
||||
|
||||
// anti-hack
|
||||
if (callfunc("F_IsEquipIDHack", .@part, .@equip_id))
|
||||
close;
|
||||
|
||||
delequip .@part;
|
||||
if (rand(1,10) > 5) {
|
||||
getitem .@slotted,1;
|
||||
@ -113,7 +118,6 @@ prontera,147,59,3 script Goldberg#pron 878,{
|
||||
mes "Alright, then, see you next time...";
|
||||
close;
|
||||
}
|
||||
set .@equip_refine, getequiprefinerycnt(.@part);
|
||||
setarray .@equip_card[0], getequipcardid(.@part,0),getequipcardid(.@part,1),getequipcardid(.@part,2),getequipcardid(.@part,3);
|
||||
if (.@select == 1) {
|
||||
switch(getequipid(.@part)) {
|
||||
@ -257,6 +261,11 @@ prontera,147,59,3 script Goldberg#pron 878,{
|
||||
else if (.@i < 301) set .@enchant, .@enc[2];
|
||||
else set .@enchant,9;
|
||||
|
||||
// anti-hack
|
||||
if (callfunc("F_IsEquipIDHack", .@part, .@equip_id) ||
|
||||
callfunc("F_IsEquipCardHack", .@part, .@equip_card[0], .@equip_card[1], .@equip_card[2], .@equip_card[3]))
|
||||
close;
|
||||
|
||||
set .@equip_card[.@slot], .@enchant;
|
||||
if (.@slot == 2 && .@enchant == 0) {
|
||||
set .@equip_card[3],0;
|
||||
@ -269,6 +278,7 @@ prontera,147,59,3 script Goldberg#pron 878,{
|
||||
set .@equip_card[3],0;
|
||||
}
|
||||
|
||||
set .@equip_refine, getequiprefinerycnt(.@part);
|
||||
delequip .@part;
|
||||
if (.@enchant == 9) {
|
||||
mes "[Goldberg]";
|
||||
|
@ -104,6 +104,6 @@ L_Reset:
|
||||
mes @npcname$;
|
||||
mes "Thank you.";
|
||||
emotion e_thx;
|
||||
logmes "SKILL RESET EVENT";
|
||||
// logmes "SKILL RESET EVENT";
|
||||
close;
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ mosk_in,21,244,3 script Baker Extraordinaire 410,{
|
||||
close;
|
||||
} else if(#V_QUE12==1) {
|
||||
mes .@n$;
|
||||
if (getequipid(1) == 5024 && getequiprefinerycnt(1) >= 8) {
|
||||
if (getequipid(EQI_HEAD_TOP) == 5024 && getequiprefinerycnt(EQI_HEAD_TOP) >= 8) {
|
||||
mes "Ah, so Pinkamenia told you";
|
||||
mes "to bring me the +8 Cake";
|
||||
mes "Hat. Now I'm going";
|
||||
|
@ -360,7 +360,7 @@ prt_castle,164,32,1 script Man in Anguish 733,{
|
||||
mes "Let me take";
|
||||
mes "a look at your face.";
|
||||
next;
|
||||
if(getequipid(7) != 2608 && getequipid(8) != 2608) {
|
||||
if(getequipid(EQI_ACC_L) != 2608 && getequipid(EQI_ACC_R) != 2608) {
|
||||
mes "[Murnak Mijoul]";
|
||||
mes "Hmm. You wish to become a Crusader, but do not wear a Rosary? I have no business with you if you cannot uphold our customs.";
|
||||
close;
|
||||
@ -401,7 +401,7 @@ prt_castle,164,32,1 script Man in Anguish 733,{
|
||||
mes "I'll let you retake the test as much as you like. But if you continuously fail, there's an inherent problem with your";
|
||||
mes "state of mind.";
|
||||
next;
|
||||
if(getequipid(7) != 2608 && getequipid(8) != 2608) {
|
||||
if(getequipid(EQI_ACC_L) != 2608 && getequipid(EQI_ACC_R) != 2608) {
|
||||
mes "[Murnak Mijoul]";
|
||||
mes "Wait...";
|
||||
mes "Where have you left your Rosary? You can't let that lie around just anywhere. We are supposed to be warriors of holiness.";
|
||||
@ -888,7 +888,7 @@ prt_castle,35,151,5 script Patron Knight 751,{
|
||||
}
|
||||
next;
|
||||
if (select("I would like to begin.:Give me some time to prepare.") == 1) {
|
||||
if(getequipid(7) != 2608 && getequipid(8) != 2608) {
|
||||
if(getequipid(EQI_ACC_L) != 2608 && getequipid(EQI_ACC_R) != 2608) {
|
||||
mes "[Bliant Piyord]";
|
||||
mes "Just a second, you do not have a Rosary equipped. As a Crusader, you must always have a Rosary on your person.";
|
||||
next;
|
||||
|
@ -578,7 +578,7 @@ function script F_EntKafCode {
|
||||
set @kafcode_try,@kafcode_try+1;
|
||||
if(@kafcode_try>10) {
|
||||
set @kafcode_try,0;
|
||||
logmes "Hack: Tried to fit storage password.";
|
||||
logmes "Tried to fit storage password.";
|
||||
}
|
||||
if(input(@code_) == 1) {
|
||||
mes "You can't use such big password.";
|
||||
|
@ -708,13 +708,9 @@ function script refinemain {
|
||||
set Zeny, Zeny-.@price;
|
||||
delitem .@material,1;
|
||||
|
||||
//custom checks
|
||||
if(getequipisequiped(.@part) == 0) { // hacker has removed the item (not changed, why?)
|
||||
mes "[" + getarg(0) + "]";
|
||||
mes "Look here... you don't have any Items on...";
|
||||
close;
|
||||
}
|
||||
if(getequiprefinerycnt(.@part) != .@refinerycnt || getequipid(.@part) != .@refineitemid) { // hacker has changed the item
|
||||
// anti-hack
|
||||
if (callfunc("F_IsEquipIDHack", .@part, .@refineitemid) ||
|
||||
callfunc("F_IsEquipRefineHack", .@part, .@refinerycnt)) {
|
||||
mes "[" + getarg(0) + "]";
|
||||
emotion e_an;
|
||||
mes "Wait a second...";
|
||||
|
@ -3,7 +3,7 @@
|
||||
//===== By: ==================================================
|
||||
//= Lupus, kobra_k88
|
||||
//===== Current Version: =====================================
|
||||
//= 2.23
|
||||
//= 2.24
|
||||
//===== Compatible With: =====================================
|
||||
//= rAthena Project
|
||||
//===== Description: =========================================
|
||||
@ -46,6 +46,7 @@
|
||||
//= 2.21 Added format string to "F_InsertPlural" and more checks to "F_GetPlural". [Euphy]
|
||||
//= 2.22 Further improvements to "F_GetPlural". [Euphy]
|
||||
//= 2.23 Completed article function and added "F_GetArticle". [Euphy]
|
||||
//= 2.24 Added functions to check for equipment swap hacks. [Euphy]
|
||||
//============================================================
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
@ -139,7 +140,7 @@ function script F_ClearGarbage {
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
function script Job_Change {
|
||||
jobchange getarg(0),Upper;
|
||||
logmes "CLASS CHANGE: " +strcharinfo(0)+ " become a "+jobname(Class);
|
||||
// logmes "CLASS CHANGE: " +strcharinfo(0)+ " become a "+jobname(Class);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -362,6 +363,47 @@ function script Time2Str {
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Checks if equipment has been swapped (i.e. via hacks).
|
||||
// The function checks the current equipment at a position against the supplied
|
||||
// values, and logs any mismatches.
|
||||
// Returns 0 if match, 1 if mismatch.
|
||||
// -- callfunc "F_IsEquipIDHack",<equip position>,<equip ID>
|
||||
// -- callfunc "F_IsEquipRefineHack",<equip position>,<refine>
|
||||
// -- callfunc "F_IsEquipCardHack",<equip position>,<card 0>,<card 1>,<card 2>,<card 3>
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
function script F_IsEquipIDHack {
|
||||
set .@id_chk, getequipid(getarg(0));
|
||||
set .@id, getarg(1);
|
||||
if (.@id != .@id_chk) {
|
||||
logmes "Hack: Tried to swap equip " + getitemname(.@id) + " for " + getitemname(.@id_chk) + ".";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
function script F_IsEquipRefineHack {
|
||||
set .@refine_chk, getequiprefinerycnt(getarg(0));
|
||||
set .@refine, getarg(1);
|
||||
if (.@refine != .@refine_chk) {
|
||||
logmes "Hack: Tried to swap equip with refine +" + .@refine + " for +" + .@refine_chk + ".";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
function script F_IsEquipCardHack {
|
||||
set .@pos, getarg(0);
|
||||
for (set .@i,0; .@i < 4; set .@i, .@i+1) {
|
||||
set .@card, getarg(.@i + 1);
|
||||
set .@card_chk, getequipcardid(.@pos, .@i);
|
||||
if (.@card != .@card_chk) {
|
||||
logmes "Hack: Tried to swap card " + getitemname(.@card) + " for " + getitemname(.@card_chk) + ".";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Functions for text manipulation [Euphy]
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -79,7 +79,7 @@ prt_castle,43,30,3 script Charles Orleans#cook 878,{
|
||||
mes "the stairs for me, alright?";
|
||||
goto L_End;
|
||||
}
|
||||
else if (getequipid(1) != 5026) {
|
||||
else if (getequipid(EQI_HEAD_TOP) != 5026) {
|
||||
if (Sex) {
|
||||
cutin "orleans_5",0;
|
||||
emotion e_an;
|
||||
|
@ -924,20 +924,20 @@ lhz_cube,233,24,4 script Sorcerer#Bio4Reward 4_M_UMDANCEKID,{
|
||||
.@refine_count = getequiprefinerycnt(.@part);
|
||||
.@equip_item = getequipid(.@part);
|
||||
.@lhz_max_num = 4000;
|
||||
if (.@equip_item == Agent_Katar || .@equip_item == Guillotine_Katar || .@equip_item == Ygnus_Stale ||
|
||||
.@equip_item == End_Sektura || .@equip_item = Cannon_Spear || .@equip_item == Giant_Lance ||
|
||||
.@equip_item == Aztoe_Nail || .@equip_item == Scarletto_Nail || .@equip_item == Bloody_Cross) {
|
||||
if (.@equip_item == 13069 || .@equip_item == 1291 || .@equip_item == 1392 ||
|
||||
.@equip_item == 1393 || .@equip_item = 1435 || .@equip_item == 1490 ||
|
||||
.@equip_item == 13069 || .@equip_item == 13070 || .@equip_item == 16017) {
|
||||
.@type = 1;
|
||||
if (.@equip_item == Giant_Lance)
|
||||
if (.@equip_item == 1490)
|
||||
.@lhz_max_num = 4200;
|
||||
} else if (.@equip_item == Catapult || .@equip_item == Big_CrossBow || .@equip_item == Creeper_Bow) {
|
||||
} else if (.@equip_item == 18109 || .@equip_item == 18110 || .@equip_item == 18111) {
|
||||
.@type = 2;
|
||||
} else if (.@equip_item == Chilly_Spell_Book || .@equip_item == Recovery_Light) {
|
||||
} else if (.@equip_item == 1584 || .@equip_item == 1659) {
|
||||
.@type = 3;
|
||||
} else if (.@equip_item== Giant_Shield || .@equip_item == Geffenia_Book_Water || .@equip_item == Bible_Of_Promise2 ||
|
||||
.@equip_item == Salvage_Cape || .@equip_item == Assassin_Handcuffs || .@equip_item == Green_Operation_Coat ||
|
||||
.@equip_item == Ancient_Gold_Deco) {
|
||||
if (.@equip_item == Salvage_Cape || .@equip_item == Ancient_Gold_Deco)
|
||||
} else if (.@equip_item == 2160 || .@equip_item == 2161 || .@equip_item == 2162 ||
|
||||
.@equip_item == 2582 || .@equip_item == 2892 || .@equip_item == 15044 ||
|
||||
.@equip_item == 18570) {
|
||||
if (.@equip_item == 2582 || .@equip_item == 18570)
|
||||
.@lhz_max_num = 4200;
|
||||
} else {
|
||||
mes "[Pudding]";
|
||||
@ -1258,12 +1258,6 @@ lhz_cube,233,24,4 script Sorcerer#Bio4Reward 4_M_UMDANCEKID,{
|
||||
} else {
|
||||
specialeffect2 EF_FIREHIT;
|
||||
getitem2 .@equip_item, 1, 1, .@refine_count, 0, .@equip_card[0], .@equip_card[1], .@equip_card[2], .@equip_card[3];
|
||||
//dispbottom "1:"+ .@equip_item;
|
||||
//dispbottom "1:"+ .@refine_count;
|
||||
//dispbottom "1:"+ .@equip_card[0];
|
||||
//dispbottom "1:"+ .@equip_card[1];
|
||||
//dispbottom "1:"+ .@equip_card[2];
|
||||
//dispbottom "1:"+ .@equip_card[3];
|
||||
emotion e_ho;
|
||||
mes "[Pudding]";
|
||||
mes "Fortunately the power of "+((.@socket_type==3)?"'^952420Thirst for Blood^000000'":"'^F2766EWill of Warrior^000000'")+" has been dwelt well in your equipment...";
|
||||
|
@ -285,6 +285,11 @@
|
||||
|
||||
set .@equip_id, getequipid(.@equip_num);
|
||||
set .@equip_refine, getequiprefinerycnt(.@equip_num);
|
||||
|
||||
// anti-hack
|
||||
if (callfunc("F_IsEquipCardHack", .@equip_num, .@equip_card[0], .@equip_card[1], .@equip_card[2], .@equip_card[3]))
|
||||
close;
|
||||
|
||||
delequip .@equip_num;
|
||||
|
||||
// Chance of retaining refine level.
|
||||
|
@ -318,7 +318,6 @@ L_Socket:
|
||||
set .@select, @mal_enchant_select;
|
||||
set .@equip_id, @mal_equip_id;
|
||||
set .@equip_name$, getitemname(.@equip_id)+((getitemslots(.@equip_id))?"["+getitemslots(.@equip_id)+"]":"");
|
||||
set .@equip_refine, getequiprefinerycnt(EQI_HAND_R);
|
||||
setarray .@equip_card[0], getequipcardid(EQI_HAND_R,0),getequipcardid(EQI_HAND_R,1),getequipcardid(EQI_HAND_R,2),getequipcardid(EQI_HAND_R,3);
|
||||
set @mal_equip_id,0;
|
||||
set @mal_enchant_select,0;
|
||||
@ -570,6 +569,12 @@ L_Socket:
|
||||
mes "There is something wrong. Please try again.";
|
||||
close;
|
||||
}
|
||||
|
||||
// anti-hack
|
||||
if (callfunc("F_IsEquipIDHack", EQI_HAND_R, .@equip_id) ||
|
||||
callfunc("F_IsEquipCardHack", EQI_HAND_R, .@equip_card[0], .@equip_card[1], .@equip_card[2], .@equip_card[3]))
|
||||
close;
|
||||
|
||||
if (.@equip_card[3] == 0 && getarg(1) < 4) set .@equip_card[3],.@enchant;
|
||||
else if (.@equip_card[2] == 0 && getarg(1) < 3) set .@equip_card[2],.@enchant;
|
||||
else if (.@equip_card[1] == 0 && getarg(1) < 2) set .@equip_card[1],.@enchant;
|
||||
@ -595,6 +600,7 @@ L_Socket:
|
||||
mes "[Mayomayo]";
|
||||
mes "I have enchanted ^990000slot "+.@socket+"^000000 of this equipment.";
|
||||
delitem .@coin[.@coin_select],.@total[.@coin_select];
|
||||
set .@equip_refine, getequiprefinerycnt(EQI_HAND_R);
|
||||
delequip EQI_HAND_R;
|
||||
|
||||
// GetNonSlotItemSock2 .@equip_refine .@equip_id .@equip_card[0] .@equip_card[1] .@equip_card[2] .@equip_card[3]
|
||||
@ -629,6 +635,13 @@ L_Socket:
|
||||
mes "[Mayomayo]";
|
||||
mes "Initialize the enchant effect from the equipment.";
|
||||
delitem 6417,1; //Silvervine
|
||||
|
||||
// anti-hack
|
||||
if (callfunc("F_IsEquipIDHack", EQI_HAND_R, .@equip_id) ||
|
||||
callfunc("F_IsEquipCardHack", EQI_HAND_R, .@equip_card[0], .@equip_card[1], .@equip_card[2], .@equip_card[3]))
|
||||
close;
|
||||
|
||||
set .@equip_refine, getequiprefinerycnt(EQI_HAND_R);
|
||||
delequip EQI_HAND_R;
|
||||
|
||||
// GetNonSlotItemSock2 .@equip_refine .@equip_id .@equip_card[0] .@equip_card[1] .@equip_card[2] .@equip_card[3]
|
||||
|
@ -1078,6 +1078,13 @@ L_Socket:
|
||||
mes "Well I guess I was wrong...";
|
||||
close;
|
||||
}
|
||||
|
||||
// anti-hack
|
||||
if (callfunc("F_IsEquipIDHack", .@part, .@equip_id) ||
|
||||
callfunc("F_IsEquipRefineHack", .@part, .@equip_refine) ||
|
||||
callfunc("F_IsEquipCardHack", .@part, .@equip_card[0], .@equip_card[1], .@equip_card[2], .@equip_card[3]))
|
||||
close;
|
||||
|
||||
if (.@equip_card[3] == 0 && getarg(2) < 4) {
|
||||
set .@equip_card[3],.@enchant;
|
||||
} else if (.@equip_card[2] == 0 && getarg(2) < 3) {
|
||||
@ -1103,6 +1110,13 @@ L_Socket:
|
||||
}
|
||||
delitem 6380,1; //Mora_Coin
|
||||
set Zeny, Zeny-100000;
|
||||
|
||||
// anti-hack
|
||||
if (callfunc("F_IsEquipIDHack", .@part, .@equip_id) ||
|
||||
callfunc("F_IsEquipRefineHack", .@part, .@equip_refine) ||
|
||||
callfunc("F_IsEquipCardHack", .@part, .@equip_card[0], .@equip_card[1], .@equip_card[2], .@equip_card[3]))
|
||||
close;
|
||||
|
||||
delequip .@part;
|
||||
if (.@enchant == 9) {
|
||||
specialeffect2 EF_SUI_EXPLOSION;
|
||||
|
@ -89,7 +89,6 @@ prt_in,28,73,3 script Devil Enchant Master#prq 63,{
|
||||
mes "I don't want to touch your equipment now!";
|
||||
close;
|
||||
}
|
||||
set .@equip_refine, getequiprefinerycnt(.@part);
|
||||
|
||||
if (.@select == 1) {
|
||||
if (!countitem(6484)) {
|
||||
@ -218,6 +217,7 @@ prt_in,28,73,3 script Devil Enchant Master#prq 63,{
|
||||
mes "Are you listening to me? I will only do for you if you bring the Enchant Book!";
|
||||
close;
|
||||
}
|
||||
set .@equip_refine, getequiprefinerycnt(.@part);
|
||||
if (.@enchant == 0) {
|
||||
specialeffect EF_SHIELDCHARGE;
|
||||
mes "Oh! Unbelievable!! It failed!! Please come again!";
|
||||
@ -228,6 +228,12 @@ prt_in,28,73,3 script Devil Enchant Master#prq 63,{
|
||||
mes "The slot ^9900004^000000 has been enchanted!";
|
||||
}
|
||||
delitem 6484,1; //Enchant_Book
|
||||
|
||||
// anti-hack
|
||||
if (callfunc("F_IsEquipIDHack", .@part, .@equip_id) ||
|
||||
callfunc("F_IsEquipCardHack", .@part, .@equip_card[0], .@equip_card[1], .@equip_card[2], .@equip_card[3]))
|
||||
close;
|
||||
|
||||
delequip .@part;
|
||||
|
||||
// GetNonSlotItemSock2 .@equip_refine .@equip_id .@equip_card[0] .@equip_card[1] .@equip_card[2] .@enchant
|
||||
@ -255,6 +261,13 @@ prt_in,28,73,3 script Devil Enchant Master#prq 63,{
|
||||
specialeffect EF_REPAIRWEAPON;
|
||||
mes "I initialized the enchant effects.";
|
||||
set Zeny, Zeny - 100000;
|
||||
|
||||
// anti-hack
|
||||
if (callfunc("F_IsEquipIDHack", .@part, .@equip_id) ||
|
||||
callfunc("F_IsEquipCardHack", .@part, .@equip_card[0], .@equip_card[1], .@equip_card[2], .@equip_card[3]))
|
||||
close;
|
||||
|
||||
set .@equip_refine, getequiprefinerycnt(.@part);
|
||||
delequip .@part;
|
||||
|
||||
// GetNonSlotItemSock2 .@equip_refine .@equip_id .@equip_card[0] .@equip_card[1] .@equip_card[2] 0
|
||||
|
@ -157,13 +157,9 @@ function script refinenew {
|
||||
set Zeny,Zeny - .@price;
|
||||
delitem .@material,1;
|
||||
|
||||
//custom checks
|
||||
if (getequipisequiped(.@part) == 0) { // hacker has removed the item (not changed, why?)
|
||||
mes "[" + getarg(0) + "]";
|
||||
mes "Look here... you don't have any items on...";
|
||||
close;
|
||||
}
|
||||
if (getequiprefinerycnt(.@part) != .@refinerycnt || getequipid(.@part) != .@refineitemid) { // hacker has changed the item
|
||||
// anti-hack
|
||||
if (callfunc("F_IsEquipIDHack", .@part, .@refineitemid) ||
|
||||
callfunc("F_IsEquipRefineHack", .@part, .@refinerycnt)) {
|
||||
mes "[" + getarg(0) + "]";
|
||||
emotion e_an;
|
||||
mes "Wait a second...";
|
||||
|
@ -3773,7 +3773,7 @@ ma_fild01,158,243,6 script Tribe Blacksmith#malaya 582,{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(.@item)) {
|
||||
if (!getequipisequiped(.@part)) {
|
||||
mes "[Bayani]";
|
||||
mes "You should wear the equipment to upgrade and not come without it on you.";
|
||||
close;
|
||||
@ -3819,11 +3819,14 @@ ma_fild01,158,243,6 script Tribe Blacksmith#malaya 582,{
|
||||
mes "[Bayani]";
|
||||
mes "BAM!!";
|
||||
next;
|
||||
|
||||
delitem 6499,20; //Ancient_Grudge
|
||||
|
||||
// anti-hack
|
||||
if (callfunc("F_IsEquipIDHack", .@part, .@item))
|
||||
close;
|
||||
|
||||
delequip .@part;
|
||||
getitem .@newItem, 1;
|
||||
|
||||
mes "[Bayani]";
|
||||
mes "Ha ha. Perfect.";
|
||||
mes "Congratulations. Your armor is better than ever.";
|
||||
|
@ -7021,7 +7021,7 @@ REPLACE INTO `item_db_re` VALUES (13309,'Huuma_Giant_Wheel_C','Huuma Giant Wheel
|
||||
REPLACE INTO `item_db_re` VALUES (13310,'P_Huuma_Suriken1','P.Huuma Suriken I',5,0,NULL,0,'170',NULL,1,0,0x02000000,63,2,34,3,'60',0,22,'bonus bMatk,50;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (13311,'Huuma_Shadow','Sword Huuma Shuriken',5,5000,NULL,1500,'170',NULL,1,0,0x02000000,63,2,34,3,'99',1,22,'bonus bStr,3;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (13312,'Huuma_Job_Test','Prototype Huuma Shuriken',5,0,NULL,3000,'0',NULL,1,0,0x02000000,63,2,34,4,'99',1,22,NULL,NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (13313,'Huuma_Swirling_Petal','Flower Huuma Shuriken',5,100000,NULL,1500,'150',NULL,1,2,0x02000000,63,2,34,3,'110',1,22,'bonus bMatk,50; bonus bAtkEle,Ele_Fire; bonus2 bSkillAtk,"KO_HUUMARANKA",20;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (13313,'Huuma_Swirling_Petal','Flower Huuma Shuriken',5,100000,NULL,1500,'150',NULL,1,2,0x02000000,63,2,34,3,'110',1,22,'bonus bMatk,50; bonus2 bSkillAtk,"KO_HUUMARANKA",20;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (13314,'Huuma_Fluttering_Snow','Wave Huuma Shuriken',5,100000,NULL,1500,'200',NULL,1,0,0x02000000,63,2,34,4,'110',1,22,'bonus bMatk,50; bonus bAtkEle,Ele_Water; bonus3 bAutoSpell,"NJ_HYOUSYOURAKU",(getskilllv("NJ_HYOUSYOURAKU")?getskilllv("NJ_HYOUSYOURAKU"):1),30;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (13315,'Huuma_Thunderstorm','Thunderstorm Huuma Shuriken',5,100000,NULL,1500,'200',NULL,1,0,0x02000000,63,2,34,4,'110',1,22,'bonus bMatk,50; bonus bAtkEle,Ele_Wind; bonus3 bAutoSpell,"NJ_RAIGEKISAI",(getskilllv("NJ_RAIGEKISAI")?getskilllv("NJ_RAIGEKISAI"):1),30;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (13316,'Upg_Huuma_Shuriken','Upg Huuma Shuriken',5,20,NULL,1500,'55',NULL,1,1,0x02000000,63,2,34,3,'1',1,22,'bonus bBaseAtk,(getrefine()*10); bonus bMatk,(getrefine()*5); bonus bLongAtkRate,(getrefine()); if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*5);',NULL,NULL);
|
||||
|
@ -6277,14 +6277,14 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
|
||||
* Initial refactoring by Baalberith
|
||||
* Refined and optimized by helvetica
|
||||
*/
|
||||
struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,uint16 skill_id,uint16 skill_lv,int count)
|
||||
struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,uint16 skill_id,uint16 skill_lv,int flag)
|
||||
{
|
||||
struct Damage d;
|
||||
|
||||
switch(attack_type) {
|
||||
case BF_WEAPON: d = battle_calc_weapon_attack(bl,target,skill_id,skill_lv,count); break;
|
||||
case BF_MAGIC: d = battle_calc_magic_attack(bl,target,skill_id,skill_lv,count); break;
|
||||
case BF_MISC: d = battle_calc_misc_attack(bl,target,skill_id,skill_lv,count); break;
|
||||
case BF_WEAPON: d = battle_calc_weapon_attack(bl,target,skill_id,skill_lv,flag); break;
|
||||
case BF_MAGIC: d = battle_calc_magic_attack(bl,target,skill_id,skill_lv,flag); break;
|
||||
case BF_MISC: d = battle_calc_misc_attack(bl,target,skill_id,skill_lv,flag); break;
|
||||
default:
|
||||
ShowError("battle_calc_attack: unknown attack type! %d (skill_id=%d, skill_lv=%d)\n", attack_type, skill_id, skill_lv);
|
||||
memset(&d,0,sizeof(d));
|
||||
@ -7798,6 +7798,7 @@ static const struct _battle_data {
|
||||
{ "at_monsterignore", &battle_config.autotrade_monsterignore, 0, 0, 1, },
|
||||
{ "idletime_option", &battle_config.idletime_option, 0x25, 1, INT_MAX, },
|
||||
{ "spawn_direction", &battle_config.spawn_direction, 0, 0, 1, },
|
||||
{ "arrow_shower_knockback", &battle_config.arrow_shower_knockback, 1, 0, 1, },
|
||||
};
|
||||
#ifndef STATS_OPT_OUT
|
||||
/**
|
||||
|
@ -79,7 +79,7 @@ struct block_list;
|
||||
|
||||
// Damage Calculation
|
||||
|
||||
struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,uint16 skill_id,uint16 skill_lv,int count);
|
||||
struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,uint16 skill_id,uint16 skill_lv,int flag);
|
||||
|
||||
int64 battle_calc_return_damage(struct block_list *bl, struct block_list *src, int64 *, int flag, uint16 skill_id, bool status_reflect);
|
||||
|
||||
@ -567,6 +567,7 @@ extern struct Battle_Config
|
||||
int autotrade_monsterignore;
|
||||
int idletime_option;
|
||||
int spawn_direction;
|
||||
int arrow_shower_knockback;
|
||||
} battle_config;
|
||||
|
||||
void do_init_battle(void);
|
||||
|
149
src/map/script.c
149
src/map/script.c
@ -8092,12 +8092,12 @@ BUILDIN_FUNC(getequippercentrefinery)
|
||||
/*==========================================
|
||||
* Refine +1 item at pos and log and display refine
|
||||
*------------------------------------------*/
|
||||
BUILDIN_FUNC(successrefitem)
|
||||
{
|
||||
int i = -1, num, up = 1;
|
||||
BUILDIN_FUNC(successrefitem) {
|
||||
short i = -1, up = 1;
|
||||
int pos;
|
||||
TBL_PC *sd;
|
||||
|
||||
num = script_getnum(st,2);
|
||||
pos = script_getnum(st,2);
|
||||
sd = script_rid2sd(st);
|
||||
if (sd == NULL)
|
||||
return 0;
|
||||
@ -8105,16 +8105,18 @@ BUILDIN_FUNC(successrefitem)
|
||||
if (script_hasdata(st, 3))
|
||||
up = script_getnum(st, 3);
|
||||
|
||||
if (num > 0 && num <= ARRAYLENGTH(equip))
|
||||
i = pc_checkequip(sd,equip[num-1]);
|
||||
if (pos > 0 && pos <= ARRAYLENGTH(equip))
|
||||
i = pc_checkequip(sd,equip[pos-1]);
|
||||
if (i >= 0) {
|
||||
unsigned int ep = sd->status.inventory[i].equip;
|
||||
|
||||
//Logs items, got from (N)PC scripts [Lupus]
|
||||
log_pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i]);
|
||||
|
||||
if (sd->status.inventory[i].refine >= MAX_REFINE)
|
||||
if (sd->status.inventory[i].refine >= MAX_REFINE) {
|
||||
script_pushint(st, MAX_REFINE);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
sd->status.inventory[i].refine += up;
|
||||
sd->status.inventory[i].refine = cap_value( sd->status.inventory[i].refine, 0, MAX_REFINE);
|
||||
@ -8131,8 +8133,8 @@ BUILDIN_FUNC(successrefitem)
|
||||
clif_misceffect(&sd->bl,3);
|
||||
if (sd->status.inventory[i].refine == MAX_REFINE &&
|
||||
sd->status.inventory[i].card[0] == CARD0_FORGE &&
|
||||
sd->status.char_id == (int)MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3])
|
||||
){ // Fame point system [DracoRPG]
|
||||
sd->status.char_id == (int)MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3]))
|
||||
{ // Fame point system [DracoRPG]
|
||||
switch (sd->inventory_data[i]->wlv){
|
||||
case 1:
|
||||
pc_addfame(sd, battle_config.fame_refine_lv1); // Success to refine to +10 a lv1 weapon you forged = +1 fame point
|
||||
@ -8145,56 +8147,62 @@ BUILDIN_FUNC(successrefitem)
|
||||
break;
|
||||
}
|
||||
}
|
||||
script_pushint(st, sd->status.inventory[i].refine);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
ShowError("buildin_successrefitem: No item equipped at pos %d (CID=%d/AID=%d).\n", pos, sd->status.char_id, sd->status.account_id);
|
||||
script_pushint(st, -1);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Show a failed Refine +1 attempt
|
||||
*------------------------------------------*/
|
||||
BUILDIN_FUNC(failedrefitem)
|
||||
{
|
||||
int i=-1,num;
|
||||
BUILDIN_FUNC(failedrefitem) {
|
||||
short i = -1;
|
||||
int pos;
|
||||
TBL_PC *sd;
|
||||
|
||||
num = script_getnum(st,2);
|
||||
pos = script_getnum(st,2);
|
||||
sd = script_rid2sd(st);
|
||||
if (sd == NULL)
|
||||
return 0;
|
||||
|
||||
if (num > 0 && num <= ARRAYLENGTH(equip))
|
||||
i=pc_checkequip(sd,equip[num-1]);
|
||||
if (pos > 0 && pos <= ARRAYLENGTH(equip))
|
||||
i = pc_checkequip(sd,equip[pos-1]);
|
||||
if (i >= 0) {
|
||||
sd->status.inventory[i].refine = 0;
|
||||
pc_unequipitem(sd,i,3); //recalculate bonus
|
||||
clif_refine(sd->fd,1,i,sd->status.inventory[i].refine); //notify client of failure
|
||||
|
||||
pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT);
|
||||
|
||||
clif_misceffect(&sd->bl,2); // display failure effect
|
||||
script_pushint(st, 1);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
ShowError("buildin_failedrefitem: No item equipped at pos %d (CID=%d/AID=%d).\n", pos, sd->status.char_id, sd->status.account_id);
|
||||
script_pushint(st, 0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Downgrades an Equipment Part by -1 . [Masao]
|
||||
*------------------------------------------*/
|
||||
BUILDIN_FUNC(downrefitem)
|
||||
{
|
||||
int i = -1, num, down = 1;
|
||||
BUILDIN_FUNC(downrefitem) {
|
||||
short i = -1, down = 1;
|
||||
int pos;
|
||||
TBL_PC *sd;
|
||||
|
||||
sd = script_rid2sd(st);
|
||||
if( sd == NULL )
|
||||
return 0;
|
||||
num = script_getnum(st,2);
|
||||
pos = script_getnum(st,2);
|
||||
if (script_hasdata(st, 3))
|
||||
down = script_getnum(st, 3);
|
||||
|
||||
if (num > 0 && num <= ARRAYLENGTH(equip))
|
||||
i = pc_checkequip(sd,equip[num-1]);
|
||||
if (pos > 0 && pos <= ARRAYLENGTH(equip))
|
||||
i = pc_checkequip(sd,equip[pos-1]);
|
||||
if (i >= 0) {
|
||||
unsigned int ep = sd->status.inventory[i].equip;
|
||||
|
||||
@ -8214,30 +8222,40 @@ BUILDIN_FUNC(downrefitem)
|
||||
clif_additem(sd,i,1,0);
|
||||
pc_equipitem(sd,i,ep);
|
||||
clif_misceffect(&sd->bl,2);
|
||||
script_pushint(st, sd->status.inventory[i].refine);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
ShowError("buildin_downrefitem: No item equipped at pos %d (CID=%d/AID=%d).\n", pos, sd->status.char_id, sd->status.account_id);
|
||||
script_pushint(st, -1);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Delete the item equipped at pos.
|
||||
*------------------------------------------*/
|
||||
BUILDIN_FUNC(delequip)
|
||||
{
|
||||
int i=-1,num,ret=0;
|
||||
BUILDIN_FUNC(delequip) {
|
||||
short i = -1;
|
||||
int pos;
|
||||
int8 ret;
|
||||
TBL_PC *sd;
|
||||
|
||||
num = script_getnum(st,2);
|
||||
pos = script_getnum(st,2);
|
||||
sd = script_rid2sd(st);
|
||||
if (sd == NULL)
|
||||
return 0;
|
||||
|
||||
if (num > 0 && num <= ARRAYLENGTH(equip))
|
||||
i=pc_checkequip(sd,equip[num-1]);
|
||||
if (pos > 0 && pos <= ARRAYLENGTH(equip))
|
||||
i = pc_checkequip(sd,equip[pos-1]);
|
||||
if (i >= 0) {
|
||||
pc_unequipitem(sd,i,3); //recalculate bonus
|
||||
ret = !(pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT));
|
||||
}
|
||||
else {
|
||||
ShowError("buildin_delequip: No item equipped at pos %d (CID=%d/AID=%d).\n", pos, sd->status.char_id, sd->status.account_id);
|
||||
st->state = END;
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
script_pushint(st,ret);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
@ -8246,29 +8264,31 @@ BUILDIN_FUNC(delequip)
|
||||
/*==========================================
|
||||
* Break the item equipped at pos.
|
||||
*------------------------------------------*/
|
||||
BUILDIN_FUNC(breakequip)
|
||||
{
|
||||
int i=-1,num;
|
||||
BUILDIN_FUNC(breakequip) {
|
||||
short i = -1;
|
||||
int pos;
|
||||
TBL_PC *sd;
|
||||
|
||||
num = script_getnum(st,2);
|
||||
pos = script_getnum(st,2);
|
||||
sd = script_rid2sd(st);
|
||||
if (sd == NULL)
|
||||
return 0;
|
||||
|
||||
if (num > 0 && num <= ARRAYLENGTH(equip))
|
||||
i = pc_checkequip(sd,equip[num-1]);
|
||||
if (pos > 0 && pos <= ARRAYLENGTH(equip))
|
||||
i = pc_checkequip(sd,equip[pos-1]);
|
||||
if (i >= 0) {
|
||||
sd->status.inventory[i].attribute = 1;
|
||||
pc_unequipitem(sd,i,3);
|
||||
clif_equiplist(sd);
|
||||
script_pushint(st,1);
|
||||
} else
|
||||
script_pushint(st,0);
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
ShowError("buildin_breakequip: No item equipped at pos %d (CID=%d/AID=%d).\n", pos, sd->status.char_id, sd->status.account_id);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
*------------------------------------------*/
|
||||
@ -14254,43 +14274,50 @@ BUILDIN_FUNC(day)
|
||||
//=======================================================
|
||||
// Unequip [Spectre]
|
||||
//-------------------------------------------------------
|
||||
BUILDIN_FUNC(unequip)
|
||||
{
|
||||
size_t num;
|
||||
BUILDIN_FUNC(unequip) {
|
||||
int pos;
|
||||
TBL_PC *sd;
|
||||
|
||||
num = script_getnum(st,2);
|
||||
sd = script_rid2sd(st);
|
||||
if( sd != NULL && num >= 1 && num <= ARRAYLENGTH(equip) )
|
||||
{
|
||||
short i = pc_checkequip(sd,equip[num-1]);
|
||||
if (i >= 0)
|
||||
if (!(sd = script_rid2sd(st)))
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
|
||||
pos = script_getnum(st,2);
|
||||
if (pos >= 1 && pos <= ARRAYLENGTH(equip)) {
|
||||
short i = pc_checkequip(sd,equip[pos-1]);
|
||||
if (i >= 0) {
|
||||
pc_unequipitem(sd,i,1|2);
|
||||
}
|
||||
script_pushint(st, 1);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
}
|
||||
ShowError("buildin_unequip: No item equipped at pos %d (CID=%d/AID=%d).\n", pos, sd->status.char_id, sd->status.account_id);
|
||||
script_pushint(st, 0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
BUILDIN_FUNC(equip)
|
||||
{
|
||||
BUILDIN_FUNC(equip) {
|
||||
unsigned short nameid = 0;
|
||||
int i;
|
||||
TBL_PC *sd;
|
||||
struct item_data *item_data;
|
||||
|
||||
sd = script_rid2sd(st);
|
||||
if (!(sd = script_rid2sd(st)))
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
|
||||
nameid = script_getnum(st,2);
|
||||
if((item_data = itemdb_exists(nameid)) == NULL)
|
||||
{
|
||||
ShowError("wrong item ID : equipitem(%hu)\n",nameid);
|
||||
return 1;
|
||||
}
|
||||
if ((item_data = itemdb_exists(nameid))) {
|
||||
ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == nameid );
|
||||
if( i < MAX_INVENTORY )
|
||||
if (i < MAX_INVENTORY) {
|
||||
pc_equipitem(sd,i,item_data->equip);
|
||||
|
||||
script_pushint(st,1);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
ShowError("buildin_equip: Item %hu cannot be equipped\n",nameid);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
BUILDIN_FUNC(autoequip)
|
||||
{
|
||||
|
485
src/map/skill.c
485
src/map/skill.c
@ -112,8 +112,9 @@ int firewall_unit_pos;
|
||||
int icewall_unit_pos;
|
||||
int earthstrain_unit_pos;
|
||||
int firerain_unit_pos;
|
||||
int wallofthorn_unit_pos;
|
||||
|
||||
struct s_skill_nounit_layout skill_nounit_layout[MAX_SKILL_UNIT_LAYOUT];
|
||||
struct s_skill_nounit_layout skill_nounit_layout[MAX_SKILL_UNIT_LAYOUT2];
|
||||
int overbrand_nounit_pos;
|
||||
int overbrand_brandish_nounit_pos;
|
||||
|
||||
@ -771,6 +772,8 @@ struct s_skill_unit_layout* skill_get_unit_layout (uint16 skill_id, uint16 skill
|
||||
return &skill_unit_layout [earthstrain_unit_pos + dir];
|
||||
else if( skill_id == RL_FIRE_RAIN )
|
||||
return &skill_unit_layout[firerain_unit_pos + dir];
|
||||
else if( skill_id == GN_WALLOFTHORN )
|
||||
return &skill_unit_layout[wallofthorn_unit_pos + dir];
|
||||
|
||||
ShowError("skill_get_unit_layout: unknown unit layout for skill %d (level %d)\n", skill_id, skill_lv);
|
||||
return &skill_unit_layout[0]; // default 1x1 layout
|
||||
@ -2723,19 +2726,110 @@ static void skill_do_copy(struct block_list* src,struct block_list *bl, uint16 s
|
||||
clif_addskill(tsd,skill_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Knockback the target on skill_attack
|
||||
* @param src is the master behind the attack
|
||||
* @param dsrc is the actual originator of the damage, can be the same as src, or a BL_SKILL
|
||||
* @param target is the target to be attacked.
|
||||
* @param blewcount
|
||||
* @param skill_id
|
||||
* @param skill_lv
|
||||
* @param damage
|
||||
* @param tick
|
||||
* @param flag can hold a bunch of information:
|
||||
*/
|
||||
void skill_attack_blow(struct block_list *src, struct block_list *dsrc, struct block_list *target, uint8 blewcount, uint16 skill_id, uint16 skill_lv, int64 damage, unsigned int tick, int flag) {
|
||||
int8 dir = -1; // Default direction
|
||||
//Only knockback if it's still alive, otherwise a "ghost" is left behind. [Skotlex]
|
||||
//Reflected spells do not bounce back (src == dsrc since it only happens for direct skills)
|
||||
if (!blewcount || target == dsrc || status_isdead(target))
|
||||
return;
|
||||
|
||||
// Skill spesific direction
|
||||
switch (skill_id) {
|
||||
case MG_FIREWALL:
|
||||
case PR_SANCTUARY:
|
||||
case SC_TRIANGLESHOT:
|
||||
case GN_WALLOFTHORN:
|
||||
case EL_FIRE_MANTLE:
|
||||
dir = unit_getdir(target); // Backwards
|
||||
break;
|
||||
// This ensures the storm randomly pushes instead of exactly a cell backwards per official mechanics.
|
||||
case WZ_STORMGUST:
|
||||
dir = rand()%8;
|
||||
break;
|
||||
case WL_CRIMSONROCK:
|
||||
dir = map_calc_dir(target,skill_area_temp[4],skill_area_temp[5]);
|
||||
break;
|
||||
case MC_CARTREVOLUTION:
|
||||
if (battle_config.cart_revo_knockback)
|
||||
dir = 6; // Official servers push target to the West
|
||||
break;
|
||||
case AC_SHOWER:
|
||||
if (!battle_config.arrow_shower_knockback)
|
||||
dir = map_calc_dir(target, src->x, src->y);
|
||||
break;
|
||||
}
|
||||
|
||||
// Blown-specific handling
|
||||
switch( skill_id ) {
|
||||
case LG_OVERBRAND_BRANDISH:
|
||||
// Give knockback damage bonus only hits the wall. (bugreport:9096)
|
||||
if (skill_blown(dsrc,target,blewcount,dir,0x04|0x08|0x10|0x20) < blewcount)
|
||||
skill_addtimerskill(src, tick + status_get_amotion(src), target->id, 0, 0, LG_OVERBRAND_PLUSATK, skill_lv, BF_WEAPON, flag|SD_ANIMATION);
|
||||
break;
|
||||
case SR_KNUCKLEARROW:
|
||||
{
|
||||
short x = target->x, y = target->y;
|
||||
|
||||
// Ignore knockback damage bonus if in WOE (player cannot be knocked in WOE)
|
||||
// Boss & Immune Knockback (mode or from bonus bNoKnockBack) target still remains the damage bonus
|
||||
// (bugreport:9096)
|
||||
if (skill_blown(dsrc, target, blewcount, dir_ka, 0x04) < blewcount)
|
||||
skill_addtimerskill(src, tick + 300 * ((flag&2) ? 1 : 2), target->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag|4);
|
||||
|
||||
dir_ka = -1;
|
||||
|
||||
// Move attacker to the target position after knocked back
|
||||
if ((target->x != x || target->y != y) && unit_movepos(src,target->x,target->y,1,1)) {
|
||||
clif_slide(src, target->x, target->y);
|
||||
clif_fixpos(src);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RL_R_TRIP:
|
||||
if (skill_blown(dsrc,target,blewcount,dir,0) < blewcount)
|
||||
skill_addtimerskill(src, tick + status_get_amotion(src), target->id, 0, 0, RL_R_TRIP_PLUSATK, skill_lv, BF_WEAPON, flag|SD_ANIMATION);
|
||||
break;
|
||||
default:
|
||||
skill_blown(dsrc,target,blewcount,dir, 0x0 );
|
||||
if (!blewcount && target->type == BL_SKILL && damage > 0) {
|
||||
TBL_SKILL *su = (TBL_SKILL*)target;
|
||||
if (su->group && su->group->skill_id == HT_BLASTMINE)
|
||||
skill_blown(src, target, 3, -1, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
clif_fixpos(target);
|
||||
}
|
||||
|
||||
/*
|
||||
* =========================================================================
|
||||
* Does a skill attack with the given properties.
|
||||
* src is the master behind the attack (player/mob/pet)
|
||||
* dsrc is the actual originator of the damage, can be the same as src, or a BL_SKILL
|
||||
* bl is the target to be attacked.
|
||||
* flag can hold a bunch of information:
|
||||
* @param src is the master behind the attack (player/mob/pet)
|
||||
* @param dsrc is the actual originator of the damage, can be the same as src, or a BL_SKILL
|
||||
* @param bl is the target to be attacked.
|
||||
* @param flag can hold a bunch of information:
|
||||
* flag&1
|
||||
* flag&2 - Disable re-triggered by double casting
|
||||
* flag&4 - Skip to blow target (because already knocked back before skill_attack somewhere)
|
||||
*
|
||||
* flag&0xFFF is passed to the underlying battle_calc_attack for processing
|
||||
* (usually holds number of targets, or just 1 for simple splash attacks)
|
||||
* flag&0x1000 is used to tag that this is a splash-attack (so the damage
|
||||
* packet shouldn't display a skill animation)
|
||||
* flag&0x2000 is used to signal that the skill_lv should be passed as -1 to the
|
||||
* client (causes player characters to not scream skill name)
|
||||
*
|
||||
* Values from enum e_skill_display *
|
||||
* Values from enum e_battle_check_target
|
||||
*-------------------------------------------------------------------------*/
|
||||
int64 skill_attack (int attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag)
|
||||
{
|
||||
@ -3076,8 +3170,8 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
|
||||
|
||||
shadow_flag = skill_check_shadowform(bl, damage, dmg.div_);
|
||||
|
||||
if( !dmg.amotion ) {
|
||||
// Instant damage
|
||||
if( !dmg.amotion ) {
|
||||
if( (!tsc || (!tsc->data[SC_DEVOTION] && skill_id != CR_REFLECTSHIELD)) && !shadow_flag )
|
||||
status_fix_damage(src,bl,damage,dmg.dmotion); //Deal damage before knockback to allow stuff like firewall+storm gust combo.
|
||||
if( !status_isdead(bl) && additional_effects )
|
||||
@ -3086,76 +3180,9 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
|
||||
skill_counter_additional_effect(src,bl,skill_id,skill_lv,dmg.flag,tick);
|
||||
}
|
||||
|
||||
//Only knockback if it's still alive, otherwise a "ghost" is left behind. [Skotlex]
|
||||
//Reflected spells do not bounce back (bl == dsrc since it only happens for direct skills)
|
||||
if (dmg.blewcount > 0 && bl != dsrc && !status_isdead(bl)) {
|
||||
int8 dir = -1; // Default direction
|
||||
// Skill spesific direction
|
||||
switch (skill_id) {
|
||||
case MG_FIREWALL:
|
||||
case PR_SANCTUARY:
|
||||
case SC_TRIANGLESHOT:
|
||||
case GN_WALLOFTHORN:
|
||||
case EL_FIRE_MANTLE:
|
||||
dir = unit_getdir(bl); // Backwards
|
||||
break;
|
||||
// This ensures the storm randomly pushes instead of exactly a cell backwards per official mechanics.
|
||||
case WZ_STORMGUST:
|
||||
dir = rand()%8;
|
||||
break;
|
||||
case WL_CRIMSONROCK:
|
||||
dir = map_calc_dir(bl,skill_area_temp[4],skill_area_temp[5]);
|
||||
break;
|
||||
case MC_CARTREVOLUTION:
|
||||
if (battle_config.cart_revo_knockback)
|
||||
dir = 6; // Official servers push target to the West
|
||||
break;
|
||||
case AC_SHOWER:
|
||||
// Direction between target to actual attacker location instead of the unit location (bugreport:1709)
|
||||
if (dsrc != src)
|
||||
dir = map_calc_dir(bl, src->x, src->y);
|
||||
break;
|
||||
}
|
||||
// Blown-specific handling
|
||||
switch( skill_id ) {
|
||||
case LG_OVERBRAND_BRANDISH:
|
||||
// Give knockback damage bonus only hits the wall. (bugreport:9096)
|
||||
if( skill_blown(dsrc,bl,dmg.blewcount,dir,0x04|0x08|0x10|0x20) < dmg.blewcount )
|
||||
skill_addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skill_lv, BF_WEAPON, flag|SD_ANIMATION);
|
||||
break;
|
||||
case SR_KNUCKLEARROW:
|
||||
if (!(flag&4)) {
|
||||
short x = bl->x, y = bl->y;
|
||||
|
||||
// Ignore knockback damage bonus if in WOE (player cannot be knocked in WOE)
|
||||
// Boss & Immune Knockback (mode or from bonus bNoKnockBack) target still remains the damage bonus
|
||||
// (bugreport:9096)
|
||||
if (skill_blown(dsrc, bl, dmg.blewcount, dir_ka, 0x04) < dmg.blewcount)
|
||||
skill_addtimerskill(src, tick + 300 * ((flag&2) ? 1 : 2), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag|4);
|
||||
|
||||
dir_ka = -1;
|
||||
|
||||
// Move attacker to the target position after knocked back
|
||||
if ((bl->x != x || bl->y != y) && unit_movepos(src,bl->x,bl->y,1,1)) {
|
||||
clif_slide(src, bl->x, bl->y);
|
||||
clif_fixpos(src);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RL_R_TRIP:
|
||||
if( skill_blown(dsrc,bl,dmg.blewcount,dir,0) < dmg.blewcount )
|
||||
skill_addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, RL_R_TRIP_PLUSATK, skill_lv, BF_WEAPON, flag|SD_ANIMATION);
|
||||
break;
|
||||
default:
|
||||
skill_blown(dsrc,bl,dmg.blewcount,dir, 0x0 );
|
||||
if ( !dmg.blewcount && bl->type == BL_SKILL && damage > 0 ){
|
||||
TBL_SKILL *su = (TBL_SKILL*)bl;
|
||||
if( su->group && su->group->skill_id == HT_BLASTMINE)
|
||||
skill_blown(src, bl, 3, -1, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Blow!
|
||||
if (!(flag&4))
|
||||
skill_attack_blow(src, dsrc, bl, (uint8)dmg.blewcount, skill_id, skill_lv, damage, tick, flag);
|
||||
|
||||
// Delayed damage must be dealt after the knockback (it needs to know actual position of target)
|
||||
if( dmg.amotion ) {
|
||||
@ -10855,6 +10882,8 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
||||
skill_unitsetting(src,skill_id,skill_lv,x,y,0);
|
||||
break;
|
||||
}
|
||||
|
||||
// Skill Unit Setting
|
||||
case MG_SAFETYWALL:
|
||||
case MG_FIREWALL:
|
||||
case MG_THUNDERSTORM:
|
||||
@ -10964,6 +10993,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
||||
sd->skill_id_old = skill_id;
|
||||
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.
|
||||
case GN_WALLOFTHORN:
|
||||
skill_unitsetting(src,skill_id,skill_lv,x,y,0);
|
||||
break;
|
||||
case RG_GRAFFITI: /* Graffiti [Valaris] */
|
||||
@ -11390,19 +11420,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
||||
skill_unitsetting(src,skill_id,skill_lv,x,y,0);
|
||||
break;
|
||||
|
||||
case GN_WALLOFTHORN: {
|
||||
static const int dx[] = {-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2, 2, 2, 1, 0};
|
||||
static const int dy[] = { 2, 2, 1, 0,-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2};
|
||||
struct unit_data *ud = unit_bl2ud(src);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
x = ud->skillx + dx[i];
|
||||
y = ud->skilly + dy[i];
|
||||
skill_unitsetting(src, skill_id, skill_lv, x, y, 0);
|
||||
}
|
||||
flag |= 1;
|
||||
}
|
||||
break;
|
||||
case GN_CRAZYWEED: {
|
||||
int area = skill_get_splash(GN_CRAZYWEED_ATK, skill_lv);
|
||||
for( i = 0; i < 3 + (skill_lv/2); i++ ) {
|
||||
@ -12123,6 +12140,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
|
||||
skill_clear_group(src, 8);
|
||||
break;
|
||||
case GN_WALLOFTHORN:
|
||||
// Turns to Firewall
|
||||
if( flag&1 )
|
||||
limit = 3000;
|
||||
val3 = (x<<16)|y;
|
||||
@ -12188,8 +12206,8 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
|
||||
struct skill_unit *unit;
|
||||
int ux = x + layout->dx[i];
|
||||
int uy = y + layout->dy[i];
|
||||
int val1_2 = skill_lv;
|
||||
int val2_2 = 0;
|
||||
int unit_val1 = skill_lv;
|
||||
int unit_val2 = 0;
|
||||
int alive = 1;
|
||||
|
||||
// are the coordinates out of range?
|
||||
@ -12205,11 +12223,11 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
|
||||
switch( skill_id ) {
|
||||
case MG_FIREWALL:
|
||||
case NJ_KAENSIN:
|
||||
val2_2 = group->val2;
|
||||
unit_val2 = group->val2;
|
||||
break;
|
||||
case WZ_ICEWALL:
|
||||
val1_2 = (skill_lv <= 1) ? 500 : 200 + 200*skill_lv;
|
||||
val2_2 = map_getcell(src->m, ux, uy, CELL_GETTYPE);
|
||||
unit_val1 = (skill_lv <= 1) ? 500 : 200 + 200*skill_lv;
|
||||
unit_val2 = map_getcell(src->m, ux, uy, CELL_GETTYPE);
|
||||
break;
|
||||
case HT_LANDMINE:
|
||||
case MA_LANDMINE:
|
||||
@ -12234,35 +12252,37 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
|
||||
case RA_FIRINGTRAP:
|
||||
case RA_ICEBOUNDTRAP:
|
||||
case RL_B_TRAP:
|
||||
val1_2 = 3500;
|
||||
unit_val1 = 3500;
|
||||
break;
|
||||
case GS_DESPERADO:
|
||||
val1_2 = abs(layout->dx[i]);
|
||||
val2_2 = abs(layout->dy[i]);
|
||||
if (val1_2 < 2 || val2_2 < 2) { //Nearby cross, linear decrease with no diagonals
|
||||
if (val2_2 > val1_2) val1_2 = val2_2;
|
||||
if (val1_2) val1_2--;
|
||||
val1_2 = 36 -12*val1_2;
|
||||
unit_val1 = abs(layout->dx[i]);
|
||||
unit_val2 = abs(layout->dy[i]);
|
||||
if (unit_val1 < 2 || unit_val2 < 2) { //Nearby cross, linear decrease with no diagonals
|
||||
if (unit_val2 > unit_val1) unit_val1 = unit_val2;
|
||||
if (unit_val1) unit_val1--;
|
||||
unit_val1 = 36 -12*unit_val1;
|
||||
} else //Diagonal edges
|
||||
val1_2 = 28 -4*val1_2 -4*val2_2;
|
||||
if (val1_2 < 1) val1_2 = 1;
|
||||
val2_2 = 0;
|
||||
unit_val1 = 28 -4*unit_val1 -4*unit_val2;
|
||||
if (unit_val1 < 1) unit_val1 = 1;
|
||||
unit_val2 = 0;
|
||||
break;
|
||||
case WM_REVERBERATION:
|
||||
case WM_POEMOFNETHERWORLD:
|
||||
val1_2 = 1 + skill_lv;
|
||||
unit_val1 = 1 + skill_lv;
|
||||
break;
|
||||
case GN_WALLOFTHORN:
|
||||
val1_2 = 2000 + 2000 * skill_lv;
|
||||
val2_2 = 20;
|
||||
if (flag&1) // Turned become Firewall
|
||||
break;
|
||||
unit_val1 = 2000 + 2000 * skill_lv; // HP
|
||||
unit_val2 = 20; // Max hits
|
||||
break;
|
||||
default:
|
||||
if (group->state.song_dance&0x1)
|
||||
val2_2 = unit_flag&(UF_DANCE|UF_SONG); //Store whether this is a song/dance
|
||||
unit_val2 = unit_flag&(UF_DANCE|UF_SONG); //Store whether this is a song/dance
|
||||
break;
|
||||
}
|
||||
if (unit_flag&UF_RANGEDSINGLEUNIT && i == (layout->count / 2))
|
||||
val2_2 |= UF_RANGEDSINGLEUNIT; // center.
|
||||
unit_val2 |= UF_RANGEDSINGLEUNIT; // center.
|
||||
|
||||
if( sd && map_getcell(src->m, ux, uy, CELL_CHKMAELSTROM) ) //Does not recover SP from monster skills
|
||||
map_foreachincell(skill_maelstrom_suction,src->m,ux,uy,BL_SKILL,skill_id,skill_lv);
|
||||
@ -12273,7 +12293,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
|
||||
if( !alive )
|
||||
continue;
|
||||
|
||||
nullpo_retr(NULL, (unit = skill_initunit(group,i,ux,uy,val1_2,val2_2)));
|
||||
nullpo_retr(NULL, (unit = skill_initunit(group,i,ux,uy,unit_val1,unit_val2)));
|
||||
unit->limit = limit;
|
||||
unit->range = range;
|
||||
|
||||
@ -12558,11 +12578,11 @@ static int skill_unit_onplace (struct skill_unit *unit, struct block_list *bl, u
|
||||
|
||||
/*==========================================
|
||||
* Process skill unit each interval (sg->interval, see interval field of skill_unit_db.txt)
|
||||
* @param src Skill unit
|
||||
* @param unit Skill unit
|
||||
* @param bl Valid 'target' above the unit, that has been check in skill_unit_timer_sub_onplace
|
||||
* @param tick
|
||||
*------------------------------------------*/
|
||||
int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, unsigned int tick)
|
||||
int skill_unit_onplace_timer (struct skill_unit *unit, struct block_list *bl, unsigned int tick)
|
||||
{
|
||||
struct skill_unit_group *sg;
|
||||
struct block_list *ss;
|
||||
@ -12574,13 +12594,13 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
uint16 skill_id;
|
||||
int diff = 0;
|
||||
|
||||
nullpo_ret(src);
|
||||
nullpo_ret(unit);
|
||||
nullpo_ret(bl);
|
||||
|
||||
if (bl->prev == NULL || !src->alive || status_isdead(bl))
|
||||
if (bl->prev == NULL || !unit->alive || status_isdead(bl))
|
||||
return 0;
|
||||
|
||||
nullpo_ret(sg = src->group);
|
||||
nullpo_ret(sg = unit->group);
|
||||
nullpo_ret(ss = map_id2bl(sg->src_id));
|
||||
|
||||
tsd = BL_CAST(BL_PC, bl);
|
||||
@ -12616,31 +12636,42 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
ts->tick += sg->interval*(map_count_oncell(bl->m,bl->x,bl->y,BL_CHAR)-1);
|
||||
}
|
||||
|
||||
// Wall of Thorn damaged by Fire element unit [Cydh]
|
||||
//! TODO: This check doesn't matter the location, as long as one of units touched, this check will be executed.
|
||||
if (bl->type == BL_SKILL && skill_get_ele(sg->skill_id, sg->skill_lv) == ELE_FIRE) {
|
||||
struct skill_unit *su = (struct skill_unit *)bl;
|
||||
if (su && su->group && su->group->unit_id == UNT_WALLOFTHORN) {
|
||||
skill_unitsetting(map_id2bl(su->group->src_id), su->group->skill_id, su->group->skill_lv, su->group->val3>>16, su->group->val3&0xffff, 1);
|
||||
su->group->limit = sg->limit = 0;
|
||||
su->group->unit_id = sg->unit_id = UNT_USED_TRAPS;
|
||||
return skill_id;
|
||||
}
|
||||
}
|
||||
|
||||
switch (sg->unit_id) {
|
||||
case UNT_FIREWALL:
|
||||
case UNT_KAEN: {
|
||||
int count = 0;
|
||||
|
||||
const int x = bl->x, y = bl->y;
|
||||
|
||||
if (skill_id == GN_WALLOFTHORN && battle_check_target(ss, bl, BCT_ENEMY) <= 0)
|
||||
if (skill_id == GN_WALLOFTHORN && battle_check_target(ss, bl, sg->target_flag) <= 0)
|
||||
break;
|
||||
|
||||
//Take into account these hit more times than the timer interval can handle.
|
||||
do
|
||||
skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick+count*sg->interval,0);
|
||||
while(--src->val2 && x == bl->x && y == bl->y &&
|
||||
skill_attack(BF_MAGIC,ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick+count*sg->interval,0);
|
||||
while(--unit->val2 && x == bl->x && y == bl->y &&
|
||||
++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status_isdead(bl));
|
||||
|
||||
if (src->val2 <= 0)
|
||||
skill_delunit(src);
|
||||
if (unit->val2 <= 0)
|
||||
skill_delunit(unit);
|
||||
}
|
||||
break;
|
||||
|
||||
case UNT_SANCTUARY:
|
||||
if( battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race==RC_DEMON )
|
||||
{ //Only damage enemies with offensive Sanctuary. [Skotlex]
|
||||
if( battle_check_target(&src->bl,bl,BCT_ENEMY) > 0 && skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0) )
|
||||
if( battle_check_target(&unit->bl,bl,BCT_ENEMY) > 0 && skill_attack(BF_MAGIC, ss, &unit->bl, bl, sg->skill_id, sg->skill_lv, tick, 0) )
|
||||
sg->val1 -= 2; // reduce healing count if this was meant for damaging [hekate]
|
||||
} else {
|
||||
int heal = skill_calc_heal(ss,bl,sg->skill_id,sg->skill_lv,true);
|
||||
@ -12655,7 +12686,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
break;
|
||||
if( status_isimmune(bl) )
|
||||
heal = 0;
|
||||
clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
|
||||
clif_skill_nodamage(&unit->bl, bl, AL_HEAL, heal, 1);
|
||||
if( tsc && tsc->data[SC_AKAITSUKI] && heal )
|
||||
heal = ~heal + 1;
|
||||
status_heal(bl, heal, 0, 0);
|
||||
@ -12670,8 +12701,8 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
//Will heal demon and undead element monsters, but not players.
|
||||
if ((bl->type == BL_PC) || (!battle_check_undead(tstatus->race, tstatus->def_ele) && tstatus->race!=RC_DEMON))
|
||||
{ //Damage enemies
|
||||
if(battle_check_target(&src->bl,bl,BCT_ENEMY)>0)
|
||||
skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
|
||||
if(battle_check_target(&unit->bl,bl,BCT_ENEMY)>0)
|
||||
skill_attack(BF_MISC, ss, &unit->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
|
||||
} else {
|
||||
int heal = skill_calc_heal(ss,bl,sg->skill_id,sg->skill_lv,true);
|
||||
|
||||
@ -12679,7 +12710,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
break;
|
||||
if (status_isimmune(bl))
|
||||
heal = 0;
|
||||
clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
|
||||
clif_skill_nodamage(&unit->bl, bl, AL_HEAL, heal, 1);
|
||||
status_heal(bl, heal, 0, 0);
|
||||
}
|
||||
break;
|
||||
@ -12687,7 +12718,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
case UNT_MAGNUS:
|
||||
if (!battle_check_undead(tstatus->race,tstatus->def_ele) && tstatus->race!=RC_DEMON)
|
||||
break;
|
||||
skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
skill_attack(BF_MAGIC,ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
break;
|
||||
|
||||
case UNT_DUMMYSKILL:
|
||||
@ -12708,7 +12739,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
else // mobs
|
||||
if( status_charge(ss, 0, 2) ) // costs 2 SP per hit
|
||||
{
|
||||
if( !skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick+count*sg->interval,0) )
|
||||
if( !skill_attack(BF_WEAPON,ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick+count*sg->interval,0) )
|
||||
status_charge(ss, 0, 8); //costs additional 8 SP if miss
|
||||
}
|
||||
else
|
||||
@ -12727,13 +12758,13 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
case WZ_STORMGUST: //SG counter does not reset per stormgust. IE: One hit from a SG and two hits from another will freeze you.
|
||||
if (tsc)
|
||||
tsc->sg_counter++; //SG hit counter.
|
||||
if (skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0) <= 0 && tsc)
|
||||
if (skill_attack(skill_get_type(sg->skill_id),ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0) <= 0 && tsc)
|
||||
tsc->sg_counter=0; //Attack absorbed.
|
||||
break;
|
||||
#endif
|
||||
case GS_DESPERADO:
|
||||
if (rnd()%100 < src->val1)
|
||||
skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
if (rnd()%100 < unit->val1)
|
||||
skill_attack(BF_WEAPON,ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
break;
|
||||
case GN_CRAZYWEED_ATK:
|
||||
if( bl->type == BL_SKILL ){
|
||||
@ -12742,19 +12773,19 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
break;
|
||||
}
|
||||
default:
|
||||
skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
skill_attack(skill_get_type(sg->skill_id),ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
}
|
||||
break;
|
||||
|
||||
case UNT_FIREPILLAR_WAITING:
|
||||
skill_unitsetting(ss,sg->skill_id,sg->skill_lv,src->bl.x,src->bl.y,1);
|
||||
skill_delunit(src);
|
||||
skill_unitsetting(ss,sg->skill_id,sg->skill_lv,unit->bl.x,unit->bl.y,1);
|
||||
skill_delunit(unit);
|
||||
break;
|
||||
|
||||
case UNT_SKIDTRAP: {
|
||||
skill_blown(&src->bl,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0);
|
||||
skill_blown(&unit->bl,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0);
|
||||
sg->unit_id = UNT_USED_TRAPS;
|
||||
clif_changetraplook(&src->bl, UNT_USED_TRAPS);
|
||||
clif_changetraplook(&unit->bl, UNT_USED_TRAPS);
|
||||
sg->limit=DIFF_TICK(tick,sg->tick)+1500;
|
||||
}
|
||||
break;
|
||||
@ -12769,25 +12800,25 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
|
||||
if( td )
|
||||
sec = DIFF_TICK(td->tick, tick);
|
||||
if( sg->unit_id == UNT_MANHOLE || battle_config.skill_trap_type || !map_flag_gvg(src->bl.m) ) {
|
||||
unit_movepos(bl, src->bl.x, src->bl.y, 0, 0);
|
||||
if( sg->unit_id == UNT_MANHOLE || battle_config.skill_trap_type || !map_flag_gvg(unit->bl.m) ) {
|
||||
unit_movepos(bl, unit->bl.x, unit->bl.y, 0, 0);
|
||||
clif_fixpos(bl);
|
||||
}
|
||||
sg->val2 = bl->id;
|
||||
} else
|
||||
sec = 3000; //Couldn't trap it?
|
||||
if (sg->unit_id == UNT_ANKLESNARE) {
|
||||
clif_skillunit_update(&src->bl);
|
||||
clif_skillunit_update(&unit->bl);
|
||||
/**
|
||||
* If you're snared from a trap that was invisible this makes the trap be
|
||||
* visible again -- being you stepped on it (w/o this the trap remains invisible and you go "WTF WHY I CANT MOVE")
|
||||
* bugreport:3961
|
||||
**/
|
||||
clif_changetraplook(&src->bl, UNT_ANKLESNARE);
|
||||
clif_changetraplook(&unit->bl, UNT_ANKLESNARE);
|
||||
}
|
||||
sg->limit = DIFF_TICK(tick,sg->tick)+sec;
|
||||
sg->interval = -1;
|
||||
src->range = 0;
|
||||
unit->range = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -12796,10 +12827,10 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
if( status_get_mode(bl)&MD_BOSS )
|
||||
break;
|
||||
if( status_change_start(ss, bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id, sg->skill_lv), 8) ) {
|
||||
map_moveblock(bl, src->bl.x, src->bl.y, tick);
|
||||
map_moveblock(bl, unit->bl.x, unit->bl.y, tick);
|
||||
clif_fixpos(bl);
|
||||
}
|
||||
map_foreachinrange(skill_trap_splash, &src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl, tick);
|
||||
map_foreachinrange(skill_trap_splash, &unit->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &unit->bl, tick);
|
||||
sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again.
|
||||
}
|
||||
break;
|
||||
@ -12831,11 +12862,11 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
if (tsc && tsc->data[SC__MANHOLE])
|
||||
break;
|
||||
if (sg->unit_id == UNT_FIRINGTRAP || sg->unit_id == UNT_ICEBOUNDTRAP || sg->unit_id == UNT_CLAYMORETRAP)
|
||||
map_foreachinrange(skill_trap_splash, &src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &src->bl, tick);
|
||||
map_foreachinrange(skill_trap_splash, &unit->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &unit->bl, tick);
|
||||
else
|
||||
map_foreachinrange(skill_trap_splash, &src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl, tick);
|
||||
map_foreachinrange(skill_trap_splash, &unit->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &unit->bl, tick);
|
||||
if (sg->unit_id != UNT_FIREPILLAR_ACTIVE)
|
||||
clif_changetraplook(&src->bl,(sg->unit_id == UNT_LANDMINE ? UNT_FIREPILLAR_ACTIVE : UNT_USED_TRAPS));
|
||||
clif_changetraplook(&unit->bl,(sg->unit_id == UNT_LANDMINE ? UNT_FIREPILLAR_ACTIVE : UNT_USED_TRAPS));
|
||||
sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again.
|
||||
sg->limit = DIFF_TICK(tick, sg->tick) + 1500 +
|
||||
(sg->unit_id == UNT_CLUSTERBOMB || sg->unit_id == UNT_ICEBOUNDTRAP ? 1000 : 0); // Cluster Bomb/Icebound has 1s to disappear once activated.
|
||||
@ -12845,9 +12876,9 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
if (sg->src_id == bl->id)
|
||||
break;
|
||||
if (sg->val2 == 0) {
|
||||
clif_talkiebox(&src->bl, sg->valstr);
|
||||
clif_talkiebox(&unit->bl, sg->valstr);
|
||||
sg->unit_id = UNT_USED_TRAPS;
|
||||
clif_changetraplook(&src->bl, UNT_USED_TRAPS);
|
||||
clif_changetraplook(&unit->bl, UNT_USED_TRAPS);
|
||||
sg->limit = DIFF_TICK(tick, sg->tick) + 5000;
|
||||
sg->val2 = -1;
|
||||
}
|
||||
@ -12865,7 +12896,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
break;
|
||||
|
||||
case UNT_DISSONANCE:
|
||||
skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
|
||||
skill_attack(BF_MISC, ss, &unit->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
|
||||
break;
|
||||
|
||||
case UNT_APPLEIDUN: { //Apple of Idun [Skotlex]
|
||||
@ -12881,14 +12912,14 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
heal = skill_calc_heal(ss,bl,sg->skill_id, sg->skill_lv, true);
|
||||
if (tsc->data[SC_AKAITSUKI] && heal)
|
||||
heal = ~heal + 1;
|
||||
clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
|
||||
clif_skill_nodamage(&unit->bl, bl, AL_HEAL, heal, 1);
|
||||
status_heal(bl, heal, 0, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case UNT_TATAMIGAESHI:
|
||||
case UNT_DEMONSTRATION:
|
||||
skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
skill_attack(BF_WEAPON,ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
break;
|
||||
|
||||
case UNT_GOSPEL:
|
||||
@ -12955,14 +12986,14 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0)
|
||||
else if (battle_check_target(&unit->bl,bl,BCT_ENEMY)>0)
|
||||
{ // Offensive Effect
|
||||
int i = rnd()%9; // Negative buff count
|
||||
int time = skill_get_time2(sg->skill_id, sg->skill_lv);
|
||||
switch (i)
|
||||
{
|
||||
case 0: // Deal 1~9999 damage
|
||||
skill_attack(BF_MISC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
skill_attack(BF_MISC,ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
break;
|
||||
case 1: // Curse
|
||||
sc_start(ss, bl,SC_CURSE,100,1,time);
|
||||
@ -12994,10 +13025,10 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
|
||||
case UNT_BASILICA:
|
||||
{
|
||||
int i = battle_check_target(&src->bl, bl, BCT_ENEMY);
|
||||
int i = battle_check_target(&unit->bl, bl, BCT_ENEMY);
|
||||
if( i > 0 && !(status_get_mode(bl)&MD_BOSS) )
|
||||
{ // knock-back any enemy except Boss
|
||||
skill_blown(&src->bl, bl, skill_get_blewcount(skill_id, sg->skill_lv), unit_getdir(bl), 0);
|
||||
skill_blown(&unit->bl, bl, skill_get_blewcount(skill_id, sg->skill_lv), unit_getdir(bl), 0);
|
||||
clif_fixpos(bl);
|
||||
break;
|
||||
}
|
||||
@ -13013,7 +13044,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
case UNT_PSYCHIC_WAVE:
|
||||
case UNT_MAGMA_ERUPTION:
|
||||
case UNT_MAKIBISHI:
|
||||
skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
skill_attack(skill_get_type(sg->skill_id),ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
break;
|
||||
|
||||
case UNT_GROUNDDRIFT_WIND:
|
||||
@ -13021,9 +13052,9 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
case UNT_GROUNDDRIFT_POISON:
|
||||
case UNT_GROUNDDRIFT_WATER:
|
||||
case UNT_GROUNDDRIFT_FIRE:
|
||||
map_foreachinrange(skill_trap_splash,&src->bl,
|
||||
map_foreachinrange(skill_trap_splash,&unit->bl,
|
||||
skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag,
|
||||
&src->bl,tick);
|
||||
&unit->bl,tick);
|
||||
sg->unit_id = UNT_USED_TRAPS;
|
||||
//clif_changetraplook(&src->bl, UNT_FIREPILLAR_ACTIVE);
|
||||
sg->limit=DIFF_TICK(tick,sg->tick)+1500;
|
||||
@ -13047,9 +13078,9 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
hp = tstatus->max_hp * hp / 100;
|
||||
sp = tstatus->max_sp * sp / 100;
|
||||
if (tstatus->hp < tstatus->max_hp)
|
||||
clif_skill_nodamage(&src->bl, bl, AL_HEAL, hp, 1);
|
||||
clif_skill_nodamage(&unit->bl, bl, AL_HEAL, hp, 1);
|
||||
if (tstatus->sp < tstatus->max_sp)
|
||||
clif_skill_nodamage(&src->bl, bl, MG_SRECOVERY, sp, 1);
|
||||
clif_skill_nodamage(&unit->bl, bl, MG_SRECOVERY, sp, 1);
|
||||
if (tsc && tsc->data[SC_AKAITSUKI] && hp)
|
||||
hp = ~hp + 1;
|
||||
status_heal(bl, hp, sp, 3);
|
||||
@ -13084,18 +13115,18 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
break;
|
||||
|
||||
case UNT_REVERBERATION:
|
||||
clif_changetraplook(&src->bl,UNT_USED_TRAPS);
|
||||
map_foreachinrange(skill_trap_splash,&src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick);
|
||||
clif_changetraplook(&unit->bl,UNT_USED_TRAPS);
|
||||
map_foreachinrange(skill_trap_splash,&unit->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &unit->bl,tick);
|
||||
sg->limit = DIFF_TICK(tick,sg->tick)+1000;
|
||||
sg->unit_id = UNT_USED_TRAPS;
|
||||
break;
|
||||
|
||||
case UNT_SEVERE_RAINSTORM:
|
||||
if( battle_check_target(&src->bl, bl, BCT_ENEMY) > 0 )
|
||||
skill_attack(BF_WEAPON,ss,&src->bl,bl,WM_SEVERE_RAINSTORM_MELEE,sg->skill_lv,tick,0);
|
||||
if( battle_check_target(&unit->bl, bl, BCT_ENEMY) > 0 )
|
||||
skill_attack(BF_WEAPON,ss,&unit->bl,bl,WM_SEVERE_RAINSTORM_MELEE,sg->skill_lv,tick,0);
|
||||
break;
|
||||
case UNT_NETHERWORLD:
|
||||
if (!(status_get_mode(bl)&MD_BOSS) || (!map_flag_gvg2(ss->m) && battle_check_target(&src->bl,bl,BCT_PARTY) < 0)) {
|
||||
if (!(status_get_mode(bl)&MD_BOSS) || (!map_flag_gvg2(ss->m) && battle_check_target(&unit->bl,bl,BCT_PARTY) < 0)) {
|
||||
if (!(tsc && tsc->data[type])) {
|
||||
sc_start(ss, bl, type, 100, sg->skill_lv, skill_get_time2(sg->skill_id,sg->skill_lv));
|
||||
sg->limit = DIFF_TICK(tick,sg->tick);
|
||||
@ -13123,14 +13154,13 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
break;
|
||||
|
||||
case UNT_WALLOFTHORN:
|
||||
if (unit->val2-- <= 0) // Max hit reached
|
||||
break;
|
||||
if (status_get_mode(bl)&MD_BOSS)
|
||||
break; // This skill doesn't affect to Boss monsters. [iRO Wiki]
|
||||
if (battle_check_target(ss, bl, BCT_ENEMY) <= 0) {
|
||||
unit_stop_walking(bl, 1);
|
||||
skill_blown(&src->bl, bl, skill_get_blewcount(sg->skill_id, sg->skill_lv), unit_getdir(bl), 0x2);
|
||||
skill_blown(&unit->bl, bl, skill_get_blewcount(sg->skill_id, sg->skill_lv), -1, 0);
|
||||
clif_fixpos(bl);
|
||||
} else
|
||||
skill_attack(skill_get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
|
||||
skill_addtimerskill(ss, tick + 100, bl->id, unit->bl.x, unit->bl.y, sg->skill_id, sg->skill_lv, skill_get_type(sg->skill_id), 4|SD_LEVEL);
|
||||
break;
|
||||
|
||||
case UNT_DEMONIC_FIRE:
|
||||
@ -13138,14 +13168,14 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
case 1:
|
||||
default:
|
||||
sc_start(ss, bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv));
|
||||
skill_attack(skill_get_type(skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv + 10 * sg->val2, tick, 0);
|
||||
skill_attack(skill_get_type(skill_id), ss, &unit->bl, bl, sg->skill_id, sg->skill_lv + 10 * sg->val2, tick, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case UNT_HELLS_PLANT:
|
||||
if( battle_check_target(&src->bl,bl,BCT_ENEMY) > 0 )
|
||||
skill_attack(skill_get_type(GN_HELLS_PLANT_ATK), ss, &src->bl, bl, GN_HELLS_PLANT_ATK, sg->skill_lv, tick, 0);
|
||||
if( battle_check_target(&unit->bl,bl,BCT_ENEMY) > 0 )
|
||||
skill_attack(skill_get_type(GN_HELLS_PLANT_ATK), ss, &unit->bl, bl, GN_HELLS_PLANT_ATK, sg->skill_lv, tick, 0);
|
||||
if( ss != bl) // The caster is the only one who can step on the Plants without destroying them
|
||||
sg->limit = DIFF_TICK(tick, sg->tick) + 100;
|
||||
break;
|
||||
@ -13153,7 +13183,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
case UNT_CLOUD_KILL:
|
||||
if(tsc && !tsc->data[type])
|
||||
status_change_start(ss, bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),8);
|
||||
skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
skill_attack(skill_get_type(sg->skill_id),ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
break;
|
||||
|
||||
case UNT_WARMER:
|
||||
@ -13166,7 +13196,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
else
|
||||
hp = tstatus->max_hp * sg->skill_lv / 100;
|
||||
if( tstatus->hp != tstatus->max_hp )
|
||||
clif_skill_nodamage(&src->bl, bl, AL_HEAL, hp, 0);
|
||||
clif_skill_nodamage(&unit->bl, bl, AL_HEAL, hp, 0);
|
||||
if( tsc && tsc->data[SC_AKAITSUKI] && hp )
|
||||
hp = ~hp + 1;
|
||||
status_heal(bl, hp, 0, 0);
|
||||
@ -13213,20 +13243,20 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
break;
|
||||
|
||||
case UNT_BANDING:
|
||||
if( battle_check_target(&src->bl, bl, BCT_ENEMY) > 0 && !(status_get_mode(bl)&MD_BOSS) && !(tsc && tsc->data[SC_BANDING_DEFENCE]) )
|
||||
sc_start(ss, bl, SC_BANDING_DEFENCE, (status_get_lv(&src->bl) / 5) + (sg->skill_lv * 5) - (status_get_agi(bl) / 10), 90, skill_get_time2(sg->skill_id, sg->skill_lv));
|
||||
if( battle_check_target(&unit->bl, bl, BCT_ENEMY) > 0 && !(status_get_mode(bl)&MD_BOSS) && !(tsc && tsc->data[SC_BANDING_DEFENCE]) )
|
||||
sc_start(ss, bl, SC_BANDING_DEFENCE, (status_get_lv(&unit->bl) / 5) + (sg->skill_lv * 5) - (status_get_agi(bl) / 10), 90, skill_get_time2(sg->skill_id, sg->skill_lv));
|
||||
break;
|
||||
|
||||
case UNT_FIRE_MANTLE:
|
||||
if( battle_check_target(&src->bl, bl, BCT_ENEMY) > 0 )
|
||||
skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
if( battle_check_target(&unit->bl, bl, BCT_ENEMY) > 0 )
|
||||
skill_attack(BF_MAGIC,ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
||||
break;
|
||||
|
||||
case UNT_ZENKAI_WATER:
|
||||
case UNT_ZENKAI_LAND:
|
||||
case UNT_ZENKAI_FIRE:
|
||||
case UNT_ZENKAI_WIND:
|
||||
if( battle_check_target(&src->bl,bl,BCT_ENEMY) > 0 ) {
|
||||
if( battle_check_target(&unit->bl,bl,BCT_ENEMY) > 0 ) {
|
||||
switch( sg->unit_id ) {
|
||||
case UNT_ZENKAI_WATER:
|
||||
switch (rnd()%2 + 1) {
|
||||
@ -13270,24 +13300,24 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
break;
|
||||
|
||||
case UNT_LAVA_SLIDE:
|
||||
skill_attack(BF_WEAPON, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
|
||||
skill_attack(BF_WEAPON, ss, &unit->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);
|
||||
skill_attack(BF_MAGIC, ss, &unit->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
|
||||
status_change_start(ss, bl, SC_BLIND, (10 + 10 * sg->skill_lv)*100, sg->skill_lv, sg->skill_id, 0, 0, skill_get_time2(sg->skill_id, sg->skill_lv), 2|8);
|
||||
break;
|
||||
|
||||
case UNT_B_TRAP:
|
||||
sc_start(ss,bl,SC_B_TRAP,100,sg->skill_lv,max(status_get_str(bl) * 150,5000)); //(custom)
|
||||
sg->unit_id = UNT_USED_TRAPS;
|
||||
clif_changetraplook(&src->bl, UNT_USED_TRAPS);
|
||||
clif_changetraplook(&unit->bl, UNT_USED_TRAPS);
|
||||
sg->limit = DIFF_TICK(tick,sg->tick)+1500;
|
||||
break;
|
||||
case UNT_FIRE_RAIN:
|
||||
clif_skill_damage(ss,bl,tick,status_get_amotion(ss),0,
|
||||
skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,SD_ANIMATION|SD_SPLASH),
|
||||
skill_attack(skill_get_type(sg->skill_id),ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,SD_ANIMATION|SD_SPLASH),
|
||||
1,sg->skill_id,sg->skill_lv,6);
|
||||
break;
|
||||
}
|
||||
@ -13563,11 +13593,10 @@ static int skill_unit_effect (struct block_list* bl, va_list ap)
|
||||
/*==========================================
|
||||
* Check skill unit while receiving damage
|
||||
* @param unit Skill unit
|
||||
* @param bl Attacker
|
||||
* @param damage Received damage
|
||||
* @return Damage
|
||||
*------------------------------------------*/
|
||||
int64 skill_unit_ondamaged (struct skill_unit *unit, struct block_list *bl, int64 damage)
|
||||
int64 skill_unit_ondamaged (struct skill_unit *unit, int64 damage)
|
||||
{
|
||||
struct skill_unit_group *sg;
|
||||
|
||||
@ -16963,10 +16992,9 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
|
||||
{
|
||||
struct block_list* src;
|
||||
struct unit_data *ud;
|
||||
int i,j;
|
||||
short i, j;
|
||||
|
||||
if( group == NULL )
|
||||
{
|
||||
if( group == NULL ) {
|
||||
ShowDebug("skill_delunitgroup: group is NULL (source=%s:%d, %s)! Please report this! (#3504)\n", file, line, func);
|
||||
return 0;
|
||||
}
|
||||
@ -16995,31 +17023,25 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
|
||||
}
|
||||
}
|
||||
|
||||
if (skill_get_unit_flag(group->skill_id)&(UF_DANCE|UF_SONG|UF_ENSEMBLE))
|
||||
{
|
||||
if (skill_get_unit_flag(group->skill_id)&(UF_DANCE|UF_SONG|UF_ENSEMBLE)) {
|
||||
struct status_change* sc = status_get_sc(src);
|
||||
if (sc && sc->data[SC_DANCING])
|
||||
{
|
||||
if (sc && sc->data[SC_DANCING]) {
|
||||
sc->data[SC_DANCING]->val2 = 0 ; //This prevents status_change_end attempting to redelete the group. [Skotlex]
|
||||
status_change_end(src, SC_DANCING, INVALID_TIMER);
|
||||
}
|
||||
}
|
||||
|
||||
// end Gospel's status change on 'src'
|
||||
// (needs to be done when the group is deleted by other means than skill deactivation)
|
||||
if (group->unit_id == UNT_GOSPEL) {
|
||||
struct status_change *sc = status_get_sc(src);
|
||||
if(sc && sc->data[SC_GOSPEL]) {
|
||||
sc->data[SC_GOSPEL]->val3 = 0; //Remove reference to this group. [Skotlex]
|
||||
status_change_end(src, SC_GOSPEL, INVALID_TIMER);
|
||||
// End SC from the master when the skill group is deleted
|
||||
i = SC_NONE;
|
||||
switch (group->unit_id) {
|
||||
case UNT_GOSPEL: i = SC_GOSPEL; break;
|
||||
case UNT_BASILICA: i = SC_BASILICA; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (group->unit_id == UNT_BASILICA) {
|
||||
if (i != SC_NONE) {
|
||||
struct status_change *sc = status_get_sc(src);
|
||||
if(sc && sc->data[SC_BASILICA]) {
|
||||
sc->data[SC_BASILICA]->val3 = 0;
|
||||
status_change_end(src, SC_BASILICA, INVALID_TIMER);
|
||||
if (sc && sc->data[i]) {
|
||||
sc->data[i]->val3 = 0; //Remove reference to this group. [Skotlex]
|
||||
status_change_end(src, (sc_type)i, INVALID_TIMER);
|
||||
}
|
||||
}
|
||||
|
||||
@ -17371,10 +17393,16 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
|
||||
}
|
||||
break;
|
||||
case UNT_WALLOFTHORN:
|
||||
if( unit->val1 <= 0 ) {
|
||||
if (unit->val1 <= 0 || unit->val2 <= 0 || group->val3 < 0) {
|
||||
group->unit_id = UNT_USED_TRAPS;
|
||||
group->limit = DIFF_TICK(tick, group->tick);
|
||||
}
|
||||
/*if (group->val3 < 0) { // Remove if attacked by fire element, turned to Fire Wall
|
||||
skill_delunitgroup(group);
|
||||
break;
|
||||
}
|
||||
if (unit->val1 <= 0 || unit->val2 <= 0) // Remove unit only if no HP or hit limit reached
|
||||
skill_delunit(unit);*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -17550,10 +17578,13 @@ int skill_unit_move (struct block_list *bl, unsigned int tick, int flag) {
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Moves skill unit group to map m with coordinates x & y (example when knocked back)
|
||||
* @param group Skill Group
|
||||
* @param m Map
|
||||
* @param dx
|
||||
* @param dy
|
||||
*------------------------------------------*/
|
||||
int skill_unit_move_unit_group (struct skill_unit_group *group, int16 m, int16 dx, int16 dy)
|
||||
{
|
||||
void skill_unit_move_unit_group(struct skill_unit_group *group, int16 m, int16 dx, int16 dy) {
|
||||
int i,j;
|
||||
unsigned int tick = gettick();
|
||||
int *m_flag;
|
||||
@ -17561,14 +17592,14 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int16 m, int16 d
|
||||
struct skill_unit *unit2;
|
||||
|
||||
if (group == NULL)
|
||||
return 0;
|
||||
return;
|
||||
if (group->unit_count <= 0)
|
||||
return 0;
|
||||
return;
|
||||
if (group->unit == NULL)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if (skill_get_unit_flag(group->skill_id)&UF_ENSEMBLE)
|
||||
return 0; //Ensembles may not be moved around.
|
||||
return; //Ensembles may not be moved around.
|
||||
|
||||
m_flag = (int *) aCalloc(group->unit_count, sizeof(int));
|
||||
// m_flag
|
||||
@ -17603,8 +17634,7 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int16 m, int16 d
|
||||
map_foreachincell(skill_unit_effect,unit1->bl.m,unit1->bl.x,unit1->bl.y,group->bl_flag,&unit1->bl,tick,4);
|
||||
}
|
||||
//Move Cell using "smart" criteria (avoid useless moving around)
|
||||
switch(m_flag[i])
|
||||
{
|
||||
switch(m_flag[i]) {
|
||||
case 0:
|
||||
//Cell moves independently, safely move it.
|
||||
map_moveblock(&unit1->bl, unit1->bl.x+dx, unit1->bl.y+dy, tick);
|
||||
@ -17612,8 +17642,7 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int16 m, int16 d
|
||||
case 1:
|
||||
//Cell moves unto another cell, look for a replacement cell that won't collide
|
||||
//and has no cell moving into it (flag == 2)
|
||||
for(;j<group->unit_count;j++)
|
||||
{
|
||||
for(;j<group->unit_count;j++) {
|
||||
if(m_flag[j]!=2 || !group->unit[j].alive)
|
||||
continue;
|
||||
//Move to where this cell would had moved.
|
||||
@ -17635,7 +17664,7 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int16 m, int16 d
|
||||
}
|
||||
}
|
||||
aFree(m_flag);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
@ -19063,6 +19092,14 @@ void skill_init_unit_layout (void) {
|
||||
pos++;
|
||||
}
|
||||
break;
|
||||
case GN_WALLOFTHORN: {
|
||||
static const int dx[] = {-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2, 2, 2, 1, 0};
|
||||
static const int dy[] = { 2, 2, 1, 0,-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2};
|
||||
skill_unit_layout[pos].count = 16;
|
||||
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
|
||||
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ShowError("unknown unit layout at skill %d\n",i);
|
||||
break;
|
||||
@ -19359,7 +19396,7 @@ void skill_init_nounit_layout (void) {
|
||||
pos++;
|
||||
}
|
||||
|
||||
if( pos >= MAX_SKILL_UNIT_LAYOUT )
|
||||
if( pos >= MAX_SKILL_UNIT_LAYOUT2 )
|
||||
ShowError("skill_init_nounit_layout: The skill_nounit_layout has met the limit or overflowed (pos=%d)\n", pos);
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,8 @@ struct s_skill_db {
|
||||
};
|
||||
extern struct s_skill_db skill_db[MAX_SKILL_DB];
|
||||
|
||||
#define MAX_SKILL_UNIT_LAYOUT 55
|
||||
#define MAX_SKILL_UNIT_LAYOUT 52
|
||||
#define MAX_SKILL_UNIT_LAYOUT2 17
|
||||
#define MAX_SQUARE_LAYOUT 5 // 11*11 Placement of a maximum unit
|
||||
#define MAX_SKILL_UNIT_COUNT ((MAX_SQUARE_LAYOUT*2+1)*(MAX_SQUARE_LAYOUT*2+1))
|
||||
struct s_skill_unit_layout {
|
||||
@ -388,7 +389,7 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
|
||||
void skill_clear_unitgroup(struct block_list *src);
|
||||
int skill_clear_group(struct block_list *bl, int flag);
|
||||
void ext_skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, unsigned int tick);
|
||||
int64 skill_unit_ondamaged(struct skill_unit *unit,struct block_list *bl,int64 damage);
|
||||
int64 skill_unit_ondamaged(struct skill_unit *unit,int64 damage);
|
||||
|
||||
int skill_castfix( struct block_list *bl, uint16 skill_id, uint16 skill_lv);
|
||||
int skill_castfix_sc( struct block_list *bl, int time);
|
||||
@ -410,7 +411,7 @@ int skill_check_pc_partner(struct map_session_data *sd, uint16 skill_id, uint16
|
||||
int skill_check_unit_cell(uint16 skill_id,int16 m,int16 x,int16 y,int unit_id);
|
||||
int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range);
|
||||
int skill_unit_move(struct block_list *bl,unsigned int tick,int flag);
|
||||
int skill_unit_move_unit_group( struct skill_unit_group *group, int16 m,int16 dx,int16 dy);
|
||||
void skill_unit_move_unit_group( struct skill_unit_group *group, int16 m,int16 dx,int16 dy);
|
||||
|
||||
struct skill_unit_group *skill_check_dancing( struct block_list *src );
|
||||
|
||||
|
@ -1352,7 +1352,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
|
||||
}
|
||||
|
||||
if (target->type == BL_SKILL)
|
||||
return (int)skill_unit_ondamaged((struct skill_unit *)target, src, hp);
|
||||
return (int)skill_unit_ondamaged((struct skill_unit *)target, hp);
|
||||
|
||||
status = status_get_status_data(target);
|
||||
if(!status || status == &dummy_status )
|
||||
|
@ -898,7 +898,7 @@ uint8 unit_getdir(struct block_list *bl)
|
||||
* @param dx: Destination cell X
|
||||
* @param dy: Destination cell Y
|
||||
* @param count: How many cells to push bl
|
||||
* @param flag: Whether or not to send position packet updates
|
||||
* @param flag: &1 Whether or not to send position packet updates
|
||||
* @return count (can be modified due to map cell restrictions)
|
||||
*/
|
||||
int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
|
||||
|
Loading…
x
Reference in New Issue
Block a user