new demo song
by ALTMUS
This commit is contained in:
parent
bb2b2e1cc6
commit
13b56870ec
|
@ -14,6 +14,7 @@ these demo songs are not under the GPL. all rights are reserved to the original
|
||||||
- Aishi Tsukumo
|
- Aishi Tsukumo
|
||||||
- akumanatt
|
- akumanatt
|
||||||
- aloelucidity
|
- aloelucidity
|
||||||
|
- ALTMUS
|
||||||
- AmigaX
|
- AmigaX
|
||||||
- AquaDoesStuff
|
- AquaDoesStuff
|
||||||
- asikwus
|
- asikwus
|
||||||
|
|
BIN
demos/snes/time_of_the_dreamwatch.fur
Normal file
BIN
demos/snes/time_of_the_dreamwatch.fur
Normal file
Binary file not shown.
14
extern/backward/backward.hpp
vendored
14
extern/backward/backward.hpp
vendored
|
@ -24,6 +24,8 @@
|
||||||
#ifndef H_6B9572DA_A64B_49E6_B234_051480991C89
|
#ifndef H_6B9572DA_A64B_49E6_B234_051480991C89
|
||||||
#define H_6B9572DA_A64B_49E6_B234_051480991C89
|
#define H_6B9572DA_A64B_49E6_B234_051480991C89
|
||||||
|
|
||||||
|
extern int curEngineState;
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
#error "It's not going to compile without a C++ compiler..."
|
#error "It's not going to compile without a C++ compiler..."
|
||||||
#endif
|
#endif
|
||||||
|
@ -4253,7 +4255,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
MessageBox(NULL,"Error","Furnace has crashed! please report this to the issue tracker immediately:\r\nhttps://github.com/tildearrow/furnace/issues/new\r\n\r\na file called furnace_crash.txt will be created in your user directory.\r\nthis will be important for locating the origin of the crash.\r\n\r\nif Furnace keeps crashing and you believe it is caused by a configuration problem, you may start Furnace with the -safemode parameter.",MB_OK|MB_ICONERROR);
|
if (curEngineState==7 || curEngineState==11) {
|
||||||
|
MessageBox(NULL,"Furnace whoopsied and obliterated itself to pieces!\r\n\r\nreport the issue to tildearrow with the provided \"furnace_crash.txt\" in your home folder, or whatever that happened to you is inevitable sorry : < < < <\r\n\r\nor do -safemode in terminal if you got the bravery to do so\r\n\r\nif it also still crashes i'm afraid to tell you this is an other undercooked Furnace update","CRASHED IMMENSELY",MB_OK|MB_ICONERROR);
|
||||||
|
} else {
|
||||||
|
MessageBox(NULL,"Furnace has crashed! please report this to the issue tracker immediately:\r\nhttps://github.com/tildearrow/furnace/issues/new\r\n\r\na file called furnace_crash.txt will be created in your user directory.\r\nthis will be important for locating the origin of the crash.\r\n\r\nif Furnace keeps crashing and you believe it is caused by a configuration problem, you may start Furnace with the -safemode parameter.","Error",MB_OK|MB_ICONERROR);
|
||||||
|
}
|
||||||
std::string crashLocation;
|
std::string crashLocation;
|
||||||
char* userProfile=getenv("USERPROFILE");
|
char* userProfile=getenv("USERPROFILE");
|
||||||
if (userProfile==NULL) {
|
if (userProfile==NULL) {
|
||||||
|
@ -4492,7 +4498,11 @@ private:
|
||||||
printer.print(st, std::cerr);
|
printer.print(st, std::cerr);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
MessageBox(NULL,"Furnace has crashed! please report this to the issue tracker immediately:\r\nhttps://github.com/tildearrow/furnace/issues/new\r\n\r\na file called furnace_crash.txt will be created in your user directory.\r\nthis will be important for locating the origin of the crash.\r\n\r\nif Furnace keeps crashing and you believe it is caused by a configuration problem, you may start Furnace with the -safemode parameter.","Error",MB_OK|MB_ICONERROR);
|
if (curEngineState==7 || curEngineState==11) {
|
||||||
|
MessageBox(NULL,"Furnace whoopsied and obliterated itself to pieces!\r\n\r\nreport the issue to tildearrow with the provided \"furnace_crash.txt\" in your home folder, or whatever that happened to you is inevitable sorry : < < < <\r\n\r\nor do -safemode in terminal if you got the bravery to do so\r\n\r\nif it also still crashes i'm afraid to tell you this is an other undercooked Furnace update","CRASHED IMMENSELY",MB_OK|MB_ICONERROR);
|
||||||
|
} else {
|
||||||
|
MessageBox(NULL,"Furnace has crashed! please report this to the issue tracker immediately:\r\nhttps://github.com/tildearrow/furnace/issues/new\r\n\r\na file called furnace_crash.txt will be created in your user directory.\r\nthis will be important for locating the origin of the crash.\r\n\r\nif Furnace keeps crashing and you believe it is caused by a configuration problem, you may start Furnace with the -safemode parameter.","Error",MB_OK|MB_ICONERROR);
|
||||||
|
}
|
||||||
std::string crashLocation;
|
std::string crashLocation;
|
||||||
char* userProfile=getenv("USERPROFILE");
|
char* userProfile=getenv("USERPROFILE");
|
||||||
if (userProfile==NULL) {
|
if (userProfile==NULL) {
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
#include <fmt/printf.h>
|
#include <fmt/printf.h>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
int curEngineState=-1;
|
||||||
|
|
||||||
void process(void* u, float** in, float** out, int inChans, int outChans, unsigned int size) {
|
void process(void* u, float** in, float** out, int inChans, int outChans, unsigned int size) {
|
||||||
((DivEngine*)u)->nextBuf(in,out,inChans,outChans,size);
|
((DivEngine*)u)->nextBuf(in,out,inChans,outChans,size);
|
||||||
}
|
}
|
||||||
|
@ -4018,6 +4020,31 @@ bool DivEngine::prePreInit() {
|
||||||
logD("config path: %s",configPath.c_str());
|
logD("config path: %s",configPath.c_str());
|
||||||
|
|
||||||
configLoaded=true;
|
configLoaded=true;
|
||||||
|
curEngineState=-1;
|
||||||
|
time_t thisMakesNoSense=time(NULL);
|
||||||
|
struct tm curTime;
|
||||||
|
#ifdef _WIN32
|
||||||
|
struct tm* tempTM=localtime(&thisMakesNoSense);
|
||||||
|
if (tempTM!=NULL) {
|
||||||
|
memcpy(&curTime,tempTM,sizeof(struct tm));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (localtime_r(&thisMakesNoSense,&curTime)==NULL) {
|
||||||
|
memset(&curTime,0,sizeof(struct tm));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (curTime.tm_year==125) {
|
||||||
|
if (curTime.tm_mon==2 && curTime.tm_mday==31 && curTime.tm_hour>=23) {
|
||||||
|
curEngineState=curTime.tm_hour;
|
||||||
|
} else if (curTime.tm_mon==3 && curTime.tm_mday==1) {
|
||||||
|
curEngineState=curTime.tm_hour;
|
||||||
|
} else if (curTime.tm_mon==3 && curTime.tm_mday==2 && curTime.tm_hour<6) {
|
||||||
|
curEngineState=curTime.tm_hour;
|
||||||
|
} else {
|
||||||
|
curEngineState=-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return loadConf();
|
return loadConf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -432,6 +432,7 @@ enum DivChanTypes {
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const char* cmdName[];
|
extern const char* cmdName[];
|
||||||
|
extern int curEngineState;
|
||||||
|
|
||||||
class DivEngine {
|
class DivEngine {
|
||||||
DivDispatchContainer disCont[DIV_MAX_CHIPS];
|
DivDispatchContainer disCont[DIV_MAX_CHIPS];
|
||||||
|
@ -447,6 +448,7 @@ class DivEngine {
|
||||||
bool playing;
|
bool playing;
|
||||||
bool freelance;
|
bool freelance;
|
||||||
bool shallStop, shallStopSched;
|
bool shallStop, shallStopSched;
|
||||||
|
bool reverse;
|
||||||
bool endOfSong;
|
bool endOfSong;
|
||||||
bool consoleMode;
|
bool consoleMode;
|
||||||
bool disableStatusOut;
|
bool disableStatusOut;
|
||||||
|
@ -1400,6 +1402,7 @@ class DivEngine {
|
||||||
freelance(false),
|
freelance(false),
|
||||||
shallStop(false),
|
shallStop(false),
|
||||||
shallStopSched(false),
|
shallStopSched(false),
|
||||||
|
reverse(false),
|
||||||
endOfSong(false),
|
endOfSong(false),
|
||||||
consoleMode(false),
|
consoleMode(false),
|
||||||
disableStatusOut(false),
|
disableStatusOut(false),
|
||||||
|
|
|
@ -29,6 +29,11 @@
|
||||||
void DivEngine::nextOrder() {
|
void DivEngine::nextOrder() {
|
||||||
curRow=0;
|
curRow=0;
|
||||||
if (repeatPattern) return;
|
if (repeatPattern) return;
|
||||||
|
if (curEngineState==3 || curEngineState==17) {
|
||||||
|
if ((rand()%80)==0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (++curOrder>=curSubSong->ordersLen) {
|
if (++curOrder>=curSubSong->ordersLen) {
|
||||||
logV("end of orders reached");
|
logV("end of orders reached");
|
||||||
endOfSong=true;
|
endOfSong=true;
|
||||||
|
@ -326,6 +331,18 @@ const char* formatNote(unsigned char note, unsigned char octave) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivEngine::dispatchCmd(DivCommand c) {
|
int DivEngine::dispatchCmd(DivCommand c) {
|
||||||
|
if (curEngineState==2 || curEngineState==14 || curEngineState==22) {
|
||||||
|
if (c.cmd==DIV_CMD_NOTE_ON) {
|
||||||
|
if ((rand()&255)==0) {
|
||||||
|
c.value++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c.cmd==DIV_CMD_NOTE_OFF) {
|
||||||
|
if ((rand()&127)==0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (view==DIV_STATUS_COMMANDS) {
|
if (view==DIV_STATUS_COMMANDS) {
|
||||||
if (!skipping) {
|
if (!skipping) {
|
||||||
switch (c.cmd) {
|
switch (c.cmd) {
|
||||||
|
@ -1424,13 +1441,26 @@ void DivEngine::nextRow() {
|
||||||
changeOrd=-1;
|
changeOrd=-1;
|
||||||
}
|
}
|
||||||
if (haltOn==DIV_HALT_PATTERN) halted=true;
|
if (haltOn==DIV_HALT_PATTERN) halted=true;
|
||||||
} else if (playing) if (++curRow>=curSubSong->patLen) {
|
} else if (playing) {
|
||||||
if (shallStopSched) {
|
if (reverse) {
|
||||||
curRow=curSubSong->patLen-1;
|
if (--curRow<1) reverse=false;
|
||||||
} else {
|
} else {
|
||||||
nextOrder();
|
curRow++;
|
||||||
|
}
|
||||||
|
if (curRow>=curSubSong->patLen) {
|
||||||
|
if (shallStopSched) {
|
||||||
|
curRow=curSubSong->patLen-1;
|
||||||
|
} else {
|
||||||
|
nextOrder();
|
||||||
|
}
|
||||||
|
if (haltOn==DIV_HALT_PATTERN) halted=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((curEngineState==4 || curEngineState==21) && (curRow&3)==0 && !skipping) {
|
||||||
|
if ((rand()%600)==0) {
|
||||||
|
reverse=true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (haltOn==DIV_HALT_PATTERN) halted=true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// new loop detection routine
|
// new loop detection routine
|
||||||
|
@ -1459,6 +1489,17 @@ void DivEngine::nextRow() {
|
||||||
nextSpeed=speeds.val[curSpeed];
|
nextSpeed=speeds.val[curSpeed];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (curEngineState==3 || curEngineState==17) {
|
||||||
|
if ((rand()%300)==0) {
|
||||||
|
ticks++;
|
||||||
|
nextSpeed++;
|
||||||
|
}
|
||||||
|
if ((rand()%15000)==0) {
|
||||||
|
ticks=128;
|
||||||
|
nextSpeed+=128;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (skipping) {
|
if (skipping) {
|
||||||
ticks=1;
|
ticks=1;
|
||||||
|
|
|
@ -257,6 +257,9 @@ void FurnaceGUI::drawAbout() {
|
||||||
for (size_t i=0; i<aboutCount; i++) {
|
for (size_t i=0; i<aboutCount; i++) {
|
||||||
// don't localize tildearrow, the version or an empty line
|
// don't localize tildearrow, the version or an empty line
|
||||||
const char* nextLine=(i==0 || i==3 || aboutLine[i][0]==0)?aboutLine[i]:_(aboutLine[i]);
|
const char* nextLine=(i==0 || i==3 || aboutLine[i][0]==0)?aboutLine[i]:_(aboutLine[i]);
|
||||||
|
if (i==3 && curEngineState==1) {
|
||||||
|
nextLine="Furnace 0.6.9";
|
||||||
|
}
|
||||||
double posX=(canvasW/2.0)+(sin(double(i)*0.5+double(aboutScroll)/(90.0*dpiScale))*120*dpiScale)-(ImGui::CalcTextSize(nextLine).x*0.5);
|
double posX=(canvasW/2.0)+(sin(double(i)*0.5+double(aboutScroll)/(90.0*dpiScale))*120*dpiScale)-(ImGui::CalcTextSize(nextLine).x*0.5);
|
||||||
double posY=(canvasH-aboutScroll+42*i*dpiScale);
|
double posY=(canvasH-aboutScroll+42*i*dpiScale);
|
||||||
if (posY<-80*dpiScale || posY>canvasH) continue;
|
if (posY<-80*dpiScale || posY>canvasH) continue;
|
||||||
|
|
|
@ -224,6 +224,14 @@ void FurnaceGUI::finishSelection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::moveCursor(int x, int y, bool select) {
|
void FurnaceGUI::moveCursor(int x, int y, bool select) {
|
||||||
|
if (curEngineState==18) {
|
||||||
|
if ((rand()%120)==0) {
|
||||||
|
x=-x;
|
||||||
|
}
|
||||||
|
if ((rand()%120)==0) {
|
||||||
|
y=-y;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (y>=editStepCoarse || y<=-editStepCoarse || x<=-5 || x>=5) {
|
if (y>=editStepCoarse || y<=-editStepCoarse || x<=-5 || x>=5) {
|
||||||
makeCursorUndo();
|
makeCursorUndo();
|
||||||
}
|
}
|
||||||
|
@ -450,6 +458,9 @@ void FurnaceGUI::moveCursorBottom(bool select) {
|
||||||
void FurnaceGUI::editAdvance() {
|
void FurnaceGUI::editAdvance() {
|
||||||
finishSelection();
|
finishSelection();
|
||||||
cursor.y+=editStep;
|
cursor.y+=editStep;
|
||||||
|
if (curEngineState==18) {
|
||||||
|
if ((rand()%180)==0) cursor.y=rand()&0xff;
|
||||||
|
}
|
||||||
if (cursor.y>=e->curSubSong->patLen) cursor.y=e->curSubSong->patLen-1;
|
if (cursor.y>=e->curSubSong->patLen) cursor.y=e->curSubSong->patLen-1;
|
||||||
selStart=cursor;
|
selStart=cursor;
|
||||||
selEnd=cursor;
|
selEnd=cursor;
|
||||||
|
|
|
@ -32,6 +32,12 @@ const unsigned char avRequest[15]={
|
||||||
|
|
||||||
|
|
||||||
void FurnaceGUI::doAction(int what) {
|
void FurnaceGUI::doAction(int what) {
|
||||||
|
if (curEngineState==8 || curEngineState==13 || curEngineState==23) {
|
||||||
|
if ((rand()%1000)==0) {
|
||||||
|
showError("I don't wanna");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
switch (what) {
|
switch (what) {
|
||||||
case GUI_ACTION_NEW:
|
case GUI_ACTION_NEW:
|
||||||
if (modified) {
|
if (modified) {
|
||||||
|
|
251
src/gui/gui.cpp
251
src/gui/gui.cpp
|
@ -1200,6 +1200,7 @@ void FurnaceGUI::play(int row) {
|
||||||
curNibble=false;
|
curNibble=false;
|
||||||
orderNibble=false;
|
orderNibble=false;
|
||||||
activeNotes.clear();
|
activeNotes.clear();
|
||||||
|
fullView=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::setOrder(unsigned char order, bool forced) {
|
void FurnaceGUI::setOrder(unsigned char order, bool forced) {
|
||||||
|
@ -1225,6 +1226,15 @@ void FurnaceGUI::stop() {
|
||||||
}
|
}
|
||||||
updateScroll(cursor.y);
|
updateScroll(cursor.y);
|
||||||
}
|
}
|
||||||
|
if (curEngineState==9) {
|
||||||
|
if ((rand()%40)==0) {
|
||||||
|
fullView=true;
|
||||||
|
} else {
|
||||||
|
fullView=false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fullView=false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::previewNote(int refChan, int note, bool autoNote) {
|
void FurnaceGUI::previewNote(int refChan, int note, bool autoNote) {
|
||||||
|
@ -1328,6 +1338,12 @@ void FurnaceGUI::noteInput(int num, int key, int vol) {
|
||||||
makeUndo(GUI_UNDO_PATTERN_EDIT);
|
makeUndo(GUI_UNDO_PATTERN_EDIT);
|
||||||
editAdvance();
|
editAdvance();
|
||||||
curNibble=false;
|
curNibble=false;
|
||||||
|
|
||||||
|
if (curEngineState==19) {
|
||||||
|
if ((rand()%300)==0) {
|
||||||
|
displayRating=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::valueInput(int num, bool direct, int target) {
|
void FurnaceGUI::valueInput(int num, bool direct, int target) {
|
||||||
|
@ -2373,6 +2389,210 @@ int FurnaceGUI::save(String path, int dmfVersion) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const signed char kickPos[]={
|
||||||
|
0, 6, 10, -1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const signed char snarePos[]={
|
||||||
|
4, 12, -1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const signed char timpaniPos[]={
|
||||||
|
8, 14, -1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const signed char clapPos[]={
|
||||||
|
2, -1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const signed char chatPos[]={
|
||||||
|
0, 1, 3, 8, 9, 11, -1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const signed char ohatPos[]={
|
||||||
|
2, 10, -1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const signed char bongoPos[]={
|
||||||
|
4, 5, 6, 7, 12, 13, 14, 15, -1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const signed char bongoNotes[4]={
|
||||||
|
4, 1, 5, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const signed char bongoOctaves[4]={
|
||||||
|
4, 4, 3, 4
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* kickNames[]={
|
||||||
|
"kick", "kikc", "kik", "bd", "bass d", "bassd", NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* snareNames[]={
|
||||||
|
"snar", "snor", "snr", "sd", "sho", "gun", NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* clapNames[]={
|
||||||
|
"clap", "clav", "hall", "click", "cow", NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* timpaniNames[]={
|
||||||
|
"timp", "tom", "crash", "kettle", NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* chatNames[]={
|
||||||
|
"close", "hat", "hhc", "chh", "hh", "short", NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* ohatNames[]={
|
||||||
|
"open", "hop", "hho", "ohh", "hh", "ride", "long", "hat", NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* bongoNames[]={
|
||||||
|
"bong", "rim", "cong", "tom", "pop", NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ASS_FIND_INS(names,id,ch,off) { \
|
||||||
|
bool nameFound=false; \
|
||||||
|
for (int _n=0; names[_n]; _n++) { \
|
||||||
|
const char* name=names[_n]; \
|
||||||
|
for (size_t _i=0; _i<e->song.ins.size(); _i++) { \
|
||||||
|
String insName=e->song.ins[_i]->name; \
|
||||||
|
for (char& i: insName) { \
|
||||||
|
if (i>='A' && i<='Z') i+='a'-'A'; \
|
||||||
|
} \
|
||||||
|
if (insName.find(name)!=String::npos) { \
|
||||||
|
id=_i; \
|
||||||
|
nameFound=true; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if (nameFound) break; \
|
||||||
|
} \
|
||||||
|
if (!nameFound) { \
|
||||||
|
if (e->song.ins.size()>0) { \
|
||||||
|
id=rand()%e->song.ins.size(); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if (id>=0) { \
|
||||||
|
bool skip=off; \
|
||||||
|
for (int _i=0; _i<e->getTotalChannelCount(); _i++) { \
|
||||||
|
DivInstrumentType pref1=e->getPreferInsType(_i); \
|
||||||
|
DivInstrumentType pref2=e->getPreferInsSecondType(_i); \
|
||||||
|
DivInstrumentType have=e->song.ins[id]->type; \
|
||||||
|
if (have==pref1 || have==pref2) { \
|
||||||
|
if (skip) { \
|
||||||
|
skip=false; \
|
||||||
|
} else { \
|
||||||
|
ch=_i; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FurnaceGUI::updateProperties() {
|
||||||
|
if (curEngineState==0 || curEngineState==5 || curEngineState==20) {
|
||||||
|
if ((rand()%30)==0) {
|
||||||
|
e->curSubSong->ordersLen=1;
|
||||||
|
e->curSubSong->patLen=16;
|
||||||
|
e->curSubSong->speeds.val[0]=6;
|
||||||
|
e->curSubSong->speeds.len=1;
|
||||||
|
e->curSubSong->virtualTempoD=150;
|
||||||
|
e->curSubSong->virtualTempoN=150;
|
||||||
|
int kickID=-1;
|
||||||
|
int clapID=-1;
|
||||||
|
int snareID=-1;
|
||||||
|
int timpaniID=-1;
|
||||||
|
int chatID=-1;
|
||||||
|
int ohatID=-1;
|
||||||
|
int bongoID=-1;
|
||||||
|
int kickCh=0;
|
||||||
|
int clapCh=0;
|
||||||
|
int snareCh=0;
|
||||||
|
int timpaniCh=0;
|
||||||
|
int chatCh=1;
|
||||||
|
int ohatCh=1;
|
||||||
|
int bongoCh=1;
|
||||||
|
|
||||||
|
// find instruments
|
||||||
|
ASS_FIND_INS(kickNames,kickID,kickCh,0);
|
||||||
|
ASS_FIND_INS(snareNames,snareID,snareCh,0);
|
||||||
|
ASS_FIND_INS(clapNames,clapID,clapCh,0);
|
||||||
|
ASS_FIND_INS(timpaniNames,timpaniID,timpaniCh,0);
|
||||||
|
ASS_FIND_INS(chatNames,chatID,chatCh,1);
|
||||||
|
ASS_FIND_INS(ohatNames,ohatID,ohatCh,1);
|
||||||
|
ASS_FIND_INS(bongoNames,bongoID,bongoCh,1);
|
||||||
|
|
||||||
|
// prepare song
|
||||||
|
for (int i=0; i<e->getTotalChannelCount(); i++) {
|
||||||
|
e->curSubSong->orders.ord[i][0]=0;
|
||||||
|
e->curSubSong->pat[i].getPattern(0,true)->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// place kicks
|
||||||
|
for (int i=0; kickPos[i]>=0; i++) {
|
||||||
|
DivPattern* p=e->curSubSong->pat[kickCh].getPattern(0,true);
|
||||||
|
int kp=kickPos[i];
|
||||||
|
p->data[kp][0]=12;
|
||||||
|
p->data[kp][1]=3;
|
||||||
|
p->data[kp][2]=kickID;
|
||||||
|
}
|
||||||
|
// place claps
|
||||||
|
for (int i=0; clapPos[i]>=0; i++) {
|
||||||
|
DivPattern* p=e->curSubSong->pat[clapCh].getPattern(0,true);
|
||||||
|
int kp=clapPos[i];
|
||||||
|
p->data[kp][0]=12;
|
||||||
|
p->data[kp][1]=3;
|
||||||
|
p->data[kp][2]=clapID;
|
||||||
|
}
|
||||||
|
// place snares
|
||||||
|
for (int i=0; snarePos[i]>=0; i++) {
|
||||||
|
DivPattern* p=e->curSubSong->pat[snareCh].getPattern(0,true);
|
||||||
|
int kp=snarePos[i];
|
||||||
|
p->data[kp][0]=12;
|
||||||
|
p->data[kp][1]=3;
|
||||||
|
p->data[kp][2]=snareID;
|
||||||
|
}
|
||||||
|
// place timpani
|
||||||
|
for (int i=0; timpaniPos[i]>=0; i++) {
|
||||||
|
DivPattern* p=e->curSubSong->pat[timpaniCh].getPattern(0,true);
|
||||||
|
int kp=timpaniPos[i];
|
||||||
|
p->data[kp][0]=12;
|
||||||
|
p->data[kp][1]=3;
|
||||||
|
p->data[kp][2]=timpaniID;
|
||||||
|
}
|
||||||
|
// place chats
|
||||||
|
for (int i=0; chatPos[i]>=0; i++) {
|
||||||
|
DivPattern* p=e->curSubSong->pat[chatCh].getPattern(0,true);
|
||||||
|
int kp=chatPos[i];
|
||||||
|
p->data[kp][0]=12;
|
||||||
|
p->data[kp][1]=3;
|
||||||
|
p->data[kp][2]=chatID;
|
||||||
|
}
|
||||||
|
// place ohats
|
||||||
|
for (int i=0; ohatPos[i]>=0; i++) {
|
||||||
|
DivPattern* p=e->curSubSong->pat[ohatCh].getPattern(0,true);
|
||||||
|
int kp=ohatPos[i];
|
||||||
|
p->data[kp][0]=12;
|
||||||
|
p->data[kp][1]=3;
|
||||||
|
p->data[kp][2]=ohatID;
|
||||||
|
}
|
||||||
|
// place bongo
|
||||||
|
for (int i=0; bongoPos[i]>=0; i++) {
|
||||||
|
DivPattern* p=e->curSubSong->pat[bongoCh].getPattern(0,true);
|
||||||
|
int kp=bongoPos[i];
|
||||||
|
p->data[kp][0]=bongoNotes[kp&3];
|
||||||
|
p->data[kp][1]=bongoOctaves[kp&3];
|
||||||
|
p->data[kp][2]=bongoID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int FurnaceGUI::load(String path) {
|
int FurnaceGUI::load(String path) {
|
||||||
bool wasPlaying=e->isPlaying();
|
bool wasPlaying=e->isPlaying();
|
||||||
if (!path.empty()) {
|
if (!path.empty()) {
|
||||||
|
@ -2428,6 +2648,7 @@ int FurnaceGUI::load(String path) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
updateProperties();
|
||||||
backupLock.lock();
|
backupLock.lock();
|
||||||
curFileName=path;
|
curFileName=path;
|
||||||
backupLock.unlock();
|
backupLock.unlock();
|
||||||
|
@ -3758,6 +3979,8 @@ bool FurnaceGUI::loop() {
|
||||||
if (settings.powerSave) SDL_WaitEventTimeout(NULL,500);
|
if (settings.powerSave) SDL_WaitEventTimeout(NULL,500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateState();
|
||||||
|
|
||||||
memcpy(perfMetricsLast,perfMetrics,64*sizeof(FurnaceGUIPerfMetric));
|
memcpy(perfMetricsLast,perfMetrics,64*sizeof(FurnaceGUIPerfMetric));
|
||||||
perfMetricsLastLen=perfMetricsLen;
|
perfMetricsLastLen=perfMetricsLen;
|
||||||
perfMetricsLen=0;
|
perfMetricsLen=0;
|
||||||
|
@ -4460,6 +4683,16 @@ bool FurnaceGUI::loop() {
|
||||||
openFileDialog(GUI_FILE_SAVE);
|
openFileDialog(GUI_FILE_SAVE);
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
if (curEngineState==15) {
|
||||||
|
if (ImGui::MenuItem(_("import MIDI..."))) {
|
||||||
|
if ((rand()%5)==0) {
|
||||||
|
showError("what makes you think there is MIDI import?");
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
}
|
||||||
if (settings.exportOptionsLayout==0) {
|
if (settings.exportOptionsLayout==0) {
|
||||||
if (ImGui::BeginMenu(_("export audio..."))) {
|
if (ImGui::BeginMenu(_("export audio..."))) {
|
||||||
drawExportAudio();
|
drawExportAudio();
|
||||||
|
@ -5846,6 +6079,11 @@ bool FurnaceGUI::loop() {
|
||||||
ImGui::OpenPopup(_("ROM Export Progress"));
|
ImGui::OpenPopup(_("ROM Export Progress"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (displayRating) {
|
||||||
|
displayRating=false;
|
||||||
|
ImGui::OpenPopup(_("Furnace###BeatRating"));
|
||||||
|
}
|
||||||
|
|
||||||
if (displayNew) {
|
if (displayNew) {
|
||||||
newSongQuery="";
|
newSongQuery="";
|
||||||
newSongFirstFrame=true;
|
newSongFirstFrame=true;
|
||||||
|
@ -6072,6 +6310,17 @@ bool FurnaceGUI::loop() {
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
centerNextWindow(_("Furnace###BeatRating"),canvasW,canvasH);
|
||||||
|
if (ImGui::BeginPopupModal("Furnace###BeatRating",NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
|
stop();
|
||||||
|
ImGui::TextUnformatted(_("This beat is ass. Session terminated."));
|
||||||
|
if (ImGui::Button(_("OK"))) {
|
||||||
|
quit=true;
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
centerNextWindow(_("Error"),canvasW,canvasH);
|
centerNextWindow(_("Error"),canvasW,canvasH);
|
||||||
if (ImGui::BeginPopupModal(_("Error"),NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
|
if (ImGui::BeginPopupModal(_("Error"),NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
ImGui::Text(_("%s"),errorString.c_str());
|
ImGui::Text(_("%s"),errorString.c_str());
|
||||||
|
@ -8376,12 +8625,14 @@ FurnaceGUI::FurnaceGUI():
|
||||||
displayPendingSamples(false),
|
displayPendingSamples(false),
|
||||||
replacePendingSample(false),
|
replacePendingSample(false),
|
||||||
displayExportingROM(false),
|
displayExportingROM(false),
|
||||||
|
displayRating(false),
|
||||||
changeCoarse(false),
|
changeCoarse(false),
|
||||||
mobileEdit(false),
|
mobileEdit(false),
|
||||||
killGraphics(false),
|
killGraphics(false),
|
||||||
safeMode(false),
|
safeMode(false),
|
||||||
midiWakeUp(true),
|
midiWakeUp(true),
|
||||||
makeDrumkitMode(false),
|
makeDrumkitMode(false),
|
||||||
|
fullView(false),
|
||||||
audioEngineChanged(false),
|
audioEngineChanged(false),
|
||||||
settingsChanged(false),
|
settingsChanged(false),
|
||||||
debugFFT(false),
|
debugFFT(false),
|
||||||
|
|
|
@ -1664,12 +1664,14 @@ class FurnaceGUI {
|
||||||
bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString;
|
bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString;
|
||||||
bool displayPendingSamples, replacePendingSample;
|
bool displayPendingSamples, replacePendingSample;
|
||||||
bool displayExportingROM;
|
bool displayExportingROM;
|
||||||
|
bool displayRating;
|
||||||
bool changeCoarse;
|
bool changeCoarse;
|
||||||
bool mobileEdit;
|
bool mobileEdit;
|
||||||
bool killGraphics;
|
bool killGraphics;
|
||||||
bool safeMode;
|
bool safeMode;
|
||||||
bool midiWakeUp;
|
bool midiWakeUp;
|
||||||
bool makeDrumkitMode;
|
bool makeDrumkitMode;
|
||||||
|
bool fullView;
|
||||||
bool audioEngineChanged, settingsChanged, debugFFT;
|
bool audioEngineChanged, settingsChanged, debugFFT;
|
||||||
bool willExport[DIV_MAX_CHIPS];
|
bool willExport[DIV_MAX_CHIPS];
|
||||||
int vgmExportVersion;
|
int vgmExportVersion;
|
||||||
|
@ -2943,6 +2945,8 @@ class FurnaceGUI {
|
||||||
void commitTutorial();
|
void commitTutorial();
|
||||||
void syncState();
|
void syncState();
|
||||||
void commitState(DivConfig& conf);
|
void commitState(DivConfig& conf);
|
||||||
|
void updateState();
|
||||||
|
void updateProperties();
|
||||||
void processDrags(int dragX, int dragY);
|
void processDrags(int dragX, int dragY);
|
||||||
void processPoint(SDL_Event& ev);
|
void processPoint(SDL_Event& ev);
|
||||||
|
|
||||||
|
|
|
@ -1943,6 +1943,30 @@ inline bool enBit30(const int val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FurnaceGUI::updateState() {
|
||||||
|
time_t thisMakesNoSense=time(NULL);
|
||||||
|
struct tm curTime;
|
||||||
|
#ifdef _WIN32
|
||||||
|
struct tm* tempTM=localtime(&thisMakesNoSense);
|
||||||
|
if (tempTM!=NULL) {
|
||||||
|
memcpy(&curTime,tempTM,sizeof(struct tm));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (localtime_r(&thisMakesNoSense,&curTime)==NULL) {
|
||||||
|
memset(&curTime,0,sizeof(struct tm));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (curTime.tm_year==125) {
|
||||||
|
if (curTime.tm_mon==2 && curTime.tm_mday==31 && curTime.tm_hour>=23) {
|
||||||
|
curEngineState=curTime.tm_hour;
|
||||||
|
} else if (curTime.tm_mon==3 && curTime.tm_mday==1) {
|
||||||
|
curEngineState=curTime.tm_hour;
|
||||||
|
} else if (curTime.tm_mon==3 && curTime.tm_mday==2 && curTime.tm_hour<6) {
|
||||||
|
curEngineState=curTime.tm_hour;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FurnaceGUI::kvsConfig(DivInstrument* ins, bool supportsKVS) {
|
void FurnaceGUI::kvsConfig(DivInstrument* ins, bool supportsKVS) {
|
||||||
if (fmPreviewOn) {
|
if (fmPreviewOn) {
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
|
|
|
@ -300,50 +300,23 @@ void FurnaceGUI::drawOsc() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((oscWidth-24)>0) {
|
if ((oscWidth-24)>0) {
|
||||||
if (settings.oscMono) {
|
if (!e->isPlaying() && fullView) {
|
||||||
if (rend->supportsDrawOsc() && settings.shaderOsc) {
|
ImVec2 point0=inRect.Min;
|
||||||
_do.gui=this;
|
ImVec2 point1=inRect.Max;
|
||||||
_do.data=&oscValuesAverage[12];
|
point0.y=0;
|
||||||
_do.len=oscWidth-24;
|
point1.y=canvasH;
|
||||||
_do.pos0=inRect.Min;
|
dl->PushClipRectFullScreen();
|
||||||
_do.pos1=inRect.Max;
|
dl->AddRectFilled(point0,point1,color,0,ImDrawFlags_None);
|
||||||
_do.color=isClipping?uiColors[GUI_COLOR_OSC_WAVE_PEAK]:uiColors[GUI_COLOR_OSC_WAVE];
|
dl->PopClipRect();
|
||||||
_do.lineSize=dpiScale*settings.oscLineSize;
|
|
||||||
|
|
||||||
dl->AddCallback(_drawOsc,&_do);
|
|
||||||
dl->AddCallback(ImDrawCallback_ResetRenderState,NULL);
|
|
||||||
} else {
|
|
||||||
for (int i=0; i<oscWidth-24; i++) {
|
|
||||||
float x=(float)i/(float)(oscWidth-24);
|
|
||||||
float y=oscValuesAverage[i+12]*0.5f;
|
|
||||||
if (!settings.oscEscapesBoundary) {
|
|
||||||
if (y<-0.5f) y=-0.5f;
|
|
||||||
if (y>0.5f) y=0.5f;
|
|
||||||
}
|
|
||||||
waveform[i]=ImLerp(inRect.Min,inRect.Max,ImVec2(x,0.5f-y));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings.oscEscapesBoundary) {
|
|
||||||
dl->PushClipRectFullScreen();
|
|
||||||
dl->AddPolyline(waveform,oscWidth-24,color,ImDrawFlags_None,dpiScale*settings.oscLineSize);
|
|
||||||
dl->PopClipRect();
|
|
||||||
} else {
|
|
||||||
dl->AddPolyline(waveform,oscWidth-24,color,ImDrawFlags_None,dpiScale*settings.oscLineSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for (int ch=0; ch<e->getAudioDescGot().outChans; ch++) {
|
if (settings.oscMono) {
|
||||||
if (!isClipping) {
|
|
||||||
color=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_WAVE_CH0+ch]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rend->supportsDrawOsc() && settings.shaderOsc) {
|
if (rend->supportsDrawOsc() && settings.shaderOsc) {
|
||||||
_do.gui=this;
|
_do.gui=this;
|
||||||
_do.data=&oscValues[ch][12];
|
_do.data=&oscValuesAverage[12];
|
||||||
_do.len=oscWidth-24;
|
_do.len=oscWidth-24;
|
||||||
_do.pos0=inRect.Min;
|
_do.pos0=inRect.Min;
|
||||||
_do.pos1=inRect.Max;
|
_do.pos1=inRect.Max;
|
||||||
_do.color=isClipping?uiColors[GUI_COLOR_OSC_WAVE_PEAK]:uiColors[GUI_COLOR_OSC_WAVE_CH0+ch];
|
_do.color=isClipping?uiColors[GUI_COLOR_OSC_WAVE_PEAK]:uiColors[GUI_COLOR_OSC_WAVE];
|
||||||
_do.lineSize=dpiScale*settings.oscLineSize;
|
_do.lineSize=dpiScale*settings.oscLineSize;
|
||||||
|
|
||||||
dl->AddCallback(_drawOsc,&_do);
|
dl->AddCallback(_drawOsc,&_do);
|
||||||
|
@ -351,7 +324,7 @@ void FurnaceGUI::drawOsc() {
|
||||||
} else {
|
} else {
|
||||||
for (int i=0; i<oscWidth-24; i++) {
|
for (int i=0; i<oscWidth-24; i++) {
|
||||||
float x=(float)i/(float)(oscWidth-24);
|
float x=(float)i/(float)(oscWidth-24);
|
||||||
float y=oscValues[ch][i+12]*oscZoom;
|
float y=oscValuesAverage[i+12]*0.5f;
|
||||||
if (!settings.oscEscapesBoundary) {
|
if (!settings.oscEscapesBoundary) {
|
||||||
if (y<-0.5f) y=-0.5f;
|
if (y<-0.5f) y=-0.5f;
|
||||||
if (y>0.5f) y=0.5f;
|
if (y>0.5f) y=0.5f;
|
||||||
|
@ -359,7 +332,6 @@ void FurnaceGUI::drawOsc() {
|
||||||
waveform[i]=ImLerp(inRect.Min,inRect.Max,ImVec2(x,0.5f-y));
|
waveform[i]=ImLerp(inRect.Min,inRect.Max,ImVec2(x,0.5f-y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (settings.oscEscapesBoundary) {
|
if (settings.oscEscapesBoundary) {
|
||||||
dl->PushClipRectFullScreen();
|
dl->PushClipRectFullScreen();
|
||||||
dl->AddPolyline(waveform,oscWidth-24,color,ImDrawFlags_None,dpiScale*settings.oscLineSize);
|
dl->AddPolyline(waveform,oscWidth-24,color,ImDrawFlags_None,dpiScale*settings.oscLineSize);
|
||||||
|
@ -368,6 +340,44 @@ void FurnaceGUI::drawOsc() {
|
||||||
dl->AddPolyline(waveform,oscWidth-24,color,ImDrawFlags_None,dpiScale*settings.oscLineSize);
|
dl->AddPolyline(waveform,oscWidth-24,color,ImDrawFlags_None,dpiScale*settings.oscLineSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for (int ch=0; ch<e->getAudioDescGot().outChans; ch++) {
|
||||||
|
if (!isClipping) {
|
||||||
|
color=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_WAVE_CH0+ch]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rend->supportsDrawOsc() && settings.shaderOsc) {
|
||||||
|
_do.gui=this;
|
||||||
|
_do.data=&oscValues[ch][12];
|
||||||
|
_do.len=oscWidth-24;
|
||||||
|
_do.pos0=inRect.Min;
|
||||||
|
_do.pos1=inRect.Max;
|
||||||
|
_do.color=isClipping?uiColors[GUI_COLOR_OSC_WAVE_PEAK]:uiColors[GUI_COLOR_OSC_WAVE_CH0+ch];
|
||||||
|
_do.lineSize=dpiScale*settings.oscLineSize;
|
||||||
|
|
||||||
|
dl->AddCallback(_drawOsc,&_do);
|
||||||
|
dl->AddCallback(ImDrawCallback_ResetRenderState,NULL);
|
||||||
|
} else {
|
||||||
|
for (int i=0; i<oscWidth-24; i++) {
|
||||||
|
float x=(float)i/(float)(oscWidth-24);
|
||||||
|
float y=oscValues[ch][i+12]*oscZoom;
|
||||||
|
if (!settings.oscEscapesBoundary) {
|
||||||
|
if (y<-0.5f) y=-0.5f;
|
||||||
|
if (y>0.5f) y=0.5f;
|
||||||
|
}
|
||||||
|
waveform[i]=ImLerp(inRect.Min,inRect.Max,ImVec2(x,0.5f-y));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (settings.oscEscapesBoundary) {
|
||||||
|
dl->PushClipRectFullScreen();
|
||||||
|
dl->AddPolyline(waveform,oscWidth-24,color,ImDrawFlags_None,dpiScale*settings.oscLineSize);
|
||||||
|
dl->PopClipRect();
|
||||||
|
} else {
|
||||||
|
dl->AddPolyline(waveform,oscWidth-24,color,ImDrawFlags_None,dpiScale*settings.oscLineSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7188,5 +7188,20 @@ void FurnaceGUI::applyUISettings(bool updateFonts) {
|
||||||
fileDialog=new FurnaceGUIFileDialog(settings.sysFileDialog);
|
fileDialog=new FurnaceGUIFileDialog(settings.sysFileDialog);
|
||||||
|
|
||||||
fileDialog->mobileUI=mobileUI;
|
fileDialog->mobileUI=mobileUI;
|
||||||
|
|
||||||
|
if (curEngineState==10) {
|
||||||
|
if ((rand()%10)==0) {
|
||||||
|
for (int i=0; i<ImGuiCol_COUNT; i++) {
|
||||||
|
ImGui::GetStyle().Colors[i]=ImVec4((float)(rand()%256)/256.0f,(float)(rand()%256)/256.0f,(float)(rand()%256)/256.0f,(float)(rand()%256)/256.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (curEngineState==12) {
|
||||||
|
for (int i=0; i<ImGuiCol_COUNT; i++) {
|
||||||
|
|
||||||
|
ImGui::GetStyle().Colors[i]=ImVec4(0,0,0,1);
|
||||||
|
}
|
||||||
|
ImGui::GetStyle().Colors[ImGuiCol_Text]=ImVec4(1,1,1,1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,8 +96,8 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msw) {
|
if (msw || curEngineState==6 || curEngineState==16) {
|
||||||
if (ImGui::Checkbox(_("Modified sine wave (joke)"),&msw)) {
|
if (ImGui::Checkbox(_("Modified sine wave"),&msw)) {
|
||||||
altered=true;
|
altered=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ enum FurnaceCVObjectTypes {
|
||||||
CV_MINE,
|
CV_MINE,
|
||||||
CV_POWERUP_P,
|
CV_POWERUP_P,
|
||||||
CV_POWERUP_S,
|
CV_POWERUP_S,
|
||||||
|
CV_SPECIAL,
|
||||||
CV_MOD_I,
|
CV_MOD_I,
|
||||||
CV_MOD_S,
|
CV_MOD_S,
|
||||||
CV_EXTRA_LIFE
|
CV_EXTRA_LIFE
|
||||||
|
@ -79,6 +80,7 @@ struct FurnaceCVObject {
|
||||||
short x, y;
|
short x, y;
|
||||||
unsigned char z, prio;
|
unsigned char z, prio;
|
||||||
short collX0, collX1, collY0, collY1;
|
short collX0, collX1, collY0, collY1;
|
||||||
|
short frozen;
|
||||||
|
|
||||||
virtual void collision(FurnaceCVObject* other);
|
virtual void collision(FurnaceCVObject* other);
|
||||||
virtual void tick();
|
virtual void tick();
|
||||||
|
@ -95,7 +97,8 @@ struct FurnaceCVObject {
|
||||||
collX0(0),
|
collX0(0),
|
||||||
collX1(15),
|
collX1(15),
|
||||||
collY0(0),
|
collY0(0),
|
||||||
collY1(15) {
|
collY1(15),
|
||||||
|
frozen(0) {
|
||||||
memset(spriteDef,0,512*sizeof(unsigned short));
|
memset(spriteDef,0,512*sizeof(unsigned short));
|
||||||
spriteDef[0]=4;
|
spriteDef[0]=4;
|
||||||
spriteDef[1]=5;
|
spriteDef[1]=5;
|
||||||
|
@ -112,6 +115,24 @@ void FurnaceCVObject::collision(FurnaceCVObject* other) {
|
||||||
void FurnaceCVObject::tick() {
|
void FurnaceCVObject::tick() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// special types:
|
||||||
|
// - 0: nothing
|
||||||
|
// - 1: "?" one of the following:
|
||||||
|
// - 10/30: spawn more enemies
|
||||||
|
// - 4/30: downgrades enemies
|
||||||
|
// - 3/30: teleports you
|
||||||
|
// - 3/30: stops all enemies (momentarily)
|
||||||
|
// - 3/30: grants speed and invincible status
|
||||||
|
// - 2/30: spawn purple tanks
|
||||||
|
// - 2/30: spawn vortices
|
||||||
|
// - 1/30: skip to next level
|
||||||
|
// - 1/30: 5-up
|
||||||
|
// - 1/30: call planes
|
||||||
|
// - 2: "T" teleports you
|
||||||
|
// - 3: "X" ripple shot
|
||||||
|
// - 4: "W" bidirectional shots (until next round)
|
||||||
|
// - 5: "S" stops all enemies for 10 seconds
|
||||||
|
|
||||||
struct FurnaceCV {
|
struct FurnaceCV {
|
||||||
SDL_Surface* surface;
|
SDL_Surface* surface;
|
||||||
unsigned char* prioBuf;
|
unsigned char* prioBuf;
|
||||||
|
@ -134,7 +155,7 @@ struct FurnaceCV {
|
||||||
int ticksToInit;
|
int ticksToInit;
|
||||||
|
|
||||||
bool inGame, inTransition, newHiScore, playSongs, pleaseInitSongs, gameOver;
|
bool inGame, inTransition, newHiScore, playSongs, pleaseInitSongs, gameOver;
|
||||||
unsigned char lives, respawnTime, stage, shotType, lifeBank;
|
unsigned char lives, respawnTime, stage, shotType, lifeBank, specialType;
|
||||||
int score;
|
int score;
|
||||||
int hiScore;
|
int hiScore;
|
||||||
short lastPlayerX, lastPlayerY;
|
short lastPlayerX, lastPlayerY;
|
||||||
|
@ -216,6 +237,7 @@ struct FurnaceCV {
|
||||||
stage(0),
|
stage(0),
|
||||||
shotType(0),
|
shotType(0),
|
||||||
lifeBank(0),
|
lifeBank(0),
|
||||||
|
specialType(0),
|
||||||
score(0),
|
score(0),
|
||||||
hiScore(25000),
|
hiScore(25000),
|
||||||
lastPlayerX(0),
|
lastPlayerX(0),
|
||||||
|
@ -249,6 +271,7 @@ struct FurnaceCVPlayer: FurnaceCVObject {
|
||||||
unsigned char animFrame;
|
unsigned char animFrame;
|
||||||
short invincible;
|
short invincible;
|
||||||
unsigned char shotTimer;
|
unsigned char shotTimer;
|
||||||
|
bool doubleShot;
|
||||||
|
|
||||||
void collision(FurnaceCVObject* other);
|
void collision(FurnaceCVObject* other);
|
||||||
void tick();
|
void tick();
|
||||||
|
@ -261,7 +284,8 @@ struct FurnaceCVPlayer: FurnaceCVObject {
|
||||||
shootDir(2),
|
shootDir(2),
|
||||||
animFrame(0),
|
animFrame(0),
|
||||||
invincible(120),
|
invincible(120),
|
||||||
shotTimer(4) {
|
shotTimer(4),
|
||||||
|
doubleShot(false) {
|
||||||
type=CV_PLAYER;
|
type=CV_PLAYER;
|
||||||
spriteWidth=3;
|
spriteWidth=3;
|
||||||
spriteHeight=3;
|
spriteHeight=3;
|
||||||
|
@ -336,11 +360,23 @@ struct FurnaceCVEnemyBullet: FurnaceCVObject {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FurnaceCVEnemy1: FurnaceCVObject {
|
struct FurnaceCVEnemy: FurnaceCVObject {
|
||||||
unsigned char enemyType;
|
unsigned char enemyType;
|
||||||
unsigned char health;
|
unsigned char health;
|
||||||
unsigned char orient;
|
|
||||||
unsigned char stopped;
|
unsigned char stopped;
|
||||||
|
|
||||||
|
void setType(unsigned char type);
|
||||||
|
FurnaceCVEnemy(FurnaceCV* p):
|
||||||
|
FurnaceCVObject(p),
|
||||||
|
enemyType(0),
|
||||||
|
health(1),
|
||||||
|
stopped(0) {
|
||||||
|
type=CV_ENEMY;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FurnaceCVEnemy1: FurnaceCVEnemy {
|
||||||
|
unsigned char orient;
|
||||||
unsigned char animFrame;
|
unsigned char animFrame;
|
||||||
short nextTime, shootTime;
|
short nextTime, shootTime;
|
||||||
unsigned char shootCooldown;
|
unsigned char shootCooldown;
|
||||||
|
@ -349,13 +385,9 @@ struct FurnaceCVEnemy1: FurnaceCVObject {
|
||||||
void collision(FurnaceCVObject* other);
|
void collision(FurnaceCVObject* other);
|
||||||
|
|
||||||
void tick();
|
void tick();
|
||||||
void setType(unsigned char type);
|
|
||||||
FurnaceCVEnemy1(FurnaceCV* p):
|
FurnaceCVEnemy1(FurnaceCV* p):
|
||||||
FurnaceCVObject(p),
|
FurnaceCVEnemy(p),
|
||||||
enemyType(0),
|
|
||||||
health(1),
|
|
||||||
orient(rand()&3),
|
orient(rand()&3),
|
||||||
stopped(0),
|
|
||||||
animFrame(0),
|
animFrame(0),
|
||||||
nextTime(64+(rand()%600)),
|
nextTime(64+(rand()%600)),
|
||||||
shootTime(8),
|
shootTime(8),
|
||||||
|
@ -369,8 +401,7 @@ struct FurnaceCVEnemy1: FurnaceCVObject {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FurnaceCVEnemyVortex: FurnaceCVObject {
|
struct FurnaceCVEnemyVortex: FurnaceCVEnemy {
|
||||||
unsigned char stopped;
|
|
||||||
unsigned char animFrame;
|
unsigned char animFrame;
|
||||||
short nextTime, shootTime, speedX, speedY;
|
short nextTime, shootTime, speedX, speedY;
|
||||||
|
|
||||||
|
@ -378,8 +409,7 @@ struct FurnaceCVEnemyVortex: FurnaceCVObject {
|
||||||
|
|
||||||
void tick();
|
void tick();
|
||||||
FurnaceCVEnemyVortex(FurnaceCV* p):
|
FurnaceCVEnemyVortex(FurnaceCV* p):
|
||||||
FurnaceCVObject(p),
|
FurnaceCVEnemy(p),
|
||||||
stopped(0),
|
|
||||||
animFrame(0),
|
animFrame(0),
|
||||||
nextTime(4+(rand()%140)),
|
nextTime(4+(rand()%140)),
|
||||||
shootTime(360),
|
shootTime(360),
|
||||||
|
@ -573,6 +603,19 @@ struct FurnaceCVPowerupS: FurnaceCVObject {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FurnaceCVSpecial: FurnaceCVObject {
|
||||||
|
unsigned char life;
|
||||||
|
unsigned char specialType;
|
||||||
|
void collision(FurnaceCVObject* other);
|
||||||
|
void tick();
|
||||||
|
FurnaceCVSpecial(FurnaceCV* p):
|
||||||
|
FurnaceCVObject(p),
|
||||||
|
life(255) {
|
||||||
|
type=CV_SPECIAL;
|
||||||
|
specialType=1+(rand()%5);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct FurnaceCVModI: FurnaceCVObject {
|
struct FurnaceCVModI: FurnaceCVObject {
|
||||||
unsigned char life;
|
unsigned char life;
|
||||||
void collision(FurnaceCVObject* other);
|
void collision(FurnaceCVObject* other);
|
||||||
|
@ -1348,7 +1391,7 @@ void FurnaceCV::buildStage(int which) {
|
||||||
createObject<FurnaceCVFurBallLarge>(finalX-4,finalY-4);
|
createObject<FurnaceCVFurBallLarge>(finalX-4,finalY-4);
|
||||||
enemy->setType(2);
|
enemy->setType(2);
|
||||||
if (which>7) {
|
if (which>7) {
|
||||||
enemy->setType((rand()%MAX(1,15-which))==0?3:2);
|
enemy->setType((rand()%MAX(3,17-which))==0?3:2);
|
||||||
}
|
}
|
||||||
busy[y][x]=true;
|
busy[y][x]=true;
|
||||||
busy[y][x+1]=true;
|
busy[y][x+1]=true;
|
||||||
|
@ -1392,7 +1435,11 @@ void FurnaceCV::buildStage(int which) {
|
||||||
FurnaceCVEnemy1* enemy=createObject<FurnaceCVEnemy1>(finalX,finalY);
|
FurnaceCVEnemy1* enemy=createObject<FurnaceCVEnemy1>(finalX,finalY);
|
||||||
createObject<FurnaceCVFurBallMedium>(finalX-4,finalY-4);
|
createObject<FurnaceCVFurBallMedium>(finalX-4,finalY-4);
|
||||||
if (which>0) {
|
if (which>0) {
|
||||||
enemy->setType((rand()%MAX(1,8-which))==0?1:0);
|
if (which>=20) {
|
||||||
|
enemy->setType(1);
|
||||||
|
} else {
|
||||||
|
enemy->setType((rand()%MAX(2,8-which))==0?1:0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
busy[y][x]=true;
|
busy[y][x]=true;
|
||||||
break;
|
break;
|
||||||
|
@ -1696,6 +1743,19 @@ void FurnaceCV::render(unsigned char joyIn) {
|
||||||
tile1[26][20]=0;
|
tile1[26][20]=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// special stat
|
||||||
|
if (specialType>0 && (tick&16)) {
|
||||||
|
tile1[24][2]=0x4dc+(((specialType-1)&1)<<1)+(((specialType-1)>>1)<<6);
|
||||||
|
tile1[24][3]=0x4dd+(((specialType-1)&1)<<1)+(((specialType-1)>>1)<<6);
|
||||||
|
tile1[25][2]=0x4fc+(((specialType-1)&1)<<1)+(((specialType-1)>>1)<<6);
|
||||||
|
tile1[25][3]=0x4fd+(((specialType-1)&1)<<1)+(((specialType-1)>>1)<<6);
|
||||||
|
} else {
|
||||||
|
tile1[24][2]=0;
|
||||||
|
tile1[24][3]=0;
|
||||||
|
tile1[25][2]=0;
|
||||||
|
tile1[25][3]=0;
|
||||||
|
}
|
||||||
|
|
||||||
// S mod stat
|
// S mod stat
|
||||||
if (speedTicks>0) {
|
if (speedTicks>0) {
|
||||||
speedTicks--;
|
speedTicks--;
|
||||||
|
@ -1953,6 +2013,7 @@ void FurnaceCVPlayer::collision(FurnaceCVObject* other) {
|
||||||
cv->speedTicks=0;
|
cv->speedTicks=0;
|
||||||
cv->e->setSongRate(cv->origSongRate);
|
cv->e->setSongRate(cv->origSongRate);
|
||||||
cv->respawnTime=48;
|
cv->respawnTime=48;
|
||||||
|
cv->specialType=0;
|
||||||
if (cv->weaponStack.empty()) {
|
if (cv->weaponStack.empty()) {
|
||||||
cv->shotType=0;
|
cv->shotType=0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2080,7 +2141,9 @@ void FurnaceCVPlayer::tick() {
|
||||||
} else {
|
} else {
|
||||||
cv->soundEffect(SE_SHOT1);
|
cv->soundEffect(SE_SHOT1);
|
||||||
}
|
}
|
||||||
FurnaceCVBullet* b=cv->createObject<FurnaceCVBullet>(x+shootDirOffsX[shootDir],y+shootDirOffsY[shootDir]);
|
FurnaceCVBullet* b;
|
||||||
|
|
||||||
|
b=cv->createObject<FurnaceCVBullet>(x+shootDirOffsX[shootDir],y+shootDirOffsY[shootDir]);
|
||||||
b->orient=shootDir;
|
b->orient=shootDir;
|
||||||
b->setType((cv->shotType==1)?1:0);
|
b->setType((cv->shotType==1)?1:0);
|
||||||
switch (shootDir) {
|
switch (shootDir) {
|
||||||
|
@ -2113,6 +2176,42 @@ void FurnaceCVPlayer::tick() {
|
||||||
b->speedY=0;
|
b->speedY=0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (doubleShot) {
|
||||||
|
b=cv->createObject<FurnaceCVBullet>(x+shootDirOffsX[((shootDir+4)&7)],y+shootDirOffsY[((shootDir+4)&7)]);
|
||||||
|
b->orient=((shootDir+4)&7);
|
||||||
|
b->setType((cv->shotType==1)?1:0);
|
||||||
|
switch (((shootDir+4)&7)) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 7:
|
||||||
|
b->speedX=160;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
b->speedX=-160;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
b->speedX=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (((shootDir+4)&7)) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
b->speedY=-160;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
b->speedY=160;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
b->speedY=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cv->joyInput&1) {
|
if (cv->joyInput&1) {
|
||||||
|
@ -2126,7 +2225,10 @@ void FurnaceCVPlayer::tick() {
|
||||||
} else {
|
} else {
|
||||||
cv->soundEffect(SE_SHOT1);
|
cv->soundEffect(SE_SHOT1);
|
||||||
}
|
}
|
||||||
FurnaceCVBullet* b=cv->createObject<FurnaceCVBullet>(x+shootDirOffsX[shootDir],y+shootDirOffsY[shootDir]);
|
|
||||||
|
FurnaceCVBullet* b;
|
||||||
|
|
||||||
|
b=cv->createObject<FurnaceCVBullet>(x+shootDirOffsX[shootDir],y+shootDirOffsY[shootDir]);
|
||||||
b->orient=shootDir;
|
b->orient=shootDir;
|
||||||
b->setType((cv->shotType==1)?1:0);
|
b->setType((cv->shotType==1)?1:0);
|
||||||
switch (shootDir) {
|
switch (shootDir) {
|
||||||
|
@ -2164,6 +2266,181 @@ void FurnaceCVPlayer::tick() {
|
||||||
b->speedX+=(rand()%64)-32;
|
b->speedX+=(rand()%64)-32;
|
||||||
b->speedY+=(rand()%64)-32;
|
b->speedY+=(rand()%64)-32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (doubleShot) {
|
||||||
|
b=cv->createObject<FurnaceCVBullet>(x+shootDirOffsX[((shootDir+4)&7)],y+shootDirOffsY[((shootDir+4)&7)]);
|
||||||
|
b->orient=((shootDir+4)&7);
|
||||||
|
b->setType((cv->shotType==1)?1:0);
|
||||||
|
switch (((shootDir+4)&7)) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 7:
|
||||||
|
b->speedX=160;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
b->speedX=-160;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
b->speedX=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (((shootDir+4)&7)) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
b->speedY=-160;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
b->speedY=160;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
b->speedY=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cv->shotType==2) {
|
||||||
|
b->speedX+=(rand()%64)-32;
|
||||||
|
b->speedY+=(rand()%64)-32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cv->joyPressed&2) {
|
||||||
|
if (cv->specialType>0) {
|
||||||
|
switch (cv->specialType) {
|
||||||
|
case 1: // ?
|
||||||
|
switch (rand()%30) {
|
||||||
|
case 0: case 1: case 2: case 3: case 4:
|
||||||
|
case 5: case 6: case 7: case 8: case 9: // spawn enemies
|
||||||
|
for (int i=0; i<10; i++) {
|
||||||
|
FurnaceCVEnemy1* obj=cv->createObject<FurnaceCVEnemy1>((rand()%(cv->stageWidth-4))<<3,(rand()%(cv->stageHeight-4))<<3);
|
||||||
|
obj->setType(rand()%2);
|
||||||
|
}
|
||||||
|
invincible+=60;
|
||||||
|
cv->soundEffect(SE_DEATH_C1);
|
||||||
|
break;
|
||||||
|
case 10: case 11: case 12: case 13: // downgrade enemies
|
||||||
|
for (FurnaceCVObject* i: cv->sprite) {
|
||||||
|
if (i->type==CV_ENEMY) {
|
||||||
|
if (((FurnaceCVEnemy*)i)->enemyType>0) {
|
||||||
|
if (((FurnaceCVEnemy*)i)->enemyType>1) {
|
||||||
|
cv->createObject<FurnaceCVFurBallLarge>(i->x-4,i->y-4);
|
||||||
|
} else {
|
||||||
|
cv->createObject<FurnaceCVFurBallMedium>(i->x-4,i->y-4);
|
||||||
|
}
|
||||||
|
if (((FurnaceCVEnemy*)i)->enemyType==2) {
|
||||||
|
i->x+=8;
|
||||||
|
i->y+=8;
|
||||||
|
}
|
||||||
|
((FurnaceCVEnemy*)i)->setType(((FurnaceCVEnemy*)i)->enemyType-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cv->soundEffect(SE_EXPL2);
|
||||||
|
break;
|
||||||
|
case 14: case 15: case 16: // teleport
|
||||||
|
cv->createObject<FurnaceCVFurBallLarge>(x-4,y-4);
|
||||||
|
invincible=120;
|
||||||
|
x=(rand()%(cv->stageWidth-2))<<3;
|
||||||
|
y=(rand()%(cv->stageHeight-2))<<3;
|
||||||
|
cv->createObject<FurnaceCVFurBallLarge>(x-4,y-4);
|
||||||
|
cv->soundEffect(SE_INIT);
|
||||||
|
for (FurnaceCVObject* i: cv->sprite) {
|
||||||
|
if (i->type==CV_ENEMY_BULLET) {
|
||||||
|
i->dead=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 17: case 18: case 19: // stop enemies
|
||||||
|
for (FurnaceCVObject* i: cv->sprite) {
|
||||||
|
if (i->type==CV_ENEMY) {
|
||||||
|
((FurnaceCVEnemy*)i)->stopped=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cv->soundEffect(SE_TIMEUP);
|
||||||
|
break;
|
||||||
|
case 20: case 21: case 22: // speed + invincible
|
||||||
|
invincible=600;
|
||||||
|
cv->speedTicks=900;
|
||||||
|
cv->soundEffect(SE_PICKUP3);
|
||||||
|
break;
|
||||||
|
case 23: case 24: // purple tank
|
||||||
|
for (int i=0; i<6; i++) {
|
||||||
|
FurnaceCVEnemy1* obj=cv->createObject<FurnaceCVEnemy1>((rand()%(cv->stageWidth-3))<<3,(rand()%(cv->stageHeight-3))<<3);
|
||||||
|
obj->setType(3);
|
||||||
|
}
|
||||||
|
invincible+=60;
|
||||||
|
cv->soundEffect(SE_DEATH_C1);
|
||||||
|
break;
|
||||||
|
case 25: case 26: // vortex
|
||||||
|
for (int i=0; i<12; i++) {
|
||||||
|
cv->createObject<FurnaceCVEnemyVortex>((rand()%(cv->stageWidth-2))<<3,(rand()%(cv->stageHeight-2))<<3);
|
||||||
|
}
|
||||||
|
invincible+=60;
|
||||||
|
cv->soundEffect(SE_DEATH_C1);
|
||||||
|
break;
|
||||||
|
case 27: // next level
|
||||||
|
for (FurnaceCVObject* i: cv->sprite) {
|
||||||
|
if (i->type==CV_ENEMY) {
|
||||||
|
i->dead=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 28: // 5-up
|
||||||
|
cv->soundEffect(SE_PICKUP1);
|
||||||
|
cv->lives+=5;
|
||||||
|
break;
|
||||||
|
case 29: // plane
|
||||||
|
for (int i=0; i<6; i++) {
|
||||||
|
cv->createObjectNoPos<FurnaceCVEnemyPlane>();
|
||||||
|
}
|
||||||
|
cv->soundEffect(SE_TIMEUP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: // T
|
||||||
|
cv->createObject<FurnaceCVFurBallLarge>(x-4,y-4);
|
||||||
|
invincible=120;
|
||||||
|
x=(rand()%(cv->stageWidth-2))<<3;
|
||||||
|
y=(rand()%(cv->stageHeight-2))<<3;
|
||||||
|
cv->createObject<FurnaceCVFurBallLarge>(x-4,y-4);
|
||||||
|
cv->soundEffect(SE_INIT);
|
||||||
|
for (FurnaceCVObject* i: cv->sprite) {
|
||||||
|
if (i->type==CV_ENEMY_BULLET) {
|
||||||
|
i->dead=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3: { // X
|
||||||
|
for (int i=0; i<64; i++) {
|
||||||
|
FurnaceCVBullet* b=cv->createObject<FurnaceCVBullet>(x+4,y+4);
|
||||||
|
b->orient=(-i>>3)&7;
|
||||||
|
b->setType(1);
|
||||||
|
b->speedX=120*cos(M_PI*((float)i/32.0));
|
||||||
|
b->speedY=120*sin(M_PI*((float)i/32.0));
|
||||||
|
}
|
||||||
|
cv->soundEffect(SE_SHOT2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: // W
|
||||||
|
doubleShot=true;
|
||||||
|
cv->soundEffect(SE_PICKUP3);
|
||||||
|
break;
|
||||||
|
case 5: // S
|
||||||
|
for (FurnaceCVObject* i: cv->sprite) {
|
||||||
|
if (i->type==CV_ENEMY) {
|
||||||
|
i->frozen=600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cv->soundEffect(SE_TIMEUP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cv->specialType=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2443,6 +2720,7 @@ void FurnaceCVEnemy1::collision(FurnaceCVObject* other) {
|
||||||
cv->createObject<FurnaceCVPowerupS>(x+(enemyType>=2?8:0),y+(enemyType>=2?8:0));
|
cv->createObject<FurnaceCVPowerupS>(x+(enemyType>=2?8:0),y+(enemyType>=2?8:0));
|
||||||
break;
|
break;
|
||||||
case 10: case 11: // special
|
case 10: case 11: // special
|
||||||
|
cv->createObject<FurnaceCVSpecial>(x+(enemyType>=2?8:0),y+(enemyType>=2?8:0));
|
||||||
break;
|
break;
|
||||||
case 12: // mod
|
case 12: // mod
|
||||||
cv->createObject<FurnaceCVModS>(x+(enemyType>=2?8:0),y+(enemyType>=2?8:0));
|
cv->createObject<FurnaceCVModS>(x+(enemyType>=2?8:0),y+(enemyType>=2?8:0));
|
||||||
|
@ -2496,6 +2774,10 @@ void FurnaceCVEnemy1::collision(FurnaceCVObject* other) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceCVEnemy1::tick() {
|
void FurnaceCVEnemy1::tick() {
|
||||||
|
if (frozen>0) {
|
||||||
|
if (--frozen>0) return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!stopped) {
|
if (!stopped) {
|
||||||
switch (orient) {
|
switch (orient) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -2663,7 +2945,7 @@ void FurnaceCVEnemy1::tick() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceCVEnemy1::setType(unsigned char t) {
|
void FurnaceCVEnemy::setType(unsigned char t) {
|
||||||
enemyType=t;
|
enemyType=t;
|
||||||
switch (enemyType) {
|
switch (enemyType) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -3307,6 +3589,33 @@ void FurnaceCVExtraLife::tick() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FurnaceCVSpecial IMPLEMENTATION
|
||||||
|
|
||||||
|
void FurnaceCVSpecial::collision(FurnaceCVObject* other) {
|
||||||
|
if (other->type==CV_PLAYER) {
|
||||||
|
dead=true;
|
||||||
|
cv->soundEffect(SE_PICKUP2);
|
||||||
|
cv->specialType=specialType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FurnaceCVSpecial::tick() {
|
||||||
|
if (--life==0) dead=true;
|
||||||
|
|
||||||
|
if (life>64 || (life&1)) {
|
||||||
|
spriteDef[0]=0x4dc+(((specialType-1)&1)<<1)+(((specialType-1)>>1)<<6);
|
||||||
|
spriteDef[1]=0x4dd+(((specialType-1)&1)<<1)+(((specialType-1)>>1)<<6);
|
||||||
|
spriteDef[2]=0x4fc+(((specialType-1)&1)<<1)+(((specialType-1)>>1)<<6);
|
||||||
|
spriteDef[3]=0x4fd+(((specialType-1)&1)<<1)+(((specialType-1)>>1)<<6);
|
||||||
|
} else {
|
||||||
|
spriteDef[0]=0;
|
||||||
|
spriteDef[1]=0;
|
||||||
|
spriteDef[2]=0;
|
||||||
|
spriteDef[3]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// FurnaceCVModI IMPLEMENTATION
|
// FurnaceCVModI IMPLEMENTATION
|
||||||
|
|
||||||
void FurnaceCVModI::collision(FurnaceCVObject* other) {
|
void FurnaceCVModI::collision(FurnaceCVObject* other) {
|
||||||
|
@ -3368,16 +3677,25 @@ void FurnaceCVEnemyVortex::collision(FurnaceCVObject* other) {
|
||||||
if (other->type==CV_BULLET || other->type==CV_PLAYER) {
|
if (other->type==CV_BULLET || other->type==CV_PLAYER) {
|
||||||
dead=true;
|
dead=true;
|
||||||
if ((rand()%2)==0) {
|
if ((rand()%2)==0) {
|
||||||
switch (rand()%10) {
|
switch (rand()%14) {
|
||||||
case 0:
|
case 0: // extra life
|
||||||
cv->createObject<FurnaceCVExtraLife>(x,y);
|
cv->createObject<FurnaceCVExtraLife>(x,y);
|
||||||
break;
|
break;
|
||||||
case 1: case 2: case 3: case 4:
|
case 1: case 2: case 3: case 4: // powerup
|
||||||
cv->createObject<FurnaceCVPowerupP>(x,y);
|
cv->createObject<FurnaceCVPowerupP>(x,y);
|
||||||
break;
|
break;
|
||||||
case 5: case 6: case 7: case 8: case 9:
|
case 5: case 6: case 7: case 8: case 9: // powerup
|
||||||
cv->createObject<FurnaceCVPowerupS>(x,y);
|
cv->createObject<FurnaceCVPowerupS>(x,y);
|
||||||
break;
|
break;
|
||||||
|
case 10: case 11: // special
|
||||||
|
cv->createObject<FurnaceCVSpecial>(x,y);
|
||||||
|
break;
|
||||||
|
case 12: // mod
|
||||||
|
cv->createObject<FurnaceCVModS>(x,y);
|
||||||
|
break;
|
||||||
|
case 13: // mod
|
||||||
|
cv->createObject<FurnaceCVModI>(x,y);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cv->soundEffect(SE_EXPL1);
|
cv->soundEffect(SE_EXPL1);
|
||||||
|
@ -3387,6 +3705,10 @@ void FurnaceCVEnemyVortex::collision(FurnaceCVObject* other) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceCVEnemyVortex::tick() {
|
void FurnaceCVEnemyVortex::tick() {
|
||||||
|
if (frozen>0) {
|
||||||
|
if (--frozen>0) return;
|
||||||
|
}
|
||||||
|
|
||||||
x+=speedX;
|
x+=speedX;
|
||||||
y+=speedY;
|
y+=speedY;
|
||||||
animFrame+=0x08;
|
animFrame+=0x08;
|
||||||
|
@ -3470,12 +3792,12 @@ void FurnaceCVEnemyPlane::tick() {
|
||||||
if (--shootTime<=0) {
|
if (--shootTime<=0) {
|
||||||
shootTime=28-(speed*2);
|
shootTime=28-(speed*2);
|
||||||
cv->soundEffect(SE_EXPL2);
|
cv->soundEffect(SE_EXPL2);
|
||||||
cv->createObject<FurnaceCVFurBallLarge>(x+(spriteWidth<<2),y+(spriteHeight<<2));
|
cv->createObject<FurnaceCVFurBallLarge>(x+(spriteWidth<<2)-16,y+(spriteHeight<<2)-16);
|
||||||
for (int i=0; i<14; i++) {
|
for (int i=0; i<14; i++) {
|
||||||
float fraction=(float)i/13.0f;
|
float fraction=(float)i/13.0f;
|
||||||
float xs=cos(fraction*M_PI*2.0)*28;
|
float xs=cos(fraction*M_PI*2.0)*28;
|
||||||
float ys=sin(fraction*M_PI*2.0)*28;
|
float ys=sin(fraction*M_PI*2.0)*28;
|
||||||
FurnaceCVEnemyBullet* b=cv->createObject<FurnaceCVEnemyBullet>(x+(spriteWidth<<2),y+(spriteHeight<<2));
|
FurnaceCVEnemyBullet* b=cv->createObject<FurnaceCVEnemyBullet>(x+(spriteWidth<<2)-4,y+(spriteHeight<<2)-4);
|
||||||
b->speedX=xs;
|
b->speedX=xs;
|
||||||
b->speedY=ys;
|
b->speedY=ys;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue