make recruit undoable when there is no randomness in recruiting

This commit is contained in:
Jérémy Rosen 2006-05-08 06:55:40 +00:00
parent e33805092b
commit fc168242bd
8 changed files with 93 additions and 6 deletions

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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());

View file

@ -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)

View file

@ -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);

View file

@ -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_;

View file

@ -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;