示例#1
0
bool play_controller::hotkey_handler::execute_command(const hotkey::hotkey_command& cmd, int index)
{
	hotkey::HOTKEY_COMMAND command = cmd.id;
	if(index >= 0) {
		unsigned i = static_cast<unsigned>(index);
		if(i < savenames_.size() && !savenames_[i].empty()) {
			// Load the game by throwing load_game_exception
			throw game::load_game_exception(savenames_[i],false,false,false,"",true);

		} else if ( i < wml_commands_.size()  &&  wml_commands_[i] ) {
			if (!wml_command_pager_->capture(*wml_commands_[i])) {
				wml_commands_[i]->fire_event(mouse_handler_.get_last_hex(), gamestate().gamedata_);
			} else { //relaunch the menu
				show_menu(gui()->get_theme().context_menu()->items(),last_context_menu_x_,last_context_menu_y_,true, *gui());
			}
			return true;
		}
	}
	int prefixlen = wml_menu_hotkey_prefix.length();
	if(command == hotkey::HOTKEY_WML && cmd.command.compare(0, prefixlen, wml_menu_hotkey_prefix) == 0)
	{
		std::string name = cmd.command.substr(prefixlen);
		const map_location& hex = mouse_handler_.get_last_hex();

		gamestate().gamedata_.get_wml_menu_items().fire_item(name, hex, gamestate().gamedata_, gamestate(), gamestate().board_.units_);
		/// @todo Shouldn't the function return at this point?
	}
	return command_executor::execute_command(cmd, index);
}
示例#2
0
void play_controller::check_time_over()
{
    const bool time_left = gamestate().tod_manager_.next_turn(&gamestate().gamedata_);

    if(!time_left) {
        LOG_NG << "firing time over event...\n";
        set_scontext_synced_base sync;
        pump().fire("time_over");
        LOG_NG << "done firing time over event...\n";
        // If turns are added while handling 'time over' event.
        if (gamestate().tod_manager_.is_time_left()) {
            return;
        }

        if(gui_->video().non_interactive()) {
            LOG_AIT << "time over (draw)\n";
            ai_testing::log_draw();
        }

        check_victory();
        if (is_regular_game_end()) {
            return;
        }
        end_level_data e;
        e.proceed_to_next_level = false;
        e.is_victory = false;
        set_end_level_data(e);
    }
}
void playsingle_controller::init_gui(){
	LOG_NG << "Initializing GUI... " << (SDL_GetTicks() - ticks()) << "\n";
	play_controller::init_gui();

	// Scroll to the starting position of the first team. If there is a
	// human team, use that team; otherwise use team 1. If the map defines
	// a starting position for the selected team, scroll to that tile. Note
	// this often does not matter since many scenario start with messages,
	// which will usually scroll to the speaker. Also note that the map
	// does not necessarily define the starting positions. While usually
	// best to use the map, the scenarion may explicitly set the positions,
	// overriding those found in the map (if any).
	{
		int scroll_team = gamestate().first_human_team_ + 1;
		if (scroll_team == 0) {
			scroll_team = 1;
		}
		map_location loc(gamestate().board_.map().starting_position(scroll_team));
		if ((loc.x >= 0) && (loc.y >= 0)) {
			gui_->scroll_to_tile(loc, game_display::WARP);
		}
	}

	update_locker lock_display(gui_->video(), is_skipping_replay());
	gui_->draw();
	get_hotkey_command_executor()->set_button_state();
	events::raise_draw_event();
}
void playsingle_controller::play_scenario_main_loop()
{
	LOG_NG << "starting main loop\n" << (SDL_GetTicks() - ticks()) << "\n";


	// Avoid autosaving after loading, but still
	// allow the first turn to have an autosave.
	ai_testing::log_game_start();
	if(gamestate().board_.teams().empty())
	{
		ERR_NG << "Playing game with 0 teams." << std::endl;
	}
	while(true) {
		try {
			play_turn();
			if (is_regular_game_end()) {
				turn_data_.send_data();
				return;
			}
			gamestate_->player_number_ = 1;
		}
		catch(const reset_gamestate_exception& ex) {
			//
			// TODO:
			//
			// The MP replay feature still doesn't work properly (causes OOS)
			// because:
			//
			// 1) The undo stack is not reset along with the gamestate (fixed).
			// 2) The server_request_number_ is not reset along with the
			//    gamestate (fixed).
			// 3) chat and other unsynced actions are inserted in the middle of
			//    the replay bringing the replay_pos in unorder (fixed).
			// 4) untracked changes in side controllers are lost when resetting
			//    gamestate (fixed).
			// 5) The game should have a stricter check for whether the loaded
			//    game is actually a parent of this game.
			// 6) If an action was undone after a game was saved it can cause
			//    OOS if the undone action is in the snapshot of the saved
			//    game (luckily this is never the case for autosaves).
			//
			boost::dynamic_bitset<> local_players;
			local_players.resize(gamestate().board_.teams().size(), true);
			//Preserve side controllers, becasue we won't get the side controoller updates again when replaying.
			for(size_t i = 0; i < local_players.size(); ++i) {
				local_players[i] = gamestate().board_.teams()[i].is_local();
			}
			reset_gamestate(*ex.level, (*ex.level)["replay_pos"]);
			for(size_t i = 0; i < local_players.size(); ++i) {
				resources::gameboard->teams()[i].set_local(local_players[i]);
			}
			play_scenario_init();
			replay_.reset(new replay_controller(*this, false, ex.level));
			if(ex.start_replay) {
				replay_->play_replay();
			}
		}
	} //end for loop
}
示例#5
0
void play_controller::tab()
{
    gui::TEXTBOX_MODE mode = menu_handler_.get_textbox().mode();

    std::set<std::string> dictionary;
    switch(mode) {
    case gui::TEXTBOX_SEARCH:
    {
        for (const unit& u : gamestate().board_.units()) {
            const map_location& loc = u.get_location();
            if(!gui_->fogged(loc) &&
                    !(gamestate().board_.teams()[gui_->viewing_team()].is_enemy(u.side()) && u.invisible(loc, gui_->get_disp_context())))
                dictionary.insert(u.name());
        }
        //TODO List map labels
        break;
    }
    case gui::TEXTBOX_COMMAND:
    {
        std::vector<std::string> commands = menu_handler_.get_commands_list();
        dictionary.insert(commands.begin(), commands.end());
        // no break here, we also want player names from the next case
    }
    case gui::TEXTBOX_MESSAGE:
    {
        for (const team& t : gamestate().board_.teams()) {
            if(!t.is_empty())
                dictionary.insert(t.current_player());
        }

        // Add observers
        for (const std::string& o : gui_->observers()) {
            dictionary.insert(o);
        }

        // Add nicks who whispered you
        for (const std::string& w : gui_->get_chat_manager().whisperers()) {
            dictionary.insert(w);
        }

        // Add nicks from friendlist
        const std::map<std::string, std::string> friends = preferences::get_acquaintances_nice("friend");

        for(std::map<std::string, std::string>::const_iterator iter = friends.begin(); iter != friends.end(); ++iter) {
            dictionary.insert((*iter).first);
        }

        //Exclude own nick from tab-completion.
        //NOTE why ?
        dictionary.erase(preferences::login());
        break;
    }

    default:
        ERR_DP << "unknown textbox mode" << std::endl;
    } //switch(mode)

    menu_handler_.get_textbox().tab(dictionary);
}
示例#6
0
void replay_savegame::write_game(config_writer &out) {
	savegame::write_game(out);
	
	gamestate().write_carryover(out);
	out.write_child("replay_start", gamestate().replay_start());
	out.write_child("replay", gamestate().replay_data);

}
示例#7
0
void ingame_savegame::create_filename()
{
	std::stringstream stream;

	const std::string ellipsed_name = font::make_text_ellipsis(gamestate().classification().label,
			font::SIZE_NORMAL, 200);
	stream << ellipsed_name << " " << _("Turn") << " " << gamestate().get_starting_pos()["turn_at"];
	set_filename(stream.str());
}
示例#8
0
void ingame_savegame::write_game(config_writer &out) {
	log_scope("write_game");

	savegame::write_game(out);
	
	gamestate().write_carryover(out);
	out.write_child("snapshot",snapshot());
	out.write_child("replay_start", gamestate().replay_start());
	out.write_child("replay", gamestate().replay_data);
}
示例#9
0
文件: menu.c 项目: slaeshjag/svgestim
void menu_handle(DARNIT_KEYS *keys, DARNIT_MOUSE *mouse) {
	if(keys->a)
		gamestate(GAMESTATE_GAME);
	else if(keys->b)
		gamestate(GAMESTATE_HIGHSCORE);
	else if(keys->x)
		gamestate(GAMESTATE_INSTRUCTIONS);
	else if(keys->y)
		gamestate(GAMESTATE_QUIT);
}
示例#10
0
void autosave_savegame::create_filename()
{
	std::string filename;
	if (gamestate().classification().label.empty())
		filename = _("Auto-Save");
	else
		filename = gamestate().classification().label + "-" + _("Auto-Save") + gamestate().get_starting_pos()["turn_at"];

	set_filename(filename);
}
示例#11
0
void playsingle_controller::check_objectives()
{
	if (!gamestate().board_.teams().empty()) {
		const team &t = gamestate().board_.teams()[gui_->viewing_team()];

		if (!is_regular_game_end() && !is_browsing() && t.objectives_changed()) {
			show_objectives();
		}
	}
}
示例#12
0
void replay_savegame::write_game(config_writer &out) {
	savegame::write_game(out);

	gamestate().write_carryover(out);
	out.write_child("replay_start", gamestate().replay_start());

	out.open_child("replay");
	gamestate().get_replay().write(out);
	out.close_child("replay");

}
示例#13
0
void ingame_savegame::write_game(config_writer &out) {
	log_scope("write_game");

	savegame::write_game(out);

	gamestate().write_carryover(out);
	out.write_child("snapshot",gamestate().get_starting_pos());
	out.write_child("replay_start", gamestate().replay_start());
	out.open_child("replay");
	gamestate().get_replay().write(out);
	out.close_child("replay");
}
示例#14
0
void scenariostart_savegame::before_save()
{
	//Add the player section to the starting position so we can get the correct recall list
	//when loading the replay later on
	// if there is no scenario information in the starting pos, add the (persistent) sides from the snapshot
	// else do nothing, as persistence information was already added at the end of the previous scenario
	if (gamestate().starting_pos["id"].empty()) {
		foreach(const config &snapshot_side, gamestate().snapshot.child_range("side")) {
			//add all side tags (assuming they only contain carryover information)
			gamestate().starting_pos.add_child("side", snapshot_side);
		}
	}
示例#15
0
int play_controller::find_last_visible_team() const
{
    assert(current_side() <= int(gamestate().board_.teams().size()));
    const int num_teams = gamestate().board_.teams().size();
    const bool is_observer = this->is_observer();

    for(int i = 0; i < num_teams; i++) {
        const int team_num = modulo(current_side() - i, num_teams, 1);
        if(is_team_visible(team_num, is_observer)) {
            return team_num;
        }
    }
    return 0;
}
示例#16
0
void playsingle_controller::init_gui(){
	LOG_NG << "Initializing GUI... " << (SDL_GetTicks() - ticks()) << "\n";
	play_controller::init_gui();

	if(gamestate().first_human_team_ != -1) {
		gui_->scroll_to_tile(gamestate().board_.map().starting_position(gamestate().first_human_team_ + 1), game_display::WARP);
	}
	gui_->scroll_to_tile(gamestate().board_.map().starting_position(1), game_display::WARP);

	update_locker lock_display(gui_->video(), is_skipping_replay());
	gui_->draw();
	get_hotkey_command_executor()->set_button_state();
	events::raise_draw_event();
}
示例#17
0
void play_controller::play_turn()
{
    whiteboard_manager_->on_gamestate_change();
    gui_->new_turn();
    gui_->invalidate_game_status();
    events::raise_draw_event();

    LOG_NG << "turn: " << turn() << "\n";

    if(gui_->video().non_interactive()) {
        LOG_AIT << "Turn " << turn() << ":" << std::endl;
    }

    for (; gamestate_->player_number_ <= int(gamestate().board_.teams().size()); ++gamestate_->player_number_)
    {
        // If a side is empty skip over it.
        if (current_team().is_empty()) {
            continue;
        }
        init_side_begin();
        if(gamestate_->init_side_done()) {
            // This is the case in a reloaded game where the side was initialized before saving the game.
            init_side_end();
        }

        ai_testing::log_turn_start(current_side());
        play_side();
        if(is_regular_game_end()) {
            return;
        }
        finish_side_turn();
        if(is_regular_game_end()) {
            return;
        }
        if(gui_->video().non_interactive()) {
            LOG_AIT << " Player " << current_side() << ": " <<
                    current_team().villages().size() << " Villages" <<
                    std::endl;
            ai_testing::log_turn_end(current_side());
        }
    }
    // If the loop exits due to the last team having been processed.
    gamestate_->player_number_ = gamestate().board_.teams().size();

    finish_turn();

    // Time has run out
    check_time_over();
}
示例#18
0
文件: menu.c 项目: slaeshjag/svgestim
void gameover_handle(DARNIT_KEYS *keys, DARNIT_MOUSE *mouse) {
	if (highscore_is_new(score)) {
		d_render_begin();
		if (d_menu_loop(highscore.name) != -1) {
			if (*highscore.name_buff < 0x20)
				sprintf(highscore.name_buff, "arne.");
			highscore_add(score, highscore.name_buff);
			gamestate(GAMESTATE_HIGHSCORE);
		}
		d_render_end();
	}

	else if(keys->start)
		gamestate(GAMESTATE_MENU);
}
示例#19
0
int main(int argc, char **argv) {
	DARNIT_KEYS keys;
	DARNIT_MOUSE mouse;
	//particle_emitter_new(30, 5000, 8000, 10000, 255, 0, 0, PARTICLE_TYPE_PULSE, 400, 240, 0, -100, 100);
	//particle_emitter_new(30, 5000, 8000, 10000, 255, 255, 0, PARTICLE_TYPE_PULSE, 400, 240, 0, -100, 100);
	
	init();
	gamestate(GAMESTATE_MENU);
	
	while(_gamestate!=GAMESTATE_QUIT) {
		keys=d_keys_get();
		mouse=d_mouse_get();
		
		if(handle[_gamestate])
			handle[_gamestate](&keys, &mouse);
		d_render_begin();
		if(render[_gamestate])
			render[_gamestate]();
		d_render_end();
		d_loop();
	}
	
	d_quit();
	return 0;
}
示例#20
0
void playmp_controller::maybe_linger()
{
	// mouse_handler expects at least one team for linger mode to work.
	assert(is_regular_game_end());
	if (!get_end_level_data_const().transient.linger_mode || gamestate().board_.teams().empty() || gui_->video().faked()) {
		const bool has_next_scenario = !gamestate().gamedata_.next_scenario().empty() && gamestate().gamedata_.next_scenario() != "null";
		if(!is_host() && has_next_scenario) {
			// If we continue without lingering we need to
			// make sure the host uploads the next scenario
			// before we attempt to download it.
			wait_for_upload();
		}
	} else {
		linger();
	}
}
示例#21
0
void play_controller::process_keyup_event(const SDL_Event& event)
{
    // If the user has pressed 1 through 9, we want to show
    // how far the unit can move in that many turns
    if(event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9') {
        const int new_path_turns = (event.type == SDL_KEYDOWN) ?
                                   event.key.keysym.sym - '1' : 0;

        if(new_path_turns != mouse_handler_.get_path_turns()) {
            mouse_handler_.set_path_turns(new_path_turns);

            const unit_map::iterator u = mouse_handler_.selected_unit();

            if(u.valid()) {
                // if it's not the unit's turn, we reset its moves
                unit_movement_resetter move_reset(*u, u->side() != current_side());

                mouse_handler_.set_current_paths(pathfind::paths(*u, false,
                                                 true, gamestate().board_.teams_[gui_->viewing_team()],
                                                 mouse_handler_.get_path_turns()));

                gui_->highlight_reach(mouse_handler_.current_paths());
            } else {
                mouse_handler_.select_hex(mouse_handler_.get_selected_hex(), false, false, false);
            }

        }
    } else if (event.key.keysym.sym == SDLK_TAB) {
        static CKey keys;
        if (!keys[SDLK_TAB]) {
            whiteboard_manager_->set_invert_behavior(false);
        }
    }
}
示例#22
0
void playsingle_controller::enable_replay(bool is_unit_test)
{
	replay_.reset(new replay_controller(*this, gamestate().has_human_sides(), boost::shared_ptr<config>( new config(saved_game_.replay_start())), boost::bind(&playsingle_controller::on_replay_end, this, is_unit_test)));
	if(is_unit_test) {
		replay_->play_replay();
	}
}
示例#23
0
void play_controller::play_side()
{
    //check for team-specific items in the scenario
    gui_->parse_team_overlays();
    do {
        update_viewing_player();
        {
            save_blocker blocker;
            maybe_do_init_side();
            if(is_regular_game_end()) {
                return;
            }
        }
        // This flag can be set by derived classes (in overridden functions).
        player_type_changed_ = false;

        statistics::reset_turn_stats(gamestate().board_.teams()[current_side() - 1].save_id());

        play_side_impl();

        if(is_regular_game_end()) {
            return;
        }

    } while (player_type_changed_);
    // Keep looping if the type of a team (human/ai/networked)
    // has changed mid-turn
    sync_end_turn();
}
示例#24
0
void play_controller::fire_start()
{
    gamestate().gamedata_.set_phase(game_data::START);
    pump().fire("start");
    // start event may modify start turn with WML, reflect any changes.
    gamestate().gamedata_.get_variable("turn_number") = int(turn());
    check_objectives();
    // prestart and start events may modify the initial gold amount,
    // reflect any changes.
    for (team& tm : gamestate().board_.teams_)
    {
        tm.set_start_gold(tm.gold());
    }
    gamestate_->init_side_done() = false;
    gamestate().gamedata_.set_phase(game_data::PLAY);
}
示例#25
0
bool play_controller::hotkey_handler::in_context_menu(hotkey::HOTKEY_COMMAND command) const
{
	switch(command) {
	// Only display these if the mouse is over a castle or keep tile
	case hotkey::HOTKEY_RECRUIT:
	case hotkey::HOTKEY_REPEAT_RECRUIT:
	case hotkey::HOTKEY_RECALL: {
		// last_hex_ is set by mouse_events::mouse_motion
		const map_location & last_hex = mouse_handler_.get_last_hex();
		const int viewing_side = gui()->viewing_side();

		// A quick check to save us having to create the future map and
		// possibly loop through all units.
		if ( !play_controller_.get_map_const().is_keep(last_hex)  &&
		     !play_controller_.get_map_const().is_castle(last_hex) )
			return false;

		wb::future_map future; /* lasts until method returns. */

		return gamestate().side_can_recruit_on(viewing_side, last_hex);
	}
	default:
		return true;
	}
}
示例#26
0
void play_controller::finish_side_turn()
{
    whiteboard_manager_->on_finish_side_turn(current_side());

    {   //Block for set_scontext_synced
        set_scontext_synced sync(1);
        // Ending the turn commits all moves.
        undo_stack().clear();
        gamestate().board_.end_turn(current_side());
        const std::string turn_num = std::to_string(turn());
        const std::string side_num = std::to_string(current_side());

        // Clear shroud, in case units had been slowed for the turn.
        actions::clear_shroud(current_side());

        pump().fire("side_turn_end");
        pump().fire("side_"+ side_num + "_turn_end");
        pump().fire("side_turn_" + turn_num + "_end");
        pump().fire("side_" + side_num + "_turn_" + turn_num + "_end");
        // This is where we refog, after all of a side's events are done.
        actions::recalculate_fog(current_side());
        check_victory();
        sync.do_final_checkup();
    }

    mouse_handler_.deselect_hex();
    resources::gameboard->unit_id_manager().reset_fake();
    gamestate_->init_side_done() = false;
}
示例#27
0
void playsingle_controller::play_side_impl()
{
	if (!skip_next_turn_) {
		end_turn_ = END_TURN_NONE;
	}
	if(replay_.get() != NULL) {
		REPLAY_RETURN res = replay_->play_side_impl();
		if(res == REPLAY_FOUND_END_TURN) {
			end_turn_ = END_TURN_SYNCED;
		}
		if (player_type_changed_) {
			replay_.reset();
		}
	} else if((current_team().is_local_human() && current_team().is_proxy_human())) {
		LOG_NG << "is human...\n";
		// If a side is dead end the turn, but play at least side=1's
		// turn in case all sides are dead
		if (gamestate().board_.side_units(current_side()) == 0 && !(gamestate().board_.units().size() == 0 && current_side() == 1)) {
			end_turn_ = END_TURN_REQUIRED;
		}

		before_human_turn();
		if (end_turn_ == END_TURN_NONE) {
			play_human_turn();
		}
		if ( !player_type_changed_ && !is_regular_game_end()) {
			after_human_turn();
		}
		LOG_NG << "human finished turn...\n";

	} else if(current_team().is_local_ai() || (current_team().is_local_human() && current_team().is_droid())) {
		play_ai_turn();
	} else if(current_team().is_network()) {
		play_network_turn();
	} else if(current_team().is_local_human() && current_team().is_idle()) {
		end_turn_enable(false);
		do_idle_notification();
		before_human_turn();
		if (end_turn_ == END_TURN_NONE) {
			play_idle_loop();
		}
	}
	else {
		// we should have skipped over empty controllers before so this shouldn't be possible
		ERR_NG << "Found invalid side controller " << current_team().controller().to_string() << " (" << current_team().proxy_controller().to_string() << ") for side " << current_team().side() << "\n";
	}
}
示例#28
0
void play_controller::show_objectives() const
{
    const team& t = gamestate().board_.teams()[gui_->viewing_team()];
    static const std::string no_objectives(_("No objectives available"));
    std::string objectives = t.objectives();
    gui2::show_transient_message(gui_->video(), get_scenario_name(), (objectives.empty() ? no_objectives : objectives), "", true);
    t.reset_objectives_changed();
}
示例#29
0
void play_controller::fire_prestart()
{
    // pre-start events must be executed before any GUI operation,
    // as those may cause the display to be refreshed.
    update_locker lock_display(gui_->video());
    gamestate().gamedata_.set_phase(game_data::PRESTART);

    // Fire these right before prestart events, to catch only the units sides
    // have started with.
    for (const unit& u : gamestate().board_.units()) {
        pump().fire("unit_placed", map_location(u.get_location()));
    }

    pump().fire("prestart");
    // prestart event may modify start turn with WML, reflect any changes.
    gamestate().gamedata_.get_variable("turn_number") = int(turn());
}
示例#30
0
void playsingle_controller::maybe_linger()
{
	// mouse_handler expects at least one team for linger mode to work.
	assert(is_regular_game_end());
	if (get_end_level_data_const().transient.linger_mode && !gamestate().board_.teams().empty()) {
		linger();
	}
}