/*
* $Id: attractmanager.c 311 2005-12-10 17:51:50Z mrbrown $
*
* Copyright 2003 Kenta Cho. All rights reserved.
*/
/**
* Attraction(score/title/gameover) manager.
*
* @version $Revision: 311 $
*/
#include "SDL.h"
#include <stdlib.h>
#include <stdio.h>
#include "rr.h"
#include "genmcr.h"
#include "screen.h"
#include "letterrender.h"
#include "attractmanager.h"
#include "ship.h"
#include "brgmng_mtd.h"
#include "soundmanager.h"
#include "degutil.h"
#include "boss_mtd.h"
int score;
static int nextExtend, neAdd;
int left, stage, scene;
static float rank;
unsigned long seed;
int bombUsed, shipUsed;
int mode;
static HiScore hiScore;
#define PREF_FILE "rr.prf"
#define DEFAULT_HISCORE 100000
static void initHiScore() {
int i, j;
for ( j=0 ; j<MODE_NUM ; j++ ) {
for ( i=0 ; i<STAGE_NUM ; i++ ) {
hiScore.score[j][i] = DEFAULT_HISCORE;
hiScore.cleard[j][i] = 0;
}
}
hiScore.stage = hiScore.mode = 0;
}
static float bgColor[MODE_NUM][3] = {
{0.0f, 0.0f, 0.0f}, {0.1f, 0.1f, 0.3f}, {0.3f, 0.1f, 0.3f}, {0.1f, 0.3f, 0.1f},
};
static void setMode(int m) {
mode = m;
glClearColor(bgColor[m][0], bgColor[m][1], bgColor[m][2], 0.0f);
}
// Load preference.
void loadPreference() {
FILE *fp;
int i, j;
int version;
if ( NULL == (fp = fopen(PREF_FILE,"rb")) ) {
initHiScore();
return;
}
version = getw(fp);
if ( version != VERSION_NUM ) {
initHiScore();
return;
}
for ( j=0 ; j<MODE_NUM ; j++ ) {
for ( i=0 ; i<STAGE_NUM ; i++ ) {
hiScore.score[j][i] = getw(fp);
hiScore.cleard[j][i] = getw(fp);
}
}
hiScore.stage = getw(fp);
hiScore.mode = getw(fp);
fclose(fp);
}
// Save preference.
void savePreference() {
FILE *fp;
int i, j;
if ( NULL == (fp = fopen(PREF_FILE,"wb")) ) return;
putw(VERSION_NUM, fp);
for ( j=0 ; j<MODE_NUM ; j++ ) {
for ( i=0 ; i<STAGE_NUM ; i++ ) {
putw(hiScore.score[j][i], fp);
putw(hiScore.cleard[j][i], fp);
}
}
putw(hiScore.stage, fp);
putw(hiScore.mode, fp);
fclose(fp);
}
static void gotoNextScene() {
scene++;
seed = seed*8513L + 179L;
createBoss(seed, rank, scene);
bombUsed = shipUsed = 0;
}
#define RANK_UP_BASE 1.25
void initStageState(int stg) {
float rb;
int rn, sn;
int i;
scene = -1;
rn = stg/SAME_RANK_STAGE_NUM; sn = stg%SAME_RANK_STAGE_NUM;
if ( sn == SAME_RANK_STAGE_NUM-1 ) {
seed = rand();
} else {
seed = stg*10357 + 5449 + mode*947;
}
rank = 0.1; rb = 0;
for ( i=0 ; i<rn ; i++ ) {
rb += RANK_UP_BASE;
rank += rb;
}
if ( stg >= STAGE_NUM || stg < 0 ) rank = 0;
gotoNextScene();
}
static char stageStr[3] = "1A";
static void makeStageStr(int stg) {
if ( stg >= 36 ) {
stageStr[0] = '0';
} else {
stageStr[0] = '1' + stg/SAME_RANK_STAGE_NUM;
}
if ( stg%SAME_RANK_STAGE_NUM < SAME_RANK_STAGE_NUM-1 ) {
stageStr[1] = stg%SAME_RANK_STAGE_NUM + 'A';
} else {
stageStr[1] = 'R';
}
}
void initGameStateFirst() {
score = 0;
nextExtend = 200000;
neAdd = 300000;
left = 2;
stage = 0;
}
void initGameState(int stg) {
initGameStateFirst();
hiScore.stage = stage = stg;
hiScore.mode = mode;
makeStageStr(stg);
initStageState(stg);
}
void addScore(int s) {
score += s;
if ( score >= nextExtend ) {
nextExtend += neAdd;
neAdd = 500000;
if ( extendShip() ) {
playChunk(8);
}
}
}
int extendShip() {
if ( left > 8 ) return 0;
left++;
drawRPanel();
return 1;
}
int decrementShip() {
left--;
drawRPanel();
if ( left < 0 ) return 1;
return 0;
}
void addLeftBonus() {
nextExtend = 999999999;
addScore(left*100000);
}
void setHiScore(int cleard) {
if ( score > hiScore.score[mode][stage] ) {
hiScore.score[mode][stage] = score;
}
if ( cleard ) {
hiScore.cleard[mode][stage] = 1;
}
}
void drawScore() {
drawNum(score, 118, 24, 28, 200, 200, 222);
drawNum(bonusScore/10*10, 24, 14, 16, 200, 200, 222);
}
#define SCENE_STAT_X 77
#define SCENE_STAT_SIZE 9
static char *lStr = "LEFT", *bStr = "BOMB", *okStr="OK";
void drawRPanel() {
int y;
int ml;
if ( left >= 0 ) {
drawString(lStr, 40+480, 280, 18, 1, 200, 200, 222);
drawLetter(left, 40+480, 420, 18, 1, 230, 180, 150);
switch ( mode ) {
case NORMAL_MODE:
drawString(bStr, 90+480, 280, 18, 1, 200, 200, 222);
drawLetter(bomb, 90+480, 420, 18, 1, 230, 180, 150);
break;
case PSY_MODE:
ml = ship.grzCnt/40;
drawBox(550, 460, 50, 8, 120, 120, 120);
drawBox(500+ml, 460, ml, 8, 210, 210, 240);
break;
case GW_MODE:
ml = (ship.rfMtr-ship.rfMtrDec)/40;
drawBox(550, 460, 50, 8, 120, 120, 120);
drawBox(500+ml, 460, ml, 8, 210, 240, 210);
if ( ml >= 50 ) {
drawString(okStr, 540, 460, 10, 0, 230, 240, 230);
}
break;
}
}
y = 24;
drawString(stageStr, 124+480, y, 24, 1, 200, 200, 222);
y += 24*1.7f*2;
drawLetter(38, 124+480, y, 24, 1, 200, 200, 222);
y += 24*1.7f;
drawNumRight(scene+1, 124+480, y, 24, 200, 200, 222);
}
#define STG_BOX_SIZE 21
#define STG_BOX_NUM (MODE_NUM+STAGE_NUM+1)
#define LAYER_HEIGHT 480
static int stageX[STG_BOX_NUM], stageY[STG_BOX_NUM];
void initAttractManager() {
int i, j, x, y, s;
//y = 200;
y = 172;
s = 0;
for ( i=0 ; i<12 ; i++, y+=STG_BOX_SIZE*1.2f ) {
x = 180;
if ( i < 11 ) {
for ( j=0 ; j<SAME_RANK_STAGE_NUM ; j++, s++, x+=STG_BOX_SIZE*1.2f ) {
stageX[s] = x; stageY[s] = y;
}
} else {
stageX[s] = x; stageY[s] = y;
}
}
}
static int titleCnt;
static int slcStg;
static int mnp;
int initTitleAtr() {
stopMusic();
titleCnt = 0;
slcStg = hiScore.stage;
setMode(hiScore.mode);
mnp = 0;
return slcStg;
}
#define QUIT_STAGE_NUM 40
void moveTitleMenu() {
int pad = getPadState();
int btn = getButtonState();
int bs = slcStg;
if ( pad & PAD_DOWN ) {
if ( mnp ) {
if ( slcStg < STAGE_NUM-SAME_RANK_STAGE_NUM ) slcStg += SAME_RANK_STAGE_NUM;
else if ( slcStg == QUIT_STAGE_NUM ) slcStg = -MODE_NUM;
else slcStg = QUIT_STAGE_NUM;
}
} else if ( pad & PAD_UP ) {
if ( mnp ) {
if ( slcStg >= 0 ) slcStg -= SAME_RANK_STAGE_NUM;
else slcStg = QUIT_STAGE_NUM ;
}
} else if ( pad & PAD_RIGHT ) {
if ( mnp ) {
if ( slcStg >= 0 ) {
if ( (slcStg%SAME_RANK_STAGE_NUM) < SAME_RANK_STAGE_NUM-1 && slcStg != QUIT_STAGE_NUM ) {
slcStg++;
}
} else if ( slcStg < -1 ) {
slcStg++;
}
}
} else if ( pad & PAD_LEFT ) {
if ( mnp ) {
if ( slcStg >= 0 ) {
if ( (slcStg%SAME_RANK_STAGE_NUM) > 0 && slcStg != QUIT_STAGE_NUM ) {
slcStg--;
}
} else if ( slcStg > -4 ) {
slcStg--;
}
}
} else if ( btn == 0 ) {
mnp = 1;
}
if ( slcStg != bs ) {
mnp = 0;
initTitleStage(slcStg);
titleCnt = 0;
}
if ( mnp && ((btn & PAD_BUTTON1) || (btn & PAD_START)) ) {
if ( slcStg == QUIT_STAGE_NUM ) {
quitLast();
} else if ( slcStg < 0 ) {
mnp = 0;
setMode(MODE_NUM+slcStg);
} else {
hiScore.stage = slcStg;
initGame(slcStg);
}
}
if ( mnp && (btn & PAD_BUTTON2) ) {
mnp = 0;
setMode((mode+1)%MODE_NUM);
initTitleStage(slcStg);
titleCnt = 0;
}
titleCnt++;
}
void drawTitle() {
int i;
int r, g, b;
int sx, sy;
char *stgChr = "STAGE";
char *quitChr = "QUIT";
char *mdChr[] = {"NORMAL MODE", "PSY MODE", "IKA MODE", "GW MODE"};
int mdChrX[] = {270, 330, 330, 350};
char mdIni[] = {'N', 'P', 'I', 'G'};
drawTitleBoard();
for ( i=-MODE_NUM ; i<STAGE_NUM+1 ; i++ ) {
if ( i < 0 ) {
if ( 4+i == mode ) {
r = 100; g = 100; b = 240;
} else {
r = 150; g = 150; b = 200;
}
} else if ( i < QUIT_STAGE_NUM && hiScore.cleard[mode][i] ) {
r = 240; g = 180; b = 180;
} else {
r = 210; g = 210; b = 240;
}
sx = stageX[i+MODE_NUM]; sy = stageY[i+MODE_NUM];
if ( i == slcStg ) {
int sz = STG_BOX_SIZE*3/2;
if ( titleCnt < 16 ) sz = sz*titleCnt/16;
drawBox(sx, sy, sz, sz, r, g, b);
sz = sz*3/5;
if ( i < 0 ) {
int md = MODE_NUM+i;
drawString(mdChr[md], mdChrX[md], 133, 12, 0, 150, 150, 200);
drawLetter(mdIni[md]-'A'+10, sx, sy, sz, 0, 150, 150, 240);
} else if ( i < QUIT_STAGE_NUM ) {
makeStageStr(i);
drawString(stageStr, sx-sz, sy, sz, 0, 210, 210, 240);
drawString(stgChr, 330, 133, 12, 0, 210, 210, 240);
drawString(stageStr, 445, 133, 12, 0, 210, 210, 240);
drawNumCenter(hiScore.score[mode][i], 466, 168, 12, 210, 210, 240);
} else {
drawLetter('Q'-'A'+10, sx, sy, sz, 0, 210, 210, 240);
drawString(quitChr, 410, 133, 12, 0, 210, 210, 240);
}
} else {
drawBox(sx, sy, STG_BOX_SIZE/2, STG_BOX_SIZE/2, r*2/3, g*2/3, b*2/3);
}
}
drawString(mdChr[mode], mdChrX[mode], 455, 12, 0, 150, 150, 200);
}
static int goCnt;
void initGameoverAtr() {
goCnt = 0;
mnp = 0;
fadeMusic();
}
void moveGameover() {
int btn = getButtonState();
if ( goCnt > 900 || (goCnt > 128 && mnp && (btn & PAD_BUTTON1)) ) {
setHiScore(0);
initTitle();
return;
}
if ( btn == 0 ) {
mnp = 1;
}
goCnt++;
}
void drawGameover() {
char *goChr = "GAME OVER";
int y;
if ( goCnt < 128 ) {
y = LAYER_HEIGHT/3*goCnt/128;
} else {
y = LAYER_HEIGHT/3;
}
drawString(goChr, 184, y, 20, 0, 180, 180, 220);
}
static int psCnt = 0;
void movePause() {
psCnt++;
}
void drawPause() {
char *psChr = "PAUSE";
if ( (psCnt&63) < 32 ) {
drawString(psChr, 252, LAYER_HEIGHT/3, 20, 0, 200, 200, 180);
}
}
static int bsCnt, bossScore, bsAdd;
void initBossScoreAtr(int bs) {
bsCnt = 0;
mnp = 0;
bossScore = bs;
bsAdd = bs/(1 + shipUsed + bombUsed)/10*10;
if ( scene > 3 ) {
status = STAGE_CLEAR;
fadeMusic();
}
}
void moveBossScoreAtr() {
int btn = getButtonState();
if ( bsCnt == 128 ) addScore(bsAdd);
if ( bsCnt > 600 || (bsCnt > 160 && mnp && (btn & PAD_BUTTON1)) ) {
if ( status != STAGE_CLEAR ) {
gotoNextScene();
} else {
setHiScore(1);
initTitle();
}
return;
}
if ( btn == 0 ) {
mnp = 1;
}
bsCnt++;
}
void drawBossScoreAtr() {
if ( bsCnt < 32 ) return;
drawNumCenter(bossScore, 450, 240, 16, 200, 200, 220);
if ( bsCnt < 64 ) return;
drawBox(320, 272, 150, 4, 200, 200, 220);
if ( bsCnt < 96 ) return;
drawNumCenter(1, 230, 306, 16, 200, 200, 220);
drawLetter(39, 260, 306, 16, 0, 200, 200 ,220);
drawNumCenter(shipUsed, 340, 306, 16, 200, 200, 220);
if ( mode == NORMAL_MODE ) {
drawLetter(39, 380, 306, 16, 0, 200, 200 ,220);
drawNumCenter(bombUsed, 450, 306, 16, 200, 200, 220);
}
if ( bsCnt < 128 ) return;
drawNumCenter(bsAdd, 450, 380, 19, 200, 220, 200);
if ( status == STAGE_CLEAR ) {
char *scChr = "STAGE CLEAR";
drawString(scChr, 190, 440, 15, 0, 180, 220, 180);
}
}