#include "m_game.h" #include "actor.h" #include "room.h" #include "jui.h" #include "jinput.h" #include "jgame.h" #include "console.h" #include "editor.h" namespace modules { namespace game { enum sections { SECTION_GENERAL, SECTION_ROOM, SECTION_ACTOR }; std::vector gifs; int treeview_scroll = 0; void init() { actor::clear(true); ::game::setUpdateTicks(64); actor::templates::load(); if (editor::isDevMode()) { draw::stencil::init(); FILE* f = fopen("data/gifs.txt", "r"); int buffer_len=255; char buffer[buffer_len]; while(fgets(buffer, buffer_len, f)) { auto len = strlen(buffer); buffer[len-1]=0; gifs.push_back(std::string(buffer)); } fclose(f); } actor::hero::init(); room::load(1); } void print(int x, int y, int num) { int digits=0; bool sign = num < 0; num = SDL_abs(num); int n = num; while (n>0) {n=n/10;digits++;} if (sign) digits++; x=x+digits*4; if (num==0) draw::draw(x+4,y,5,7,0,120); while (num>0) { draw::draw(x,y,5,7,(num%10)*5,120); num=num/10; x=x-4; } if (sign) draw::draw(x,y,5,7,50,120); } const bool btn_small(const int x, const int y, int &var, int min, int max) { char buffer[100]; const char *result=ui::spin(SDL_itoa(var, buffer, 10), x, y, 17, 11); if (result) { const int value = SDL_atoi(result); var=SDL_max(min, SDL_min(max, value)); return true; } return false; } const bool btn_small(const int x, const int y, int &var, int min, int max, int width) { char buffer[100]; const char *result=ui::spin(SDL_itoa(var, buffer, 10), x, y, width, 11); if (result) { const int value = SDL_atoi(result); var=SDL_max(min, SDL_min(max, value)); return true; } return false; } const bool btn_check(const int x, const int y, const char* label, int &flags, const uint16_t value, const int width=24) { int result=0; if (flags & value) { result=ui::check(label, x, y, width, 11, true); } else { result=ui::check(label, x, y, width, 11, false); } if (result) { if (flags & value) { flags = flags & ~value; } else { flags = flags | value; } return true; } return false; } const bool btn_opt(const char* label, const int x, const int y, int &var, std::vector values, std::vector labels, const int w=32) { //draw::print(label, x, y+3, 15, 0); ui::label(label, x, y, w, 11); int result = 0; std::size_t pos = 0; while (pos values) { //draw::print(label, x, y+3, PAPER, 0); ui::label(label, x, y, 48, 11); int result = 0; std::size_t pos = 0; std::string v = var; while (pos < values.size() && v != values[pos]) { pos++; } if (pos==values.size()) pos = 0; result = ui::combo(var, x+47, y, 48, 11); if (result) { pos++; if (pos==values.size()) pos=0; strcpy(var,values[pos].c_str()); return true; } return false; } const uint8_t scancode_to_char(const uint8_t scancode) { if (scancode == SDL_SCANCODE_0) return '0'; if (scancode >= SDL_SCANCODE_1 && scancode <= SDL_SCANCODE_9) return scancode+19; if (scancode >= SDL_SCANCODE_A && scancode <= SDL_SCANCODE_Z) return scancode+61; //if (scancode == SDL_SCANCODE_MINUS) return '-'; return '-'; } const bool btn_txt(const char* label, const int x, const int y, char *var) { //draw::print(label, x, y+3, PAPER, 0); ui::label(label, x, y, 48, 11); int result = 0; result = ui::textbox(var, x+47, y, 48, 11); if (result) { const int len = strlen(var); if (result == SDL_SCANCODE_BACKSPACE) { if (len>0) var[len-1] = 0; } else { if (len<15) { var[len] = scancode_to_char(result); var[len+1] = 0; } } return true; } return false; } int section = SECTION_ROOM; void editor_select_by_keyboard() { if ( !(input::keyDown(SDL_SCANCODE_LCTRL) || input::keyDown(SDL_SCANCODE_RCTRL)) ) return; actor::actor_t *selected = actor::getSelected(); if ( input::keyPressed(SDL_SCANCODE_UP) ) { if (!selected) { actor::actor_t *first = actor::getFirst(); while (first && (first->flags&FLAG_IGNORE)) first=first->next; actor::select(first); } else { if (selected->prev) { actor::actor_t *prev = selected->prev; while (prev && (prev->flags&FLAG_IGNORE)) prev=prev->prev; actor::select(prev); } else { actor::actor_t *last = actor::getLast(); while (last && (last->flags&FLAG_IGNORE)) last=last->prev; actor::select(last); } } section=SECTION_ACTOR; } if ( input::keyPressed(SDL_SCANCODE_DOWN) ) { if (!selected) { actor::actor_t *last = actor::getLast(); while (last && (last->flags&FLAG_IGNORE)) last=last->prev; actor::select(last); } else { if (selected->next) { actor::actor_t *next = selected->next; while (next && (next->flags&FLAG_IGNORE)) next=next->next; if (next) { actor::select(next); } else { actor::actor_t *first = actor::getFirst(); while (first && (first->flags&FLAG_IGNORE)) first=first->next; actor::select(first); } } else { actor::actor_t *first = actor::getFirst(); while (first && (first->flags&FLAG_IGNORE)) first=first->next; actor::select(first); } } section=SECTION_ACTOR; } } void editor_move_selected() { actor::actor_t *selected = actor::getSelected(); if (!selected) return; if ( input::keyDown(SDL_SCANCODE_LCTRL) || input::keyDown(SDL_SCANCODE_RCTRL) ) return; vec3_t min = room::getMin(); vec3_t max = room::getMax(); if ( input::keyDown(SDL_SCANCODE_LEFT) && selected->pos.x>min.x ) { selected->pos.x--; actor::setDirty(selected); room::editor::modify(); } if ( input::keyDown(SDL_SCANCODE_RIGHT) && (selected->pos.x+selected->size.x)pos.x++; actor::setDirty(selected); room::editor::modify(); } if ( input::keyDown(SDL_SCANCODE_UP) && selected->pos.y>min.y ) { selected->pos.y--; actor::setDirty(selected); room::editor::modify(); } if ( input::keyDown(SDL_SCANCODE_DOWN) && (selected->pos.y+selected->size.y)pos.y++; actor::setDirty(selected); room::editor::modify(); } if ( input::keyDown(SDL_SCANCODE_PAGEDOWN) && selected->pos.z>min.z ) { selected->pos.z--; actor::setDirty(selected); room::editor::modify(); } if ( input::keyDown(SDL_SCANCODE_PAGEUP) /*&& selected->pos.zpos.z++; actor::setDirty(selected); room::editor::modify(); } } bool loop() { if (input::keyPressed(SDL_SCANCODE_ESCAPE)) { if (console::isEnabled()) console::toggle(); else return false; } if (input::keyPressed(SDL_SCANCODE_TAB) || input::keyPressed(SDL_SCANCODE_GRAVE) ) console::toggle(); // WHILE EDITING... if (editor::isEditing()) { editor_move_selected(); actor::updateEditor(actor::getFirst()); } else { if (!console::update()) { actor::update(actor::getFirst()); actor::hero::useBoostGod(); } } actor::reorder(); if (editor::isEditing()) editor_select_by_keyboard(); draw::resetViewport(); draw::cls(2); if (editor::isDevMode()) draw::setViewport(100,0,320,240); room::draw(); draw::stencil::enable(); draw::stencil::clear(255); actor::draw(actor::getFirst()); draw::stencil::disable(); room::draw2(); draw::swapcol(1, WHITE+LIGHT); actor::draw(actor::getPicked(), false); if (editor::isDevMode() && input::mouseBtn(1)) { const uint8_t val = draw::stencil::query(input::mouseX(), input::mouseY()); if (val != 255) { actor::select(actor::findByTag(val)); section = SECTION_ACTOR; } } const int col1 = room::getColor(1); const int col2 = room::getColor(2); const int col3 = room::getColor(3); draw::print2("a", 4, 26, col1, FONT_ZOOM_NONE); draw::print2("b", 7, 26, col2, FONT_ZOOM_NONE); draw::print2("c", 10, 26, col3, FONT_ZOOM_NONE); draw::print2(actor::hero::getBoostJump(), 2, 3, 27, col3, FONT_ZOOM_NONE); draw::print2(actor::hero::getBoostGod()/2, 2, 6, 27, col1, FONT_ZOOM_NONE); draw::print2(actor::hero::getBoostRun()/2, 2, 9, 27, col2, FONT_ZOOM_NONE); draw::setSource(draw::getSurface("objectes.gif")); draw::swapcol(1, actor::hero::getSkills()&SKILL_SHOES ? col1 : col3); draw::draw(276,166, 28, 22, 162, 0); draw::swapcol(1, actor::hero::getSkills()&SKILL_PANTS ? col1 : col3); draw::draw(250,183, 18, 23, 167, 22); draw::swapcol(1, actor::hero::getSkills()&SKILL_GLOVES ? col1 : col3); draw::draw(222,200, 21, 22, 165, 45); draw::swapcol(1, actor::hero::getSkills()&SKILL_BAG ? col1 : col3); draw::draw(279,200, 20, 25, 145, 41); /* print(0,0,input::mouseX()); print(0,20,input::mouseY()); print(0,30,input::mouseBtn(1)?1:0); print(0,40,input::mouseBtn(2)?1:0); print(0,50,input::mouseBtn(3)?1:0); */ if (!editor::isDevMode()) { console::draw(); draw::render(); return true; } ui::start(); actor::actor_t *act = nullptr; draw::setViewport(0,0,100,240); draw::color(WHITE); draw::fillrect(0, 0, 100, 240); int result = ui::combo(actor::templates::get(editor::getCurrentTemplate())->name, 2, 2, 76, 11); if (result) { int new_current_template = editor::getCurrentTemplate() + (result-2); if (new_current_template >= actor::templates::size()) new_current_template = 0; if (new_current_template < 0) new_current_template = actor::templates::size()-1; editor::setCurrentTemplate(new_current_template); } if (ui::button("NEW", 78, 2, 20, 11)) { actor::actor_t *new_act = actor::duplicate(actor::templates::get(editor::getCurrentTemplate())); actor::setUniqueName(new_act); actor::setDirty(new_act, true); actor::select(new_act); room::editor::modify(); } draw::color(LIGHT+WHITE); draw::fillrect(2, 15, 96, 223); draw::color(PAPER); draw::rect(2, 15, 96, 223); draw::setViewport(0, 15, 100, 222); const int mx = draw::getLocalX(input::mouseX()); const int my = draw::getLocalY(input::mouseY()); const bool btnDown = input::mouseBtn(1) || input::mouseBtn(3); if (mx>=0 && mx <=100 && my>=0 && my<=221) { treeview_scroll -= input::mouseWheel(); if (treeview_scroll<0) treeview_scroll=0; } switch (section) { case SECTION_GENERAL: treeview_scroll = 0; break; case SECTION_ROOM: if (treeview_scroll > room::editor::getCurrentRoom()+1) treeview_scroll = room::editor::getCurrentRoom()+1; } int line = -treeview_scroll; if (section==SECTION_GENERAL) { draw::color(LIGHT+BLUE); draw::fillrect(4, 2+line*9, 92, 9); } if ((mx>=2) && (mx<98) && (my>=2+line*9) && (my<2+9+line*9) && btnDown) { section = SECTION_GENERAL; } draw::print("-THE POOL", 6, 4+line*9, LIGHT+WHITE, BLACK); line++; for (int i=0;i<64;++i) { if (room::editor::roomExists(i)) { if (section==SECTION_ROOM && i == room::editor::getCurrentRoom()) { draw::color(LIGHT+BLUE); draw::fillrect(4, 2+line*9, 92, 9); } if ((mx>=2) && (mx<98) && (my>=2+line*9) && (my<2+9+line*9) && btnDown) { room::load(i); section = SECTION_ROOM; } char num[] = "+ROOM 00"; num[6] = int(i/10)+48; num[7] = (i%10)+48; draw::print(num, 10, 4+line*9, LIGHT+WHITE, BLACK); line++; if (i==room::editor::getCurrentRoom()) { act = actor::getFirst(); while (act) { if ((act->flags&FLAG_NOEDITOR)!=FLAG_NOEDITOR && (act->flags&FLAG_HERO)!=FLAG_HERO) { if (section==SECTION_ACTOR && act==actor::getSelected()) { draw::color(LIGHT+BLUE); draw::fillrect(4, 2+line*9, 92, 9); } if ((mx>=2) && (mx<98) && (my>=2+line*9) && (my<2+9+line*9) && btnDown) { actor::select(act); section = SECTION_ACTOR; } draw::print(act->name, 14, 4+line*9, LIGHT+WHITE, BLACK); line++; } act = act->next; } } } } if ((line+treeview_scroll)>24) { const float total_size = float(line+treeview_scroll); int ascensor_length = 222.0f/(total_size/24.0f); int ascensor_pos = 222.0f/(total_size/treeview_scroll); draw::color(WHITE); draw::fillrect(95, ascensor_pos, 2, ascensor_length); } draw::setViewport(420, 0, 100, 240); draw::color(WHITE); draw::fillrect(0, 0, 100, 240); if (ui::button("EDITING", 2, 2, 96, 11, editor::isEditing())) { room::load(room::editor::getCurrentRoom()); if (!editor::isEditing()) actor::find("HERO")->pos.z=24; editor::setEditing(!editor::isEditing()); } draw::setViewport(420, 15, 100, 225); bool changed = false; switch (section) { case SECTION_GENERAL: break; case SECTION_ROOM: draw::color(LIGHT+WHITE); draw::fillrect(2, 0, 96, 223); line = 0; //changed |= btn("ROOM WIDTH:", 10, 40, room::editor::refWidth(), 0, 3); //changed |= btn("ROOM HEIGHT:", 10, 55, room::editor::refHeight(), 0, 3); ui::label("ROOM DIMENSIONS", 2, line, 96, 11, GRAY); line+=10; ui::label("WIDTH", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refWidth(), 0, 3, 50); line += 10; ui::label("HEIGHT", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refHeight(), 0, 3, 50); line += 10; ui::label("DOOR HEIGHTS", 2, line, 96, 11, GRAY); line+=10; ui::label("XN", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refDoor(XN), -1, 5, 50); line += 10; ui::label("YP", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refDoor(YP), -1, 5, 50); line += 10; ui::label("XP", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refDoor(XP), -1, 5, 50); line += 10; ui::label("YN", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refDoor(YN), -1, 5, 50); line += 10; ui::label("TEXTURES", 2, line, 96, 11, GRAY); line+=10; changed |= btn_opt("COLOR", 2, line, room::editor::refColor(), {0, 1, 2, 3, 4}, {"PURPLE", "GREEN", "CYAN", "YELLOW", "WHITE"}, 47); //ui::label("COLOR", 2, line, 64, 11); //changed |= btn_small(64, line, room::editor::refColor(), 5, 11); line += 10; ui::label("FLOOR", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refFloorTex(), 0, room::getFloorCount()-1, 50); line += 10; ui::label("WALL", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refWallTex(), 0, room::getWallsCount()-1, 50); line += 10; ui::label("DOOR", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refDoorTex(), 0, room::getDoorCount()-1, 50); line += 10; ui::label("UNDER DOOR", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refWallDoorTex(), 0, room::getWallsCount()-1, 50); line += 10; ui::label("EXITS", 2, line, 96, 11, GRAY); line+=10; ui::label("XN", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refExit(XN), -1, 64, 36); if (ui::button("GO", 84, line, 13, 11)) room::load(room::editor::refExit(XN), XP); line += 10; ui::label("YP", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refExit(YP), -1, 64, 36); if (ui::button("GO", 84, line, 13, 11)) room::load(room::editor::refExit(YP), YN); line += 10; ui::label("XP", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refExit(XP), -1, 64, 36); if (ui::button("GO", 84, line, 13, 11)) room::load(room::editor::refExit(XP), XN); line += 10; ui::label("YN", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refExit(YN), -1, 64, 36); if (ui::button("GO", 84, line, 13, 11)) room::load(room::editor::refExit(YN), YP); line += 10; ui::label("ZP", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refExit(ZP), -1, 64, 36); if (ui::button("GO", 84, line, 13, 11)) room::load(room::editor::refExit(ZP), ZN); line += 10; ui::label("ZN", 2, line, 48, 11); changed |= btn_small(48, line, room::editor::refExit(ZN), -1, 64, 36); if (ui::button("GO", 84, line, 13, 11)) room::load(room::editor::refExit(ZN), ZP); line += 10; /*changed |= btn("COLOR:", 10, 140, room::editor::refColor(), 5, 11); changed |= btn("FLOOR:", 10, 155, room::editor::refFloorTex(), 0, 5); changed |= btn("WALLS:", 10, 170, room::editor::refWallTex(), 0, 5); changed |= btn("DOORS:", 10, 185, room::editor::refDoorTex(), 0, 4); changed |= btn("WDOORS:", 10, 200, room::editor::refWallDoorTex(), 0, 5);*/ if (changed) { room::editor::modify(); room::update(); } draw::color(PAPER); draw::rect(2, 0, 96, 223); break; case SECTION_ACTOR: draw::color(LIGHT+WHITE); draw::fillrect(2, 0, 96, 153); changed = false; act = actor::getSelected(); if (act) { line = 0; //draw::setViewport(420, 90, 100, 150); changed |= btn_txt("NAME", 2, line, act->name); line+=10; ui::label("LOCATION", 2, line, 96, 11, GRAY); line+=10; ui::label("POS", 2, line, 48, 11); changed |= btn_small(49, line, act->pos.x, 0, 512); changed |= btn_small(65, line, act->pos.y, 0, 512); changed |= btn_small(81, line, act->pos.z, 0, 512); line+=10; ui::label("SIZE", 2, line, 48, 11); changed |= btn_small(49, line, act->size.x, 0, 512); changed |= btn_small(65, line, act->size.y, 0, 512); changed |= btn_small(81, line, act->size.z, 0, 512); line+=10; ui::label("BITMAP", 2, line, 96, 11, GRAY); line+=10; if (btn_opt2("FILE", 2, line, act->bmp, gifs)) { //draw::freeSurface(act->surface); act->surface = draw::getSurface(act->bmp); changed = true; } line+=10; ui::label("POS", 2, line, 48, 11); changed |= btn_small(49, line, act->bmp_rect.x, 0, 512, 25); changed |= btn_small(73, line, act->bmp_rect.y, 0, 512, 25); line+=10; ui::label("SIZE", 2, line, 48, 11); changed |= btn_small(49, line, act->bmp_rect.w, 0, 512, 25); changed |= btn_small(73, line, act->bmp_rect.h, 0, 512, 25); line+=10; ui::label("OFFSET", 2, line, 48, 11); changed |= btn_small(49, line, act->bmp_offset.x, -32, 64, 25); changed |= btn_small(73, line, act->bmp_offset.y, -32, 64, 25); line+=10; ui::label("FLAGS", 2, line, 96, 11, GRAY); changed |= btn_check(74, line, "SPEC", act->flags, FLAG_SPECIAL); line+=10; changed |= btn_check(2, line, "PICK", act->flags, FLAG_PICKABLE); changed |= btn_check(26, line, "PUSH", act->flags, FLAG_PUSHABLE); changed |= btn_check(50, line, "REAC", act->flags, FLAG_REACTIVE); changed |= btn_check(74, line, "MOVI", act->flags, FLAG_MOVING); line+=10; changed |= btn_check(2, line, "ANIM", act->flags, FLAG_ANIMATED); changed |= btn_check(26, line, "ORIE", act->flags, FLAG_ORIENTABLE); changed |= btn_check(50, line, "DEAD", act->flags, FLAG_DEADLY); changed |= btn_check(74, line, "GRAV", act->flags, FLAG_GRAVITY); line+=11; ui::label("PROPERTIES", 2, line, 96, 11, GRAY); line+=10; if (btn_opt("ORIENT", 2, line, act->orient, {PUSH_NONE, PUSH_XP, PUSH_XN, PUSH_YP, PUSH_YN, PUSH_ZP, PUSH_ZN}, {"NONE", "XP", "XN", "YP", "YN", "ZP", "ZN"}, 48)) { act->mov_push = act->orient; changed = true; } line+=10; changed |= btn_opt("MOVEMNT", 2, line, act->movement, {MOV_NONE, MOV_X, MOV_Y, MOV_Z, MOV_CW, MOV_CCW, MOV_RAND, MOV_HUNT}, {"NONE", "X", "Y", "Z", "CW", "CCW", "RAND", "HUNT"}, 48); line+=10; changed |= btn_opt("ANIMCYC", 2, line, act->anim_cycle, {0, 1, 2}, {"0 1 0 2", "0 1 2 3", "0 1 2"}, 48); line+=10; //draw::print("ANIM SPEED:", 2, 156, 15, 0); ui::label("ANMSPED", 2, line, 49, 11); changed |= btn_small(49, line, act->anim_wait, 0, 10, 49); line+=10; ui::label("MASKS", 2, line, 96, 11, GRAY); line+=10; ui::label("RMASK", 2, line, 24, 11); changed |= btn_check(24+2, line, "XP", act->react_mask, PUSH_XP, 12); changed |= btn_check(24+14, line, "XN", act->react_mask, PUSH_XN, 12); changed |= btn_check(24+26, line, "YP", act->react_mask, PUSH_YP, 12); changed |= btn_check(24+38, line, "YN", act->react_mask, PUSH_YN, 12); changed |= btn_check(24+50, line, "ZP", act->react_mask, PUSH_ZP, 12); changed |= btn_check(24+62, line, "ZN", act->react_mask, PUSH_ZN, 12); line+=11; ui::label("RPUSH", 2, line, 24, 11); changed |= btn_check(24+2, line, "XP", act->react_push, PUSH_XP, 12); changed |= btn_check(24+14, line, "XN", act->react_push, PUSH_XN, 12); changed |= btn_check(24+26, line, "YP", act->react_push, PUSH_YP, 12); changed |= btn_check(24+38, line, "YN", act->react_push, PUSH_YN, 12); changed |= btn_check(24+50, line, "ZP", act->react_push, PUSH_ZP, 12); changed |= btn_check(24+62, line, "ZN", act->react_push, PUSH_ZN, 12); line+=12; draw::color(PAPER); draw::rect(2, 0, 96, 204); if (ui::button("DUPLICATE", 2, line, 48, 11)) { actor::actor_t *new_act = actor::duplicate(act); actor::setUniqueName(new_act); new_act->pos.x++; new_act->pos.y++; actor::setDirty(new_act, true); actor::select(new_act); changed = true; } if (ui::button("DELETE", 48, line, 48, 11)) { actor::remove(act); act = nullptr; changed = true; } line+=10; if (changed) { room::editor::modify(); } if (ui::button("ADD TO TEMPLATES", 2, line, 96, 11)) { if (act) actor::templates::add(act); } //changed |= btn_opt("ANIMCYC", 2, 106, act->anim_cycle, {0, 1}, {"0 1 0 2", "0 1 2 3"}); } break; }; draw::render(); return true; } } }