Jump to content

Scripting and related questions


Recommended Posts

I seem to recall some version of the 3D editor incorporating a palette, like the floor/terrain palettes, to select items and monsters. However, the latest version on Niemand's website does not appear to have this. smirk I can cycle through floor/terrain/height as usual, but item and monster are not in the cycle.

 

Am I missing something? Was it removed? Is that not the latest version? smirk

Link to comment
Share on other sites

Is it possible to make a character do something special when they are attacked? For example, summoning aid or initiating dialog.

 

And if the answer is "yes", would it require a special script? Or could it be done by calling a town or scenario state?

 

I assume going hostile is automatic if you attack a friendly?

Link to comment
Share on other sites

To your first question, sort of, but not exactly. You can have the creature' script call who_hit_me() to find out if it has been attacked that round, but this means that it will wait until its turn to react to being attacked. So, if you were going to do something like advance the plot when the party attacks a certain enemy, you might need to put fallback code into the creature's DEAD_STATE as well, just in case the party somehow wipes it out in one round before it gets a chance to act.

 

To your second question: yes. However, there is a distinction between having the attacked creature turn hostile and all of the friendly creatures in the town turn hostile; the latter you can tune with set_crime_tolerance().

Link to comment
Share on other sites

Is the state executed by the party stepping into a special encounter rectangle? (move_to_new_town() won't do anything otherwise). Or, have you tried having it print out the value of choice right after you set it (print_num(choice);)? At a glance your code looks correct to me, but you might want to make sure that the value that you're getting is the one you expect.

Link to comment
Share on other sites

A lot of it apparently has to do with the fact that the game needs to unload and load scripts to do the move, including needing to unload the script which it is running. It's not that it's an impossible task, but it's annoying, and a lot of important details might change if the call were allowed to be used in more complicated ways. My understanding is that Jeff restricted its usage to minimize the trouble he would have with implementing it.

Link to comment
Share on other sites

If I'm spawning a creature, there's some way of getting its number for further calls, right?

 

Also, if you give a creature an item in the editor, does it count as part of their inventory, or is it just something they might drop? For example, if I give a wand in the editor, will it (possibly) use it?

Link to comment
Share on other sites

Quote:
f I'm spawning a creature, there's some way of getting its number for further calls, right?

Ha, ha, ha; no.

I think that you can work around this by determining the first unused summoned creature slot before doing the summon, to know what number it will end up with when summoned; I seem to recall that's what other designers have done in the past.

Quote:
Also, if you give a creature an item in the editor, does it count as part of their inventory, or is it just something they might drop? For example, if I give a wand in the editor, will it (possibly) use it?

I think so, but I'm really not sure. You might just have to run some (a lot) of tests.
Link to comment
Share on other sites

I agree that hidden groups are the answer, if and only if the creatures you want and the places where you want them are constant. This won't help you if you want to do something like a custom summoning spell, where the type and location of the creatures depend on parameters not known until runtime. If that is the case, more advanced methods are needed.

 

(Another method, although not one I'd recommend depending on, as it can be flaky unless you're very careful, is simply checking what creature is on the space where you placed the summon after you do the summon. This will go badly wrong if for any reason the game decided to place the summoned creature on a slightly different space than the one you specified, but is otherwise simple.)

Link to comment
Share on other sites

So, there are three possible methods, not including hidden groups (because this is, in fact, a custom summoning spell).

 

Though... you can resurrect monsters, right? So a hidden group could be possible if the location it appears on is a constant; but I was going to randomly select a location, so that doesn't work.

 

Originally Posted By: Niemand
I think that you can work around this by determining the first unused summoned creature slot before doing the summon, to know what number it will end up with when summoned; I seem to recall that's what other designers have done in the past.
So, how is this done? Looping through characters starting at 6 until char_ok() returns false? Or something else?

 

Originally Posted By: Enraged Slith
You can have summoned creatures give their number with custom creature scripts. This is how I make my awesome necromancer script work. Otherwise, Niemand's suggestion is, as usual, the best solution.
That would require the custom script being the creature's default script, though, right? So I don't think I can do it that way. Still, it would be nice to know how that works.

 

Originally Posted By: Niemand
(Another method, although not one I'd recommend depending on, as it can be flaky unless you're very careful, is simply checking what creature is on the space where you placed the summon after you do the summon. This will go badly wrong if for any reason the game decided to place the summoned creature on a slightly different space than the one you specified, but is otherwise simple.)
But wait... if you tell the game to spawn a creature on (x,y), it will be spawned on (x,y), right? (If all goes well, it'll also be guaranteed that there's no creature on the randomly selected location.)
Link to comment
Share on other sites

You could change your summoned creatures default scripts to a custom script, which could be as simple as basicnpc + a call in each state that either sends a message or replicates something like it. You could even set a condition that they would only send that message if their creature number was greater than the summoned creature slots.

 

EDIT: This is the summoning portion of my script which works pretty damn well (thanks again Niemand). Although you might try a different method, this works like a summoning spell.

Code:
 beginstate 3; // summoning	if (target_ok() == FALSE)		set_state(START_STATE);	if(friends_nearby(24) >= 1)		set_state(4);	i = 0;	w = 0;	myx = my_loc_x();	myy = my_loc_y();	set_character_pose(ME,1);	force_instant_terrain_redraw();	put_sparkles_on_char(ME,1,7);	run_animation_sound(-25);	print_str_color("Necromancer casts Dark Summoning!",4);	pause(4);	num = get_ran(1,2,5);	while(i < num){		who = get_ran(1,0,99);		if(who <= 29) //skeleton			sum = 234;		if((30 <= who) && (who <= 55)) //zombie			sum = 235;		if((56 <= who) && (who <= 71)) //shade			sum = 240;		if((72 <= who) && (who <= 82)) //ghoul			sum = 236;		if((83 <= who) && (who <= 88)) //greater shade			sum = 241;		if((89 <= who) && (who <= 94)) //ghast			sum = 237;		if((95 <= who) && (who <= 99)) //wight			sum = 239;		w = 0;		while(w < 100){ //make it possible to give up rather than trying for too long			tx = get_ran(1,(myx - 2),(myx + 2));			ty = get_ran(1,(myy - 2),(myy + 2));			if(can_see_loc(tx,ty) == TRUE){				if(char_on_loc(tx,ty) < 0){					if(get_terrain(tx,ty) < 1)						w = 100 + 1; //break out of the loop					}				}			else				w = w + 1;			}		if(w == 101){ //a valid space was found			place_monster(tx,ty,sum,1);			put_boom_on_space(tx,ty,7,0);			run_animation_sound(75);			pause(4);			}		i = i + 1;		}	set_character_pose(ME,0);	force_instant_terrain_redraw();	end_combat_turn();break; 
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
So, there are three possible methods, not including hidden groups (because this is, in fact, a custom summoning spell).

Though... you can resurrect monsters, right? So a hidden group could be possible if the location it appears on is a constant; but I was going to randomly select a location, so that doesn't work.

This would necessarily require a constant location as much as a constant creature type; you can always relocate the creature somewhere else after you reveal it, but the only creature you'll be able to reveal will be the type you place in the editor. Also, you'll only be able to have one of it, which might or might not be appropriate.

Originally Posted By: Celtic Minstrel
Originally Posted By: Niemand
I think that you can work around this by determining the first unused summoned creature slot before doing the summon, to know what number it will end up with when summoned; I seem to recall that's what other designers have done in the past.
So, how is this done? Looping through characters starting at 6 until char_ok() returns false? Or something else?

You don't want to start at 6, but instead at the lowest number (86) that a summoned creature can have. Numbers [6,85] can only be creatures placed in the editor, so even if you find an empty space in the range it won't be the one the game chooses for your summon. See "How Characters Are Identified" in section 2.8 of the Editor Docs.

Originally Posted By: Celtic Minstrel
Originally Posted By: Niemand
(Another method, although not one I'd recommend depending on, as it can be flaky unless you're very careful, is simply checking what creature is on the space where you placed the summon after you do the summon. This will go badly wrong if for any reason the game decided to place the summoned creature on a slightly different space than the one you specified, but is otherwise simple.)
But wait... if you tell the game to spawn a creature on (x,y), it will be spawned on (x,y), right? (If all goes well, it'll also be guaranteed that there's no creature on the randomly selected location.)

If you are very careful you can ensure that the space is clear before you request the summon, and so it will be placed on that space, but it's easy to make mistakes. For instance, since there are no calls to check whether a given floor type is passable*, you'll need to check the floor type 'manually' to make sure you can place a creature on it.

*This just gave me an idea that I'm now itching to implement. Sadly, it will have to wait until after classes and work.
Link to comment
Share on other sites

Originally Posted By: Niemand
You don't want to start at 6, but instead at the lowest number (86) that a summoned creature can have. Numbers [6,85] can only be creatures placed in the editor, so even if you find an empty space in the range it won't be the one the game chooses for your summon. See "How Characters Are Identified" in section 2.8 of the Editor Docs.
Okay, so that's fairly simple to do.

Originally Posted By: Niemand
If you are very careful you can ensure that the space is clear before you request the summon, and so it will be placed on that space, but it's easy to make mistakes. For instance, since there are no calls to check whether a given floor type is passable*, you'll need to check the floor type 'manually' to make sure you can place a creature on it.
Well, I'll do something like this to select the location:
Code:
x = get_ran(1,min_x,max_x);y = get_ran(1,min_y,max_y);while(char_on_loc(x,y) >= 0) {    x = get_ran(1,min_x,max_x);    y = get_ran(1,min_y,max_y);}
So, there shouldn't be another character on the eventually selected space. And I'm not worried about the space being passable, but if I were I would incorporate similar checks for that.
Link to comment
Share on other sites

100% sure. I even went and tested it. The monster is unable to move, since the table blocks movement in all directions.

 

Edit: The easiest thing you can do is do a quick check to see if the target space is set to terrain 0, or some of the more common, non-movement blocking terrains like torches, wall hangings, and so on.

Link to comment
Share on other sites

One thing to note is that using the call place_monster(), will place the monster a space away if another creature is already standing on it. This was still a problem in my script as I added animation effects for the creatures being summoned, but it might remove one concern from your list.

Link to comment
Share on other sites

Well, that's kind of silly... being on an impassable space shouldn't prevent a creature from acting.

 

Though it's probably best to refrain from doing it for a different reason: it should be impossible to attack such a monster.

 

There are only three blocked spaces, so that should be easy to deal with.

 

By the way, is a PC on a blocked space able to move?

Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
Well, that's kind of silly... being on an impassable space shouldn't prevent a creature from acting.


Think about how impassable terrains actually operate: it's not the space itself that's blocked to movement, it's all four directions around it. They're simply terrains which block passage to and from the north, south, east and west. Just like you can't walk through a wall even if you're standing on the space where the wall terrain has been placed, you can't walk through the barriers around an impossible terrain space, whether you're inside it or out.
Link to comment
Share on other sites

A quick test reveals this to be at least partially false. A PC on a desk can move off of it. A PC on a bed cannot move off of it, but can still cast a spell (I dunno whether they could melee attack or throw something; probably the latter but not the former). So it prevents you from moving, but not from acting.

 

The same appears to be true of monsters on an impassable space: they can act, but not move off the space by conventional means.

 

So, no need to ensure the target space is passable.

 

EDIT: Wait, no, there's another reason to ensure the target space is passable - I don't think you can target something on an impassable space. Fortunately this will be an easy task.

 

EDIT2: Well, you can target it with spells; attempting to target with melee seems to work yet does no damage.

Link to comment
Share on other sites

Soooo...

 

"get_nearest_good_char" returns the nearest character friendly to the party, yet is intended for use in creature and terrain scripts? How is that useful? I need to locate a creature friendly to the one whose script is running, without knowing whether it is friendly to the party or not.

 

Unless of course that's a documentation error? But I bet it isn't...

Link to comment
Share on other sites

It's useful directly if you know you're writing a script for a creature that will be on the party's side, or a terrain that you know will be a tool for the dungeon boss. . . Of course you can just decide dynamically which to use depending on the current creature's attitude toward the party.

 

Code:
//set i to the nearest character friendly to meif(get_attitude(ME) == 3)	i = get_nearest_good_char(radius);else	i = get_nearest_evil_char(radius);

This would still run into trouble if you need to have both hostile types A and B in play. In that case, you probably just want to write your own search loop. (I always write my own loop anyway, since I pretty much always want to impose additional conditions on the character I select.)

Link to comment
Share on other sites

  • 3 weeks later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...