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
|
||||
- akumanatt
|
||||
- aloelucidity
|
||||
- ALTMUS
|
||||
- AmigaX
|
||||
- AquaDoesStuff
|
||||
- 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.
12
extern/backward/backward.hpp
vendored
12
extern/backward/backward.hpp
vendored
|
@ -24,6 +24,8 @@
|
|||
#ifndef H_6B9572DA_A64B_49E6_B234_051480991C89
|
||||
#define H_6B9572DA_A64B_49E6_B234_051480991C89
|
||||
|
||||
extern int curEngineState;
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error "It's not going to compile without a C++ compiler..."
|
||||
#endif
|
||||
|
@ -4253,7 +4255,11 @@ public:
|
|||
}
|
||||
|
||||
#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;
|
||||
char* userProfile=getenv("USERPROFILE");
|
||||
if (userProfile==NULL) {
|
||||
|
@ -4492,7 +4498,11 @@ private:
|
|||
printer.print(st, std::cerr);
|
||||
|
||||
#ifdef _WIN32
|
||||
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;
|
||||
char* userProfile=getenv("USERPROFILE");
|
||||
if (userProfile==NULL) {
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include <fmt/printf.h>
|
||||
#include <chrono>
|
||||
|
||||
int curEngineState=-1;
|
||||
|
||||
void process(void* u, float** in, float** out, int inChans, int outChans, unsigned int size) {
|
||||
((DivEngine*)u)->nextBuf(in,out,inChans,outChans,size);
|
||||
}
|
||||
|
@ -4018,6 +4020,31 @@ bool DivEngine::prePreInit() {
|
|||
logD("config path: %s",configPath.c_str());
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -432,6 +432,7 @@ enum DivChanTypes {
|
|||
};
|
||||
|
||||
extern const char* cmdName[];
|
||||
extern int curEngineState;
|
||||
|
||||
class DivEngine {
|
||||
DivDispatchContainer disCont[DIV_MAX_CHIPS];
|
||||
|
@ -447,6 +448,7 @@ class DivEngine {
|
|||
bool playing;
|
||||
bool freelance;
|
||||
bool shallStop, shallStopSched;
|
||||
bool reverse;
|
||||
bool endOfSong;
|
||||
bool consoleMode;
|
||||
bool disableStatusOut;
|
||||
|
@ -1400,6 +1402,7 @@ class DivEngine {
|
|||
freelance(false),
|
||||
shallStop(false),
|
||||
shallStopSched(false),
|
||||
reverse(false),
|
||||
endOfSong(false),
|
||||
consoleMode(false),
|
||||
disableStatusOut(false),
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
void DivEngine::nextOrder() {
|
||||
curRow=0;
|
||||
if (repeatPattern) return;
|
||||
if (curEngineState==3 || curEngineState==17) {
|
||||
if ((rand()%80)==0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (++curOrder>=curSubSong->ordersLen) {
|
||||
logV("end of orders reached");
|
||||
endOfSong=true;
|
||||
|
@ -326,6 +331,18 @@ const char* formatNote(unsigned char note, unsigned char octave) {
|
|||
}
|
||||
|
||||
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 (!skipping) {
|
||||
switch (c.cmd) {
|
||||
|
@ -1424,7 +1441,13 @@ void DivEngine::nextRow() {
|
|||
changeOrd=-1;
|
||||
}
|
||||
if (haltOn==DIV_HALT_PATTERN) halted=true;
|
||||
} else if (playing) if (++curRow>=curSubSong->patLen) {
|
||||
} else if (playing) {
|
||||
if (reverse) {
|
||||
if (--curRow<1) reverse=false;
|
||||
} else {
|
||||
curRow++;
|
||||
}
|
||||
if (curRow>=curSubSong->patLen) {
|
||||
if (shallStopSched) {
|
||||
curRow=curSubSong->patLen-1;
|
||||
} else {
|
||||
|
@ -1433,6 +1456,13 @@ void DivEngine::nextRow() {
|
|||
if (haltOn==DIV_HALT_PATTERN) halted=true;
|
||||
}
|
||||
|
||||
if ((curEngineState==4 || curEngineState==21) && (curRow&3)==0 && !skipping) {
|
||||
if ((rand()%600)==0) {
|
||||
reverse=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// new loop detection routine
|
||||
if (!endOfSong && walked[((curOrder<<5)+(curRow>>3))&8191]&(1<<(curRow&7)) && !shallStopSched) {
|
||||
logV("loop reached");
|
||||
|
@ -1459,6 +1489,17 @@ void DivEngine::nextRow() {
|
|||
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) {
|
||||
ticks=1;
|
||||
|
|
|
@ -257,6 +257,9 @@ void FurnaceGUI::drawAbout() {
|
|||
for (size_t i=0; i<aboutCount; i++) {
|
||||
// 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]);
|
||||
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 posY=(canvasH-aboutScroll+42*i*dpiScale);
|
||||
if (posY<-80*dpiScale || posY>canvasH) continue;
|
||||
|
|
|
@ -224,6 +224,14 @@ void FurnaceGUI::finishSelection() {
|
|||
}
|
||||
|
||||
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) {
|
||||
makeCursorUndo();
|
||||
}
|
||||
|
@ -450,6 +458,9 @@ void FurnaceGUI::moveCursorBottom(bool select) {
|
|||
void FurnaceGUI::editAdvance() {
|
||||
finishSelection();
|
||||
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;
|
||||
selStart=cursor;
|
||||
selEnd=cursor;
|
||||
|
|
|
@ -32,6 +32,12 @@ const unsigned char avRequest[15]={
|
|||
|
||||
|
||||
void FurnaceGUI::doAction(int what) {
|
||||
if (curEngineState==8 || curEngineState==13 || curEngineState==23) {
|
||||
if ((rand()%1000)==0) {
|
||||
showError("I don't wanna");
|
||||
return;
|
||||
}
|
||||
}
|
||||
switch (what) {
|
||||
case GUI_ACTION_NEW:
|
||||
if (modified) {
|
||||
|
|
251
src/gui/gui.cpp
251
src/gui/gui.cpp
|
@ -1200,6 +1200,7 @@ void FurnaceGUI::play(int row) {
|
|||
curNibble=false;
|
||||
orderNibble=false;
|
||||
activeNotes.clear();
|
||||
fullView=false;
|
||||
}
|
||||
|
||||
void FurnaceGUI::setOrder(unsigned char order, bool forced) {
|
||||
|
@ -1225,6 +1226,15 @@ void FurnaceGUI::stop() {
|
|||
}
|
||||
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) {
|
||||
|
@ -1328,6 +1338,12 @@ void FurnaceGUI::noteInput(int num, int key, int vol) {
|
|||
makeUndo(GUI_UNDO_PATTERN_EDIT);
|
||||
editAdvance();
|
||||
curNibble=false;
|
||||
|
||||
if (curEngineState==19) {
|
||||
if ((rand()%300)==0) {
|
||||
displayRating=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FurnaceGUI::valueInput(int num, bool direct, int target) {
|
||||
|
@ -2373,6 +2389,210 @@ int FurnaceGUI::save(String path, int dmfVersion) {
|
|||
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) {
|
||||
bool wasPlaying=e->isPlaying();
|
||||
if (!path.empty()) {
|
||||
|
@ -2428,6 +2648,7 @@ int FurnaceGUI::load(String path) {
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
updateProperties();
|
||||
backupLock.lock();
|
||||
curFileName=path;
|
||||
backupLock.unlock();
|
||||
|
@ -3758,6 +3979,8 @@ bool FurnaceGUI::loop() {
|
|||
if (settings.powerSave) SDL_WaitEventTimeout(NULL,500);
|
||||
}
|
||||
|
||||
updateState();
|
||||
|
||||
memcpy(perfMetricsLast,perfMetrics,64*sizeof(FurnaceGUIPerfMetric));
|
||||
perfMetricsLastLen=perfMetricsLen;
|
||||
perfMetricsLen=0;
|
||||
|
@ -4460,6 +4683,16 @@ bool FurnaceGUI::loop() {
|
|||
openFileDialog(GUI_FILE_SAVE);
|
||||
}
|
||||
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 (ImGui::BeginMenu(_("export audio..."))) {
|
||||
drawExportAudio();
|
||||
|
@ -5846,6 +6079,11 @@ bool FurnaceGUI::loop() {
|
|||
ImGui::OpenPopup(_("ROM Export Progress"));
|
||||
}
|
||||
|
||||
if (displayRating) {
|
||||
displayRating=false;
|
||||
ImGui::OpenPopup(_("Furnace###BeatRating"));
|
||||
}
|
||||
|
||||
if (displayNew) {
|
||||
newSongQuery="";
|
||||
newSongFirstFrame=true;
|
||||
|
@ -6072,6 +6310,17 @@ bool FurnaceGUI::loop() {
|
|||
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);
|
||||
if (ImGui::BeginPopupModal(_("Error"),NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::Text(_("%s"),errorString.c_str());
|
||||
|
@ -8376,12 +8625,14 @@ FurnaceGUI::FurnaceGUI():
|
|||
displayPendingSamples(false),
|
||||
replacePendingSample(false),
|
||||
displayExportingROM(false),
|
||||
displayRating(false),
|
||||
changeCoarse(false),
|
||||
mobileEdit(false),
|
||||
killGraphics(false),
|
||||
safeMode(false),
|
||||
midiWakeUp(true),
|
||||
makeDrumkitMode(false),
|
||||
fullView(false),
|
||||
audioEngineChanged(false),
|
||||
settingsChanged(false),
|
||||
debugFFT(false),
|
||||
|
|
|
@ -1664,12 +1664,14 @@ class FurnaceGUI {
|
|||
bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString;
|
||||
bool displayPendingSamples, replacePendingSample;
|
||||
bool displayExportingROM;
|
||||
bool displayRating;
|
||||
bool changeCoarse;
|
||||
bool mobileEdit;
|
||||
bool killGraphics;
|
||||
bool safeMode;
|
||||
bool midiWakeUp;
|
||||
bool makeDrumkitMode;
|
||||
bool fullView;
|
||||
bool audioEngineChanged, settingsChanged, debugFFT;
|
||||
bool willExport[DIV_MAX_CHIPS];
|
||||
int vgmExportVersion;
|
||||
|
@ -2943,6 +2945,8 @@ class FurnaceGUI {
|
|||
void commitTutorial();
|
||||
void syncState();
|
||||
void commitState(DivConfig& conf);
|
||||
void updateState();
|
||||
void updateProperties();
|
||||
void processDrags(int dragX, int dragY);
|
||||
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) {
|
||||
if (fmPreviewOn) {
|
||||
if (ImGui::IsItemHovered()) {
|
||||
|
|
|
@ -300,6 +300,15 @@ void FurnaceGUI::drawOsc() {
|
|||
}
|
||||
|
||||
if ((oscWidth-24)>0) {
|
||||
if (!e->isPlaying() && fullView) {
|
||||
ImVec2 point0=inRect.Min;
|
||||
ImVec2 point1=inRect.Max;
|
||||
point0.y=0;
|
||||
point1.y=canvasH;
|
||||
dl->PushClipRectFullScreen();
|
||||
dl->AddRectFilled(point0,point1,color,0,ImDrawFlags_None);
|
||||
dl->PopClipRect();
|
||||
} else {
|
||||
if (settings.oscMono) {
|
||||
if (rend->supportsDrawOsc() && settings.shaderOsc) {
|
||||
_do.gui=this;
|
||||
|
@ -371,6 +380,7 @@ void FurnaceGUI::drawOsc() {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dl->Flags=prevFlags;
|
||||
|
||||
|
|
|
@ -7188,5 +7188,20 @@ void FurnaceGUI::applyUISettings(bool updateFonts) {
|
|||
fileDialog=new FurnaceGUIFileDialog(settings.sysFileDialog);
|
||||
|
||||
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 (ImGui::Checkbox(_("Modified sine wave (joke)"),&msw)) {
|
||||
if (msw || curEngineState==6 || curEngineState==16) {
|
||||
if (ImGui::Checkbox(_("Modified sine wave"),&msw)) {
|
||||
altered=true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ enum FurnaceCVObjectTypes {
|
|||
CV_MINE,
|
||||
CV_POWERUP_P,
|
||||
CV_POWERUP_S,
|
||||
CV_SPECIAL,
|
||||
CV_MOD_I,
|
||||
CV_MOD_S,
|
||||
CV_EXTRA_LIFE
|
||||
|
@ -79,6 +80,7 @@ struct FurnaceCVObject {
|
|||
short x, y;
|
||||
unsigned char z, prio;
|
||||
short collX0, collX1, collY0, collY1;
|
||||
short frozen;
|
||||
|
||||
virtual void collision(FurnaceCVObject* other);
|
||||
virtual void tick();
|
||||
|
@ -95,7 +97,8 @@ struct FurnaceCVObject {
|
|||
collX0(0),
|
||||
collX1(15),
|
||||
collY0(0),
|
||||
collY1(15) {
|
||||
collY1(15),
|
||||
frozen(0) {
|
||||
memset(spriteDef,0,512*sizeof(unsigned short));
|
||||
spriteDef[0]=4;
|
||||
spriteDef[1]=5;
|
||||
|
@ -112,6 +115,24 @@ void FurnaceCVObject::collision(FurnaceCVObject* other) {
|
|||
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 {
|
||||
SDL_Surface* surface;
|
||||
unsigned char* prioBuf;
|
||||
|
@ -134,7 +155,7 @@ struct FurnaceCV {
|
|||
int ticksToInit;
|
||||
|
||||
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 hiScore;
|
||||
short lastPlayerX, lastPlayerY;
|
||||
|
@ -216,6 +237,7 @@ struct FurnaceCV {
|
|||
stage(0),
|
||||
shotType(0),
|
||||
lifeBank(0),
|
||||
specialType(0),
|
||||
score(0),
|
||||
hiScore(25000),
|
||||
lastPlayerX(0),
|
||||
|
@ -249,6 +271,7 @@ struct FurnaceCVPlayer: FurnaceCVObject {
|
|||
unsigned char animFrame;
|
||||
short invincible;
|
||||
unsigned char shotTimer;
|
||||
bool doubleShot;
|
||||
|
||||
void collision(FurnaceCVObject* other);
|
||||
void tick();
|
||||
|
@ -261,7 +284,8 @@ struct FurnaceCVPlayer: FurnaceCVObject {
|
|||
shootDir(2),
|
||||
animFrame(0),
|
||||
invincible(120),
|
||||
shotTimer(4) {
|
||||
shotTimer(4),
|
||||
doubleShot(false) {
|
||||
type=CV_PLAYER;
|
||||
spriteWidth=3;
|
||||
spriteHeight=3;
|
||||
|
@ -336,11 +360,23 @@ struct FurnaceCVEnemyBullet: FurnaceCVObject {
|
|||
}
|
||||
};
|
||||
|
||||
struct FurnaceCVEnemy1: FurnaceCVObject {
|
||||
struct FurnaceCVEnemy: FurnaceCVObject {
|
||||
unsigned char enemyType;
|
||||
unsigned char health;
|
||||
unsigned char orient;
|
||||
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;
|
||||
short nextTime, shootTime;
|
||||
unsigned char shootCooldown;
|
||||
|
@ -349,13 +385,9 @@ struct FurnaceCVEnemy1: FurnaceCVObject {
|
|||
void collision(FurnaceCVObject* other);
|
||||
|
||||
void tick();
|
||||
void setType(unsigned char type);
|
||||
FurnaceCVEnemy1(FurnaceCV* p):
|
||||
FurnaceCVObject(p),
|
||||
enemyType(0),
|
||||
health(1),
|
||||
FurnaceCVEnemy(p),
|
||||
orient(rand()&3),
|
||||
stopped(0),
|
||||
animFrame(0),
|
||||
nextTime(64+(rand()%600)),
|
||||
shootTime(8),
|
||||
|
@ -369,8 +401,7 @@ struct FurnaceCVEnemy1: FurnaceCVObject {
|
|||
}
|
||||
};
|
||||
|
||||
struct FurnaceCVEnemyVortex: FurnaceCVObject {
|
||||
unsigned char stopped;
|
||||
struct FurnaceCVEnemyVortex: FurnaceCVEnemy {
|
||||
unsigned char animFrame;
|
||||
short nextTime, shootTime, speedX, speedY;
|
||||
|
||||
|
@ -378,8 +409,7 @@ struct FurnaceCVEnemyVortex: FurnaceCVObject {
|
|||
|
||||
void tick();
|
||||
FurnaceCVEnemyVortex(FurnaceCV* p):
|
||||
FurnaceCVObject(p),
|
||||
stopped(0),
|
||||
FurnaceCVEnemy(p),
|
||||
animFrame(0),
|
||||
nextTime(4+(rand()%140)),
|
||||
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 {
|
||||
unsigned char life;
|
||||
void collision(FurnaceCVObject* other);
|
||||
|
@ -1348,7 +1391,7 @@ void FurnaceCV::buildStage(int which) {
|
|||
createObject<FurnaceCVFurBallLarge>(finalX-4,finalY-4);
|
||||
enemy->setType(2);
|
||||
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+1]=true;
|
||||
|
@ -1392,7 +1435,11 @@ void FurnaceCV::buildStage(int which) {
|
|||
FurnaceCVEnemy1* enemy=createObject<FurnaceCVEnemy1>(finalX,finalY);
|
||||
createObject<FurnaceCVFurBallMedium>(finalX-4,finalY-4);
|
||||
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;
|
||||
break;
|
||||
|
@ -1696,6 +1743,19 @@ void FurnaceCV::render(unsigned char joyIn) {
|
|||
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
|
||||
if (speedTicks>0) {
|
||||
speedTicks--;
|
||||
|
@ -1953,6 +2013,7 @@ void FurnaceCVPlayer::collision(FurnaceCVObject* other) {
|
|||
cv->speedTicks=0;
|
||||
cv->e->setSongRate(cv->origSongRate);
|
||||
cv->respawnTime=48;
|
||||
cv->specialType=0;
|
||||
if (cv->weaponStack.empty()) {
|
||||
cv->shotType=0;
|
||||
} else {
|
||||
|
@ -2080,7 +2141,9 @@ void FurnaceCVPlayer::tick() {
|
|||
} else {
|
||||
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->setType((cv->shotType==1)?1:0);
|
||||
switch (shootDir) {
|
||||
|
@ -2113,6 +2176,42 @@ void FurnaceCVPlayer::tick() {
|
|||
b->speedY=0;
|
||||
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) {
|
||||
|
@ -2126,7 +2225,10 @@ void FurnaceCVPlayer::tick() {
|
|||
} else {
|
||||
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->setType((cv->shotType==1)?1:0);
|
||||
switch (shootDir) {
|
||||
|
@ -2164,6 +2266,181 @@ void FurnaceCVPlayer::tick() {
|
|||
b->speedX+=(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));
|
||||
break;
|
||||
case 10: case 11: // special
|
||||
cv->createObject<FurnaceCVSpecial>(x+(enemyType>=2?8:0),y+(enemyType>=2?8:0));
|
||||
break;
|
||||
case 12: // mod
|
||||
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() {
|
||||
if (frozen>0) {
|
||||
if (--frozen>0) return;
|
||||
}
|
||||
|
||||
if (!stopped) {
|
||||
switch (orient) {
|
||||
case 0:
|
||||
|
@ -2663,7 +2945,7 @@ void FurnaceCVEnemy1::tick() {
|
|||
}
|
||||
}
|
||||
|
||||
void FurnaceCVEnemy1::setType(unsigned char t) {
|
||||
void FurnaceCVEnemy::setType(unsigned char t) {
|
||||
enemyType=t;
|
||||
switch (enemyType) {
|
||||
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
|
||||
|
||||
void FurnaceCVModI::collision(FurnaceCVObject* other) {
|
||||
|
@ -3368,16 +3677,25 @@ void FurnaceCVEnemyVortex::collision(FurnaceCVObject* other) {
|
|||
if (other->type==CV_BULLET || other->type==CV_PLAYER) {
|
||||
dead=true;
|
||||
if ((rand()%2)==0) {
|
||||
switch (rand()%10) {
|
||||
case 0:
|
||||
switch (rand()%14) {
|
||||
case 0: // extra life
|
||||
cv->createObject<FurnaceCVExtraLife>(x,y);
|
||||
break;
|
||||
case 1: case 2: case 3: case 4:
|
||||
case 1: case 2: case 3: case 4: // powerup
|
||||
cv->createObject<FurnaceCVPowerupP>(x,y);
|
||||
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);
|
||||
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);
|
||||
|
@ -3387,6 +3705,10 @@ void FurnaceCVEnemyVortex::collision(FurnaceCVObject* other) {
|
|||
}
|
||||
|
||||
void FurnaceCVEnemyVortex::tick() {
|
||||
if (frozen>0) {
|
||||
if (--frozen>0) return;
|
||||
}
|
||||
|
||||
x+=speedX;
|
||||
y+=speedY;
|
||||
animFrame+=0x08;
|
||||
|
@ -3470,12 +3792,12 @@ void FurnaceCVEnemyPlane::tick() {
|
|||
if (--shootTime<=0) {
|
||||
shootTime=28-(speed*2);
|
||||
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++) {
|
||||
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<FurnaceCVEnemyBullet>(x+(spriteWidth<<2),y+(spriteHeight<<2));
|
||||
FurnaceCVEnemyBullet* b=cv->createObject<FurnaceCVEnemyBullet>(x+(spriteWidth<<2)-4,y+(spriteHeight<<2)-4);
|
||||
b->speedX=xs;
|
||||
b->speedY=ys;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue