<commit_before>/*
 * This software is licensed under the terms of the MIT-License
 * See COPYING for further information. 
 * ---
 * Copyright (C) 2011, <NAME> <<EMAIL>>
 */

#include "player.h"

#include <SDL/SDL.h>
#include "projectile.h"
#include "global.h"
#include "plrmodes.h"
#include "menu/gameovermenu.h"

void init_player(Player* plr) {
	memset(plr, 0, sizeof(Player));
	
	plr->pos = VIEWPORT_W/2 + I*(VIEWPORT_H-20);
		
	plr->lifes = PLR_START_LIVES;
	plr->bombs = PLR_START_BOMBS;
		
	plr->deathtime = -1;
	plr->continues = 0;
}

Animation *player_get_ani(Character cha) {
	Animation *ani;
	switch(cha) {
	case Youmu:
		ani = get_ani("youmu");
		break;
	case Marisa:
		ani = get_ani("marisa");
		break;
	}
	
	return ani;
}

void player_set_power(Player *plr, float npow) {
	switch(plr->cha) {
		case Youmu:
			youmu_power(plr, npow);
			break;
		case Marisa:
			marisa_power(plr, npow);
			break;
	}
	
	plr->power = npow;
	
	if(plr->power > PLR_MAXPOWER)
		plr->power = PLR_MAXPOWER;
	
	if(plr->power < 0)
		plr->power = 0;
}

void player_move(Player *plr, complex delta) {
	float speed = 0.01*VIEWPORT_W/((plr->focus > 0)+1);
	
	if(plr->cha == Marisa && plr->shot == MarisaLaser && global.frames - plr->recovery < 0)
		speed /= 5.0;
	
	complex opos = plr->pos - VIEWPORT_W/2.0 - VIEWPORT_H/2.0*I;
	complex npos = opos + delta*speed;
	
	Animation *ani = player_get_ani(plr->cha);
	
	short xfac = fabs(creal(npos)) < fabs(creal(opos)) || fabs(creal(npos)) < VIEWPORT_W/2.0 - ani->w/2;
	short yfac = fabs(cimag(npos)) < fabs(cimag(opos)) || fabs(cimag(npos)) < VIEWPORT_H/2.0 - ani->h/2;
		
	plr->pos += (creal(delta)*xfac + cimag(delta)*yfac*I)*speed;
}
	
void player_draw(Player* plr) {
	draw_enemies(plr->slaves);
	
	glPushMatrix();
		glTranslatef(creal(plr->pos), cimag(plr->pos), 0);
		
		if(plr->focus != 0) {
			glPushMatrix();
				glRotatef(global.frames*10, 0, 0, 1);
				glScalef(1, 1, 1);
				glColor4f(1,1,1,0.2);
				draw_texture(0, 0, "fairy_circle");
				glColor4f(1,1,1,1);
			glPopMatrix();
		}
					
		glDisable(GL_CULL_FACE);
		if(plr->dir) {
			glPushMatrix();
			glScalef(-1,1,1);
		}
		
		int clr_changed = 0;
		
		if(global.frames - abs(plr->recovery) < 0 && (global.frames/8)&1) {
			glColor4f(0.4,0.4,1,0.9);
			clr_changed = 1;
		}
				
		draw_animation_p(0, 0, !plr->moving, player_get_ani(plr->cha));
		
		if(clr_changed)
			glColor3f(1,1,1);
		
		if(plr->dir)
			glPopMatrix();
		
		glEnable(GL_CULL_FACE);
		
		if(plr->focus != 0) {
			glPushMatrix();
				glColor4f(1,1,1,fabs((float)plr->focus/30.0f));
				glRotatef(global.frames, 0, 0, -1);
				draw_texture(0, 0, "focus");
				glColor4f(1,1,1,1);
			glPopMatrix();
		}
		
	glPopMatrix();
}

