From e07b2622e22fa66566f3e18427e2bb2f9012682e Mon Sep 17 00:00:00 2001 From: dshaligram Date: Sun, 30 Dec 2007 13:37:01 +0000 Subject: Moved handle_time and friends to effects.cc. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3157 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/effects.cc | 808 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 808 insertions(+) (limited to 'crawl-ref/source/effects.cc') diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc index 4159e7e0ee..0aa101bf09 100644 --- a/crawl-ref/source/effects.cc +++ b/crawl-ref/source/effects.cc @@ -20,8 +20,11 @@ #include "externs.h" #include "beam.h" +#include "cloud.h" #include "decks.h" +#include "delay.h" #include "direct.h" +#include "dgnevent.h" #include "food.h" #include "hiscores.h" #include "it_use2.h" @@ -41,15 +44,19 @@ #include "ouch.h" #include "player.h" #include "randart.h" +#include "religion.h" +#include "skills.h" #include "skills2.h" #include "spells3.h" #include "spells4.h" #include "spl-book.h" +#include "spl-cast.h" #include "spl-util.h" #include "state.h" #include "stuff.h" #include "terrain.h" #include "traps.h" +#include "tutorial.h" #include "view.h" #include "xom.h" @@ -1870,3 +1877,804 @@ bool forget_inventory(bool quiet) return (items_forgotten > 0); } + +/////////////////////////////////////////////////////////////////////// + +static void hell_effects() +{ + int temp_rand = random2(17); + spschool_flag_type which_miscast = SPTYP_RANDOM; + bool summon_instead = false; + monster_type which_beastie = MONS_PROGRAM_BUG; + + mpr((temp_rand == 0) ? "\"You will not leave this place.\"" : + (temp_rand == 1) ? "\"Die, mortal!\"" : + (temp_rand == 2) ? "\"We do not forgive those who trespass against us!\"" : + (temp_rand == 3) ? "\"Trespassers are not welcome here!\"" : + (temp_rand == 4) ? "\"You do not belong in this place!\"" : + (temp_rand == 5) ? "\"Leave now, before it is too late!\"" : + (temp_rand == 6) ? "\"We have you now!\"" : + // plain messages + (temp_rand == 7) ? (player_can_smell()) ? "You smell brimstone." : + "Brimstone rains from above." : + (temp_rand == 8) ? "You feel lost and a long, long way from home..." : + (temp_rand == 9) ? "You shiver with fear." : + // warning + (temp_rand == 10) ? "You feel a terrible foreboding..." : + (temp_rand == 11) ? "Something frightening happens." : + (temp_rand == 12) ? "You sense an ancient evil watching you..." : + (temp_rand == 13) ? "You suddenly feel all small and vulnerable." : + (temp_rand == 14) ? "You sense a hostile presence." : + // sounds + (temp_rand == 15) ? "A gut-wrenching scream fills the air!" : + (temp_rand == 16) ? "You hear words spoken in a strange and terrible language..." + : "You hear diabolical laughter!", + (temp_rand < 7 ? MSGCH_TALK : + temp_rand < 10 ? MSGCH_PLAIN : + temp_rand < 15 ? MSGCH_WARN + : MSGCH_SOUND) ); + + temp_rand = random2(27); + + if (temp_rand > 17) // 9 in 27 odds {dlb} + { + temp_rand = random2(8); + + if (temp_rand > 3) // 4 in 8 odds {dlb} + which_miscast = SPTYP_NECROMANCY; + else if (temp_rand > 1) // 2 in 8 odds {dlb} + which_miscast = SPTYP_SUMMONING; + else if (temp_rand > 0) // 1 in 8 odds {dlb} + which_miscast = SPTYP_CONJURATION; + else // 1 in 8 odds {dlb} + which_miscast = SPTYP_ENCHANTMENT; + + miscast_effect( which_miscast, 4 + random2(6), random2avg(97, 3), + 100, "the effects of Hell" ); + } + else if (temp_rand > 7) // 10 in 27 odds {dlb} + { + // 60:40 miscast:summon split {dlb} + summon_instead = (random2(5) > 2); + + switch (you.where_are_you) + { + case BRANCH_DIS: + if (summon_instead) + which_beastie = summon_any_demon(DEMON_GREATER); + else + which_miscast = SPTYP_EARTH; + break; + case BRANCH_GEHENNA: + if (summon_instead) + which_beastie = MONS_FIEND; + else + which_miscast = SPTYP_FIRE; + break; + case BRANCH_COCYTUS: + if (summon_instead) + which_beastie = MONS_ICE_FIEND; + else + which_miscast = SPTYP_ICE; + break; + case BRANCH_TARTARUS: + if (summon_instead) + which_beastie = MONS_SHADOW_FIEND; + else + which_miscast = SPTYP_NECROMANCY; + break; + default: // this is to silence gcc compiler warnings {dlb} + if (summon_instead) + which_beastie = MONS_FIEND; + else + which_miscast = SPTYP_NECROMANCY; + break; + } + + if (summon_instead) + { + create_monster( which_beastie, 0, BEH_HOSTILE, you.x_pos, + you.y_pos, MHITYOU, 250 ); + } + else + { + miscast_effect( which_miscast, 4 + random2(6), + random2avg(97, 3), 100, "the effects of Hell" ); + } + } + + // NB: no "else" - 8 in 27 odds that nothing happens through + // first chain {dlb} + // also note that the following is distinct from and in + // addition to the above chain: + + // try to summon at least one and up to five random monsters {dlb} + if (one_chance_in(3)) + { + create_monster( RANDOM_MONSTER, 0, BEH_HOSTILE, + you.x_pos, you.y_pos, MHITYOU, 250 ); + + for (int i = 0; i < 4; i++) + { + if (one_chance_in(3)) + { + create_monster( RANDOM_MONSTER, 0, BEH_HOSTILE, + you.x_pos, you.y_pos, MHITYOU, 250 ); + } + } + } +} + +static void rot_inventory_food(long time_delta) +{ + // Update all of the corpses and food chunks in the player's + // inventory {should be moved elsewhere - dlb} + + bool burden_changed_by_rot = false; + bool new_rotting_item = false; + for (int i = 0; i < ENDOFPACK; i++) + { + if (you.inv[i].quantity < 1) + continue; + + if (you.inv[i].base_type != OBJ_CORPSES && you.inv[i].base_type != OBJ_FOOD) + continue; + + if (you.inv[i].base_type == OBJ_CORPSES + && you.inv[i].sub_type > CORPSE_SKELETON) + { + continue; + } + + if (you.inv[i].base_type == OBJ_FOOD && you.inv[i].sub_type != FOOD_CHUNK) + continue; + + if ((time_delta / 20) >= you.inv[i].special) + { + if (you.inv[i].base_type == OBJ_FOOD) + { + if (you.equip[EQ_WEAPON] == i) + unwield_item(); + + destroy_item(you.inv[i]); + burden_changed_by_rot = true; + continue; + } + + if (you.inv[i].sub_type == CORPSE_SKELETON) + continue; // carried skeletons are not destroyed + + if (!mons_skeleton( you.inv[i].plus )) + { + if (you.equip[EQ_WEAPON] == i) + unwield_item(); + + destroy_item(you.inv[i]); + burden_changed_by_rot = true; + continue; + } + + you.inv[i].sub_type = CORPSE_SKELETON; + you.inv[i].special = 0; + you.inv[i].colour = LIGHTGREY; + you.wield_change = true; + burden_changed_by_rot = true; + continue; + } + + you.inv[i].special -= (time_delta / 20); + + if (you.inv[i].special < 100 && (you.inv[i].special + (time_delta / 20)>=100)) + { + new_rotting_item = true; + } + } + + //mv: messages when chunks/corpses become rotten + if (new_rotting_item) + { + // XXX: should probably still notice? + // Races that can't smell don't care, and trolls are stupid and + // don't care. + if (player_can_smell() && you.species != SP_TROLL) + { + int temp_rand = 0; // Grr. + switch (you.mutation[MUT_SAPROVOROUS]) + { + // level 1 and level 2 saprovores aren't so touchy + case 1: + case 2: + temp_rand = random2(8); + mpr( ((temp_rand < 5) ? "You smell something rotten." : + (temp_rand == 5) ? "You smell rotting flesh." : + (temp_rand == 6) ? "You smell decay." + : "There is something rotten in your inventory."), + MSGCH_ROTTEN_MEAT ); + break; + + // level 3 saprovores like it + case 3: + temp_rand = random2(8); + mpr( ((temp_rand < 5) ? "You smell something rotten." : + (temp_rand == 5) ? "The smell of rotting flesh makes you hungry." : + (temp_rand == 6) ? "You smell decay. Yum-yum." + : "Wow! There is something tasty in your inventory."), + MSGCH_ROTTEN_MEAT ); + break; + + default: + temp_rand = random2(8); + mpr( ((temp_rand < 5) ? "You smell something rotten." : + (temp_rand == 5) ? "The smell of rotting flesh makes you sick." : + (temp_rand == 6) ? "You smell decay. Yuck!" + : "Ugh! There is something really disgusting in your inventory."), + MSGCH_ROTTEN_MEAT ); + break; + } + } + learned_something_new(TUT_ROTTEN_FOOD); + } + if (burden_changed_by_rot) + { + mpr("Your equipment suddenly weighs less.", MSGCH_ROTTEN_MEAT); + burden_change(); + } +} + +//--------------------------------------------------------------- +// +// handle_time +// +// Do various time related actions... +// This function is called about every 20 turns. +// +//--------------------------------------------------------------- +void handle_time( long time_delta ) +{ + // BEGIN - Nasty things happen to people who spend too long in Hell: + if (player_in_hell() && coinflip()) + hell_effects(); + + // Adjust the player's stats if s/he's diseased (or recovering). + if (!you.disease) + { + if (you.strength < you.max_strength && one_chance_in(100)) + { + mpr("You feel your strength returning.", MSGCH_RECOVERY); + you.strength++; + you.redraw_strength = 1; + } + + if (you.dex < you.max_dex && one_chance_in(100)) + { + mpr("You feel your dexterity returning.", MSGCH_RECOVERY); + you.dex++; + you.redraw_dexterity = 1; + } + + if (you.intel < you.max_intel && one_chance_in(100)) + { + mpr("You feel your intelligence returning.", MSGCH_RECOVERY); + you.intel++; + you.redraw_intelligence = 1; + } + } + else + { + if (one_chance_in(30)) + { + mpr("Your disease is taking its toll.", MSGCH_WARN); + lose_stat(STAT_RANDOM, 1, false, "disease"); + } + } + + // Adjust the player's stats if s/he has the deterioration mutation + if (you.mutation[MUT_DETERIORATION] + && random2(200) <= you.mutation[MUT_DETERIORATION] * 5 - 2) + { + lose_stat(STAT_RANDOM, 1, false, "deterioration mutation"); + } + + int added_contamination = 0; + + // Account for mutagenic radiation. Invis and haste will give the + // player about .1 points per turn, mutagenic randarts will give + // about 1.5 points on average, so they can corrupt the player + // quite quickly. Wielding one for a short battle is OK, which is + // as things should be. -- GDL + if (you.duration[DUR_INVIS] && random2(10) < 6) + added_contamination++; + + if (you.duration[DUR_HASTE] && !you.duration[DUR_BERSERKER] + && random2(10) < 6) + { + added_contamination++; + } + + if (const int randart_glow = scan_randarts(RAP_MUTAGENIC)) + { + // Reduced randart glow. Note that one randart will contribute + // 2 - 5 units of glow to randart_glow. A randart with a mutagen + // index of 2 does about 0.58 points of contamination per turn. + // A randart with a mutagen index of 5 does about 0.7 points of + // contamination per turn. + + const int mean_glow = 500 + randart_glow * 40; + const int actual_glow = mean_glow / 2 + random2(mean_glow); + added_contamination += div_rand_round(actual_glow, 1000); + } + + // we take off about .5 points per turn + if (!you.duration[DUR_INVIS] && !you.duration[DUR_HASTE] && coinflip()) + added_contamination -= 1; + + contaminate_player( added_contamination ); + + // only check for badness once every other turn + if (coinflip()) + { + // [ds] Be less harsh with glow mutation; Brent and Mark Mackey note + // that the commented out random2(X) <= MC check was a bug. I've + // uncommented it but dropped the roll sharply from 150. (Brent used + // the original roll of 150 for 4.1.2, but I think players are + // sufficiently used to beta 26's unkindness that we can use a lower + // roll.) + if (you.magic_contamination >= 5 + && random2(25) <= you.magic_contamination) + { + mpr("Your body shudders with the violent release of wild energies!", MSGCH_WARN); + + // for particularly violent releases, make a little boom + if (you.magic_contamination >= 10 && coinflip()) + { + struct bolt boom; + boom.type = dchar_glyph(DCHAR_FIRED_BURST); + boom.colour = BLACK; + boom.flavour = BEAM_RANDOM; + boom.target_x = you.x_pos; + boom.target_y = you.y_pos; + // Undead enjoy extra contamination explosion damage because + // the magical contamination has a harder time dissipating + // through non-living flesh. :-) + boom.damage = + dice_def( 3, + you.magic_contamination + * (you.is_undead? 4 : 2) + / 4 ); + boom.thrower = KILL_MISC; + boom.aux_source = "a magical explosion"; + boom.beam_source = NON_MONSTER; + boom.is_beam = false; + boom.is_tracer = false; + boom.is_explosion = true; + boom.name = "magical storm"; + + boom.ench_power = (you.magic_contamination * 5); + boom.ex_size = (you.magic_contamination / 15); + if (boom.ex_size > 9) + boom.ex_size = 9; + + explosion(boom); + } + + // we want to warp the player, not do good stuff! + if (one_chance_in(5)) + mutate(RANDOM_MUTATION); + else + give_bad_mutation(coinflip()); + + // we're meaner now, what with explosions and whatnot, but + // we dial down the contamination a little faster if its actually + // mutating you. -- GDL + contaminate_player( -(random2(you.magic_contamination / 4) + 1) ); + } + } + + // Random chance to identify staff in hand based off of Spellcasting + // and an appropriate other spell skill... is 1/20 too fast? + if (you.equip[EQ_WEAPON] != -1 + && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_STAVES + && !item_type_known( you.inv[you.equip[EQ_WEAPON]] ) + && one_chance_in(20)) + { + int total_skill = you.skills[SK_SPELLCASTING]; + + switch (you.inv[you.equip[EQ_WEAPON]].sub_type) + { + case STAFF_WIZARDRY: + case STAFF_ENERGY: + total_skill += you.skills[SK_SPELLCASTING]; + break; + case STAFF_FIRE: + if (you.skills[SK_FIRE_MAGIC] > you.skills[SK_ICE_MAGIC]) + total_skill += you.skills[SK_FIRE_MAGIC]; + else + total_skill += you.skills[SK_ICE_MAGIC]; + break; + case STAFF_COLD: + if (you.skills[SK_ICE_MAGIC] > you.skills[SK_FIRE_MAGIC]) + total_skill += you.skills[SK_ICE_MAGIC]; + else + total_skill += you.skills[SK_FIRE_MAGIC]; + break; + case STAFF_AIR: + if (you.skills[SK_AIR_MAGIC] > you.skills[SK_EARTH_MAGIC]) + total_skill += you.skills[SK_AIR_MAGIC]; + else + total_skill += you.skills[SK_EARTH_MAGIC]; + break; + case STAFF_EARTH: + if (you.skills[SK_EARTH_MAGIC] > you.skills[SK_AIR_MAGIC]) + total_skill += you.skills[SK_EARTH_MAGIC]; + else + total_skill += you.skills[SK_AIR_MAGIC]; + break; + case STAFF_POISON: + total_skill += you.skills[SK_POISON_MAGIC]; + break; + case STAFF_DEATH: + total_skill += you.skills[SK_NECROMANCY]; + break; + case STAFF_CONJURATION: + total_skill += you.skills[SK_CONJURATIONS]; + break; + case STAFF_ENCHANTMENT: + total_skill += you.skills[SK_ENCHANTMENTS]; + break; + case STAFF_SUMMONING: + total_skill += you.skills[SK_SUMMONINGS]; + break; + } + + if (random2(100) < total_skill) + { + item_def& item = you.inv[you.equip[EQ_WEAPON]]; + set_ident_flags( item, ISFLAG_IDENT_MASK ); + + mprf("You are wielding %s.", item.name(DESC_NOCAP_A).c_str()); + more(); + + you.wield_change = true; + } + } + + // Check to see if an upset god wants to do something to the player + // jmf: moved huge thing to religion.cc + handle_god_time(); + + if (you.mutation[MUT_SCREAM] + && (random2(100) <= 2 + you.mutation[MUT_SCREAM] * 3) ) + { + yell(true); + } + else if (you.mutation[MUT_SLEEPINESS] + && random2(100) < you.mutation[MUT_SLEEPINESS] * 5) + { + you.put_to_sleep(); + } + + // Update all of the corpses and food chunks on the floor + update_corpses(time_delta); + + rot_inventory_food(time_delta); + + // exercise armour *xor* stealth skill: {dlb} + if (!player_light_armour(true)) + { + if (random2(1000) <= item_mass( you.inv[you.equip[EQ_BODY_ARMOUR]] )) + return; + + if (one_chance_in(6)) // lowered random roll from 7 to 6 -- bwross + exercise(SK_ARMOUR, 1); + } + else // exercise stealth skill: + { + if (you.burden_state != BS_UNENCUMBERED || you.duration[DUR_BERSERKER]) + return; + + if (you.special_wield == SPWLD_SHADOW) + return; + + if (you.equip[EQ_BODY_ARMOUR] != -1 + && random2( item_mass( you.inv[you.equip[EQ_BODY_ARMOUR]] )) >= 100) + { + return; + } + + if (one_chance_in(18)) + exercise(SK_STEALTH, 1); + } +} + +//--------------------------------------------------------------- +// +// update_level +// +// Update the level when the player returns to it. +// +//--------------------------------------------------------------- +void update_level( double elapsedTime ) +{ + int m, i; + const int turns = static_cast(elapsedTime / 10.0); + +#if DEBUG_DIAGNOSTICS + int mons_total = 0; + + mprf(MSGCH_DIAGNOSTICS, "turns: %d", turns ); +#endif + + update_corpses( elapsedTime ); + + dungeon_events.fire_event( + dgn_event(DET_TURN_ELAPSED, coord_def(0, 0), turns * 10)); + + for (m = 0; m < MAX_MONSTERS; m++) + { + struct monsters *mon = &menv[m]; + + if (mon->type == -1) + continue; + +#if DEBUG_DIAGNOSTICS + mons_total++; +#endif + + // following monsters don't get movement + if (mon->flags & MF_JUST_SUMMONED) + continue; + + // XXX: Allow some spellcasting (like Healing and Teleport)? -- bwr + // const bool healthy = (mon->hit_points * 2 > mon->max_hit_points); + + // This is the monster healing code, moved here from tag.cc: + if (monster_descriptor( mon->type, MDSC_REGENERATES ) + || mon->type == MONS_PLAYER_GHOST) + { + heal_monster( mon, turns, false ); + } + else + { + heal_monster( mon, (turns / 10), false ); + } + + if (turns >= 10) + mon->timeout_enchantments( turns / 10 ); + + // Don't move water, lava, or stationary monsters around + if (monster_habitat( mon->type ) != DNGN_FLOOR + || mons_is_stationary( mon )) + { + continue; + } + + // Let sleeping monsters lie + if (mon->behaviour == BEH_SLEEP || mons_is_paralysed(mon)) + continue; + + const int range = (turns * mon->speed) / 10; + const int moves = (range > 50) ? 50 : range; + + // const bool short_time = (range >= 5 + random2(10)); + const bool long_time = (range >= (500 + roll_dice( 2, 500 ))); + + const bool ranged_attack = (mons_has_ranged_spell( mon ) + || mons_has_ranged_attack( mon )); + +#if DEBUG_DIAGNOSTICS + // probably too annoying even for DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, + "mon #%d: range %d; long %d; " + "pos (%d,%d); targ %d(%d,%d); flags %ld", + m, range, long_time, mon->x, mon->y, + mon->foe, mon->target_x, mon->target_y, mon->flags ); +#endif + + if (range <= 0) + continue; + + if (long_time + && (mon->behaviour == BEH_FLEE + || mon->behaviour == BEH_CORNERED + || testbits( mon->flags, MF_BATTY ) + || ranged_attack + || coinflip())) + { + if (mon->behaviour != BEH_WANDER) + { + mon->behaviour = BEH_WANDER; + mon->foe = MHITNOT; + mon->target_x = 10 + random2( GXM - 10 ); + mon->target_y = 10 + random2( GYM - 10 ); + } + else + { + // monster will be sleeping after we move it + mon->behaviour = BEH_SLEEP; + } + } + else if (ranged_attack) + { + // if we're doing short time movement and the monster has a + // ranged attack (missile or spell), then the monster will + // flee to gain distance if its "too close", else it will + // just shift its position rather than charge the player. -- bwr + if (grid_distance(mon->x, mon->y, mon->target_x, mon->target_y) < 3) + { + mon->behaviour = BEH_FLEE; + + // if the monster is on the target square, fleeing won't work + if (mon->x == mon->target_x && mon->y == mon->target_y) + { + if (you.x_pos != mon->x || you.y_pos != mon->y) + { + // flee from player's position if different + mon->target_x = you.x_pos; + mon->target_y = you.y_pos; + } + else + { + // randomize the target so we have a direction to flee + mon->target_x += (random2(3) - 1); + mon->target_y += (random2(3) - 1); + } + } + +#if DEBUG_DIAGNOSTICS + mpr( "backing off...", MSGCH_DIAGNOSTICS ); +#endif + } + else + { + shift_monster( mon, mon->x, mon->y ); + +#if DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, "shifted to (%d,%d)", mon->x, mon->y); +#endif + continue; + } + } + + coord_def pos(mon->pos()); + // dirt simple movement: + for (i = 0; i < moves; i++) + { + coord_def inc(mon->target_pos() - pos); + inc = coord_def(sgn(inc.x), sgn(inc.y)); + + if (mon->behaviour == BEH_FLEE) + inc *= -1; + + if (pos.x + inc.x < 0 || pos.x + inc.x >= GXM) + inc.x = 0; + + if (pos.y + inc.y < 0 || pos.y + inc.y >= GYM) + inc.y = 0; + + if (inc.origin()) + break; + + const coord_def next(pos + inc); + const dungeon_feature_type feat = grd(next); + if (grid_is_solid(feat) + || mgrd(next) != NON_MONSTER + || !monster_habitable_grid(mon, feat)) + break; + + pos = next; + } + + if (!shift_monster( mon, pos.x, pos.y )) + shift_monster( mon, mon->x, mon->y ); + +#if DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, "moved to (%d,%d)", mon->x, mon->y ); +#endif + } + +#if DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, "total monsters on level = %d", mons_total ); +#endif + + for (i = 0; i < MAX_CLOUDS; i++) + delete_cloud( i ); +} + +//--------------------------------------------------------------- +// +// update_corpses +// +// Update all of the corpses and food chunks on the floor. (The +// elapsed time is a double because this is called when we re- +// enter a level and a *long* time may have elapsed). +// +//--------------------------------------------------------------- +void update_corpses(double elapsedTime) +{ + int cx, cy; + + if (elapsedTime <= 0.0) + return; + + const long rot_time = static_cast(elapsedTime / 20.0); + + for (int c = 0; c < MAX_ITEMS; c++) + { + item_def &it = mitm[c]; + + if (!is_valid_item(it)) + continue; + + if (it.base_type != OBJ_CORPSES && it.base_type != OBJ_FOOD) + { + continue; + } + + if (it.base_type == OBJ_CORPSES + && it.sub_type > CORPSE_SKELETON) + { + continue; + } + + if (it.base_type == OBJ_FOOD && it.sub_type != FOOD_CHUNK) + { + continue; + } + + if (rot_time >= it.special && !is_being_butchered(it)) + { + if (it.base_type == OBJ_FOOD) + { + destroy_item(c); + } + else + { + if (it.sub_type == CORPSE_SKELETON + || !mons_skeleton( it.plus )) + { + destroy_item(c); + } + else + { + it.sub_type = CORPSE_SKELETON; + it.special = 200; + it.colour = LIGHTGREY; + } + } + } + else + { + ASSERT(rot_time < 256); + it.special -= rot_time; + } + } + + int fountain_checks = static_cast(elapsedTime / 1000.0); + if (random2(1000) < static_cast(elapsedTime) % 1000) + fountain_checks += 1; + + // dry fountains may start flowing again + if (fountain_checks > 0) + { + for (cx=0; cx DNGN_SPARKLING_FOUNTAIN + && grd[cx][cy] < DNGN_PERMADRY_FOUNTAIN) + { + for (int i=0; i DNGN_SPARKLING_FOUNTAIN) + grd[cx][cy] = + static_cast( + grd[cx][cy] - 1); + } + } + } + } + } + } +} -- cgit v1.2.3-54-g00ecf