/* Copyright (C) 1995-2002  FSGames. Ported by Sean Ford and Yan Shosh
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
//
// treasure; a derived class of walker
//

//#include "graph.h"
#include <math.h>
#include "obmap.h"
#include "loader.h"
#include "screen.h"
#include "treasure.h"
#include "text.h"
#include "stats.h"
#include "guy.h"

// Zardus: this is the func to get events
void get_input_events(bool);

// Zardus: from video.cpp for retreat crash ugly hack fix
extern bool retreat;

treasure::treasure(unsigned char  *data, screen  *myscreen) : walker(data, myscreen)
{
	ignore =(char) 0;
	dead =  (char) 0;
}

treasure::~treasure()
{
	//bufffers: PORT: cannot call destructor w/o obj: walker::~walker();
}

short treasure::act()
{
	// Abort all later code for now ..
	return 1;
}

short treasure::eat_me(walker  * eater)
{
	short guys_here;
	oblink *here;
	static text eattext(screenp);
	char message[80];
	char * eatkeys;
	long distance;
	walker  *target, *flash;
	static char exitname[40];
	long leftside, rightside;

	switch (family)
	{
		case FAMILY_DRUMSTICK:
			if (eater->stats->hitpoints >= eater->stats->max_hitpoints)
				return 1;
			else
			{
				eater->stats->hitpoints += (short) ((10*stats->level) + (short) random((short) 10*stats->level));
				if (eater->stats->hitpoints > eater->stats->max_hitpoints)
					eater->stats->hitpoints = eater->stats->max_hitpoints;
				dead = 1;
				if (on_screen())
					screenp->soundp->play_sound(SOUND_EAT);
				return 1;
			}
		case FAMILY_GOLD_BAR:
			if (eater->team_num == 0 || eater->myguy)
			{
				myscreen->m_score[eater->team_num] += (200*stats->level);
				dead = 1;
				if (on_screen())
					screenp->soundp->play_sound(SOUND_MONEY);
			}
			return 1;
		case FAMILY_SILVER_BAR:
			if (eater->team_num == 0 || eater->myguy)
			{
				myscreen->m_score[eater->team_num] += (50*stats->level);
				dead = 1;
				if (on_screen())
					screenp->soundp->play_sound(SOUND_MONEY);
			}
			return 1;
		case FAMILY_FLIGHT_POTION:
			if (!eater->stats->query_bit_flags(BIT_FLYING) )
			{
				eater->flight_left += (150*stats->level);
				if (eater->user != -1)
				{
					sprintf(message, "Potion of Flight(%d)!", stats->level);
					screenp->do_notify(message, eater);
				}
				dead = 1;
			}
			return 1;
		case FAMILY_MAGIC_POTION:
			if (eater->stats->magicpoints < eater->stats->max_magicpoints)
				eater->stats->magicpoints = eater->stats->max_magicpoints;
			eater->stats->magicpoints += (50*stats->level);
			dead = 1;
			if (eater->user != -1)
			{
				sprintf(message, "Potion of Mana(%d)!", stats->level);
				screenp->do_notify(message, eater);
			}
			return 1;
		case FAMILY_INVULNERABLE_POTION:
			if (!eater->stats->query_bit_flags(BIT_INVINCIBLE) )
			{
				eater->invulnerable_left += (150*stats->level);
				dead = 1;
				if (eater->user != -1)
				{
					sprintf(message, "Potion of Invulnerability(%d)!", stats->level);
					screenp->do_notify(message, eater);
				}
			}
			return 1;
		case FAMILY_INVIS_POTION:
			eater->invisibility_left += (150*stats->level);
			if (eater->user != -1)
			{
				sprintf(message, "Potion of Invisibility(%d)!", stats->level);
				screenp->do_notify(message, eater);
			}
			dead = 1;
			return 1;
		case FAMILY_SPEED_POTION:
			eater->speed_bonus_left += 50*stats->level;
			eater->speed_bonus = stats->level;
			if (eater->user != -1)
			{
				sprintf(message, "Potion of Speed(%d)!", stats->level);
				screenp->do_notify(message, eater);
			}
			dead = 1;
			return 1;
		case FAMILY_EXIT: // go to another level, possibly
			if (eater->in_act) return 1;
			if (eater->query_act_type()!= ACT_CONTROL || (eater->skip_exit > 1))
				return 1;
			eater->skip_exit = 10;
			// See if there are any enemies left ...
			if (screenp->level_done == 0)
				guys_here = 1;
			else
				guys_here = 0;
			// Get the name of our exit..
			sprintf(message, "scen%d", stats->level);
			strcpy(exitname, myscreen->get_scen_title(message, myscreen) );

			//buffers: PORT: using strcmp instead of stricmp
			if (!strcmp(exitname, "none"))
				sprintf(exitname, "Level %d", stats->level);

			leftside  = 160 - ( (strlen(exitname) + 18) * 3);
			rightside = 160 + ( (strlen(exitname) + 18) * 3);
			// First check to see if we're withdrawing into
			//    somewhere we've been, in which case we abort
			//    this level, and set our current level to
			//    that pointed to by the exit ...
			if ( (screenp->levelstatus[stats->level] == 1)
			        && (screenp->levelstatus[screenp->scen_num] == 0)
			        && (guys_here != 0)
			   ) // okay to leave
			{
				leftside -= 12;
				rightside += 12;
				screenp->draw_dialog(leftside, 20, rightside, 54, "Exit Field");
				sprintf(message, "Withdraw to %s? (Y/N)", exitname);
				eattext.write_y(42, message, DARK_BLUE, 1);
				screenp->buffer_to_screen(0, 0, 320, 200);
				eatkeys = query_keyboard();
				clear_keyboard();
				while (!eatkeys[SDLK_KP_MULTIPLY] && !eatkeys[SDLK_ESCAPE])
					get_input_events(WAIT);
				// Redraw screen ..
				screenp->redrawme = 1;

				if (eatkeys[SDLK_KP_MULTIPLY]) // accepted level change
				{
					clear_keyboard();
					screenp->levelstatus[screenp->scen_num] = 0;  // NOT done
					// Delete all of our current information and abort ..
					here = myscreen->oblist;
					while (here)
					{
						if (here->ob && here->ob->query_order() == ORDER_LIVING)
						{
							//myscreen->remove_ob(here->ob);
							here->ob->dead = 1;
							myscreen->myobmap->remove
							(here->ob);
							//myscreen->remove_obmap(here->ob);
						}
						here = here->next;
					}
					//here = myscreen->fxlist;
					//while (here)
					//{
					//  if (here->ob)
					//    myscreen->remove_fx_ob(here->ob);
					//  here = here->next;
					//}
					// Now load the game as it was ...
					load_saved_game("save0", myscreen);
					myscreen->scen_num = (short) (stats->level-1);
					myscreen->end = 1;
					save_game("save0", myscreen);
					retreat = 1;

					return screenp->endgame(1, stats->level); // retreat
				}  // end of accepted withdraw to new level ..
				clear_keyboard();
			} // end of checking for withdrawal to completed level

			if (!guys_here) // nobody evil left, so okay to exit level ..
			{
				screenp->draw_dialog(30, 20, 290, 54, "Exit Field");
				sprintf(message, "Exit to %s? (Y/N)", exitname);
				eattext.write_y(42, message, DARK_BLUE, 1);
				screenp->buffer_to_screen(0, 0, 320, 200);
				eatkeys = query_keyboard();
				clear_keyboard();
				// Zardus: FIX: get_input_events instead of freezing and counting :-)
				while (!eatkeys[SDLK_KP_MULTIPLY] && !eatkeys[SDLK_ESCAPE])
					get_input_events(WAIT);
				// Redraw screen ..
				screenp->redrawme = 1;

				if (eatkeys[SDLK_KP_MULTIPLY]) // accepted level change
				{
					clear_keyboard();
					//screenp->levelstatus[screenp->scen_num] = 1;
					return screenp->endgame(0, stats->level);
				}
				clear_keyboard();
				return 1;
			}
			return 1;
		case FAMILY_TELEPORTER:
			if (eater->skip_exit > 1)
				return 1;
			distance = distance_to_ob_center(eater); // how  away?
			if (distance > 21)
				return 1;
			if (distance < 4 && eater->skip_exit)
			{
				//eater->skip_exit++;
				eater->skip_exit = 8;
				return 1;
			}
			// If we're close enough, teleport ..
			eater->skip_exit += 20;
			if (!leader)
				target = find_teleport_target();
			else
				target = leader;
			if (!target)
				return 1;
			leader = target;
			eater->center_on(target);
			if (!screenp->query_passable(eater->xpos, eater->ypos, eater))
			{
				eater->center_on(this);
				return 1;
			}
			// Now do special effects
			flash = screenp->add_ob(ORDER_FX, FAMILY_FLASH);
			flash->ani_type = ANI_EXPAND_8;
			flash->center_on(this);
			return 1;
		case FAMILY_LIFE_GEM: // get back some of lost man's xp ..
			if (eater->team_num != team_num) // only our team can get these
				return 1;
			myscreen->m_score[eater->team_num] += stats->hitpoints;
			flash = screenp->add_ob(ORDER_FX, FAMILY_FLASH);
			flash->ani_type = ANI_EXPAND_8;
			flash->center_on(this);
			dead = 1;
			death();
			return 1;
		case FAMILY_KEY: // get the key to this door ..
			if (!(eater->keys & (long)(pow((double) 2, stats->level)) )) // just got it?
			{
				eater->keys |= (long) (pow((double)2, stats->level)); // ie, 2, 4, 8, 16...
				if (eater->myguy)
					sprintf(message, "%s picks up key %d", eater->myguy->name,
					        stats->level);
				else
					sprintf(message, "%s picks up key %d", eater->stats->name, stats->level);
				if (eater->team_num == 0) // only show players picking up keys
				{
					myscreen->do_notify(message, eater);
					if (eater->on_screen())
						myscreen->soundp->play_sound(SOUND_MONEY);
				}
			}
			return 1;
		default:
			return 1;
	} // end of treasure-check
}

void treasure::set_direct_frame(short whatframe)
{
	unsigned char  * data;
	frame = whatframe;

	data = screenp->myloader->graphics[PIX(order, family)];
	bmp = (unsigned char  *) (data+3 + frame*size);

}

walker  * treasure::find_teleport_target()
{
	walker  *target = NULL;
	oblink  *here = screenp->fxlist;
	short keep_looking = 1;
	short number = 0;

	// First find where we are in the list ...
	while (here && keep_looking)
	{
		if (here->ob && here->ob == this) // found us
			keep_looking = 0;
		else
		{
			here = here->next;
			number++;
		}
	}

	if (keep_looking) // didn't find us?
		return NULL;

	//printf("Teleporting from #%d ..", number);

	// Now search the rest of the loop ..
	keep_looking = 1;
	here = here->next;
	number++;
	while (here && keep_looking)
	{
		if (here->ob && !here->ob->dead)
		{
			if (here->ob->query_order() == ORDER_TREASURE &&
			        here->ob->query_family() == FAMILY_TELEPORTER &&
			        here->ob->stats->level == stats->level)
			{
				target = here->ob;
				keep_looking = 0;
				//printf(" to target %d\n", number);
				return target;
			}
		}
		here = here->next;
		number++;
	}

	// Hit the end of the list, look from top down now ..
	here = screenp->fxlist;
	number = 0;
	while (here)
	{
		if (here->ob && !here->ob->dead)
		{
			if (here->ob->query_order() == ORDER_TREASURE &&
			        here->ob->query_family() == FAMILY_TELEPORTER &&
			        here->ob->stats->level == stats->level)
			{
				target = here->ob;
				//printf(" to looped target %d\n", number);
				return target;
			}
		}
		here = here->next;
		number++;
	}

	return target;
}

