The Dink Network

Summoning

March 6th 2006, 11:27 AM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
I'm working on scripts to summon a monster and have run into some complications, when you switch screens, he (the summoned creature) isn't created anew. Here is the script, I dunno what's wrong with it...

//create summon and screen follow and crap

void main( void )
{
//for explosion
int &explo;
//for summon
int &beast;
//to figure out if we need to creaet him on the new screen
int &mapnum
//for 'x' coordinate so we can create summon at Dink's spot
int &mholdx
//for 'y' coordinate so we can create summon at Dink's spot
int &mholdy

//get dink's coordinates
&mholdx = sp_x(1, -1);
&mholdy = sp_y(1, -1);

//create explosion - set all of this crap so it'll play right (stolen from 'dam-sfb')
//used for effects, so he doesn't just appear from nowhere
&explo = create_sprite(&mholdx , &mholdy, 0 , 167, 1);
sp_seq(&explo, 167);
sp_pseq(&explo, 167);
sp_frame(&explo, 1);
sp_brain(&explo, 7);
sp_nohit(&explo, 1);

//create our summon
&beast = create_sprite(&mholdx, &mholdy, 9, 823, 1);
//give him his script
sp_script(&beast, "summoned");

//he is created on the same screen as dink
&mapnum = &player_map

//so script will stay active beyond screen transition
script_attach(1000);

//set up a loop so it'll keep checking
loop:

//dink changed screens, we need to create summon anew
if (&mapnum != &player_map)
{
//is summon alive?
if (&summon <= 1)
{
//make him again and give him his script
int &beast = create_sprite(&mholdx, mholdy, 9, 823, 1);
sp_script(&beast, "summoned");
}

}
//whether Dink changed screens or not...he's dead, kill the script
if (&summon == 0)
kill_this_task();

//go to the begining of loop to keep checking infinitely...until he's dead at least
goto loop;
}
March 6th 2006, 01:01 PM
old.gif
jjohn
Peasant He/Him
 
I'm going to ask a silly question.

&summoned is a declare global variable right?

Otherwise, I believe it will not retain its value between
script invocations.
March 6th 2006, 01:12 PM
slimeg.gif
metatarasal
Bard He/Him Netherlands
I object 
A loop without a wait(); command... Dangerous...

Wouldn't you need (&summon >= 1) instead of (&summon <= 1)? I guess I need to know how &summon is changed... Also &summon needs to be a global (like jjohn said).
March 6th 2006, 01:28 PM
duck.gif
wesley
Peasant He/Him United States
 
I created something like this yesterday actually, although not for a summon spell. First off missing semi-colons might be causing problems (they definitely will, but perhaps not this problem)

int &mapnum
int &mholdx
int &mholdy
&mapnum = &player_map

Further, I think the problem is that you aren't setting &mapnum = &player_map inside the loop. You need to constantly check to see if you switched screens, not just check initially... the script doesn't restart on a map switch.

loop:
wait(25);
if (&mapnum != &player_map)
{
//Do all your checks to see if summon is active. If not, kill the summon var and skip to the end
goto end;

//looks like we switched maps, time to create the beast again
...
//make beast code here
...
}

//now set the &mapnum to &player_map.
&mapnum = &player_map;

//after you restart the loop, if you change screens in the next 25ms then the beast will be re-summoned (created)
goto loop;

end:
//reset vars if needed
kill_this_task();
March 6th 2006, 07:11 PM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
It is working 100% properly now. Thanks everybody for helping out. Here is what the loop looks like now...

//set up a loop so it'll keep checking
loopy:
wait(25);

//if dink changed screens, we need to create summon anew
if (&mapnum != &player_map)
{
//is summon alive?
if (&summon >= 1)
{
//make him again and give him his script
&mholdx = sp_x(1, -1);
&mholdy = sp_y(1, -1);
&beast = create_sprite(&mholdx, mholdy, 9, 823, 1);
sp_script(&beast, "summoned");
&mapnum = &player_map;
}

}
//whether Dink changed screens or not...if he's dead, kill the script
if (&summon == 0)
{
kill_this_task();
}

//go to the begining of loop to keep checking infinitely,
//until he's dead at least
wait(1);

goto loopy;
March 6th 2006, 07:25 PM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
Another problem. This time it concerns the script for the summoned sprite itself. Here is a piece of it's script. The thing that's wrong? As you can see, I attempted to add experience if the thing kills the enemy. Doesn't seem to work though...

void attack( void )
{
//sound effect
playsound(27, 28050,0,&current_sprite, 0);

//attack delay
&mcounter = random(4000,0);
sp_attack_wait(&current_sprite, &mcounter);

//check to kill
&enemy_hp = sp_hitpoints(&mtarget, -1);

//yay, we killed our target, get a new one, or just act stupid...and add some experience too
if (&enemy_hp <= 0)
{
//experience..why won't this freaking work!! X0
&my_exp = sp_exp(&mtarget, -1);
//&my_exp = &my_exp / 2 //say we only want dink to get half...
add_exp(&my_exp, &mtarget);
goto get_target;
}
}

