// BlinkGame - Hunt for the Lost Pixels
// an SDL game in honor of the BlinkenArea crew
//
// (C) 2005-06 Rene Schickbauer
//
// See License.txt for licensing information
//
#ifdef NOP_CODE
/*--------------------------------------------------------------------
					CVS AUTO-GENERATED INFO
$Author: cavac $
$Date: 2006/03/02 13:03:43 $
$Name: rel-0-3-patches $
$Revision: 1.10 $
$State: Exp $

$Log: monstersprites.cpp,v $
Revision 1.10  2006/03/02 13:03:43  cavac
Re-formatted all .cpp and .h files a bit to get rid of the TAB/SPACE mess
that makes troubles with XCode's "re-format" feature

Revision 1.9  2006/02/18 12:05:47  cavac
Try to fix a problem with solaris (untested)

Revision 1.8  2006/02/17 10:49:42  cavac
Added error-handling

Revision 1.7  2006/02/12 15:54:11  cavac
Added a new monster: The Buggy
This monster patrols a tight space except when the player is in sight

Revision 1.6  2006/02/12 15:11:22  dauti
Fixed a error with the Solaris compiler
(Error: Overloading ambiguity between "std::abs (int)" and "std::abs(long)".)
(http://groups.google.at/group/comp.unix.solaris/browse_thread/thread/e9afd7da4dde4c75/)

Revision 1.5  2006/02/10 18:56:17  cavac
Code Audit: Fixed many 64Bit based problems (mostly untested)

Revision 1.4  2006/01/18 01:22:39  cavac
Added SDL_Image to load additional graphics formats
Updated osdef* and xcode-project to to add SDL_Image
Updated all image-loader functions to use SDL_Image
Added level6 as temporary testlevel
Added code to display start- and goal-points with an animation (needs some fixing)
Removed temporary "marker"-tiles from level-definitions, as we have now an
animated display for that.

Revision 1.3  2006/01/09 00:50:34  cavac
Bugfixed CVS autogenerated entries in background.cpp
Added CVS autogenerated entries to remaining .cpp and .h files
Updated copyright from "2005 Rene Schickbauer" to "2005-06 Rene Schickbauer"


--------------------------------------------------------------------*/
#endif //NOP_CODE

#include <stdlib.h> // Try to fix problem with solaris (see also changes in version 1.6)

#include "globals.h"
#include "monstersprites.h"
#include "memops.h"
#include "levelhandler.h"
#include "colission.h"
#include "errorhandler.h"

SDL_Surface *MONSTERSPRITE_Left[MAX_MONSTER_TYPES];
SDL_Surface *MONSTERSPRITE_Right[MAX_MONSTER_TYPES];

void loadMonsterSprites() {
	char fullfname[MAX_FNAME_LENGTH];
	SDL_Surface* temp;
	
	for(Uint32 i = 0; i < MAX_MONSTER_TYPES; i++) {
		sprintf(fullfname, "%smonster%d_left.bmp", RESPATH, (i+1));
		temp = IMG_Load(fullfname);
		if(!temp) {
			DIE(ERROR_IMAGE_READ, fullfname);
		}
		MONSTERSPRITE_Left[i] = SDL_ConvertSurface(temp, gScreen->format, SDL_SWSURFACE);
		SDL_FreeSurface(temp);
		
		sprintf(fullfname, "%smonster%d_right.bmp", RESPATH, (i+1));
		temp = IMG_Load(fullfname);
		if(!temp) {
			DIE(ERROR_IMAGE_READ, fullfname);
		}
		MONSTERSPRITE_Right[i] = SDL_ConvertSurface(temp, gScreen->format, SDL_SWSURFACE);
		SDL_FreeSurface(temp);
		
	}
}


void unloadMonsterSprites() {
	for(Uint32 i = 0; i < MAX_MONSTER_TYPES; i++) {
		SDL_FreeSurface(MONSTERSPRITE_Left[i]);
		SDL_FreeSurface(MONSTERSPRITE_Right[i]);
	}
}

void addMonster(Uint32 type, Uint32 x, Uint32 y) {
	MONSTERS* tthis = (MONSTERS*)malloc(sizeof(MONSTERS));
	tthis->next = 0;
	tthis->type = type;
	tthis->startx = x;
	tthis->starty = y;
	tthis->spritenum = 0;
	if(!lhandle.monsters) {
		lhandle.monsters = tthis;
	} else {
		MONSTERS *last = lhandle.monsters;
		while(last->next) {
			last = last->next;
		}
		last->next = tthis;
	}
	lhandle.numMonsters++;	
}

