Anonymous | Login | 2024-04-26 13:30 CEST |
Main | My View | View Issues | Change Log | Wiki | Tavern | News |
Viewing Issue Simple Details [ Jump to Notes ] [ Wiki ] | [ View Advanced ] [ Issue History ] [ Print ] | ||||||||||||
ID | Category | Severity | Reproducibility | Date Submitted | Last Update | ||||||||
0002744 | [DCSS] Patches | minor | have not tried | 2010-10-22 00:56 | 2014-08-30 19:31 | ||||||||
Reporter | minced | View Status | public | ||||||||||
Assigned To | PleasingFungus | ||||||||||||
Priority | normal | Resolution | won't do | ||||||||||
Status | resolved | Product Branch | 0.8 ancient branch | ||||||||||
Summary | 0002744: Nome racial patch! | ||||||||||||
Description |
Nomes are here. They are modeled after the Nomes appearing in "Return to Oz," scary-looking claymation people that moved through solid rock. "Nomes are gravel-skinned humanoids that live deep under the surface as wealthy scions of a small but fiercely defended subterranean empire. The few explorers unfortunate enough to trespass upon their holdings are swiftly dispatched by cold, stony hands reaching from the cavern walls, for the Nomes are so attuned to the earth they can swim through rock, stone or even metal like a shark through water. Despite their frailty, inflexibility and small stature, Nomes are powerful fighters when ensconced inside rock, gaining physical durability and significantly tougher skin. They are familiar with the smaller types of axes and mace favored by the neighboring deep dwarves, though Nomes are still dangerous when armed only with their stony fists. By nature, Nomes are peerless earth elementalists and transmuters and abysmal air elementalists, and are generally attuned to the more destructive magics. They advance in levels slightly less quickly than humans." |
||||||||||||
Additional Information | |||||||||||||
Tags | No tags attached. | ||||||||||||
Attached Files |
0001-Nomes.-Hooray.patch [^] (20,923 bytes) 2010-10-22 00:56 [Show Content] [Hide Content]From 7b38ffe95f8699c628f44c3807e4389340d221e5 Mon Sep 17 00:00:00 2001 From: Matthew M Ince <matthew@Y.(none)> Date: Thu, 21 Oct 2010 18:52:21 -0400 Subject: Nomes. Hooray. --- crawl-ref/docs/crawl_manual.txt | 19 +++++ crawl-ref/source/dat/descript/species.txt | 4 + crawl-ref/source/delay.cc | 7 +- crawl-ref/source/enum.h | 3 +- crawl-ref/source/misc.cc | 45 +++++++++++ crawl-ref/source/misc.h | 3 + crawl-ref/source/ng-setup.cc | 1 + crawl-ref/source/player-act.cc | 21 +++++- crawl-ref/source/player.cc | 114 ++++++++++++++++++++++++++++- crawl-ref/source/player.h | 4 + crawl-ref/source/skills2.cc | 38 ++++++++++ crawl-ref/source/species.cc | 7 +- crawl-ref/source/tags.cc | 2 + 13 files changed, 261 insertions(+), 7 deletions(-) diff --git a/crawl-ref/docs/crawl_manual.txt b/crawl-ref/docs/crawl_manual.txt index 1c724af..36e5c70 100644 --- a/crawl-ref/docs/crawl_manual.txt +++ b/crawl-ref/docs/crawl_manual.txt @@ -1566,6 +1566,25 @@ Deep Dwarves Dwarves can tinker with gadgets so as to recharge them. However, each time they do so, they lose a bit of their magical essence. +Nomes +--------- +Nomes are gravel-skinned humanoids that live deep under the surface as +wealthy scions of a small but fiercely defended subterranean empire. The few +explorers unfortunate enough to trespass upon their holdings are +swiftly dispatched by cold, stony hands reaching from the cavern +walls, for the Nomes are so attuned to the earth they can swim through +rock, stone or even metal like a shark through water. + +Despite their frailty, inflexibility and small stature, Nomes are +powerful fighters when ensconced inside rock, gaining physical +durability and significantly tougher skin. They are familiar with the +smaller types of axes and mace favored by the neighboring deep +dwarves, though Nomes are still dangerous when armed only with their +stony fists. By nature, Nomes are peerless earth elementalists and +transmuters and abysmal air elementalists, and are generally attuned +to the more destructive magics. They advance in levels slightly less +quickly than humans. + Hill Orcs --------- Hill Orcs are Orcs from the upper world who, jealous of the riches which diff --git a/crawl-ref/source/dat/descript/species.txt b/crawl-ref/source/dat/descript/species.txt index 6603a67..0bdf957 100644 --- a/crawl-ref/source/dat/descript/species.txt +++ b/crawl-ref/source/dat/descript/species.txt @@ -75,6 +75,10 @@ Naga A hybrid; human from the chest up, with a scaly, muscular torso trailing off like that of a snake. %%%% +Nome + +A gravel-skinned humanoid able to swim through solid rock. +%%%% Ogre Large and strong, they're mostly seen as brutes. Casting ogres have been spotted, however. diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index 0f73102..291e53c 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -996,7 +996,10 @@ static void _finish_delay(const delay_queue_item &delay) mprf(MSGCH_PLAIN, "You finish %s.", _get_zin_recite_speech("other", you.num_turns + delay.duration).c_str()); break; - + + case DELAY_ROCK_SWIMMING: + //no "finish" message to avoid spam. + break; case DELAY_PASSWALL: { mpr("You finish merging with the rock."); @@ -1678,7 +1681,7 @@ static const char *delay_names[] = "not_delayed", "eat", "vampire_feed", "armour_on", "armour_off", "jewellery_on", "memorise", "butcher", "bottle_blood", "weapon_swap", "passwall", "drop_item", "multidrop", "ascending_stairs", - "descending_stairs", "recite", "run", "rest", "travel", "macro", + "descending_stairs", "recite","swim_through_rock" ,"run", "rest", "travel", "macro", "macro_process_key", "interruptible", "uninterruptible" }; diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index f351375..fab408b 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -857,13 +857,13 @@ enum delay_type DELAY_ASCENDING_STAIRS, DELAY_DESCENDING_STAIRS, DELAY_RECITE, // Zin's Recite invocation + DELAY_ROCK_SWIMMING, //Nomes entering/leaving rock // [dshaligram] Shift-running, resting, travel and macros are now // also handled as delays. DELAY_RUN, DELAY_REST, DELAY_TRAVEL, - DELAY_MACRO, // In a macro delay, a stacked delay to tell Crawl to read and act on @@ -2975,6 +2975,7 @@ enum species_type SP_VAMPIRE, SP_DEEP_DWARF, SP_CAT, + SP_NOME, SP_ELF, // (placeholder) SP_HILL_DWARF, // (placeholder) SP_OGRE_MAGE, // (placeholder) diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc index f994c2e..6a0e5a9 100644 --- a/crawl-ref/source/misc.cc +++ b/crawl-ref/source/misc.cc @@ -1322,6 +1322,51 @@ void search_around(bool only_adjacent) } } + +void nome_start_rock_swimming() +{ + //redraw HP/AC regardless of rocky status, as these + //change if you swim from rock to stone + you.redraw_hit_points = true; + you.redraw_armour_class=true; + + if (you.rocky) + return; + + you.rocky=true; + + if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE + && you.attribute[ATTR_TRANSFORMATION] != TRAN_STATUE) + { + mpr("You quickly transform back into your natural form."); + untransform(false, true); // We're already entering the water. + } + + calc_hp(); + you.hp = you.hp * 13/10; + deflate_hp(you.hp_max,false); +} + +void nome_stop_rock_swimming() +{ + + you.rocky=false; + + if (you.hp != you.hp_max) + { + you.hp = you.hp * 10 / 13; + if (you.hp < 1) + you.hp = 1; + else if (you.hp > you.hp_max) + you.hp = you.hp_max; + } + calc_hp(); + + + you.redraw_hit_points = true; + you.redraw_armour_class=true; +} + void merfolk_start_swimming(bool stepped) { if (you.fishtail) diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h index 835b05c..83a05ca 100644 --- a/crawl-ref/source/misc.h +++ b/crawl-ref/source/misc.h @@ -17,6 +17,9 @@ struct activity_interrupt_data; bool go_berserk(bool intentional, bool potion = false); void search_around(bool only_adjacent = false); +void nome_start_rock_swimming(); +void nome_stop_rock_swimming(); + void merfolk_start_swimming(bool step = false); void merfolk_stop_swimming(); void trackers_init_new_level(bool transit); diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index 263bc35..9559ae1 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -70,6 +70,7 @@ static void _species_stat_init(species_type which_species) case SP_MERFOLK: sb = 6; ib = 5; db = 7; break; // 18 case SP_KENKU: sb = 6; ib = 6; db = 7; break; // 19 + case SP_NOME: sb = 7; ib = 6; db = 5; break; // 18 case SP_KOBOLD: sb = 5; ib = 4; db = 8; break; // 17 case SP_HALFLING: sb = 3; ib = 6; db = 9; break; // 18 case SP_SPRIGGAN: sb = 2; ib = 7; db = 9; break; // 18 diff --git a/crawl-ref/source/player-act.cc b/crawl-ref/source/player-act.cc index 4e0c3a6..5fb8aa5 100644 --- a/crawl-ref/source/player-act.cc +++ b/crawl-ref/source/player-act.cc @@ -128,7 +128,26 @@ int player::get_experience_level() const bool player::can_pass_through_feat(dungeon_feature_type grid) const { - return !feat_is_solid(grid) && grid != DNGN_TEMP_PORTAL; + if (!feat_is_solid(grid) && grid != DNGN_TEMP_PORTAL) + return true; + + if (can_swim_through_rock()) { + switch (grid) + { + case DNGN_METAL_WALL: + case DNGN_GREEN_CRYSTAL_WALL: + case DNGN_ROCK_WALL: + case DNGN_STONE_WALL: + case DNGN_PERMAROCK_WALL: + case DNGN_CLEAR_ROCK_WALL: + case DNGN_CLEAR_STONE_WALL: + case DNGN_CLEAR_PERMAROCK_WALL: + return true; + default: + return false; + } + } + } bool player::is_habitable_feat(dungeon_feature_type actual_grid) const diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index d984372..d516a5a 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -149,6 +149,20 @@ static bool _check_moveto_cloud(const coord_def& p, return (true); } +static bool _feat_is_there(dungeon_feature_type feat) { + return true; +} + +static bool _check_moveto_breathable(const coord_def& p, const std::string &move_verb) +{ + //see if square or one of surroundings is non-wall. Used for Nomes. + const dungeon_feature_type new_grid = env.grid(p); + + return !feat_is_solid(new_grid) + || (count_neighbours_with_func(p, &feat_is_solid) < + count_neighbours_with_func(p, &_feat_is_there )) ; +} + static bool _check_moveto_trap(const coord_def& p, const std::string &move_verb) { // If we're walking along, give a chance to avoid traps. @@ -245,6 +259,7 @@ static bool _check_moveto_trap(const coord_def& p, const std::string &move_verb) static bool _check_moveto_dangerous(const coord_def& p, const std::string move_verb) { + if (you.can_swim() && feat_is_water(env.grid(p)) || !is_feat_dangerous(env.grid(p))) { @@ -267,9 +282,20 @@ static bool _check_moveto_terrain(const coord_def& p, return (_check_moveto_dangerous(p, move_verb)); } +static bool _check_moveto_rock(const coord_def& p, + const std::string &move_verb) +{ + if (!feat_is_solid(env.grid(p))) + return true; + if (you.can_swim_through_rock() && feat_is_solid(env.grid(p)) && _check_moveto_breathable(p , move_verb)) + return (true); + return false; +} + bool check_moveto(const coord_def& p, const std::string &move_verb) { - return (_check_moveto_terrain(p, move_verb) + return (_check_moveto_rock(p,move_verb) + && _check_moveto_terrain(p, move_verb) && _check_moveto_cloud(p, move_verb) && _check_moveto_trap(p, move_verb)); } @@ -291,6 +317,27 @@ void moveto_location_effects(dungeon_feature_type old_feat, return; } + //Nome effects for entering/leaving rock + if (you.can_swim_through_rock()) { + //air -> rock + if (feat_is_solid(new_grid) && !feat_is_solid(old_feat)) { + mpr("You slowly crumble into the wall."); + start_delay(DELAY_ROCK_SWIMMING,1); + nome_start_rock_swimming(); + } + //rock -> air + if (feat_is_solid(old_feat) && !feat_is_solid(new_grid)) { + mpr("Your skin softens as you crumble out of the wall."); + start_delay(DELAY_ROCK_SWIMMING,1); + nome_stop_rock_swimming(); + } + //rock -> different rock + if (feat_is_solid(old_feat) && feat_is_solid(new_grid) && (old_feat != new_grid)) { + mpr("Your body changes slightly with the surrounding material."); + nome_start_rock_swimming(); + } + } + if (!you.airborne()) { if (you.species == SP_MERFOLK) @@ -3076,7 +3123,22 @@ void level_change(bool skip_attribute_increase) if (you.experience_level % 3) mp_adjust++; break; + case SP_NOME: + if (you.experience_level < 17) + hp_adjust--; + + if (you.experience_level % 3) + hp_adjust--; + + mp_adjust++; + if (!(you.experience_level % 5)) + { + modify_stat((coinflip() ? STAT_STR + : STAT_INT), 1, false, + "level gain"); + } + break; case SP_SPRIGGAN: if (you.experience_level < 17) hp_adjust--; @@ -3331,6 +3393,7 @@ int check_stealth(void) else stealth += (you.skills[SK_STEALTH] * 18); break; + case SP_NOME: case SP_HALFLING: case SP_KOBOLD: case SP_SPRIGGAN: @@ -3387,6 +3450,10 @@ int check_stealth(void) stealth += scan_artefacts(ARTP_STEALTH); + //Nome stealth boost in rock + if (you.in_rock() && you.rocky) + stealth += 30; + if (you.airborne()) stealth += 10; else if (you.in_water()) @@ -3795,6 +3862,7 @@ static int _species_exp_mod(species_type species) case SP_KOBOLD: return 10; case SP_OGRE: + case SP_NOME: return 11; case SP_SLUDGE_ELF: case SP_NAGA: @@ -4300,6 +4368,10 @@ int get_real_hp(bool trans, bool rotted) hitp += (you.experience_level * you.skills[SK_FIGHTING]) / (you.species == SP_CAT ? 7 : 5); + //Nome wall-swimming HP bonus (does not stack with statue form) + if (trans && you.species == SP_NOME && you.rocky && (you.attribute[ATTR_TRANSFORMATION] != TRAN_STATUE)) + hitp = hitp * 13 / 10; + // Being berserk makes you resistant to damage. I don't know why. if (trans && you.berserk()) hitp = hitp * 3 / 2; @@ -5294,6 +5366,11 @@ bool player::is_levitating() const return (duration[DUR_LEVITATION]); } +bool player::in_rock() const +{ + return feat_is_solid(grd(pos())); +} + bool player::in_water() const { return (!airborne() && !beogh_water_walk() @@ -5308,6 +5385,11 @@ bool player::can_swim(bool permanently) const || (!permanently && transform_can_swim())); } +bool player::can_swim_through_rock() const +{ + return species == SP_NOME; +} + int player::visible_igrd(const coord_def &where) const { if (grd(where) == DNGN_LAVA @@ -5483,9 +5565,39 @@ int player_icemail_armour_class() * ICEMAIL_MAX / ICEMAIL_TIME)); } +int player::nome_ac_boost() const +{ + //bonuses do not stack with statue form + if ( you.attribute[ATTR_TRANSFORMATION] == TRAN_STATUE) + return 0; + + // get player's current terrain type + //grd(you. + dungeon_feature_type current_grid = env.grid(you.pos()); + switch (current_grid) + { + case DNGN_PERMAROCK_WALL: + case DNGN_ROCK_WALL: + case DNGN_CLEAR_ROCK_WALL: + case DNGN_CLEAR_PERMAROCK_WALL: + return (100 * you.experience_level/4) + 500; + case DNGN_STONE_WALL: + case DNGN_CLEAR_STONE_WALL: + return (100 * you.experience_level/4) + 700; + case DNGN_METAL_WALL: + case DNGN_GREEN_CRYSTAL_WALL: + return (100 * you.experience_level/4) + 900; + default: + return 0; + } +} + int player::armour_class() const { int AC = 0; + + if (you.species == SP_NOME ) + AC += nome_ac_boost(); for (int eq = EQ_MIN_ARMOUR; eq <= EQ_MAX_ARMOUR; ++eq) { diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index 76b3b96..3ab3120 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -96,6 +96,7 @@ public: bool royal_jelly_dead; bool transform_uncancellable; bool fishtail; // Merfolk fishtail transformation + bool rocky; //Nome wall transformation unsigned short pet_target; @@ -356,8 +357,10 @@ public: bool in_water() const; bool can_swim(bool permanently = false) const; + bool can_swim_through_rock() const; int visible_igrd(const coord_def&) const; bool is_levitating() const; + bool in_rock() const; bool cannot_speak() const; bool invisible() const; bool misled() const; @@ -570,6 +573,7 @@ public: bool can_throw_large_rocks() const; bool can_smell() const; + int nome_ac_boost() const; int armour_class() const; int gdr_perc() const; int melee_evasion(const actor *attacker, diff --git a/crawl-ref/source/skills2.cc b/crawl-ref/source/skills2.cc index cd1743c..362c20d 100644 --- a/crawl-ref/source/skills2.cc +++ b/crawl-ref/source/skills2.cc @@ -1282,6 +1282,43 @@ static const species_skill_aptitude species_skill_aptitudes[] = APT(SP_CAT, SK_POISON_MAGIC, -1), APT(SP_CAT, SK_INVOCATIONS, -1), APT(SP_CAT, SK_EVOCATIONS, -2), + + + // SP_NOME + APT(SP_NOME, SK_FIGHTING, 1), + APT(SP_NOME, SK_SHORT_BLADES, 1), + APT(SP_NOME, SK_LONG_BLADES, -1), + APT(SP_NOME, SK_AXES, 0), + APT(SP_NOME, SK_MACES_FLAILS, 0), + APT(SP_NOME, SK_POLEARMS, -3), + APT(SP_NOME, SK_STAVES, 0), + APT(SP_NOME, SK_SLINGS, 1), + APT(SP_NOME, SK_BOWS, -1), + APT(SP_NOME, SK_CROSSBOWS, -1), + APT(SP_NOME, SK_THROWING, 1), + APT(SP_NOME, SK_ARMOUR, 1), + APT(SP_NOME, SK_DODGING, -1), + APT(SP_NOME, SK_STEALTH, 1), + APT(SP_NOME, SK_STABBING, 1), + APT(SP_NOME, SK_SHIELDS, 0), + APT(SP_NOME, SK_TRAPS_DOORS, 0), + APT(SP_NOME, SK_UNARMED_COMBAT, 1), + APT(SP_NOME, SK_SPELLCASTING, 0), + APT(SP_NOME, SK_CONJURATIONS, 0), + APT(SP_NOME, SK_ENCHANTMENTS, -2), + APT(SP_NOME, SK_SUMMONINGS, 0), + APT(SP_NOME, SK_NECROMANCY, 0), + APT(SP_NOME, SK_TRANSLOCATIONS, -2), + APT(SP_NOME, SK_TRANSMUTATIONS, 4), + APT(SP_NOME, SK_FIRE_MAGIC, 1), + APT(SP_NOME, SK_ICE_MAGIC, -1), + APT(SP_NOME, SK_AIR_MAGIC, -3), + APT(SP_NOME, SK_EARTH_MAGIC, 5), + APT(SP_NOME, SK_POISON_MAGIC, -1), + APT(SP_NOME, SK_INVOCATIONS, 0), + APT(SP_NOME, SK_EVOCATIONS, 0), + + }; // Traditionally, Spellcasting and In/Evocations formed the exceptions here: @@ -1643,6 +1680,7 @@ static std::string _stk_weight() case SP_KENKU: return "Light"; + case SP_NOME: case SP_HALFLING: case SP_KOBOLD: return "Feather"; diff --git a/crawl-ref/source/species.cc b/crawl-ref/source/species.cc index 526e994..bb8e68d 100644 --- a/crawl-ref/source/species.cc +++ b/crawl-ref/source/species.cc @@ -25,7 +25,7 @@ static species_type species_order[] = { SP_HILL_ORC, SP_MERFOLK, // small species SP_HALFLING, SP_KOBOLD, - SP_SPRIGGAN, + SP_SPRIGGAN, SP_NOME, // significantly different body type from human SP_NAGA, SP_CENTAUR, SP_OGRE, SP_TROLL, @@ -60,7 +60,7 @@ static const char * Species_Abbrev_List[NUM_SPECIES] = // the draconians "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Ce", "DG", "Sp", "Mi", "DS", "Gh", "Ke", "Mf", "Vp", "DD", - "Fe", + "Fe", "No", // placeholders "El", "HD", "OM", "GE", "Gn" }; @@ -247,6 +247,7 @@ std::string species_name(species_type speci, bool genus, bool adj) case SP_MERFOLK: res = (adj ? "Merfolkian" : "Merfolk"); break; case SP_VAMPIRE: res = (adj ? "Vampiric" : "Vampire"); break; case SP_CAT: res = (adj ? "Feline" : "Felid"); break; + case SP_NOME: res = (adj ? "Nomish" : "Nome" ); break; default: res = (adj ? "Yakish" : "Yak"); break; } } @@ -319,6 +320,7 @@ size_type species_size(species_type species, size_part_type psize) return ((psize == PSIZE_TORSO) ? SIZE_MEDIUM : SIZE_LARGE); case SP_HALFLING: case SP_KOBOLD: + case SP_NOME: return (SIZE_SMALL); case SP_SPRIGGAN: return (SIZE_LITTLE); @@ -341,6 +343,7 @@ monster_type player_species_to_mons_species(species_type species) case SP_SLUDGE_ELF: return (MONS_ELF); case SP_MOUNTAIN_DWARF: + case SP_NOME: //PLACEHOLDER until Nome monster implemented return (MONS_DWARF); case SP_HALFLING: return (MONS_HALFLING); diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index e65ba85..dce5730 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -1029,6 +1029,7 @@ static void tag_construct_you(writer &th) marshallShort(th, you.hunger); marshallBoolean(th, you.fishtail); + marshallBoolean(th, you.rocky); // how many you.equip? marshallByte(th, NUM_EQUIP); @@ -1609,6 +1610,7 @@ static void tag_read_you(reader &th, int minorVersion) if (minorVersion >= TAG_MINOR_FISHTAIL) #endif you.fishtail = unmarshallBoolean(th); + you.rocky = unmarshallBoolean(th); // How many you.equip? count = unmarshallByte(th); -- 1.6.3.3 0001-nome-patch.-Same-great-taste-less-overpowered.patch [^] (27,836 bytes) 2010-10-24 02:46 [Show Content] [Hide Content] From 2573f89de462770b8f51298d0329be16d7ac74d5 Mon Sep 17 00:00:00 2001 From: Matthew M Ince <matthew@Y.(none)> Date: Sat, 23 Oct 2010 20:42:50 -0400 Subject: nome patch. Same great taste, less overpowered. --- crawl-ref/docs/crawl_manual.txt | 27 +++++ crawl-ref/source/dat/descript/species.txt | 4 + crawl-ref/source/delay.cc | 7 +- crawl-ref/source/effects.cc | 6 + crawl-ref/source/enum.h | 3 +- crawl-ref/source/fight.cc | 5 + crawl-ref/source/misc.cc | 51 +++++++++ crawl-ref/source/misc.h | 3 + crawl-ref/source/ng-setup.cc | 1 + crawl-ref/source/output.cc | 1 + crawl-ref/source/player-act.cc | 19 +++- crawl-ref/source/player.cc | 166 ++++++++++++++++++++++++++++- crawl-ref/source/player.h | 10 ++ crawl-ref/source/skills2.cc | 38 +++++++ crawl-ref/source/species.cc | 7 +- crawl-ref/source/status.cc | 23 ++++ crawl-ref/source/status.h | 1 + crawl-ref/source/tags.cc | 2 + 18 files changed, 367 insertions(+), 7 deletions(-) diff --git a/crawl-ref/docs/crawl_manual.txt b/crawl-ref/docs/crawl_manual.txt index 1c724af..5139ee4 100644 --- a/crawl-ref/docs/crawl_manual.txt +++ b/crawl-ref/docs/crawl_manual.txt @@ -1566,6 +1566,33 @@ Deep Dwarves Dwarves can tinker with gadgets so as to recharge them. However, each time they do so, they lose a bit of their magical essence. +Nomes +--------- + +The stooped, gravel-skinned Nomes are true children of the earth: +stubborn and strong as the stones, and insular as diamonds trapped in the rocky +depths. Few Nomes ever glimpse the light of day, preferring instead to swim +through the walls of their native caverns in search of ever-prettier gems. +For Nomes can indeed swim through solid rock, stone or even metal. + + +To swim through a wall, a Nome first becomes attuned to the earth, a +slow process that leaves Nomes entering a wall vulnerable for a short +time but greatly increases their resilience. Higher attunement allows +passage into harder walls, grants a Nome increasingly tough skin , and +slows the Nome's actions proportionally - rock barely slows a Nome, +but a swim through metal is tantamount to a swim through +molasses. Although attunement gradually decreases when the Nome moves +in open air, the Nome remains in this slowed but more resilient state +for some time. + +The Nomes' earthy nature is their greatest strength and greatest +weakness. Nomes are the masters of earth magic, and excel at bashing +enemies with mace or stony fists alike. On the other hand, they are by +nature inflexible in mind, learning at a slow pace and having little +patience for magics foreign to their caverns, and equally inflexible +in body, relying mostly on their diminutive stature to avoid blows. + Hill Orcs --------- Hill Orcs are Orcs from the upper world who, jealous of the riches which diff --git a/crawl-ref/source/dat/descript/species.txt b/crawl-ref/source/dat/descript/species.txt index 6603a67..0bdf957 100644 --- a/crawl-ref/source/dat/descript/species.txt +++ b/crawl-ref/source/dat/descript/species.txt @@ -75,6 +75,10 @@ Naga A hybrid; human from the chest up, with a scaly, muscular torso trailing off like that of a snake. %%%% +Nome + +A gravel-skinned humanoid able to swim through solid rock. +%%%% Ogre Large and strong, they're mostly seen as brutes. Casting ogres have been spotted, however. diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index 0f73102..291e53c 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -996,7 +996,10 @@ static void _finish_delay(const delay_queue_item &delay) mprf(MSGCH_PLAIN, "You finish %s.", _get_zin_recite_speech("other", you.num_turns + delay.duration).c_str()); break; - + + case DELAY_ROCK_SWIMMING: + //no "finish" message to avoid spam. + break; case DELAY_PASSWALL: { mpr("You finish merging with the rock."); @@ -1678,7 +1681,7 @@ static const char *delay_names[] = "not_delayed", "eat", "vampire_feed", "armour_on", "armour_off", "jewellery_on", "memorise", "butcher", "bottle_blood", "weapon_swap", "passwall", "drop_item", "multidrop", "ascending_stairs", - "descending_stairs", "recite", "run", "rest", "travel", "macro", + "descending_stairs", "recite","swim_through_rock" ,"run", "rest", "travel", "macro", "macro_process_key", "interruptible", "uninterruptible" }; diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc index 3bdd8ca..ad56584 100644 --- a/crawl-ref/source/effects.cc +++ b/crawl-ref/source/effects.cc @@ -2222,6 +2222,12 @@ void handle_time() lose_stat(STAT_RANDOM, 1, false, "deterioration mutation"); } + // earth attunement + // decrease earth attunement outside of walls. + if (you.rocky() && ! you.in_rock()) { + change_earth_attunement(-1); + } + int added_contamination = 0; // Account for mutagenic radiation. Invis and haste will give the diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index f351375..fab408b 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -857,13 +857,13 @@ enum delay_type DELAY_ASCENDING_STAIRS, DELAY_DESCENDING_STAIRS, DELAY_RECITE, // Zin's Recite invocation + DELAY_ROCK_SWIMMING, //Nomes entering/leaving rock // [dshaligram] Shift-running, resting, travel and macros are now // also handled as delays. DELAY_RUN, DELAY_REST, DELAY_TRAVEL, - DELAY_MACRO, // In a macro delay, a stacked delay to tell Crawl to read and act on @@ -2975,6 +2975,7 @@ enum species_type SP_VAMPIRE, SP_DEEP_DWARF, SP_CAT, + SP_NOME, SP_ELF, // (placeholder) SP_HILL_DWARF, // (placeholder) SP_OGRE_MAGE, // (placeholder) diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index 0c98bf0..373a79c 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -4216,6 +4216,11 @@ int melee_attack::player_calc_base_unarmed_damage() damage = 0; } + //unarmed bonus for earth-attuned Nomes in base form + if (you.rocky() && you.attribute[ATTR_TRANSFORMATION] == TRAN_NONE) { + damage += 2 + you.earth_attunement; + } + if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE) { switch (you.attribute[ATTR_TRANSFORMATION]) diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc index f994c2e..0ef1b44 100644 --- a/crawl-ref/source/misc.cc +++ b/crawl-ref/source/misc.cc @@ -1322,6 +1322,57 @@ void search_around(bool only_adjacent) } } +static int required_earth_attunement(dungeon_feature_type wall) { + switch (wall) + { + case DNGN_ROCK_WALL: + case DNGN_CLEAR_ROCK_WALL: + return 1; + case DNGN_GREEN_CRYSTAL_WALL: + return 2; + case DNGN_STONE_WALL: + case DNGN_CLEAR_STONE_WALL: + return 3; + case DNGN_METAL_WALL: + return 4; + default: + return -1; + } +} + +void nome_start_rock_swimming() +{ + //redraw HP/AC regardless of rocky status, as these + //change if you swim from rock to stone + you.redraw_hit_points = true; + you.redraw_armour_class=true; + + dungeon_feature_type current_grid = env.grid(you.pos()); + + //increment earth attunement to proper level + //before rock swimming + int needed_earth_attunement = required_earth_attunement(current_grid) - you.earth_attunement ; + if ( needed_earth_attunement > 0 ) + { + change_earth_attunement(needed_earth_attunement); + start_delay(DELAY_ROCK_SWIMMING, needed_earth_attunement); + } + + if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE + && you.attribute[ATTR_TRANSFORMATION] != TRAN_STATUE) + { + mpr("You quickly transform back into your natural form."); + untransform(false, true); // We're already entering the water. + } +} + +void nome_stop_rock_swimming() +{ + + you.redraw_hit_points = true; + you.redraw_armour_class=true; +} + void merfolk_start_swimming(bool stepped) { if (you.fishtail) diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h index 835b05c..83a05ca 100644 --- a/crawl-ref/source/misc.h +++ b/crawl-ref/source/misc.h @@ -17,6 +17,9 @@ struct activity_interrupt_data; bool go_berserk(bool intentional, bool potion = false); void search_around(bool only_adjacent = false); +void nome_start_rock_swimming(); +void nome_stop_rock_swimming(); + void merfolk_start_swimming(bool step = false); void merfolk_stop_swimming(); void trackers_init_new_level(bool transit); diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index 263bc35..9559ae1 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -70,6 +70,7 @@ static void _species_stat_init(species_type which_species) case SP_MERFOLK: sb = 6; ib = 5; db = 7; break; // 18 case SP_KENKU: sb = 6; ib = 6; db = 7; break; // 19 + case SP_NOME: sb = 7; ib = 6; db = 5; break; // 18 case SP_KOBOLD: sb = 5; ib = 4; db = 8; break; // 17 case SP_HALFLING: sb = 3; ib = 6; db = 9; break; // 18 case SP_SPRIGGAN: sb = 2; ib = 7; db = 9; break; // 18 diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index b4948ff..03a57f3 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -506,6 +506,7 @@ static void _get_status_lights(std::vector<status_light>& out) STATUS_SPEED, DUR_DEATH_CHANNEL, DUR_TELEPATHY, DUR_STEALTH, DUR_BREATH_WEAPON, DUR_EXHAUSTED, DUR_POWERED_BY_DEATH, DUR_TRANSFORMATION, DUR_AFRAID, DUR_MIRROR_DAMAGE, DUR_SCRYING, + STATUS_EARTH_ATTUNED, }; status_info inf; diff --git a/crawl-ref/source/player-act.cc b/crawl-ref/source/player-act.cc index 4e0c3a6..a3de4ee 100644 --- a/crawl-ref/source/player-act.cc +++ b/crawl-ref/source/player-act.cc @@ -128,7 +128,24 @@ int player::get_experience_level() const bool player::can_pass_through_feat(dungeon_feature_type grid) const { - return !feat_is_solid(grid) && grid != DNGN_TEMP_PORTAL; + if (!feat_is_solid(grid) && grid != DNGN_TEMP_PORTAL) + return true; + + if (can_swim_through_rock()) { + switch (grid) + { + case DNGN_METAL_WALL: + case DNGN_GREEN_CRYSTAL_WALL: + case DNGN_ROCK_WALL: + case DNGN_STONE_WALL: + case DNGN_CLEAR_ROCK_WALL: + case DNGN_CLEAR_STONE_WALL: + return true; + default: + return false; + } + } + return false; } bool player::is_habitable_feat(dungeon_feature_type actual_grid) const diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index d984372..ce85b08 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -149,6 +149,20 @@ static bool _check_moveto_cloud(const coord_def& p, return (true); } +static bool _feat_is_there(dungeon_feature_type feat) { + return true; +} + +static bool _check_moveto_breathable(const coord_def& p, const std::string &move_verb) +{ + //see if square or one of surroundings is non-wall. Used for Nomes. + const dungeon_feature_type new_grid = env.grid(p); + + return !feat_is_solid(new_grid) + || (count_neighbours_with_func(p, &feat_is_solid) < + count_neighbours_with_func(p, &_feat_is_there )) ; +} + static bool _check_moveto_trap(const coord_def& p, const std::string &move_verb) { // If we're walking along, give a chance to avoid traps. @@ -245,6 +259,7 @@ static bool _check_moveto_trap(const coord_def& p, const std::string &move_verb) static bool _check_moveto_dangerous(const coord_def& p, const std::string move_verb) { + if (you.can_swim() && feat_is_water(env.grid(p)) || !is_feat_dangerous(env.grid(p))) { @@ -267,9 +282,20 @@ static bool _check_moveto_terrain(const coord_def& p, return (_check_moveto_dangerous(p, move_verb)); } +static bool _check_moveto_rock(const coord_def& p, + const std::string &move_verb) +{ + if (!feat_is_solid(env.grid(p))) + return true; + if (you.can_swim_through_rock() && feat_is_solid(env.grid(p)) && _check_moveto_breathable(p , move_verb)) + return (true); + return false; +} + bool check_moveto(const coord_def& p, const std::string &move_verb) { - return (_check_moveto_terrain(p, move_verb) + return (_check_moveto_rock(p,move_verb) + && _check_moveto_terrain(p, move_verb) && _check_moveto_cloud(p, move_verb) && _check_moveto_trap(p, move_verb)); } @@ -291,6 +317,27 @@ void moveto_location_effects(dungeon_feature_type old_feat, return; } + //Nome effects for entering/leaving rock + if (you.can_swim_through_rock()) { + //air -> rock + if (feat_is_solid(new_grid) && !feat_is_solid(old_feat)) { + mpr("You slowly crumble into the wall."); + //start_delay(DELAY_ROCK_SWIMMING,1); + nome_start_rock_swimming(); + } + //rock -> air + if (feat_is_solid(old_feat) && !feat_is_solid(new_grid)) { + mpr("Your skin softens as you crumble out of the wall."); + //start_delay(DELAY_ROCK_SWIMMING,1); + nome_stop_rock_swimming(); + } + //rock -> different rock + if (feat_is_solid(old_feat) && feat_is_solid(new_grid) && (old_feat != new_grid)) { + //mpr("Your body changes slightly with the surrounding material."); + nome_start_rock_swimming(); + } + } + if (!you.airborne()) { if (you.species == SP_MERFOLK) @@ -1993,6 +2040,16 @@ int player_speed(void) break; } + if (you.earth_attunement > 0) { + int earth = you.earth_attunement; + ps *= (earth == 4) ? 15 : + (earth == 3) ? 14 : + (earth == 2) ? 13 : + (earth == 1) ? 12 : + 20; + ps /= 10; + } + return ps; } @@ -3076,7 +3133,22 @@ void level_change(bool skip_attribute_increase) if (you.experience_level % 3) mp_adjust++; break; + case SP_NOME: + if (you.experience_level < 17) + hp_adjust--; + + if (you.experience_level % 3) + hp_adjust--; + + mp_adjust++; + if (!(you.experience_level % 5)) + { + modify_stat((coinflip() ? STAT_STR + : STAT_INT), 1, false, + "level gain"); + } + break; case SP_SPRIGGAN: if (you.experience_level < 17) hp_adjust--; @@ -3331,6 +3403,7 @@ int check_stealth(void) else stealth += (you.skills[SK_STEALTH] * 18); break; + case SP_NOME: case SP_HALFLING: case SP_KOBOLD: case SP_SPRIGGAN: @@ -3387,6 +3460,10 @@ int check_stealth(void) stealth += scan_artefacts(ARTP_STEALTH); + //Nome stealth boost in rock + if (you.in_rock() && you.rocky()) + stealth += 30; + if (you.airborne()) stealth += 10; else if (you.in_water()) @@ -3693,6 +3770,7 @@ void display_char_status() STATUS_AIRBORNE, STATUS_NET, DUR_POISONING, STATUS_SICK, STATUS_ROT, STATUS_GLOW, DUR_CONFUSING_TOUCH, DUR_SURE_BLADE, DUR_AFRAID, DUR_MIRROR_DAMAGE, DUR_SCRYING, + STATUS_EARTH_ATTUNED, }; status_info inf; @@ -3804,6 +3882,7 @@ static int _species_exp_mod(species_type species) case SP_SPRIGGAN: case SP_KENKU: return 13; + case SP_NOME: case SP_DEEP_ELF: case SP_CENTAUR: case SP_MINOTAUR: @@ -4300,6 +4379,10 @@ int get_real_hp(bool trans, bool rotted) hitp += (you.experience_level * you.skills[SK_FIGHTING]) / (you.species == SP_CAT ? 7 : 5); + //Nome wall-swimming HP bonus + if (trans && you.species == SP_NOME && you.rocky() ) + hitp = hitp * 13 / 10; + // Being berserk makes you resistant to damage. I don't know why. if (trans && you.berserk()) hitp = hitp * 3 / 2; @@ -4397,6 +4480,17 @@ int get_contamination_level() return (0); } +std::string describe_earth_attunement(int earth_attunement) +{ + if (earth_attunement <= 0) + return ""; + return make_stringf("You are %s attuned to the earth.", + (earth_attunement == 4) ? "intimately" : + (earth_attunement == 3) ? "deeply" : + (earth_attunement == 2) ? "moderately" : + (earth_attunement == 1) ? "slightly" : "buggily"); +} + std::string describe_contamination(int cont) { if (cont > 5) @@ -4477,6 +4571,41 @@ void contaminate_player(int change, bool controlled, bool msg) } } +void change_earth_attunement(int change, bool msg ) +{ + you.redraw_armour_class = true; + you.redraw_hit_points = true; + + int old_ea = you.earth_attunement; + you.earth_attunement += change; + if (msg) { + if (you.earth_attunement <= 0 && old_ea > 0) { + mpr("You are no longer attuned to the earth."); + } + } + + //handle HP gain/loss + if (you.earth_attunement > 0 && old_ea <= 0) { + calc_hp(); + you.hp = you.hp * 13/10; + deflate_hp(you.hp_max,false); + } + + if (you.earth_attunement <= 0 && old_ea > 0) { + if (you.hp != you.hp_max) + { + you.hp = you.hp * 10 / 13; + if (you.hp < 1) + you.hp = 1; + else if (you.hp > you.hp_max) + you.hp = you.hp_max; + } + calc_hp(); + } + +} + + bool confuse_player(int amount, bool resistable) { ASSERT(!crawl_state.game_is_arena()); @@ -5294,6 +5423,16 @@ bool player::is_levitating() const return (duration[DUR_LEVITATION]); } +bool player::in_rock() const +{ + return feat_is_solid(grd(pos())); +} + +bool player::rocky() const +{ + return (earth_attunement > 0); +} + bool player::in_water() const { return (!airborne() && !beogh_water_walk() @@ -5308,6 +5447,11 @@ bool player::can_swim(bool permanently) const || (!permanently && transform_can_swim())); } +bool player::can_swim_through_rock() const +{ + return species == SP_NOME; +} + int player::visible_igrd(const coord_def &where) const { if (grd(where) == DNGN_LAVA @@ -5483,9 +5627,29 @@ int player_icemail_armour_class() * ICEMAIL_MAX / ICEMAIL_TIME)); } +int player::nome_ac_boost() const +{ + int earth = you.earth_attunement; + if (earth > 0) { + return 100* ( you.experience_level/4 + + (earth == 4) ? 8 : + (earth == 3) ? 7 : + (earth == 2) ? 6 : + (earth == 1) ? 5 : 9 ); + } + + return 0; +// //bonuses do not stack with statue form +// if ( you.attribute[ATTR_TRANSFORMATION] == TRAN_STATUE) +// return 0; +} + int player::armour_class() const { int AC = 0; + + if (you.species == SP_NOME ) + AC += nome_ac_boost(); for (int eq = EQ_MIN_ARMOUR; eq <= EQ_MAX_ARMOUR; ++eq) { diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index 76b3b96..6f46e97 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -96,6 +96,7 @@ public: bool royal_jelly_dead; bool transform_uncancellable; bool fishtail; // Merfolk fishtail transformation + // bool rocky; //Nome wall transformation unsigned short pet_target; @@ -193,6 +194,7 @@ public: std::vector<demon_trait> demonic_traits; + int earth_attunement; // nomes only int magic_contamination; FixedVector<bool, NUM_FIXED_BOOKS> had_book; @@ -356,8 +358,13 @@ public: bool in_water() const; bool can_swim(bool permanently = false) const; + bool can_swim_through_rock() const; int visible_igrd(const coord_def&) const; bool is_levitating() const; + bool in_rock() const; + //at least one level of earth attunement (nomes) + bool rocky() const; + bool cannot_speak() const; bool invisible() const; bool misled() const; @@ -570,6 +577,7 @@ public: bool can_throw_large_rocks() const; bool can_smell() const; + int nome_ac_boost() const; int armour_class() const; int gdr_perc() const; int melee_evasion(const actor *attacker, @@ -850,6 +858,8 @@ void set_mp(int new_amount, bool max_too); void contaminate_player(int change, bool controlled = false, bool msg = true); +void change_earth_attunement(int change, bool msg = true); +std::string describe_earth_attunement( int earth_attunement) ; bool confuse_player(int amount, bool resistable = true); diff --git a/crawl-ref/source/skills2.cc b/crawl-ref/source/skills2.cc index cd1743c..c110d97 100644 --- a/crawl-ref/source/skills2.cc +++ b/crawl-ref/source/skills2.cc @@ -1282,6 +1282,43 @@ static const species_skill_aptitude species_skill_aptitudes[] = APT(SP_CAT, SK_POISON_MAGIC, -1), APT(SP_CAT, SK_INVOCATIONS, -1), APT(SP_CAT, SK_EVOCATIONS, -2), + + + // SP_NOME + APT(SP_NOME, SK_FIGHTING, 0), + APT(SP_NOME, SK_SHORT_BLADES, 0), + APT(SP_NOME, SK_LONG_BLADES, -2), + APT(SP_NOME, SK_AXES, 0), + APT(SP_NOME, SK_MACES_FLAILS, 1), + APT(SP_NOME, SK_POLEARMS, -3), + APT(SP_NOME, SK_STAVES, 0), + APT(SP_NOME, SK_SLINGS, 1), + APT(SP_NOME, SK_BOWS, -1), + APT(SP_NOME, SK_CROSSBOWS, -1), + APT(SP_NOME, SK_THROWING, 1), + APT(SP_NOME, SK_ARMOUR, 1), + APT(SP_NOME, SK_DODGING, -1), + APT(SP_NOME, SK_STEALTH, 1), + APT(SP_NOME, SK_STABBING, 1), + APT(SP_NOME, SK_SHIELDS, 0), + APT(SP_NOME, SK_TRAPS_DOORS, 0), + APT(SP_NOME, SK_UNARMED_COMBAT, 0), + APT(SP_NOME, SK_SPELLCASTING, 0), + APT(SP_NOME, SK_CONJURATIONS, 0), + APT(SP_NOME, SK_ENCHANTMENTS, -2), + APT(SP_NOME, SK_SUMMONINGS, 0), + APT(SP_NOME, SK_NECROMANCY, 0), + APT(SP_NOME, SK_TRANSLOCATIONS, -2), + APT(SP_NOME, SK_TRANSMUTATIONS, 1), + APT(SP_NOME, SK_FIRE_MAGIC, 1), + APT(SP_NOME, SK_ICE_MAGIC, -1), + APT(SP_NOME, SK_AIR_MAGIC, -4), + APT(SP_NOME, SK_EARTH_MAGIC, 5), + APT(SP_NOME, SK_POISON_MAGIC, -1), + APT(SP_NOME, SK_INVOCATIONS, -1), + APT(SP_NOME, SK_EVOCATIONS, -1), + + }; // Traditionally, Spellcasting and In/Evocations formed the exceptions here: @@ -1643,6 +1680,7 @@ static std::string _stk_weight() case SP_KENKU: return "Light"; + case SP_NOME: case SP_HALFLING: case SP_KOBOLD: return "Feather"; diff --git a/crawl-ref/source/species.cc b/crawl-ref/source/species.cc index 526e994..bb8e68d 100644 --- a/crawl-ref/source/species.cc +++ b/crawl-ref/source/species.cc @@ -25,7 +25,7 @@ static species_type species_order[] = { SP_HILL_ORC, SP_MERFOLK, // small species SP_HALFLING, SP_KOBOLD, - SP_SPRIGGAN, + SP_SPRIGGAN, SP_NOME, // significantly different body type from human SP_NAGA, SP_CENTAUR, SP_OGRE, SP_TROLL, @@ -60,7 +60,7 @@ static const char * Species_Abbrev_List[NUM_SPECIES] = // the draconians "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Ce", "DG", "Sp", "Mi", "DS", "Gh", "Ke", "Mf", "Vp", "DD", - "Fe", + "Fe", "No", // placeholders "El", "HD", "OM", "GE", "Gn" }; @@ -247,6 +247,7 @@ std::string species_name(species_type speci, bool genus, bool adj) case SP_MERFOLK: res = (adj ? "Merfolkian" : "Merfolk"); break; case SP_VAMPIRE: res = (adj ? "Vampiric" : "Vampire"); break; case SP_CAT: res = (adj ? "Feline" : "Felid"); break; + case SP_NOME: res = (adj ? "Nomish" : "Nome" ); break; default: res = (adj ? "Yakish" : "Yak"); break; } } @@ -319,6 +320,7 @@ size_type species_size(species_type species, size_part_type psize) return ((psize == PSIZE_TORSO) ? SIZE_MEDIUM : SIZE_LARGE); case SP_HALFLING: case SP_KOBOLD: + case SP_NOME: return (SIZE_SMALL); case SP_SPRIGGAN: return (SIZE_LITTLE); @@ -341,6 +343,7 @@ monster_type player_species_to_mons_species(species_type species) case SP_SLUDGE_ELF: return (MONS_ELF); case SP_MOUNTAIN_DWARF: + case SP_NOME: //PLACEHOLDER until Nome monster implemented return (MONS_DWARF); case SP_HALFLING: return (MONS_HALFLING); diff --git a/crawl-ref/source/status.cc b/crawl-ref/source/status.cc index 65749e4..7588c70 100644 --- a/crawl-ref/source/status.cc +++ b/crawl-ref/source/status.cc @@ -195,6 +195,7 @@ static void _mark_expiring(status_info* inf, bool expiring) static void _describe_airborne(status_info* inf); static void _describe_burden(status_info* inf); +static void _describe_earth_attunement(status_info* inf); static void _describe_glow(status_info* inf); static void _describe_hunger(status_info* inf); static void _describe_regen(status_info* inf); @@ -257,6 +258,9 @@ void fill_status_info(int status, status_info* inf) _describe_burden(inf); break; + case STATUS_EARTH_ATTUNED: + _describe_earth_attunement(inf); + break; case STATUS_GLOW: // includes corona _describe_glow(inf); @@ -440,6 +444,25 @@ static void _describe_hunger(status_info* inf) break; } } +static void _describe_earth_attunement(status_info* inf) +{ + int earth = you.earth_attunement; + if ( earth > 0) + { + + inf -> light_text = "earth"; + inf->light_colour = _bad_ench_colour(earth, 2, 3); + + inf->short_text = + (earth == 1) ? "slightly " : + (earth == 2) ? "moderately " : + (earth == 3) ? "deeply" : + (earth == 4) ? "intimately " : "ridiculously"; + inf->short_text += " earth-attuned"; + inf->long_text = describe_earth_attunement(earth); + } + +} static void _describe_glow(status_info* inf) { diff --git a/crawl-ref/source/status.h b/crawl-ref/source/status.h index d983794..734abab 100644 --- a/crawl-ref/source/status.h +++ b/crawl-ref/source/status.h @@ -11,6 +11,7 @@ enum status_type STATUS_AIRBORNE = NUM_DURATIONS + 1, STATUS_BEHELD, STATUS_BURDEN, + STATUS_EARTH_ATTUNED, STATUS_GLOW, STATUS_NET, STATUS_HUNGER, diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index e65ba85..3023fef 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -1029,6 +1029,7 @@ static void tag_construct_you(writer &th) marshallShort(th, you.hunger); marshallBoolean(th, you.fishtail); + marshallInt(th, you.earth_attunement); // how many you.equip? marshallByte(th, NUM_EQUIP); @@ -1609,6 +1610,7 @@ static void tag_read_you(reader &th, int minorVersion) if (minorVersion >= TAG_MINOR_FISHTAIL) #endif you.fishtail = unmarshallBoolean(th); + you.earth_attunement = unmarshallInt(th); // How many you.equip? count = unmarshallByte(th); -- 1.6.3.3 nomes.updated.patch [^] (27,803 bytes) 2010-10-24 05:31 [Show Content] [Hide Content] From a93fc7145fdec234adfd8149649413828f7bfe32 Mon Sep 17 00:00:00 2001 From: Matthew M Ince <matthew@Y.(none)> Date: Sat, 23 Oct 2010 23:27:12 -0400 Subject: Nome patch. --- crawl-ref/docs/crawl_manual.txt | 27 +++++ crawl-ref/source/dat/descript/species.txt | 4 + crawl-ref/source/delay.cc | 7 +- crawl-ref/source/effects.cc | 6 + crawl-ref/source/enum.h | 3 +- crawl-ref/source/fight.cc | 5 + crawl-ref/source/misc.cc | 51 +++++++++ crawl-ref/source/misc.h | 3 + crawl-ref/source/ng-setup.cc | 1 + crawl-ref/source/output.cc | 1 + crawl-ref/source/player-act.cc | 19 +++- crawl-ref/source/player.cc | 166 ++++++++++++++++++++++++++++- crawl-ref/source/player.h | 10 ++ crawl-ref/source/skills2.cc | 38 +++++++ crawl-ref/source/species.cc | 7 +- crawl-ref/source/status.cc | 23 ++++ crawl-ref/source/status.h | 1 + crawl-ref/source/tags.cc | 2 + 18 files changed, 367 insertions(+), 7 deletions(-) diff --git a/crawl-ref/docs/crawl_manual.txt b/crawl-ref/docs/crawl_manual.txt index 1c724af..5139ee4 100644 --- a/crawl-ref/docs/crawl_manual.txt +++ b/crawl-ref/docs/crawl_manual.txt @@ -1566,6 +1566,33 @@ Deep Dwarves Dwarves can tinker with gadgets so as to recharge them. However, each time they do so, they lose a bit of their magical essence. +Nomes +--------- + +The stooped, gravel-skinned Nomes are true children of the earth: +stubborn and strong as the stones, and insular as diamonds trapped in the rocky +depths. Few Nomes ever glimpse the light of day, preferring instead to swim +through the walls of their native caverns in search of ever-prettier gems. +For Nomes can indeed swim through solid rock, stone or even metal. + + +To swim through a wall, a Nome first becomes attuned to the earth, a +slow process that leaves Nomes entering a wall vulnerable for a short +time but greatly increases their resilience. Higher attunement allows +passage into harder walls, grants a Nome increasingly tough skin , and +slows the Nome's actions proportionally - rock barely slows a Nome, +but a swim through metal is tantamount to a swim through +molasses. Although attunement gradually decreases when the Nome moves +in open air, the Nome remains in this slowed but more resilient state +for some time. + +The Nomes' earthy nature is their greatest strength and greatest +weakness. Nomes are the masters of earth magic, and excel at bashing +enemies with mace or stony fists alike. On the other hand, they are by +nature inflexible in mind, learning at a slow pace and having little +patience for magics foreign to their caverns, and equally inflexible +in body, relying mostly on their diminutive stature to avoid blows. + Hill Orcs --------- Hill Orcs are Orcs from the upper world who, jealous of the riches which diff --git a/crawl-ref/source/dat/descript/species.txt b/crawl-ref/source/dat/descript/species.txt index 6603a67..0bdf957 100644 --- a/crawl-ref/source/dat/descript/species.txt +++ b/crawl-ref/source/dat/descript/species.txt @@ -75,6 +75,10 @@ Naga A hybrid; human from the chest up, with a scaly, muscular torso trailing off like that of a snake. %%%% +Nome + +A gravel-skinned humanoid able to swim through solid rock. +%%%% Ogre Large and strong, they're mostly seen as brutes. Casting ogres have been spotted, however. diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index a314716..81a4149 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -995,7 +995,10 @@ static void _finish_delay(const delay_queue_item &delay) mprf(MSGCH_PLAIN, "You finish %s.", _get_zin_recite_speech("other", you.num_turns + delay.duration).c_str()); break; - + + case DELAY_ROCK_SWIMMING: + //no "finish" message to avoid spam. + break; case DELAY_PASSWALL: { mpr("You finish merging with the rock."); @@ -1677,7 +1680,7 @@ static const char *delay_names[] = "not_delayed", "eat", "vampire_feed", "armour_on", "armour_off", "jewellery_on", "memorise", "butcher", "bottle_blood", "weapon_swap", "passwall", "drop_item", "multidrop", "ascending_stairs", - "descending_stairs", "recite", "run", "rest", "travel", "macro", + "descending_stairs", "recite","swim_through_rock" ,"run", "rest", "travel", "macro", "macro_process_key", "interruptible", "uninterruptible" }; diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc index ffc7236..97bdd5e 100644 --- a/crawl-ref/source/effects.cc +++ b/crawl-ref/source/effects.cc @@ -2222,6 +2222,12 @@ void handle_time() lose_stat(STAT_RANDOM, 1, false, "deterioration mutation"); } + // earth attunement + // decrease earth attunement outside of walls. + if (you.rocky() && ! you.in_rock()) { + change_earth_attunement(-1); + } + int added_contamination = 0; // Account for mutagenic radiation. Invis and haste will give the diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index 819b9eb..83fd5c3 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -858,13 +858,13 @@ enum delay_type DELAY_ASCENDING_STAIRS, DELAY_DESCENDING_STAIRS, DELAY_RECITE, // Zin's Recite invocation + DELAY_ROCK_SWIMMING, //Nomes entering/leaving rock // [dshaligram] Shift-running, resting, travel and macros are now // also handled as delays. DELAY_RUN, DELAY_REST, DELAY_TRAVEL, - DELAY_MACRO, // In a macro delay, a stacked delay to tell Crawl to read and act on @@ -2982,6 +2982,7 @@ enum species_type SP_VAMPIRE, SP_DEEP_DWARF, SP_CAT, + SP_NOME, SP_ELF, // (placeholder) SP_HILL_DWARF, // (placeholder) SP_OGRE_MAGE, // (placeholder) diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index 5675fa6..1f0ca17 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -4221,6 +4221,11 @@ int melee_attack::player_calc_base_unarmed_damage() damage = 0; } + //unarmed bonus for earth-attuned Nomes in base form + if (you.rocky() && you.attribute[ATTR_TRANSFORMATION] == TRAN_NONE) { + damage += 2 + you.earth_attunement; + } + if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE) { switch (you.attribute[ATTR_TRANSFORMATION]) diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc index a3e639c..974a2a7 100644 --- a/crawl-ref/source/misc.cc +++ b/crawl-ref/source/misc.cc @@ -1322,6 +1322,57 @@ void search_around(bool only_adjacent) } } +static int required_earth_attunement(dungeon_feature_type wall) { + switch (wall) + { + case DNGN_ROCK_WALL: + case DNGN_CLEAR_ROCK_WALL: + return 1; + case DNGN_GREEN_CRYSTAL_WALL: + return 2; + case DNGN_STONE_WALL: + case DNGN_CLEAR_STONE_WALL: + return 3; + case DNGN_METAL_WALL: + return 4; + default: + return -1; + } +} + +void nome_start_rock_swimming() +{ + //redraw HP/AC regardless of rocky status, as these + //change if you swim from rock to stone + you.redraw_hit_points = true; + you.redraw_armour_class=true; + + dungeon_feature_type current_grid = env.grid(you.pos()); + + //increment earth attunement to proper level + //before rock swimming + int needed_earth_attunement = required_earth_attunement(current_grid) - you.earth_attunement ; + if ( needed_earth_attunement > 0 ) + { + change_earth_attunement(needed_earth_attunement); + start_delay(DELAY_ROCK_SWIMMING, needed_earth_attunement); + } + + if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE + && you.attribute[ATTR_TRANSFORMATION] != TRAN_STATUE) + { + mpr("You quickly transform back into your natural form."); + untransform(false, true); // We're already entering the water. + } +} + +void nome_stop_rock_swimming() +{ + + you.redraw_hit_points = true; + you.redraw_armour_class=true; +} + void merfolk_start_swimming(bool stepped) { if (you.fishtail) diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h index 835b05c..83a05ca 100644 --- a/crawl-ref/source/misc.h +++ b/crawl-ref/source/misc.h @@ -17,6 +17,9 @@ struct activity_interrupt_data; bool go_berserk(bool intentional, bool potion = false); void search_around(bool only_adjacent = false); +void nome_start_rock_swimming(); +void nome_stop_rock_swimming(); + void merfolk_start_swimming(bool step = false); void merfolk_stop_swimming(); void trackers_init_new_level(bool transit); diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index bb7d9c5..3f56d0c 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -70,6 +70,7 @@ static void _species_stat_init(species_type which_species) case SP_MERFOLK: sb = 6; ib = 5; db = 7; break; // 18 case SP_KENKU: sb = 6; ib = 6; db = 7; break; // 19 + case SP_NOME: sb = 7; ib = 6; db = 5; break; // 18 case SP_KOBOLD: sb = 5; ib = 4; db = 8; break; // 17 case SP_HALFLING: sb = 3; ib = 6; db = 9; break; // 18 case SP_SPRIGGAN: sb = 2; ib = 7; db = 9; break; // 18 diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index b4948ff..03a57f3 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -506,6 +506,7 @@ static void _get_status_lights(std::vector<status_light>& out) STATUS_SPEED, DUR_DEATH_CHANNEL, DUR_TELEPATHY, DUR_STEALTH, DUR_BREATH_WEAPON, DUR_EXHAUSTED, DUR_POWERED_BY_DEATH, DUR_TRANSFORMATION, DUR_AFRAID, DUR_MIRROR_DAMAGE, DUR_SCRYING, + STATUS_EARTH_ATTUNED, }; status_info inf; diff --git a/crawl-ref/source/player-act.cc b/crawl-ref/source/player-act.cc index 4e0c3a6..a3de4ee 100644 --- a/crawl-ref/source/player-act.cc +++ b/crawl-ref/source/player-act.cc @@ -128,7 +128,24 @@ int player::get_experience_level() const bool player::can_pass_through_feat(dungeon_feature_type grid) const { - return !feat_is_solid(grid) && grid != DNGN_TEMP_PORTAL; + if (!feat_is_solid(grid) && grid != DNGN_TEMP_PORTAL) + return true; + + if (can_swim_through_rock()) { + switch (grid) + { + case DNGN_METAL_WALL: + case DNGN_GREEN_CRYSTAL_WALL: + case DNGN_ROCK_WALL: + case DNGN_STONE_WALL: + case DNGN_CLEAR_ROCK_WALL: + case DNGN_CLEAR_STONE_WALL: + return true; + default: + return false; + } + } + return false; } bool player::is_habitable_feat(dungeon_feature_type actual_grid) const diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 6c0a3f9..6c74944 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -149,6 +149,20 @@ static bool _check_moveto_cloud(const coord_def& p, return (true); } +static bool _feat_is_there(dungeon_feature_type feat) { + return true; +} + +static bool _check_moveto_breathable(const coord_def& p, const std::string &move_verb) +{ + //see if square or one of surroundings is non-wall. Used for Nomes. + const dungeon_feature_type new_grid = env.grid(p); + + return !feat_is_solid(new_grid) + || (count_neighbours_with_func(p, &feat_is_solid) < + count_neighbours_with_func(p, &_feat_is_there )) ; +} + static bool _check_moveto_trap(const coord_def& p, const std::string &move_verb) { // If we're walking along, give a chance to avoid traps. @@ -245,6 +259,7 @@ static bool _check_moveto_trap(const coord_def& p, const std::string &move_verb) static bool _check_moveto_dangerous(const coord_def& p, const std::string move_verb) { + if (you.can_swim() && feat_is_water(env.grid(p)) || !is_feat_dangerous(env.grid(p))) { @@ -267,9 +282,20 @@ static bool _check_moveto_terrain(const coord_def& p, return (_check_moveto_dangerous(p, move_verb)); } +static bool _check_moveto_rock(const coord_def& p, + const std::string &move_verb) +{ + if (!feat_is_solid(env.grid(p))) + return true; + if (you.can_swim_through_rock() && feat_is_solid(env.grid(p)) && _check_moveto_breathable(p , move_verb)) + return (true); + return false; +} + bool check_moveto(const coord_def& p, const std::string &move_verb) { - return (_check_moveto_terrain(p, move_verb) + return (_check_moveto_rock(p,move_verb) + && _check_moveto_terrain(p, move_verb) && _check_moveto_cloud(p, move_verb) && _check_moveto_trap(p, move_verb)); } @@ -291,6 +317,27 @@ void moveto_location_effects(dungeon_feature_type old_feat, return; } + //Nome effects for entering/leaving rock + if (you.can_swim_through_rock()) { + //air -> rock + if (feat_is_solid(new_grid) && !feat_is_solid(old_feat)) { + mpr("You slowly crumble into the wall."); + //start_delay(DELAY_ROCK_SWIMMING,1); + nome_start_rock_swimming(); + } + //rock -> air + if (feat_is_solid(old_feat) && !feat_is_solid(new_grid)) { + mpr("Your skin softens as you crumble out of the wall."); + //start_delay(DELAY_ROCK_SWIMMING,1); + nome_stop_rock_swimming(); + } + //rock -> different rock + if (feat_is_solid(old_feat) && feat_is_solid(new_grid) && (old_feat != new_grid)) { + //mpr("Your body changes slightly with the surrounding material."); + nome_start_rock_swimming(); + } + } + if (!you.airborne()) { if (you.species == SP_MERFOLK) @@ -2006,6 +2053,16 @@ int player_speed(void) break; } + if (you.earth_attunement > 0) { + int earth = you.earth_attunement; + ps *= (earth == 4) ? 15 : + (earth == 3) ? 14 : + (earth == 2) ? 13 : + (earth == 1) ? 12 : + 20; + ps /= 10; + } + return ps; } @@ -3090,7 +3147,22 @@ void level_change(bool skip_attribute_increase) if (you.experience_level % 3) mp_adjust++; break; + case SP_NOME: + if (you.experience_level < 17) + hp_adjust--; + + if (you.experience_level % 3) + hp_adjust--; + + mp_adjust++; + if (!(you.experience_level % 5)) + { + modify_stat((coinflip() ? STAT_STR + : STAT_INT), 1, false, + "level gain"); + } + break; case SP_SPRIGGAN: if (you.experience_level < 17) hp_adjust--; @@ -3345,6 +3417,7 @@ int check_stealth(void) else stealth += (you.skills[SK_STEALTH] * 18); break; + case SP_NOME: case SP_HALFLING: case SP_KOBOLD: case SP_SPRIGGAN: @@ -3401,6 +3474,10 @@ int check_stealth(void) stealth += scan_artefacts(ARTP_STEALTH); + //Nome stealth boost in rock + if (you.in_rock() && you.rocky()) + stealth += 30; + if (you.airborne()) stealth += 10; else if (you.in_water()) @@ -3707,6 +3784,7 @@ void display_char_status() STATUS_AIRBORNE, STATUS_NET, DUR_POISONING, STATUS_SICK, STATUS_ROT, STATUS_GLOW, DUR_CONFUSING_TOUCH, DUR_SURE_BLADE, DUR_AFRAID, DUR_MIRROR_DAMAGE, DUR_SCRYING, + STATUS_EARTH_ATTUNED, }; status_info inf; @@ -3818,6 +3896,7 @@ static int _species_exp_mod(species_type species) case SP_SPRIGGAN: case SP_KENKU: return 13; + case SP_NOME: case SP_DEEP_ELF: case SP_CENTAUR: case SP_MINOTAUR: @@ -4313,6 +4392,10 @@ int get_real_hp(bool trans, bool rotted) hitp = (you.base_hp - 5000) + (you.base_hp2 - 5000); hitp += (you.experience_level * you.skills[SK_FIGHTING]) / 5; + //Nome wall-swimming HP bonus + if (trans && you.species == SP_NOME && you.rocky() ) + hitp = hitp * 13 / 10; + // Being berserk makes you resistant to damage. I don't know why. if (trans && you.berserk()) hitp = hitp * 3 / 2; @@ -4410,6 +4493,17 @@ int get_contamination_level() return (0); } +std::string describe_earth_attunement(int earth_attunement) +{ + if (earth_attunement <= 0) + return ""; + return make_stringf("You are %s attuned to the earth.", + (earth_attunement == 4) ? "intimately" : + (earth_attunement == 3) ? "deeply" : + (earth_attunement == 2) ? "moderately" : + (earth_attunement == 1) ? "slightly" : "buggily"); +} + std::string describe_contamination(int cont) { if (cont > 5) @@ -4490,6 +4584,41 @@ void contaminate_player(int change, bool controlled, bool msg) } } +void change_earth_attunement(int change, bool msg ) +{ + you.redraw_armour_class = true; + you.redraw_hit_points = true; + + int old_ea = you.earth_attunement; + you.earth_attunement += change; + if (msg) { + if (you.earth_attunement <= 0 && old_ea > 0) { + mpr("You are no longer attuned to the earth."); + } + } + + //handle HP gain/loss + if (you.earth_attunement > 0 && old_ea <= 0) { + calc_hp(); + you.hp = you.hp * 13/10; + deflate_hp(you.hp_max,false); + } + + if (you.earth_attunement <= 0 && old_ea > 0) { + if (you.hp != you.hp_max) + { + you.hp = you.hp * 10 / 13; + if (you.hp < 1) + you.hp = 1; + else if (you.hp > you.hp_max) + you.hp = you.hp_max; + } + calc_hp(); + } + +} + + bool confuse_player(int amount, bool resistable) { ASSERT(!crawl_state.game_is_arena()); @@ -5316,6 +5445,16 @@ bool player::is_levitating() const return (duration[DUR_LEVITATION]); } +bool player::in_rock() const +{ + return feat_is_solid(grd(pos())); +} + +bool player::rocky() const +{ + return (earth_attunement > 0); +} + bool player::in_water() const { return (!airborne() && !beogh_water_walk() @@ -5330,6 +5469,11 @@ bool player::can_swim(bool permanently) const || (!permanently && transform_can_swim())); } +bool player::can_swim_through_rock() const +{ + return species == SP_NOME; +} + int player::visible_igrd(const coord_def &where) const { if (grd(where) == DNGN_LAVA @@ -5505,9 +5649,29 @@ int player_icemail_armour_class() * ICEMAIL_MAX / ICEMAIL_TIME)); } +int player::nome_ac_boost() const +{ + int earth = you.earth_attunement; + if (earth > 0) { + return 100* ( you.experience_level/4 + + (earth == 4) ? 8 : + (earth == 3) ? 7 : + (earth == 2) ? 6 : + (earth == 1) ? 5 : 9 ); + } + + return 0; +// //bonuses do not stack with statue form +// if ( you.attribute[ATTR_TRANSFORMATION] == TRAN_STATUE) +// return 0; +} + int player::armour_class() const { int AC = 0; + + if (you.species == SP_NOME ) + AC += nome_ac_boost(); for (int eq = EQ_MIN_ARMOUR; eq <= EQ_MAX_ARMOUR; ++eq) { diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index b271bc4..38d4ab2 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -96,6 +96,7 @@ public: bool royal_jelly_dead; bool transform_uncancellable; bool fishtail; // Merfolk fishtail transformation + // bool rocky; //Nome wall transformation unsigned short pet_target; @@ -193,6 +194,7 @@ public: std::vector<demon_trait> demonic_traits; + int earth_attunement; // nomes only int magic_contamination; FixedVector<bool, NUM_FIXED_BOOKS> had_book; @@ -359,8 +361,13 @@ public: bool in_water() const; bool can_swim(bool permanently = false) const; + bool can_swim_through_rock() const; int visible_igrd(const coord_def&) const; bool is_levitating() const; + bool in_rock() const; + //at least one level of earth attunement (nomes) + bool rocky() const; + bool cannot_speak() const; bool invisible() const; bool misled() const; @@ -574,6 +581,7 @@ public: bool can_throw_large_rocks() const; bool can_smell() const; + int nome_ac_boost() const; int armour_class() const; int gdr_perc() const; int melee_evasion(const actor *attacker, @@ -854,6 +862,8 @@ void set_mp(int new_amount, bool max_too); void contaminate_player(int change, bool controlled = false, bool msg = true); +void change_earth_attunement(int change, bool msg = true); +std::string describe_earth_attunement( int earth_attunement) ; bool confuse_player(int amount, bool resistable = true); diff --git a/crawl-ref/source/skills2.cc b/crawl-ref/source/skills2.cc index fd2775a..2ac9e67 100644 --- a/crawl-ref/source/skills2.cc +++ b/crawl-ref/source/skills2.cc @@ -1282,6 +1282,43 @@ static const species_skill_aptitude species_skill_aptitudes[] = APT(SP_CAT, SK_POISON_MAGIC, -1), APT(SP_CAT, SK_INVOCATIONS, -1), APT(SP_CAT, SK_EVOCATIONS, -2), + + + // SP_NOME + APT(SP_NOME, SK_FIGHTING, 0), + APT(SP_NOME, SK_SHORT_BLADES, 0), + APT(SP_NOME, SK_LONG_BLADES, -2), + APT(SP_NOME, SK_AXES, 0), + APT(SP_NOME, SK_MACES_FLAILS, 1), + APT(SP_NOME, SK_POLEARMS, -3), + APT(SP_NOME, SK_STAVES, 0), + APT(SP_NOME, SK_SLINGS, 1), + APT(SP_NOME, SK_BOWS, -1), + APT(SP_NOME, SK_CROSSBOWS, -1), + APT(SP_NOME, SK_THROWING, 1), + APT(SP_NOME, SK_ARMOUR, 1), + APT(SP_NOME, SK_DODGING, -1), + APT(SP_NOME, SK_STEALTH, 1), + APT(SP_NOME, SK_STABBING, 1), + APT(SP_NOME, SK_SHIELDS, 0), + APT(SP_NOME, SK_TRAPS_DOORS, 0), + APT(SP_NOME, SK_UNARMED_COMBAT, 0), + APT(SP_NOME, SK_SPELLCASTING, 0), + APT(SP_NOME, SK_CONJURATIONS, 0), + APT(SP_NOME, SK_ENCHANTMENTS, -2), + APT(SP_NOME, SK_SUMMONINGS, 0), + APT(SP_NOME, SK_NECROMANCY, 0), + APT(SP_NOME, SK_TRANSLOCATIONS, -2), + APT(SP_NOME, SK_TRANSMUTATIONS, 1), + APT(SP_NOME, SK_FIRE_MAGIC, 1), + APT(SP_NOME, SK_ICE_MAGIC, -1), + APT(SP_NOME, SK_AIR_MAGIC, -4), + APT(SP_NOME, SK_EARTH_MAGIC, 5), + APT(SP_NOME, SK_POISON_MAGIC, -1), + APT(SP_NOME, SK_INVOCATIONS, -1), + APT(SP_NOME, SK_EVOCATIONS, -1), + + }; // Traditionally, Spellcasting and In/Evocations formed the exceptions here: @@ -1639,6 +1676,7 @@ static std::string _stk_weight() case SP_KENKU: return "Light"; + case SP_NOME: case SP_HALFLING: case SP_KOBOLD: return "Feather"; diff --git a/crawl-ref/source/species.cc b/crawl-ref/source/species.cc index e626619..961f95f 100644 --- a/crawl-ref/source/species.cc +++ b/crawl-ref/source/species.cc @@ -25,7 +25,7 @@ static species_type species_order[] = { SP_HILL_ORC, SP_MERFOLK, // small species SP_HALFLING, SP_KOBOLD, - SP_SPRIGGAN, + SP_SPRIGGAN, SP_NOME, // significantly different body type from human SP_NAGA, SP_CENTAUR, SP_OGRE, SP_TROLL, @@ -60,7 +60,7 @@ static const char * Species_Abbrev_List[NUM_SPECIES] = // the draconians "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Ce", "DG", "Sp", "Mi", "DS", "Gh", "Ke", "Mf", "Vp", "DD", - "Fe", + "Fe", "No", // placeholders "El", "HD", "OM", "GE", "Gn" }; @@ -247,6 +247,7 @@ std::string species_name(species_type speci, bool genus, bool adj) case SP_MERFOLK: res = (adj ? "Merfolkian" : "Merfolk"); break; case SP_VAMPIRE: res = (adj ? "Vampiric" : "Vampire"); break; case SP_CAT: res = (adj ? "Feline" : "Felid"); break; + case SP_NOME: res = (adj ? "Nomish" : "Nome" ); break; default: res = (adj ? "Yakish" : "Yak"); break; } } @@ -319,6 +320,7 @@ size_type species_size(species_type species, size_part_type psize) return ((psize == PSIZE_TORSO) ? SIZE_MEDIUM : SIZE_LARGE); case SP_HALFLING: case SP_KOBOLD: + case SP_NOME: return (SIZE_SMALL); case SP_SPRIGGAN: case SP_CAT: @@ -340,6 +342,7 @@ monster_type player_species_to_mons_species(species_type species) case SP_SLUDGE_ELF: return (MONS_ELF); case SP_MOUNTAIN_DWARF: + case SP_NOME: //PLACEHOLDER until Nome monster implemented return (MONS_DWARF); case SP_HALFLING: return (MONS_HALFLING); diff --git a/crawl-ref/source/status.cc b/crawl-ref/source/status.cc index 83cb1a1..f05ab8c 100644 --- a/crawl-ref/source/status.cc +++ b/crawl-ref/source/status.cc @@ -196,6 +196,7 @@ static void _mark_expiring(status_info* inf, bool expiring) static void _describe_airborne(status_info* inf); static void _describe_burden(status_info* inf); +static void _describe_earth_attunement(status_info* inf); static void _describe_glow(status_info* inf); static void _describe_hunger(status_info* inf); static void _describe_regen(status_info* inf); @@ -258,6 +259,9 @@ void fill_status_info(int status, status_info* inf) _describe_burden(inf); break; + case STATUS_EARTH_ATTUNED: + _describe_earth_attunement(inf); + break; case STATUS_GLOW: // includes corona _describe_glow(inf); @@ -443,6 +447,25 @@ static void _describe_hunger(status_info* inf) break; } } +static void _describe_earth_attunement(status_info* inf) +{ + int earth = you.earth_attunement; + if ( earth > 0) + { + + inf -> light_text = "earth"; + inf->light_colour = _bad_ench_colour(earth, 2, 3); + + inf->short_text = + (earth == 1) ? "slightly " : + (earth == 2) ? "moderately " : + (earth == 3) ? "deeply" : + (earth == 4) ? "intimately " : "ridiculously"; + inf->short_text += " earth-attuned"; + inf->long_text = describe_earth_attunement(earth); + } + +} static void _describe_glow(status_info* inf) { diff --git a/crawl-ref/source/status.h b/crawl-ref/source/status.h index d983794..734abab 100644 --- a/crawl-ref/source/status.h +++ b/crawl-ref/source/status.h @@ -11,6 +11,7 @@ enum status_type STATUS_AIRBORNE = NUM_DURATIONS + 1, STATUS_BEHELD, STATUS_BURDEN, + STATUS_EARTH_ATTUNED, STATUS_GLOW, STATUS_NET, STATUS_HUNGER, diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index f6ba936..524209c 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -1029,6 +1029,7 @@ static void tag_construct_you(writer &th) marshallShort(th, you.hunger); marshallBoolean(th, you.fishtail); + marshallInt(th, you.earth_attunement); // how many you.equip? marshallByte(th, NUM_EQUIP); @@ -1609,6 +1610,7 @@ static void tag_read_you(reader &th, int minorVersion) if (minorVersion >= TAG_MINOR_FISHTAIL) #endif you.fishtail = unmarshallBoolean(th); + you.earth_attunement = unmarshallInt(th); // How many you.equip? count = unmarshallByte(th); -- 1.6.3.3 |
||||||||||||
|
Notes | |
(0009053) BirdoPrey (reporter) 2010-10-22 01:11 edited on: 2010-10-22 08:24 |
So, uh... a race that trivializes every threat in the game? will be very cool & unique though if we can figure out some way to balance it. |
(0009054) minced (reporter) 2010-10-22 01:32 edited on: 2010-10-23 10:11 |
This race is indeed ridiculously overpowered right now. Leave feedback at this wiki page: https://crawl.develz.org/wiki/doku.php?id=dcss:brainstorm:species:nome [^] - I'll try my best to make a second implementation that's somewhat challenging to play. |
(0009072) minced (reporter) 2010-10-24 02:47 |
Second implementation attached - uses Wensleydale's suggested "earth attunement" mechanic with some changes, see wiki page for details. Aptitudes have also been lowered in many cases. |
(0027127) PleasingFungus (administrator) 2014-08-30 19:31 |
I get the feeling this one isn't going anywhere. |
Mantis 1.1.8[^] Copyright © 2000 - 2009 Mantis Group |