void advance_unit(const map_location &loc, bool automatic, bool add_replay_event, const ai::unit_advancements_aspect& advancements) { unit_map::iterator u = resources::units->find(loc); if(!unit_helper::will_certainly_advance(u)) { return; } LOG_DP << "advance_unit: " << u->type_id() << " (advances: " << u->advances() << " XP: " <<u->experience() << '/' << u->max_experience() << ")\n"; int res; if (automatic) { //if the advancements are empty or don't match any option //choose random instead. res = rand() % unit_helper::number_of_possible_advances(*u); const std::vector<std::string>& options = u->advances_to(); const std::vector<std::string>& allowed = advancements.get_advancements(u); for(std::vector<std::string>::const_iterator a = options.begin(); a != options.end(); ++a) { if (std::find(allowed.begin(), allowed.end(), *a) != allowed.end()){ res = a - options.begin(); break; } } } else { res = advance_unit_dialog(loc); } if(add_replay_event) { recorder.add_advancement(loc); } config choice_cfg; choice_cfg["value"] = res; recorder.user_input("choose", choice_cfg); LOG_DP << "animating advancement...\n"; animate_unit_advancement(loc, size_t(res)); // In some rare cases the unit can have enough XP to advance again, // so try to do that. // Make sure that we don't enter an infinite level loop. u = resources::units->find(loc); if (u != resources::units->end()) { // Level 10 unit gives 80 XP and the highest mainline is level 5 if (u->experience() < 81) { // For all leveling up we have to add advancement to replay here because replay // doesn't handle cascading advancement since it just calls animate_unit_advancement(). advance_unit(loc, automatic, true, advancements); } else { ERR_CF << "Unit has too many (" << u->experience() << ") XP left; cascade leveling disabled.\n"; } } else { ERR_NG << "Unit advanced no longer exists.\n"; } }
void advance_unit(const map_location &loc, bool random_choice, bool add_replay_event) { unit_map::iterator u = resources::units->find(loc); if(!unit_helper::will_certainly_advance(u)) { return; } LOG_DP << "advance_unit: " << u->type_id() << " (advances: " << u->advances() << " XP: " <<u->experience() << '/' << u->max_experience() << ")\n"; int res; if (random_choice) { res = rand() % unit_helper::number_of_possible_advances(*u); } else { res = advance_unit_dialog(loc); } if(add_replay_event) { recorder.add_advancement(loc); } config choice_cfg; choice_cfg["value"] = res; recorder.user_input("choose", choice_cfg); LOG_DP << "animating advancement...\n"; animate_unit_advancement(loc, size_t(res)); // In some rare cases the unit can have enough XP to advance again, // so try to do that. // Make sure that we don't enter an infinite level loop. u = resources::units->find(loc); if (u != resources::units->end()) { // Level 10 unit gives 80 XP and the highest mainline is level 5 if (u->experience() < 81) { // For all leveling up we have to add advancement to replay here because replay // doesn't handle cascading advancement since it just calls animate_unit_advancement(). advance_unit(loc, random_choice, true); } else { ERR_CF << "Unit has an too high amount of " << u->experience() << " XP left, cascade leveling disabled\n"; } } else { ERR_NG << "Unit advanced no longer exists\n"; } }
/* advances the unit and stores data in the replay (or reads data from replay). */ void advance_unit_at(const advance_unit_params& params) { //i just don't want infinite loops... // the 20 is picked rather randomly. for(int advacment_number = 0; advacment_number < 20; advacment_number++) { unit_map::iterator u = resources::gameboard->units().find(params.loc_); //this implies u.valid() if(!unit_helper::will_certainly_advance(u)) { return; } if(params.fire_events_) { LOG_NG << "Firing pre advance event at " << params.loc_ <<".\n"; resources::game_events->pump().fire("pre_advance", params.loc_); //TODO: maybe use id instead of location here ?. u = resources::gameboard->units().find(params.loc_); if(!unit_helper::will_certainly_advance(u)) { LOG_NG << "pre advance event aborted advancing.\n"; return; } } //we don't want to let side 1 decide it during start/prestart. int side_for = resources::gamedata->phase() == game_data::PLAY ? 0: u->side(); config selected = mp_sync::get_user_choice("choose", unit_advancement_choice(params.loc_, unit_helper::number_of_possible_advances(*u), u->side(), params.ai_advancements_, params.force_dialog_), side_for); //calls actions::advance_unit. bool result = animate_unit_advancement(params.loc_, selected["value"], params.fire_events_, params.animate_); DBG_NG << "animate_unit_advancement result = " << result << std::endl; u = resources::gameboard->units().find(params.loc_); // level 10 unit gives 80 XP and the highest mainline is level 5 if (u.valid() && u->experience() > 80) { WRN_NG << "Unit has too many (" << u->experience() << ") XP left; cascade leveling goes on still." << std::endl; } } ERR_NG << "unit at " << params.loc_ << "tried to advance more than 20 times. Advancing was aborted" << std::endl; }