/** * Enemies that drop loot raise a "loot_drop" flag to notify this loot * manager to create loot based on that creature's level and position. */ void LootManager::checkEnemiesForLoot() { ItemStack istack; istack.quantity = 1; for (int i=0; i<enemies->enemy_count; i++) { if (enemies->enemies[i]->loot_drop) { if (enemies->enemies[i]->stats.quest_loot_id != 0) { // quest loot istack.item = enemies->enemies[i]->stats.quest_loot_id; addLoot(istack, enemies->enemies[i]->stats.pos); } else { // random loot determineLoot(enemies->enemies[i]->stats.level, enemies->enemies[i]->stats.pos); } enemies->enemies[i]->loot_drop = false; } } }
/** * As map events occur, some might have a component named "loot" * Loot is created at component x,y */ void LootManager::checkMapForLoot() { Point p; Event_Component *ec; ItemStack loot; while (!map->loot.empty()) { ec = &map->loot.front(); p.x = ec->x; p.y = ec->y; if (ec->s == "random") { determineLoot(ec->z, p); } else if (ec->s == "id") { loot.item = ec->z; loot.quantity = 1; addLoot(loot, p); } else if (ec->s == "currency") { addGold(ec->z, p); } map->loot.pop(); } }
void LootManager::checkLoot(std::vector<Event_Component> &loot_table, FPoint *pos) { if (hero == NULL) { logError("LootManager: checkLoot() failed, no hero."); return; } FPoint p; Event_Component *ec; ItemStack new_loot; std::vector<Event_Component*> possible_ids; int chance = rand() % 100; // first drop any 'fixed' (0% chance) items for (size_t i = loot_table.size(); i > 0; i--) { ec = &loot_table[i-1]; if (ec->z == 0) { Point src; if (pos) { src = floor(*pos); } else { src.x = ec->x; src.y = ec->y; } p = mapr->collider.get_random_neighbor(src, drop_radius); if (!mapr->collider.is_valid_position(p.x, p.y, MOVEMENT_NORMAL, false)) { p = hero->pos; } else { if (src.x == p.x && src.y == p.y) p = hero->pos; mapr->collider.block(p.x, p.y, false); tiles_to_unblock.push_back(floor(p)); } new_loot.quantity = randBetween(ec->a,ec->b); // an item id of 0 means we should drop currency instead if (ec->c == 0 || ec->c == CURRENCY_ID) { new_loot.item = CURRENCY_ID; new_loot.quantity = new_loot.quantity * (100 + hero->get(STAT_CURRENCY_FIND)) / 100; } else { new_loot.item = ec->c; } addLoot(new_loot, p); loot_table.erase(loot_table.begin()+i-1); } } // now pick up to 1 random item to drop int threshold = hero->get(STAT_ITEM_FIND) + 100; for (unsigned i = 0; i < loot_table.size(); i++) { ec = &loot_table[i]; int real_chance = ec->z; if (ec->c != 0 && ec->c != CURRENCY_ID) { real_chance = static_cast<int>(static_cast<float>(ec->z) * static_cast<float>(hero->get(STAT_ITEM_FIND) + 100) / 100.f); } if (real_chance >= chance) { if (real_chance <= threshold) { if (real_chance != threshold) { possible_ids.clear(); } threshold = real_chance; } if (chance <= threshold) { possible_ids.push_back(ec); } } } if (!possible_ids.empty()) { // if there was more than one item with the same chance, randomly pick one of them size_t chosen_loot = static_cast<size_t>(rand()) % possible_ids.size(); ec = possible_ids[chosen_loot]; Point src; if (pos) { src = floor(*pos); } else { src.x = ec->x; src.y = ec->y; } p = mapr->collider.get_random_neighbor(src, drop_radius); if (!mapr->collider.is_valid_position(p.x, p.y, MOVEMENT_NORMAL, false)) { p = hero->pos; } else { if (src.x == p.x && src.y == p.y) p = hero->pos; mapr->collider.block(p.x, p.y, false); tiles_to_unblock.push_back(floor(p)); } new_loot.quantity = randBetween(ec->a,ec->b); // an item id of 0 means we should drop currency instead if (ec->c == 0 || ec->c == CURRENCY_ID) { new_loot.item = CURRENCY_ID; new_loot.quantity = new_loot.quantity * (100 + hero->get(STAT_CURRENCY_FIND)) / 100; } else { new_loot.item = ec->c; } addLoot(new_loot, p); } }