// Field Shooter v1.0.1
// fieldshooter.txt
// by Kelandon (tomwatts@berkeley.edu)
//
// Much like basicnpc, but in combat, it shoots fields at its enemies sometimes.
// Also, to save memory cells, this creature optionally calls a town state when
// it dies, rather than just setting a flag.
//
// In this version, the creature's default strategy is that of an archer.
//
// Memory Cells:
//	Cell 0 - How creature moves.
//     0 - If 0, wander randomly. 
//     1 - Stands still until a target appears.
//     2 - Completely immobile, even if target appears.
//	Cell 1 - Which town state to call when dying. If left at 0, none.
//	Cell 2 - Dialogue node to start with if talked to. if left at 0, this
//     character doesn't talk.
//	Cell 3 - What kind of field to shoot.
//		From the docs, field choices are:
//		0 - sleep cloud
//		1 - fire wall
//		2 - antimagic
//		3 - stinking cloud
//		4 - ice wall
//		5 - blade wall
//		6 - quickfire
//	Cell 4 - What color zap to use when shooting a field. If -1, no zap.
//		From the docs, color choices are:
//		0 - fire ray
//		1 - ice ray
//		2 - death ray
//		3 - green ray
//		4 - white ray
//		5 - black ray
//		6 - blue ray
//	Cell 5 - What sound to make when zapping. If left at 0, defaults to 54
//		(lightning).
//	Cell 6 - What sort of targeting algorithm to use. 
//		0 - normal select_target.
//		1 - also select_target, but won't shoot if there's already a field on
//		that space.
//		2 - finds the best spellcaster and targets it. Also will not target a
//		character who already has a field. Useful for targeting anti-magic 
//		fields. Much of this AI was "borrowed" from magekiller by Stareye and
//		Walker White.
//	Cell 7 - How many turns to elapse before acquiring new targets. (So if this
//		is 0, the creature gets new targets every turn.)
//	Cell 8 - What sort of AI for shooting fields to use. 
//		0 - randomization.
//		1 - requires a minimum amount of spellcasting power.
//	Cell 9 - A number to define the AI selected in the previous cell.
//		If cell 8 is 0, it is the chance that the creature will shoot a field
//		(so a value of 5 means that the creature will shoot a field 1/5 of the
//		time it attacks). If left at 0, defaults to 4.

begincreaturescript;

variables;

short i,j,target,shoot_field,highest,strength;
short func_return = 0;

body;

beginstate INIT_STATE;
	// Set memory cells to reasonable values.
	if ((get_memory_cell(8) == 0) && (get_memory_cell(9) == 0))
		set_memory_cell(9,4);
	if (get_memory_cell(5) == 0)
		set_memory_cell(5,54);
		
	if (get_memory_cell(0) == 2)
		set_mobility(ME,0);
		
	set_strategy(my_number(),1);
break;

beginstate DEAD_STATE;
	// Call a town state.
	if (get_memory_cell(1) > 0)
		run_town_script(get_memory_cell(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)) {
		do_attack();
		set_state(3);
		}
		
	// Have I been hit? Strike back!
	if (who_hit_me() >= 0) {
		set_target(ME,who_hit_me());
		do_attack();
		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; // attacking
	// If this is the beginning of the combat turn, go to the targeting state.
	if (func_return == 0) {
		shoot_field = 1;
		set_state_continue(4);
		}
	func_return = 0;
	
	// If the creature can't see the target, don't shoot.
	if (can_see_char(get_target()) == 0)
		shoot_field = 0;
	
	// If the creature is supposed to shoot a field, do it.
	if (shoot_field)
		if (get_memory_cell(4) >= 0) {
			put_straight_zap(my_loc_x(),my_loc_y(),char_loc_x(get_target()),char_loc_y(get_target()),get_memory_cell(4));
			put_field_on_space(char_loc_x(get_target()) - 1,char_loc_y(get_target()) - 1,get_memory_cell(3));
			put_field_on_space(char_loc_x(get_target()),char_loc_y(get_target()) - 1,get_memory_cell(3));
			put_field_on_space(char_loc_x(get_target()) + 1,char_loc_y(get_target()) - 1,get_memory_cell(3));
			put_field_on_space(char_loc_x(get_target()) - 1,char_loc_y(get_target()),get_memory_cell(3));
			put_field_on_space(char_loc_x(get_target()),char_loc_y(get_target()),get_memory_cell(3));
			put_field_on_space(char_loc_x(get_target()) + 1,char_loc_y(get_target()),get_memory_cell(3));
			put_field_on_space(char_loc_x(get_target()) - 1,char_loc_y(get_target()) + 1,get_memory_cell(3));
			put_field_on_space(char_loc_x(get_target()),char_loc_y(get_target()) + 1,get_memory_cell(3));
			put_field_on_space(char_loc_x(get_target()) + 1,char_loc_y(get_target()) + 1,get_memory_cell(3));
			run_animation_sound(get_memory_cell(5));
			print_named_str(ME,"shoots a magical field!");
			end_combat_turn();
			}
	// Otherwise, attack.
	do_attack();
break;

beginstate 4; // targeting
	func_return = 1;
	if (get_memory_cell(6) <= 1)
		select_target(ME,8,0);
	if (get_memory_cell(6) == 1)
		if (is_field_on_space(char_loc_x(get_target()),char_loc_y(get_target()),get_memory_cell(3)) == 1)
			shoot_field = 0;
	if (get_memory_cell(6) == 2) {
		highest = 0;
		j = 0;
		i = 150;
		while (j < 120) {
			if ((can_see_char(j) == TRUE) && (char_attitude_to_char(ME,j) == 2)) {
				// Assessment metric "borrowed" and adapted from magekiller by
				// *i and Walker White.
				strength = ((get_stat(j,11) + get_stat(j,12) + get_stat(j,2) + get_stat(j,25)) * (get_stat(j,11) + get_stat(j,12))) * (get_energy(j) / 10);
				if ((strength > highest) && (is_field_on_space(char_loc_x(get_target()),char_loc_y(get_target()),get_memory_cell(3)) == 0)) {
					highest = strength;
					i = j;
					}
				}
			j = j + 1;
			}
		if (i != 150)
			set_target(ME,i);
		}
	
	// If that left us with a target, figure out whether to shoot. Otherwise
	// leave combat and try something new.
	if (target_ok() == 0)
		set_state_continue(START_STATE);
	else
		set_state_continue(5);
break;

beginstate 5; // To shoot or not to shoot, that is the question...
	if (get_memory_cell(8) == 0)
		if (get_ran(1,1,get_memory_cell(9)) != 1)
			shoot_field = 0;
	set_state_continue(3);
break;

beginstate TALKING_STATE;
	if (get_memory_cell(2) == 0) {
		print_str("Talking: It doesn't respond.");
		end();
		}
	begin_talk_mode(get_memory_cell(3));
break;