note:all variables are initted in main procedure
March 6th 2006, 11:15 PM
duck.gif
wesley
Peasant He/Him United States
 
I haven't tested it, but it could be that the add_exp() isn't working because &mtarget is dead/not active. Just a guess. What if you do

add_exp(&my_exp, 1);

the number will float above you, but that will test if my theory is correct or not.
March 7th 2006, 05:51 AM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
Yeah, IIRC, the HP is deducted after the attack procedure, not before... so you'll never actually get to reach a negative HP... or something like that.
March 7th 2006, 11:12 AM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
I've fixed that now Phoenix. After futher testing, by using a 'say' command, I've noticed that the calculated experience points (my_exp) is always -1...
March 7th 2006, 04:27 PM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
Experience bug now fixed. I defining the variable after the thing died, that caused the problem. One more...turns out I'm not done with the other script. When you change screens, the summon is created again...in the corner...here's the script:

//create summon and screen follow and crap

void main( void )
{
//for explosion
int &explo;
//to figure out if we need to create him on the new screen
int &mapnum;
//for 'x' coordinate so we can create summon at Dink's spot
int &mholdx;
//for 'y' coordinate so we can create summon at Dink's spot
int &mholdy;

//get dink's coordinates
&mholdx = sp_x(1, -1);
&mholdy = sp_y(1, -1);

//create explosion - set all of this crap so it'll play right (stolen from 'dam-sfb')
//used for effects, so he doesn't just appear from nowhere
&explo = create_sprite(&mholdx , &mholdy, 0 , 167, 1);
sp_seq(&explo, 167);
sp_pseq(&explo, 167);
sp_frame(&explo, 1);
sp_brain(&explo, 7);
sp_nohit(&explo, 1);

//create our summon
&summon = create_sprite(&mholdx, &mholdy, 9, 823, 1);
//give him his script
sp_script(&summon, "summoned");

//he is created on the same screen as dink
&mapnum = &player_map;

//so script will stay active beyond screen transition
script_attach(1000);

//set up a loop so it'll keep checking
loopy:
wait(25);

//if dink changed screens, we need to create summon anew
if (&mapnum != &player_map)
{
//is summon alive?
if (&summon >= 1)
{
//make him again and give him his script
wait(200);
//get Dink's new coordinates
&mholdx = sp_x(1, -1);
&mholdy = sp_y(1, -1);
&summon = create_sprite(&mholdx, mholdy, 9, 823, 1);
sp_script(&summon, "summoned");
//change his map to Dink's
&mapnum = &player_map;
}

}
//whether Dink changed screens or not...if he's dead, kill the script
if (&summon == 0)
{
kill_this_task();
}

//go to the begining of loop to keep checking infinitely,
//until he's dead at least
wait(1);

goto loopy;
}
March 7th 2006, 08:53 PM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
I figured out the problem...
&summon = create_sprite(&mholdx, mholdy, 9, 823, 1);
needed to be
&summon = create_sprite(&mholdx, &mholdy, 9, 823, 1);
that y coordinate made him shift to the corner. I'm almost finished with this thing so I'll keep everyone posted on it's progress.
March 8th 2006, 10:39 AM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
I made my summon be created as a global variable, but I can't seem to get enemies to target him. I was hoping I could edit the enemy scripts, so they have an 'option' of targeting the summon (like they target Dink) upon screen entry. Otherwise, the only way they will target him is if they get hit. If no one can help me, I guess I'll just keep it as is..This appears to be the last thing that needs to be done.
March 8th 2006, 11:17 AM
bonca.gif
Christiaan
Bard They/Them Netherlands
Lazy bum 
sp_target(¤t_sprite, &variable); doesn't work, I assume?

edit: a weird idea, but you might let the summoned creature "hit" a random brain 9 or 10 creature with magic, like the dragons. But then make it so it does 0 damage, then they will come after him. I don't know if it works, and if so, if you can make the "0" dissapear that's floating above the targeted creature, but it might just do the trick.
March 10th 2006, 10:13 AM
duck.gif
wesley
Peasant He/Him United States
 
would doing a wait(1); in the enemy scripts work? The main proc might be running before the summon sprite is created. Actually since your summon script loop is a wait(25); to check if the screen has changed, maybe put a wait(30); at then end of the enemy's main proc and then sp_target(&cur... &summon); after the wait command.

Might work. They can't target the summon if it isn't drawn yet.
March 10th 2006, 11:23 AM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
That makes sense. I'll try it when I get home. I guess I'll try something like...

wait(30);
//see if there is a summon
if (&summon > 0)
{
if ((&random(1,2)) == 2)
{
sp_target(&current_sprite, &summon);
}
}

If this doesn't work, maybe theres a way I can force them to do this upon creating the summon on the screens. I was thinking on putting these lines in a new procedure for the enemy. I think you can make a script do a procedure from another. I'll check into it.
March 10th 2006, 11:26 AM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
Christiaan: I'm almost positive that a variable in that line works...look at an enemies hit procedure, isn't there something like sp_target(&current_sprite, &enemy); ?
March 10th 2006, 02:08 PM
duck.gif
wesley
Peasant He/Him United States
 
From the Dink source code: en-pbon.c

void hit( void )
{
...
sp_target(&current_sprite, &enemy_sprite);
...
}
March 10th 2006, 03:32 PM
custom_magicman.gif
magicman
Peasant They/Them Netherlands duck
Mmmm, pizza. 
You can't nest functions (or control structures, like if) in DinkC:

if ((&random(1,2)) == 2)
{
sp_target(&current_sprite, &summon);
}

Isn't strictly possible, instead, try:

int &crap = random(2,1)
if (&crap == 2)
{
sp_target(&current_sprite, &summon);
}

&random doesn't make sense, random is a function, not a variable. The & sign is not needed.
Furthermore, random(&a, &b) generates a number between &b and &b + &a - 1, so random(1,2) is constant 2.
March 10th 2006, 03:51 PM
anon.gif
rabidwolf9
Ghost They/Them
 
I was trying to remembr off the top of my head, yep, i realize not that I have the numbers inverted, and there's no use for the "&", but, after looking at the "en-pill1" script, I found this line.

if (random(2,1) == 1)
{
sp_target(&current_sprite, 1);
}

I knew I saw it before...I remembered the concept of it, just not every little detail. So, I guess there's no need for an extra variable. But thanks for clearing things up a little
March 10th 2006, 03:52 PM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
I was trying to remember off the top of my head. Yep, I realize now that I have the numbers inverted, and there's no use for the "&", but, after looking at the "en-pill1" script, I found this line.

if (random(2,1) == 1)
{
sp_target(&current_sprite, 1);
}

I knew I saw it before...I remembered the concept of it, just not every little detail. So, I guess there's no need for an extra variable. But thanks for clearing things up a little
March 10th 2006, 03:55 PM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
Oops...I hate it when that happens
March 10th 2006, 04:07 PM
custom_magicman.gif
magicman
Peasant They/Them Netherlands duck
Mmmm, pizza. 
Anyway, the & sign and the reverse order of the arguments might've screwed things up. IIRC, the Dink engine will see everything starting with an & as a variable.
March 10th 2006, 04:11 PM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
Just a random question, sorry for being slow, but what exactly does "IIRC" mean?
March 10th 2006, 04:34 PM
custom_magicman.gif
magicman
Peasant They/Them Netherlands duck
Mmmm, pizza. 
If I Remember/Recall Correctly
March 13th 2006, 04:13 PM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
Okay, I've got a surefire meathod now. All I need to know is how I can save all sprite numbers with a certain brain into a set variable.
March 14th 2006, 01:42 PM
knightg.gif
cypry
Peasant He/Him Romania
Chop your own wood, and it will warm you twice. 
You mean saving several numbers in a single variable? It can be done, but it's not easy. If this is what you want(I'm not sure I understood your question) I'll teach you how to do it.
March 14th 2006, 03:41 PM
custom_magicman.gif
magicman
Peasant They/Them Netherlands duck
Mmmm, pizza. 
Supervars?

Yes, it can be done... It's still pretty limited, though.
March 14th 2006, 04:10 PM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
What I meant...you know how you can do this to get a sprite number with a certain brain?:

int &mtarget;
&mtarget = get_sprite_with_this_brain(9, &current_sprite);

I need a meathod or such to do this for all sprites with that certain brain number on the screen.
March 14th 2006, 04:26 PM
custom_king.png
redink1
King He/Him United States bloop
A mother ducking wizard 
From the DinkC Reference v4.0, under get_next_sprite_with_this_brain:

int &sprite = 0;
loop:
&sprite = get_next_sprite_with_this_brain(9, 0, &sprite);
if (&sprite > 0)
{
say("Banana!", &sprite);
//Increment &sprite so we start with the next sprite
&sprite++;
goto loop;
}
March 14th 2006, 06:56 PM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
Hmmm...shouldn't I be able to copy that as is and it'll work? I tried testing it and it freezes the game
March 14th 2006, 07:11 PM
custom_magicman.gif
magicman
Peasant They/Them Netherlands duck
Mmmm, pizza. 
After making sure you are using 1.08 (get_next_sprite_with_this_brain() is new in 1.08), put
wait(1);
right after loop:

