Пример #1
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;
}
Пример #2
0
void play_controller::reset_gamestate(const config& level, int replay_pos)
{
    resources::gameboard = nullptr;
    resources::gamedata = nullptr;
    resources::tod_manager = nullptr;
    resources::units = nullptr;
    resources::filter_con = nullptr;
    resources::lua_kernel = nullptr;
    resources::game_events = nullptr;
    resources::tunnels = nullptr;
    resources::undo_stack = nullptr;

    gui_->labels().set_team(nullptr);

    gamestate_.reset(new game_state(level, *this, tdata_));
    resources::gameboard = &gamestate().board_;
    resources::gamedata = &gamestate().gamedata_;
    resources::tod_manager = &gamestate().tod_manager_;
    resources::units = &gamestate().board_.units_;
    resources::filter_con = &gamestate();
    resources::undo_stack = &undo_stack();
    resources::game_events = gamestate().events_manager_.get();
    resources::lua_kernel = gamestate().lua_kernel_.get();

    gamestate_->init(level, *this);
    gamestate().set_game_display(gui_.get());
    resources::tunnels = gamestate().pathfind_manager_.get();

    gui_->reset_tod_manager(gamestate().tod_manager_);
    gui_->reset_reports(*gamestate().reports_);
    gui_->change_display_context(&gamestate().board_);
    saved_game_.get_replay().set_pos(replay_pos);
    gamestate().gamedata_.set_phase(game_data::PRELOAD);
    gamestate().lua_kernel_->load_game(level);
}
Пример #3
0
void playmp_controller::send_user_choice()
{
	// when using a remote user choice undoing must be impossible because that network traffic cannot be undone
	// Also turn_data_.send_data() won't work if the undo stack isn't empty because undoable moves won't be sended
	// Also undo_stack()clear() must be called synced so we cannot do that here.
	assert(!undo_stack().can_undo());
	turn_data_.send_data();
}
Пример #4
0
void playmp_controller::pull_remote_choice()
{
	// when using a remote user choice undoing must be impossible because that network traffic cannot be undone
	// Also turn_data_.sync_network() (which calls turn_data_.send_data()) won't work if the undo stack isn't empty because undoable moves won't be sended
	// Also undo_stack()clear() must be called synced so we cannot do that here.
	assert(!undo_stack().can_undo());
	turn_info::PROCESS_DATA_RESULT res = turn_data_.sync_network();
	assert(res != turn_info::PROCESS_END_LINGER);
	assert(res != turn_info::PROCESS_END_TURN);
	if(res == turn_info::PROCESS_RESTART_TURN)
	{
		player_type_changed_ = true;
	}
}
Пример #5
0
void playsingle_controller::play_ai_turn()
{
	LOG_NG << "is ai...\n";

	end_turn_enable(false);
	gui_->recalculate_minimap();

	const cursor::setter cursor_setter(cursor::WAIT);

	// Correct an oddball case where a human could have left delayed shroud
	// updates on before giving control to the AI. (The AI does not bother
	// with the undo stack, so it cannot delay shroud updates.)
	team & cur_team = current_team();
	if ( !cur_team.auto_shroud_updates() ) {
		// We just took control, so the undo stack is empty. We still need
		// to record this change for the replay though.
		synced_context::run_and_store("auto_shroud", replay_helper::get_auto_shroud(true));
	}
	undo_stack().clear();

	turn_data_.send_data();
	try {
		try {
			if (!should_return_to_play_side()) {
				ai::manager::play_turn(current_side());
			}
		}
		catch (return_to_play_side_exception&) {
		}
		catch (fallback_ai_to_human_exception&) {
			current_team().make_human();
			player_type_changed_ = true;
		}
	}
	catch(...) {
		turn_data_.sync_network();
		throw;
	}
	if(!should_return_to_play_side()) {
		end_turn_ = END_TURN_REQUIRED;
	}
	turn_data_.sync_network();
	gui_->recalculate_minimap();
	gui_->invalidate_unit();
	gui_->invalidate_game_status();
	gui_->invalidate_all();
	gui_->draw();
}
Пример #6
0
void GameView::dropEvent(QDropEvent *event)
{
  if (my_world == nullptr) {
    return;
  }

  if (event->mimeData()->hasFormat("mm/object")) {
    log_debug(DEBUG_EDITOR, "Drop accepted");

    const QMimeData *mime_data = event->mimeData();

    if (mime_data->hasFormat("mm/object")) {
      event->acceptProposedAction();
      QString object_type(mime_data->data("mm/object"));
      log_debug(DEBUG_EDITOR, "Drop event %s", object_type.toLatin1().data());

      bool ok = false;
      u32 index = object_type.toLatin1().toInt(&ok);

      if (index >= application().core().entity_creators().size()) {
        log_warning("Invalid object index %i, max index is %i", index,
          application().core().entity_creators().size());
        return;
      }

      if (!ok) {
        return;
      }

      sptr<Entity> entity = application().core().entity_creators()[index].create(*my_world, application().core());

      if (entity != nullptr) {
        entity->set_class_name(application().core().entity_creators()[index].name);
        log_info("Adding entity to the world");

        EntityAdd *command = new EntityAdd(entity, application().world());
        undo_stack().push(command);
      } else {
        log_warning("Error while creating object");
      }
    } else {
      log_debug(DEBUG_EDITOR, "Drop ignored");
      event->ignore();
    }
  }
}
Пример #7
0
void playmp_controller::surrender(int side_number) {
	undo_stack().clear();
	resources::recorder->add_surrender(side_number);
	turn_data_.send_data();
}
Пример #8
0
void playmp_controller::play_human_turn()
{
	LOG_NG << "playmp::play_human_turn...\n";
	assert(!linger_);
	assert(gamestate_->init_side_done());
	assert(gamestate().gamedata_.phase() == game_data::PLAY);

	mp_ui_alerts::turn_changed(current_team().current_player());

	LOG_NG << "events::commands_disabled=" << events::commands_disabled <<"\n";

	remove_blindfold();
	const std::unique_ptr<countdown_clock> timer(saved_game_.mp_settings().mp_countdown
        ? new countdown_clock(current_team())
        : nullptr);
	show_turn_dialog();
	if(undo_stack().can_undo()) {
		// If we reload a networked mp game we cannot undo moves made before the save
		// because other players already received them
		if(!current_team().auto_shroud_updates()) {
			synced_context::run_and_store("update_shroud", replay_helper::get_update_shroud());
		}
		undo_stack().clear();
	}
	if (!preferences::disable_auto_moves()) {
		execute_gotos();
	}

	end_turn_enable(true);
	while(!should_return_to_play_side()) {
		try {
			process_network_data();
			check_objectives();
			play_slice_catch();
			if (player_type_changed_)
			{
				// Clean undo stack if turn has to be restarted (losing control)
				if ( undo_stack().can_undo() )
				{
					font::floating_label flabel(_("Undoing moves not yet transmitted to the server."));

					color_t color {255,255,255,SDL_ALPHA_OPAQUE};
					flabel.set_color(color);
					SDL_Rect rect = gui_->map_area();
					flabel.set_position(rect.w/2, rect.h/2);
					flabel.set_lifetime(150);
					flabel.set_clip_rect(rect);

					font::add_floating_label(flabel);
				}

				while( undo_stack().can_undo() )
					undo_stack().undo();

			}
			if(timer)
			{
				bool time_left = timer->update();
				if(!time_left)
				{
					end_turn_ = END_TURN_REQUIRED;
				}
			}
		}
		catch(...)
		{
			turn_data_.send_data();
			throw;
		}
		turn_data_.send_data();
	}
}
Пример #9
0
bool play_controller::can_redo() const
{
    return !linger_ && !is_browsing() && !events::commands_disabled && undo_stack().can_redo();
}
Пример #10
0
void play_controller::redo()
{
    mouse_handler_.deselect_hex();
    undo_stack().redo();
}
Пример #11
0
void play_controller::do_init_side()
{
    set_scontext_synced sync;
    log_scope("player turn");
    // In case we might end up calling sync:network during the side turn events,
    // and we don't want do_init_side to be called when a player drops.
    gamestate_->init_side_done() = true;
    init_side_done_now_ = true;

    const std::string turn_num = std::to_string(turn());
    const std::string side_num = std::to_string(current_side());

    gamestate().gamedata_.get_variable("side_number") = current_side();

    // We might have skipped some sides because they were empty so it is not enough to check for side_num==1
    if(!gamestate().tod_manager_.has_turn_event_fired())
    {
        pump().fire("turn_" + turn_num);
        pump().fire("new_turn");
        gamestate().tod_manager_.turn_event_fired();
    }

    pump().fire("side_turn");
    pump().fire("side_" + side_num + "_turn");
    pump().fire("side_turn_" + turn_num);
    pump().fire("side_" + side_num + "_turn_" + turn_num);

    // We want to work out if units for this player should get healed,
    // and the player should get income now.
    // Healing/income happen if it's not the first turn of processing,
    // or if we are loading a game.
    if (turn() > 1) {
        gamestate().board_.new_turn(current_side());
        current_team().new_turn();

        // If the expense is less than the number of villages owned
        // times the village support capacity,
        // then we don't have to pay anything at all
        int expense = gamestate().board_.side_upkeep(current_side()) -
                      current_team().support();
        if(expense > 0) {
            current_team().spend_gold(expense);
        }

        calculate_healing(current_side(), !is_skipping_replay());
    }

    // Prepare the undo stack.
    undo_stack().new_side_turn(current_side());

    pump().fire("turn_refresh");
    pump().fire("side_" + side_num + "_turn_refresh");
    pump().fire("turn_" + turn_num + "_refresh");
    pump().fire("side_" + side_num + "_turn_" + turn_num + "_refresh");

    // Make sure vision is accurate.
    actions::clear_shroud(current_side(), true);
    init_side_end();
    check_victory();
    sync.do_final_checkup();
}
Пример #12
0
void play_controller::init(CVideo& video, const config& level)
{

    gui2::dialogs::loading_screen::display(video, [this, &video, &level]() {
        gui2::dialogs::loading_screen::progress("load level");

        LOG_NG << "initializing game_state..." << (SDL_GetTicks() - ticks()) << std::endl;
        gamestate_.reset(new game_state(level, *this, tdata_));

        resources::gameboard = &gamestate().board_;
        resources::gamedata = &gamestate().gamedata_;
        resources::tod_manager = &gamestate().tod_manager_;
        resources::units = &gamestate().board_.units_;
        resources::filter_con = &gamestate();
        resources::undo_stack = &undo_stack();
        resources::game_events = gamestate().events_manager_.get();
        resources::lua_kernel = gamestate().lua_kernel_.get();

        gamestate_->init(level, *this);
        resources::tunnels = gamestate().pathfind_manager_.get();

        LOG_NG << "initializing whiteboard..." << (SDL_GetTicks() - ticks()) << std::endl;
        gui2::dialogs::loading_screen::progress("init whiteboard");
        whiteboard_manager_.reset(new wb::manager());
        resources::whiteboard = whiteboard_manager_;

        LOG_NG << "loading units..." << (SDL_GetTicks() - ticks()) << std::endl;
        gui2::dialogs::loading_screen::progress("load units");
        preferences::encounter_all_content(gamestate().board_);

        LOG_NG << "initializing theme... " << (SDL_GetTicks() - ticks()) << std::endl;
        gui2::dialogs::loading_screen::progress("init theme");
        const config& theme_cfg = controller_base::get_theme(game_config_, level["theme"]);

        LOG_NG << "building terrain rules... " << (SDL_GetTicks() - ticks()) << std::endl;
        gui2::dialogs::loading_screen::progress("build terrain");
        gui_.reset(new game_display(gamestate().board_, video, whiteboard_manager_, *gamestate().reports_, gamestate().tod_manager_, theme_cfg, level));
        if (!gui_->video().faked()) {
            if (saved_game_.mp_settings().mp_countdown)
                gui_->get_theme().modify_label("time-icon", _ ("time left for current turn"));
            else
                gui_->get_theme().modify_label("time-icon", _ ("current local time"));
        }

        gui2::dialogs::loading_screen::progress("init display");
        mouse_handler_.set_gui(gui_.get());
        menu_handler_.set_gui(gui_.get());
        resources::screen = gui_.get();

        LOG_NG << "done initializing display... " << (SDL_GetTicks() - ticks()) << std::endl;

        LOG_NG << "building gamestate to gui and whiteboard... " << (SDL_GetTicks() - ticks()) << std::endl;
        // This *needs* to be created before the show_intro and show_map_scene
        // as that functions use the manager state_of_game
        // Has to be done before registering any events!
        gamestate().set_game_display(gui_.get());
        gui2::dialogs::loading_screen::progress("init lua");

        if(gamestate().first_human_team_ != -1) {
            gui_->set_team(gamestate().first_human_team_);
        }
        else if(is_observer()) {
            // Find first team that is allowed to be observed.
            // If not set here observer would be without fog until
            // the first turn of observable side
            size_t i;
            for (i=0; i < gamestate().board_.teams().size(); ++i)
            {
                if (!gamestate().board_.teams()[i].get_disallow_observers())
                {
                    gui_->set_team(i);
                }
            }
        }

        init_managers();
        gui2::dialogs::loading_screen::progress("start game");
        //loadscreen_manager->reset();
        gamestate().gamedata_.set_phase(game_data::PRELOAD);
        gamestate().lua_kernel_->load_game(level);

        plugins_context_.reset(new plugins_context("Game"));
        plugins_context_->set_callback("save_game", [this](const config& cfg) {
            save_game_auto(cfg["filename"]);
        }, true);
        plugins_context_->set_callback("save_replay", [this](const config& cfg) {
            save_replay_auto(cfg["filename"]);
        }, true);
        plugins_context_->set_callback("quit", throw_end_level(), false);
        plugins_context_->set_accessor_string("scenario_name", [this](config) {
            return get_scenario_name();
        });
    });
    //Do this after the loadingscreen, so that ita happens in the main thread.
    gui_->join();
}
Пример #13
0
	actions::undo_list& get_undo_stack() { return undo_stack(); }