void player_logic(Player* plr) {
	process_enemies(&plr->slaves);
	if(plr->deathtime < -1) {
		plr->deathtime++;
		plr->pos -= 0.7I;
		return;
	}
		
	if(plr->focus < 0 || (plr->focus > 0 && plr->focus < 30))
		plr->focus++;
	
		
	switch(plr->cha) {
	case Youmu:
		youmu_shot(plr);
		break;
	case Marisa:
		marisa_shot(plr);
		break;
	}

	
	if(global.frames == plr->deathtime)
		player_realdeath(plr);
	
	if(global.frames - plr->recovery < 0) {
		Enemy *en;
		for(en = global.enemies; en; en = en->next)
			if(!en->unbombable)
				en->hp -= 300;
		
		Projectile *p;
		for(p = global.projs; p; p = p->next)
			if(p->type >= FairyProj)
				p->type = DeadProj;
			
		if(global.boss && global.boss->current) {
			AttackType at = global.boss->current->type;
			if(at != AT_Move && at != AT_SurvivalSpell)
				global.boss->dmg += 30;
		}
	}
}

void player_bomb(Player *plr) {
	if(global.frames - plr->recovery >= 0 && plr->bombs > 0) {
		
		delete_projectiles(&global.projs);
				
		switch(plr->cha) {
		case Marisa:
			marisa_bomb(plr);
			break;
		case Youmu:
			youmu_bomb(plr);
			break;
		}
		
		plr->bombs--;
		
		if(plr->deathtime > 0) {
			plr->deathtime = -1;
			plr->bombs /= 2;
		}			
		
		plr->recovery = global.frames + BOMB_RECOVERY;
	}
}

void player_realdeath(Player *plr) {
	plr->deathtime = -DEATH_DELAY-1;
	
	plr->moveflags = 0;
		
	create_item(plr->pos, 6-15*I, Power);
	create_item(plr->pos, -6-15*I, Power);
	
	plr->pos = VIEWPORT_W/2 + VIEWPORT_H*I+30I;
	plr->recovery = -(global.frames + DEATH_DELAY + 150);

	if(plr->bombs < PLR_START_BOMBS)
		plr->bombs = PLR_START_BOMBS;
	
	if(plr->lifes-- == 0 && global.replaymode != REPLAY_PLAY)
		global.menu = create_gameover_menu();
}

void player_death(Player *plr) {
	if(plr->deathtime == -1 && global.frames - abs(plr->recovery) > 0) {
		int i;
		for(i = 0; i < 20; i++) {
			tsrand_fill(2);
			create_particle2c("flare", plr->pos, NULL, Shrink, timeout_linear, 40, (3+afrand(0)*7)*cexp(I*tsrand_a(1)));
		}
		create_particle2c("blast", plr->pos, rgb(1,0.5,0.3), GrowFade, timeout, 35, 2.4);
		plr->deathtime = global.frames + DEATHBOMB_TIME;
	}
}

void player_setmoveflag(Player* plr, int key, int mode) {
	int flag = 0;
	
	switch(key) {
		case KEY_UP:	flag = MOVEFLAG_UP; 	break;
		case KEY_DOWN:	flag = MOVEFLAG_DOWN;	break;
		case KEY_LEFT:	flag = MOVEFLAG_LEFT;	break;
		case KEY_RIGHT:	flag = MOVEFLAG_RIGHT;	break;
	}
	
	if(!flag)
		return;
	
	if(mode)
		plr->moveflags |= flag;
	else
		plr->moveflags &= ~flag;
}

void player_event(Player* plr, int type, int key) {
	switch(type) {
		case EV_PRESS:
			switch(key) {
				case KEY_FOCUS:
					plr->focus = 1;
					break;
				
				case KEY_SHOT:
					plr->fire = True;
					break;
				
				case KEY_BOMB:
					player_bomb(plr);
					break;
				
				default:
					player_setmoveflag(plr, key, True);
					break;
			}
			break;
		
		case EV_RELEASE:
			switch(key) {
				case KEY_FOCUS:
					plr->focus = -30;  // that's for the transparency timer
					break;
				
				case KEY_SHOT:
					plr->fire = False;
					break;
				
				default:
					player_setmoveflag(plr, key, False);
					break;
			}
			
			break;
	}
}

void player_applymovement(Player* plr) {
	if(plr->deathtime < -1)
		return;
	
	plr->moving = False;
	
	int up		=	plr->moveflags & MOVEFLAG_UP,
		down	=	plr->moveflags & MOVEFLAG_DOWN,
		left	=	plr->moveflags & MOVEFLAG_LEFT,
		right	=	plr->moveflags & MOVEFLAG_RIGHT;
	
	if(left && !right) {
		plr->moving = True;
		plr->dir = 1;
	} else if(right && !left) {
		plr->moving = True;
		plr->dir = 0;
	}	
	
	complex direction = 0;
	
	if(up)		direction -= 1I;
	if(down)	direction += 1I;
	if(left)	direction -= 1;
	if(right)	direction += 1;
		
	if(cabs(direction))
		direction /= cabs(direction);
	
	if(direction)
		player_move(&global.plr, direction);
	
	// workaround
	if(global.replaymode == REPLAY_RECORD) {
		Uint8 *keys = SDL_GetKeyState(NULL);
		
		if(!keys[tconfig.intval[KEY_SHOT]] && plr->fire) {
			player_event(plr, EV_RELEASE, KEY_SHOT);
			replay_event(&global.replay, EV_RELEASE, KEY_SHOT);
		}
		
		if(!keys[tconfig.intval[KEY_FOCUS]] && plr->focus > 0) {
			player_event(plr, EV_RELEASE, KEY_FOCUS);
			replay_event(&global.replay, EV_RELEASE, KEY_FOCUS);
		}
	}
}
<commit_msg>fixed immortal elly<commit_after>/*
 * This software is licensed under the terms of the MIT-License
 * See COPYING for further information. 
 * ---
 * Copyright (C) 2011, <NAME> <<EMAIL>>
 */

#include "player.h"

#include <SDL/SDL.h>
#include "projectile.h"
#include "global.h"
#include "plrmodes.h"
#include "menu/gameovermenu.h"

void init_player(Player* plr) {
	memset(plr, 0, sizeof(Player));
	
	plr->pos = VIEWPORT_W/2 + I*(VIEWPORT_H-20);
		
	plr->lifes = PLR_START_LIVES;
	plr->bombs = PLR_START_BOMBS;
		
	plr->deathtime = -1;
	plr->continues = 0;
}

Animation *player_get_ani(Character cha) {
	Animation *ani;
	switch(cha) {
	case Youmu:
		ani = get_ani("youmu");
		break;
	case Marisa:
		ani = get_ani("marisa");
		break;
	}
	
	return ani;
}

void player_set_power(Player *plr, float npow) {
	switch(plr->cha) {
		case Youmu:
			youmu_power(plr, npow);
			break;
		case Marisa:
			marisa_power(plr, npow);
			break;
	}
	
	plr->power = npow;
	
	if(plr->power > PLR_MAXPOWER)
		plr->power = PLR_MAXPOWER;
	
	if(plr->power < 0)
		plr->power = 0;
}

void player_move(Player *plr, complex delta) {
	float speed = 0.01*VIEWPORT_W/((plr->focus > 0)+1);
	
	if(plr->cha == Marisa && plr->shot == MarisaLaser && global.frames - plr->recovery < 0)
		speed /= 5.0;
	
	complex opos = plr->pos - VIEWPORT_W/2.0 - VIEWPORT_H/2.0*I;
	complex npos = opos + delta*speed;
	
	Animation *ani = player_get_ani(plr->cha);
	
	short xfac = fabs(creal(npos)) < fabs(creal(opos)) || fabs(creal(npos)) < VIEWPORT_W/2.0 - ani->w/2;
	short yfac = fabs(cimag(npos)) < fabs(cimag(opos)) || fabs(cimag(npos)) < VIEWPORT_H/2.0 - ani->h/2;
		
	plr->pos += (creal(delta)*xfac + cimag(delta)*yfac*I)*speed;
}
	
