void CueStack::switchCue(int from, int to, const QList<Universe *> ua) { qDebug() << Q_FUNC_INFO; Cue newCue; Cue oldCue; m_mutex.lock(); if (to >= 0 && to < m_cues.size()) newCue = m_cues[to]; if (from >= 0 && from < m_cues.size()) oldCue = m_cues[from]; m_mutex.unlock(); // Fade out the HTP channels of the previous cue QHashIterator <uint,uchar> oldit(oldCue.values()); while (oldit.hasNext() == true) { oldit.next(); FadeChannel fc; fc.setFixture(doc(), Fixture::invalidId()); fc.setChannel(oldit.key()); if (fc.group(doc()) == QLCChannel::Intensity) { fc.setElapsed(0); fc.setReady(false); fc.setTarget(0); fc.setFadeTime(oldCue.fadeOutSpeed()); insertStartValue(fc, ua); m_fader->add(fc); } } // Fade in all channels of the new cue QHashIterator <uint,uchar> newit(newCue.values()); while (newit.hasNext() == true) { newit.next(); FadeChannel fc; fc.setFixture(doc(), Fixture::invalidId()); fc.setChannel(newit.key()); fc.setTarget(newit.value()); fc.setElapsed(0); fc.setReady(false); fc.setFadeTime(newCue.fadeInSpeed()); insertStartValue(fc, ua); m_fader->add(fc); } }
item recipe::create_result() const { item newit( result_, calendar::turn, item::default_charges_tag{} ); if( charges >= 0 ) { newit.charges = charges; } if( !newit.craft_has_charges() ) { newit.charges = 0; } else if( result_mult != 1 ) { // @todo Make it work for charge-less items newit.charges *= result_mult; } if( newit.has_flag( "VARSIZE" ) ) { newit.item_tags.insert( "FIT" ); } if( contained == true ) { newit = newit.in_container( container ); } return newit; }
void game::complete_craft() { recipe making = recipes[u.activity.index]; // Which recipe is it? std::vector<component> will_use; // List of all items we're using, w/ count // Up to 5 components / tools for (int i = 0; i < 5; i++) { if (making.components[i].size() > 0) { // For each set of components in the recipe, fill you_have with the list of all // matching ingredients the player has. std::vector<component> you_have; for (int j = 0; j < making.components[i].size(); j++) { if (u.has_amount(making.components[i][j].type, making.components[i][j].count)) you_have.push_back(making.components[i][j]); } if (you_have.size() == 1) // Only one, so we'll definitely use it will_use.push_back(component(you_have[0].type, you_have[0].count)); else { // Let the player pick which component they want to use WINDOW* w = newwin(you_have.size() + 2, 30, 10, 25); wborder(w, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX ); mvwprintz(w, 0, 5, c_red, "Use which component?"); for (int j = 0; j < you_have.size(); j++) mvwprintz(w, j + 1, 1, c_white, "%d: %s", j + 1, itypes[you_have[j].type]->name.c_str()); wrefresh(w); char ch; do ch = getch(); while (ch < '1' || ch >= '1' + you_have.size()); ch -= '1'; will_use.push_back(component(you_have[ch].type, you_have[ch].count)); delwin(w); } } // Done looking at components // Use charges of any tools that require charges used if (making.tools[i].size() > 0) { for (int j = 0; j < making.tools[i].size(); j++) { if (making.tools[i][j].count > 0) u.use_charges(making.tools[i][j].type, making.tools[i][j].count); } } } // Done finding the components/tools needed // # of dice is 75% primary skill, 25% secondary (unless secondary is null) int skill_dice = u.sklevel[making.sk_primary] * 3; if (making.sk_secondary == sk_null) skill_dice += u.sklevel[making.sk_primary]; else skill_dice += u.sklevel[making.sk_secondary]; // Sides on dice is 16 plus your current intelligence int skill_sides = 16 + u.int_cur; int diff_dice = making.difficulty * 4; // Since skill level is * 4 also int diff_sides = 24; // 16 + 8 (default intelligence) int skill_roll = dice(skill_dice, skill_sides); int diff_roll = dice(diff_dice, diff_sides); if (making.sk_primary != sk_null) u.practice(making.sk_primary, making.difficulty * 5 + 20); if (making.sk_secondary != sk_null) u.practice(making.sk_secondary, 5); // Messed up badly; waste some components. if (making.difficulty != 0 && diff_roll > skill_roll * (1 + 0.1 * rng(1, 5))) { add_msg("You fail to make the %s, and waste some materials.", itypes[making.result]->name.c_str()); int num_lost = rng(1, will_use.size()); for (int i = 0; i < num_lost; i++) { int n = rng(0, will_use.size() - 1); if (itypes[will_use[n].type]->is_ammo() && will_use[i].type != itm_gasoline) u.use_charges(will_use[n].type, will_use[n].count); else u.use_amount(will_use[n].type, will_use[n].count); will_use.erase(will_use.begin() + n); } u.activity.type = ACT_NULL; return; // Messed up slightly; no components wasted. } else if (diff_roll > skill_roll) { add_msg("You fail to make the %s, but don't waste any materials.", itypes[making.result]->name.c_str()); u.activity.type = ACT_NULL; return; } // If we're here, the craft was a success! // Use up the items in will_use for (int i = 0; i < will_use.size(); i++) { if (itypes[will_use[i].type]->is_ammo() && will_use[i].type != itm_gasoline) u.use_charges(will_use[i].type, will_use[i].count); else u.use_amount(will_use[i].type, will_use[i].count); } // Set up the new item, and pick an inventory letter int iter = 0; item newit(itypes[making.result], turn, nextinv); do { newit.invlet = nextinv; advance_nextinv(); iter++; } while (u.has_item(newit.invlet) && iter < 52); newit = newit.in_its_container(&itypes); // We might not have space for the item if (iter == 52 || u.volume_carried()+newit.volume() > u.volume_capacity()) { add_msg("There's no room in your inventory for the %s, so you drop it.", newit.tname().c_str()); m.add_item(u.posx, u.posy, newit); } else if (u.weight_carried() + newit.volume() > u.weight_capacity()) { add_msg("The %s is too heavy to carry, so you drop it.", newit.tname().c_str()); m.add_item(u.posx, u.posy, newit); } else { u.i_add(newit); add_msg("%c - %s", newit.invlet, newit.tname().c_str()); } }
void player::complete_disassemble( int item_pos, const tripoint &loc, bool from_ground, const recipe &dis ) { // Get the proper recipe - the one for disassembly, not assembly const auto dis_requirements = dis.disassembly_requirements(); item &org_item = get_item_for_uncraft( *this, item_pos, loc, from_ground ); bool filthy = org_item.is_filthy(); if( org_item.is_null() ) { add_msg( _( "The item has vanished." ) ); activity.set_to_null(); return; } if( org_item.typeId() != dis.result ) { add_msg( _( "The item might be gone, at least it is not at the expected position anymore." ) ); activity.set_to_null(); return; } // Make a copy to keep its data (damage/components) even after it // has been removed. item dis_item = org_item; float component_success_chance = std::min( std::pow( 0.8, dis_item.damage() ), 1.0 ); add_msg( _( "You disassemble the %s into its components." ), dis_item.tname().c_str() ); // Remove any batteries, ammo and mods first remove_ammo( &dis_item, *this ); remove_radio_mod( dis_item, *this ); if( dis_item.count_by_charges() ) { // remove the charges that one would get from crafting it org_item.charges -= dis.create_result().charges; } // remove the item, except when it's counted by charges and still has some if( !org_item.count_by_charges() || org_item.charges <= 0 ) { if( from_ground ) { g->m.i_rem( loc, item_pos ); } else { i_rem( item_pos ); } } // Consume tool charges for( const auto &it : dis_requirements.get_tools() ) { consume_tools( it ); } // add the components to the map // Player skills should determine how many components are returned int skill_dice = 2 + get_skill_level( dis.skill_used ) * 3; skill_dice += get_skill_level( dis.skill_used ); // Sides on dice is 16 plus your current intelligence ///\EFFECT_INT increases success rate for disassembling items int skill_sides = 16 + int_cur; int diff_dice = dis.difficulty; int diff_sides = 24; // 16 + 8 (default intelligence) // disassembly only nets a bit of practice if( dis.skill_used ) { practice( dis.skill_used, ( dis.difficulty ) * 2, dis.difficulty ); } for( const auto &altercomps : dis_requirements.get_components() ) { const item_comp comp = find_component( altercomps, dis_item ); int compcount = comp.count; item newit( comp.type, calendar::turn ); // Counted-by-charge items that can be disassembled individually // have their component count multiplied by the number of charges. if( dis_item.count_by_charges() && dis.has_flag( "UNCRAFT_SINGLE_CHARGE" ) ) { compcount *= std::min( dis_item.charges, dis.create_result().charges ); } // Compress liquids and counted-by-charges items into one item, // they are added together on the map anyway and handle_liquid // should only be called once to put it all into a container at once. if( newit.count_by_charges() || newit.made_of( LIQUID ) ) { newit.charges = compcount; compcount = 1; } else if( !newit.craft_has_charges() && newit.charges > 0 ) { // tools that can be unloaded should be created unloaded, // tools that can't be unloaded will keep their default charges. newit.charges = 0; } for( ; compcount > 0; compcount-- ) { const bool comp_success = ( dice( skill_dice, skill_sides ) > dice( diff_dice, diff_sides ) ); if( dis.difficulty != 0 && !comp_success ) { add_msg( m_bad, _( "You fail to recover %s." ), newit.tname().c_str() ); continue; } const bool dmg_success = component_success_chance > rng_float( 0, 1 ); if( !dmg_success ) { // Show reason for failure (damaged item, tname contains the damage adjective) //~ %1s - material, %2$s - disassembled item add_msg( m_bad, _( "You fail to recover %1$s from the %2$s." ), newit.tname().c_str(), dis_item.tname().c_str() ); continue; } // Use item from components list, or (if not contained) // use newit, the default constructed. item act_item = newit; if( filthy ) { act_item.item_tags.insert( "FILTHY" ); } for( item::t_item_vector::iterator a = dis_item.components.begin(); a != dis_item.components.end(); ++a ) { if( a->type == newit.type ) { act_item = *a; dis_item.components.erase( a ); break; } } int veh_part = -1; vehicle *veh = g->m.veh_at( pos(), veh_part ); if( veh != nullptr ) { veh_part = veh->part_with_feature( veh_part, "CARGO" ); } if( act_item.made_of( LIQUID ) ) { g->handle_all_liquid( act_item, PICKUP_RANGE ); } else if( veh_part != -1 && veh->add_item( veh_part, act_item ) ) { // add_item did put the items in the vehicle, nothing further to be done } else { // TODO: For items counted by charges, add as much as we can to the vehicle, and // the rest on the ground (see dropping code and @vehicle::add_charges) g->m.add_item_or_charges( pos(), act_item ); } } } if( !dis.learn_by_disassembly.empty() && !knows_recipe( &dis ) ) { if( can_decomp_learn( dis ) ) { // @todo: make this depend on intelligence if( one_in( 4 ) ) { learn_recipe( &recipe_dict[ dis.ident() ] ); add_msg( m_good, _( "You learned a recipe from disassembling it!" ) ); } else { add_msg( m_info, _( "You might be able to learn a recipe if you disassemble another." ) ); } } else { add_msg( m_info, _( "If you had better skills, you might learn a recipe next time." ) ); } } }
void player::activate_mutation( const std::string &mut ) { const auto &mdata = mutation_branch::get( mut ); auto &tdata = my_mutations[mut]; int cost = mdata.cost; // You can take yourself halfway to Near Death levels of hunger/thirst. // Fatigue can go to Exhausted. if ((mdata.hunger && hunger >= 700) || (mdata.thirst && thirst >= 260) || (mdata.fatigue && fatigue >= 575)) { // Insufficient Foo to *maintain* operation is handled in player::suffer add_msg(m_warning, _("You feel like using your %s would kill you!"), mdata.name.c_str()); return; } if (tdata.powered && tdata.charge > 0) { // Already-on units just lose a bit of charge tdata.charge--; } else { // Not-on units, or those with zero charge, have to pay the power cost if (mdata.cooldown > 0) { tdata.charge = mdata.cooldown - 1; } if (mdata.hunger){ hunger += cost; } if (mdata.thirst){ thirst += cost; } if (mdata.fatigue){ fatigue += cost; } tdata.powered = true; // Handle stat changes from activation apply_mods(mut, true); recalc_sight_limits(); } if( mut == "WEB_WEAVER" ) { g->m.add_field(pos(), fd_web, 1, 0); add_msg(_("You start spinning web with your spinnerets!")); } else if (mut == "BURROW"){ if (g->u.is_underwater()) { add_msg_if_player(m_info, _("You can't do that while underwater.")); tdata.powered = false; return; } int dirx, diry; if (!choose_adjacent(_("Burrow where?"), dirx, diry)) { tdata.powered = false; return; } if (dirx == g->u.posx() && diry == g->u.posy()) { add_msg_if_player(_("You've got places to go and critters to beat.")); add_msg_if_player(_("Let the lesser folks eat their hearts out.")); tdata.powered = false; return; } int turns; if (g->m.is_bashable(dirx, diry) && g->m.has_flag("SUPPORTS_ROOF", dirx, diry) && g->m.ter(dirx, diry) != t_tree) { // Takes about 100 minutes (not quite two hours) base time. // Being better-adapted to the task means that skillful Survivors can do it almost twice as fast. turns = (100000 - 5000 * g->u.skillLevel("carpentry")); } else if (g->m.move_cost(dirx, diry) == 2 && g->get_levz() == 0 && g->m.ter(dirx, diry) != t_dirt && g->m.ter(dirx, diry) != t_grass) { turns = 18000; } else { add_msg_if_player(m_info, _("You can't burrow there.")); tdata.powered = false; return; } g->u.assign_activity(ACT_BURROW, turns, -1, 0); g->u.activity.placement = tripoint(dirx, diry,0); add_msg_if_player(_("You tear into the %s with your teeth and claws."), g->m.tername(dirx, diry).c_str()); tdata.powered = false; return; // handled when the activity finishes } else if (mut == "SLIMESPAWNER") { std::vector<tripoint> valid; for (int x = posx() - 1; x <= posx() + 1; x++) { for (int y = posy() - 1; y <= posy() + 1; y++) { tripoint dest(x, y, posz()); if (g->is_empty(dest)) { valid.push_back( dest ); } } } // Oops, no room to divide! if (valid.size() == 0) { add_msg(m_bad, _("You focus, but are too hemmed in to birth a new slimespring!")); tdata.powered = false; return; } add_msg(m_good, _("You focus, and with a pleasant splitting feeling, birth a new slimespring!")); int numslime = 1; for (int i = 0; i < numslime && !valid.empty(); i++) { const tripoint target = random_entry_removed( valid ); if (g->summon_mon("mon_player_blob", target)) { monster *slime = g->monster_at( target ); slime->friendly = -1; } } //~ Usual enthusiastic slimespring small voices! :D if (one_in(3)) { add_msg(m_good, _("wow! you look just like me! we should look out for each other!")); } else if (one_in(2)) { add_msg(m_good, _("come on, big me, let's go!")); } else { add_msg(m_good, _("we're a team, we've got this!")); } tdata.powered = false; return; } else if (mut == "SHOUT1") { sounds::sound(pos(), 10 + 2 * str_cur, _("You shout loudly!")); tdata.powered = false; return; } else if (mut == "SHOUT2"){ sounds::sound(pos(), 15 + 3 * str_cur, _("You scream loudly!")); tdata.powered = false; return; } else if (mut == "SHOUT3"){ sounds::sound(pos(), 20 + 4 * str_cur, _("You let out a piercing howl!")); tdata.powered = false; return; } else if ((mut == "NAUSEA") || (mut == "VOMITOUS") ){ vomit(); tdata.powered = false; return; } else if (mut == "M_FERTILE"){ spores(); tdata.powered = false; return; } else if (mut == "M_BLOOM"){ blossoms(); tdata.powered = false; return; } else if (mut == "VINES3"){ item newit("vine_30", calendar::turn, false); if (!can_pickVolume(newit.volume())) { //Accounts for result_mult add_msg(_("You detach a vine but don't have room to carry it, so you drop it.")); g->m.add_item_or_charges(posx(), posy(), newit); } else if (!can_pickWeight(newit.weight(), !OPTIONS["DANGEROUS_PICKUPS"])) { add_msg(_("Your freshly-detached vine is too heavy to carry, so you drop it.")); g->m.add_item_or_charges(posx(), posy(), newit); } else { inv.assign_empty_invlet(newit); newit = i_add(newit); add_msg(m_info, "%c - %s", newit.invlet == 0 ? ' ' : newit.invlet, newit.tname().c_str()); } tdata.powered = false; return; } }
void game::complete_craft() { recipe* making = recipes[u.activity.index]; // Which recipe is it? // # of dice is 75% primary skill, 25% secondary (unless secondary is null) int skill_dice = u.sklevel[making->sk_primary] * 3; if (making->sk_secondary == sk_null) skill_dice += u.sklevel[making->sk_primary]; else skill_dice += u.sklevel[making->sk_secondary]; // Sides on dice is 16 plus your current intelligence int skill_sides = 16 + u.int_cur; int diff_dice = making->difficulty * 4; // Since skill level is * 4 also int diff_sides = 24; // 16 + 8 (default intelligence) int skill_roll = dice(skill_dice, skill_sides); int diff_roll = dice(diff_dice, diff_sides); if (making->sk_primary != sk_null) u.practice(making->sk_primary, making->difficulty * 5 + 20); if (making->sk_secondary != sk_null) u.practice(making->sk_secondary, 5); // Messed up badly; waste some components. if (making->difficulty != 0 && diff_roll > skill_roll * (1 + 0.1 * rng(1, 5))) { add_msg("You fail to make the %s, and waste some materials.", itypes[making->result]->name.c_str()); for (int i = 0; i < 5; i++) { if (making->components[i].size() > 0) { std::vector<component> copy = making->components[i]; for (int j = 0; j < copy.size(); j++) copy[j].count = rng(0, copy[j].count); consume_items(this, copy); } if (making->tools[i].size() > 0) consume_tools(this, making->tools[i]); } u.activity.type = ACT_NULL; return; // Messed up slightly; no components wasted. } else if (diff_roll > skill_roll) { add_msg("You fail to make the %s, but don't waste any materials.", itypes[making->result]->name.c_str()); u.activity.type = ACT_NULL; return; } // If we're here, the craft was a success! // Use up the components and tools for (int i = 0; i < 5; i++) { if (making->components[i].size() > 0) consume_items(this, making->components[i]); if (making->tools[i].size() > 0) consume_tools(this, making->tools[i]); } // Set up the new item, and pick an inventory letter int iter = 0; item newit(itypes[making->result], turn, nextinv); if (!newit.craft_has_charges()) newit.charges = 0; do { newit.invlet = nextinv; advance_nextinv(); iter++; } while (u.has_item(newit.invlet) && iter < 52); //newit = newit.in_its_container(&itypes); if (newit.made_of(LIQUID)) handle_liquid(newit, false, false); else { // We might not have space for the item if (iter == 52 || u.volume_carried()+newit.volume() > u.volume_capacity()) { add_msg("There's no room in your inventory for the %s, so you drop it.", newit.tname().c_str()); m.add_item(u.posx, u.posy, newit); } else if (u.weight_carried() + newit.volume() > u.weight_capacity()) { add_msg("The %s is too heavy to carry, so you drop it.", newit.tname().c_str()); m.add_item(u.posx, u.posy, newit); } else { u.i_add(newit); add_msg("%c - %s", newit.invlet, newit.tname().c_str()); } } }