void initMonsters() {
	MONSTERS* tthis = lhandle.monsters;
	while(tthis) {
		
		if(tthis->type < 3) {
			tthis->maxspeed = -0.1 * (tthis->type + 1);
			tthis->monstervx = tthis->maxspeed;
		} else if(tthis->type == 3) {
			tthis->maxspeed = 0.3;
			tthis->monstervx = tthis->maxspeed;
		} else if(tthis->type == 4) {
			tthis->maxspeed = 0.6;
			tthis->monstervx = tthis->maxspeed;
		} else {
			tthis->maxspeed = 0.3;
			tthis->monstervx = tthis->maxspeed;			
		}
		tthis->isAlive = 1;
		tthis->score = (tthis->type + 1) * 100;
		tthis->monsterx = tthis->startx;
		tthis->monstery = tthis->starty;
		tthis->mtype = MOVE_LEFT;
		tthis->newmtype = MOVE_LEFT;
		tthis->spritetick = SDL_GetTicks();
		tthis->spritenum = 0;
		tthis->isDying = false;
		tthis->dyeCount = TILESIZE;
		tthis->ai.lastTurnTick = 0;
		tthis = tthis->next;
	}
}

void freeMonsters() {
	lhandle.numMonsters = 0;
	MONSTERS* tthis;
	MONSTERS* tnext = lhandle.monsters;
	tthis = lhandle.monsters; 
	while(tnext) {
		tnext = tthis->next;
		free(tthis);
		tthis = tnext;
	}
	lhandle.monsters = 0;
}

void blitMonsterSprite(Sint32 x, Sint32 y, SDL_Surface* src, Uint32 srcoffs, Uint32 maxheight) {
	// Ignore sprites we can't display anyway
	if(maxheight <= 0) {
		return;
	}
	
	if (SDL_MUSTLOCK(src))
		if (SDL_LockSurface(src) < 0) 
			return;
	Uint32 pixel;
	
	if(x < (1 - TILESIZE) || 
	   y < (1 - TILESIZE) ||
	   x > SCR_WIDTH || 
	   y > SCR_HEIGHT) {
		return; // Tile is invisible so we ignore it
	}
	
	// Calculate offset in tiles-pixmap
	Uint32 xorigoffs = 0;
	Uint32 yorigoffs = 0;
	if(x < 0) {
		xorigoffs = -x;
	}
	if(y < 0) {
		yorigoffs = -y;
	}
	
	// Calculate HEIGHT/WIDTH of tiles to copy
	Uint32 width = TILESIZE;
	Uint32 height = TILESIZE;
	if(x > (SCR_WIDTH - TILESIZE)) {
		width = SCR_WIDTH - x;
	}
	if(y > (SCR_HEIGHT - TILESIZE)) {
		height = SCR_HEIGHT - y;
	}
	
	
	Uint32 ydieoffs = TILESIZE - maxheight;
	Uint32 scrpitch = gScreen->pitch / 4;
	Uint32 tilpitch = src->pitch / 4;
	
	for(Uint32 ybg = (yorigoffs + ydieoffs); ybg < height; ybg++) { 
		for(Uint32 xbg = xorigoffs; xbg < width; xbg++) {
			pixel = ((Uint32*)src->pixels)[xbg + (ybg - ydieoffs + srcoffs*TILESIZE) * tilpitch];
			if(pixel != 0x0000ff00) {
				((Uint32*)gScreen->pixels)[xbg + x + (y + ybg - ydieoffs) * scrpitch] = pixel;
			}
		}
	}
	
	
	// Unlock Surfaces if needed
	if (SDL_MUSTLOCK(src)) 
		SDL_UnlockSurface(src);
}