void player_draw(Player* plr) {
	draw_enemies(plr->slaves);
	
	glPushMatrix();
		glTranslatef(creal(plr->pos), cimag(plr->pos), 0);
		
		if(plr->focus != 0) {
			glPushMatrix();
				glRotatef(global.frames*10, 0, 0, 1);
				glScalef(1, 1, 1);
				glColor4f(1,1,1,0.2);
				draw_texture(0, 0, "fairy_circle");
				glColor4f(1,1,1,1);
			glPopMatrix();
		}
					
		glDisable(GL_CULL_FACE);
		if(plr->dir) {
			glPushMatrix();
			glScalef(-1,1,1);
		}
		
		int clr_changed = 0;
		
		if(global.frames - abs(plr->recovery) < 0 && (global.frames/8)&1) {
			glColor4f(0.4,0.4,1,0.9);
			clr_changed = 1;
		}
				
		draw_animation_p(0, 0, !plr->moving, player_get_ani(plr->cha));
		
		if(clr_changed)
			glColor3f(1,1,1);
		
		if(plr->dir)
			glPopMatrix();
		
		glEnable(GL_CULL_FACE);
		
		if(plr->focus != 0) {
			glPushMatrix();
				glColor4f(1,1,1,fabs((float)plr->focus/30.0f));
				glRotatef(global.frames, 0, 0, -1);
				draw_texture(0, 0, "focus");
				glColor4f(1,1,1,1);
			glPopMatrix();
		}
		
	glPopMatrix();
}

void player_logic(Player* plr) {
	process_enemies(&plr->slaves);
	if(plr->deathtime < -1) {
		plr->deathtime++;
		plr->pos -= 0.7I;
		return;
	}

	if(plr->focus < 0 || (plr->focus > 0 && plr->focus < 30))
		plr->focus++;


	switch(plr->cha) {
	case Youmu:
		youmu_shot(plr);
		break;
	case Marisa:
		marisa_shot(plr);
		break;
	}


	if(global.frames == plr->deathtime)
		player_realdeath(plr);

	if(global.frames - plr->recovery < 0) {
		Enemy *en;
		for(en = global.enemies; en; en = en->next)
			if(!en->unbombable && en->hp > ENEMY_IMMUNE)
				en->hp -= 300;

		Projectile *p;
		for(p = global.projs; p; p = p->next)
			if(p->type >= FairyProj)
				p->type = DeadProj;

		if(global.boss && global.boss->current) {
			AttackType at = global.boss->current->type;
			if(at != AT_Move && at != AT_SurvivalSpell)
				global.boss->dmg += 30;
		}
	}
}

void player_bomb(Player *plr) {
	if(global.frames - plr->recovery >= 0 && plr->bombs > 0) {
		
		delete_projectiles(&global.projs);
				
		switch(plr->cha) {
		case Marisa:
			marisa_bomb(plr);
			break;
		case Youmu:
			youmu_bomb(plr);
			break;
		}
		
		plr->bombs--;
		
		if(plr->deathtime > 0) {
			plr->deathtime = -1;
			plr->bombs /= 2;
		}			
		
		plr->recovery = global.frames + BOMB_RECOVERY;
	}
}

void player_realdeath(Player *plr) {
	plr->deathtime = -DEATH_DELAY-1;
	
	plr->moveflags = 0;
		
	create_item(plr->pos, 6-15*I, Power);
	create_item(plr->pos, -6-15*I, Power);
	
	plr->pos = VIEWPORT_W/2 + VIEWPORT_H*I+30I;
	plr->recovery = -(global.frames + DEATH_DELAY + 150);

	if(plr->bombs < PLR_START_BOMBS)
		plr->bombs = PLR_START_BOMBS;
	
	if(plr->lifes-- == 0 && global.replaymode != REPLAY_PLAY)
		global.menu = create_gameover_menu();
}

