示例#1
0
//Quantity is adjusted directly as a side effect of this function
MonsterGroupResult MonsterGroupManager::GetResultFromGroup(
    const mongroup_id &group_name, int *quantity )
{
    auto &group = GetUpgradedMonsterGroup( group_name );
    int spawn_chance = rng( 1, group.freq_total ); //Default 1000 unless specified
    //Our spawn details specify, by default, a single instance of the default monster
    MonsterGroupResult spawn_details = MonsterGroupResult( group.defaultMonster, 1 );

    bool monster_found = false;
    // Loop invariant values
    const time_point sunset = calendar::turn.sunset();
    const time_point sunrise = calendar::turn.sunrise();
    const season_type season = season_of_year( calendar::turn );
    // Step through spawn definitions from the monster group until one is found or
    for( auto it = group.monsters.begin(); it != group.monsters.end() && !monster_found; ++it ) {
        // There's a lot of conditions to work through to see if this spawn definition is valid
        bool valid_entry = true;
        //Insure that the time is not before the spawn first appears or after it stops appearing
        valid_entry = valid_entry && ( calendar::time_of_cataclysm + it->starts < calendar::turn );
        valid_entry = valid_entry && ( it->lasts_forever() ||
                                       calendar::time_of_cataclysm + it->ends > calendar::turn );

        std::vector<std::pair<time_point, time_point> > valid_times_of_day;
        bool season_limited = false;
        bool season_matched = false;
        //Collect the various spawn conditions, and then insure they are met appropriately
        for( auto &elem : it->conditions ) {
            //Collect valid time of day ranges
            if( elem == "DAY" || elem == "NIGHT" || elem == "DUSK" || elem == "DAWN" ) {
                if( elem == "DAY" ) {
                    valid_times_of_day.push_back( std::make_pair( sunrise, sunset ) );
                } else if( elem == "NIGHT" ) {
                    valid_times_of_day.push_back( std::make_pair( sunset, sunrise ) );
                } else if( elem == "DUSK" ) {
                    valid_times_of_day.push_back( std::make_pair( sunset - 1_hours, sunset + 1_hours ) );
                } else if( elem == "DAWN" ) {
                    valid_times_of_day.push_back( std::make_pair( sunrise - 1_hours, sunrise + 1_hours ) );
                }
            }

            //If we have any seasons listed, we know to limit by season, and if any season matches this season, we are good to spawn
            if( elem == "SUMMER" || elem == "WINTER" || elem == "SPRING" || elem == "AUTUMN" ) {
                season_limited = true;
                if( ( season == SUMMER && elem == "SUMMER" ) ||
                    ( season == WINTER && elem == "WINTER" ) ||
                    ( season == SPRING && elem == "SPRING" ) ||
                    ( season == AUTUMN && elem == "AUTUMN" ) ) {
                    season_matched = true;
                }
            }
        }

        //Make sure the current time of day is within one of the valid time ranges for this spawn
        bool is_valid_time_of_day = false;
        if( valid_times_of_day.empty() ) {
            //Then it can spawn whenever, since no times were defined
            is_valid_time_of_day = true;
        } else {
            //Otherwise, it's valid if it matches any of the times of day
            for( auto &elem : valid_times_of_day ) {
                if( calendar::turn > elem.first && calendar::turn < elem.second ) {
                    is_valid_time_of_day = true;
                }
            }
        }
        if( !is_valid_time_of_day ) {
            valid_entry = false;
        }

        //If we are limited by season, make sure we matched a season
        if( season_limited && !season_matched ) {
            valid_entry = false;
        }

        //If the entry was valid, check to see if we actually spawn it
        if( valid_entry ) {
            //If the monsters frequency is greater than the spawn_chance, select this spawn rule
            if( it->frequency >= spawn_chance ) {
                if( it->pack_maximum > 1 ) {
                    spawn_details = MonsterGroupResult( it->name, rng( it->pack_minimum, it->pack_maximum ) );
                } else {
                    spawn_details = MonsterGroupResult( it->name, 1 );
                }
                //And if a quantity pointer with remaining value was passed, will modify the external value as a side effect
                //We will reduce it by the spawn rule's cost multiplier
                if( quantity ) {
                    *quantity -= std::max( 1, it->cost_multiplier * spawn_details.pack_size );
                }
                monster_found = true;
                //Otherwise, subtract the frequency from spawn result for the next loop around
            } else {
                spawn_chance -= it->frequency;
            }
        }
    }

    // Force quantity to decrement regardless of whether we found a monster.
    if( quantity && !monster_found ) {
        ( *quantity )--;
    }

    return spawn_details;
}
示例#2
0
//Quantity is adjusted directly as a side effect of this function
MonsterGroupResult MonsterGroupManager::GetResultFromGroup(
        std::string group_name, int *quantity, int turn )
{
    int spawn_chance = rng(1, 1000);
    MonsterGroup group = monsterGroupMap[group_name];

    //Our spawn details specify, by default, a single instance of the default monster
    MonsterGroupResult spawn_details = MonsterGroupResult(group.defaultMonster,1);
    //If the default monster is too difficult, replace this with "mon_null"
    if(turn!=-1 && (turn + 900 < MINUTES(STARTING_MINUTES) + HOURS(GetMType(group.defaultMonster)->difficulty))){
        spawn_details = MonsterGroupResult("mon_null",0);
    }

    bool monster_found = false;
    // Step through spawn definitions from the monster group until one is found or
    for (FreqDef_iter it = group.monsters.begin(); it != group.monsters.end() && !monster_found; ++it){
        // There's a lot of conditions to work through to see if this spawn definition is valid
        bool valid_entry = true;
        // I don't know what turn == -1 is checking for, but it makes monsters always valid for difficulty purposes
        valid_entry = valid_entry && (turn == -1 || (turn+900) >= (MINUTES(STARTING_MINUTES) + HOURS(GetMType(it->name)->difficulty)));
        // If we are in classic mode, require the monster type to be either CLASSIC or WILDLIFE
        if(ACTIVE_WORLD_OPTIONS["CLASSIC_ZOMBIES"]){
            valid_entry = valid_entry && (GetMType(it->name)->in_category("CLASSIC") || GetMType(it->name)->in_category("WILDLIFE"));
        }
        //Insure that the time is not before the spawn first appears or after it stops appearing
        valid_entry = valid_entry && (HOURS(it->starts) < g->turn.get_turn());
        valid_entry = valid_entry && (it->lasts_forever() || HOURS(it->ends) > g->turn.get_turn());

        std::vector<std::pair<int,int> > valid_times_of_day;
        bool season_limited = false;
        bool season_matched = false;
        //Collect the various spawn conditions, and then insure they are met appropriately
        for(std::vector<std::string>::iterator condition = it->conditions.begin(); condition != it->conditions.end(); ++condition){
            //Collect valid time of day ranges
            if( (*condition) == "DAY" || (*condition) == "NIGHT" || (*condition) == "DUSK" || (*condition) == "DAWN" ){
                int sunset = g->turn.sunset().get_turn();
                int sunrise = g->turn.sunrise().get_turn();
                if((*condition) == "DAY"){
                    valid_times_of_day.push_back( std::make_pair(sunrise,sunset) );
                } else if((*condition) == "NIGHT"){
                    valid_times_of_day.push_back( std::make_pair(sunset,sunrise) );
                } else if((*condition) == "DUSK"){
                    valid_times_of_day.push_back( std::make_pair(sunset-HOURS(1),sunset+HOURS(1)) );
                } else if((*condition) == "DAWN"){
                    valid_times_of_day.push_back( std::make_pair(sunrise-HOURS(1),sunrise+HOURS(1)) );
                }
            }
            
            //If we have any seasons listed, we know to limit by season, and if any season matches this season, we are good to spawn
            if( (*condition) == "SUMMER" || (*condition) == "WINTER" || (*condition) == "SPRING" || (*condition) == "AUTUMN" ){
                season_limited = true;
                if( (g->turn.get_season() == SUMMER && (*condition) == "SUMMER") ||
                    (g->turn.get_season() == WINTER && (*condition) == "WINTER") ||
                    (g->turn.get_season() == SPRING && (*condition) == "SPRING") ||
                    (g->turn.get_season() == AUTUMN && (*condition) == "AUTUMN") ){
                    season_matched = true;
                }
            }
        }

        //Make sure the current time of day is within one of the valid time ranges for this spawn
        bool is_valid_time_of_day = false;
        if(valid_times_of_day.size() < 1){
            //Then it can spawn whenever, since no times were defined
            is_valid_time_of_day = true;
        } else {
            //Otherwise, it's valid if it matches any of the times of day
            for(std::vector<std::pair<int,int> >::iterator time_pair = valid_times_of_day.begin(); time_pair != valid_times_of_day.end(); ++time_pair){
                int time_now = g->turn.get_turn();
                if(time_now > time_pair->first &&  time_now < time_pair->second){
                    is_valid_time_of_day = true;
                }
            }
        }
        if(!is_valid_time_of_day){
            valid_entry = false;
        }

        //If we are limited by season, make sure we matched a season
        if(season_limited && !season_matched){
            valid_entry = false;
        }

        //If the entry was valid, check to see if we actually spawn it
        if(valid_entry){
            //If the monsters frequency is greater than the spawn_chance, select this spawn rule
            if(it->frequency >= spawn_chance){
                if(it->pack_maximum > 1){
                  spawn_details = MonsterGroupResult(it->name, rng(it->pack_minimum,it->pack_maximum));
                } else {
                  spawn_details = MonsterGroupResult(it->name, 1);
                }
                //And if a quantity pointer with remaining value was passed, will will modify the external value as a side effect
                //We will reduce it by the spawn rule's cost multiplier
                if(quantity){
                    *quantity -= it->cost_multiplier * spawn_details.pack_size;
                }
                monster_found = true;
            //Otherwise, subtract the frequency from spawn result for the next loop around
            }else{
                spawn_chance -= it->frequency;
            }
        }
    }

    return spawn_details;
}