Have teams pay for their recruits between the pre- and recruit events.

And similarly for recalls.

Fetaure request / bug #16711
This commit is contained in:
J. Tyne 2012-09-01 18:22:21 +00:00
parent c47788c4d6
commit a3a8d7c448
7 changed files with 23 additions and 25 deletions

View file

@ -15,6 +15,8 @@ Version 1.11.0+svn:
* WML engine:
* The recall, recruit, prerecall, and prerecruit events will now block
undoing unless they contain [allow_undo].
* The cost of a recall/recruit is now paid between the prerecall/prerecruit
and recall/recruit events. (FR #16711)
* Miscellaneous and bug fixes:
* Fix invalid memory access crash resulting from deleting all saved games
in the Load Game dialog

View file

@ -696,7 +696,7 @@ static bool validate_recruit_iterator(unit_map::iterator & un_it,
}
bool place_recruit(const unit &u, const map_location &recruit_location, const map_location& recruited_from,
bool is_recall, bool show, bool fire_event, bool full_movement,
int cost, bool is_recall, bool show, bool fire_event, bool full_movement,
bool wml_triggered)
{
// Alias
@ -736,6 +736,7 @@ bool place_recruit(const unit &u, const map_location &recruit_location, const ma
new_unit_itor->set_hidden(true);
}
preferences::encountered_units().insert(new_unit_itor->type_id());
(*resources::teams)[new_unit.side()-1].spend_gold(cost);
if ( show ) {
// Find a leader to animate.

View file

@ -137,7 +137,7 @@ const std::vector<const unit*> get_recalls_for_location(int side, const map_loca
* @returns true if an event has mutated the game state.
*/
bool place_recruit(const unit &u, const map_location &recruit_location, const map_location& recruited_from,
bool is_recall, bool show = false, bool fire_event = true, bool full_movement = false,
int cost, bool is_recall, bool show = false, bool fire_event = true, bool full_movement = false,
bool wml_triggered = false);
#endif

View file

@ -678,9 +678,8 @@ void recall_result::do_execute()
unit &un = *rec;
recorder.add_recall(un.id(), recall_location_, recall_from_);
place_recruit(un, recall_location_, recall_from_, true, true);
place_recruit(un, recall_location_, recall_from_, my_team.recall_cost(), true, true);
statistics::recall_unit(un);
my_team.spend_gold(my_team.recall_cost());
my_team.recall_list().erase(rec);
if (resources::screen!=NULL) {
@ -885,9 +884,8 @@ void recruit_result::do_execute()
const std::string recruit_err = find_recruit_location(get_side(), recruit_location_, recruit_from_, u->id());
if(recruit_err.empty()) {
const unit new_unit(u, get_side(), true);
place_recruit(new_unit, recruit_location_, recruit_from_, false, preferences::show_ai_moves());
place_recruit(new_unit, recruit_location_, recruit_from_, u->cost(), false, preferences::show_ai_moves());
statistics::recruit_unit(new_unit);
get_my_team().spend_gold(u->cost());
// Confirm the transaction - i.e. don't undo recruitment
replay_guard.confirm_transaction();
set_gamestate_changed();

View file

@ -1937,7 +1937,7 @@ WML_HANDLER_FUNCTION(recall, /*event_info*/, cfg)
if(resources::game_map->on_board(loc)) {
DBG_NG << "...valid location for the recall found. Recalling.\n";
avail.erase(u); // Erase before recruiting, since recruiting can fire more events
place_recruit(to_recruit, loc, leader->get_location(), true,
place_recruit(to_recruit, loc, leader->get_location(), 0, true,
cfg["show"].to_bool(true), cfg["fire_event"].to_bool(false), true, true);
return;
}
@ -1952,7 +1952,7 @@ WML_HANDLER_FUNCTION(recall, /*event_info*/, cfg)
DBG_NG << "No usable leader found, but found usable location. Recalling.\n";
avail.erase(u); // Erase before recruiting, since recruiting can fire more events
map_location null_location = map_location::null_location;
place_recruit(to_recruit, loc, null_location, true,
place_recruit(to_recruit, loc, null_location, 0, true,
cfg["show"].to_bool(true), cfg["fire_event"].to_bool(false), true, true);
return;
}

View file

@ -856,8 +856,7 @@ bool menu_handler::do_recruit(const std::string &name, int side_num,
//create a unit with traits
recorder.add_recruit(recruit_num, loc, recruited_from);
const unit new_unit(u_type, side_num, true);
bool mutated = place_recruit(new_unit, loc, recruited_from, false, true);
current_team.spend_gold(u_type->cost());
bool mutated = place_recruit(new_unit, loc, recruited_from, u_type->cost(), false, true);
statistics::recruit_unit(new_unit);
//MP_COUNTDOWN grant time bonus for recruiting
@ -1077,9 +1076,8 @@ bool menu_handler::do_recall(const unit& un, int side_num, const map_location& r
recall_list_team.erase(it);
recorder.add_recall(un.id(), recall_location, recall_from);
bool mutated = place_recruit(un, recall_location, recall_from, true, true);
bool mutated = place_recruit(un, recall_location, recall_from, current_team.recall_cost(), true, true);
statistics::recall_unit(un);
current_team.spend_gold(current_team.recall_cost());
bool shroud_cleared = clear_shroud(side_num);
resources::undo_stack->push_back(undo_action(un, recall_location, recall_from, undo_action::RECALL));
@ -1256,9 +1254,8 @@ void menu_handler::redo(int side_num)
assert(unit_it != current_team.recall_list().end());
current_team.recall_list().erase(unit_it);
place_recruit(un, loc, from, true, true);
place_recruit(un, loc, from, current_team.recall_cost(), true, true);
statistics::recall_unit(un);
current_team.spend_gold(current_team.recall_cost());
gui_->invalidate(loc);
recorder.add_checksum_check(loc);
} else {
@ -1295,8 +1292,7 @@ void menu_handler::redo(int side_num)
if(msg.empty()) {
const unit new_unit = action.affected_unit;
//unit new_unit(action.affected_unit.type(),team_num_,true);
place_recruit(new_unit, loc, from, false, true);
current_team.spend_gold(new_unit.type()->cost());
place_recruit(new_unit, loc, from, new_unit.type()->cost(), false, true);
statistics::recruit_unit(new_unit);
gui_->invalidate(loc);

View file

@ -987,28 +987,30 @@ bool do_replay_handle(int side_num, const std::string &do_untill)
const std::string res = find_recruit_location(side_num, loc, from, u_type->id());
const unit new_unit(u_type, side_num, true);
const int beginning_gold = current_team.gold();
if (res.empty()) {
place_recruit(new_unit, loc, from, false, !get_replay_source().is_skipping());
place_recruit(new_unit, loc, from, u_type->cost(), false, !get_replay_source().is_skipping());
} else {
std::stringstream errbuf;
errbuf << "cannot recruit unit: " << res << "\n";
replay::process_error(errbuf.str());
// Keep the gold total right.
current_team.spend_gold(u_type->cost());
}
if (u_type->cost() > current_team.gold()) {
if ( u_type->cost() > beginning_gold ) {
std::stringstream errbuf;
errbuf << "unit '" << u_type->id() << "' is too expensive to recruit: "
<< u_type->cost() << "/" << current_team.gold() << "\n";
<< u_type->cost() << "/" << beginning_gold << "\n";
replay::process_error(errbuf.str());
}
LOG_REPLAY << "recruit: team=" << side_num << " '" << u_type->id() << "' at (" << loc
<< ") cost=" << u_type->cost() << " from gold=" << current_team.gold() << ' ';
<< ") cost=" << u_type->cost() << " from gold=" << beginning_gold << ' '
<< "-> " << current_team.gold() << "\n";
statistics::recruit_unit(new_unit);
current_team.spend_gold(u_type->cost());
LOG_REPLAY << "-> " << (current_team.gold()) << "\n";
fix_shroud = true;
check_checksums(*cfg);
}
@ -1024,9 +1026,8 @@ bool do_replay_handle(int side_num, const std::string &do_untill)
if (recall_unit != current_team.recall_list().end()) {
statistics::recall_unit(*recall_unit);
place_recruit(*recall_unit, loc, from, true, !get_replay_source().is_skipping());
place_recruit(*recall_unit, loc, from, current_team.recall_cost(), true, !get_replay_source().is_skipping());
current_team.recall_list().erase(recall_unit);
current_team.spend_gold(current_team.recall_cost());
fix_shroud = true;
} else {
replay::process_error("illegal recall: unit_id '" + unit_id + "' could not be found within the recall list.\n");