void player_death(Player *plr) {
	if(plr->deathtime == -1 && global.frames - abs(plr->recovery) > 0) {
		int i;
		for(i = 0; i < 20; i++) {
			tsrand_fill(2);
			create_particle2c("flare", plr->pos, NULL, Shrink, timeout_linear, 40, (3+afrand(0)*7)*cexp(I*tsrand_a(1)));
		}
		create_particle2c("blast", plr->pos, rgb(1,0.5,0.3), GrowFade, timeout, 35, 2.4);
		plr->deathtime = global.frames + DEATHBOMB_TIME;
	}
}

void player_setmoveflag(Player* plr, int key, int mode) {
	int flag = 0;
	
	switch(key) {
		case KEY_UP:	flag = MOVEFLAG_UP; 	break;
		case KEY_DOWN:	flag = MOVEFLAG_DOWN;	break;
		case KEY_LEFT:	flag = MOVEFLAG_LEFT;	break;
		case KEY_RIGHT:	flag = MOVEFLAG_RIGHT;	break;
	}
	
	if(!flag)
		return;
	
	if(mode)
		plr->moveflags |= flag;
	else
		plr->moveflags &= ~flag;
}

void player_event(Player* plr, int type, int key) {
	switch(type) {
		case EV_PRESS:
			switch(key) {
				case KEY_FOCUS:
					plr->focus = 1;
					break;
				
				case KEY_SHOT:
					plr->fire = True;
					break;
				
				case KEY_BOMB:
					player_bomb(plr);
					break;
				
				default:
					player_setmoveflag(plr, key, True);
					break;
			}
			break;
		
		case EV_RELEASE:
			switch(key) {
				case KEY_FOCUS:
					plr->focus = -30;  // that's for the transparency timer
					break;
				
				case KEY_SHOT:
					plr->fire = False;
					break;
				
				default:
					player_setmoveflag(plr, key, False);
					break;
			}
			
			break;
	}
}

void player_applymovement(Player* plr) {
	if(plr->deathtime < -1)
		return;
	
	plr->moving = False;
	
	int up		=	plr->moveflags & MOVEFLAG_UP,
		down	=	plr->moveflags & MOVEFLAG_DOWN,
		left	=	plr->moveflags & MOVEFLAG_LEFT,
		right	=	plr->moveflags & MOVEFLAG_RIGHT;
	
	if(left && !right) {
		plr->moving = True;
		plr->dir = 1;
	} else if(right && !left) {
		plr->moving = True;
		plr->dir = 0;
	}	
	
	complex direction = 0;
	
	if(up)		direction -= 1I;
	if(down)	direction += 1I;
	if(left)	direction -= 1;
	if(right)	direction += 1;
		
	if(cabs(direction))
		direction /= cabs(direction);
	
	if(direction)
		player_move(&global.plr, direction);
	
	// workaround
	if(global.replaymode == REPLAY_RECORD) {
		Uint8 *keys = SDL_GetKeyState(NULL);
		
		if(!keys[tconfig.intval[KEY_SHOT]] && plr->fire) {
			player_event(plr, EV_RELEASE, KEY_SHOT);
			replay_event(&global.replay, EV_RELEASE, KEY_SHOT);
		}
		
		if(!keys[tconfig.intval[KEY_FOCUS]] && plr->focus > 0) {
			player_event(plr, EV_RELEASE, KEY_FOCUS);
			replay_event(&global.replay, EV_RELEASE, KEY_FOCUS);
		}
	}
}

{'fraction_non_alphanumeric': 0.17116205076288957, 'fraction_numerical': 0.02357364957697592, 'mean_word_length': 3.2371323529411766, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 215, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6906649', 'n_tokens_mistral': 7055, 'n_tokens_neox': 6013, 'n_words': 1062}