Jump to content

Creature Curiosities


Enraged Slith

Recommended Posts

Two things I've noticed about creatures lately when trying to script interesting encounters:

 

1. Their pathfinding is ass. One of my fights involves the party starting up on a cliff, with a ramp leading down to the battle. The enemy creatures literally beeline straight for the cliff edge from below and just sit there like statues. I can work around this with waypoints, but eww...

 

2. Creatures (maybe just certain creature types) don't like to follow drop percentages. They just drop whatever you feel like. If you decide that you're going to have a creature use a long sword, and you set it to 100%, you aren't going to see 100% long swords every time you kill that creature. Chances are, you aren't even going to see 50% long swords. As another example, in Gluckcluck, I tried giving a random monster a 1% chance of dropping a Ring of Speed, and yet, in my tests and from every beta report I received, that ring dropped nearly every single time. I really don't know the specifics behind this bug, but it's pretty darn aggravating.

 

If anyone has any other creature related curiosities, or can expand on these two, I'd be happy to hear it.

Link to comment
Share on other sites

I just did a quick check in the original Avernumscript documentation; do_attack_tactic(3) will force a character to "strongly prefer to use an item in its inventory." I'm assuming that means there's still a chance (albeit lessened) that the character can use other tactics, so using an item won't happen automatically every time.

Link to comment
Share on other sites

  • 6 months later...

This repeats until the creature runs out of action points, without running through the rest of the script.

Code:
	if(enemies_nearby(1) > 1){		print_str("test");		deduct_ap(1);		}

 

Removing the call deduct_ap() doesn't produce this problem. Neither does changing the condition. I have no idea why the combination of enemies_nearby() and deduct_ap() cause the script to behave silly.

Link to comment
Share on other sites

It isn't finished yet and it's still messy because I'm trying to figure out the best way to get it to leave a trail of flames behind after every step. It works, crudely, but the deduct_ap() in the problem section caused everything past it to completely stop. There were no errors, the script simply loops until he's out of action points. When I changed the condition, there was no problem, and when I removed the call, there was no problem.

 

Code:
beginstate 3;	// attacking	target = get_target();	if (target_ok() == FALSE)		set_state(START_STATE);	if((myx != my_loc_x()) || (myy != my_loc_y())){		put_field_on_space(myx,myy,1);		put_effect_on_space(myx,myy,1,3,1);		run_animation_sound(-167);		}	if(enemies_nearby(1) > 1){		put_effect_on_char(ME,0,7,1);		run_animation_sound(44);		force_status_nearby(-1,1,2,0);		deduct_ap(1);		}	if(maintain_dist_to_char(ME,target,4) == 1){		x = get_ran(1,1,5);		myx = my_loc_x();		myy = my_loc_y();		tx = char_loc_x(get_target());		ty = char_loc_y(get_target());		if(x == 1){			set_character_pose(ME,1);			force_instant_terrain_redraw();			put_effect_on_char(target,12,1,2);			put_straight_zap(myx,myy,tx,ty,4);			run_animation_sound(70);			damage_char(target,get_ran(1,1,7),4);			}		if(x == 2){			set_character_pose(ME,1);			force_instant_terrain_redraw();			put_effect_on_char(target,9,1,2);			put_straight_zap(myx,myy,tx,ty,0);			run_animation_sound(11);			damage_near_loc(tx,ty,get_ran(1,3,5),2,1);			}		if(x == 3){			set_character_pose(ME,1);			force_instant_terrain_redraw();			put_effect_on_char(target,3,1,2);			put_straight_zap(myx,myy,tx,ty,0);			run_animation_sound(14);			damage_char(target,get_ran(1,1,3),1);			set_char_status(target,3,-2,0,1);			}		if(x == 4){			set_character_pose(ME,1);			force_instant_terrain_redraw();			put_effect_on_char(target,13,1,2);			put_straight_zap(myx,myy,tx,ty,3);			run_animation_sound(14);			put_field_on_space(tx,ty,3);			put_field_on_space(tx + 1,ty,3);			put_field_on_space(tx - 1,ty,3);			put_field_on_space(tx,ty + 1,3);			put_field_on_space(tx,ty - 1,3);			set_char_status(target,0,20,0,1);			set_char_status(target,21,2,0,1);			play_sound(66);			}		if(x == 5){			set_character_pose(ME,1);			force_instant_terrain_redraw();			put_sparkles_on_char(target,7,5);			put_straight_zap(myx,myy,tx,ty,0);			run_animation_sound(17);			set_char_status(target,9,2,0,1);			set_char_status(target,18,2,0,1);			}		set_character_pose(ME,0);		force_instant_terrain_redraw();		pause(2);		deduct_ap(1);		}	myx = my_loc_x();	myy = my_loc_y();break;

 

Everything else functions like the basicnpc script, save the removal of every do_attack().

