short treasure::eat_me(walker * eater) { short guys_here; oblink *here; static text eattext(screenp); char message[80]; Sint32 distance; walker *target, *flash; static char exitname[40]; Sint32 leftside, rightside; switch (family) { case FAMILY_DRUMSTICK: if (eater->stats->hitpoints >= eater->stats->max_hitpoints) return 1; else { eater->stats->hitpoints += (short) ((10*stats->level) + (short) random((short) 10*stats->level)); if (eater->stats->hitpoints > eater->stats->max_hitpoints) eater->stats->hitpoints = eater->stats->max_hitpoints; dead = 1; if (on_screen()) screenp->soundp->play_sound(SOUND_EAT); return 1; } case FAMILY_GOLD_BAR: if (eater->team_num == 0 || eater->myguy) { myscreen->m_score[eater->team_num] += (200*stats->level); dead = 1; if (on_screen()) screenp->soundp->play_sound(SOUND_MONEY); } return 1; case FAMILY_SILVER_BAR: if (eater->team_num == 0 || eater->myguy) { myscreen->m_score[eater->team_num] += (50*stats->level); dead = 1; if (on_screen()) screenp->soundp->play_sound(SOUND_MONEY); } return 1; case FAMILY_FLIGHT_POTION: if (!eater->stats->query_bit_flags(BIT_FLYING) ) { eater->flight_left += (150*stats->level); if (eater->user != -1) { sprintf(message, "Potion of Flight(%d)!", stats->level); screenp->do_notify(message, eater); } dead = 1; } return 1; case FAMILY_MAGIC_POTION: if (eater->stats->magicpoints < eater->stats->max_magicpoints) eater->stats->magicpoints = eater->stats->max_magicpoints; eater->stats->magicpoints += (50*stats->level); dead = 1; if (eater->user != -1) { sprintf(message, "Potion of Mana(%d)!", stats->level); screenp->do_notify(message, eater); } return 1; case FAMILY_INVULNERABLE_POTION: if (!eater->stats->query_bit_flags(BIT_INVINCIBLE) ) { eater->invulnerable_left += (150*stats->level); dead = 1; if (eater->user != -1) { sprintf(message, "Potion of Invulnerability(%d)!", stats->level); screenp->do_notify(message, eater); } } return 1; case FAMILY_INVIS_POTION: eater->invisibility_left += (150*stats->level); if (eater->user != -1) { sprintf(message, "Potion of Invisibility(%d)!", stats->level); screenp->do_notify(message, eater); } dead = 1; return 1; case FAMILY_SPEED_POTION: eater->speed_bonus_left += 50*stats->level; eater->speed_bonus = stats->level; if (eater->user != -1) { sprintf(message, "Potion of Speed(%d)!", stats->level); screenp->do_notify(message, eater); } dead = 1; return 1; case FAMILY_EXIT: // go to another level, possibly if (eater->in_act) return 1; if (eater->query_act_type()!= ACT_CONTROL || (eater->skip_exit > 1)) return 1; eater->skip_exit = 10; // See if there are any enemies left ... if (screenp->level_done == 0) guys_here = 1; else guys_here = 0; // Get the name of our exit.. sprintf(message, "scen%d", stats->level); strcpy(exitname, myscreen->get_scen_title(message, myscreen) ); //buffers: PORT: using strcmp instead of stricmp if (!strcmp(exitname, "none")) sprintf(exitname, "Level %d", stats->level); leftside = 160 - ( (strlen(exitname) + 18) * 3); rightside = 160 + ( (strlen(exitname) + 18) * 3); // First check to see if we're withdrawing into // somewhere we've been, in which case we abort // this level, and set our current level to // that pointed to by the exit ... if ( screenp->is_level_completed(stats->level) && !screenp->is_level_completed(screenp->scen_num) && (guys_here != 0) ) // okay to leave { leftside -= 12; rightside += 12; char buf[40]; snprintf(buf, 40, "Withdraw to %s?", exitname); bool result = yes_or_no_prompt("Exit Field", buf, false); // Redraw screen .. screenp->redrawme = 1; if (result) // accepted level change { clear_keyboard(); // Delete all of our current information and abort .. here = myscreen->oblist; while (here) { if (here->ob && here->ob->query_order() == ORDER_LIVING) { //myscreen->remove_ob(here->ob); here->ob->dead = 1; myscreen->myobmap->remove (here->ob); //myscreen->remove_obmap(here->ob); } here = here->next; } //here = myscreen->fxlist; //while (here) //{ // if (here->ob) // myscreen->remove_fx_ob(here->ob); // here = here->next; //} // Now load the game as it was ... load_saved_game("save0", myscreen); myscreen->scen_num = (short) (stats->level-1); myscreen->end = 1; save_game("save0", myscreen); retreat = 1; return screenp->endgame(1, stats->level); // retreat } // end of accepted withdraw to new level .. clear_keyboard(); } // end of checking for withdrawal to completed level //buffers: also, allow exit if scenario_type == can exit if (!guys_here || (screenp->scenario_type == SCEN_TYPE_CAN_EXIT)) // nobody evil left, so okay to exit level .. { char buf[40]; snprintf(buf, 40, "Exit to %s?", exitname); bool result = yes_or_no_prompt("Exit Field", buf, false); // Redraw screen .. screenp->redrawme = 1; if(result) // accepted level change { clear_keyboard(); //screenp->levelstatus[screenp->scen_num] = 1; return screenp->endgame(0, stats->level); } clear_keyboard(); return 1; } return 1; case FAMILY_TELEPORTER: if (eater->skip_exit > 1) return 1; distance = distance_to_ob_center(eater); // how away? if (distance > 21) return 1; if (distance < 4 && eater->skip_exit) { //eater->skip_exit++; eater->skip_exit = 8; return 1; } // If we're close enough, teleport .. eater->skip_exit += 20; if (!leader) target = find_teleport_target(); else target = leader; if (!target) return 1; leader = target; eater->center_on(target); if (!screenp->query_passable(eater->xpos, eater->ypos, eater)) { eater->center_on(this); return 1; } // Now do special effects flash = screenp->add_ob(ORDER_FX, FAMILY_FLASH); flash->ani_type = ANI_EXPAND_8; flash->center_on(this); return 1; case FAMILY_LIFE_GEM: // get back some of lost man's xp .. if (eater->team_num != team_num) // only our team can get these return 1; myscreen->m_score[eater->team_num] += stats->hitpoints; flash = screenp->add_ob(ORDER_FX, FAMILY_FLASH); flash->ani_type = ANI_EXPAND_8; flash->center_on(this); dead = 1; death(); return 1; case FAMILY_KEY: // get the key to this door .. if (!(eater->keys & (Sint32)(pow((double) 2, stats->level)) )) // just got it? { eater->keys |= (Sint32) (pow((double)2, stats->level)); // ie, 2, 4, 8, 16... if (eater->myguy) sprintf(message, "%s picks up key %d", eater->myguy->name, stats->level); else sprintf(message, "%s picks up key %d", eater->stats->name, stats->level); if (eater->team_num == 0) // only show players picking up keys { myscreen->do_notify(message, eater); if (eater->on_screen()) myscreen->soundp->play_sound(SOUND_MONEY); } } return 1; default: return 1; } // end of treasure-check }
bool results_screen(int ending, int nextlevel, std::map<int, guy*>& before, std::map<int, walker*>& after) { // Popup the ending dialog show_ending_popup(ending, nextlevel); LevelData& level_data = myscreen->level_data; SaveData& save_data = myscreen->save_data; int num_foes_left = get_num_foes(level_data); int num_foes_total = 0; { LevelData original_level(level_data.id); original_level.load(); num_foes_total = get_num_foes(original_level); } text& mytext = myscreen->text_normal; text& bigtext = myscreen->text_big; Uint32 bonuscash[4] = {0, 0, 0, 0}; Uint32 allscore = 0, allbonuscash = 0; for(int i = 0; i < 4; i++) allscore += save_data.m_score[i]; if(ending == 0) // we won { // Calculate bonuses for (int i = 0; i < 4; i++) { bonuscash[i] = get_time_bonus(i); allbonuscash += bonuscash[i]; } if (save_data.is_level_completed(save_data.scen_num)) // already won, no bonus { for(int i = 0; i < 4; i++) bonuscash[i] = 0; allbonuscash = 0; } } // Now show the results std::set<int> used_troops; std::vector<TroopResult> troops; // Get the guys from "before" for(std::map<int, guy*>::iterator e = before.begin(); e != before.end(); e++) { used_troops.insert(e->first); troops.push_back(TroopResult(e->second, after[e->first])); } // Get the ones from "after" that weren't in "before" for(std::map<int, walker*>::iterator e = after.begin(); e != after.end(); e++) { if(used_troops.insert(e->first).second) troops.push_back(TroopResult(before[e->first], e->second)); } walker* mvp = NULL; float mvp_points = 0; for(std::vector<TroopResult>::iterator e = troops.begin(); e != troops.end(); e++) { float points = 0; if(e->after == NULL) continue; points = e->after->myguy->scen_damage + 3*e->after->myguy->scen_damage_taken; if(mvp_points < points) { mvp = e->after; mvp_points = points; } } // Hold indices for troops std::vector<int> recruits; std::vector<int> losses; int i = 0; for(std::vector<TroopResult>::iterator e = troops.begin(); e != troops.end(); e++) { if(e->is_dead()) losses.push_back(i); else if(e->is_new()) recruits.push_back(i); i++; } bool retry = false; int mode = 0; float scroll = 0.0f; int frame = 0; Sint16 screenW = 320; Sint16 screenH = 200; SDL_Rect area; area.x = 50; area.y = 20; area.w = screenW - 2*area.x; area.h = screenH - 2*area.y; SDL_Rect area_inner = {area.x + 3, area.y + 17, area.w - 6, area.h - 34}; // Buttons SDL_Rect ok_rect = {Sint16(area.x + area.w/2 - 45), Sint16(area.y + area.h - 14), 35, 10}; SDL_Rect retry_rect = {Sint16(area.x + area.w/2 + 10), Sint16(area.y + area.h - 14), 35, 10}; SDL_Rect overview_rect = {Sint16(area.x + area.w/2 - 100), Sint16(area.y + 4), 50, 10}; SDL_Rect troops_rect = {Sint16(area.x + area.w/2 + 50), Sint16(area.y + 4), 50, 10}; // Controller input int retvalue = 0; int highlighted_button = 0; int ok_index = 0; int retry_index = 1; int overview_index = 2; int troops_index = 3; int num_buttons = 4; button buttons[] = { button("OK", KEYSTATE_UNKNOWN, ok_rect.x, ok_rect.y, ok_rect.w, ok_rect.h, 0, -1 , MenuNav::UpRight(overview_index, retry_index)), button("RETRY", KEYSTATE_UNKNOWN, retry_rect.x, retry_rect.y, retry_rect.w, retry_rect.h, 0, -1 , MenuNav::UpLeft(troops_index, ok_index)), button("OVERVIEW", KEYSTATE_UNKNOWN, overview_rect.x, overview_rect.y, overview_rect.w, overview_rect.h, 0, -1 , MenuNav::DownRight(ok_index, troops_index)), button("TROOPS", KEYSTATE_UNKNOWN, troops_rect.x, troops_rect.y, troops_rect.w, troops_rect.h, 0, -1 , MenuNav::DownLeft(retry_index, overview_index)), }; bool done = false; while (!done) { // Reset the timer count to zero ... reset_timer(); if(myscreen->end) break; // Get keys and stuff get_input_events(POLL); handle_menu_nav(buttons, highlighted_button, retvalue, false); // Mouse stuff .. MouseState& mymouse = query_mouse(); int mx = mymouse.x; int my = mymouse.y; #ifdef USE_CONTROLLER_INPUT { const OuyaController& c = OuyaControllerManager::getController(0); float v = c.getAxisValue(OuyaController::AXIS_LS_Y) + c.getAxisValue(OuyaController::AXIS_RS_Y); if(fabs(v) > OuyaController::DEADZONE) scroll -= -5*v; } #else scroll -= get_and_reset_scroll_amount(); #endif if(scroll < 0.0f) scroll = 0.0f; bool do_click = mymouse.left; bool do_ok = ((do_click && ok_rect.x <= mx && mx <= ok_rect.x + ok_rect.w && ok_rect.y <= my && my <= ok_rect.y + ok_rect.h) || (retvalue == OG_OK && highlighted_button == ok_index)); bool do_retry = ((do_click && retry_rect.x <= mx && mx <= retry_rect.x + retry_rect.w && retry_rect.y <= my && my <= retry_rect.y + retry_rect.h) || (retvalue == OG_OK && highlighted_button == retry_index)); bool do_overview = ((do_click && overview_rect.x <= mx && mx <= overview_rect.x + overview_rect.w && overview_rect.y <= my && my <= overview_rect.y + overview_rect.h) || (retvalue == OG_OK && highlighted_button == overview_index)); bool do_troops = ((do_click && troops_rect.x <= mx && mx <= troops_rect.x + troops_rect.w && troops_rect.y <= my && my <= troops_rect.y + troops_rect.h) || (retvalue == OG_OK && highlighted_button == troops_index)); if (mymouse.left) { while(mymouse.left) get_input_events(WAIT); } // Ok if(do_ok) { myscreen->soundp->play_sound(SOUND_BOW); done = true; } // Retry else if(do_retry) { myscreen->soundp->play_sound(SOUND_BOW); const char* msg = (ending == 0? "Try this level again?\nYou will lose your progress\non this level." : "Try this level again?"); if(yes_or_no_prompt("Retry level", msg, false)) { // Try again done = true; retry = true; } } // Overview else if(do_overview) { myscreen->soundp->play_sound(SOUND_BOW); mode = 0; } // Troops else if(do_troops) { myscreen->soundp->play_sound(SOUND_BOW); mode = 1; } retvalue = 0; // Draw myscreen->draw_button(area.x, area.y, area.x + area.w - 1, area.y + area.h - 1, 1, 1); myscreen->draw_button_inverted(area_inner.x, area_inner.y, area_inner.w, area_inner.h); bigtext.write_xy_center(area.x + area.w/2, area.y + 4, RED, "RESULTS"); int y = 0; if(mode == 0) { // Overview int x = area.x + 12; y = area.y + 30 - scroll; if(ending == 0) { // TODO: Show total possible gold collected? How is this factored into allscore? if(area_inner.y < y && y + 10 < area_inner.y + area_inner.h) { char buf[50]; snprintf(buf, 50, "%d", allscore*2); mytext.write_xy_center_shadow(area.x + area.w/2, y, YELLOW, "%s Gold ", buf); memset(buf, ' ', strlen(buf)); mytext.write_xy_center(area.x + area.w/2, y, DARK_BLUE, "%s Gained", buf); } if(area_inner.y < y && y + 10 < area_inner.y + area_inner.h) { if(allbonuscash > 0) { mytext.write_xy_center_shadow(area.x + area.w/2, y + 9, YELLOW, "+ %d Time Bonus", allbonuscash); } } y += 22; } BEGIN_IF_IN_SCROLL_AREA; if(ending == 0) { char buf[50]; snprintf(buf, 50, "%d", num_foes_total - num_foes_left); mytext.write_xy_center_shadow(area.x + area.w/2, y, PURE_WHITE, "%s Foes ", buf); memset(buf, ' ', strlen(buf)); mytext.write_xy_center(area.x + area.w/2, y, DARK_BLUE, "%s Defeated", buf); } else { char buf[50]; char buf2[50]; snprintf(buf, 50, "%d", num_foes_total - num_foes_left); snprintf(buf2, 50, "%d", num_foes_total); mytext.write_xy_center_shadow(area.x + area.w/2, y, PURE_WHITE, "%s of %s Foes ", buf, buf2); memset(buf, ' ', strlen(buf)); memset(buf2, ' ', strlen(buf2)); mytext.write_xy_center(area.x + area.w/2, y, DARK_BLUE, "%s %s Defeated", buf, buf2); } END_IF_IN_SCROLL_AREA; y += 22; if(mvp != NULL) { BEGIN_IF_IN_SCROLL_AREA; mytext.write_xy_center(area.x + area.w/2, y, DARK_BLUE, "MVP: %s the %s", mvp->myguy->name, get_family_string(mvp->myguy->family)); mytext.write_xy_center(area.x + area.w/2, y + 8, DARK_BLUE, "(%.0f pts)", mvp_points); y += 22; END_IF_IN_SCROLL_AREA; } if(ending == 0 && recruits.size() > 0) { BEGIN_IF_IN_SCROLL_AREA; mytext.write_xy(x, y, DARK_BLUE, "%d Recruits:", recruits.size()); END_IF_IN_SCROLL_AREA; y += 22; for(std::vector<int>::iterator e = recruits.begin(); e != recruits.end(); e++) { BEGIN_IF_IN_SCROLL_AREA; mytext.write_xy(x, y, DARK_BLUE, " + %s the %s LVL %d", troops[*e].get_name().c_str(), troops[*e].get_class_name().c_str(), troops[*e].get_level()); END_IF_IN_SCROLL_AREA; y += 11; } y += 11; } if(ending != 1 && losses.size() > 0) // won or lost due to NPC { BEGIN_IF_IN_SCROLL_AREA; mytext.write_xy(x, y, DARK_BLUE, "%d Losses:", losses.size()); END_IF_IN_SCROLL_AREA; y += 22; for(std::vector<int>::iterator e = losses.begin(); e != losses.end(); e++) { BEGIN_IF_IN_SCROLL_AREA; mytext.write_xy(x, y, DARK_BLUE, " - %s the %s LVL %d", troops[*e].get_name().c_str(), troops[*e].get_class_name().c_str(), troops[*e].get_level()); END_IF_IN_SCROLL_AREA; y += 11; } y += 11; } } else if(mode == 1) { int barH = 5; // Troops y = area.y + 30 - scroll; for(size_t i = 0; i < troops.size(); i++) { int x = area.x + 12; int tallies = troops[i].get_tallies(); BEGIN_IF_IN_SCROLL_AREA; int name_w = mytext.write_xy(x, y, PURE_BLACK, "%s", troops[i].get_name().c_str()); name_w += mytext.write_xy(x + name_w, y, PURE_BLACK + 2, " the %s", troops[i].get_class_name().c_str()); if(troops[i].gained_level()) mytext.write_xy(x + name_w, y, YELLOW, " LVL UP %d", troops[i].get_level()); else if(troops[i].lost_level()) mytext.write_xy(x + name_w, y, RED, " LVL DOWN %d", troops[i].get_level()); else mytext.write_xy(x + name_w, y, DARK_GREEN, " LVL %d", troops[i].get_level()); END_IF_IN_SCROLL_AREA; y += 10; BEGIN_IF_IN_SCROLL_AREA; troops[i].draw_guy(x + 5, y + 2, frame*troops[i].get_HP()); // HP if(troops[i].is_dead()) { mytext.write_xy(x + 15, y, RED, "LOST"); } else { x += 15; mytext.write_xy(x, y, RED, "HP"); x += 14; myscreen->fastbox(x, y, 60*troops[i].get_HP(), barH, RED); myscreen->fastbox_outline(x, y, 60, barH, PURE_BLACK); // XP x += 70; mytext.write_xy(x, y, DARK_GREEN, "EXP"); x += 20; float base = 60*troops[i].get_XP_base(); float gain = 60*troops[i].get_XP_gain(); if(gain >= 0) { myscreen->fastbox(x, y, base, barH, DARK_GREEN); myscreen->fastbox(x + base, y, gain, barH, LIGHT_GREEN); } else myscreen->fastbox(x + 60 + gain, y, -gain, barH, RED); myscreen->fastbox_outline(x, y, 60, barH, PURE_BLACK); if(gain > 0.0f) mytext.write_xy(x + 63, y, DARK_GREEN, "+"); else if(gain < 0.0f) mytext.write_xy(x + 63, y, RED, "-"); } END_IF_IN_SCROLL_AREA; if(tallies > 0) { y += 10; BEGIN_IF_IN_SCROLL_AREA; mytext.write_xy(area.x + 20, y, DARK_GREEN, "%d Tall%s", tallies, (tallies == 1? "y" : "ies")); END_IF_IN_SCROLL_AREA; } if(troops[i].gained_level()) { std::vector<std::string> specials = troops[i].get_gained_specials(); if(specials.size() > 0) { y += 10; BEGIN_IF_IN_SCROLL_AREA; mytext.write_xy(area.x + 20, y, DARK_BLUE, "Gained special%s:", (specials.size() == 1? "" : "s")); END_IF_IN_SCROLL_AREA; for(std::vector<std::string>::iterator e = specials.begin(); e != specials.end(); e++) { y += 10; BEGIN_IF_IN_SCROLL_AREA; mytext.write_xy(area.x + 30, y, DARK_BLUE, "%s", (*e).c_str()); END_IF_IN_SCROLL_AREA; } } } y += 13; BEGIN_IF_IN_SCROLL_AREA; myscreen->hor_line(area_inner.x + 6, y - 3, area_inner.w - 30, GREY - 4); END_IF_IN_SCROLL_AREA; } } // Draw scroll indicator if(y + scroll > area_inner.y + area_inner.h - 30) { myscreen->ver_line(area_inner.x, area_inner.y + (area_inner.h) * scroll/(y + scroll - area.y), 6, PURE_BLACK); } // Limit the scrolling depending on how long 'y' is. if(y < area_inner.y + 30) scroll = y + scroll - (area_inner.y + 30); for(int i = 0; i < num_buttons; i++) { if((mode == 0 && i == overview_index) || (mode == 1 && i == troops_index)) myscreen->draw_button_inverted(buttons[i].x, buttons[i].y, buttons[i].sizex, buttons[i].sizey); else myscreen->draw_button(buttons[i].x, buttons[i].y, buttons[i].x + buttons[i].sizex - 1, buttons[i].y + buttons[i].sizey - 1, 1, 1); mytext.write_xy(buttons[i].x + buttons[i].sizex/2 - 3*buttons[i].label.size(), buttons[i].y + 2, buttons[i].label.c_str(), DARK_BLUE, 1); } draw_highlight(buttons[highlighted_button]); myscreen->buffer_to_screen(0, 0, 320, 200); SDL_Delay(10); frame++; if(frame > 1000000) frame = 0; } return retry; }