Okay so ground skills all follow the UNT_UGLYDANCE format or whatever, you can use the same UNT_ a bunch of different ways but the actual effects will be pretty strict unless you get creative with your writing, so you can easily make a bunch of different sized sanctuary/venom dusts and things like that, but they will most likely all have the same effect... unless you get creative right? ok so this is one of my UNT_'s that ive been working on .
skill.c
case KN_DOMINATOR:
case NC_NEUTRALBARRIER:
struct status_change *tsc = status->get_sc(src);
skill->clear_unitgroup(src); // To remove previous skills - cannot used combined
if( tsc && tsc->data[SC_STAGETHREE] ) {
if( (sg = skill->unitsetting(src,NC_NEUTRALBARRIER,3,src->x,src->y,0)) != NULL ) {
sc_start2(src,src,SC_NEUTRALBARRIER_MASTER,100,skill_lv,sg->group_id,skill->get_time(skill_id,skill_lv));
status_change_end(src, SC_STAGETHREE, INVALID_TIMER);
sc_start(src, src,SC_STAGETHREE,100,skill_lv,skill->get_time(skill_id, skill_lv));
if( sd ) pc->overheat(sd,1);
}
break;
}
if( tsc && tsc->data[SC_STAGETWO] ) {
if( (sg = skill->unitsetting(src,NC_NEUTRALBARRIER,3,src->x,src->y,0)) != NULL ) {
sc_start2(src,src,SC_NEUTRALBARRIER_MASTER,100,skill_lv,sg->group_id,skill->get_time(skill_id,skill_lv));
status_change_end(src, SC_STAGETWO, INVALID_TIMER);
sc_start(src, src,SC_STAGETHREE,100,skill_lv,skill->get_time(skill_id, skill_lv));
if( sd ) pc->overheat(sd,1);
}
break;
}
if( tsc && tsc->data[SC_STAGEONE] ) {
if( (sg = skill->unitsetting(src,NC_NEUTRALBARRIER,2,src->x,src->y,0)) != NULL ) {
sc_start2(src,src,skill_id == NC_NEUTRALBARRIER ? SC_NEUTRALBARRIER_MASTER : SC_STEALTHFIELD_MASTER,100,skill_lv,sg->group_id,skill->get_time(skill_id,skill_lv));
status_change_end(src, SC_STAGEONE, INVALID_TIMER);
sc_start(src, src,SC_STAGETWO,100,skill_lv,skill->get_time(skill_id, skill_lv));
if( sd ) pc->overheat(sd,1);
}
break;
}
if( (sg = skill->unitsetting(src,NC_NEUTRALBARRIER,1,src->x,src->y,0)) != NULL ) {
sc_start2(src,src,SC_NEUTRALBARRIER_MASTER,100,skill_lv,sg->group_id,skill->get_time(skill_id,skill_lv));
sc_start(src, src,SC_STAGEONE,100,skill_lv,skill->get_time(skill_id, skill_lv));
if( sd ) pc->overheat(sd,1);
}
break;
And in my skill.db
{
Id: 1634
Name: "KN_DOMINATOR"
Description: "Dominators Presence"
MaxLevel: 3
Hit: "BDT_SKILL"
SkillType: {
Self: true
}
DamageType: {
NoDamage: true
}
InterruptCast: true
SkillData1: 15000
CoolDown: 0
Requirements: {
SPCost: 10
}
Unit: {
Id: 0xe2
Layout: {
Lv1: 2
Lv2: 3
Lv3: 4
Lv4: 2
Lv5: 2
Lv6: 2
Lv7: 2
Lv8: 2
Lv9: 2
Lv10: 2
}
Interval: 500
Target: "All"
}
},
So as you can see the bottom half has the UNT section right? not all skills have that only skills that actually have AOE like storm gust... arrow shower... things like that . . . so the skill i just posted gets bigger every stage, and the way i have it work is that when my Lord Knight gets kill he gets combo spirits, and then when he has 5 he can advance to the next stage , I cant tell you exactly how i made it into an aura that follows me around so your just gonna have to play around with skills that already have that feature. . .
Not much left i can tell you about UNT_ things, its up to you to play with it, im not really in a rush so i havnt figured out a way to reuse a unt_ more then just the sizes/intervals but it is very possible. . .
Ok now you know brandish spear actually is the most unique skill in pre re, no other skill functions like it and im gonna post one of my custom gunslinger skills that uses the same function as brandish spear, OK you will have to make 2 changes in order for this to actually work
You need to identify it in your
skill.h
void (*brandishspear) (struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag);
void (*jumpshot) (struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag);
Code:
void (*brandishspear_first) (struct square *tc, uint8 dir, int16 x, int16 y);
void (*brandishspear_dir) (struct square* tc, uint8 dir, int are);
void (*jumpshot_first) (struct squareb *tc, uint8 dir, int16 x, int16 y);
void (*jumpshot_dir) (struct squareb* tc, uint8 dir, int are);
Once you identify/declare it, we can start working in our skill.c
Your gonna wanna write this under the brandish spear function ..
Just crtl+f for this
void skill_brandishspear
Its a alot shorter then mine because it uses fancy c++ functions that you really dont need to use. So just look at what i wrote.
//JUMPSHOT
struct squareb {
int val1[50];
int val2[50];
};
void skill_jumpshot_first (struct squareb *tc, uint8 dir, int16 x, int16 y)
{
nullpo_retv(tc);
if(dir == 0){
tc->val1[0]=x;
tc->val1[1]=x+1;
tc->val1[2]=x-1;
tc->val1[3]=x;
tc->val1[4]=x+1;
tc->val1[5]=x+1;
tc->val1[6]=x;
tc->val1[7]=x+1;
tc->val1[8]=x-1;
tc->val1[9]=x;
tc->val1[10]=x+1;
tc->val1[11]=x-1;
tc->val1[12]=x;
tc->val1[13]=x+1;
tc->val1[14]=x-1;
tc->val1[15]=x;
tc->val1[16]=x+1;
tc->val1[17]=x-1;
tc->val2[0]=y;
tc->val2[1]=y;
tc->val2[2]=y;
tc->val2[3]=y-1;
tc->val2[4]=y-1;
tc->val2[5]=y-1;
tc->val2[6]=y-2;
tc->val2[7]=y-2;
tc->val2[8]=y-2;
tc->val2[9]=y-3;
tc->val2[10]=y-3;
tc->val2[11]=y-3;
tc->val2[12]=y-4;
tc->val2[13]=y-4;
tc->val2[14]=y-4;
tc->val2[15]=y+1;
tc->val2[16]=y+1;
tc->val2[17]=y+1;
} else if(dir==2){
tc->val1[0]=x+3;
tc->val1[1]=x+3;
tc->val1[2]=x+3;
tc->val1[3]=x+4;
tc->val1[4]=x+4;
tc->val1[5]=x+4;
tc->val1[6]=x+2;
tc->val1[7]=x+2;
tc->val1[8]=x+2;
tc->val1[9]=x+1;
tc->val1[10]=x+1;
tc->val1[11]=x+1;
tc->val1[12]=x-1;
tc->val1[13]=x-1;
tc->val1[14]=x-1;
tc->val1[15]=x;
tc->val1[16]=x;
tc->val1[17]=x;
tc->val2[0]=y;
tc->val2[1]=y+1;
tc->val2[2]=y-1;
tc->val2[3]=y;
tc->val2[4]=y+1;
tc->val2[5]=y+1;
tc->val2[6]=y;
tc->val2[7]=y+1;
tc->val2[8]=y-1;
tc->val2[9]=y;
tc->val2[10]=y+1;
tc->val2[11]=y-1;
tc->val2[12]=y;
tc->val2[13]=y+1;
tc->val2[14]=y-1;
tc->val2[15]=y;
tc->val2[16]=y+1;
tc->val2[17]=y-1;
} else if(dir==4){
tc->val1[0]=x;
tc->val1[1]=x+1;
tc->val1[2]=x-1;
tc->val1[3]=x;
tc->val1[4]=x+1;
tc->val1[5]=x+1;
tc->val1[6]=x;
tc->val1[7]=x+1;
tc->val1[8]=x-1;
tc->val1[9]=x;
tc->val1[10]=x+1;
tc->val1[11]=x-1;
tc->val1[12]=x;
tc->val1[13]=x+1;
tc->val1[14]=x-1;
tc->val1[15]=x;
tc->val1[16]=x+1;
tc->val1[17]=x-1;
tc->val2[0]=y;
tc->val2[1]=y;
tc->val2[2]=y;
tc->val2[3]=y+1;
tc->val2[4]=y+1;
tc->val2[5]=y+1;
tc->val2[6]=y+2;
tc->val2[7]=y+2;
tc->val2[8]=y+2;
tc->val2[9]=y+3;
tc->val2[10]=y+3;
tc->val2[11]=y+3;
tc->val2[12]=y+4;
tc->val2[13]=y+4;
tc->val2[14]=y+4;
tc->val2[15]=y-1;
tc->val2[16]=y-1;
tc->val2[17]=y-1;
} else if(dir==6){
tc->val1[0]=x-3;
tc->val1[1]=x-3;
tc->val1[2]=x-3;
tc->val1[3]=x-4;
tc->val1[4]=x-4;
tc->val1[5]=x-4;
tc->val1[6]=x-2;
tc->val1[7]=x-2;
tc->val1[8]=x-2;
tc->val1[9]=x-1;
tc->val1[10]=x-1;
tc->val1[11]=x-1;
tc->val1[12]=x+1;
tc->val1[13]=x+1;
tc->val1[14]=x+1;
tc->val1[15]=x;
tc->val1[16]=x;
tc->val1[17]=x;
tc->val2[0]=y;
tc->val2[1]=y+1;
tc->val2[2]=y-1;
tc->val2[3]=y;
tc->val2[4]=y+1;
tc->val2[5]=y+1;
tc->val2[6]=y;
tc->val2[7]=y+1;
tc->val2[8]=y-1;
tc->val2[9]=y;
tc->val2[10]=y+1;
tc->val2[11]=y-1;
tc->val2[12]=y;
tc->val2[13]=y+1;
tc->val2[14]=y-1;
tc->val2[15]=y;
tc->val2[16]=y+1;
tc->val2[17]=y-1;
} else if(dir==1){
tc->val1[0]=x;
tc->val1[1]=x+1;
tc->val1[2]=x+2;
tc->val1[3]=x;
tc->val1[4]=x;
tc->val1[5]=x+1;
tc->val1[6]=x+2;
tc->val1[7]=x+2;
tc->val1[8]=x+1;
tc->val1[9]=x+1;
tc->val1[10]=x+2;
tc->val1[11]=x+2;
tc->val1[12]=x+3;
tc->val1[13]=x+3;
tc->val1[14]=x+3;
tc->val1[15]=x+4;
tc->val1[16]=x+3;
tc->val1[17]=x+4;
tc->val1[18]=x+4;
tc->val2[0]=y;
tc->val2[1]=y;
tc->val2[2]=y;
tc->val2[3]=y-1;
tc->val2[4]=y-2;
tc->val2[5]=y-1;
tc->val2[6]=y-1;
tc->val2[7]=y-2;
tc->val2[8]=y-2;
tc->val2[9]=y-3;
tc->val2[10]=y-3;
tc->val2[11]=y-4;
tc->val2[12]=y-4;
tc->val2[13]=y-1;
tc->val2[14]=y-2;
tc->val2[15]=y-2;
tc->val2[16]=y-3;
tc->val2[17]=y-3;
tc->val2[18]=y-4;
} else if(dir==3){
tc->val1[0]=x+4;
tc->val1[1]=x+4;
tc->val1[2]=x+4;
tc->val1[3]=x+3;
tc->val1[4]=x+3;
tc->val1[5]=x+3;
tc->val1[6]=x+3;
tc->val1[7]=x+2;
tc->val1[8]=x+2;
tc->val1[9]=x+2;
tc->val1[10]=x+2;
tc->val1[11]=x+2;
tc->val1[12]=x+1;
tc->val1[13]=x+1;
tc->val1[14]=x+1;
tc->val1[15]=x+1;
tc->val1[16]=x;
tc->val1[17]=x;
tc->val1[18]=x;
tc->val2[0]=y+4;
tc->val2[1]=y+3;
tc->val2[2]=y+2;
tc->val2[3]=y+4;
tc->val2[4]=y+3;
tc->val2[5]=y+2;
tc->val2[6]=y+1;
tc->val2[7]=y+4;
tc->val2[8]=y+3;
tc->val2[9]=y+2;
tc->val2[10]=y+1;
tc->val2[11]=y;
tc->val2[12]=y+3;
tc->val2[13]=y+2;
tc->val2[14]=y+1;
tc->val2[15]=y;
tc->val2[16]=y+2;
tc->val2[17]=y+1;
tc->val2[18]=y;
} else if(dir==5){
tc->val1[0]=x-4;
tc->val1[1]=x-3;
tc->val1[2]=x-2;
tc->val1[3]=x-4;
tc->val1[4]=x-3;
tc->val1[5]=x-2;
tc->val1[6]=x-1;
tc->val1[7]=x-4;
tc->val1[8]=x-3;
tc->val1[9]=x-2;
tc->val1[10]=x-1;
tc->val1[11]=x;
tc->val1[12]=x-3;
tc->val1[13]=x-2;
tc->val1[14]=x-1;
tc->val1[15]=x;
tc->val1[16]=x-2;
tc->val1[17]=x-1;
tc->val1[18]=x;
tc->val2[0]=y+4;
tc->val2[1]=y+4;
tc->val2[2]=y+4;
tc->val2[3]=y+3;
tc->val2[4]=y+3;
tc->val2[5]=y+3;
tc->val2[6]=y+3;
tc->val2[7]=y+2;
tc->val2[8]=y+2;
tc->val2[9]=y+2;
tc->val2[10]=y+2;
tc->val2[11]=y+2;
tc->val2[12]=y+1;
tc->val2[13]=y+1;
tc->val2[14]=y+1;
tc->val2[15]=y+1;
tc->val2[16]=y;
tc->val2[17]=y;
tc->val2[18]=y;
} else if(dir==7){
tc->val1[0]=x-4;
tc->val1[1]=x-3;
tc->val1[2]=x-2;
tc->val1[3]=x-4;
tc->val1[4]=x-3;
tc->val1[5]=x-2;
tc->val1[6]=x-1;
tc->val1[7]=x-4;
tc->val1[8]=x-3;
tc->val1[9]=x-2;
tc->val1[10]=x-1;
tc->val1[11]=x;
tc->val1[12]=x-3;
tc->val1[13]=x-2;
tc->val1[14]=x-1;
tc->val1[15]=x;
tc->val1[16]=x-2;
tc->val1[17]=x-1;
tc->val1[18]=x;
tc->val2[0]=y-4;
tc->val2[1]=y-4;
tc->val2[2]=y-4;
tc->val2[3]=y-3;
tc->val2[4]=y-3;
tc->val2[5]=y-3;
tc->val2[6]=y-3;
tc->val2[7]=y-2;
tc->val2[8]=y-2;
tc->val2[9]=y-2;
tc->val2[10]=y-2;
tc->val2[11]=y-2;
tc->val2[12]=y-1;
tc->val2[13]=y-1;
tc->val2[14]=y-1;
tc->val2[15]=y-1;
tc->val2[16]=y;
tc->val2[17]=y;
tc->val2[18]=y;
}
}
void skill_jumpshot_dir (struct squareb* tc, uint8 dir, int are)
{
int c;
nullpo_retv(tc);
for( c = 0; c < 50; c++ ) {
switch( dir ) {
case 0: tc->val2[c]+=are; break;
case 1: tc->val1[c]-=are; tc->val2[c]+=are; break;
case 2: tc->val1[c]-=are; break;
case 3: tc->val1[c]-=are; tc->val2[c]-=are; break;
case 4: tc->val2[c]-=are; break;
case 5: tc->val1[c]+=are; tc->val2[c]-=are; break;
case 6: tc->val1[c]+=are; break;
case 7: tc->val1[c]+=are; tc->val2[c]+=are; break;
}
}
}
void skill_jumpshot(struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag)
{
int c,n=49;
uint8 dir;
struct squareb tc;
int x, y;
nullpo_retv(bl);
x = bl->x;
y = bl->y;
dir = map->calc_dir(src, x, y);
skill->jumpshot_first(&tc,dir,x,y);
skill->jumpshot_dir(&tc,dir,4);
skill->area_temp[1] = bl->id;
for(c=0;c<50;c++){
if(c==0||c==50) skill->jumpshot_dir(&tc,dir,-1);
map->foreachincell(skill->area_sub,
bl->m,tc.val1[c%25],tc.val2[c%25],BL_CHAR,
src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1,
skill->castend_damage_id);
}
}
Youll notice i have 8 directions... its the same as when you place an npc and chose what way you want it to face. Its not gonna make much sense if you just look at it, so i recommend drawing it on grid paper and just TRY to see where these numbers X/Y actually fit... its really wonky but once you see it youll be like shit this is easy.
Ok im gonna post my desperado as well but were using the same functions as firewall in this skill soo youve probably seen this and thought oh i can play with this and it turns out to be really fucked up... working with this function is alot easier because its just centered on you compared to brandish spear which has 8 directions, and they start from a corner that i cant explain, like i said, draw it on paper , once you see it youll catch on quick.
first go to your
skill.h
find this
#define MAX_SKILL_UNIT_LAYOUT 65
its not gonna be 65 in your SRC cause i already raised it.
Now go to
skill.c (Your probably gonna wanna test it out a bit and practise with a skill that already uses this style of grid Wall of thorn would be easy to follow cause thats where i placed my desperado
case GS_DESPERADO: {
static const int dx[] = {-4,-4,-4,-4,-4,-4,-4,-3,-3,-3,-3,-3,-3,-3,-3,-3,-2,-2,-2,-2,-2,-2,-1,-1,-1,-1, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1};
static const int dy[] = { 3, 2, 1, 0,-1,-2,-3, 4, 3, 2, 1, 0,-1,-2,-3,-4, 4, 3, 2,-2,-3,-4, 4, 3,-4,-3,-4,-3, 4, 3, 3, 2, 1, 0,-1,-2,-3, 4, 3, 2, 1, 0,-1,-2,-3,-4, 4, 3, 2,-2,-3,-4, 4, 3,-4,-3};
skill->dbs->unit_layout[pos].count = 56;
memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy));
}
break;
Ok so the first cell would be -4,3 .. . . the next cell is -4,2 then -4,1 -4,0 -4,-1 -4-2
Look at the top one and the one under it, thats the cell that it will hit.
Change the UNIT_LAYOUT[pos].count = - - - - number to match the amount of cells so i made desperado a 56 cell skill that circles around me, but it leaves a small gap so that monsters directly in front or around me dont get it. Draw it.
and this is what my desperado looks like in my skill.db
{
Id: 516
Name: "GS_DESPERADO"
Description: "Desperado"
MaxLevel: 30
Hit: "BDT_MULTIHIT"
SkillType: {
Self: true
}
AttackType: "Weapon"
Element: "Ele_Weapon"
AfterCastActDelay: 0
AfterCastWalkDelay: 1500
SkillData1: 25
CoolDown: 500
Requirements: {
SPCost: {
Lv1: 32
Lv2: 34
Lv3: 36
Lv4: 38
Lv5: 40
Lv6: 42
Lv7: 44
Lv8: 46
Lv9: 48
Lv10: 50
}
WeaponTypes: {
Revolvers: true
}
AmmoTypes: {
A_BULLET: true
}
AmmoAmount: 10
}
Unit: {
Id: 0x86
Layout: -1
Interval: 100
Target: "Enemy"
}
},
UNT ID:0x86 is used EVERYWHERE , arrowshower stormgust..comet meteor they all use the same thing but they have their effects linked client side... this is mostly used for damage skills and the other UNT_s are everything else, sanctuary has its own UNT, all the dances/songs have their own UNT's. . . youll have to look at their ID in the skill db if you wanna re use them somewhere else, but like i said, your gonna have to figure out how to use them in a bunch of different ways right?
Your probably not gonna be able to make. . . UNT_UGLYDANCE , be reused... one 2 different custom skills where one of them stuns everyone around you . . . . and then you have another skill that uses UNT_UGLYDANCE but that one freezes everybody ... im still working on this.
enjoy lol . . i didnt miss anything and i just told you everything i know about UNT_'s and how to use them and how to make custom sizes both ways, in place skills (i know desperado isnt look like a place but it actually kinda is) and the way brandish spear is use, where you click on something and then it has its SPECIFIC area, not just a splash, it has its own pattern,, you can get complicated if you want but i recommend learning from ME and not from what brandish spear function cause that thing is intermidate level C++ and uses a growth function (++) . . . i made it really simple.