diff --git a/src/gui/gui.h b/src/gui/gui.h index 4195440ae..f1204e3ce 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1871,6 +1871,7 @@ class FurnaceGUI { int loadChineseTraditional; int loadKorean; int loadFallback; + int loadFallbackPat; int fmLayout; int sampleLayout; int waveLayout; @@ -2123,6 +2124,7 @@ class FurnaceGUI { loadChineseTraditional(0), loadKorean(0), loadFallback(1), + loadFallbackPat(1), fmLayout(4), sampleLayout(0), waveLayout(0), diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 5a3c8a668..2ffe481d5 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -3150,6 +3150,15 @@ void FurnaceGUI::drawSettings() { ImGui::SetTooltip(_("disable to save video memory.")); } + bool loadFallbackPatB=settings.loadFallbackPat; + if (ImGui::Checkbox(_("Load fallback font (pattern)"),&loadFallbackPatB)) { + settings.loadFallbackPat=loadFallbackPatB; + settingsChanged=true; + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip(_("disable to save video memory.")); + } + bool loadJapaneseB=settings.loadJapanese; if (ImGui::Checkbox(_("Display Japanese characters"),&loadJapaneseB)) { settings.loadJapanese=loadJapaneseB; @@ -5015,6 +5024,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { settings.loadChineseTraditional=conf.getInt("loadChineseTraditional",0); settings.loadKorean=conf.getInt("loadKorean",0); settings.loadFallback=conf.getInt("loadFallback",1); + settings.loadFallbackPat=conf.getInt("loadFallbackPat",1); settings.fontBackend=conf.getInt("fontBackend",FONT_BACKEND_DEFAULT); settings.fontHinting=conf.getInt("fontHinting",GUI_FONT_HINTING_DEFAULT); @@ -5269,6 +5279,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { clampSetting(settings.loadChineseTraditional,0,1); clampSetting(settings.loadKorean,0,1); clampSetting(settings.loadFallback,0,1); + clampSetting(settings.loadFallbackPat,0,1); clampSetting(settings.fmLayout,0,6); clampSetting(settings.susPosition,0,3); clampSetting(settings.effectCursorDir,0,2); @@ -5590,6 +5601,7 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { conf.set("loadChineseTraditional",settings.loadChineseTraditional); conf.set("loadKorean",settings.loadKorean); conf.set("loadFallback",settings.loadFallback); + conf.set("loadFallbackPat",settings.loadFallbackPat); conf.set("fontBackend",settings.fontBackend); conf.set("fontHinting",settings.fontHinting); @@ -6993,15 +7005,14 @@ void FurnaceGUI::applyUISettings(bool updateFonts) { } // four fallback fonts - if (settings.loadJapanese || + if (settings.loadFallbackPat && (settings.loadJapanese || settings.loadChinese || settings.loadChineseTraditional || settings.loadKorean || localeRequiresJapanese || localeRequiresChinese || localeRequiresChineseTrad || - localeRequiresKorean || - settings.loadFallback) { + localeRequiresKorean)) { patFont=addFontZlib(font_plexMono_compressed_data,font_plexMono_compressed_size,MAX(1,e->getConfInt("patFontSize",18)*dpiScale),&fc1,fontRange); patFont=addFontZlib(font_plexSansJP_compressed_data,font_plexSansJP_compressed_size,MAX(1,e->getConfInt("patFontSize",18)*dpiScale),&fc1,fontRange); patFont=addFontZlib(font_plexSansKR_compressed_data,font_plexSansKR_compressed_size,MAX(1,e->getConfInt("patFontSize",18)*dpiScale),&fc1,fontRange); diff --git a/src/gui/tutorial.cpp b/src/gui/tutorial.cpp index 6ecc92af5..6a13d37c9 100644 --- a/src/gui/tutorial.cpp +++ b/src/gui/tutorial.cpp @@ -134,7 +134,7 @@ struct FurnaceCV { int ticksToInit; bool inGame, inTransition, newHiScore, playSongs, pleaseInitSongs, gameOver; - unsigned char lives, respawnTime, stage, shotType; + unsigned char lives, respawnTime, stage, shotType, lifeBank; int score; int hiScore; short lastPlayerX, lastPlayerY; @@ -215,6 +215,7 @@ struct FurnaceCV { respawnTime(0), stage(0), shotType(0), + lifeBank(0), score(0), hiScore(25000), lastPlayerX(0), @@ -396,6 +397,7 @@ struct FurnaceCVEnemyVortex: FurnaceCVObject { struct FurnaceCVEnemyPlane: FurnaceCVObject { unsigned char orient; short shootTime, speed; + bool notifyPlayer; void collision(FurnaceCVObject* other); @@ -404,7 +406,8 @@ struct FurnaceCVEnemyPlane: FurnaceCVObject { FurnaceCVObject(p), orient(rand()&3), shootTime(40), - speed(3) { + speed(3), + notifyPlayer(true) { type=CV_PLANE; speed=2+(p->stage>>2)+(rand()%3); prio=3; @@ -616,7 +619,12 @@ static const char* cvText[]={ _N("GAME OVER"), - _N("High Score!") + _N("High Score!"), + + _N("Welcome to Combat Vehicle!\n\n" + "Controls:\n" + "B - Shoot D-Pad - Move\n" + "A - Special"), }; void FurnaceGUI::syncTutorial() { @@ -854,7 +862,8 @@ void FurnaceGUI::drawTutorial() { if (ImGui::Begin("Combat Vehicle",&cvOpen,ImGuiWindowFlags_NoDocking|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoTitleBar)) { ImVec2 dpadLoc=ImVec2(canvasW*0.22,canvasH*0.85); ImVec2 buttonLoc=ImVec2(canvasW*0.78,canvasH*0.85); - float oneUnit=canvasW*0.12; + ImVec2 quitLoc=ImVec2(canvasW*0.5,canvasH*0.6); + float oneUnit=MIN(canvasW,canvasH)*0.12; ImVec2 dpadUpStart=ImVec2( dpadLoc.x-oneUnit*1.75, @@ -897,6 +906,14 @@ void FurnaceGUI::drawTutorial() { buttonLoc.x+oneUnit*1.25, buttonLoc.y+oneUnit*0.5 ); + ImVec2 buttonQuitStart=ImVec2( + quitLoc.x-oneUnit*0.5, + quitLoc.y-oneUnit*0.25 + ); + ImVec2 buttonQuitEnd=ImVec2( + quitLoc.x+oneUnit*0.5, + quitLoc.y+oneUnit*0.25 + ); unsigned char touchControls=0; @@ -932,15 +949,16 @@ void FurnaceGUI::drawTutorial() { i.x<=dpadDownEnd.x && i.y<=dpadDownEnd.y) { touchControls|=128; } - } - - if (cv!=NULL) { - if (touchControls && cv->gameOver) { - cv->unload(); - delete cv; - cv=NULL; - cvOpen=false; - return; + // quit + if (cv!=NULL) { + if (i.x>=buttonQuitStart.x && i.y>=buttonQuitStart.y && + i.x<=buttonQuitEnd.x && i.y<=buttonQuitEnd.y) { + cv->unload(); + delete cv; + cv=NULL; + cvOpen=false; + return; + } } } } @@ -1028,13 +1046,42 @@ void FurnaceGUI::drawTutorial() { dl->AddImage(rend->getTextureID(cvTex),p0,p1,ImVec2(0,0),ImVec2(rend->getTextureU(cvTex),rend->getTextureV(cvTex))); if (mobileUI) { - dl->AddRect(dpadUpStart,dpadUpEnd,0xff0000ff,0,0,dpiScale); - dl->AddRect(dpadUpStart,dpadLeftEnd,0xff00ffff,0,0,dpiScale); - dl->AddRect(dpadDownStart,dpadDownEnd,0xff00ff00,0,0,dpiScale); - dl->AddRect(dpadRightStart,dpadDownEnd,0xffff0000,0,0,dpiScale); + ImVec2 chevron[3]; - dl->AddRect(buttonBStart,buttonBEnd,0xffffff00,0,0,dpiScale); - dl->AddRect(buttonAStart,buttonAEnd,0xffff00ff,0,0,dpiScale); + // up + chevron[0]=ImLerp(dpadUpStart,dpadUpEnd,ImVec2(0.4,0.65)); + chevron[1]=ImLerp(dpadUpStart,dpadUpEnd,ImVec2(0.5,0.35)); + chevron[2]=ImLerp(dpadUpStart,dpadUpEnd,ImVec2(0.6,0.65)); + dl->AddPolyline(chevron,3,0xffffffff,0,4.0f*dpiScale); + + // left + chevron[0]=ImLerp(dpadUpStart,dpadLeftEnd,ImVec2(0.65,0.4)); + chevron[1]=ImLerp(dpadUpStart,dpadLeftEnd,ImVec2(0.35,0.5)); + chevron[2]=ImLerp(dpadUpStart,dpadLeftEnd,ImVec2(0.65,0.6)); + dl->AddPolyline(chevron,3,0xffffffff,0,4.0f*dpiScale); + + // down + chevron[0]=ImLerp(dpadDownStart,dpadDownEnd,ImVec2(0.4,0.35)); + chevron[1]=ImLerp(dpadDownStart,dpadDownEnd,ImVec2(0.5,0.65)); + chevron[2]=ImLerp(dpadDownStart,dpadDownEnd,ImVec2(0.6,0.35)); + dl->AddPolyline(chevron,3,0xffffffff,0,4.0f*dpiScale); + + // right + chevron[0]=ImLerp(dpadRightStart,dpadDownEnd,ImVec2(0.35,0.4)); + chevron[1]=ImLerp(dpadRightStart,dpadDownEnd,ImVec2(0.65,0.5)); + chevron[2]=ImLerp(dpadRightStart,dpadDownEnd,ImVec2(0.35,0.6)); + dl->AddPolyline(chevron,3,0xffffffff,0,4.0f*dpiScale); + + // A/B + dl->AddRectFilled(buttonBStart,buttonBEnd,(touchControls&1)?0x4040ffff:0x2040ffff,0,0); + dl->AddRectFilled(buttonAStart,buttonAEnd,(touchControls&2)?0x4040ffff:0x2040ffff,0,0); + dl->AddRect(buttonBStart,buttonBEnd,0xff00ffff,0,0,dpiScale); + dl->AddRect(buttonAStart,buttonAEnd,0xff00ffff,0,0,dpiScale); + dl->AddText(headFont,settings.headFontSize*dpiScale,ImLerp(buttonBStart,buttonBEnd,ImVec2(0.5,0.5))-(headFont->CalcTextSizeA(settings.headFontSize*dpiScale,FLT_MAX,0,"B")*0.5f),0xff00ffff,"B"); + dl->AddText(headFont,settings.headFontSize*dpiScale,ImLerp(buttonAStart,buttonAEnd,ImVec2(0.5,0.5))-(headFont->CalcTextSizeA(settings.headFontSize*dpiScale,FLT_MAX,0,"A")*0.5f),0xff00ffff,"A"); + + // quit + dl->AddRect(buttonQuitStart,buttonQuitEnd,0xffffffff,0,0,dpiScale); } } } @@ -1167,6 +1214,11 @@ static const unsigned char cvPalette[1024]={ #define SE_VORTEXMOVE 13, 3, 55 #define SE_VORTEXSHOOT 14, 3, 48 #define SE_RESIST 15, 1, 48 +#define SE_PLANE1 16, 1, 47 +#define SE_PLANE2 17, 2, 47 +#define SE_EXPL2 18, 1, 60 +#define SE_PICKUP3 19, 3, 67 +#define SE_TIMEUP 20, 2, 81 template T* FurnaceCV::createObject(short x, short y) { T* ret=new T(this); @@ -1522,6 +1574,7 @@ void FurnaceCV::render(unsigned char joyIn) { stopSoundEffect(0,3,0); respawnTime=0; for (FurnaceCVObject* i: sprite) { + if (i->type==CV_EXTRA_LIFE) lifeBank++; i->dead=true; } memset(tile0,0,80*56*sizeof(short)); @@ -1558,6 +1611,13 @@ void FurnaceCV::render(unsigned char joyIn) { } } + if (gameOver && lifeBank>0 && joyInput==3) { + lives+=lifeBank; + respawnTime=1; + lifeBank=0; + gameOver=false; + } + // draw score putText(CV_FONTBASE_8x8_RED,false,"1UP",0,0); putText(CV_FONTBASE_8x8,false,fmt::sprintf("%8d",score),3,0); @@ -1639,6 +1699,7 @@ void FurnaceCV::render(unsigned char joyIn) { // S mod stat if (speedTicks>0) { speedTicks--; + if (speedTicks==120) soundEffect(SE_TIMEUP); if ((speedTicks<120 && speedTicks&2) || (speedTicks>=120 && speedTicks&16)) { tile1[24][36]=0x41e; tile1[24][37]=0x41f; @@ -1707,7 +1768,8 @@ void FurnaceCV::render(unsigned char joyIn) { inGame=true; } else { memset(tile1,0,80*56*sizeof(short)); - startTyping(_(cvText[curText++]),2,3); + startTyping(_(cvText[curText]),2,3); + curText++; textWait=90; } } @@ -1878,7 +1940,15 @@ void FurnaceCVPlayer::collision(FurnaceCVObject* other) { if (other->type==CV_ENEMY_BULLET || other->type==CV_MINE || other->type==CV_ENEMY) { - if (!invincible) { + bool mustDie=!invincible; + + if (other->type==CV_ENEMY_BULLET) { + const int diffX=abs((other->x+4)-(x+12)); + const int diffY=abs((other->y+4)-(y+12)); + if (diffX>4 || diffY>4) mustDie=false; + } + + if (mustDie) { dead=true; cv->speedTicks=0; cv->e->setSongRate(cv->origSongRate); @@ -2002,6 +2072,9 @@ void FurnaceCVPlayer::tick() { if (cv->joyPressed&1) { shotTimer=(cv->shotType==2)?5:9; + if (cv->speedTicks>0) { + shotTimer=(cv->shotType==2)?2:4; + } if (cv->shotType==1) { cv->soundEffect(SE_SHOT2); } else { @@ -2045,6 +2118,9 @@ void FurnaceCVPlayer::tick() { if (cv->joyInput&1) { if (--shotTimer<1) { shotTimer=(cv->shotType==2)?4:8; + if (cv->speedTicks>0) { + shotTimer=(cv->shotType==2)?1:3; + } if (cv->shotType==1) { cv->soundEffect(SE_SHOT2); } else { @@ -2355,7 +2431,7 @@ void FurnaceCVEnemy1::collision(FurnaceCVObject* other) { if (other->type==CV_BULLET || other->type==CV_PLAYER) { if (--health<=0) { dead=true; - if ((rand()%7)==0 || (enemyType>1 && (rand()%7)==3)) { + if ((rand()%7)==0 || (enemyType>1 && (rand()%3)==2)) { switch (rand()%14) { case 0: // extra life cv->createObject(x+(enemyType>=2?8:0),y+(enemyType>=2?8:0)); @@ -2985,6 +3061,90 @@ static const unsigned char __0f_fui[] = { 0x50, 0x4e, 0x01, 0x00, 0x03 }; static const unsigned int __0f_fui_len = 101; +static const unsigned char __10_fui[] = { + 0x46, 0x49, 0x4e, 0x53, 0xe2, 0x00, 0x38, 0x00, 0x4d, 0x41, 0x94, 0x00, + 0x08, 0x00, 0x00, 0x10, 0xff, 0xff, 0x00, 0x03, 0x00, 0x01, 0x00, 0x0f, + 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x4c, 0x48, 0xff, 0x01, 0x41, 0x00, 0x01, 0xfd, 0xfc, + 0xfb, 0xfb, 0xfb, 0xfa, 0xfa, 0xfa, 0xfa, 0xf8, 0xf7, 0xf6, 0xf6, 0xf5, + 0xf5, 0xf4, 0xf3, 0xf3, 0xf2, 0xf2, 0xf3, 0xf2, 0xf1, 0xf1, 0xf0, 0xf0, + 0xef, 0xef, 0xee, 0xee, 0xee, 0xed, 0xed, 0xed, 0xec, 0xec, 0xec, 0xeb, + 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, + 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, + 0xee, 0xee, 0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf3, + 0xf3, 0xf3, 0x05, 0x01, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0e, + 0x01, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x01, 0x0f, 0x01, 0xff, 0xff, + 0x00, 0x01, 0x00, 0x01, 0x01, 0x13, 0x01, 0xff, 0xff, 0x00, 0x81, 0x00, + 0x01, 0x55, 0x55, 0xff, 0x50, 0x4e, 0x01, 0x00, 0x00 +}; +static const unsigned int __10_fui_len = 165; +static const unsigned char __11_fui[] = { + 0x46, 0x49, 0x4e, 0x53, 0xe2, 0x00, 0x38, 0x00, 0x4d, 0x41, 0x94, 0x00, + 0x08, 0x00, 0x00, 0x10, 0xff, 0xff, 0x00, 0x03, 0x00, 0x01, 0x00, 0x0f, + 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x4c, 0x48, 0xff, 0x01, 0x41, 0x00, 0x01, 0xd7, 0xfd, + 0xfb, 0xfb, 0xfb, 0xfa, 0xfa, 0xfa, 0xfa, 0xf8, 0xf7, 0xf6, 0xf6, 0xf5, + 0xf5, 0xf4, 0xf3, 0xf3, 0xf2, 0xf2, 0xf3, 0xf2, 0xf1, 0xf1, 0xf0, 0xf0, + 0xef, 0xef, 0xee, 0xee, 0xee, 0xed, 0xed, 0xed, 0xec, 0xec, 0xec, 0xeb, + 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, + 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, + 0xee, 0xee, 0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf3, + 0xf3, 0xf3, 0x05, 0x01, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0e, + 0x01, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x01, 0x0f, 0x01, 0xff, 0xff, + 0x00, 0x01, 0x00, 0x01, 0x01, 0x13, 0x01, 0xff, 0xff, 0x00, 0x81, 0x00, + 0x01, 0x55, 0x55, 0xff, 0x50, 0x4e, 0x01, 0x00, 0x00 +}; +static const unsigned int __11_fui_len = 165; +static const unsigned char __12_fui[] = { + 0x46, 0x49, 0x4e, 0x53, 0xe2, 0x00, 0x38, 0x00, 0x4d, 0x41, 0xd0, 0x00, + 0x08, 0x00, 0x00, 0x40, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x0f, 0x0f, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0e, 0x0d, 0x0d, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x09, 0x09, 0x07, + 0x07, 0x07, 0x06, 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x3c, 0x06, 0xff, 0x00, 0x41, 0x00, 0x01, 0x28, 0xfe, + 0xe8, 0xf6, 0x2c, 0x21, 0x1d, 0x05, 0x27, 0x04, 0x0b, 0x0b, 0x27, 0x28, + 0x02, 0x0d, 0x0a, 0x04, 0x03, 0x2c, 0x2c, 0x0c, 0xfc, 0x06, 0x1e, 0x2c, + 0xfe, 0xfe, 0x2c, 0x23, 0x2c, 0x24, 0x08, 0x0b, 0x2b, 0x1e, 0x2b, 0xfe, + 0x01, 0x07, 0x07, 0x0a, 0x2b, 0xff, 0x1c, 0x2a, 0x21, 0x16, 0x20, 0x16, + 0x16, 0x1d, 0x1d, 0x1c, 0x09, 0x02, 0x05, 0xfd, 0x09, 0x29, 0x05, 0x06, + 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x0e, 0x01, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x01, 0x0f, 0x03, 0xff, + 0xff, 0x00, 0x01, 0x00, 0x01, 0x0a, 0x01, 0x06, 0x10, 0x03, 0xff, 0xff, + 0x00, 0x01, 0x00, 0x01, 0x05, 0x04, 0x0c, 0x13, 0x03, 0xff, 0xff, 0x00, + 0xc1, 0x00, 0x01, 0xad, 0x3a, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x20, + 0x21, 0x00, 0x00, 0xff, 0x50, 0x4e, 0x01, 0x00, 0x00 +}; +static const unsigned int __12_fui_len = 225; +static const unsigned char __13_fui[] = { + 0x46, 0x49, 0x4e, 0x53, 0xe2, 0x00, 0x39, 0x00, 0x4d, 0x41, 0x95, 0x00, + 0x08, 0x00, 0x00, 0x52, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x0f, 0x0e, + 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, + 0x0a, 0x09, 0x08, 0x00, 0x0f, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0b, 0x06, 0xff, + 0x00, 0x01, 0x00, 0x03, 0x00, 0x04, 0x07, 0x02, 0x06, 0x09, 0x04, 0x08, + 0x0b, 0x10, 0x0b, 0x05, 0x01, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x0e, 0x01, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x01, 0x0f, 0x01, 0xff, + 0xff, 0x00, 0x01, 0x00, 0x01, 0x01, 0x13, 0x01, 0xff, 0xff, 0x00, 0x81, + 0x00, 0x01, 0x55, 0x55, 0xff, 0x50, 0x4e, 0x01, 0x00, 0x00 +}; +static const unsigned int __13_fui_len = 166; +static const unsigned char __14_fui[] = { + 0x46, 0x49, 0x4e, 0x53, 0xe2, 0x00, 0x38, 0x00, 0x4d, 0x41, 0x4f, 0x00, + 0x08, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x01, 0x00, 0x02, 0x0f, 0x0f, + 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, + 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, + 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x05, 0x01, 0xff, 0xff, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x0e, 0x01, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x01, 0x0f, + 0x01, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x01, 0x13, 0x01, 0xff, 0xff, + 0x00, 0x81, 0x00, 0x01, 0x55, 0x55, 0xff, 0x50, 0x4e, 0x01, 0x00, 0x00 +}; +static const unsigned int __14_fui_len = 96; #define LOAD_INS(x,y) { \ DivInstrument* newIns=new DivInstrument; \ @@ -3040,6 +3200,11 @@ void FurnaceCV::loadInstruments() { LOAD_INS(__0d_fui,__0d_fui_len); LOAD_INS(__0e_fui,__0e_fui_len); LOAD_INS(__0f_fui,__0f_fui_len); + LOAD_INS(__10_fui,__10_fui_len); + LOAD_INS(__11_fui,__11_fui_len); + LOAD_INS(__12_fui,__12_fui_len); + LOAD_INS(__13_fui,__13_fui_len); + LOAD_INS(__14_fui,__14_fui_len); } // FurnaceCVMine IMPLEMENTATION @@ -3124,7 +3289,10 @@ void FurnaceCVExtraLife::collision(FurnaceCVObject* other) { } void FurnaceCVExtraLife::tick() { - if (--life==0) dead=true; + if (--life==0) { + dead=true; + cv->lifeBank++; + } if (life>64 || (life&1)) { spriteDef[0]=0x0c; @@ -3171,7 +3339,7 @@ void FurnaceCVModI::tick() { void FurnaceCVModS::collision(FurnaceCVObject* other) { if (other->type==CV_PLAYER) { dead=true; - cv->soundEffect(SE_PICKUP1); + cv->soundEffect(SE_PICKUP3); cv->addScore(200); cv->speedTicks=900; cv->e->setSongRate(cv->origSongRate*1.5); @@ -3284,10 +3452,33 @@ void FurnaceCVEnemyPlane::tick() { break; } - if (dead) logE("plane dead"); - - if (--shootTime<=0) { - shootTime=40; - //cv->soundEffect(SE_VORTEXSHOOT); + if (notifyPlayer) { + for (FurnaceCVObject* i: cv->sprite) { + if (i->type==CV_PLAYER) { + if (abs((x+(spriteWidth<<2))-(i->x+(i->spriteWidth<<2)))<((orient&1)?80:180)) { + if (abs((y+(spriteHeight<<2))-(i->y+(i->spriteHeight<<2)))<((orient&1)?180:80)) { + cv->soundEffect(SE_PLANE1); + cv->soundEffect(SE_PLANE2); + shootTime=(50-speed*4)+(rand()%20); + notifyPlayer=false; + } + } + break; + } + } + } else { + if (--shootTime<=0) { + shootTime=28-(speed*2); + cv->soundEffect(SE_EXPL2); + cv->createObject(x+(spriteWidth<<2),y+(spriteHeight<<2)); + for (int i=0; i<14; i++) { + float fraction=(float)i/13.0f; + float xs=cos(fraction*M_PI*2.0)*28; + float ys=sin(fraction*M_PI*2.0)*28; + FurnaceCVEnemyBullet* b=cv->createObject(x+(spriteWidth<<2),y+(spriteHeight<<2)); + b->speedX=xs; + b->speedY=ys; + } + } } }