void showMonsterSprites(Uint32 screenXoffs, Uint32 screenYoffs) {
	MONSTERS* monster = lhandle.monsters;
	SDL_Surface* sprite = 0;
	Uint32 spritetick = SDL_GetTicks();
	Sint32 scr_x;
	Sint32 scr_y;
	while(monster) {
		if(!monster->isAlive && !monster->isDying) {
			monster = monster->next;
			continue;
		}
		switch (monster->newmtype) {
			case MOVE_LEFT:
				sprite = MONSTERSPRITE_Left[monster->type];
				break;
			case MOVE_RIGHT:
				sprite = MONSTERSPRITE_Right[monster->type];
				break;
			case JUMP_LEFT:
				break;
			case JUMP_RIGHT:
				break;
			default:
				break;
		}
		if(monster->mtype != monster->newmtype) {
			monster->spritenum = 0;
		} else {
			if(monster->spritetick < spritetick) {
				monster->spritetick = spritetick + SPRITE_SWITCHWAIT;
				if(monster->isDying) {
					monster->dyeCount -= MONSTER_DIESPEED;
					if(monster->dyeCount <= 0) {
						monster->isDying = false;
						continue;
					}
				} else {
					monster->spritenum++;
					if(monster->spritenum >= (Uint32)(sprite->h / TILESIZE)) {
						monster->spritenum = 0;
					}
				}
			}
		}
		
		scr_x = (Uint32)monster->monsterx - screenXoffs; 
		scr_y = (Uint32)monster->monstery - screenYoffs;
		if(monster->isDying) {
			scr_y += TILESIZE - monster->dyeCount;
		}
		
		if(scr_x > -TILESIZE && scr_x < SCR_WIDTH && scr_y > -TILESIZE && scr_y < SCR_HEIGHT) {
			//printf("sn: %d\n", monster->spritenum);
			blitMonsterSprite(scr_x, scr_y, sprite, monster->spritenum, monster->dyeCount);	
		}
		
		monster->mtype = monster->newmtype;
		monster = monster->next;
	}	
}

void monsterPhysics(Uint32 playerx, Uint32 playery) {
	Uint32 monstertick = SDL_GetTicks();
	MONSTERS* monster = lhandle.monsters;
	while(monster) {
		if(monster->isAlive) {
			// Look ahead to the next floor tile in our direction and change direction if it's missing
			double alignedx = ((Uint32)(monster->monsterx / TILESIZE)) * TILESIZE;
			double alignedy = ((Uint32)(monster->monstery / TILESIZE)) * TILESIZE;
			
			// Eye-monster can try to switch to player direction when it "sees" it e.g. Player is at about same Y coords as monster
			if(monster->type == 3) {
				if(abs((Uint32)(monster->monstery - playery)) < (TILESIZE * 2) && abs((Uint32)(monster->monsterx - playerx)) < (TILESIZE * 10)) {
					if(playerx < monster->monsterx) {
						monster->monstervx = -monster->maxspeed;
						monster->ai.lastTurnTick = monstertick;
					} else {
						monster->monstervx = monster->maxspeed;
						monster->ai.lastTurnTick = monstertick;
					}
				}
			// Buggy monster patrols a small place, except when it sees the player
			} else if(monster->type == 4) {
				// Player in sight?
				if(abs((Uint32)(monster->monstery - playery)) < (TILESIZE * 3) && abs((Uint32)(monster->monsterx - playerx)) < (TILESIZE * 3)) {
					if(playerx < monster->monsterx) {
						monster->monstervx = -monster->maxspeed;
						monster->ai.lastTurnTick = monstertick;
					} else {
						monster->monstervx = monster->maxspeed;
						monster->ai.lastTurnTick = monstertick;
					}
				} else if(monstertick > (monster->ai.lastTurnTick + 1000)) {
					// Need to do a turn
					monster->monstervx = -monster->monstervx;
					monster->monsterx += monster->monstervx;
					monster->ai.lastTurnTick = monstertick;
				}
			}
			
			
			
			// Check crossing of tile-end to the left
			if(monster->monstervx < 0 && (monster->monsterx + monster->monstervx) < alignedx &&
			   !checkForTile((Uint32)alignedx - TILESIZE, (Uint32)alignedy + TILESIZE)) {
				monster->monstervx = -monster->monstervx;
				monster->ai.lastTurnTick = monstertick;
			}
			
			// Check crossing of tile-end to the right
			if(monster->monstervx > 0 && (monster->monsterx + monster->monstervx) > (alignedx + (double)TILESIZE) &&
			   !checkForTile((Uint32)alignedx + TILESIZE*2, (Uint32)alignedy + TILESIZE)) {
				monster->monstervx = -monster->monstervx;
				monster->ai.lastTurnTick = monstertick;
			}
			
			
			monster->monsterx += monster->monstervx;
			Uint32 col = getTilesMonsterColission(monster);
			if(col) {
				monster->monstervx = -monster->monstervx;
				monster->monsterx += monster->monstervx;
				monster->ai.lastTurnTick = monstertick;
			}
			
			if(monster->monstervx > 0) {
				monster->newmtype = MOVE_RIGHT;
			} else {
				monster->newmtype = MOVE_LEFT;
			}
		}
		monster = monster->next;
	}
}
