Make random_traits = "yes" the default.
This makes the feature more powerful as well. You can define less than the max number of traits manually and have the remainder filled in randomly. It also forces undead and mechanical to always be assigned when available for a unit. Currently no random traits are assigned to leaders. The problem is that random number generation triggered by the leader creation isn't properly handled in MP games, so only must have traits can be given out currently. This is controlled by [trait] configuration, so down the road traits that are not unbalancing for MP play (quick was especially seen as a problem for MP) may be given to leaders.
This commit is contained in:
parent
7561441b34
commit
1e19407281
3 changed files with 81 additions and 16 deletions
|
@ -105,6 +105,11 @@ Version 1.3.6+svn:
|
|||
change (not that there are any now) so that the current leader is
|
||||
exempted and any exleaders pay for upkeep (unless the are specically
|
||||
marked as loyal).
|
||||
* make random_traits default to "yes". Leaders can't get random traits
|
||||
yet, because it breaks MP, but it does give campaign units traits
|
||||
by default. It also allows specifying some traits and letting the
|
||||
rest fill in randomly. Some traits are always forced on for units
|
||||
that can get them (undead and mechanical).
|
||||
* team color
|
||||
* allow color ranges to be defined on-the-fly (like color palettes)
|
||||
* now [side] colour=<string> is valid (previously only int)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
# Units with trait Undead cannot be drained, poisoned or plagued.
|
||||
[trait]
|
||||
id=undead
|
||||
availability="musthave"
|
||||
male_name= _ "undead"
|
||||
female_name= _ "female^undead"
|
||||
description= _ "Immune to drain, poison and plague"
|
||||
|
@ -29,6 +30,7 @@
|
|||
# Units with trait Mechanical cannot be drained, poisoned or plagued.
|
||||
[trait]
|
||||
id=mechanical
|
||||
availability="musthave"
|
||||
male_name= _ "mechanical"
|
||||
female_name= _ "female^mechanical"
|
||||
description= _ "Immune to drain, poison and plague"
|
||||
|
|
90
src/unit.cpp
90
src/unit.cpp
|
@ -265,11 +265,12 @@ unit::unit(const game_data* gamedata, unit_map* unitmap, const gamemap* map,
|
|||
//units, so they shouldn't get a description either.
|
||||
custom_unit_description_ = generate_description();
|
||||
generate_traits();
|
||||
}else{
|
||||
if (race_->name() == "undead") {
|
||||
generate_traits();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If a unit was created without using generated traits, don't
|
||||
// let them get applied later (after save and restore).
|
||||
cfg_["random_traits"]="no";
|
||||
}
|
||||
if(underlying_description_.empty()){
|
||||
char buf[80];
|
||||
if(!custom_unit_description_.empty()){
|
||||
|
@ -309,11 +310,12 @@ unit::unit(const unit_type* t, int side, bool use_traits, bool dummy_unit, unit_
|
|||
//units, so they shouldn't get a description either.
|
||||
custom_unit_description_ = generate_description();
|
||||
generate_traits();
|
||||
}else{
|
||||
if (race_->name() == "undead") {
|
||||
generate_traits();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If a unit was created without using generated traits, don't
|
||||
// let them get applied later (after save and restore).
|
||||
cfg_["random_traits"]="no";
|
||||
}
|
||||
if(underlying_description_.empty()){
|
||||
char buf[80];
|
||||
if(!custom_unit_description_.empty()){
|
||||
|
@ -372,19 +374,73 @@ void unit::set_game_context(const game_data* gamedata, unit_map* unitmap, const
|
|||
teams_ = teams;
|
||||
}
|
||||
|
||||
// Apply mandatory traits (e.g. undead, mechanical) to a unit and then
|
||||
// fill out with avaiable (leaders have a restircted set of available traits)
|
||||
// traits until no more are available or the unit has its maximum number
|
||||
// of traits.
|
||||
// Note that random numbers used in config files don't work in multiplayer,
|
||||
// so that leaders should be barred from all random traits until that
|
||||
// is fixed. Later the restrictions will be based on play balance.
|
||||
|
||||
void unit::generate_traits()
|
||||
{
|
||||
if(!traits_description_.empty())
|
||||
return;
|
||||
|
||||
wassert(gamedata_ != NULL);
|
||||
const game_data::unit_type_map::const_iterator type = gamedata_->unit_types.find(id());
|
||||
//calculate the unit's traits
|
||||
std::vector<config*> candidate_traits = type->second.possible_traits();
|
||||
std::vector<config*> traits;
|
||||
|
||||
const size_t num_traits = type->second.num_traits();
|
||||
for(size_t n = 0; n != num_traits && candidate_traits.empty() == false; ++n) {
|
||||
// First remove traits the unit already has from consideration.
|
||||
// And count them so that we can figure out how many more are needed.
|
||||
size_t t = 0;
|
||||
config::child_list const &mods = modifications_.get_children("trait");
|
||||
for(config::child_list::const_iterator j = mods.begin(), j_end = mods.end(); j != j_end; ++j) {
|
||||
++t;
|
||||
for(size_t n = 0; n < candidate_traits.size(); ++n) {
|
||||
if((**(candidate_traits.begin()+n))["id"] == (**j)["id"]) {
|
||||
candidate_traits.erase(candidate_traits.begin()+n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Next add in any manditory traits. These aren't limited by the
|
||||
// number of traits allowed for a unit. They also don't use
|
||||
// any random numbers for assignment. (And hence don't cause
|
||||
// problems for multiplayer.)
|
||||
size_t num_traits = candidate_traits.size();
|
||||
size_t m = 0;
|
||||
for(size_t n = 0; n < num_traits; ++n) {
|
||||
if(!(**(candidate_traits.begin()+m))["availability"].empty() &&
|
||||
(**(candidate_traits.begin()+m))["availability"] == "musthave") {
|
||||
traits.push_back(candidate_traits[m]);
|
||||
candidate_traits.erase(candidate_traits.begin()+m);
|
||||
++t;
|
||||
}
|
||||
else {
|
||||
++m;
|
||||
}
|
||||
}
|
||||
|
||||
// Next for leaders remove any traits that are not available to
|
||||
// the "any" category.
|
||||
if(can_recruit()) {
|
||||
num_traits = candidate_traits.size();
|
||||
m = 0;
|
||||
for(size_t n = 0; n < num_traits; ++n) {
|
||||
if(!(**(candidate_traits.begin()+m))["availability"].empty() ||
|
||||
(**(candidate_traits.begin()+m))["availability"] != "any") {
|
||||
candidate_traits.erase(candidate_traits.begin()+m);
|
||||
}
|
||||
else {
|
||||
++m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now randomly fill out to the number of traits required or until
|
||||
// there aren't any more traits.
|
||||
num_traits = type->second.num_traits();
|
||||
for(size_t n = t; n < num_traits && candidate_traits.empty() == false; ++n) {
|
||||
const int num = get_random()%candidate_traits.size();
|
||||
traits.push_back(candidate_traits[num]);
|
||||
candidate_traits.erase(candidate_traits.begin()+num);
|
||||
|
@ -395,6 +451,9 @@ void unit::generate_traits()
|
|||
}
|
||||
|
||||
apply_modifications();
|
||||
// Once random traits are applied, don't do it again.
|
||||
// Such as when restoring a saved character.
|
||||
cfg_["random_traits"]="no";
|
||||
}
|
||||
|
||||
// Advances this unit to another type
|
||||
|
@ -1151,10 +1210,9 @@ void unit::read(const config& cfg)
|
|||
backup_state();
|
||||
apply_modifications();
|
||||
}
|
||||
if(utils::string_bool(cfg["random_traits"]) ||
|
||||
race_->name() == "undead") {
|
||||
if(cfg["random_traits"].empty() ||
|
||||
utils::string_bool(cfg["random_traits"])) {
|
||||
generate_traits();
|
||||
cfg_["random_traits"] = "";
|
||||
}
|
||||
if(cfg["hitpoints"] != "") {
|
||||
hit_points_ = lexical_cast_default<int>(cfg["hitpoints"]);
|
||||
|
|
Loading…
Add table
Reference in a new issue