From 1acc5c3b399b756f29c5f458e915052f890c266c Mon Sep 17 00:00:00 2001 From: dshaligram Date: Fri, 29 Dec 2006 09:30:00 +0000 Subject: [1622133] Implemented incremental butchering as Haran suggested. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@722 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/delay.cc | 387 ++++++++++++++++++++++++---------------------- crawl-ref/source/food.cc | 145 ++++++++--------- 2 files changed, 276 insertions(+), 256 deletions(-) diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index eacddf56c1..c7aab68460 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -44,6 +44,7 @@ extern std::vector items_for_multidrop; static void armour_wear_effects(const int item_inv_slot); static void handle_run_delays(const delay_queue_item &delay); static void handle_macro_delay(); +static void finish_delay(const delay_queue_item &delay); // Returns true if this delay can act as a parent to other delays, i.e. if // other delays can be spawned while this delay is running. If is_parent_delay @@ -60,7 +61,7 @@ static bool is_parent_delay(int delay) || delay == DELAY_MULTIDROP); } -static void push_delay(const delay_queue_item &delay) +static int push_delay(const delay_queue_item &delay) { for (delay_queue_type::iterator i = you.delay_queue.begin(); i != you.delay_queue.end(); @@ -69,10 +70,11 @@ static void push_delay(const delay_queue_item &delay) if (is_parent_delay( i->type )) { you.delay_queue.insert(i, delay); - return; + return (i - you.delay_queue.begin()); } } you.delay_queue.push_back( delay ); + return (you.delay_queue.size() - 1); } static void pop_delay() @@ -97,7 +99,17 @@ void start_delay( int type, int turns, int parm1, int parm2 ) delay.parm1 = parm1; delay.parm2 = parm2; - switch ( delay.type ) { + // Handle zero-turn delays (possible with butchering). + if (turns == 0) + { + // Don't issue startup message. + if (push_delay(delay) == 0) + finish_delay(delay); + return; + } + + switch ( delay.type ) + { case DELAY_ARMOUR_ON: mpr("You start putting on your armour.", MSGCH_MULTITURN_ACTION); break; @@ -364,223 +376,228 @@ void handle_delay( void ) } else { - switch (delay.type) - { - case DELAY_AUTOPICKUP: - { - const int estop = - you.running == RMODE_EXPLORE_GREEDY? - ES_GREEDY_PICKUP : ES_PICKUP; - if ((Options.explore_stop & estop) && prompt_stop_explore(estop)) - stop_delay(); - break; - } - - case DELAY_WEAPON_SWAP: - weapon_switch( delay.parm1 ); - break; + finish_delay(delay); + } +} - case DELAY_JEWELLERY_ON: - puton_ring( delay.parm1, false ); - break; +static void finish_delay(const delay_queue_item &delay) +{ + char str_pass[ ITEMNAME_SIZE ]; + switch (delay.type) + { + case DELAY_AUTOPICKUP: + { + const int estop = + you.running == RMODE_EXPLORE_GREEDY? + ES_GREEDY_PICKUP : ES_PICKUP; + if ((Options.explore_stop & estop) && prompt_stop_explore(estop)) + stop_delay(); + break; + } - case DELAY_ARMOUR_ON: - armour_wear_effects( delay.parm1 ); - break; + case DELAY_WEAPON_SWAP: + weapon_switch( delay.parm1 ); + break; - case DELAY_ARMOUR_OFF: - { - in_name( delay.parm1, DESC_NOCAP_YOUR, str_pass ); - snprintf( info, INFO_SIZE, "You finish taking off %s.", str_pass ); - mpr(info); + case DELAY_JEWELLERY_ON: + puton_ring( delay.parm1, false ); + break; - const equipment_type slot = - get_armour_slot( you.inv[delay.parm1] ); + case DELAY_ARMOUR_ON: + armour_wear_effects( delay.parm1 ); + break; - if (slot == EQ_BODY_ARMOUR) - { - you.equip[EQ_BODY_ARMOUR] = -1; - } - else - { - switch (slot) - { - case EQ_SHIELD: - if (delay.parm1 == you.equip[EQ_SHIELD]) - you.equip[EQ_SHIELD] = -1; - break; - - case EQ_CLOAK: - if (delay.parm1 == you.equip[EQ_CLOAK]) - you.equip[EQ_CLOAK] = -1; - break; - - case EQ_HELMET: - if (delay.parm1 == you.equip[EQ_HELMET]) - you.equip[EQ_HELMET] = -1; - break; - - - case EQ_GLOVES: - if (delay.parm1 == you.equip[EQ_GLOVES]) - you.equip[EQ_GLOVES] = -1; - break; - - case EQ_BOOTS: - if (delay.parm1 == you.equip[EQ_BOOTS]) - you.equip[EQ_BOOTS] = -1; - break; - - default: - break; - } - } + case DELAY_ARMOUR_OFF: + { + in_name( delay.parm1, DESC_NOCAP_YOUR, str_pass ); + snprintf( info, INFO_SIZE, "You finish taking off %s.", str_pass ); + mpr(info); - unwear_armour( delay.parm1 ); + const equipment_type slot = + get_armour_slot( you.inv[delay.parm1] ); - you.redraw_armour_class = 1; - you.redraw_evasion = 1; - break; + if (slot == EQ_BODY_ARMOUR) + { + you.equip[EQ_BODY_ARMOUR] = -1; } - case DELAY_EAT: - mpr( "You finish eating." ); - // For chunks, warn the player if they're not getting much - // nutrition. - if (delay.parm1) - chunk_nutrition_message(delay.parm1); - break; + else + { + switch (slot) + { + case EQ_SHIELD: + if (delay.parm1 == you.equip[EQ_SHIELD]) + you.equip[EQ_SHIELD] = -1; + break; - case DELAY_MEMORISE: - mpr( "You finish memorising." ); - add_spell_to_memory( delay.parm1 ); - break; + case EQ_CLOAK: + if (delay.parm1 == you.equip[EQ_CLOAK]) + you.equip[EQ_CLOAK] = -1; + break; - case DELAY_PASSWALL: - { - mpr( "You finish merging with the rock." ); - more(); // or the above message won't be seen + case EQ_HELMET: + if (delay.parm1 == you.equip[EQ_HELMET]) + you.equip[EQ_HELMET] = -1; + break; - const int pass_x = delay.parm1; - const int pass_y = delay.parm2; + case EQ_GLOVES: + if (delay.parm1 == you.equip[EQ_GLOVES]) + you.equip[EQ_GLOVES] = -1; + break; - if (pass_x != 0 && pass_y != 0) - { + case EQ_BOOTS: + if (delay.parm1 == you.equip[EQ_BOOTS]) + you.equip[EQ_BOOTS] = -1; + break; - switch (grd[ pass_x ][ pass_y ]) - { - case DNGN_ROCK_WALL: - case DNGN_STONE_WALL: - case DNGN_METAL_WALL: - case DNGN_GREEN_CRYSTAL_WALL: - case DNGN_WAX_WALL: - case DNGN_SILVER_STATUE: - case DNGN_ORANGE_CRYSTAL_STATUE: - ouch(1 + you.hp, 0, KILLED_BY_PETRIFICATION); - break; - - case DNGN_SECRET_DOOR: // oughtn't happen - case DNGN_CLOSED_DOOR: // open the door - grd[ pass_x ][ pass_y ] = DNGN_OPEN_DOOR; - break; - - default: - break; - } - - // move any monsters out of the way: - int mon = mgrd[ pass_x ][ pass_y ]; - if (mon != NON_MONSTER) - { - // one square, a few squares, anywhere... - if (!shift_monster(&menv[mon]) - && !monster_blink(&menv[mon])) - { - monster_teleport( &menv[mon], true, true ); - } - } - - move_player_to_grid(pass_x, pass_y, false, true, true); - redraw_screen(); - } + default: + break; } - break; + } - case DELAY_BUTCHER: - snprintf(info, INFO_SIZE, "You finish %s the corpse into pieces.", - (you.species == SP_TROLL || - you.species == SP_GHOUL) ? "ripping" : "chopping" ); - mpr(info); + unwear_armour( delay.parm1 ); - turn_corpse_into_chunks( mitm[ delay.parm1 ] ); + you.redraw_armour_class = 1; + you.redraw_evasion = 1; + break; + } + case DELAY_EAT: + mpr( "You finish eating." ); + // For chunks, warn the player if they're not getting much + // nutrition. + if (delay.parm1) + chunk_nutrition_message(delay.parm1); + break; - if (you.berserker && you.berserk_penalty != NO_BERSERK_PENALTY) - { - mpr("You enjoyed that."); - you.berserk_penalty = 0; - } - break; + case DELAY_MEMORISE: + mpr( "You finish memorising." ); + add_spell_to_memory( delay.parm1 ); + break; + + case DELAY_PASSWALL: + { + mpr( "You finish merging with the rock." ); + more(); // or the above message won't be seen - case DELAY_DROP_ITEM: - // Note: checking if item is droppable is assumed to - // be done before setting up this delay... this includes - // quantity (delay.parm2). -- bwr + const int pass_x = delay.parm1; + const int pass_y = delay.parm2; - // Make sure item still exists. - if (!is_valid_item( you.inv[ delay.parm1 ] )) + if (pass_x != 0 && pass_y != 0) + { + + switch (grd[ pass_x ][ pass_y ]) + { + case DNGN_ROCK_WALL: + case DNGN_STONE_WALL: + case DNGN_METAL_WALL: + case DNGN_GREEN_CRYSTAL_WALL: + case DNGN_WAX_WALL: + case DNGN_SILVER_STATUE: + case DNGN_ORANGE_CRYSTAL_STATUE: + ouch(1 + you.hp, 0, KILLED_BY_PETRIFICATION); break; - // Must handle unwield_item before we attempt to copy - // so that temporary brands and such are cleared. -- bwr - if (delay.parm1 == you.equip[EQ_WEAPON]) - { - unwield_item( delay.parm1 ); - you.equip[EQ_WEAPON] = -1; - canned_msg( MSG_EMPTY_HANDED ); + case DNGN_SECRET_DOOR: // oughtn't happen + case DNGN_CLOSED_DOOR: // open the door + grd[ pass_x ][ pass_y ] = DNGN_OPEN_DOOR; + break; + + default: + break; } - if (!copy_item_to_grid( you.inv[ delay.parm1 ], - you.x_pos, you.y_pos, delay.parm2, - true )) + // move any monsters out of the way: + int mon = mgrd[ pass_x ][ pass_y ]; + if (mon != NON_MONSTER) { - mpr("Too many items on this level, not dropping the item."); + // one square, a few squares, anywhere... + if (!shift_monster(&menv[mon]) + && !monster_blink(&menv[mon])) + { + monster_teleport( &menv[mon], true, true ); + } } - else - { - quant_name( you.inv[ delay.parm1 ], delay.parm2, - DESC_NOCAP_A, str_pass ); - snprintf( info, INFO_SIZE, "You drop %s.", str_pass ); - mpr(info); + move_player_to_grid(pass_x, pass_y, false, true, true); + redraw_screen(); + } + break; + } - dec_inv_item_quantity( delay.parm1, delay.parm2 ); - } - break; + case DELAY_BUTCHER: + snprintf(info, INFO_SIZE, "You finish %s the corpse into pieces.", + (you.species == SP_TROLL || + you.species == SP_GHOUL) ? "ripping" : "chopping" ); + mpr(info); - case DELAY_ASCENDING_STAIRS: - up_stairs(); - untag_followers(); - break; + turn_corpse_into_chunks( mitm[ delay.parm1 ] ); - case DELAY_DESCENDING_STAIRS: - down_stairs( false, delay.parm1 ); - untag_followers(); - break; + if (you.berserker && you.berserk_penalty != NO_BERSERK_PENALTY) + { + mpr("You enjoyed that."); + you.berserk_penalty = 0; + } + break; + + case DELAY_DROP_ITEM: + // Note: checking if item is droppable is assumed to + // be done before setting up this delay... this includes + // quantity (delay.parm2). -- bwr - case DELAY_INTERRUPTIBLE: - case DELAY_UNINTERRUPTIBLE: - // these are simple delays that have no effect when complete + // Make sure item still exists. + if (!is_valid_item( you.inv[ delay.parm1 ] )) break; - default: - mpr( "You finish doing something." ); - break; + // Must handle unwield_item before we attempt to copy + // so that temporary brands and such are cleared. -- bwr + if (delay.parm1 == you.equip[EQ_WEAPON]) + { + unwield_item( delay.parm1 ); + you.equip[EQ_WEAPON] = -1; + canned_msg( MSG_EMPTY_HANDED ); } - you.wield_change = true; - print_stats(); // force redraw of the stats - you.turn_is_over = true; - pop_delay(); + if (!copy_item_to_grid( you.inv[ delay.parm1 ], + you.x_pos, you.y_pos, delay.parm2, + true )) + { + mpr("Too many items on this level, not dropping the item."); + } + else + { + quant_name( you.inv[ delay.parm1 ], delay.parm2, + DESC_NOCAP_A, str_pass ); + + snprintf( info, INFO_SIZE, "You drop %s.", str_pass ); + mpr(info); + + dec_inv_item_quantity( delay.parm1, delay.parm2 ); + } + break; + + case DELAY_ASCENDING_STAIRS: + up_stairs(); + untag_followers(); + break; + + case DELAY_DESCENDING_STAIRS: + down_stairs( false, delay.parm1 ); + untag_followers(); + break; + + case DELAY_INTERRUPTIBLE: + case DELAY_UNINTERRUPTIBLE: + // these are simple delays that have no effect when complete + break; + + default: + mpr( "You finish doing something." ); + break; } + + you.wield_change = true; + print_stats(); // force redraw of the stats + you.turn_is_over = true; + pop_delay(); } static void armour_wear_effects(const int item_slot) diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc index 5ec6b7bbfb..93af87ce84 100644 --- a/crawl-ref/source/food.cc +++ b/crawl-ref/source/food.cc @@ -232,87 +232,90 @@ bool butchery(void) // to butcher, *then* decide to actually butcher it. // The old code did it the other way. if ( !can_butcher && you.berserker ) { - mpr ("You are too berserk to search for a butchering knife!"); - return (false); + mpr ("You are too berserk to search for a butchering knife!"); + return (false); } int objl; for (objl = igrd[you.x_pos][you.y_pos]; objl != NON_ITEM; - objl = mitm[objl].link) { - - if ( (mitm[objl].base_type != OBJ_CORPSES) || - (mitm[objl].sub_type != CORPSE_BODY) ) - continue; - - // offer the possibility of butchering - it_name(objl, DESC_NOCAP_A, str_pass); - snprintf(info, INFO_SIZE, "Butcher %s?", str_pass); - int answer = yesnoquit( info, true, 'n', false ); - if ( answer == -1 ) - break; - if ( answer == 0 ) - continue; + objl = mitm[objl].link) + { + if ( (mitm[objl].base_type != OBJ_CORPSES) || + (mitm[objl].sub_type != CORPSE_BODY) ) + continue; + + // offer the possibility of butchering + it_name(objl, DESC_NOCAP_A, str_pass); + snprintf(info, INFO_SIZE, "Butcher %s?", str_pass); + int answer = yesnoquit( info, true, 'n', false ); + if ( answer == -1 ) + break; + if ( answer == 0 ) + continue; - if ( Options.easy_butcher && !can_butcher ) { - - // try to find a butchering implement - wpn_switch = find_butchering_implement(); - const int wpn = you.equip[EQ_WEAPON]; - if ( wpn_switch ) { - new_cursed = - (wpn != -1) && - (you.inv[wpn].base_type == OBJ_WEAPONS) && - item_cursed( you.inv[wpn]); - } + if ( Options.easy_butcher && !can_butcher ) + { + // try to find a butchering implement + wpn_switch = find_butchering_implement(); + const int wpn = you.equip[EQ_WEAPON]; + if ( wpn_switch ) + { + new_cursed = + (wpn != -1) && + (you.inv[wpn].base_type == OBJ_WEAPONS) && + item_cursed( you.inv[wpn]); + } - // note that barehanded butchery would not reach this - // stage, so if wpn == -1 the user selected '-' when - // switching weapons + // note that barehanded butchery would not reach this + // stage, so if wpn == -1 the user selected '-' when + // switching weapons - if (!wpn_switch || wpn == -1 || !can_cut_meat(you.inv[wpn])) { - - // still can't butcher. Early out - if ( wpn == -1 ) { - if (you.equip[EQ_GLOVES] == -1) - mpr("What, with your bare hands?"); - else - mpr("Your gloves aren't that sharp!"); - } - else - mpr("Maybe you should try using a sharper implement."); + if (!wpn_switch || wpn == -1 || !can_cut_meat(you.inv[wpn])) + { + // still can't butcher. Early out + if ( wpn == -1 ) { + if (you.equip[EQ_GLOVES] == -1) + mpr("What, with your bare hands?"); + else + mpr("Your gloves aren't that sharp!"); + } + else + mpr("Maybe you should try using a sharper implement."); - if ( !new_cursed && wpn_switch ) - start_delay( DELAY_WEAPON_SWAP, 1, old_weapon ); + if ( !new_cursed && wpn_switch ) + start_delay( DELAY_WEAPON_SWAP, 1, old_weapon ); - return false; - } + return false; + } - // switched to a good butchering knife - can_butcher = true; - } + // switched to a good butchering knife + can_butcher = true; + } - if ( can_butcher ) { - - // we actually butcher now - if ( barehand_butcher ) - mpr("You start tearing the corpse apart."); - else - mpr("You start hacking away."); - - if (you.duration[DUR_PRAYER] && - (you.religion == GOD_OKAWARU || you.religion == GOD_MAKHLEB || - you.religion == GOD_TROG)) { - offer_corpse(objl); - destroy_item(objl); - } - else { - int work_req = 3 - mitm[objl].plus2; - if (work_req < 0) - work_req = 0; - - start_delay(DELAY_BUTCHER, work_req, objl, mitm[objl].special); - } + if ( can_butcher ) + { + // we actually butcher now + if ( barehand_butcher ) + mpr("You start tearing the corpse apart."); + else + mpr("You start hacking away."); + + if (you.duration[DUR_PRAYER] && + (you.religion == GOD_OKAWARU || you.religion == GOD_MAKHLEB || + you.religion == GOD_TROG)) + { + offer_corpse(objl); + destroy_item(objl); + } + else + { + int work_req = 4 - (++mitm[objl].plus2); + if (work_req < 0) + work_req = 0; + + start_delay(DELAY_BUTCHER, work_req, objl, mitm[objl].special); + } } // switch weapon back @@ -320,10 +323,10 @@ bool butchery(void) start_delay( DELAY_WEAPON_SWAP, 1, old_weapon ); you.turn_is_over = true; - + return true; } - + mpr("There isn't anything to dissect here."); if (!new_cursed && wpn_switch) { // should never happen -- cgit v1.2.3-54-g00ecf