March 14th 2006, 08:42 PM
duck.gif
wesley
Peasant He/Him United States
 
I've done no testing to confirm this, but I believe there is an error in the example code.

I think the problem with that code is that it is always starting with sprite 0. The first loop will get the first brain 9, the second loop will ignore the first brain 9 and grab the second, but if there are more than 2 brain 9 enemies on screen, it will just keep looping and grabbing the second brain 9 sprite.

What I did in a similar script was before the goto loop; line, store the current sprite in a &temp (global) variable although it could be a local as well.

Here is my code to freeze all sprites on the screen. I might be able to remove some lines but I just wanted to get it working and move on for now.

&temp, &temp2 are global.

//Start Code snippet
&temp = get_sprite_with_this_brain(9, 0);
freeze(&temp);
freezeem:

&temp2 = get_next_sprite_with_this_brain(9, &temp, &temp);
freeze(&temp2);
if (&temp2 == 0)
goto b10;

&temp = &temp2;
goto freezeem;
March 14th 2006, 08:59 PM
custom_king.png
redink1
King He/Him United States bloop
A mother ducking wizard 
Pfft... testing.

int &sprite = 0;
loop:
&sprite = get_next_sprite_with_this_brain(9, 0, &sprite);
if (&sprite > 0)
{
say("Banana!", &sprite);
//Increment &sprite so we start with the next sprite
&sprite += 1;
goto loop;
}
March 15th 2006, 01:23 PM
custom_magicman.gif
magicman
Peasant They/Them Netherlands duck
Mmmm, pizza. 
Well, no... Say the first brain 9 sprite is number 5, the second is number 18 and the third is 35. We start with 0 "ah, we've found 5", &sprite is now 5, which is greater than 0, so say banana and increment &sprite (which is now 6). "ah, we've found 18", &sprite is now 18, which is greater than 0, so say banana and increment &sprite (which is now 19). "ah, we've found 35", etc...
March 16th 2006, 10:41 AM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
Thanks a bunch Redink. It works beautifully. After a few finishing touches it will be ready.
March 16th 2006, 04:28 PM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
Okay members of the DN one last thing, really...Everything is working fine, but... I have some lines that need to happen for the screenlock enemy to unlock the screen...Why not just copy from an example script? That's no good, it needs to exclude our summon. I know that I could make another script and spawn it..but I'm ending up with too many scripts as it is, here are the lines that need to play in the die procedure of the enemy:
note: &locks is initted in main procedure

//exclude summoned monster

&locks = get_sprite_with_this_brain(9, &summon);
//subtract one for the monster that just died
&locks -= 1;
if (&locks == 0)
{
//no more brain 9 monsters here, lets unlock the screen

screenlock(0);
playsound(43, 22050,0,0,0);

}
March 16th 2006, 04:36 PM
knightg.gif
cypry
Peasant He/Him Romania
Chop your own wood, and it will warm you twice. 
The function get_sprite_with_this_brain retruns the first sprite found that has that brain(not the number of sprites with that brain). The second parm is the calling sprite that isn't counted.
I think all you have to do is remove the
&locks-=1;
March 16th 2006, 04:44 PM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
I could do some scripting to get around this, but the problem is that the enemy that just died is counted as well. Thanks, I'll try something.
March 16th 2006, 05:01 PM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
Okay, aside from that error, I remember that doing stuff in the death procedure of a script doesn't always work, IIRC there is a way other than spawning a new script, but I don't remember.

Update: That error is no more. It works perfectly when a script is spawned...
March 17th 2006, 10:44 AM
slayer.gif
rabidwolf9
Peasant He/Him United States
twitch.tv/rabidwolf9 
I uploaded it last night, hopefully it'll be released soon. It worked perfectly when I tested it, but if there are any problems, be sure to let me know so they can be fixed asap. In case I haven't explained what it is:

It is a spell to summon a stone giant to fight for Dink. I commented the scripts to some degree, so it shouldn't be that hard to modify and implement into a DMOD. I hope that it will be used in future DMODs.
March 17th 2006, 10:14 PM
knightg.gif
cypry
Peasant He/Him Romania
Chop your own wood, and it will warm you twice. 
The other way to do this is to create a sprite outside the screen(by giving it negative coordinates), then attach the script to it.
March 18th 2006, 07:03 AM
bonca.gif
Christiaan
Bard They/Them Netherlands
Lazy bum 
This is an awesome file, really, it's perfect! I'll write a review for it soon, and I'm gonna use it my D-Mod for sure! (modify it heavily though)

Full props!
March 18th 2006, 08:16 AM
knightg.gif
cypry
Peasant He/Him Romania
Chop your own wood, and it will warm you twice. 
Great file! You even get the experience if your summoned monster kills the enemy.