Link to comment
Share on other sites

Hm. I agree that something funny is going on, but I don't think it has to with the enemies_nearby block. I marked it up like this:

Code:
if(enemies_nearby(1) > 1){		//put_effect_on_char(ME,0,7,1);		//run_animation_sound(44);		//force_status_nearby(-1,1,2,0);		print_str("Test");		deduct_ap(1);		}	print_str("After");

And it prints:

Quote:
Test

After

Test

After

Test

After

But then the character does nothing else.

 

Something that looks like an important detail is that I checked and the return value of the maintain_dist_to_char call is 0 in these cases. This doesn't make sense since the character didn't move, but it does explain why none of the other scripted actions are carried out. So, it looks like you may need to check for this case and decide what you want to do when it happens. Since you're already tracking the character's location, it may be safer to use that then to trust maintain_dist_to_char to tell you the truth.

Link to comment
Share on other sites

Code:
beginstate 3;	if (who_hit_me() >= 0) {		set_target(ME,who_hit_me());		broadcast_char_message(8,who_hit_me(),1);		}	target = get_target();	if (target_ok() == FALSE)		set_state(START_STATE);	x = 0;	myx = my_loc_x();	myy = my_loc_y();	while(x < 120){		if(char_ok(x) == TRUE)			if(can_see_char(x) == TRUE)				if(creature_type(x) == 242)					x = 120;		x = x + 1;		}	if(x == 120){		x = 0;		while(x < 100){			y = get_ran(1,(myx - 2),(myx + 2));			z = get_ran(1,(myy - 2),(myy + 2));			if((y >= 0) && (z >= 0))				if(can_see_loc(y,z) == TRUE)					if(get_terrain(y,z) == 0)						if(char_on_loc(y,z) == FALSE)							x = 100;			x = x + 1;			}		if(x == 101){			set_character_pose(ME,1);			force_instant_terrain_redraw();			place_monster(y,z,242,1);			put_sparkles_on_space(y,z,3,3);			run_animation_sound(120);			pause(2);			set_character_pose(ME,0);			force_instant_terrain_redraw();			pause(2);			deduct_ap(2);			i = get_current_tick();			}		}	if(x == 121){		if(tick_difference(i,get_current_tick()) > 2){			x = 0;			while(x < 100){				y = get_ran(1,(myx - 2),(myx + 2));				z = get_ran(1,(myy - 2),(myy + 2));				if((y >= 0) && (z >= 0))					if(can_see_loc(y,z) == TRUE)						if(get_terrain(y,z) == 0)							if(char_on_loc(y,z) == FALSE)								x = 100;				x = x + 1;				}			if(x == 101){				set_character_pose(ME,1);				force_instant_terrain_redraw();				place_monster(y,z,242,1);				put_sparkles_on_space(y,z,3,3);				run_animation_sound(120);				pause(2);				set_character_pose(ME,0);				force_instant_terrain_redraw();				pause(2);				deduct_ap(2);				}			}		}	if((approach_char(ME,target,1) == 1) && (dist_to_char(target) == 1)){		y = char_loc_x(target);		z = char_loc_y(target);		set_character_pose(ME,1);		force_instant_terrain_redraw();		put_effect_on_char(target,11,1,2);		run_animation_sound(118);		if((char_has_trait(target,10) == TRUE) || (get_ran(1,0,99) <= 19))			damage_char(target,get_ran(8,2,4),3);			else damage_char(target,get_ran(4,2,4),3);		put_field_on_space(y,z,2);		if(get_health(target) == 0){			put_boom_on_char(target,6,0);			set_char_status(target,21,3,1,0);			alter_stat(target,31,1);			run_animation_sound(25);//25,54,65,112,118			}		pause(2);		set_character_pose(ME,0);		force_instant_terrain_redraw();		end_combat_turn();		}	if(tick_difference(i,get_current_tick()) > 2)		i = get_current_tick();break;

There is no order of operations here. For whatever reason, the script insists on doing the approach_char crap first. What's also confusing, is that it is ignoring my variables. It places the sparkles directly on the script's current target while placing the monster elsewhere, even though they both follow the same coordinates. It seems to base y and z off of the coordinates of where the current target is standing, even though I base them off of myx and myy, which are specified as my_loc_x/y() respectively. None of this makes any sense to me.

Any glaring issues here, or is this just the game behaving strangely? The reason I ask is because I've had some really weird bugs lately, like the game refusing to recognize message_dialog("","") as a call, until I copy-pasted a working "message_dialog(" over that "message_dialog(". There were no errors or minor typos - I checked it over a hundred times.
Link to comment
Share on other sites

I fixed everything by changing (char_on_loc(y,z) == FALSE) to (char_on_loc(y,z) < 0). Either char_on_loc() goes wonky when you ask for it to return a -1, or FALSE does more than I thought. I have no idea why it was screwing everything up.

 

EDIT: Oh, FALSE returns a 0. That explains everything.

Link to comment
Share on other sites

Anyone mind running a script for me? I'm having trouble narrowing down what's wrong with it, because, for the most part, it works. When my monsters kill their target, they will occasionally wander off somewhere and cease to function. Sometimes they'll blip back to life and run just part of the script before slipping back into a coma. Sometimes they will completely ignore multiple calls that tell them to stop doing what they're doing and continuously cycle through their entire script while attacking nothing but air. I really have no idea where to begin troubleshooting something like this.

 

Code:
begincreaturescript;variables;short i,num,prey,health;short stealth_mode;short i_am_hurt;body;beginstate INIT_STATE;	if (get_memory_cell(0) == 2)		set_mobility(ME,0);	num = my_number();	stealth_mode = 0;	health = get_health(num);	prey = -1;	break;beginstate DEAD_STATE;	// Set the appropriate stuff done flag for this character being dead	if ((get_memory_cell(1) != 0) || (get_memory_cell(2) != 0))		set_flag(get_memory_cell(1),get_memory_cell(2),1);break;beginstate START_STATE; 	// if I have a target for some reason, go attack it	if (target_ok()) {		if (dist_to_char(get_target()) <= 16)			set_state(3);			else set_target(ME,-1);		}		// Look for a target, attack it if visible	if (select_target(ME,8,0)) {		set_state(3);		}			// Have I been hit? Strike back!	if (who_hit_me() >= 0) {		set_target(ME,who_hit_me());		set_state(3);		}			// Otherwise, just peacefully move around. Go back to start, if I'm too far	// from where I started.	if ((my_dist_from_start() >= 6) || ((my_dist_from_start() > 0) && (get_memory_cell(0) > 0))) {		if (get_ran(1,1,100) < 40) 			return_to_start(ME,1);		}		else if (get_memory_cell(0) == 0) {			fidget(ME,25);			}	// if we're in combat and the above didn't give me anything to do, just	// stop now. Otherwise, game will keep running script, and that eats up CPU time.	if (am_i_doing_action() == FALSE)		end_combat_turn();break;beginstate 3;	if(target_ok() == FALSE){		if(stealth_mode > 0){			set_special_ability(num,0);			put_effect_on_char(num,4,3,1);			run_animation_sound(62);			stealth_mode = 0;			}		set_state(START_STATE);		}	if(get_health(num) < health)		i_am_hurt = 1;	if((i_am_hurt == 1) && (stealth_mode > 0)){		set_target(num,who_hit_me());		set_special_ability(num,0);		put_effect_on_char(num,9,1,2);		run_animation_sound(61);		print_str_color("Discovered.",2);		stealth_mode = 0;		i_am_hurt = 0;		end_combat_turn();		}	if(stealth_mode == 0){		if(flee_char(num,get_target(),3) == 0){			set_char_status(num,4,1,1,0);			}			else{				put_sparkles_on_char(num,11,5);				run_animation_sound(52);				set_special_ability(num,24);				print_str_color("Stealth.",2);				stealth_mode = 1;				set_char_status(num,4,(get_char_status(num,4) * -1),1,0);				}		}	if(stealth_mode == 1){		if(prey == -1){			i = 0;			prey = 0;			while(i < 119){				if(char_ok(i) == TRUE)					if(can_see_char(i) == TRUE)						if(char_attitude_to_char(num,i) == 2)							if(get_health(i) <= get_health(prey))								prey = i;				i = i + 1;				}			set_target(num,prey);			}		if(approach_char(num,prey,2) == 0)			set_char_status(num,4,1,1,0);			else{				if(dist_to_char(prey) <= 2){					stealth_mode = 2;					set_char_status(num,4,(get_char_status(num,4) * -1),1,0);					end_combat_turn();					}				}		}	if(stealth_mode == 2){		if(approach_char(num,prey,1) == 1){			if(dist_to_char(prey) == 1){				set_special_ability(num,0);				put_effect_on_char(num,4,3,1);				run_animation_sound(62);				pause(2);				set_character_pose(num,1);				force_instant_terrain_redraw();				put_effect_on_char(prey,5,1,2);				run_animation_sound(73);				damage_char(prey,get_ran(4,1,5),0);				damage_char(prey,get_ran(4,1,5),0);				set_char_status(prey,3,-3,0,1);				set_char_status(prey,21,3,0,1);				set_character_pose(num,0);				force_instant_terrain_redraw();				print_str_color("Sneak attack!",2);				prey = -1;				stealth_mode = 0;				}			end_combat_turn();			}		}	health = get_health(num);break;beginstate TALKING_STATE;	if (get_memory_cell(3) == 0) {		print_str("Talking: It doesn't respond.");		end();		}	begin_talk_mode(get_memory_cell(3));break;
Link to comment
Share on other sites

  • 2 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...