make recruit undoable when there is no randomness in recruiting
This commit is contained in:
parent
e33805092b
commit
fc168242bd
8 changed files with 93 additions and 6 deletions
|
@ -87,6 +87,7 @@ SVN trunk (1.1.2+svn):
|
|||
* simplified upkeep: Each controlled village gives 2 GP per turn, and
|
||||
each unit costs 1*(# of Levels) GP per turn, unless loyal.
|
||||
* new /help command in mp lobby to get info on available commands
|
||||
* undo allowed when recruiting units without random traits
|
||||
* :mute command to silent observers
|
||||
* host changes automatically if game creator leaves => no disconnections
|
||||
* new --turns= commandline parameter
|
||||
|
|
|
@ -2443,7 +2443,7 @@ void apply_shroud_changes(undo_list& undos, display* disp, const gamestatus& sta
|
|||
*/
|
||||
for(undo_list::iterator un = undos.begin(); un != undos.end(); ++un) {
|
||||
std::cout << "Turning an undo...\n";
|
||||
if(un->is_recall()) continue;
|
||||
if(un->is_recall() || un->is_recruit()) continue;
|
||||
//we're not really going to mutate the unit, just temporarily
|
||||
//set its moves to maximum, but then switch them back
|
||||
const unit_movement_resetter move_resetter(un->affected_unit);
|
||||
|
|
|
@ -26,6 +26,8 @@ class replay;
|
|||
#include <deque>
|
||||
typedef std::map<gamemap::location,unit> units_map;
|
||||
|
||||
#define RECRUIT_POS -2
|
||||
|
||||
//this file defines various functions which implement different in-game
|
||||
//events and commands.
|
||||
bool can_recruit_on(const gamemap& map, const gamemap::location& leader, const gamemap::location loc);
|
||||
|
@ -269,15 +271,16 @@ struct undo_action {
|
|||
undo_action(unit u,const std::vector<gamemap::location>& rt,int sm,int timebonus=0,int orig=-1)
|
||||
: route(rt), starting_moves(sm), original_village_owner(orig), recall_pos(-1), affected_unit(u), countdown_time_bonus(timebonus) {}
|
||||
undo_action(unit u,const gamemap::location& loc, int pos)
|
||||
: recall_loc(loc), recall_pos(pos), affected_unit(u) {}
|
||||
: recall_loc(loc), recall_pos(pos), affected_unit(u), countdown_time_bonus(1) {}
|
||||
std::vector<gamemap::location> route;
|
||||
int starting_moves;
|
||||
int original_village_owner;
|
||||
gamemap::location recall_loc;
|
||||
int recall_pos;
|
||||
int recall_pos; // set to RECRUIT_POS for an undo-able recruit
|
||||
unit affected_unit;
|
||||
int countdown_time_bonus;
|
||||
bool is_recall() const { return recall_pos >= 0; }
|
||||
bool is_recruit() const { return recall_pos == RECRUIT_POS; }
|
||||
};
|
||||
|
||||
typedef std::deque<undo_action> undo_list;
|
||||
|
|
|
@ -598,8 +598,12 @@ namespace events{
|
|||
//MP_COUNTDOWN grant time bonus for recruiting
|
||||
current_team.set_action_bonus_count(1 + current_team.action_bonus_count());
|
||||
|
||||
clear_undo_stack(team_num);
|
||||
redo_stack_.clear();
|
||||
if(new_unit.type().genders().size() > 1 || new_unit.type().has_random_traits()) {
|
||||
clear_undo_stack(team_num);
|
||||
} else {
|
||||
undo_stack_.push_back(undo_action(new_unit,loc,RECRUIT_POS));
|
||||
}
|
||||
|
||||
clear_shroud(team_num);
|
||||
|
||||
|
@ -750,6 +754,26 @@ namespace events{
|
|||
gui_->invalidate(action.recall_loc);
|
||||
gui_->draw();
|
||||
}
|
||||
} else if(action.is_recruit()) {
|
||||
// Undo a recruit action
|
||||
team& current_team = teams_[team_num-1];
|
||||
if(units_.count(action.recall_loc) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const unit& un = units_.find(action.recall_loc)->second;
|
||||
statistics::un_recruit_unit(un);
|
||||
current_team.spend_gold(-un.type().cost());
|
||||
|
||||
//MP_COUNTDOWN take away recruit bonus
|
||||
if(action.countdown_time_bonus)
|
||||
{
|
||||
teams_[team_num-1].set_action_bonus_count(teams_[team_num-1].action_bonus_count() - 1);
|
||||
}
|
||||
|
||||
units_.erase(action.recall_loc);
|
||||
gui_->invalidate(action.recall_loc);
|
||||
gui_->draw();
|
||||
} else {
|
||||
// Undo a move action
|
||||
const int starting_moves = action.starting_moves;
|
||||
|
@ -764,7 +788,7 @@ namespace events{
|
|||
|
||||
if(map_.is_village(route.front())) {
|
||||
get_village(route.front(),teams_,action.original_village_owner,units_);
|
||||
//MP_COUNTDOWN take away bonus
|
||||
//MP_COUNTDOWN take away capture bonus
|
||||
if(action.countdown_time_bonus)
|
||||
{
|
||||
teams_[team_num-1].set_action_bonus_count(teams_[team_num-1].action_bonus_count() - 1);
|
||||
|
@ -844,6 +868,46 @@ namespace events{
|
|||
gui::show_dialog(*gui_,NULL,"",msg,gui::OK_ONLY);
|
||||
}
|
||||
}
|
||||
} else if(action.is_recruit()) {
|
||||
// Redo recruit action
|
||||
team& current_team = teams_[team_num-1];
|
||||
gamemap::location loc = action.recall_loc;
|
||||
const std::string name = action.affected_unit.id();
|
||||
|
||||
//search for the unit to be recruited in recruits
|
||||
int recruit_num = 0;
|
||||
const std::set<std::string>& recruits = current_team.recruits();
|
||||
for(std::set<std::string>::const_iterator r = recruits.begin(); ; ++r) {
|
||||
if (r == recruits.end()) {
|
||||
LOG_STREAM(err, engine) << "trying to redo a recruit for side " << team_num
|
||||
<< ", which does not recruit type \"" << name << "\"\n";
|
||||
wassert(0);
|
||||
}
|
||||
if (name == *r) {
|
||||
break;
|
||||
}
|
||||
++recruit_num;
|
||||
}
|
||||
last_recruit_ = name;
|
||||
recorder.add_recruit(recruit_num,loc);
|
||||
unit new_unit = action.affected_unit;
|
||||
//unit new_unit(action.affected_unit.type(),team_num_,true);
|
||||
const std::string& msg = recruit_unit(map_,team_num,units_,new_unit,loc,gui_);
|
||||
if(msg.empty()) {
|
||||
current_team.spend_gold(new_unit.type().cost());
|
||||
statistics::recruit_unit(new_unit);
|
||||
|
||||
//MP_COUNTDOWN: restore recruitment bonus
|
||||
current_team.set_action_bonus_count(1 + current_team.action_bonus_count());
|
||||
|
||||
gui_->invalidate(action.recall_loc);
|
||||
gui_->draw();
|
||||
//gui_.invalidate_game_status();
|
||||
//gui_.invalidate_all();
|
||||
} else {
|
||||
recorder.undo();
|
||||
gui::show_dialog(*gui_,NULL,"",msg,gui::OK_ONLY);
|
||||
}
|
||||
} else {
|
||||
// Redo movement action
|
||||
const int starting_moves = action.starting_moves;
|
||||
|
@ -869,7 +933,7 @@ namespace events{
|
|||
|
||||
if(map_.is_village(route.back())) {
|
||||
get_village(route.back(),teams_,un.side()-1,units_);
|
||||
//MP_COUNTDOWN restore bonus
|
||||
//MP_COUNTDOWN restore capture bonus
|
||||
if(action.countdown_time_bonus)
|
||||
{
|
||||
teams_[team_num-1].set_action_bonus_count(1 + teams_[team_num-1].action_bonus_count());
|
||||
|
|
|
@ -367,6 +367,17 @@ void un_recall_unit(const unit& u)
|
|||
s.recall_cost -= u.cost();
|
||||
}
|
||||
|
||||
void un_recruit_unit(const unit& u)
|
||||
{
|
||||
if(stats_disabled > 0)
|
||||
return;
|
||||
|
||||
stats& s = get_stats(u.side());
|
||||
s.recruits[u.type().id()]--;
|
||||
s.recruit_cost -= u.type().cost();
|
||||
}
|
||||
|
||||
|
||||
void advance_unit(const unit& u)
|
||||
{
|
||||
if(stats_disabled > 0)
|
||||
|
|
|
@ -89,6 +89,7 @@ namespace statistics
|
|||
void recruit_unit(const unit& u);
|
||||
void recall_unit(const unit& u);
|
||||
void un_recall_unit(const unit& u);
|
||||
void un_recruit_unit(const unit& u);
|
||||
|
||||
void advance_unit(const unit& u);
|
||||
|
||||
|
|
|
@ -1102,6 +1102,12 @@ const std::vector<config*>& unit_type::possible_traits() const
|
|||
return possibleTraits_;
|
||||
}
|
||||
|
||||
bool unit_type::has_random_traits() const
|
||||
{
|
||||
const int n = num_traits();
|
||||
return (n > 0 && n < possibleTraits_.size());
|
||||
}
|
||||
|
||||
const std::vector<unit_race::GENDER>& unit_type::genders() const
|
||||
{
|
||||
return genders_;
|
||||
|
|
|
@ -233,6 +233,7 @@ public:
|
|||
bool has_ability_by_id(const std::string& ability) const;
|
||||
|
||||
const std::vector<config*>& possible_traits() const;
|
||||
bool has_random_traits() const;
|
||||
|
||||
const std::vector<unit_race::GENDER>& genders() const;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue