diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..8c86bd6 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,220 @@ +# AGENTS.md + +## Purpose + +This file defines the rules, expectations, and constraints for **automated agents** +(including AI coding assistants, LLMs, bots, and scripted tools) contributing to this +codebase. + +The goal is to: +- Preserve long-term maintainability +- Avoid licensing and provenance risk +- Prevent architectural drift +- Ensure consistency with established design decisions +- Make human review straightforward and reliable + +All automated agents MUST comply with the requirements in this document. + +--- + +## Scope + +This repository is a **C-based MUD engine** derived from CircleMUD/tbaMUD and is +under active development, including significant refactors to core systems such as: + +- Skills and proficiency +- Combat resolution +- Object and mobile data models +- Online Creation (OLC) +- Persistence and serialization +- Builder and immortal tooling + +Changes often have **far-reaching consequences** across gameplay, balance, and +world data integrity. + +--- + +## General Rules for Automated Agents + +### 1. No Unreviewed Structural Changes + +Automated agents MUST NOT: +- Reorganize directories +- Rename files +- Merge or split source files +- Introduce new subsystems +- Replace existing systems wholesale + +Unless **explicitly instructed** to do so. + +Incremental, targeted changes are required. + +--- + +### 2. Preserve Existing Behavior Unless Directed + +If a function, macro, or subsystem already exists: +- Do NOT change semantics +- Do NOT “simplify” logic +- Do NOT remove edge-case handling +- Do NOT refactor stylistically + +Unless the user **explicitly requests** that behavior be changed. + +Backward compatibility is a priority. + +--- + +### 3. Minimal Diffs Are Mandatory + +Automated agents must: +- Change only what is necessary +- Avoid drive-by formatting edits +- Avoid re-indentation unless required +- Avoid renaming variables unless necessary for correctness + +If a fix can be achieved with a 3-line change, a 30-line rewrite is unacceptable. + +--- + +### 4. Follow Existing Code Style Exactly + +This codebase intentionally reflects legacy CircleMUD conventions. + +Agents MUST: +- Match indentation style +- Match brace placement +- Match naming conventions +- Match macro usage patterns + +Do not introduce modern C idioms, new abstractions, or stylistic preferences. + +--- + +## Licensing and Provenance Requirements + +### 5. No Third-Party Code Injection + +Automated agents MUST NOT: +- Paste code from external projects +- Introduce snippets from blogs, gists, StackOverflow, or forums +- Reproduce code from GPL-incompatible sources + +All code must be **original**, **derivative of existing repository code**, or +**explicitly authorized** by the user. + +If uncertain, ask before proceeding. + +--- + +### 6. Do Not Assume License Changes + +Do NOT: +- Modify license headers +- Remove attribution +- Add new license files +- Assume relicensing is permitted + +Licensing is handled deliberately and conservatively. + +--- + +## Technical Expectations + +### 7. Full-Context Awareness Required + +Before modifying a subsystem, automated agents MUST: +- Read all related `.c` and `.h` files +- Identify existing macros, helpers, and patterns +- Understand how data flows through the system + +Guessing or partial understanding is not acceptable. + +--- + +### 8. Prefer Existing Helpers and Macros + +If functionality already exists: +- Reuse it +- Extend it minimally if needed +- Do not reimplement logic elsewhere + +Duplication increases maintenance cost and risk. + +--- + +### 9. Explicitly Note Assumptions + +When producing code or recommendations, agents MUST: +- State assumptions clearly +- Identify uncertainties +- Call out areas that require human confirmation + +Silent assumptions are dangerous. + +--- + +## Data Integrity and World Safety + +### 10. Protect World Files and Player Data + +Automated agents must treat: +- World files +- Player files +- OLC data +- Serialized objects/mobs/rooms + +As **production data**. + +Do NOT: +- Change file formats casually +- Break backward compatibility +- Introduce implicit migrations + +Any data format change must be explicit and documented. + +--- + +## Communication Expectations + +### 11. Be Direct and Precise + +Agent output should: +- Use technical language appropriate to experienced developers +- Avoid verbosity for its own sake +- Avoid motivational or conversational filler +- Focus on correctness and clarity + +--- + +### 12. Ask Before Acting When Uncertain + +If instructions are ambiguous or risky: +- STOP +- Ask clarifying questions +- Do not guess intent + +Incorrect confidence is worse than delay. + +--- + +## Enforcement + +Failure to comply with this document may result in: +- Rejection of changes +- Reversion of commits +- Loss of permission to contribute + +This applies equally to humans and automated agents. + +--- + +## Summary + +This codebase prioritizes: +- Stability over novelty +- Clarity over cleverness +- Intentional design over convenience + +Automated agents are welcome collaborators **only** when they operate within +these constraints. diff --git a/README.md b/README.md index 682532d..7186eb3 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,18 @@ -***Files for Miranthas MUD.*** +***Files for Cataclysm MUD.*** -Miranthas MUD is a continuation of tbaMUD/CircleMUD, which is built on DIKU MUD. -The code here is freeware to honor that tradition. +Cataclysm MUD is a continuation of tbaMUD/CircleMUD, which is built on DIKU MUD. +Due to licensing issues with tbaMUD, all licensing attributions should remain the +same and not changed from the original, pre-LGPL license model. -Due to the sensitive nature of topics found in this setting, all characters and -players are 18+. The game world is derived from several inspirational sources, -most notably the former Armageddon MUD. +TO be clear: **this is not an LGPL licensed fork**. -Roleplay is highly encouraged, but not enforced. - -Features in Miranthas MUD Alpha release: +Changes from stock tbaMUD 2025 to Cataclysm MUD v1.0.0-alpha: * The city of Caleran is available for exploration * Experience points and levels are removed in favor of skill based progression * Initial skills/spells based partly on tbaMUD code and 5e conversion (to be cleaned up in later release) * Expanded emoting system for roleplay -* Permanent character death - aka. hardcore mode +* Permanent character death * A hybrid "5e-like" system where: - [ ] Legacy THAC0 systems are removed in favor of the modern 5e system - [ ] Your skill level translates to a proficiency bonus on a per-skill level @@ -44,24 +41,72 @@ Features in Miranthas MUD Alpha release: * Backgrounds are now available for PC's and NPC's * Account system for tracking players/characters over long periods of time -Features to be implemented in the next few releases: +Changes in v1.1.0-alpha: -* Race/species selection -* Subclass selection + * Cleaned up legacy practice system code + * Added skill caps for classes to limit ability of everyone to reach skill level 100 (and respective proficiency) + * Race/species selection and stat ranges (elves have higher dex, dwarves have higher str, etc) + * Renamed move to stamina in code to reflect how much energy is used for certain actions + * Species have base hit/mana/stamina now, plus their class modifier rolls + * Prioritized stats during character generation + * Ability to change ldesc of PC/NPC's + * Ability to look in certain directions to see what is 1-3 rooms away + * PC's and NPC's can now have an age set between 18-65 + * "audit armor" and "audit melee" commands for immortals (formerly "acaudit") to check non-compliant items + * Minor score output change to only show quest status while on a quest, PC/NPC name, sdesc, and current ldesc + * Added ability to reroll initial stats if they are not to player's liking, and undo reroll if needed + * Removed alignment from game - no more GOOD/EVIL flags or restrictions on shops + * Removed ANTI_ flags related to class restrictions on what objects they can use + * Mounts added to help with long trips, and ability to use them as pack animals + * Introduced AGENTS.md file to ensure code quality + * Migration away from OLC with new commands "rcreate" and "rset" for builders to modify rooms + * Migration away from OLC with new commands "ocreate", "oset", and "osave" for builders to modify objects + * Migration away from OLC with new command "mcreate" and for builders to modify NPC's + * Fixed issue with msave not saving items in containers on NPC's + +Features that would have been implemented in the next few releases: + +* Height and weight normalized to species +* Stables allow for purchasing of mounts +* Stables will take mounts and provide tickets to get them out +* Updated door code so that it can be closed/locked/saved with rsave code +* SECTOR/ROOM type changes to make terrain movement easier or more difficult +* Subclass selection to personalize character further +* Combat is slowed down so it isn't over in < 15 seconds (unless you're far outmatched) +* Wagons added to help with caravans +* BUILDING object type created to allow enter/leave +* Updated BUILDING object type so that it can be damaged and no longer enterable (but someone can leave at cost to health) +* Plantlife introduced, allowing a plant object to produce fruit or herbs every few hours/days +* Plantlife can be refreshed to spawn fruits/herbs more frequently by watering it +* Updated lockpicking skill +* Trap as a skill - one focused on city and one focused on desert +* Poisons and antidotes +* New alcohol and drugs/stimulants +* Skimmers/ships to traverse difficult terrain +* New elemental classes +* Introduction of gathering mana/magic for sorceror class +* Highly modified magic system +* Ranged weapons and ammo +* Components for some magical spells +* Reading/writing limited to specific castes of society +* Haggling and bartering system * New calendar and moon cycles * Heat based on time of day increases/decreases, changing hunger/thirst levels -* Sandstorms -* Shaded rooms +* Weather updates and sandstorms limiting visibility +* Shaded rooms providing bonuses to regeneration * Criminal system for cities and jails * Basic Psionics * Basic crafting system -* Continued skill and spell improvements * Apartment rentals for storing your loot * Enhanced quest system * Dialogue trees with NPC's * Additional zones/cities based on Miranthas world map * Resources on the world map can be claimed by different city-states or independent factions * Claimed resources improve quality of armor/weapons/food/prices available +* Death from old age if you roll badly on your birthday after the expected lifespan of a species +* Attacks hit different parts of the body and have different damage effects +* Armor degradation based on damage taken per body part +* Weapon degradation based on damage dealt - potentially shattering weapons ...and down the road: diff --git a/doc/building.txt b/doc/building.txt index 3a1b5a2..1d3c84d 100644 --- a/doc/building.txt +++ b/doc/building.txt @@ -226,7 +226,7 @@ sell objects to players. A single zone typically contains up to than 100 rooms, 100 monster definitions and 100 object definitions, but a large region can be subdivided into several -zones at the author’s discretion. For example, the City of Midgaard is divided +zones at the author’s discretion. For example, a large city can be divided into two zones, one for the main city and one for the southern residential area. In addition to this, with the new zone system describing top and bottom rooms of a zone, zones can contain very few rooms and indeed can overlap with other @@ -242,7 +242,7 @@ independent, so there can be both a room number 3001 and an object number refers to each entity by its Vnum and never by name. Vnums are normally not seen by players. Each zone itself also has a Vnum. A common convention is to number the zone with the Vnums of its component rooms, divided by 100. For -example, Midgaard is zone 30, consisting of rooms 3000 to 3099. Mobile and +example, the main city is zone 30, consisting of rooms 3000 to 3099. Mobile and object numbering follows the same convention. The author of the zone can define aspects of each room such as the terrain type, @@ -632,7 +632,7 @@ The format of a mobile is: ~ ~ - + {type-specific information; see below for details} Virtual Number This number is critical; it is the identity of the mobile within @@ -687,9 +687,9 @@ L) NPC Flags : ISNPC its hit points. If the WIMPY bit is set in conjunction with any of the forms of the AGGRESSIVE bit, the mob will only attack mobs that are unconscious (sleeping or incapacitated). -9) AGGR_EVIL Mob will attack players that are evil-aligned. -10) AGGR_GOOD Mob will attack players that are good-aligned. -11) AGGR_NEU Mob will attack players that are neutrally aligned. +9) RESERVED Not used. +10) RESERVED Not used. +11) RESERVED Not used. 12) MEMORY Mob will remember players that initiate attacks on it, and will attack that player if it ever runs into him again. 13) HELPER The mob will attack any player it sees in the room that is @@ -710,7 +710,7 @@ following values: M) AFF Flags : NOBITS 1) BLIND Mob is blind. 2) INVIS Mob is invisible. -3) DET-ALIGN NOT USED. +3) RESERVED NOT USED. 4) DET-INVIS Mob can see invisible characters and objects. 5) DET-MAGIC Mob is sensitive to magical presence. 6) SENSE-LIFE Mob can sense hidden life. @@ -721,23 +721,17 @@ M) AFF Flags : NOBITS 10) CURSE Mob is cursed. 11) INFRA Mob can see in dark. 12) POISON Reserved for internal use. Do not set. -13) PROT-EVIL Mob is protected from evil characters. -14) PROT-GOOD Mob is protected from good characters. +13) RESERVED NOT USED. +14) RESERVED NOT USED. 15) SLEEP Reserved for internal use. Do not set. 16) NO_TRACK Mob cannot be tracked. -17) UNUSED Unused (room for future expansion). -18) UNUSED Unused (room for future expansion). +17) FLY Mob is flying. +18) SCUBA Mob can breathe underwater. 19) SNEAK Mob can move quietly without room being informed. 20) HIDE Mob is hidden; can only be seen with sense life. -21) UNUSED Unused (room for future expansion). +21) SCAN Actively scanning for hidden threats. 22) CHARM Reserved for internal use. Do not set. -Alignment A number from -1000 to 1000 representing the mob’s initial alignment. - --1000.....-350 Evil - -349......349 Neutral - 350.....1000 Good - Type Flag This flag is a single letter which indicates what type of mobile is currently being defined, and controls what information tbaMUD expects to find next (i.e., in the file from the current point to the end of the current @@ -748,7 +742,7 @@ Standard tbaMUD supports two types of mobiles: S (for Simple), and E (for Enhanc 4.2 Type S Mobiles For type S mobs, the type-specific information should be in the following format: - S + S @@ -840,13 +834,13 @@ A beastly fido is mucking through the garbage looking for food here. The fido is a small dog that has a foul smell and pieces of rotted meat hanging around his teeth. ~ -65738 0 0 0 65536 0 0 0 -200 S +65738 0 0 0 65536 0 0 0 0 S 1 20 9 0d0+10 1d2+0 10 100 8 8 1 -This is mobile vnum 3062. The Fido has mob and affect flags set and has an -initial alignment of -200. After the S flag we see that the Fido is level 1, +This is mobile vnum 3062. The Fido has mob and affect flags set and has a +reserved value of 0. After the S flag we see that the Fido is level 1, has a THAC0 of 20, an Armor Class of 9, 0d0+10 hit points (10 hitpoints), and will do 1d2 hit points of bare hand damage per round. The Fido has 10 coins and 100 experience points, has a load position and default position of @@ -865,7 +859,7 @@ literal letter Emust then come after all E-specs to signal the end of the mob. The format of an E mobile is as follows: - E + E @@ -886,7 +880,7 @@ A beastly fido is mucking through the garbage looking for food here. The fido is a small dog that has a foul smell and pieces of rotted meat hanging around his teeth. ~ -65738 0 0 0 65536 0 0 0 -200 E +65738 0 0 0 65536 0 0 0 0 E 1 20 9 0d0+10 1d2+0 10 100 8 8 1 @@ -1033,14 +1027,10 @@ but has no substantive effect otherwise. The flags have the following values: 7) MAGIC Item has a magical aura and cannot be enchanted. 8) NODROP Item is cursed and cannot be removed or dropped. 9) BLESS Item is blessed (cosmetic). -10) ANTI_GOOD Item cannot be used by good-aligned characters. -11) ANTI_EVIL Item cannot be used by evil-aligned characters. -12) ANTI_NEUTRAL Item cannot be used by neutral align characters. -13) ANTI_MAGIC_USER Item cannot be used by the Mage class. -14) ANTI_CLERIC Item cannot be used by the Cleric class. -15) ANTI_THIEF Item cannot be used by the Thief class. -16) ANTI_WARRIOR Item cannot be used by the Warrior class. -17) NOSELL Shopkeepers will not buy or sell the item. +10) NOSELL Shopkeepers will not buy or sell the item. +11) QUEST_ITEM Shopkeepers will only accept questpoints for this item. +12) HOOD_UP WORN item hood is currently up. +13) SKINNED Item/corpse can be skinned. Wear Bitvector A bitvector (see section 2.4 on ‘Using Bitvectors’) with the following values: @@ -1311,7 +1301,7 @@ terminated by the literal letter S. Virtual Number An arbitrary number used to identify the zone. Zone numbers are traditionally the room numbers of the zone divided by 100; for example, -Midgaard, which consists of rooms 3000 through 3099, is zone 30. +The main city, which consists of rooms 3000 through 3099, is zone 30. Zone Name A label given to the zone so that it can be identified in system logs. @@ -1444,7 +1434,7 @@ Zone File Example A sample zone file annotated with comments follows. #30 * This is zone number 30 -Northern Midgaard Main City~ * The name of the zone +Northern Main City~ * The name of the zone 3099 15 2 * Top of zone is room #3099; it resets every 15 minutes. * * Resets regardless of people. * @@ -1611,16 +1601,16 @@ monty-haul campaigns. Shop Keeper Mobile Number Virtual number of the shopkeeper mobile. With Who Bitvector A bitvector (see section 2.4 on ‘Using Bitvectors’) used to -designate certain alignments or classes that the shop will not trade with, with +designate certain classes that the shop will not trade with, with the following values: E) No Trade With : NOBITS - Designates certain alignments or classes that the shop will not trade with: + Designates certain classes that the shop will not trade with: - 1) Good 2) Evil - 3) Neutral 4) Magic User - 5) Cleric 6) Thief - 7) Warrior + 1) Sorceror 2) Cleric + 3) Rogue 4) Fighter + 5) Barbarian 6) Ranger + 7) Bard 8) Druid Shop Room 1...Shop Room n The virtual numbers the mobile must be in for the shop to be effective. (So transferred shopkeepers can’t sell in the desert). @@ -1737,15 +1727,16 @@ Shop Keeper Mobile Number Virtual number of the shopkeeper mobile. With Who Bitvector A bitvector (see section ‘Using Bitvectors’) used to designate certain -alignments or classes that the shop will not trade with, with the following +classes that the shop will not trade with, with the following values: -1 a NOGOOD Keeper won’t trade with positively-aligned players. -2 b NOEVIL Keeper won’t trade with evilly-aligned players. -4 c NONEUTRAL Keeper won’t trade with neutrally-aligned players. -8 d NOMAGIC_USER Keeper won’t trade with the Mage class. +8 d NOSORCEROR Keeper won’t trade with the Sorceror class. 16 e NOCLERIC Keeper won’t trade with the Cleric class. -32 f NOTHIEF Keeper won’t trade with the Thief class. -64 g NOWARRIOR Keeper won’t trade with the Warrior class. +32 f NOROGUE Keeper won’t trade with the Rogue class. +64 g NOFIGHTER Keeper won’t trade with the Fighter class. +128 h NOBARBARIAN Keeper won’t trade with the Barbarian class. +256 i NORANGER Keeper won’t trade with the Ranger class. +512 j NOBARD Keeper won’t trade with the Bard class. +1024 k NODRUID Keeper won’t trade with the Druid class. Shop Room Number The virtual number the mobile must be in for the shop to be effective. (So @@ -1823,7 +1814,7 @@ interactions you want it to perform. See the help files in game for details. 8.2 Trigger File Example #100 -Obj Command 100 - portal to Midgaard~ +Obj Command 100 - portal to the capital~ 1 c 7 en~ if %cmd.mudcommand% == enter && %arg% /= portal @@ -1848,18 +1839,18 @@ particular MUD. Check with your implementor for details. 7) charm person 8) chill touch 9) clone 10) color spray 11) control weather 12) create food 13) create water 14) cure blind 15) cure critic -16) cure light 17) curse 18) detect alignment +16) cure light 17) curse 18) reserved 19) detect invisibility 20) detect magic 21) detect poison -22) dispel evil 23) earthquake 24) enchant weapon +22) reserved 23) earthquake 24) enchant weapon 25) energy drain 26) fireball 27) harm 28) heal 29) invisibility 30) lightning bolt 31) locate object 32) magic missile 33) poison -34) protection from evil 35) remove curse 36) sanctuary +34) reserved 35) remove curse 36) sanctuary 37) shocking grasp 38) sleep 39) strength -40) summon 41) !UNUSED! 42) word of recall +40) summon 41) !RESERVED! 42) word of recall 43) remove poison 44) sense life 45) animate dead -46) dispel good 47) group armor 48) group heal -49) !UNUSED! 50) infravision 51) waterwalk +46) reserved 47) group armor 48) group heal +49) !RESERVED! 50) infravision 51) waterwalk B Item Values for Drink Containers diff --git a/doc/coding.txt b/doc/coding.txt index ccb3eda..eabc075 100644 --- a/doc/coding.txt +++ b/doc/coding.txt @@ -813,7 +813,7 @@ equips it to the character for the specified location. unequip_char() does the opposite; it removes the object from the character’s equipment list and returns it as a free-floating object. The object being unequipped must be placed elsewhere or destroyed. Note that some objects may not be equipped by characters of certain -classes and/or alignments. +classes. void obj_to_char (struct obj_data *object, struct char_data *ch) @@ -1418,18 +1418,9 @@ search for CLASS_UNDEFINEDand add a new CLASS_xxxdefinition for your class name with the next available number. Remember to bump the value of NUM_CLASSES, just below, by 1. -Then search structs.hfor "Extra object flags" so you can add an "ITEM_ANTI_xxx" -flag for your new class. As before, use the next available number in the sequence -for ITEM_xxx flags. - -The "ITEM_xxx" extra flags have a corresponding text description in constants.c, so -search it for "ITEM_x (extra bits)". Add a string giving a short name for the new -ITEM_ANTI_xxx flag, in the appropriate order, before the "\n" entry near the -bottom. - -The shops have a similar "don’t trade" setup, so search shop.hfor "TRADE_NOGOOD" +The shops have a similar "don’t trade" setup, so search shop.h for "TRADE_NOSORCEROR" to add a new TRADE_NOxxx item to the list for the class to be added. Below that -(near "NOTRADE_GOOD"), a line will need to be added for each new class so the ’no +(near "NOTRADE_SORCEROR"), a line will need to be added for each new class so the ’no trade’ status of a shop can be tested for the class. With the definitions in shop.h, the shop code in shop.c can then be modified to @@ -1559,7 +1550,7 @@ foreground colors. Basic special procedures have largely been replaced by trigedit. Thus shifting the workload from the coder to the builder to add life and creativity into their zones. While it is easier, and less time consuming, to make triggers than special -procedures they are still used for such functions as banks and guildmasters. +procedures they are still used for such functions as banks. Using special procedures, your virtual world is not just a bunch of monsters, objects and rooms, reduced to a number of statistics. Just like good descriptions @@ -1570,7 +1561,7 @@ Several special procedures are provided with stock tbaMUD which you can use to create your own and get used to the mechanics of special procedures. These special procedures can be found in castle.c and spec_procs.c. They range from very simple procedures, like puff (pulsed special procedure) or bank (command-driven special -procedure), to very complex procedures like the guild master. +procedure), to very complex procedures. In this chapter, FALSE refers to the value 0 and TRUE to any non-zero value. diff --git a/doc/msgedit.txt b/doc/msgedit.txt index cd1ae8c..c96a98d 100644 --- a/doc/msgedit.txt +++ b/doc/msgedit.txt @@ -16,11 +16,11 @@ Message List: 0 ) [5 ] 1, burning hands 30) [314] 2, Unknown 1 ) [6 ] 1, call lightning 31) [399] 2, Unknown 2 ) [8 ] 1, chill touch 32) [33 ] 1, poison -3 ) [10 ] 1, color spray 33) [202] 1, !UNUSED! -4 ) [22 ] 1, dispel evil 34) [203] 1, !UNUSED! -5 ) [23 ] 1, earthquake 35) [204] 1, !UNUSED! -6 ) [25 ] 1, energy drain 36) [205] 1, !UNUSED! -7 ) [26 ] 1, fireball 37) [206] 1, !UNUSED! +3 ) [10 ] 1, color spray 33) [202] 1, !RESERVED! +4 ) [22 ] 1, dispel 34) [203] 1, !RESERVED! +5 ) [23 ] 1, earthquake 35) [204] 1, !RESERVED! +6 ) [25 ] 1, energy drain 36) [205] 1, !RESERVED! +7 ) [26 ] 1, fireball 37) [206] 1, !RESERVED! ========================================= diff --git a/doc/syserr.txt b/doc/syserr.txt index 35318a7..361335d 100644 --- a/doc/syserr.txt +++ b/doc/syserr.txt @@ -9,17 +9,16 @@ rumble@tbamud.com -- Rumble 1. Errant Rooms (show error command) 2. SYSERR: Object # (oedit-s-desc) doesn't have drink type as last alias. -3. SYSERR: Mob # both Aggressive and Aggressive_to_Alignment. -4. SYSERR: Object # (oedit-s-desc) has out of range level #. -5. SYSERR: Object # (oedit-s-desc) has negative weight (-2147483644). +3. SYSERR: Object # (oedit-s-desc) has out of range level #. +4. SYSERR: Object # (oedit-s-desc) has negative weight (-2147483644). SYSERR: Object # (oedit-s-desc) has out of range level #2147483647. -6. SYSERR: Object # (oedit-s-desc) uses 'UNDEFINED' spell #. -7. SYSERR: Object # (oedit-s-desc) contains (5) more than maximum (3). -8. Char is already equipped: (medit-s-desc), (oedit-s-desc) -9. SYSERR: Attempt to assign spec to non-existant mob # -10. No associated object exists when attempting to create a board [vnum #]. -11. SYSERR: Mob using >'((ch)-)player_specials.... -12: SYSERR: Object # (keyword) is type NOTE and has extra description with +5. SYSERR: Object # (oedit-s-desc) uses 'UNDEFINED' spell #. +6. SYSERR: Object # (oedit-s-desc) contains (5) more than maximum (3). +7. Char is already equipped: (medit-s-desc), (oedit-s-desc) +8. SYSERR: Attempt to assign spec to non-existant mob # +9. No associated object exists when attempting to create a board [vnum #]. +10. SYSERR: Mob using >'((ch)-)player_specials.... +11. SYSERR: Object # (keyword) is type NOTE and has extra description with same name (keyword) 1: Errant Rooms @@ -44,30 +43,23 @@ the drink aliases). i.e. a shot of whisky should have the namelist: whisky shot whisky a cup of slime mold juice namelist should be: juice cup slime juice -3: SYSERR: Mob # both Aggressive and Aggressive_to_Alignment. - - Another harmless error. If your mob is aggressive there is no need to also -make it aggressive to certain alignments since AGGR means it will attack any -player it can see. Choose to make it aggressive to an alignment or aggressive -to all. - -4: SYSERR: Object # (oedit-s-desc) has out of range level #. +3: SYSERR: Object # (oedit-s-desc) has out of range level #. A simple one. Limit spell levels to the levels available, on tbaMUD that would be 1-34. -5: SYSERR: Object # (oedit-s-desc) has negative weight (-2147483644). +4: SYSERR: Object # (oedit-s-desc) has negative weight (-2147483644). SYSERR: Object # (oedit-s-desc) has out of range level #2147483647. These are really annoying. This happens on older versions of CircleMUD when you use numbers larger than necessary. This will actually crash many older versions of CircleMUD. Just do not do it. Use realistic numbers. -6: SYSERR: Object # (oedit-s-desc) uses 'UNDEFINED' spell #. +5: SYSERR: Object # (oedit-s-desc) uses 'UNDEFINED' spell #. There is no spell zero. Either select a spell or put -1 for none. -7: SYSERR: Object # (oedit-s-desc) contains (#) more than maximum (#). +6: SYSERR: Object # (oedit-s-desc) contains (#) more than maximum (#). When making a drink container you will set how much it initially contains on creation and the max it can hold if a player were to fill it. Common sense @@ -75,24 +67,24 @@ tells us that you can not create a container that initially holds more than the max you set. To simplify the max must always be greater than or equal to the initial amount. -8: Char is already equipped: (medit-s-desc), (oedit-s-desc) +7: Char is already equipped: (medit-s-desc), (oedit-s-desc) This happens when someone tries to equip a mob with one or more object in a single location. HELP ZEDIT-EQUIP for all the possible object equipping locations. All you have to do to fix this is pick a different equip location that is not used. -9: SYSERR: Attempt to assign spec to non-existant mob # +8: SYSERR: Attempt to assign spec to non-existant mob # To get rid of this "grep # spec_assign.c" and remove this assignment. -10: No associated object exists when attempting to create a board [vnum #]. +9: No associated object exists when attempting to create a board [vnum #]. You need to delete this board from lib/etc/boards/ and modify boards.c and boards.h. Again "grep #" *.[ch] to search for this vnum in all of your .c and .h files to remove the reference. -11: SYSERR: Mob using >'((ch)-)player_specials.... +10: SYSERR: Mob using >'((ch)-)player_specials.... Players and mobs (NPC's) share many of the same data fields, but not all. So when a mob tries to access player data it gives a SYSERR like this: @@ -110,7 +102,7 @@ know this is confusing, but just copy the example below. The changed line now will not just check for a flag, instead it will check if it is a player (not an NPC) and it is flagged then continue. -12: SYSERR: Object # (keyword) is type NOTE and has extra description with +11: SYSERR: Object # (keyword) is type NOTE and has extra description with same name (keyword) Object type NOTE is meant to be written on using the action-description. So if diff --git a/lib/misc/messages b/lib/misc/messages index dacd493..1f4a4bb 100644 --- a/lib/misc/messages +++ b/lib/misc/messages @@ -308,7 +308,7 @@ You receive a punch in your kidneys which ends your worldly misery -- R.I.P.! $n punches $N in the kidneys causing immediate death! You wildly punch at the air, missing $N. $n misses a wild punch at you. -$n practices shadow-boxing while $N takes a break. +$n shadow-boxes while $N takes a break. # # # @@ -861,4 +861,3 @@ $N is hit by $n's lightning breath. $N is immortal and immune to lightning breath. $n tries to breath lightning upon you. $n tries to breath lightning upon $N. - diff --git a/lib/text/help/help.hlp b/lib/text/help/help.hlp index 80f2657..5c121b7 100644 --- a/lib/text/help/help.hlp +++ b/lib/text/help/help.hlp @@ -315,27 +315,35 @@ Situational: cover (+2/+5), spells (Shield, Haste, etc.) See Also: SCORE #0 -ACAUDIT ARMOR-AUDIT AUDIT-ARMOR IMMORTAL +AUDIT ARMOR AUDIT-ARMOR AUDIT AC AUDIT-AC ACAUDIT AUDIT MELEE AUDIT-MELEE IMMORTAL - Summary: Imm-only tool that scans all ITEM\_ARMOR prototypes and reports -per-piece fields against slot caps. Use this to catch outliers and quickly -rebalance items to the Light/Medium/Heavy targets. + Summary: Imm-only tool that scans armor and weapons for invalid config. Usage: -acaudit +audit armor|melee -What it does: +What auditing armor does: Scans prototypes for armor slots (head, body, legs, arms, hands, feet) and prints one line per item: -\[#VNUM] slot= ac=\ bulk= mag=+ flags= +[#VNUM] sl= ac= b= m= sd=<0/1> str= Markers: -OVER : value exceeds the slot’s hard cap (e.g., piece AC > slot max, or -magic > slot max) -WARN : value outside 0..3 (invalid for piece AC, bulk, or magic) -(STEALTHDISADV): flag is set (the piece imposes Stealth Disadvantage) +R! : value exceeds the slot’s hard cap (e.g., piece AC > slot max, or + magic > slot max) +Y? : value outside 0..3 (invalid for piece AC, bulk, or magic) +sd=1 : piece imposes Stealth Disadvantage + +What auditing melee weapons does: + +Scans melee weapon prototypes and reports attack type, damage (1d4/1d6/1d8/ +1d10/1d12), and weight. + +Melee markers: + +R! : attack type is missing/invalid or damage is not 1d4/1d6/1d8/1d10/1d12 +Y? : weight is 0 or less Notes: @@ -356,7 +364,7 @@ Medium : AC \~14–18 Heavy : AC \~16–20 See Also: ARMOR PIECES, BULK, SHIELDS, MAGIC CAPS, SCORE, OEDIT ARMOR -#32 +#2 ACRONYMS TERMINOLOGY VOCABULARY Here are some common terms used in building, and TBA zone: @@ -472,7 +480,7 @@ set one of these: P) Perm Affects: @cNOBITS@n 1) BLIND DO NOT USE. 2) INVIS The wearer becomes invisible. -3) DET-ALIGN The wearer detects alignments. +3) RESERVED DO NOT USE. 4) DET-INVIS The wearer sees invisible objects and players. 5) DET-MAGIC The wearer sees a magic flag on magical objects. 6) SENSE-LIFE The wearer sees hidden mobs/players. @@ -482,15 +490,15 @@ P) Perm Affects: @cNOBITS@n 10) CURSE DO NOT USE. 11) INFRA The wearer sees in the dark. 12) POISON The wearer is poisoned. -13) PROT-EVIL The wearer is protected from evil. -14) PROT-GOOD The wearer is protected from good. +13) RESERVED DO NOT USE. +14) RESERVED DO NOT USE. 15) SLEEP DO NOT USE. 16) NO_TRACK DO NOT USE. 17) FLYING The wearer can travel through room sector type IN FLIGHT. 18) SCUBA The wearer can travel through room sector type UNDERWATER. 19) SNEAK DO NOT USE. 20) HIDE DO NOT USE. -21) UNUSED DO NOT USE. +21) SCAN Actively scanning for hidden threats. 22) CHARM DO NOT USE. #2 @@ -570,45 +578,6 @@ I would type "all 13" to list everything in zone 13. I use this to check what people have done with their zone. See also: ^, RUMBLE-ALIASES -#0 -ALIGNMENT GOOD NEUTRAL EVIL %ACTOR.ALIGN% %ALIGN% %ALIGNMENT% - - Different characters and mobs have different alignments depending upon their -way of life. Because of this, they may be aggressive or friendly depending on -the mix. Some objects cannot be used by certain alignments. For mobs alignment -ranges from: - - -1000 to -350 Evil - -350 to 350 Neutral - 350 to 1000 Good - -See also: ALIGNMENTS -#2 -ALIGNMENTS - - Many good areas stick to a defined level range, such as 10-20 or 25-30. Do -not try and make your new area cover the entire range of levels. Every area -should have its moment in the sun. Conversely, it would be nice if there were -something really unique and challenging to do at every stage in a characters -history. Your area might be the most successful if you can gear it for a range -of levels that people believe is otherwise boring or neglected. - You should always try to match your mobiles to the area and the players you -want to play there. For example, you should make the mobs in the area a -similar level to the players you want to play there since a level X warrior -should be able to kill a level X mobile if the warrior is at full health. Also, -the quality of objects or mobiles should be matched with their level. - Will your area be mostly good, neutral, or evil. If it is mostly good or -mostly evil, is it strongly good or evil or just weakly aligned? In any case -try not to make your area completely homogenous (equal). In neutral -communities there is going to be some evil and good elements, and likewise with -other communities. To some extent this goes along with the question about zone -level, consider what seem to be "gaps" among the zones in the world as far as -good or evil aligned areas for a particular level range, and try to fill those -needs. Everyone's first tendency is to make extremists--The ultimate evil hell -area, or the blindingly good paladin fortress. Keep in mind that there are -many layers in between, and these are often more interesting. - -See also: ALIGN #2 ANIMATE-DEAD @@ -930,9 +899,8 @@ Backstab is a way to sneak up on a person and attempt to place your dagger in his back, at exactly the point where it does most damage. A successful backstab gives a damage multiplier, depending on your level: -The chance of successfully backstabbing a person depends on how well you -have practiced backstab at your guild. You can always backstab sleeping -people. +The chance of successfully backstabbing a person depends on your backstab +skill. You can always backstab sleeping people. #0 BALANCE BALANCING @@ -1007,7 +975,7 @@ BASH Fighters only. -The success of a bash depends upon how many times you have practiced. To bash +The success of a bash depends on your bash skill. To bash someone is to attempt to 'knock' that person over. If you succeed, you will inflict minor damage, and cause the victim to fall on its rear. The victim will be unable to issue any commands for 2 rounds of violence. If you miss @@ -1647,9 +1615,8 @@ Excluding the subfield () returns the value. Adding a subfield adjusts it. @uField@n - @uvariable returns:@n cha/con/dex/int - Checks the stat. @RHELP TRIG-STAT@n. Subfield adjusts. -str/stradd/wis() () is a subfield and allows a change to the variable. +str/wis() () is a subfield and allows a change to the variable. alias - The list of aliases of the mob or the player name. -align() - The actor's alignment @RHELP ALIGN@n. Subfield adjusts. affect() - Checks the actor for the affect. @RHELP AFFECT@n armor - Checks the actor's armor class. canbeseen - Checks if the the mob can see the actor. @RHELP CANBESEEN@n @@ -1677,14 +1644,15 @@ mana() - The current mana points of the actor. Subfield adjusts. master - The master of the actor (as an id), or an empty return. maxhitp() - The maximum hit points of the actor. Subfield adjusts. maxmana() - The maximum mana points of the actor. Subfield adjusts. -maxmove() - The maximum movement points of the actor. Subfield adjusts. -move() - The movement points of the actor. Subfield adjusts. +maxstamina() - The maximum stamina points of the actor. Subfield adjusts. +stamina() - The stamina points of the actor. Subfield adjusts. +maxmove() - Alias for maxstamina(). +move() - Alias for stamina(). name - The actor's name (the short description for mobs). next_in_room - The next mob/player in the room as a variable (id) nice to use for loops, or an empty return @RTSTAT 23@n pos() - %actor.pos% returns position. Subfield modifies. Sleeping, resting, sitting, fighting, standing. @RTSTAT 1399, 20997@n -prac() - The actor's number of practices. Subfield adjusts. pref() - Checks if actor has PRF flag enabled. @RTSTAT 1210@n quest - Returns the current quest (or 0 if there's no current quest). questdone(#) - Returns TRUE (1) if the quest vnum (#) has been completed. @@ -1697,8 +1665,6 @@ saving_breath() - The actors saving throw for breath weapons. Subfield adjusts. saving_spell() - The actors saving throw for spells. Subfield adjusts. sex - The actor's sex, as a string: MALE, FEMALE, or NEUTRAL. skill() - The percentage of learnedness in the skill subfield. -skillset("" #) - Set the actors practiced level any skill or spell (1-100). - %actor.skillset("magic missile" 95)%. thirst() - The actor's thirst. Subfield sets, -1 is off. title() - The actor's title. Subfield sets. Not used for mobs. varexists() - Returns 1 if global variable in subfield exists, 0 if not. @@ -1749,7 +1715,7 @@ Checking load info for the beastly fido... [ 3012] Main Street (15 Max.) > checkload t 100 -Checking load info for the object trigger 'Portal to Midgaard - 100': +Checking load info for the object trigger 'Portal to the Capital - 100': (obj) [ 100] the portal See also: LINKS, RLIST, OLIST, MLIST, SLIST @@ -1845,11 +1811,11 @@ Clerics have an ancient belief in not carrying sharp weapons. Hence, they can only wield bludgeoning weapons. This class gives you the wisdom of peace, blessing and healing, though it is possible to learn more violent spells. -You can improve your spells by using the practice command. +You can improve your spells by using them. See @RHELP SPELLS@n for a list of spells available. -See also: PRACTICE, SPELLS +See also: SPELLS #0 CLSOLC @@ -2366,18 +2332,6 @@ detach obj sword 1300 - You guessed it - same as above. detach sword all - detach all triggers from the sword. See also: ATTACH, TRIG-DETACH, TRIG-ATTACH, OLC, TRIGEDIT, TSTAT, STAT, ROOMFLAGS -#2 -DETECT-ALIGNMENT - -Usage : cast 'detect alignment' -Accumulative: Yes (Duration) -Duration : 12 hours + level -Level : Cleric level 4. - -Allows the caster to detect the alignment of those around them. -Evil will show as a red aura, good in a blue aura. - -See also: "DETECT INVISIBILITY" #0 DETECT-INVISIBILITY @@ -2530,48 +2484,16 @@ when done type /fi to format with indent. See also: TEXT-EDITOR -#2 -DISPEL-EVIL - -Usage : cast 'dispel evil' -Accumulative: - -Duration : Instantaneous -Level : Cleric level 14. -Save : Special - -This spell will only affect evil creatures. An evil person of level -equal or less than caster will suffer 100 damage points. - -If the victim is higher level than caster, the spell will inflict -(caster_level)d4 damage points, saving throw versus half damage. - -See also: DISPEL-GOOD -#0 -DISPEL-GOOD - -Usage : cast 'dispel good' -Accumulative: - -Duration : Instantaneous -Level : Cleric level 14. -Save : Special - -This spell will only affect good creatures. A good person of level -equal or less than caster will suffer 100 damage points. - -If the victim is higher level than caster, the spell will inflict -(caster_level)d4 damage points, saving throw versus half damage. - -See also: DISPEL-EVIL #0 DISPLAYS PROMPTS HIT-PNT-DISPLAY -Usage: prompt < H | M | V | all | auto | off > +Usage: prompt < H | M | S | all | auto | off > -Modify your prompt to show your hit points, mana, and/or movement points. +Modify your prompt to show your hit points, mana, and/or stamina points. - > prompt hv Display hit points and movement points. + > prompt hs Display hit points and stamina points. > prompt off Return to no prompt. - > prompt all Display hit, mana, and movement points. + > prompt all Display hit, mana, and stamina points. > prompt auto A separate toggle that will only display your selected prompt if the values drop below 30% of max. @@ -2825,30 +2747,23 @@ of CircleMUD expect it first). i.e. a shot of whisky should have the keyword: whisky shot whisky a cup of slime mold juice keyword should be: juice cup slime juice -3: SYSERR: Mob #5 both Aggressive and Aggressive_to_Alignment. - - Another harmless error. If your mob is aggressive there is no need to also -make it aggressive to certain alignments since AGGR means it will attack any -player it can see. Choose to make it aggressive to an alignment or aggressive -to all. - -4: SYSERR: Object # (oedit-s-desc) has out of range level #. +3: SYSERR: Object # (oedit-s-desc) has out of range level #. A simple one. Limit spell levels to the levels available, on TBA that would be 1-30. -5: SYSERR: Object # (oedit-s-desc) has negative weight (-2147483644). +4: SYSERR: Object # (oedit-s-desc) has negative weight (-2147483644). SYSERR: Object # (oedit-s-desc) has out of range level #2147483647. These are really annoying. This happens when you use numbers larger than necessary. This will actually crash many older versions of CircleMUD. Just do not do it. Use realistic numbers. -6: SYSERR: Object # (oedit-s-desc) uses 'UNDEFINED' spell #. +5: SYSERR: Object # (oedit-s-desc) uses 'UNDEFINED' spell #. There is no spell zero. Either select a spell or put -1 for none. -7: SYSERR: Object # (oedit-s-desc) contains (5) more than maximum (3). +6: SYSERR: Object # (oedit-s-desc) contains (5) more than maximum (3). When making a drink container you will set how much it initially contains on creation and the max it can hold if a player were to fill it. Common sense @@ -2930,7 +2845,7 @@ Objects : 42 Triggers : 129 Theme : Its purpose, hack & slash, quest, rescue princess, kill ogre... Completion : When do you expect to finish it, how is the progress going? -Notes : Such things as zone alignment, economy, quests, special mobs and +Notes : Such things as zone economy, quests, special mobs and objs, and anything else I should know about your zone. What makes it unique? @@ -2985,8 +2900,8 @@ right. Parenthesis can be used to create priority. | | | (if actor age is not equal to 1) | < | less than | if %actor.dex% < 16 | | | (if actor dexterity is less than 16) -| > | greater than | if %actor.align% > 349 -| | | (if actor alignment is greater than 349) +| > | greater than | if %actor.level% > 30 +| | | (if actor level is greater than 30) | <= | less than or equal | if %actor.exp% <= 2 | | | (if actor experience is less than or equal to 1) | >= | greater than or equal | if %actor.mana% >= 1 @@ -4033,7 +3948,7 @@ INFORMATION The following commands deal with information - for more info, @RHELP KEYWORD@n RULES POLICY - The rules of the game. -SCORE AFFECTS COINS TOGGLE PRACTICE - Info about yourself and your settings. +SCORE AFFECTS COINS TOGGLE - Info about yourself and your settings. HELP INFO NEWS MOTD IMOTD - Info about the game, recent changes. WHO WHERE CONSIDER FLAGS TITLE - Info on other players. TIME DATE - Info on time. @@ -4534,7 +4449,7 @@ OBJECT STANDARDS: |Age | 10 | -10 | |Weight | 50 | 1 | |Cost | 1000 | 1 | -|Hitpoints, Mana, Movement | 50 | -50 | +|Hitpoints, Mana, Stamina | 50 | -50 | |Coins | Do not use. | |Experience | Do not use. | |Armor Class Values | 10 | -10 | @@ -4773,11 +4688,11 @@ MAGIC-USER WIZARD MAGE This is the class of powerful and violent magic, but the magic user do not control the nature, and can therefore not bless and such. -You can improve your spells by using the practice command. +You can improve your spells by using them. See @RHELP SPELLS@n for a list of spells available. -See also: PRACTICE, SPELLS +See also: SPELLS #0 MAKEUID UID UNIQUE @@ -4852,7 +4767,7 @@ MEDIT-AFF-FLAGS AFFECTIONS AFFECTS M) AFF Flags : @cNOBITS@n 1) BLIND Mob is blind. 2) INVIS Mob is invisible. -3) DET-ALIGN NOT USED. +3) RESERVED NOT USED. 4) DET-INVIS Mob can see invisible characters and objects. 5) DET-MAGIC Mob is sensitive to magical presence. 6) SENSE-LIFE Mob can sense hidden life. @@ -4863,15 +4778,15 @@ M) AFF Flags : @cNOBITS@n 10) CURSE Mob is cursed. 11) INFRA Mob can see in dark. 12) POISON Reserved for internal use. Do not set. -13) PROT-EVIL Mob is protected from evil characters. -14) PROT-GOOD Mob is protected from good characters. +13) RESERVED NOT USED. +14) RESERVED NOT USED. 15) SLEEP Reserved for internal use. Do not set. 16) NO_TRACK Mob cannot be tracked. 17) FLY Mob is flying. 18) SCUBA Mob can breathe underwater. 19) SNEAK Mob can move quietly without room being informed. 20) HIDE Mob is hidden; can only be seen with sense life. -21) UNUSED Unused (room for future expansion). +21) SCAN Actively scanning for hidden threats. 22) CHARM Reserved for internal use. Do not set. See also: INVIS, MEDIT-NPC-FLAGS, DG_AFFECT, TRIG-AFFECT @@ -4903,20 +4818,9 @@ should be one of the following numbers: 5) bludgeon #2 -MEDIT-EXPERIENCE MEDIT-XP MEDIT-ALIGNMENT +MEDIT-EXPERIENCE MEDIT-XP -(B) Exp Points: [ 115600] (E) Alignment: [ 1000] - -Alignment -A number from -1000 to 1000 representing the mobs initial alignment. - -Evil -1000 to -350 -Neutral -349 to 349 -Good 350 to 1000 - -The alignment of a mobile is determined entirely by you, depending on -the type of area you are creating. The alignment can be from -1000 -(extremely evil) to +1000 (divinely good). +(B) Exp Points: [ 115600] Experience is simply the number of experience points the mobile is born with. This is not the exact number of experience points the player will get @@ -5019,7 +4923,7 @@ X) Delete Mob @RHELP MEDIT-DELETE@n Q) Quit Enter choice : #2 -MEDIT-NPC-FLAGS MEDIT-FLAGS SPEC STAYZONE AGGRESSIVE AGGR_GOOD AGGR_NEU AGGR_EVIL STAY-ZONE STAY_ZONE SCAVENGER NPCFLAGS NPC-FLAGS MOBFLAGS MOB-FLAGS SENTINEL AWARE NOCHARM MOB-NPC NPC_FLAGS HELPER +MEDIT-NPC-FLAGS MEDIT-FLAGS SPEC STAYZONE AGGRESSIVE STAY-ZONE STAY_ZONE SCAVENGER NPCFLAGS NPC-FLAGS MOBFLAGS MOB-FLAGS SENTINEL AWARE NOCHARM MOB-NPC NPC_FLAGS HELPER NPC stands for non-player-character (mob) @@ -5042,9 +4946,9 @@ L) NPC Flags : @cISNPC@n its hit points. If the WIMPY bit is set in conjunction with any of the forms of the AGGRESSIVE bit, the mob will only attack mobs that are unconscious (sleeping or incapacitated). -8) AGGR_EVIL Mob will attack players that are evil-aligned. -9) AGGR_GOOD Mob will attack players that are good-aligned. -10) AGGR_NEU Mob will attack players that are neutrally aligned. +8) RESERVED Not used. +9) RESERVED Not used. +10) RESERVED Not used. 11) MEMORY Mob will remember players that initiate attacks on it, and will attack that player if it ever runs into him again. 12) HELPER The mob will attack any player it sees in the room that is @@ -5332,7 +5236,7 @@ MOBILE-FORMATS MOB-FORMATS MOB-FILES ~ ~ - + @@ -5382,11 +5286,11 @@ Message List: 0 ) [5 ] 1, burning hands 30) [314] 2, Unknown 1 ) [6 ] 1, call lightning 31) [399] 2, Unknown 2 ) [8 ] 1, chill touch 32) [33 ] 1, poison -3 ) [10 ] 1, color spray 33) [202] 1, !UNUSED! -4 ) [22 ] 1, dispel evil 34) [203] 1, !UNUSED! -5 ) [23 ] 1, earthquake 35) [204] 1, !UNUSED! -6 ) [25 ] 1, energy drain 36) [205] 1, !UNUSED! -7 ) [26 ] 1, fireball 37) [206] 1, !UNUSED! +3 ) [10 ] 1, color spray 33) [202] 1, !RESERVED! +4 ) [22 ] 1, dispel 34) [203] 1, !RESERVED! +5 ) [23 ] 1, earthquake 35) [204] 1, !RESERVED! +6 ) [25 ] 1, energy drain 36) [205] 1, !RESERVED! +7 ) [26 ] 1, fireball 37) [206] 1, !RESERVED! ========================================= MSG #, SKILL NUMBER, NUMBER OF ENTRIES, NAME (if applicable) 0 ) [5 ] 1, burning hands @@ -5451,7 +5355,7 @@ Usage: murder [target] Kill command to hit another player. To avoid accidental flagging (i.e. trying to type kiss Nia but accidentally typing kill Nia). -See also: FLAGS +See also: SKILLS #0 MUTE SQUELCH @@ -5461,12 +5365,13 @@ Usage: mute MUTE is used to prevent a player from using global communication channels. It is a toggle that can be turned on and off by the same command. -See also: FLAGS +See also: SKILLS #2 -MV MOVEPOINTS MOVE-POINTS MOVEMENTPOINTS MOVEMENT-POINTS +STAMINA STAMINA-POINTS STAMINAPOINTS MV MOVEPOINTS MOVE-POINTS MOVEMENTPOINTS MOVEMENT-POINTS - Depending on the type of terrain your character will tire from too much -traveling and require some rest to continue. + Stamina points measure how tired you are. Depending on the type of terrain, +your character will tire from too much traveling and require some rest to +continue. See also: MANA, HITPOINTS #0 @@ -5828,7 +5733,7 @@ applies. Suggested object standards are displayed at the end of each apply 12) CHAR_HEIGHT Apply to height. 13) MAXMANA Apply to MAX mana points. 14) MAXHIT Apply to MAX hit points. -15) MAXMOVE Apply to MAX movement points. +15) MAXSTAMINA Apply to MAX stamina points. 16) COINS Unimplemented. Do not use. 17) EXP Unimplemented. Do not use. 18) ARMOR Apply to armor class (AC). negative is better. @@ -5894,36 +5799,17 @@ OEDIT-EXTRA-FLAGS OEDIT-FLAGS OBJECT-FLAGS OBJECTFLAGS GLOW HUM NODROP NO_DROP O 1) GLOW Item is glowing (cosmetic). 2) HUM Item is humming (cosmetic). +3) UNUSED Reserved (unused). 4) NODONATE Item cannot be donated. 5) NOINVIS Item cannot be made invisible. 6) INVISIBLE Item is invisible. 7) MAGIC Item has a magical aura and cannot be enchanted. 8) NODROP Item is cursed and cannot be removed or dropped. 9) BLESS Item is blessed (cosmetic). -10) ANTI_GOOD Item cannot be used by good-aligned characters. -11) ANTI_EVIL Item cannot be used by evil-aligned characters. -12) ANTI_NEUTRAL Item cannot be used by neutral align characters. -13) ANTI_MAGIC_USER Item cannot be used by the Mage class. -14) ANTI_CLERIC Item cannot be used by the Cleric class. -15) ANTI_THIEF Item cannot be used by the Thief class. -16) ANTI_WARRIOR Item cannot be used by the Warrior class. -17) NOSELL Shopkeepers will not buy or sell the item. -18) QUEST_ITEM Shopkeepers will only accept questpoints for this item. - - Always try to promote role-playing. The last thing you should do is have -Thieves running around wearing dangly bracelets making noise, Clerics and Mages -wearing large suits of armor and Warriors wearing delicate clothing. None of -that makes sense! So, use your head a little while creating equipment. If the -equipment gives addition hitpoints then it should probably be made of metal and -should be geared for Warrior types. We do not need Mages out there with bonus -hitpoints on all their eq. - Class and Race restrictions are very important. Be sure to know what your -MUD uses for both and build for them. For example, a Minotaur would not wear -a regular helmet on his head. Minotaurs take pride in their horns, so their -horns must be showing. Minotaurs also have hooves for feet. It would be tough -for most to wear regular boots. Use some common sense when creating your -equipment. Think about each object you create. Think about who you are creating -it for. +10) NOSELL Shopkeepers will not buy or sell the item. +11) QUEST_ITEM Shopkeepers will only accept questpoints for this item. +12) HOOD_UP WORN item hood is currently up. +13) SKINNED Item/corpse can be skinned. #2 OEDIT-ITEM-NUMBER OEDIT-NUMBER @@ -6515,7 +6401,7 @@ this method is that if you accidentally wipe out your work on the MUD you will have a ready backup. Be careful cutting and pasting to the MUD; if you send too much text at once you will be disconnected. -See also: WORK, CARTOGRAPHY, LOCATION, THEME, PLOT, SIZE, ALIGN, BIAS +See also: WORK, CARTOGRAPHY, LOCATION, THEME, PLOT, SIZE, BIAS #2 PLAYER-SHOPS PLAYER-OWNED-SHOPS @@ -6728,22 +6614,6 @@ game and will have to be redone. This is typical of people who are power hungry and are building for themselves and not for others. That is not a sign of a good builder (see @RHELP BUILDER@n). -#2 -PRACTICE PRACTISE TRAINING GUILDS GUILDMASTERS PRACTICING EXPERIENCES - -Usage: practice [skill or spell name] - -Practice is the way you improve your spells and skills. You can only do -so in a guild, where a guildmaster can help you train. You learn new skills -as you gain levels. A guildmaster can be found throughout the realms and will -charge you for your training. - -If you type practice anywhere other than with a guildmaster, you will get a -list of all of the spells and skills you know and your level of proficiency at -each. - -See also: SPELLS, SKILLS, LEVELS -#0 PRAISE REVIEWS RATINGS Review Submitted By: Detta @@ -7020,7 +6890,7 @@ NO_SHOUT - Player can not see shouts. NO_TELL - Player can not see tells. D_HP - Player can see their HP. D_MANA - Player can see their MANA. -D_MOVE - Player can see their MOVE. +D_STAMINA - Player can see their Stamina. AUTOEX - Player can see exits. NO_HASS - Builder is safe from aggressive mobs, triggers will not work. QUEST - Player is on a quest. @@ -7094,7 +6964,7 @@ what it takes to properly plan out your first zone. It is extremely important that you put some forethought into what you will be creating. Remember, zones are built for others to play. Be sure to make it something a player will enjoy. A zone proposal consists of an informal MUDmail to your Head Builder. It should -contain: the location, level, alignment, theme, plot, size, and any other +contain: the location, level, theme, plot, size, and any other important notes about the zone. Detailed descriptions and help files are available in the hallways starting from room 14 and 15. @@ -7104,15 +6974,6 @@ deadlines, so take the time to give your zone character. Required Reading: @RHELP PLANNING, HELP STYLISTICS@n See also: EXAMPLE-PROPOSAL -#2 -PROTECTION-FROM-EVIL PROT-EVIL - -Usage : cast 'protection from evil' [self] -Accumulative: Yes (Duration) -Duration : 24 hours -Level : Cleric level 8. - -The meaning of this spell is not yet fully defined. #0 PURGE DESTROY UNLOAD DELETE-MOBILE DISINTEGRATE DECOMPOSE CLEANUP @@ -7186,7 +7047,7 @@ large dragon steak. These are normally acquired from the large green dragons up on Wyrm Mountain. My normal source got eaten last week, and I have a large order to fill. I need these within 24 hours -Thanks, Bob the Butcher, Midgaard +Thanks, Bob the Butcher, the capital The questmaster sighs. The questmaster says "A tricky quest, but it'll cost you 5qp to back out now" #2 @@ -7766,10 +7627,10 @@ and VNUM have the same first few numbers. REDIT-SECTOR-TYPE SECTORS SECTOR-TYPE TERRAIN-TYPE FIELDS FORESTS REDIT-SECTOR-FLAGS SCUBA UNDERWATER 4) Sector type : @cInside@n - This defines movement point, light, and boat requirements. + This defines stamina point, light, and boat requirements. The following terrains may be selected (only one): - Movement Points + Stamina Points 1) Inside Indoors (no light required) 1 2) City The streets of a city. 1 3) Field An open field. 2 @@ -7929,7 +7790,7 @@ ever seen. I have never seen anyone put so much work into a zone. Kudos to Justo I am saving this because I would like everyone to use Justo's work as an outstanding example of how a builder should develop and plan a full zone. - * * * * Midgaard Mail System * * * * + * * * * City Mail System * * * * Date: Sun Oct 13 10:33:59 2002 To: rumble From: justo @@ -7977,7 +7838,15 @@ From: justo #2 REROLL -Usage: reroll +Usage: reroll + reroll undo + +Reroll lets you roll a new set of stats once. Your original stats are saved +for 2 hours; during that window you may use 'reroll undo' to restore them. +After the review period or after using reroll undo, your stats are permanent +and you cannot reroll again. + +Immortals: reroll rerolls that player's stats. REROLL gives a player new stats (i.e., Str, Int, Wis, Dex, Con, and Cha) @@ -8004,7 +7873,7 @@ RESTORE REVIVE Usage: restore - RESTORE restores a player or mobile to full hit, mana, and movement points. + RESTORE restores a player or mobile to full hit, mana, and stamina points. Restore all will restore all players in the game. If used on immortals, it also sets all skill levels to 100%. @@ -8133,7 +8002,7 @@ SCORE Summary: Score provides useful information about your character that you would find on a traditional tabletop character sheet. Examples: -HP, Mana, and Movement points +HP, Mana, and Stamina points Strength, Dexterity, Constituion, Intelligence, Wisdom, and Charisma scores Armor Class with breakdown Stealth Disadvantage @@ -8403,12 +8272,12 @@ Enter choice : SEDIT-TRADE E) No Trade With : @cNOBITS@n - Designates certain alignments or classes that the shop will not trade with: + Designates certain classes that the shop will not trade with: - 1) Good 2) Evil - 3) Neutral 4) Magic User - 5) Cleric 6) Thief - 7) Warrior + 1) Sorceror 2) Cleric + 3) Rogue 4) Fighter + 5) Barbarian 6) Ranger + 7) Bard 8) Druid Currently will not trade with: @cNOBITS@n Enter choice (-1 for none): @@ -8514,14 +8383,13 @@ hunger Imm BOTH MISC int Imm BOTH NUMBER invis God PC NUMBER invstart Imm PC BINARY -killer God PC BINARY level GrGod BOTH NUMBER loadroom Imm PC MISC mana Imm BOTH NUMBER maxhit Imm BOTH NUMBER maxmana Imm BOTH NUMBER -maxmove Imm BOTH NUMBER -move Imm BOTH NUMBER +maxstam Imm BOTH NUMBER +stam Imm BOTH NUMBER name Imm PC MISC nodelete God PC BINARY nohassle God PC BINARY @@ -8531,7 +8399,6 @@ olc GrGod PC MISC password GrGod PC MISC poofin Imm PC MISC poofout Imm PC MISC -practices God PC NUMBER quest God PC BINARY questhistory God PC NUMBER questpoints God PC NUMBER @@ -8541,8 +8408,6 @@ sex God BOTH MISC showvnums Imm PC BINARY siteok God PC BINARY str Imm BOTH NUMBER -stradd Imm BOTH NUMBER -thief God PC BINARY thirst Imm BOTH MISC title God PC MISC variable GrGod PC MISC @@ -8711,11 +8576,11 @@ The following room flags can be selected: 16) * - DO NOT USE. Breadth-first search mark used by track and hunt. 17) WORLDMAP - DO NOT USE. World Map style maps. -Never set UNUSED or DO NOT USE bits, if you find them anywhere. If you +Never set RESERVED or DO NOT USE bits, if you find them anywhere. If you do not know what a flag does, DO NOT SET IT! This requires repeating since it is so often ignored: - @YIf a flag says UNUSED; DO NOT SET IT. If you do not know what it does; DO NOT SET IT!@n + @YIf a flag says RESERVED; DO NOT SET IT. If you do not know what it does; DO NOT SET IT!@n See Also: TOGGLE #2 @@ -8952,7 +8817,7 @@ SPECIALS SPEC-PROC SPECIAL-PROCEDURES SPECPROC SPEC_PROC mobs, and objects. They are written by coders and are normally not created by builders. If you have something you wish to assign a special procedure to talk it over with a coder. The most common special procedures include: -Postmasters, banks, guildmasters, pet shops, and boards. If your zone requires +Postmasters, banks, pet shops, and boards. If your zone requires any of the above mudmail your coder after your zone is complete. Most of the things possible through special procedures can now be done through trigedit. @@ -8961,12 +8826,6 @@ To create a postmaster make a mob, set one of the keywords as "postmaster," set the NPC flag SPEC, and load it to the room via zedit. Then have your coder add to spec_assign.c:110: ASSIGNMOB(#, postmaster); NOTE: # = the mob/obj vnum. -To create a guildmaster make a mob, set one of the keywords as "guildmaster," -set the NPC flag SPEC, and load it to the room via zedit. Then have your coder -add to spec_assign.c:69: ASSIGNMOB(#, guild); A player can practice at any -guildmaster, it is the guildguards that usually limit who can access what -guildmaster. @RTSTAT 133@n - To create a bank make an object, set it to type OTHER, add keyword "bank" and load it to the room via zedit. Then have your coder add to spec_assign.c: 138: ASSIGNOBJ(#, bank); @@ -8981,7 +8840,7 @@ In all cases special procedures need to be added in by a coder. Once your zone is complete mudmail your coder for the additions you want including type and mob or object vnum. -See also: POSTMASTER, PETSHOPS, BANKS, GUILDMASTER, BOARDS +See also: POSTMASTER, PETSHOPS, BANKS, BOARDS #2 SPELLS @@ -8990,18 +8849,18 @@ SPELLS 7) charm person 8) chill touch 9) clone 10) color spray 11) control weather 12) create food 13) create water 14) cure blind 15) cure critic -16) cure light 17) curse 18) detect alignment +16) cure light 17) curse 18) reserved 19) detect invisibility 20) detect magic 21) detect poison -22) dispel evil 23) earthquake 24) enchant weapon +22) reserved 23) earthquake 24) enchant weapon 25) energy drain 26) fireball 27) harm 28) heal 29) invisibility 30) lightning bolt 31) locate object 32) magic missile 33) poison -34) protection from evil 35) remove curse 36) sanctuary +34) reserved 35) remove curse 36) sanctuary 37) shocking grasp 38) sleep 39) strength -40) summon 41) !UNUSED! 42) word of recall +40) summon 41) !RESERVED! 42) word of recall 43) remove poison 44) sense life 45) animate dead -46) dispel good 47) group armor 48) group heal -49) !UNUSED! 50) infravision 51) waterwalk +46) reserved 47) group armor 48) group heal +49) !RESERVED! 50) infravision 51) waterwalk 52) identify #2 @@ -9014,13 +8873,13 @@ SPELLS MAGICS SPELLBOOKS TOMBS SPELL-LEVELS SPELLS-STOCK SPELLLIST | Detect Magic 2 | Create Food 2 | | Chill Touch 3 | Create Water 2 | | Infravision 3 | Detect Poison 3 | -| Invisibility 4 | Detect Alignment 4 | +| Invisibility 4 | Reserved 4 | | Armor 4 | Cure Blind 4 | | Burning Hands 5 | Bless 5 | | Locate Object 6 | Detect Invisibility 6 | | Strength 6 | Blindness 6 | | Shocking Grasp 7 | Infravision 7 | -| Sleep 8 | Protection from Evil 8 | +| Sleep 8 | Reserved 8 | | Lightning Bolt 9 | Poison 8 | | Blindness 9 | Group Armor 9 | | Detect Poison 10 | Cure Crit 9 | @@ -9030,8 +8889,8 @@ SPELLS MAGICS SPELLBOOKS TOMBS SPELL-LEVELS SPELLS-STOCK SPELLLIST | Poison 14 | Word of Recall 12 | | Fireball 15 | Earthquake 12 | | Charm 16 | Darkness 13 | -| Identify 20 | Dispel Evil 14 | -| Enchant Weapon 26 | Dispel Good 14 | +| Identify 20 | Reserved 14 | +| Enchant Weapon 26 | Reserved 14 | | Clone 30 | Sanctuary 15 | | | Call Lightning 15 | | | Heal 16 | @@ -9192,7 +9051,7 @@ A list is below: Wisdom - How wise you are. Helps in combat, and when regaining mana. Constitution - How healthy and robust you are. Determines how many hit points you gain per level, and how well you heal. -Dexterity - How agile you are. How many movement points you gain per level, +Dexterity - How agile you are. How many stamina points you gain per level, and how well you dodge attacks, pick locks, and kick without falling over. Charisma - How personable your character is. This can affect shop prices @@ -9224,9 +9083,8 @@ Thief Only. Usage: steal [target] -Use steal to steal coins or items from people. The chance of not getting -caught depends on how well you have practiced steal, and if the person -is asleep. +Use steal to steal coins or items from people. The chance of not getting +caught depends on your steal skill and whether the person is asleep. Examples: @@ -9281,11 +9139,11 @@ This is a listing of stock areas. 186 Newbie Zone -- Maynard of StrangeMUD 25 The High Tower of Magic -- Skylar of SillyMUD* 26 The High Tower Of Magic -- Skylar of SillyMUD* -30 Northern Midgaard Main City -- DikuMUD -31 Southern Part of Midgaard -- DikuMUD +30 Northern Main City -- DikuMUD +31 Southern Main City -- DikuMUD 33 The Three Of Swords -- C.A.W. 35 Miden'Nir -- Copper II, modified by VampLestat of MercMUD* -36 The Chessboard of Midgaard -- Exxon of SillyMUD +36 The Chessboard of the City -- Exxon of SillyMUD 40 Mines of Moria -- Redferne of DikuMUD* 41 Mines of Moria -- Redferne of DikuMUD* 50 The Great Eastern Desert -- Rorschach @@ -9970,7 +9828,7 @@ redit 34800 q y See Also: TBA-STAFF, TBA-ZONES -#32 +#2 TBA-ADVERTISING Mud Created: 2000 @@ -10059,7 +9917,7 @@ The teleporter is used to transfer players between zones. Accessible zones are listed under HELP ZONES by being CAPITALIZED. For example to teleport to: 74 Newbie GRAVEyard -- Jojen 3- 5 type: teleport grave - The teleporter may also be used to recall back to Midgaard at any time. + The teleporter may also be used to recall back to the capital at any time. Uncapitalized zones are linked through a capitalized zone. @@ -10254,13 +10112,13 @@ Thieves are known to have very special qualities, that no other class offers. Their specialty tends to be in the darker, sneakier art. Many of these qualities can come in handy in many situations, such as picking locks. -You can improve you skills by using the practice command. +You can improve your skills by using them. Skills available to thieves: sneak, hide, steal, backstab, pick lock, track See the help on each skill for more information. -See also: PRACTICE, FLAGS +See also: FLAGS #0 TILDES ~ @@ -10345,7 +10203,7 @@ time you change it. Level IMP toggle includes: NoHassle: ON Holylight: ON ShowVnums: ON Syslog: normal Hit Pnt Display: OFF Brief: OFF Summonable: OFF - Move Display: OFF Compact: ON Quest: OFF + Stamina Display: OFF Compact: ON Quest: OFF Mana Display: OFF NoTell: OFF NoRepeat: OFF AutoExits: OFF NoShout: OFF Wimpy: OFF AutoLoot: ON AutoSplit: ON @@ -10366,7 +10224,7 @@ argument. When a toggle is set, it will be saved in that state until the next time you change it. Hit Pnt Display: OFF Brief: OFF Summonable: OFF - Move Display: OFF Compact: ON Quest: OFF + Stamina Display: OFF Compact: ON Quest: OFF Mana Display: OFF NoTell: OFF NoRepeat: OFF AutoExits: OFF NoShout: OFF Wimpy: OFF AutoLoot: ON AutoSplit: ON @@ -10592,7 +10450,7 @@ Trig Usage: %actor.(<#>)% %actor.str(18) sets it to 18 Checks the actor's stat. A number in the subfield sets. -Stats include: cha, con, dex, int, str, stradd (only if str is 18). +Stats include: cha, con, dex, int, str, wis. See also: STATS #2 @@ -12444,11 +12302,11 @@ them better at hand-to-hand-combat, as they possess skills of violence and fighting unequaled by the members of any other class. However, they lack the ability to use magic of any sort. -You can improve your skills by using the practice command. +You can improve your skills by using them. Skills available to warriors: kick, rescue, track, bash -See also: PRACTICE +See also: FLAGS #0 WATERWALK WATWALK @@ -12672,7 +12530,7 @@ ban copyover freeze hcontrol reroll skillset thaw unban wizupdate Level 32 (God): -acaudit advance aedit checkload dc file +audit advance aedit checkload dc file force gecho hedit helpcheck hsedit last links mcopy mute notitle ocopy pardon plist qecho rcopy restore scopy send @@ -12716,7 +12574,7 @@ Examples: >; @ - shows all gods that are on and visible to you. - also shows if the gods who are visible to you are writing. >;# - sends text to everyone and above. - - ;#32 only God and above will see this. + - ;#2 only God and above will see this. See also: NOWIZ #2 @@ -13314,12 +13172,12 @@ rumble@*tbamud.com 26 High Tower Of Magic II -- Skylar 1-30 27 MEMLIN Caves -- Detta 17-25 28 MUDSCHOOL -- Welcor 1- 3 - 30 Northern MIDGAARD -- DikuMUD 1-33 - 31 Southern MIDGAARD -- DikuMUD 1-33 - 32 MIDGAARD -- DikuMUD 1-33 + 30 Northern MAIN CITY -- DikuMUD 1-33 + 31 Southern MAIN CITY -- DikuMUD 1-33 + 32 MAIN CITY -- DikuMUD 1-33 33 Three Of Swords -- C.A.W. 5-30 35 Miden'Nir -- Copper II 4-10 - 36 Chessboard of Midgaard -- Exxon 6-30 + 36 Chessboard of the City -- Exxon 6-30 37 CAPITAL Sewer System -- Welcor 3- 7 38 CAPITAL Sewer System II -- Welcor 7-14 39 HAVEN -- Nivan 3-14 @@ -13388,7 +13246,7 @@ rumble@*tbamud.com 239 South PASS -- Crysanthia 16-21 240 Dun MAURA -- Rumble 7-10 241 Starship ENTERPRISE -- Crazyman 26-30 - 242 NEW Midgaard -- Crazyman 3- 7 + 242 NEW Main City -- Crazyman 3- 7 243 Snowy VALLEY -- Crazyman 7-10 244 Cooland PRISON -- Crazyman 30 245 The NETHER -- Kaan 20 @@ -13589,4 +13447,89 @@ Amos sees: Gesturing to your empty mug, the bald, pudgy man waves you over with his right hand, pointing to an empty seat at his table. #0 +OVALS + + Ovals are object value slots (0-7). Use OSET ADD OVAL +to set them. Positions are 0-based. + +LIGHT: + 2 - hours_left + +SCROLL: + 0 - spell_level + 1 - spell1 + 2 - spell2 + 3 - spell3 + +POTION: + 0 - spell_level + 1 - spell1 + 2 - spell2 + 3 - spell3 + +WAND: + 0 - level + 1 - max_charges + 2 - remaining_charges + 3 - spell + +STAFF: + 0 - level + 1 - max_charges + 2 - remaining_charges + 3 - spell + +WEAPON: + 0 - dice_num + 1 - dice_size + 2 - weapon_type + 3 - message_type + +ARMOR: + 0 - piece_ac + 1 - bulk + 2 - magic_bonus + 3 - stealth_disadv + 4 - durability + 5 - str_requirement + +CONTAINER: + 0 - capacity + 1 - flags + 2 - key_vnum + 3 - corpse + +WORN: + 0 - closable + 1 - hooded + 2 - is_closed + 3 - capacity + 4 - hood_raised + +LIQ CONTAINER: + 0 - capacity + 1 - contains + 2 - liquid_type + 3 - poisoned + +FOUNTAIN: + 0 - capacity + 1 - contains + 2 - liquid_type + 3 - poisoned + +FOOD: + 0 - bites_capacity + 1 - bites_left + 2 - hours_full_per_bite + 3 - poisoned + +COINS: + 0 - coins + +FURNITURE: + 0 - max_seats + 1 - current_occupants + 2 - allowed_pos +#0 $~ diff --git a/lib/text/info b/lib/text/info index 661518c..23dab0a 100644 --- a/lib/text/info +++ b/lib/text/info @@ -3,7 +3,7 @@ [Note: Further information can be gained on the capitalized words by using the HELP-command] -Classes, skills, and guilds: +Classes and skills: When you enter the game the first time, you are asked to select a class; either THIEF, WARRIOR, CLERIC, or MAGIC user. Characters belonging to each of these @@ -16,10 +16,7 @@ keys, creating food supplies out of nothing, and destroying an enemy in several different ways. It is not advisable for a new player to offend the members of such a group! -In order to learn the tricks of your specific trade, you need to find your -GUILD, which may take a little exploring. However, you can usually find a -guild in any reasonably populated city. Once you've found it, you need to -look up your guildmaster and PRACTICE. +You improve your skills by using them in play. Equipment: diff --git a/lib/world/mob/1.mob b/lib/world/mob/1.mob index 892c795..6543ebc 100644 --- a/lib/world/mob/1.mob +++ b/lib/world/mob/1.mob @@ -8,20 +8,13 @@ A tall, burly human soldier stands here at the gate. has a thick, haggard looking brown beard that is flecked with dust and sand. His eyes have a bluish-tint to them with a small amount of green. One might call his stature bulky, as he has quite a bit of muscle. -~ -B - - - - - ~ 6218 0 0 0 0 0 0 0 0 E 1 3d20+40 8 8 1 Str: 16 Class: 3 -SaveStr: 3 +Species: 0 Skill 132 5 Skill 134 5 Skill 137 5 @@ -33,17 +26,17 @@ Skill 145 5 Skill 146 5 Skill 147 5 E -L 17 127 1 -L 16 117 1 -L 15 117 1 -L 11 111 1 -L 10 107 1 -L 9 124 1 -L 8 115 1 -L 7 108 1 -L 6 110 1 -L 5 131 1 L 3 118 1 +L 5 131 1 +L 6 110 1 +L 7 108 1 +L 8 115 1 +L 9 124 1 +L 10 107 1 +L 11 111 1 +L 15 117 1 +L 16 117 1 +L 17 127 1 #101 Sally~ slim lanky human soldier guard~ @@ -55,27 +48,25 @@ tightly. What muscle she does have is accentuated, though there is not much. Her arms and legs are lanky, seeming to be longer than normal. A ponytail of dark hair has been pulled back behind her head, intensifying the sharpness of her nose. -~ -B - - - - - ~ 6218 0 0 0 0 0 0 0 0 E 1 3d20+40 8 8 2 +Class: 3 +Species: 0 Skill 132 5 Skill 134 5 Skill 137 5 +Skill 140 5 Skill 141 5 Skill 142 5 Skill 143 5 Skill 144 5 Skill 145 5 Skill 146 5 -Skill 147 5 +Skill 152 5 +Skill 156 5 +Skill 163 5 E L 3 118 1 L 5 131 1 @@ -99,20 +90,13 @@ has taken hold, yet he has a thick and wiry beard that covers most of his face. Pale blue eyes look bloodshot, and bluish-purple bags hang under them. His hands are marred with minor cuts and scars from years of working in service to others. -~ -B - - - - - ~ 10 0 0 0 0 0 0 0 0 E 1 3d12+60 8 8 1 E -L 9 112 1 L 14 113 1 +L 9 112 1 #103 Lanky~ woman lanky scarred~ @@ -125,13 +109,6 @@ dehydration. Tanned dark from the harsh rays of the sun, her upper torso is covered in scars from a lifetime of labor. Unkempt brown hair covers her head, descending to just above her shoulders. Her eyes are a light blue color and appear slightly bloodshot. -~ -B - - - - - ~ 10 0 0 0 0 0 0 0 0 E 1 3d8+60 @@ -161,17 +138,56 @@ appear thick and ready to propel the animal if it feels threatened. B + + + + + + + + + + It's a rat. ~ 8 0 0 0 0 0 0 0 0 E 1 0d0+10 8 8 2 -Str: 6 -Dex: 10 -Int: 4 -Wis: 4 -Con: 6 +Str: 3 +Dex: 7 +Int: 3 +Wis: 8 +Con: 8 Cha: 3 +Species: 25 +Age: 42 +AtkT 4 +E +#105 +Kank~ +kank sandy brown~ +a sandy brown kank~ +A sandy brown kank is here, clacking its pincers. +~ +It looks unfinished. +~ +B + + + + +No background has been recorded. +~ +1048584 0 0 0 0 0 0 0 0 E +1 0d0+10 +8 8 0 +Str: 18 +Dex: 5 +Int: 3 +Wis: 7 +Con: 18 +Cha: 3 +Species: 21 AtkT 4 E $ diff --git a/lib/world/obj/1.obj b/lib/world/obj/1.obj index f284cd9..8a1b289 100644 --- a/lib/world/obj/1.obj +++ b/lib/world/obj/1.obj @@ -642,4 +642,12 @@ hide, reinforcing the foot from the ground below. 11 0 0 0 0 ah 0 0 0 0 0 0 0 0 0 0 0 1 40 0 0 0 +#168 +unfinished object~ +unfinished object made by Kinther~ +This is an unfinished object created by Kinther on Wed Dec 31 14:19:06 2025~ +~ +0 0 0 0 0 a 0 0 0 0 0 0 0 +0 0 0 0 +0 0 0 0 0 $~ diff --git a/lib/world/rsv/1.rsv b/lib/world/rsv/1.rsv index a8bbff6..21810c8 100644 --- a/lib/world/rsv/1.rsv +++ b/lib/world/rsv/1.rsv @@ -43,59 +43,6 @@ V 5 0 V 6 0 V 7 0 . -#R 131 1759603279 -O 144 0 20 0 0 -X 0 0 -X 1 0 -X 2 0 -X 3 0 -W 0 0 -W 1 0 -W 2 0 -W 3 0 -V 0 100 -V 1 100 -V 2 0 -V 3 0 -V 4 0 -V 5 0 -V 6 0 -V 7 0 -O 145 0 40 0 0 -X 0 0 -X 1 0 -X 2 0 -X 3 0 -W 0 0 -W 1 0 -W 2 0 -W 3 0 -V 0 4 -V 1 0 -V 2 2 -V 3 0 -V 4 0 -V 5 0 -V 6 0 -V 7 0 -O 146 0 80 0 0 -X 0 0 -X 1 0 -X 2 0 -X 3 0 -W 0 0 -W 1 0 -W 2 0 -W 3 0 -V 0 6 -V 1 0 -V 2 2 -V 3 0 -V 4 0 -V 5 0 -V 6 0 -V 7 0 -. #R 136 1759603517 O 147 0 100 0 0 X 0 0 @@ -197,3 +144,58 @@ V 5 0 V 6 0 V 7 0 . +#R 131 1767296856 +O 144 0 20 0 0 +X 0 0 +X 1 0 +X 2 0 +X 3 0 +W 0 0 +W 1 0 +W 2 0 +W 3 0 +V 0 100 +V 1 100 +V 2 0 +V 3 0 +V 4 0 +V 5 0 +V 6 0 +V 7 0 +O 145 0 40 0 0 +X 0 0 +X 1 0 +X 2 0 +X 3 0 +W 0 0 +W 1 0 +W 2 0 +W 3 0 +V 0 4 +V 1 0 +V 2 2 +V 3 0 +V 4 0 +V 5 0 +V 6 0 +V 7 0 +O 146 0 80 0 0 +X 0 0 +X 1 0 +X 2 0 +X 3 0 +W 0 0 +W 1 0 +W 2 0 +W 3 0 +V 0 6 +V 1 0 +V 2 2 +V 3 0 +V 4 0 +V 5 0 +V 6 0 +V 7 0 +. +#R 101 1767296996 +. diff --git a/lib/world/trg/0.trg b/lib/world/trg/0.trg index 185c943..ffda257 100644 --- a/lib/world/trg/0.trg +++ b/lib/world/trg/0.trg @@ -1 +1,7 @@ +#1 +Test~ +0 q 1 +~ +* No Script +~ $~ diff --git a/lib/world/trg/30.trg b/lib/world/trg/30.trg deleted file mode 100644 index 9d7d2a9..0000000 --- a/lib/world/trg/30.trg +++ /dev/null @@ -1,596 +0,0 @@ -#3000 -Mage Guildguard - 3024~ -0 q 100 -~ -* Check the direction the player must go to enter the guild. -if %direction% == south - * Stop them if they are not the appropriate class. - if %actor.class% != Magic User - return 0 - %send% %actor% The guard humiliates you, and blocks your way. - %echoaround% %actor% The guard humiliates %actor.name%, and blocks %actor.hisher% way. - end -end -~ -#3001 -Cleric Guildguard - 3025~ -0 q 100 -~ -* Check the direction the player must go to enter the guild. -if %direction% == north - * Stop them if they are not the appropriate class. - if %actor.class% != Cleric - return 0 - %send% %actor% The guard humiliates you, and blocks your way. - %echoaround% %actor% The guard humiliates %actor.name%, and blocks %actor.hisher% way. - end -end -~ -#3002 -Thief Guildguard - 3026~ -0 q 100 -~ -* Check the direction the player must go to enter the guild. -if %direction% == east - * Stop them if they are not the appropriate class. - if %actor.class% != Thief - return 0 - %send% %actor% The guard humiliates you, and blocks your way. - %echoaround% %actor% The guard humiliates %actor.name%, and blocks %actor.hisher% way. - end -end -~ -#3003 -Warrior Guildguard - 3027~ -0 q 100 -~ -* Check the direction the player must go to enter the guild. -if %direction% == east - * Stop them if they are not the appropriate class. - if %actor.class% != Warrior - return 0 - %send% %actor% The guard humiliates you, and blocks your way. - %echoaround% %actor% The guard humiliates %actor.name%, and blocks %actor.hisher% way. - end -end -~ -#3004 -Dump - 3030~ -2 h 100 -~ -%send% %actor% You are awarded for outstanding performance. -%echoaround% %actor% %actor.name% has been awarded for being a good citizen. -eval value %object.cost% / 10 -if %value% > 50 - set value 50 -elseif %value% < 1 - set value 1 -end -if %actor.level% < 3 - nop %actor.exp(%value%)% -else - nop %actor.coins(%value%)% -end -%purge% %object% -~ -#3005 -Stock Thief~ -0 b 10 -~ -set actor %random.char% -if %actor% - if %actor.is_pc% && %actor.coins% - %send% %actor% You discover that %self.name% has %self.hisher% hands in your wallet. - %echoaround% %actor% %self.name% tries to steal coins from %actor.name%. - eval coins %actor.coins% * %random.10% / 100 - nop %actor.coins(-%coins%)% - nop %self.coins(%coins%)% - end -end -~ -#3006 -Stock Snake~ -0 k 10 -~ -%send% %actor% %self.name% bites you! -%echoaround% %actor% %self.name% bites %actor.name%. -dg_cast 'poison' %actor% -~ -#3007 -Stock Magic User~ -0 k 10 -~ -switch %actor.level% - case 1 - case 2 - case 3 - break - case 4 - dg_cast 'magic missile' %actor% - break - case 5 - dg_cast 'chill touch' %actor% - break - case 6 - dg_cast 'burning hands' %actor% - break - case 7 - case 8 - dg_cast 'shocking grasp' %actor% - break - case 9 - case 10 - case 11 - dg_cast 'lightning bolt' %actor% - break - case 12 - dg_cast 'color spray' %actor% - break - case 13 - dg_cast 'energy drain' %actor% - break - case 14 - dg_cast 'curse' %actor% - break - case 15 - dg_cast 'poison' %actor% - break - case 16 - if %actor.align% > 0 - dg_cast 'dispel good' %actor% - else - dg_cast 'dispel evil' %actor% - end - break - case 17 - case 18 - dg_cast 'call lightning' %actor% - break - case 19 - case 20 - case 21 - case 22 - dg_cast 'harm' %actor% - break - default - dg_cast 'fireball' %actor% - break -done -~ -#3008 -Near Death Trap~ -2 g 100 -~ -* By Rumble of The Builder Academy tbamud.com 9091 -* Near Death Trap stuns actor -set stunned %actor.hitp% -%damage% %actor% %stunned% -%send% %actor% You are on the brink of life and death. -%send% %actor% The Gods must favor you this day. -~ -#3009 -Stock Cityguard - 3059, 60, 67~ -0 b 50 -~ -if !%self.fighting% - set actor %random.char% - if %actor% - if %actor.is_killer% - emote screams 'HEY!!! You're one of those PLAYER KILLERS!!!!!!' - kill %actor.name% - elseif %actor.is_thief% - emote screams 'HEY!!! You're one of those PLAYER THIEVES!!!!!!' - kill %actor.name% - elseif %actor.cha% < 6 - %send% %actor% %self.name% spits in your face. - %echoaround% %actor% %self.name% spits in %actor.name%'s face. - end - if %actor.fighting% - eval victim %actor.fighting% - if %actor.align% < %victim.align% && %victim.align% >= 0 - emote screams 'PROTECT THE INNOCENT! BANZAI! CHARGE! ARARARAGGGHH!' - kill %actor.name% - end - end - end -end -~ -#3010 -Stock Fido - 3062, 3066~ -0 b 100 -~ -set inroom %self.room% -set item %inroom.contents% -while %item% - * Target the next item in room. In case it is devoured. - set next_item %item.next_in_list% - * Check for a corpse. Corpse on TBA is vnum 65535. Stock is -1. - if %item.vnum(65535)% - emote savagely devours a corpse. - %purge% %item% - halt - end - set item %next_item% - * Loop back -done -~ -#3011 -Stock Janitor - 3061, 3068~ -0 b 100 -~ -eval inroom %self.room% -eval item %inroom.contents% -while %item% - * Target the next item in room. In case it is picked up. - set next_item %item.next_in_list% -* TODO: if %item.wearflag(take)% - * Check for fountains and expensive items. - if %item.type% != FOUNTAIN && %item.cost% <= 15 - take %item.name% - end - set item %next_item% - * Loop back -done -~ -#3012 -Newbie Tour Guide~ -0 e 0 -has entered the game.~ -%echo% This trigger commandlist is not complete! -~ -#3013 -Newbie Tour Guide Loader~ -0 e 0 -has entered the game.~ -* By Rumble of The Builder Academy tbamud.com 9091 -* Num Arg 0 means the argument has to match exactly. So trig will only fire off: -* "has entered game." and not "has" or "entered" etc. (that would be num arg 1). -* Figure out what vnum the mob is in so we can use zoneecho. -eval inroom %self.room% -%zoneecho% %inroom.vnum% %self.name% shouts, 'Welcome, %actor.name%!' -~ -#3014 -Teleporter~ -1 c 3 -teleport~ -* By Rumble and Jamie Nelson of The Builder Academy tbamud.com 9091 -%send% %actor% You attempt to manipulate space and time. -%echoaround% %actor% %actor.name% attempts to manipulate space and time. -wait 1 sec -set sanctus 100 -set jade 400 -set newbie 500 -set sea 600 -set camelot 775 -set nuclear 1800 -set spider 1999 -set arena 2000 -set tower 2200 -set memlin 2798 -set mudschool 2800 -set midgaard 3001 -set capital 3702 -set haven 3998 -set chasm 4200 -set arctic 4396 -set Orc 4401 -set monastery 4512 -set ant 4600 -set zodiac 5701 -set grave 7401 -set zamba 7500 -set gidean 7801 -set glumcoins 8301 -set duke 8660 -set oasis 9000 -set domiae 9603 -set northern 10004 -set south 10101 -set dbz 10301 -set orchan 10401 -set elcardo 10604 -set iuel 10701 -set omega 11501 -set torres 11701 -set dollhouse 11899 -set hannah 12500 -set maze 13001 -set wyvern 14000 -set caves 16999 -set cardinal 17501 -set circus 18700 -set western 20001 -set sapphire 20101 -set kitchen 22001 -set terringham 23200 -set dragon 23300 -set school 23400 -set mines 23500 -set aldin 23601 -set crystal 23875 -set pass 23901 -set maura 24000 -set enterprise 24100 -set new 24200 -set valley 24300 -set prison 24457 -set nether 24500 -set yard 24700 -set elven 24801 -set jedi 24901 -set dragonspyre 25000 -set ape 25100 -set vampyre 25200 -set windmill 25300 -set village 25400 -set shipwreck 25516 -set keep 25645 -set jareth 25705 -set light 25800 -set mansion 25907 -set grasslands 26000 -set igor's 26100 -set forest 26201 -set farmlands 26300 -set banshide 26400 -set beach 26500 -set ankou 26600 -set vice 26728 -set desert 26900 -set wasteland 27001 -set sundhaven 27119 -set station 27300 -set smurfville 27400 -set sparta 27501 -set shire 27700 -set oceania 27800 -set notre 27900 -set motherboard 28000 -set khanjar 28100 -set kerjim 28200 -set haunted 28300 -set ghenna 28400 -set hell 28601 -set goblin 28700 -set galaxy 28801 -set werith's 28900 -set lizard 29000 -set black 29100 -set kerofk 29202 -set trade 29400 -set jungle 29500 -set froboz 29600 -set desire 29801 -set cathedral 29900 -set ancalador 30000 -set campus 30100 -set bull 30401 -set chessboard 30537 -set tree 30600 -set castle 30700 -set baron 30800 -set westlawn 30900 -set graye 31003 -set teeth 31100 -set leper 31200 -set altar 31400 -set mcgintey 31500 -set wharf 31700 -set dock 31801 -set yllnthad 31900 -set bay 32200 -set pale 32300 -set army 32400 -set revelry 32500 -set perimeter 32600 -set asylum 34501 -set ultima 55685 -set tarot 21101 -if !%arg% - *they didnt type a location - set fail 1 -else - *take the first word they type after the teleport command - *compare it to a variable above - eval loc %%%arg.car%%% - if !%loc% - *they typed an invalid location - set fail 1 - end -end -if %fail% - %send% %actor% You fail. - %echoaround% %actor% %actor.name% fails. - halt -end -%echoaround% %actor% %actor.name% seems successful as %actor.heshe% steps into another realm. -%teleport% %actor% %loc% -%force% %actor% look -%echoaround% %actor% %actor.name% steps out of space and time. -~ -#3015 -Teleporter Recall and Return~ -1 c 7 -re~ -* By Rumble of The Builder Academy tbamud.com 9091 -if %cmd% == recall - eval teleporter_return_room %actor.room.vnum% - remote teleporter_return_room %actor.id% - %send% %actor% You recall to safety. - %echoaround% %actor% %actor.name% recalls. - %teleport% %actor% 3001 - %force% %actor% look - %echoaround% %actor% %actor.name% appears in the room. -elseif %cmd% == return - %send% %actor% You return to your previous location. - %echoaround% %actor% %actor.name% teleports out of the room. - %teleport% %actor% %actor.teleporter_return_room% - %force% %actor% look - %echoaround% %actor% %actor.name% appears in the room. -else - return 0 -end -~ -#3016 -Kind Soul Gives Newbie Equipment~ -0 g 100 -~ -* By Rumble of The Builder Academy tbamud.com 9091 -* If a player is < level 5 and naked it fully equips them. If < 5 and missing -* some equipment it will equip one spot. -if %actor.is_pc% && %actor.level% < 5 - wait 2 sec - if !%actor.eq(*)% - say get some clothes on! Here, I will help. - %load% obj 3037 %actor% light - %load% obj 3083 %actor% rfinger - %load% obj 3083 %actor% lfinger - %load% obj 3082 %actor% neck1 - %load% obj 3082 %actor% neck2 - %load% obj 3040 %actor% body - %load% obj 3076 %actor% head - %load% obj 3080 %actor% legs - %load% obj 3084 %actor% feet - %load% obj 3071 %actor% hands - %load% obj 3086 %actor% arms - %load% obj 3042 %actor% shield - %load% obj 3087 %actor% about - %load% obj 3088 %actor% waist - %load% obj 3089 %actor% rwrist - %load% obj 3089 %actor% lwrist - %load% obj 3021 %actor% wield - %load% obj 3055 %actor% hold - halt - end - if !%actor.eq(light)% - say you really shouldn't be wandering these parts without a light source %actor.name%. - shake - %load% obj 3037 - give candle %actor.name% - halt - end - if !%actor.eq(rfinger)% || !%actor.eq(lfinger)% - say did you lose one of your rings? - sigh - %load% obj 3083 - give ring %actor.name% - halt - end - if !%actor.eq(neck1)% || !%actor.eq(neck2)% - say you lose everything don't you? - roll - %load% obj 3082 - give neck %actor.name% - halt - end - if !%actor.eq(body)% - say you won't get far without some body armor %actor.name%. - %load% obj 3040 - give plate %actor.name% - halt - end - if !%actor.eq(head)% - say protect that noggin of yours, %actor.name%. - %load% obj 3076 - give cap %actor.name% - halt - end - if !%actor.eq(legs)% - say why do you always lose your pants %actor.name%? - %load% obj 3080 - give leggings %actor.name% - halt - end - if !%actor.eq(feet)% - say you can't go around barefoot %actor.name%. - %load% obj 3084 - give boots %actor.name% - halt - end - if !%actor.eq(hands)% - say need some gloves %actor.name%? - %load% obj 3071 - give gloves %actor.name% - halt - end - if !%actor.eq(arms)% - say you must be freezing %actor.name%. - %load% obj 3086 - give sleeve %actor.name% - halt - end - if !%actor.eq(shield)% - say you need one of these to protect yourself %actor.name%. - %load% obj 3042 - give shield %actor.name% - halt - end - if !%actor.eq(about)% - say you are going to catch a cold %actor.name%. - %load% obj 3087 - give cape %actor.name% - halt - end - if !%actor.eq(waist)% - say better use this to hold your pants up %actor.name%. - %load% obj 3088 - give belt %actor.name% - halt - end - if !%actor.eq(rwrist)% || !%actor.eq(lwrist)% - say misplace something? - smile - %load% obj 3089 - give wristguard %actor.name% - halt - end - if !%actor.eq(wield)% - say without a weapon you will be Fido food %actor.name%. - %load% obj 3021 - give sword %actor.name% - halt - end -end -~ -#3017 -Mortal Greet~ -2 s 100 -~ -* By Rumble of The Builder Academy tbamud.com 9091 -* TBA mortal greet and equip. New players start at level 0. -wait 1 sec -if %actor.level% == 0 - if !%actor.eq(*)% - %load% obj 3037 %actor% light - %load% obj 3083 %actor% rfinger - %load% obj 3083 %actor% lfinger - %load% obj 3082 %actor% neck1 - %load% obj 3082 %actor% neck2 - %load% obj 3040 %actor% body - %load% obj 3076 %actor% head - %load% obj 3080 %actor% legs - %load% obj 3084 %actor% feet - %load% obj 3071 %actor% hands - %load% obj 3086 %actor% arms - %load% obj 3042 %actor% shield - %load% obj 3087 %actor% about - %load% obj 3088 %actor% waist - %load% obj 3089 %actor% rwrist - %load% obj 3089 %actor% lwrist - %load% obj 3021 %actor% wield - %load% obj 3055 %actor% hold - end - if !%actor.has_item(3006)% - %load% obj 3006 %actor% inv - end -end -wait 3 sec -%zoneecho% 3001 A booming voice announces, 'Welcome %actor.name% to the realm!' -~ -#3099 -Test~ -2 b 1 -~ -%zoneecho% 3001 You hear a loud --=BOOM=--, -~ -$~ diff --git a/lib/world/trg/index b/lib/world/trg/index index 30dfe62..95df992 100644 --- a/lib/world/trg/index +++ b/lib/world/trg/index @@ -1,5 +1,5 @@ 0.trg 1.trg 2.trg -30.trg + $ diff --git a/lib/world/trg/index.mini b/lib/world/trg/index.mini index 81a6b8c..857f13a 100644 --- a/lib/world/trg/index.mini +++ b/lib/world/trg/index.mini @@ -1,2 +1 @@ -30.trg $ diff --git a/lib/world/wld/1.wld b/lib/world/wld/1.wld index 50b8760..05e17e6 100644 --- a/lib/world/wld/1.wld +++ b/lib/world/wld/1.wld @@ -726,7 +726,7 @@ map of the city can be seen upon one wall, giving the impression this would be a good place to learn more about where certain landmarks are. To the south lies Caravan Way, while to the east Wall Road can be seen. ~ -1 131072 0 0 0 0 +1 131080 0 0 0 0 D1 ~ ~ diff --git a/src/Makefile.amiga b/src/Makefile.amiga index d4fe8f5..1ca73cc 100644 --- a/src/Makefile.amiga +++ b/src/Makefile.amiga @@ -20,7 +20,7 @@ PROFILE = CFLAGS = $(MYFLAGS) $(PROFILE) OBJFILES = comm.o act.comm.o act.informative.o act.movement.o act.item.o \ - act.offensive.o act.other.o act.social.o act.wizard.o ban.o boards.o \ + act.offensive.o act.other.o act.social.o act.wizard.o set.o ban.o boards.o \ castle.o class.o config.o constants.o db.o fight.o graph.o handler.o \ house.o interpreter.o limits.o magic.o mail.o mobact.o modify.o \ objsave.o shop.o spec_assign.o spec_procs.o spell_parser.o \ @@ -115,6 +115,10 @@ act.social.o: act.social.c conf.h sysdep.h structs.h utils.h comm.h \ act.wizard.o: act.wizard.c conf.h sysdep.h structs.h utils.h comm.h \ interpreter.h handler.h db.h spells.h house.h screen.h constants.h $(CC) -c $(CFLAGS) act.wizard.c +set.o: set.c conf.h sysdep.h structs.h utils.h comm.h \ + interpreter.h handler.h db.h constants.h genolc.h genwld.h genzon.h \ + oasis.h improved-edit.h modify.h genobj.h dg_scripts.h set.h + $(CC) -c $(CFLAGS) set.c ban.o: ban.c conf.h sysdep.h structs.h utils.h comm.h interpreter.h handler.h db.h $(CC) -c $(CFLAGS) ban.c boards.o: boards.c conf.h sysdep.h structs.h utils.h comm.h db.h boards.h \ diff --git a/src/Makefile.arc b/src/Makefile.arc index 29c1c61..6c68962 100644 --- a/src/Makefile.arc +++ b/src/Makefile.arc @@ -22,7 +22,7 @@ BINDIR = ^.bin CFLAGS = $(MYFLAGS) $(PROFILE) OBJFILES = o.comm act.o.comm act.o.informative act.o.movement act.o.item \ - act.o.offensive act.o.other act.o.social act.o.wizard o.ban o.boards \ + act.o.offensive act.o.other act.o.social act.o.wizard o.set o.ban o.boards \ o.castle o.class o.config o.constants o.db o.fight o.graph o.handler \ o.house o.interpreter o.limits o.magic o.mail o.mobact o.modify \ o.objsave o.random o.shop o.spec_assign o.spec_procs \ @@ -73,6 +73,11 @@ act.o.wizard: act.c.wizard h.conf h.sysdep h.structs \ h.utils h.comm h.interpreter h.handler \ h.db h.spells h.house h.screen h.constants $(CC) -c $(CFLAGS) act.c.wizard -o act.o.wizard +o.set: c.set h.conf h.sysdep h.structs \ + h.utils h.comm h.interpreter h.handler \ + h.db h.constants h.genobj h.genolc h.genwld h.genzon h.oasis \ + h.improved-edit h.modify h.dg_scripts h.set + $(CC) -c $(CFLAGS) c.set -o o.set o.ban: c.ban h.conf h.sysdep h.structs h.utils h.comm h.interpreter h.handler h.db $(CC) -c $(CFLAGS) c.ban o.boards: c.boards h.conf h.sysdep h.structs h.utils h.comm h.db h.boards \ diff --git a/src/Makefile.bcc b/src/Makefile.bcc index d5b6493..73b1fd1 100644 --- a/src/Makefile.bcc +++ b/src/Makefile.bcc @@ -49,6 +49,7 @@ Dep_circledexe = \ act.informative.obj\ act.offensive.obj\ act.other.obj\ + set.obj\ boards.obj\ ban.obj\ act.wizard.obj\ @@ -93,6 +94,7 @@ act.item.obj+ act.informative.obj+ act.offensive.obj+ act.other.obj+ +set.obj+ boards.obj+ ban.obj+ act.wizard.obj+ @@ -163,6 +165,11 @@ act.other.obj : act.other.c $(CompOptsAt_circledexe) $(CompInheritOptsAt_circledexe) -o$@ act.other.c | +set.obj : set.c + $(BCC32) -P- -c @&&| + $(CompOptsAt_circledexe) $(CompInheritOptsAt_circledexe) -o$@ set.c +| + boards.obj : boards.c $(BCC32) -P- -c @&&| $(CompOptsAt_circledexe) $(CompInheritOptsAt_circledexe) -o$@ boards.c @@ -339,5 +346,3 @@ BccW32.cfg : -WC -g0 | $@ - - diff --git a/src/Makefile.bcc55 b/src/Makefile.bcc55 index 9d16c19..4479b1b 100644 --- a/src/Makefile.bcc55 +++ b/src/Makefile.bcc55 @@ -50,6 +50,7 @@ Dep_circledexe = \ act.informative.obj\ act.offensive.obj\ act.other.obj\ + set.obj\ boards.obj\ ban.obj\ act.wizard.obj\ @@ -94,6 +95,7 @@ act.item.obj+ act.informative.obj+ act.offensive.obj+ act.other.obj+ +set.obj+ boards.obj+ ban.obj+ act.wizard.obj+ @@ -162,6 +164,11 @@ act.other.obj : act.other.c $(CompOptsAt_circledexe) $(CompInheritOptsAt_circledexe) -o$@ act.other.c | +set.obj : set.c + $(BCC32) -P- -c @&&| + $(CompOptsAt_circledexe) $(CompInheritOptsAt_circledexe) -o$@ set.c +| + boards.obj : boards.c $(BCC32) -P- -c @&&| $(CompOptsAt_circledexe) $(CompInheritOptsAt_circledexe) -o$@ boards.c @@ -339,5 +346,3 @@ BccW32.cfg : -WC -g0 | $@ - - diff --git a/src/Makefile.lcc b/src/Makefile.lcc index f2d4df8..a128ba6 100644 --- a/src/Makefile.lcc +++ b/src/Makefile.lcc @@ -48,6 +48,7 @@ OBJS=\ boards.obj \ ban.obj \ act.wizard.obj \ + set.obj \ act.social.obj \ act.other.obj \ act.offensive.obj \ @@ -494,6 +495,29 @@ ACT_WIZARD_C=\ act.wizard.obj: $(ACT_WIZARD_C) $(DISTDIR)\src\act.wizard.c $(CC) $(CFLAGS) $(DISTDIR)\src\act.wizard.c +# Build SET.C +SET_C=\ + $(DISTDIR)\src\sysdep.h\ + $(DISTDIR)\src\structs.h\ + $(DISTDIR)\src\utils.h\ + $(DISTDIR)\src\comm.h\ + $(DISTDIR)\src\interpreter.h\ + $(DISTDIR)\src\handler.h\ + $(DISTDIR)\src\db.h\ + $(DISTDIR)\src\constants.h\ + $(DISTDIR)\src\genobj.h\ + $(DISTDIR)\src\genolc.h\ + $(DISTDIR)\src\genwld.h\ + $(DISTDIR)\src\genzon.h\ + $(DISTDIR)\src\oasis.h\ + $(DISTDIR)\src\improved-edit.h\ + $(DISTDIR)\src\modify.h\ + $(DISTDIR)\src\dg_scripts.h\ + $(DISTDIR)\src\set.h\ + +set.obj: $(SET_C) $(DISTDIR)\src\set.c + $(CC) $(CFLAGS) $(DISTDIR)\src\set.c + # Build ACT.SOCIAL.C ACT_SOCIAL_C=\ $(DISTDIR)\src\sysdep.h\ @@ -598,4 +622,3 @@ ACT_COMM_C=\ act.comm.obj: $(ACT_COMM_C) $(DISTDIR)\src\act.comm.c $(CC) $(CFLAGS) $(DISTDIR)\src\act.comm.c - diff --git a/src/Makefile.msvc b/src/Makefile.msvc index cc06f68..60d54e9 100644 --- a/src/Makefile.msvc +++ b/src/Makefile.msvc @@ -37,6 +37,7 @@ MAKE = $(MAKE) /NOLOGO /S OBJFILES = comm.obj act.comm.obj act.informative.obj act.movement.obj act.item.obj \ asciimap.obj act.offensive.obj act.other.obj act.social.obj act.wizard.obj \ +set.obj \ ban.obj boards.obj castle.obj class.obj config.obj constants.obj db.obj \ dg_event.obj dg_scripts.obj dg_triggers.obj fight.obj genolc.obj graph.obj \ handler.obj house.obj ibt.obj interpreter.obj limits.obj lists.obj magic.obj \ @@ -83,6 +84,10 @@ act.social.obj: act.social.c conf.h sysdep.h structs.h utils.h comm.h \ act.wizard.obj: act.wizard.c conf.h sysdep.h structs.h utils.h comm.h \ interpreter.h handler.h db.h spells.h house.h screen.h constants.h $(CC) -c $(CFLAGS) act.wizard.c +set.obj: set.c conf.h sysdep.h structs.h utils.h comm.h \ + interpreter.h handler.h db.h constants.h genolc.h genwld.h genzon.h \ + oasis.h improved-edit.h modify.h genobj.h dg_scripts.h set.h + $(CC) -c $(CFLAGS) set.c ban.obj: ban.c conf.h sysdep.h structs.h utils.h comm.h interpreter.h handler.h db.h $(CC) -c $(CFLAGS) ban.c boards.obj: boards.c conf.h sysdep.h structs.h utils.h comm.h db.h boards.h \ diff --git a/src/Makefile.os2 b/src/Makefile.os2 index 765d057..c22f256 100644 --- a/src/Makefile.os2 +++ b/src/Makefile.os2 @@ -22,7 +22,7 @@ LIB = -lsocket CFLAGS = $(MYFLAGS) $(PROFILE) OBJFILES = comm.o act.comm.o act.informative.o act.movement.o act.item.o \ - act.offensive.o act.other.o act.social.o act.wizard.o ban.o boards.o \ + act.offensive.o act.other.o act.social.o act.wizard.o set.o ban.o boards.o \ castle.o class.o config.o constants.o db.o fight.o graph.o handler.o \ house.o interpreter.o limits.o magic.o mail.o mobact.o modify.o \ objsave.o shop.o spec_assign.o spec_procs.o spell_parser.o \ @@ -117,6 +117,10 @@ act.social.o: act.social.c conf.h sysdep.h structs.h utils.h comm.h \ act.wizard.o: act.wizard.c conf.h sysdep.h structs.h utils.h comm.h \ interpreter.h handler.h db.h spells.h house.h screen.h constants.h $(CC) -c $(CFLAGS) act.wizard.c +set.o: set.c conf.h sysdep.h structs.h utils.h comm.h \ + interpreter.h handler.h db.h constants.h genolc.h genwld.h genzon.h \ + oasis.h improved-edit.h modify.h genobj.h dg_scripts.h set.h + $(CC) -c $(CFLAGS) set.c ban.o: ban.c conf.h sysdep.h structs.h utils.h comm.h interpreter.h handler.h db.h $(CC) -c $(CFLAGS) ban.c boards.o: boards.c conf.h sysdep.h structs.h utils.h comm.h db.h boards.h \ diff --git a/src/Smakefile b/src/Smakefile index 1f62ca5..5635a98 100644 --- a/src/Smakefile +++ b/src/Smakefile @@ -18,7 +18,7 @@ CFLAGS = NOLINK $(MYFLAGS) $(PROFILE) MAKE = SMAKE OBJFILES = comm.o act.comm.o act.informative.o act.movement.o act.item.o \ - act.offensive.o act.other.o act.social.o act.wizard.o ban.o boards.o \ + act.offensive.o act.other.o act.social.o act.wizard.o set.o ban.o boards.o \ castle.o class.o config.o constants.o db.o fight.o graph.o handler.o \ house.o interpreter.o limits.o magic.o mail.o mobact.o modify.o \ objsave.o olc.o shop.o spec_assign.o spec_procs.o spell_parser.o \ @@ -109,6 +109,10 @@ act.social.o: act.social.c conf.h sysdep.h structs.h utils.h comm.h \ act.wizard.o: act.wizard.c conf.h sysdep.h structs.h utils.h comm.h \ interpreter.h handler.h db.h spells.h house.h screen.h $(CC) $(CFLAGS) act.wizard.c +set.o: set.c conf.h sysdep.h structs.h utils.h comm.h \ + interpreter.h handler.h db.h constants.h genolc.h genwld.h genzon.h \ + oasis.h improved-edit.h modify.h genobj.h dg_scripts.h set.h + $(CC) $(CFLAGS) set.c ban.o: ban.c conf.h sysdep.h structs.h utils.h comm.h interpreter.h handler.h db.h $(CC) $(CFLAGS) ban.c boards.o: boards.c conf.h sysdep.h structs.h utils.h comm.h db.h boards.h \ @@ -189,4 +193,3 @@ utils.o: utils.c conf.h sysdep.h structs.h utils.h comm.h screen.h spells.h \ weather.o: weather.c conf.h sysdep.h structs.h utils.h comm.h handler.h \ interpreter.h db.h $(CC) $(CFLAGS) weather.c - diff --git a/src/act.h b/src/act.h index ef84127..8f20741 100644 --- a/src/act.h +++ b/src/act.h @@ -19,6 +19,7 @@ #define _ACT_H_ #include "utils.h" /* for the ACMD macro */ +#include "set.h" #ifndef MAX_EMOTE_TOKENS #define MAX_EMOTE_TOKENS 16 @@ -175,12 +176,18 @@ ACMD(do_gen_door); /* Functions without subcommands */ ACMD(do_enter); ACMD(do_follow); +ACMD(do_hitch); ACMD(do_leave); +ACMD(do_mount); ACMD(do_move); +ACMD(do_pack); ACMD(do_rest); +ACMD(do_dismount); ACMD(do_sit); ACMD(do_sleep); ACMD(do_stand); +ACMD(do_unhitch); +ACMD(do_unpack); ACMD(do_unfollow); ACMD(do_wake); /* Global variables from act.movement.c */ @@ -257,6 +264,8 @@ ACMD(do_group); ACMD(do_hide); ACMD(do_listen); ACMD(do_not_here); +ACMD(do_change); +ACMD(do_reroll); ACMD(do_report); ACMD(do_save); ACMD(do_skills); @@ -342,7 +351,7 @@ ACMD(do_wizutil); #define SCMD_THAW 4 #define SCMD_UNAFFECT 5 /* Functions without subcommands */ -ACMD(do_acaudit); +ACMD(do_audit); ACMD(do_advance); ACMD(do_at); ACMD(do_checkloadstatus); diff --git a/src/act.informative.c b/src/act.informative.c index 33dc482..4956ccb 100644 --- a/src/act.informative.c +++ b/src/act.informative.c @@ -41,6 +41,8 @@ static void look_at_target(struct char_data *ch, char *arg); static void look_in_direction(struct char_data *ch, int dir); static void look_in_obj(struct char_data *ch, char *arg); static void look_at_tables(struct char_data *ch); +static bool look_can_spot_hidden(struct char_data *ch, struct char_data *tch, room_rnum room); +static bool look_list_direction_chars(struct char_data *ch, room_rnum room); /* do_look, do_inventory utility functions */ static void list_obj_to_char(struct obj_data *list, struct char_data *ch, int mode, int show); /* do_look, do_equipment, do_examine, do_inventory */ @@ -101,8 +103,11 @@ static void show_obj_to_char(struct obj_data *obj, struct char_data *ch, int mod found++; } if (found) { - send_to_char(ch, "You are %s upon %s.", GET_POS(ch) == POS_SITTING ? "sitting" : - "resting", obj->short_description); + const char *pos = (GET_POS(ch) == POS_STANDING ? "standing" : + (GET_POS(ch) == POS_SITTING ? "sitting" : + (GET_POS(ch) == POS_SLEEPING ? "sleeping" : "resting"))); + const char *prep = (GET_POS(ch) == POS_STANDING || GET_POS(ch) == POS_SITTING) ? "at" : "upon"; + send_to_char(ch, "You are %s %s %s.", pos, prep, obj->short_description); goto end; } } @@ -234,9 +239,6 @@ static void show_obj_modifiers(struct obj_data *obj, struct char_data *ch) if (OBJ_FLAGGED(obj, ITEM_INVISIBLE)) send_to_char(ch, " (invisible)"); - if (OBJ_FLAGGED(obj, ITEM_BLESS) && AFF_FLAGGED(ch, AFF_DETECT_ALIGN)) - send_to_char(ch, " ..It glows blue!"); - if (OBJ_FLAGGED(obj, ITEM_MAGIC) && AFF_FLAGGED(ch, AFF_DETECT_MAGIC)) send_to_char(ch, " ..It glows yellow!"); @@ -567,17 +569,62 @@ static void list_one_char(struct char_data *i, struct char_data *ch) CCNRM(ch, C_NRM)); } - /* NPCs with a full long description at default position: print that and bail. */ - if (IS_NPC(i) && i->player.long_descr && GET_POS(i) == GET_DEFAULT_POS(i)) { + if (AFF_FLAGGED(i, AFF_MOUNTED) && MOUNT(i) && + IN_ROOM(MOUNT(i)) == IN_ROOM(i) && + MOB_FLAGGED(MOUNT(i), MOB_MOUNT)) { + const char *rdesc = get_char_sdesc(i); + const char *mdesc = get_char_sdesc(MOUNT(i)); + + if (rdesc && *rdesc) + send_to_char(ch, "%c%s", UPPER(*rdesc), rdesc + 1); + else + send_to_char(ch, "Someone"); + + if (mdesc && *mdesc) + send_to_char(ch, " is riding %s here.", mdesc); + else + send_to_char(ch, " is riding someone here."); + + if (AFF_FLAGGED(i, AFF_INVISIBLE)) + send_to_char(ch, " (invisible)"); + if (AFF_FLAGGED(i, AFF_HIDE)) + send_to_char(ch, " (hidden)"); + if (!IS_NPC(i) && !i->desc) + send_to_char(ch, " (linkless)"); + if (!IS_NPC(i) && PLR_FLAGGED(i, PLR_WRITING)) + send_to_char(ch, " (writing)"); + if (!IS_NPC(i) && PRF_FLAGGED(i, PRF_BUILDWALK)) + send_to_char(ch, " (buildwalk)"); + if (!IS_NPC(i) && PRF_FLAGGED(i, PRF_AFK)) + send_to_char(ch, " (AFK)"); + + send_to_char(ch, "\r\n"); + + if (AFF_FLAGGED(i, AFF_SANCTUARY)) + act("...$e glows with a bright light!", FALSE, i, 0, ch, TO_VICT); + + return; + } + + /* Custom ldesc overrides position-based output. */ + if (i->char_specials.custom_ldesc && i->player.long_descr) { if (AFF_FLAGGED(i, AFF_INVISIBLE)) send_to_char(ch, "*"); - if (AFF_FLAGGED(ch, AFF_DETECT_ALIGN)) { - if (IS_EVIL(i)) - send_to_char(ch, "(Red Aura) "); - else if (IS_GOOD(i)) - send_to_char(ch, "(Blue Aura) "); - } + send_to_char(ch, "%s", i->player.long_descr); + + if (AFF_FLAGGED(i, AFF_SANCTUARY)) + act("...$e glows with a bright light!", FALSE, i, 0, ch, TO_VICT); + if (AFF_FLAGGED(i, AFF_BLIND) && GET_LEVEL(i) < LVL_IMMORT) + act("...$e is groping around blindly!", FALSE, i, 0, ch, TO_VICT); + + return; + } + + /* Characters with a full long description at default position: print that and bail. */ + if (i->player.long_descr && GET_POS(i) == GET_DEFAULT_POS(i)) { + if (AFF_FLAGGED(i, AFF_INVISIBLE)) + send_to_char(ch, "*"); send_to_char(ch, "%s", i->player.long_descr); @@ -618,9 +665,13 @@ static void list_one_char(struct char_data *i, struct char_data *ch) send_to_char(ch, "%s", positions[(int) GET_POS(i)]); else { furniture = SITTING(i); - send_to_char(ch, " is %s upon %s.", (GET_POS(i) == POS_SLEEPING ? - "sleeping" : (GET_POS(i) == POS_RESTING ? "resting" : "sitting")), - OBJS(furniture, ch)); + { + const char *pos = (GET_POS(i) == POS_STANDING ? "standing" : + (GET_POS(i) == POS_SITTING ? "sitting" : + (GET_POS(i) == POS_SLEEPING ? "sleeping" : "resting"))); + const char *prep = (GET_POS(i) == POS_STANDING || GET_POS(i) == POS_SITTING) ? "at" : "upon"; + send_to_char(ch, " is %s %s %s.", pos, prep, OBJS(furniture, ch)); + } } } else { if (FIGHTING(i)) { @@ -637,19 +688,115 @@ static void list_one_char(struct char_data *i, struct char_data *ch) send_to_char(ch, " is here struggling with thin air."); } - if (AFF_FLAGGED(ch, AFF_DETECT_ALIGN)) { - if (IS_EVIL(i)) - send_to_char(ch, " (Red Aura)"); - else if (IS_GOOD(i)) - send_to_char(ch, " (Blue Aura)"); - } - send_to_char(ch, "\r\n"); if (AFF_FLAGGED(i, AFF_SANCTUARY)) act("...$e glows with a bright light!", FALSE, i, 0, ch, TO_VICT); } +static void strip_trailing_crlf(char *str) +{ + size_t len; + + if (!str) + return; + + len = strlen(str); + while (len > 0 && (str[len - 1] == '\n' || str[len - 1] == '\r')) + str[--len] = '\0'; +} + +static void build_current_ldesc(const struct char_data *ch, char *out, size_t outsz) +{ + struct obj_data *furniture; + const char *positions[] = { + " is lying here, dead.", + " is lying here, mortally wounded.", + " is lying here, incapacitated.", + " is lying here, stunned.", + " is sleeping here.", + " is resting here.", + " is sitting here.", + " is here, fighting someone.", + " is standing here." + }; + const char *sdesc; + char base[MAX_INPUT_LENGTH]; + + if (!out || outsz == 0) + return; + + *out = '\0'; + + if (!ch) { + strlcpy(out, "Someone is here.", outsz); + return; + } + + if (AFF_FLAGGED(ch, AFF_MOUNTED) && MOUNT(ch) && + IN_ROOM(MOUNT(ch)) == IN_ROOM(ch) && + MOB_FLAGGED(MOUNT(ch), MOB_MOUNT)) { + const char *rdesc = get_char_sdesc(ch); + const char *mdesc = get_char_sdesc(MOUNT(ch)); + + if (!rdesc || !*rdesc) + rdesc = "someone"; + if (!mdesc || !*mdesc) + mdesc = "someone"; + + snprintf(out, outsz, "%c%s is riding %s here.", + UPPER(*rdesc), rdesc + 1, mdesc); + strip_trailing_crlf(out); + return; + } + + if (ch->char_specials.custom_ldesc && ch->player.long_descr) { + strlcpy(out, ch->player.long_descr, outsz); + strip_trailing_crlf(out); + return; + } + + if (ch->player.long_descr && GET_POS(ch) == GET_DEFAULT_POS(ch)) { + strlcpy(out, ch->player.long_descr, outsz); + strip_trailing_crlf(out); + return; + } + + sdesc = get_char_sdesc(ch); + if (!sdesc || !*sdesc) + sdesc = "someone"; + + strlcpy(base, sdesc, sizeof(base)); + if (*base) + base[0] = UPPER(*base); + + if (GET_POS(ch) != POS_FIGHTING) { + if (!SITTING(ch)) { + snprintf(out, outsz, "%s%s", base, positions[(int) GET_POS(ch)]); + } else { + furniture = SITTING(ch); + { + const char *pos = (GET_POS(ch) == POS_STANDING ? "standing" : + (GET_POS(ch) == POS_SITTING ? "sitting" : + (GET_POS(ch) == POS_SLEEPING ? "sleeping" : "resting"))); + const char *prep = (GET_POS(ch) == POS_STANDING || GET_POS(ch) == POS_SITTING) ? "at" : "upon"; + snprintf(out, outsz, "%s is %s %s %s.", base, pos, prep, OBJS(furniture, ch)); + } + } + } else { + if (FIGHTING(ch)) { + if (IN_ROOM(ch) == IN_ROOM(FIGHTING(ch))) + snprintf(out, outsz, "%s is here, fighting %s!", base, PERS(FIGHTING(ch), ch)); + else + snprintf(out, outsz, "%s is here, fighting someone who has already left!", base); + } else { + snprintf(out, outsz, "%s is here, fighting someone who has already left!", base); + } + } + + strip_trailing_crlf(out); +} + static void list_char_to_char(struct char_data *list, struct char_data *ch) { struct char_data *i; @@ -660,6 +807,9 @@ static void list_char_to_char(struct char_data *list, struct char_data *ch) if (!IS_NPC(ch) && !PRF_FLAGGED(ch, PRF_HOLYLIGHT) && IS_NPC(i) && i->player.long_descr && *i->player.long_descr == '.') continue; + if (RIDDEN_BY(i) && IN_ROOM(RIDDEN_BY(i)) == IN_ROOM(i) && + CAN_SEE(ch, RIDDEN_BY(i))) + continue; send_to_char(ch, "%s", CCYEL(ch, C_NRM)); if (CAN_SEE(ch, i)) list_one_char(i, ch); @@ -809,18 +959,123 @@ void look_at_room(struct char_data *ch, int ignore_brief) static void look_in_direction(struct char_data *ch, int dir) { - if (EXIT(ch, dir)) { - if (EXIT(ch, dir)->general_description) - send_to_char(ch, "%s", EXIT(ch, dir)->general_description); - else - send_to_char(ch, "You see nothing special.\r\n"); + static const char *range_labels[] = { "[near]", "[far]", "[very far]" }; + room_rnum room = IN_ROOM(ch); + struct room_direction_data *start_exit = W_EXIT(room, dir); + const char *door_name = NULL; + int distance; + bool blocked = FALSE; - if (EXIT_FLAGGED(EXIT(ch, dir), EX_CLOSED) && EXIT(ch, dir)->keyword) - send_to_char(ch, "The %s is closed.\r\n", fname(EXIT(ch, dir)->keyword)); - else if (EXIT_FLAGGED(EXIT(ch, dir), EX_ISDOOR) && EXIT(ch, dir)->keyword) - send_to_char(ch, "The %s is open.\r\n", fname(EXIT(ch, dir)->keyword)); - } else - send_to_char(ch, "Nothing special there...\r\n"); + if (start_exit && start_exit->to_room != NOWHERE && + EXIT_FLAGGED(start_exit, EX_ISDOOR) && + (!EXIT_FLAGGED(start_exit, EX_HIDDEN) || PRF_FLAGGED(ch, PRF_HOLYLIGHT))) { + door_name = start_exit->keyword ? fname(start_exit->keyword) : "door"; + if (EXIT_FLAGGED(start_exit, EX_CLOSED)) { + send_to_char(ch, "You look to the %s and see the %s is closed.\r\n", dirs[dir], door_name); + return; + } + send_to_char(ch, "You look to the %s and see the %s is open:\r\n", dirs[dir], door_name); + } else { + send_to_char(ch, "You look to the %s and see:\r\n", dirs[dir]); + } + + for (distance = 0; distance < 3; distance++) { + struct room_direction_data *exit = NULL; + + if (!blocked) { + exit = W_EXIT(room, dir); + + if (!exit || exit->to_room == NOWHERE) + blocked = TRUE; + else if (EXIT_FLAGGED(exit, EX_HIDDEN) && !PRF_FLAGGED(ch, PRF_HOLYLIGHT)) + blocked = TRUE; + else if (EXIT_FLAGGED(exit, EX_CLOSED)) + blocked = TRUE; + else + room = exit->to_room; + } + + if (blocked || !VALID_ROOM_RNUM(room)) { + if (distance == 0) + send_to_char(ch, "nothing\r\n"); + break; + } + + send_to_char(ch, "%s\r\n", range_labels[distance]); + + if (!look_list_direction_chars(ch, room)) + send_to_char(ch, "nothing\r\n"); + } +} + +static bool look_can_spot_hidden(struct char_data *ch, struct char_data *tch, room_rnum room) +{ + int total; + + if (!ch || !tch) + return FALSE; + if (!AFF_FLAGGED(tch, AFF_HIDE)) + return FALSE; + if (!GET_SKILL(ch, SKILL_PERCEPTION)) + return FALSE; + if (AFF_FLAGGED(ch, AFF_BLIND)) + return FALSE; + if (IS_DARK(room) && !CAN_SEE_IN_DARK(ch)) + return FALSE; + + total = roll_scan_perception(ch); + + if (AFF_FLAGGED(ch, AFF_SCAN)) + total += 5; /* Match scan bonus from other detection checks. */ + + if (GET_STEALTH_CHECK(tch) <= 0) + SET_STEALTH_CHECK(tch, 5); + + return (total >= (GET_STEALTH_CHECK(tch) + 2)); +} + +static bool look_list_direction_chars(struct char_data *ch, room_rnum room) +{ + struct char_data *tch; + bool found = FALSE; + + if (!VALID_ROOM_RNUM(room)) + return FALSE; + if (IS_DARK(room) && !CAN_SEE_IN_DARK(ch)) + return FALSE; + + for (tch = world[room].people; tch; tch = tch->next_in_room) { + if (tch == ch) + continue; + if (!IS_NPC(ch) && !PRF_FLAGGED(ch, PRF_HOLYLIGHT) && + IS_NPC(tch) && tch->player.long_descr && *tch->player.long_descr == '.') + continue; + if (RIDDEN_BY(tch) && IN_ROOM(RIDDEN_BY(tch)) == room && + CAN_SEE(ch, RIDDEN_BY(tch))) + continue; + + if (AFF_FLAGGED(tch, AFF_HIDE)) { + if (CAN_SEE(ch, tch) || look_can_spot_hidden(ch, tch, room)) { + char hidden_ldesc[MAX_STRING_LENGTH]; + if (build_hidden_ldesc(tch, hidden_ldesc, sizeof(hidden_ldesc))) + send_to_char(ch, "%s", hidden_ldesc); + else + send_to_char(ch, "a shadowy figure\r\n"); + found = TRUE; + } + continue; + } + + if (CAN_SEE(ch, tch)) { + char ldesc[MAX_STRING_LENGTH]; + + build_current_ldesc(tch, ldesc, sizeof(ldesc)); + send_to_char(ch, "%s\r\n", ldesc); + found = TRUE; + } + } + + return found; } static void look_in_obj(struct char_data *ch, char *arg) @@ -961,6 +1216,42 @@ static void look_at_target(struct char_data *ch, char *arg) return; } + if (!found_char) { + struct char_data *tch; + char tmp[MAX_INPUT_LENGTH]; + char *name = tmp; + int matchnum; + + strlcpy(tmp, arg, sizeof(tmp)); + matchnum = get_number(&name); + if (matchnum > 0) { + for (tch = world[IN_ROOM(ch)].people; tch && matchnum; tch = tch->next_in_room) { + if (tch == ch) + continue; + if (!AFF_FLAGGED(tch, AFF_MOUNTED)) + continue; + if (!CAN_SEE(ch, tch)) + continue; + if (isname(name, (char *)get_char_sdesc(tch))) { + if (--matchnum == 0) { + found_char = tch; + break; + } + } + } + } + } + + if (found_char != NULL) { + look_at_char(found_char, ch); + if (ch != found_char) { + if (CAN_SEE(found_char, ch)) + act("$n looks at you.", TRUE, ch, 0, found_char, TO_VICT); + act("$n looks at $N.", TRUE, ch, 0, found_char, TO_NOTVICT); + } + return; + } + /* Strip off "number." from 2.foo and friends. */ if (!(fnum = get_number(&arg))) { send_to_char(ch, "Look at what?\r\n"); @@ -1144,9 +1435,14 @@ ACMD(do_coins) ACMD(do_score) { - struct time_info_data playing_time; + time_t played_seconds; + int played_minutes; + int played_hours; + int played_days; struct ac_breakdown acb; bool ismob = IS_NPC(ch); + char ldesc[MAX_STRING_LENGTH]; + const char *sdesc = get_char_sdesc(ch); compute_ac_breakdown(ch, &acb); @@ -1154,11 +1450,22 @@ ACMD(do_score) "\r\n" "====================[ Score ]====================\r\n"); + build_current_ldesc(ch, ldesc, sizeof(ldesc)); + send_to_char(ch, "Name: %s\r\n", GET_NAME(ch) ? GET_NAME(ch) : "someone"); + send_to_char(ch, "Sdesc: %s\r\n", sdesc && *sdesc ? sdesc : "someone"); + send_to_char(ch, "Ldesc: %s\r\n", *ldesc ? ldesc : "None"); + + send_to_char(ch, "Weight: %d Height: %d\r\n", + GET_WEIGHT(ch), GET_HEIGHT(ch)); + send_to_char(ch, - "HP: %d/%d Mana: %d/%d Move: %d/%d\r\n", + "HP: %d/%d Mana: %d/%d Stamina: %d/%d\r\n", GET_HIT(ch), GET_MAX_HIT(ch), GET_MANA(ch), GET_MAX_MANA(ch), - GET_MOVE(ch), GET_MAX_MOVE(ch)); + GET_STAMINA(ch), GET_MAX_STAMINA(ch)); + + send_to_char(ch, "Carrying Weight: %d/%d\r\n", + IS_CARRYING_W(ch), CAN_CARRY_W(ch)); /* Abilities and 5e modifiers */ send_to_char(ch, @@ -1189,36 +1496,31 @@ ACMD(do_score) send_to_char(ch, "Stealth Disadvantage: %s\r\n", has_stealth_disadv(ch) ? "Yes" : "No"); - send_to_char(ch, "You are %d years old.", GET_AGE(ch)); + send_to_char(ch, "You are %d years old.", GET_ROLEPLAY_AGE(ch)); - if (age(ch)->month == 0 && age(ch)->day == 0) - send_to_char(ch, " It's your birthday today.\r\n"); - else - send_to_char(ch, "\r\n"); + send_to_char(ch, "\r\n"); /* Only players have quest data */ - if (!ismob) { - send_to_char(ch, "You have %d questpoints.\r\n", GET_QUESTPOINTS(ch)); - - if (GET_QUEST(ch) == NOTHING) - send_to_char(ch, "You are not on a quest at the moment.\r\n"); - else { - send_to_char(ch, "Your current quest is: %s", - QST_NAME(real_quest(GET_QUEST(ch)))); - if (PRF_FLAGGED(ch, PRF_SHOWVNUMS)) - send_to_char(ch, " [%d]\r\n", GET_QUEST(ch)); - else - send_to_char(ch, "\r\n"); - } + if (!ismob && GET_QUEST(ch) != NOTHING) { + send_to_char(ch, "Your current quest is: %s", + QST_NAME(real_quest(GET_QUEST(ch)))); + if (PRF_FLAGGED(ch, PRF_SHOWVNUMS)) + send_to_char(ch, " [%d]\r\n", GET_QUEST(ch)); + else + send_to_char(ch, "\r\n"); } /* Only players have valid playtime data */ if (!ismob) { - playing_time = *real_time_passed((time(0) - ch->player.time.logon) + - ch->player.time.played, 0); - send_to_char(ch, "You have been playing for %d day%s and %d hour%s.\r\n", - playing_time.day, playing_time.day == 1 ? "" : "s", - playing_time.hours, playing_time.hours == 1 ? "" : "s"); + played_seconds = get_total_played_seconds(ch); + played_minutes = (played_seconds / SECS_PER_REAL_MIN) % 60; + played_hours = (played_seconds / SECS_PER_REAL_HOUR) % 24; + played_days = played_seconds / SECS_PER_REAL_DAY; + send_to_char(ch, + "You have been playing for %d minute%s, %d hour%s, and %d day%s.\r\n", + played_minutes, played_minutes == 1 ? "" : "s", + played_hours, played_hours == 1 ? "" : "s", + played_days, played_days == 1 ? "" : "s"); } /* Position */ @@ -1246,7 +1548,7 @@ ACMD(do_score) send_to_char(ch, "You are sitting.\r\n"); else { struct obj_data *furniture = SITTING(ch); - send_to_char(ch, "You are sitting upon %s.\r\n", furniture->short_description); + send_to_char(ch, "You are sitting at %s.\r\n", furniture->short_description); } break; case POS_FIGHTING: @@ -1254,7 +1556,13 @@ ACMD(do_score) FIGHTING(ch) ? PERS(FIGHTING(ch), ch) : "thin air"); break; case POS_STANDING: - send_to_char(ch, "You are standing.\r\n"); + if (AFF_FLAGGED(ch, AFF_MOUNTED) && MOUNT(ch) && + IN_ROOM(MOUNT(ch)) == IN_ROOM(ch) && + MOB_FLAGGED(MOUNT(ch), MOB_MOUNT)) { + send_to_char(ch, "You are riding %s.\r\n", get_char_sdesc(MOUNT(ch))); + } else { + send_to_char(ch, "You are standing.\r\n"); + } break; default: send_to_char(ch, "You are floating.\r\n"); @@ -1589,8 +1897,6 @@ ACMD(do_who) continue; if (!CAN_SEE(ch, tch) || GET_LEVEL(tch) < low || GET_LEVEL(tch) > high) continue; - if (outlaws && !PLR_FLAGGED(tch, PLR_KILLER) && !PLR_FLAGGED(tch, PLR_THIEF)) - continue; if (questwho && !PRF_FLAGGED(tch, PRF_QUEST)) continue; if (localwho && world[IN_ROOM(ch)].zone != world[IN_ROOM(tch)].zone) @@ -1635,8 +1941,6 @@ ACMD(do_who) continue; if (!CAN_SEE(ch, tch) || GET_LEVEL(tch) < low || GET_LEVEL(tch) > high) continue; - if (outlaws && !PLR_FLAGGED(tch, PLR_KILLER) && !PLR_FLAGGED(tch, PLR_THIEF)) - continue; if (questwho && !PRF_FLAGGED(tch, PRF_QUEST)) continue; if (localwho && world[IN_ROOM(ch)].zone != world[IN_ROOM(tch)].zone) @@ -1709,10 +2013,6 @@ ACMD(do_who) send_to_char(ch, " (noshout)"); if (PRF_FLAGGED(tch, PRF_QUEST)) send_to_char(ch, " (quest)"); - if (PLR_FLAGGED(tch, PLR_THIEF)) - send_to_char(ch, " (THIEF)"); - if (PLR_FLAGGED(tch, PLR_KILLER)) - send_to_char(ch, " (KILLER)"); send_to_char(ch, "\r\n"); } } @@ -1820,9 +2120,6 @@ ACMD(do_users) continue; if (!CAN_SEE(ch, tch) || GET_LEVEL(tch) < low || GET_LEVEL(tch) > high) continue; - if (outlaws && !PLR_FLAGGED(tch, PLR_KILLER) && - !PLR_FLAGGED(tch, PLR_THIEF)) - continue; if (showclass && !(showclass & (1 << GET_CLASS(tch)))) continue; if (GET_INVIS_LEV(tch) > GET_LEVEL(ch)) @@ -2340,7 +2637,7 @@ ACMD(do_toggle) " Brief: %-3s " " Summonable: %-3s\r\n" - " Move Display: %-3s " + " Stamina Display: %-3s " " Compact: %-3s " " Quest: %-3s\r\n" @@ -2369,7 +2666,7 @@ ACMD(do_toggle) ONOFF(PRF_FLAGGED(ch, PRF_BRIEF)), ONOFF(PRF_FLAGGED(ch, PRF_SUMMONABLE)), - ONOFF(PRF_FLAGGED(ch, PRF_DISPMOVE)), + ONOFF(PRF_FLAGGED(ch, PRF_DISPSTAMINA)), ONOFF(PRF_FLAGGED(ch, PRF_COMPACT)), ONOFF(PRF_FLAGGED(ch, PRF_QUEST)), diff --git a/src/act.item.c b/src/act.item.c index 88a8742..9c753cc 100644 --- a/src/act.item.c +++ b/src/act.item.c @@ -920,6 +920,9 @@ void weight_change_object(struct obj_data *obj, int weight) obj_from_char(obj); GET_OBJ_WEIGHT(obj) += weight; obj_to_char(obj, tmp_ch); + } else if ((tmp_ch = obj->worn_by)) { + IS_CARRYING_W(tmp_ch) += weight; + GET_OBJ_WEIGHT(obj) += weight; } else if ((tmp_obj = obj->in_obj)) { obj_from_obj(obj); GET_OBJ_WEIGHT(obj) += weight; @@ -2162,7 +2165,7 @@ ACMD(do_forage) prof_bonus = GET_PROFICIENCY(GET_SKILL(ch, SKILL_SURVIVAL)); cost = MAX(1, 10 - prof_bonus); - if (!IS_NPC(ch) && GET_MOVE(ch) < cost) { + if (!IS_NPC(ch) && GET_STAMINA(ch) < cost) { send_to_char(ch, "You are too exhausted to forage.\r\n"); return; } @@ -2171,7 +2174,7 @@ ACMD(do_forage) WAIT_STATE(ch, delay_seconds * PASSES_PER_SEC); if (!IS_NPC(ch)) - GET_MOVE(ch) = MAX(0, GET_MOVE(ch) - cost); + GET_STAMINA(ch) = MAX(0, GET_STAMINA(ch) - cost); total = roll_skill_check(ch, SKILL_SURVIVAL, 0, NULL); diff --git a/src/act.movement.c b/src/act.movement.c index 7f3eb59..295cae4 100644 --- a/src/act.movement.c +++ b/src/act.movement.c @@ -44,6 +44,13 @@ static bool validate_furniture_use(struct char_data *ch, struct obj_data *furnit bool already_there); static void attach_char_to_furniture(struct char_data *ch, struct obj_data *furniture); static const char *position_gerund(int pos); +static void clear_mount_state(struct char_data *ch); +static bool mount_skill_check(struct char_data *ch, int dc); +static bool resolve_mounted_move(struct char_data *ch, struct char_data **mount); +static int count_hitched_mounts(struct char_data *ch); +static int max_hitched_mounts(struct char_data *ch); +static struct char_data *first_hitched_mount_in_room(struct char_data *ch); +static struct char_data *find_hitched_mount_for_pack(struct char_data *ch, struct obj_data *obj); /* simple function to determine if char can walk on water */ @@ -263,6 +270,138 @@ static const char *position_gerund(int pos) return "using"; } } + +static void clear_mount_state(struct char_data *ch) +{ + struct char_data *mount; + + if (!ch) + return; + + mount = MOUNT(ch); + if (mount && RIDDEN_BY(mount) == ch) { + int rider_weight = GET_WEIGHT(ch) + IS_CARRYING_W(ch); + IS_CARRYING_W(mount) = MAX(0, IS_CARRYING_W(mount) - rider_weight); + RIDDEN_BY(mount) = NULL; + } + MOUNT(ch) = NULL; + REMOVE_BIT_AR(AFF_FLAGS(ch), AFF_MOUNTED); +} + +static bool mount_skill_check(struct char_data *ch, int dc) +{ + int total = roll_skill_check(ch, SKILL_ANIMAL_HANDLING, 0, NULL); + bool success = (total >= dc); + + gain_skill(ch, "animal handling", success); + return success; +} + +static bool resolve_mounted_move(struct char_data *ch, struct char_data **mount) +{ + struct char_data *mount_ch; + + if (!AFF_FLAGGED(ch, AFF_MOUNTED)) + return FALSE; + + mount_ch = MOUNT(ch); + if (!mount_ch || IN_ROOM(mount_ch) != IN_ROOM(ch)) { + clear_mount_state(ch); + send_to_char(ch, "You aren't mounted on anything.\r\n"); + return FALSE; + } + + if (!mount_skill_check(ch, 5)) { + send_to_char(ch, "%s refuses to move.\r\n", get_char_sdesc(mount_ch)); + act("$n tries to urge $N forward, but $N refuses to move.", + TRUE, ch, 0, mount_ch, TO_ROOM); + return FALSE; + } + + if (!mount_skill_check(ch, 3)) { + int dam = dice(1, 8); + + send_to_char(ch, "You are thrown from %s!\r\n", get_char_sdesc(mount_ch)); + act("$n is thrown from $N!", TRUE, ch, 0, mount_ch, TO_ROOM); + clear_mount_state(ch); + GET_POS(ch) = POS_RESTING; + WAIT_STATE(ch, PULSE_VIOLENCE); + damage(ch, ch, dam, TYPE_SUFFERING); + return FALSE; + } + + if (mount) + *mount = mount_ch; + return TRUE; +} + +static int count_hitched_mounts(struct char_data *ch) +{ + struct follow_type *follow; + int count = 0; + + if (!ch) + return 0; + + for (follow = ch->followers; follow; follow = follow->next) { + if (HITCHED_TO(follow->follower) == ch && + MOB_FLAGGED(follow->follower, MOB_MOUNT)) + count++; + } + + return count; +} + +static int max_hitched_mounts(struct char_data *ch) +{ + int skill = GET_SKILL(ch, SKILL_ANIMAL_HANDLING); + + if (skill > 59) + return 2; + return 1; +} + +static struct char_data *first_hitched_mount_in_room(struct char_data *ch) +{ + struct follow_type *follow; + + if (!ch) + return NULL; + + for (follow = ch->followers; follow; follow = follow->next) { + if (HITCHED_TO(follow->follower) == ch && + MOB_FLAGGED(follow->follower, MOB_MOUNT) && + IN_ROOM(follow->follower) == IN_ROOM(ch)) + return follow->follower; + } + + return NULL; +} + +static struct char_data *find_hitched_mount_for_pack(struct char_data *ch, struct obj_data *obj) +{ + struct follow_type *follow; + + if (!ch || !obj) + return NULL; + + for (follow = ch->followers; follow; follow = follow->next) { + struct char_data *mount = follow->follower; + + if (HITCHED_TO(mount) != ch || !MOB_FLAGGED(mount, MOB_MOUNT)) + continue; + if (IN_ROOM(mount) != IN_ROOM(ch)) + continue; + if ((IS_CARRYING_N(mount) + 1) > CAN_CARRY_N(mount)) + continue; + if ((IS_CARRYING_W(mount) + GET_OBJ_WEIGHT(obj)) > CAN_CARRY_W(mount)) + continue; + + return mount; + } + + return NULL; +} /** Move a PC/NPC character from their current location to a new location. This * is the standard movement locomotion function that all normal walking * movement by characters should be sent through. This function also defines @@ -290,9 +429,12 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) room_rnum was_in = IN_ROOM(ch); /* ... and the room the character will move into. */ room_rnum going_to = EXIT(ch, dir)->to_room; - /* How many movement points are required to travel from was_in to going_to. + /* How many stamina points are required to travel from was_in to going_to. * We redefine this later when we need it. */ int need_movement = 0; + /* Character whose stamina is used for movement (mounts override). */ + struct char_data *stamina_ch = ch; + bool mounted_move = FALSE; /* Contains the "leave" message to display to the was_in room. */ char leave_message[SMALL_BUFSIZE]; /*---------------------------------------------------------------------*/ @@ -400,16 +542,24 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) } /* All checks passed, nothing will prevent movement now other than lack of - * move points. */ - /* move points needed is avg. move loss for src and destination sect type */ + * stamina points. */ + /* stamina points needed is avg. move loss for src and destination sect type */ need_movement = (movement_loss[SECT(was_in)] + movement_loss[SECT(going_to)]) / 2; /* Move Point Requirement Check */ - if (GET_MOVE(ch) < need_movement && !IS_NPC(ch)) + if (AFF_FLAGGED(ch, AFF_MOUNTED) && MOUNT(ch) && IN_ROOM(MOUNT(ch)) == was_in) + { + stamina_ch = MOUNT(ch); + mounted_move = TRUE; + } + + if (GET_STAMINA(stamina_ch) < need_movement && (mounted_move || !IS_NPC(ch))) { if (need_specials_check && ch->master) send_to_char(ch, "You are too exhausted to follow.\r\n"); + else if (mounted_move) + send_to_char(ch, "Your mount is too exhausted.\r\n"); else send_to_char(ch, "You are too exhausted.\r\n"); @@ -423,8 +573,8 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) /* Begin: the leave operation. */ /*---------------------------------------------------------------------*/ /* If applicable, subtract movement cost. */ - if (GET_LEVEL(ch) < LVL_IMMORT && !IS_NPC(ch)) - GET_MOVE(ch) -= need_movement; + if (GET_LEVEL(ch) < LVL_IMMORT && (mounted_move || !IS_NPC(ch))) + GET_STAMINA(stamina_ch) -= need_movement; /* Generate the leave message and display to others in the was_in room. */ if (AFF_FLAGGED(ch, AFF_SNEAK)) { @@ -492,6 +642,7 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) /* Only here is the move successful *and* complete. Return success for * calling functions to handle post move operations. */ + clear_custom_ldesc(ch); return (1); } @@ -499,6 +650,7 @@ int perform_move(struct char_data *ch, int dir, int need_specials_check) { room_rnum was_in; struct follow_type *k, *next; + struct char_data *mount = NULL; if (ch == NULL || dir < 0 || dir >= NUM_OF_DIRS || FIGHTING(ch)) return (0); @@ -512,13 +664,22 @@ int perform_move(struct char_data *ch, int dir, int need_specials_check) else send_to_char(ch, "It seems to be closed.\r\n"); } else { - if (!ch->followers) - return (do_simple_move(ch, dir, need_specials_check)); - was_in = IN_ROOM(ch); + if (AFF_FLAGGED(ch, AFF_MOUNTED) && + !resolve_mounted_move(ch, &mount)) + return (0); + if (!do_simple_move(ch, dir, need_specials_check)) return (0); + if (mount && IN_ROOM(mount) == was_in) { + char_from_room(mount); + char_to_room(mount, IN_ROOM(ch)); + } + + if (!ch->followers) + return (1); + for (k = ch->followers; k; k = next) { next = k->next; if ((IN_ROOM(k->follower) == was_in) && @@ -936,10 +1097,69 @@ ACMD(do_stand) { char token[MAX_INPUT_LENGTH]; struct obj_data *furniture = NULL, *current_furniture = SITTING(ch); + struct char_data *mount = NULL; + char arg[MAX_INPUT_LENGTH]; bool has_target = FALSE, used_number = FALSE; int ordinal = 0; int orig_pos = GET_POS(ch); + if (*argument) { + one_argument(argument, arg); + if (*arg && !is_abbrev(arg, "at")) + mount = get_char_vis(ch, arg, NULL, FIND_CHAR_ROOM); + if (mount && MOB_FLAGGED(mount, MOB_MOUNT) && HITCHED_TO(mount) != ch) { + act("You don't have $N hitched.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + if (mount && HITCHED_TO(mount) == ch && MOB_FLAGGED(mount, MOB_MOUNT)) { + if (FIGHTING(mount)) { + act("$N is fighting right now.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + if (GET_POS(mount) == POS_RESTING) { + act("You get $N to stand up.", FALSE, ch, 0, mount, TO_CHAR); + act("$n gets $N to stand up.", TRUE, ch, 0, mount, TO_ROOM); + GET_POS(mount) = POS_STANDING; + clear_custom_ldesc(mount); + return; + } + if (GET_POS(mount) == POS_SLEEPING) { + act("$N has to wake up first.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + act("$N is already standing.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + } + + if (!*argument && AFF_FLAGGED(ch, AFF_MOUNTED) && MOUNT(ch)) { + mount = MOUNT(ch); + if (IN_ROOM(mount) != IN_ROOM(ch) || RIDDEN_BY(mount) != ch) { + clear_mount_state(ch); + send_to_char(ch, "You aren't mounted on anything.\r\n"); + return; + } + if (FIGHTING(mount)) { + send_to_char(ch, "Your mount is fighting right now.\r\n"); + return; + } + if (GET_POS(mount) != POS_SLEEPING) { + act("You get $N to rest and dismount.", FALSE, ch, 0, mount, TO_CHAR); + act("$n gets $N to rest and dismounts.", TRUE, ch, 0, mount, TO_ROOM); + GET_POS(mount) = POS_RESTING; + clear_custom_ldesc(mount); + } else { + act("$N is already asleep.", FALSE, ch, 0, mount, TO_CHAR); + } + clear_mount_state(ch); + return; + } + + if (AFF_FLAGGED(ch, AFF_MOUNTED)) { + send_to_char(ch, "You must dismount first.\r\n"); + return; + } + if (*argument) { if (!extract_furniture_token(ch, argument, token, sizeof(token), "Stand")) return; @@ -1000,6 +1220,7 @@ ACMD(do_stand) act(self_msg, TRUE, ch, furniture, 0, TO_CHAR); act(room_msg, TRUE, ch, furniture, 0, TO_ROOM); GET_POS(ch) = FIGHTING(ch) ? POS_FIGHTING : POS_STANDING; + clear_custom_ldesc(ch); return; } @@ -1020,6 +1241,7 @@ ACMD(do_stand) char_from_furniture(ch); /* Will be standing after a successful bash and may still be fighting. */ GET_POS(ch) = FIGHTING(ch) ? POS_FIGHTING : POS_STANDING; + clear_custom_ldesc(ch); break; case POS_RESTING: @@ -1033,6 +1255,7 @@ ACMD(do_stand) GET_POS(ch) = POS_STANDING; /* Were they sitting in something. */ char_from_furniture(ch); + clear_custom_ldesc(ch); break; case POS_SLEEPING: @@ -1050,6 +1273,7 @@ ACMD(do_stand) else act("$n stops floating around, and puts $s feet on the ground.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_STANDING; + clear_custom_ldesc(ch); break; } } @@ -1062,6 +1286,11 @@ ACMD(do_sit) int ordinal = 0; int orig_pos = GET_POS(ch); + if (AFF_FLAGGED(ch, AFF_MOUNTED)) { + send_to_char(ch, "You must dismount first.\r\n"); + return; + } + if (*argument) { if (!extract_furniture_token(ch, argument, token, sizeof(token), "Sit")) return; @@ -1122,6 +1351,7 @@ ACMD(do_sit) act(self_msg, TRUE, ch, furniture, 0, TO_CHAR); act(room_msg, TRUE, ch, furniture, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; + clear_custom_ldesc(ch); return; } @@ -1130,6 +1360,7 @@ ACMD(do_sit) send_to_char(ch, "You sit down.\r\n"); act("$n sits down.", FALSE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; + clear_custom_ldesc(ch); break; case POS_SITTING: send_to_char(ch, "You're sitting already.\r\n"); @@ -1141,6 +1372,7 @@ ACMD(do_sit) else act("$n stops resting and sits up.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; + clear_custom_ldesc(ch); break; case POS_SLEEPING: send_to_char(ch, "You have to wake up first.\r\n"); @@ -1155,6 +1387,7 @@ ACMD(do_sit) else act("$n stops floating around, and sits down.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; + clear_custom_ldesc(ch); break; } } @@ -1163,9 +1396,69 @@ ACMD(do_rest) { char token[MAX_INPUT_LENGTH]; struct obj_data *furniture = NULL, *current_furniture = SITTING(ch); + struct char_data *mount = NULL; + char arg[MAX_INPUT_LENGTH]; bool has_target = FALSE, used_number = FALSE; int ordinal = 0; + if (*argument) { + one_argument(argument, arg); + if (*arg && !is_abbrev(arg, "at")) + mount = get_char_vis(ch, arg, NULL, FIND_CHAR_ROOM); + if (mount && MOB_FLAGGED(mount, MOB_MOUNT) && HITCHED_TO(mount) != ch) { + act("You don't have $N hitched.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + if (mount && HITCHED_TO(mount) == ch && MOB_FLAGGED(mount, MOB_MOUNT)) { + if (FIGHTING(mount)) { + act("$N is fighting right now.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + if (GET_POS(mount) == POS_RESTING) { + act("$N is already resting.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + if (GET_POS(mount) == POS_SLEEPING) { + act("$N is already asleep.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + act("You pull on $N's reins, forcing it to rest.", FALSE, ch, 0, mount, TO_CHAR); + act("$n pulls on $N's reins, forcing it to rest.", TRUE, ch, 0, mount, TO_ROOM); + GET_POS(mount) = POS_RESTING; + clear_custom_ldesc(mount); + return; + } + } + + if (!*argument && AFF_FLAGGED(ch, AFF_MOUNTED) && MOUNT(ch)) { + mount = MOUNT(ch); + if (IN_ROOM(mount) != IN_ROOM(ch) || RIDDEN_BY(mount) != ch) { + clear_mount_state(ch); + send_to_char(ch, "You aren't mounted on anything.\r\n"); + return; + } + if (FIGHTING(mount)) { + send_to_char(ch, "Your mount is fighting right now.\r\n"); + return; + } + if (GET_POS(mount) == POS_SLEEPING) { + act("$N is already asleep.", FALSE, ch, 0, mount, TO_CHAR); + clear_mount_state(ch); + return; + } + act("You pull on $N's reins, forcing it to rest.", FALSE, ch, 0, mount, TO_CHAR); + act("$n pulls on $N's reins, forcing it to rest and dismounts.", TRUE, ch, 0, mount, TO_ROOM); + GET_POS(mount) = POS_RESTING; + clear_custom_ldesc(mount); + clear_mount_state(ch); + return; + } + + if (AFF_FLAGGED(ch, AFF_MOUNTED)) { + send_to_char(ch, "You must dismount first.\r\n"); + return; + } + if (*argument) { if (!extract_furniture_token(ch, argument, token, sizeof(token), "Rest")) return; @@ -1227,6 +1520,7 @@ ACMD(do_rest) act(self_msg, TRUE, ch, furniture, 0, TO_CHAR); act(room_msg, TRUE, ch, furniture, 0, TO_ROOM); GET_POS(ch) = POS_RESTING; + clear_custom_ldesc(ch); return; } @@ -1240,6 +1534,7 @@ ACMD(do_rest) act("$n sits down and rests.", TRUE, ch, 0, 0, TO_ROOM); } GET_POS(ch) = POS_RESTING; + clear_custom_ldesc(ch); break; case POS_SITTING: @@ -1258,6 +1553,7 @@ ACMD(do_rest) act("$n rests.", TRUE, ch, 0, 0, TO_ROOM); } GET_POS(ch) = POS_RESTING; + clear_custom_ldesc(ch); break; case POS_RESTING: @@ -1279,6 +1575,7 @@ ACMD(do_rest) else act("$n stops floating around, and rests.", FALSE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_RESTING; + clear_custom_ldesc(ch); break; } } @@ -1290,6 +1587,11 @@ ACMD(do_sleep) bool has_target = FALSE, used_number = FALSE; int ordinal = 0; + if (AFF_FLAGGED(ch, AFF_MOUNTED)) { + send_to_char(ch, "You must dismount first.\r\n"); + return; + } + if (*argument) { if (!extract_furniture_token(ch, argument, token, sizeof(token), "Sleep")) return; @@ -1332,6 +1634,7 @@ ACMD(do_sleep) act("You go to sleep on $p.", TRUE, ch, furniture, 0, TO_CHAR); act("$n lies down and falls asleep on $p.", TRUE, ch, furniture, 0, TO_ROOM); GET_POS(ch) = POS_SLEEPING; + clear_custom_ldesc(ch); return; } @@ -1354,6 +1657,7 @@ ACMD(do_sleep) act("$n lies down and falls asleep.", TRUE, ch, 0, 0, TO_ROOM); } GET_POS(ch) = POS_SLEEPING; + clear_custom_ldesc(ch); break; case POS_SLEEPING: @@ -1371,6 +1675,7 @@ ACMD(do_sleep) else act("$n stops floating around, and lies down to sleep.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SLEEPING; + clear_custom_ldesc(ch); break; } } @@ -1468,6 +1773,285 @@ ACMD(do_follow) } } +ACMD(do_mount) +{ + char arg[MAX_INPUT_LENGTH]; + struct char_data *mount; + + one_argument(argument, arg); + + if (!*arg) { + send_to_char(ch, "Mount what?\r\n"); + return; + } + + if (AFF_FLAGGED(ch, AFF_MOUNTED)) { + send_to_char(ch, "You are already mounted.\r\n"); + return; + } + + if (!(mount = get_char_vis(ch, arg, NULL, FIND_CHAR_ROOM))) { + send_to_char(ch, "%s", CONFIG_NOPERSON); + return; + } + + if (mount == ch) { + send_to_char(ch, "You can't mount yourself.\r\n"); + return; + } + + if (!IS_NPC(mount) || !MOB_FLAGGED(mount, MOB_MOUNT)) { + send_to_char(ch, "You can't mount %s!\r\n", get_char_sdesc(mount)); + return; + } + + if (HITCHED_TO(mount) && HITCHED_TO(mount) != ch) { + act("$N is already hitched to someone else.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + + if (RIDDEN_BY(mount)) { + act("$N is already being ridden.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + + if ((GET_WEIGHT(ch) + IS_CARRYING_W(ch) + IS_CARRYING_W(mount)) > CAN_CARRY_W(mount)) { + act("$N can't carry that much weight.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + + SET_BIT_AR(AFF_FLAGS(ch), AFF_MOUNTED); + MOUNT(ch) = mount; + RIDDEN_BY(mount) = ch; + IS_CARRYING_W(mount) += GET_WEIGHT(ch) + IS_CARRYING_W(ch); + + act("You mount $N.", FALSE, ch, 0, mount, TO_CHAR); + act("$n mounts $N.", TRUE, ch, 0, mount, TO_ROOM); +} + +ACMD(do_dismount) +{ + struct char_data *mount = MOUNT(ch); + + if (!AFF_FLAGGED(ch, AFF_MOUNTED) || !mount) { + clear_mount_state(ch); + send_to_char(ch, "You aren't mounted on anything.\r\n"); + return; + } + + act("You dismount $N.", FALSE, ch, 0, mount, TO_CHAR); + act("$n dismounts $N.", TRUE, ch, 0, mount, TO_ROOM); + clear_mount_state(ch); +} + +ACMD(do_hitch) +{ + char arg[MAX_INPUT_LENGTH]; + struct char_data *mount; + int max_hitched; + + one_argument(argument, arg); + + if (!*arg) { + send_to_char(ch, "Hitch what?\r\n"); + return; + } + + if (!(mount = get_char_vis(ch, arg, NULL, FIND_CHAR_ROOM))) { + send_to_char(ch, "%s", CONFIG_NOPERSON); + return; + } + + if (mount == ch) { + send_to_char(ch, "You can't hitch yourself.\r\n"); + return; + } + + if (!IS_NPC(mount) || !MOB_FLAGGED(mount, MOB_MOUNT)) { + send_to_char(ch, "You can't hitch %s!\r\n", get_char_sdesc(mount)); + return; + } + + if (RIDDEN_BY(mount) && RIDDEN_BY(mount) != ch) { + act("$N is already being ridden.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + + if (HITCHED_TO(mount) == ch) { + act("$N is already hitched to you.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + + if (HITCHED_TO(mount) && HITCHED_TO(mount) != ch) { + act("$N is already hitched to someone else.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + + if (mount->master && mount->master != ch) { + act("$N is already following someone else.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + + max_hitched = max_hitched_mounts(ch); + if (count_hitched_mounts(ch) >= max_hitched) { + send_to_char(ch, "You can't hitch any more mounts.\r\n"); + return; + } + + if (!mount->master) + add_follower(mount, ch); + + HITCHED_TO(mount) = ch; + act("You hitch $N to you.", FALSE, ch, 0, mount, TO_CHAR); + act("$n hitches $N to $m.", TRUE, ch, 0, mount, TO_ROOM); +} + +ACMD(do_unhitch) +{ + char arg[MAX_INPUT_LENGTH]; + struct char_data *mount; + + one_argument(argument, arg); + + if (!*arg) { + send_to_char(ch, "Unhitch what?\r\n"); + return; + } + + if (!(mount = get_char_vis(ch, arg, NULL, FIND_CHAR_ROOM))) { + send_to_char(ch, "%s", CONFIG_NOPERSON); + return; + } + + if (HITCHED_TO(mount) != ch || !MOB_FLAGGED(mount, MOB_MOUNT)) { + act("You don't have $N hitched.", FALSE, ch, 0, mount, TO_CHAR); + return; + } + + if (mount->master == ch) + stop_follower(mount); + else + HITCHED_TO(mount) = NULL; + + act("You unhitch $N.", FALSE, ch, 0, mount, TO_CHAR); + act("$n unhitches $N.", TRUE, ch, 0, mount, TO_ROOM); +} + +ACMD(do_pack) +{ + char arg[MAX_INPUT_LENGTH]; + struct char_data *mount; + struct obj_data *obj; + struct follow_type *follow; + bool found_mount = FALSE; + + one_argument(argument, arg); + + if (!*arg) { + for (follow = ch->followers; follow; follow = follow->next) { + bool found_item = FALSE; + + mount = follow->follower; + if (HITCHED_TO(mount) != ch || !MOB_FLAGGED(mount, MOB_MOUNT)) + continue; + if (IN_ROOM(mount) != IN_ROOM(ch)) + continue; + + found_mount = TRUE; + send_to_char(ch, "Packed on %s:\r\n", get_char_sdesc(mount)); + + for (obj = mount->carrying; obj; obj = obj->next_content) { + if (GET_OBJ_TYPE(obj) != ITEM_CONTAINER) + continue; + if (!CAN_SEE_OBJ(ch, obj)) + continue; + send_to_char(ch, " %s\r\n", obj->short_description ? obj->short_description : "something"); + found_item = TRUE; + } + + if (!found_item) + send_to_char(ch, " Nothing.\r\n"); + } + + if (!found_mount) + send_to_char(ch, "You don't have any mounts hitched.\r\n"); + return; + } + + if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying))) { + send_to_char(ch, "You don't seem to have that.\r\n"); + return; + } + + if (GET_OBJ_TYPE(obj) != ITEM_CONTAINER) { + send_to_char(ch, "You can only pack containers onto a mount.\r\n"); + return; + } + + mount = find_hitched_mount_for_pack(ch, obj); + if (!mount) { + if (!first_hitched_mount_in_room(ch)) + send_to_char(ch, "You don't have any mounts hitched here.\r\n"); + else + send_to_char(ch, "Your mount can't carry that much.\r\n"); + return; + } + + obj_from_char(obj); + obj_to_char(obj, mount); + + act("You pack $p onto $N.", FALSE, ch, obj, mount, TO_CHAR); + act("$n packs $p onto $N.", TRUE, ch, obj, mount, TO_ROOM); +} + +ACMD(do_unpack) +{ + char arg[MAX_INPUT_LENGTH]; + struct char_data *mount; + struct obj_data *obj; + struct follow_type *follow; + + one_argument(argument, arg); + + if (!*arg) { + send_to_char(ch, "Unpack what?\r\n"); + return; + } + + for (follow = ch->followers; follow; follow = follow->next) { + mount = follow->follower; + + if (HITCHED_TO(mount) != ch || !MOB_FLAGGED(mount, MOB_MOUNT)) + continue; + if (IN_ROOM(mount) != IN_ROOM(ch)) + continue; + + obj = get_obj_in_list_vis(ch, arg, NULL, mount->carrying); + if (!obj) + continue; + if (GET_OBJ_TYPE(obj) != ITEM_CONTAINER) + continue; + + if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch)) { + send_to_char(ch, "You can't carry any more items.\r\n"); + return; + } + if ((IS_CARRYING_W(ch) + GET_OBJ_WEIGHT(obj)) > CAN_CARRY_W(ch)) { + send_to_char(ch, "You can't carry that much weight.\r\n"); + return; + } + + obj_from_char(obj); + obj_to_char(obj, ch); + + act("You unpack $p from $N.", FALSE, ch, obj, mount, TO_CHAR); + act("$n unpacks $p from $N.", TRUE, ch, obj, mount, TO_ROOM); + return; + } + + send_to_char(ch, "You don't have that packed on a hitched mount.\r\n"); +} + ACMD(do_unfollow) { if (ch->master) { diff --git a/src/act.offensive.c b/src/act.offensive.c index 3d59499..61bdf03 100644 --- a/src/act.offensive.c +++ b/src/act.offensive.c @@ -54,8 +54,6 @@ ACMD(do_assist) else if (!CAN_SEE(ch, opponent)) act("You can't see who is fighting $M!", FALSE, ch, 0, helpee, TO_CHAR); /* prevent accidental pkill */ - else if (!CONFIG_PK_ALLOWED && !IS_NPC(opponent)) - send_to_char(ch, "You cannot kill other players.\r\n"); else { send_to_char(ch, "You join the fight!\r\n"); act("$N assists you!", 0, helpee, 0, ch, TO_CHAR); @@ -82,9 +80,6 @@ ACMD(do_hit) } else if (AFF_FLAGGED(ch, AFF_CHARM) && (ch->master == vict)) act("$N is just such a good friend, you simply can't hit $M.", FALSE, ch, 0, vict, TO_CHAR); else { - if (!CONFIG_PK_ALLOWED && !IS_NPC(vict) && !IS_NPC(ch)) - check_killer(ch, vict); - if ((GET_POS(ch) == POS_STANDING) && (vict != FIGHTING(ch))) { if (GET_DEX(ch) > GET_DEX(vict) || (GET_DEX(ch) == GET_DEX(vict) && rand_number(1, 2) == 1)) /* if faster */ hit(ch, vict, TYPE_UNDEFINED); /* first */ @@ -150,7 +145,7 @@ ACMD(do_backstab) return; } /* Only piercing weapons allowed */ - if (GET_OBJ_VAL(weap, 3) != TYPE_PIERCE - TYPE_HIT) { + if (GET_OBJ_VAL(weap, 2) != TYPE_PIERCE - TYPE_HIT) { send_to_char(ch, "Only piercing weapons can be used for backstabbing.\r\n"); return; } @@ -187,14 +182,14 @@ ACMD(do_backstab) /* Keeping this logic really simple so it can be adjusted later if need be */ if (crit_success) { /* Simple crit = 2x damage */ - int base = dice(GET_OBJ_VAL(weap, 1), GET_OBJ_VAL(weap, 2)); + int base = dice(GET_OBJ_VAL(weap, 0), GET_OBJ_VAL(weap, 1)); int dmg = base + GET_ABILITY_MOD(GET_DEX(ch)); if (dmg < 1) dmg = 1; dmg *= 2; damage(ch, vict, dmg, SKILL_BACKSTAB); } else { /* Hit but not crit = 1.5x damage */ - int base = dice(GET_OBJ_VAL(weap, 1), GET_OBJ_VAL(weap, 2)); + int base = dice(GET_OBJ_VAL(weap, 0), GET_OBJ_VAL(weap, 1)); int dmg = base + GET_ABILITY_MOD(GET_DEX(ch)); if (dmg < 1) dmg = 1; dmg *= 1.5; diff --git a/src/act.other.c b/src/act.other.c index 07e47f0..7c67feb 100644 --- a/src/act.other.c +++ b/src/act.other.c @@ -29,13 +29,50 @@ #include "shop.h" #include "quest.h" #include "modify.h" -#include "roomsave.h" /* Local defined utility functions */ /* do_group utility functions */ static void print_group(struct char_data *ch); static void display_group_list(struct char_data * ch); +static bool change_has_emote_tokens(const char *text) +{ + for (; text && *text; text++) { + switch (*text) { + case '~': case '!': case '%': case '^': + case '#': case '&': case '=': case '+': + case '@': + return TRUE; + } + } + return FALSE; +} + +static bool change_ends_with_punct(const char *text) +{ + size_t len = text ? strlen(text) : 0; + if (len == 0) + return FALSE; + return (text[len - 1] == '.' || text[len - 1] == '!' || text[len - 1] == '?'); +} + +static void change_trim_trailing_spaces(char *text) +{ + size_t len = text ? strlen(text) : 0; + while (len > 0 && isspace((unsigned char)text[len - 1])) { + text[len - 1] = '\0'; + len--; + } +} + +#define REROLL_REVIEW_SECONDS (2 * SECS_PER_REAL_HOUR) + +static void reroll_clear_saved(struct char_data *ch) +{ + GET_REROLL_EXPIRES(ch) = 0; + memset(&GET_REROLL_OLD_ABILS(ch), 0, sizeof(struct char_ability_data)); +} + ACMD(do_quit) { char first[MAX_INPUT_LENGTH]; @@ -182,6 +219,168 @@ ACMD(do_save) Crash_crashsave(ch); } +ACMD(do_change) +{ + char option[MAX_INPUT_LENGTH]; + char suffix[MAX_INPUT_LENGTH]; + char base_buf[MAX_INPUT_LENGTH]; + char ldesc[MAX_STRING_LENGTH]; + char *rest = argument; + const char *base; + + rest = one_argument(rest, option); + if (!*option) { + send_to_char(ch, "Usage: change ldesc \r\n"); + return; + } + + if (!is_abbrev(option, "ldesc")) { + send_to_char(ch, "Unknown change option. Available: ldesc\r\n"); + return; + } + + skip_spaces(&rest); + if (!*rest) { + send_to_char(ch, "Usage: change ldesc \r\n"); + return; + } + + if (change_has_emote_tokens(rest)) { + send_to_char(ch, "You can't use emote tokens in your ldesc.\r\n"); + return; + } + + strlcpy(suffix, rest, sizeof(suffix)); + change_trim_trailing_spaces(suffix); + if (!*suffix) { + send_to_char(ch, "Usage: change ldesc \r\n"); + return; + } + + if (!change_ends_with_punct(suffix)) + strlcat(suffix, ".", sizeof(suffix)); + + base = (GET_SHORT_DESC(ch) && *GET_SHORT_DESC(ch)) ? GET_SHORT_DESC(ch) : GET_NAME(ch); + if (!base || !*base) + base = "someone"; + + strlcpy(base_buf, base, sizeof(base_buf)); + if (*base_buf) + base_buf[0] = UPPER(*base_buf); + + snprintf(ldesc, sizeof(ldesc), "%s %s\r\n", base_buf, suffix); + + if (ch->player.long_descr) { + if (!IS_NPC(ch) || GET_MOB_RNUM(ch) == NOBODY || + ch->player.long_descr != mob_proto[GET_MOB_RNUM(ch)].player.long_descr) { + free(ch->player.long_descr); + } + } + ch->player.long_descr = strdup(ldesc); + ch->char_specials.custom_ldesc = TRUE; + + send_to_char(ch, "Long description updated.\r\n"); +} + +ACMD(do_reroll) +{ + char arg[MAX_INPUT_LENGTH]; + struct char_data *vict; + time_t now; + time_t remaining; + bool expired = FALSE; + + one_argument(argument, arg); + + if (IS_NPC(ch)) { + send_to_char(ch, "You can't reroll stats.\r\n"); + return; + } + + now = time(0); + if (GET_REROLL_EXPIRES(ch) > 0 && now >= GET_REROLL_EXPIRES(ch)) { + reroll_clear_saved(ch); + save_char(ch); + expired = TRUE; + } + + if (*arg && is_abbrev(arg, "undo")) { + if (!GET_REROLL_USED(ch)) { + send_to_char(ch, "You haven't rerolled yet.\r\n"); + return; + } + if (GET_REROLL_EXPIRES(ch) <= 0 || expired) { + send_to_char(ch, "You no longer have a reroll pending; your stats are permanent.\r\n"); + return; + } + + ch->real_abils = GET_REROLL_OLD_ABILS(ch); + affect_total(ch); + reroll_clear_saved(ch); + save_char(ch); + + send_to_char(ch, "Your original stats have been restored. You cannot reroll again.\r\n"); + send_to_char(ch, "Stats: Str %d, Int %d, Wis %d, Dex %d, Con %d, Cha %d\r\n", + GET_STR(ch), GET_INT(ch), GET_WIS(ch), + GET_DEX(ch), GET_CON(ch), GET_CHA(ch)); + return; + } + + if (*arg && GET_LEVEL(ch) >= LVL_GRGOD) { + if (!(vict = get_char_vis(ch, arg, NULL, FIND_CHAR_WORLD))) + send_to_char(ch, "There is no such player.\r\n"); + else if (IS_NPC(vict)) + send_to_char(ch, "You can't do that to a mob!\r\n"); + else { + roll_real_abils(vict); + affect_total(vict); + send_to_char(ch, "Rerolled...\r\n"); + log("(GC) %s has rerolled %s.", GET_NAME(ch), GET_NAME(vict)); + send_to_char(ch, "New stats: Str %d, Int %d, Wis %d, Dex %d, Con %d, Cha %d\r\n", + GET_STR(vict), GET_INT(vict), GET_WIS(vict), + GET_DEX(vict), GET_CON(vict), GET_CHA(vict)); + save_char(vict); + } + return; + } + + if (*arg) { + send_to_char(ch, "Usage: reroll | reroll undo\r\n"); + return; + } + + if (GET_REROLL_USED(ch)) { + if (GET_REROLL_EXPIRES(ch) > 0 && now < GET_REROLL_EXPIRES(ch)) { + remaining = GET_REROLL_EXPIRES(ch) - now; + int hours = remaining / SECS_PER_REAL_HOUR; + int mins = (remaining % SECS_PER_REAL_HOUR) / SECS_PER_REAL_MIN; + + if (hours > 0) + send_to_char(ch, "You have already rerolled. You can 'reroll undo' within %d hour%s %d minute%s.\r\n", + hours, hours == 1 ? "" : "s", mins, mins == 1 ? "" : "s"); + else + send_to_char(ch, "You have already rerolled. You can 'reroll undo' within %d minute%s.\r\n", + mins, mins == 1 ? "" : "s"); + } else { + send_to_char(ch, "You have already rerolled and cannot reroll again.\r\n"); + } + return; + } + + GET_REROLL_OLD_ABILS(ch) = ch->real_abils; + roll_real_abils(ch); + affect_total(ch); + GET_REROLL_USED(ch) = TRUE; + GET_REROLL_EXPIRES(ch) = now + REROLL_REVIEW_SECONDS; + save_char(ch); + + send_to_char(ch, "Your stats have been rerolled. You have 2 hours to review them.\r\n"); + send_to_char(ch, "New stats: Str %d, Int %d, Wis %d, Dex %d, Con %d, Cha %d\r\n", + GET_STR(ch), GET_INT(ch), GET_WIS(ch), + GET_DEX(ch), GET_CON(ch), GET_CHA(ch)); + send_to_char(ch, "Use 'reroll undo' to restore your original stats before the timer expires.\r\n"); +} + /* Generic function for commands which are normally overridden by special * procedures - i.e., shop commands, mail commands, etc. */ ACMD(do_not_here) @@ -557,7 +756,7 @@ ACMD(do_sneak) if (total < dc) { gain_skill(ch, "stealth", FALSE); WAIT_STATE(ch, PULSE_VIOLENCE / 2); - GET_MOVE(ch) -= 10; + GET_STAMINA(ch) -= 10; return; } @@ -576,7 +775,7 @@ ACMD(do_sneak) SET_STEALTH_CHECK(ch, MAX(GET_STEALTH_CHECK(ch), total)); gain_skill(ch, "stealth", TRUE); - GET_MOVE(ch) -= 10; + GET_STAMINA(ch) -= 10; } ACMD(do_hide) @@ -612,7 +811,7 @@ ACMD(do_hide) /* Failure */ gain_skill(ch, "stealth", FALSE); WAIT_STATE(ch, PULSE_VIOLENCE / 2); - GET_MOVE(ch) -= 10; + GET_STAMINA(ch) -= 10; return; } @@ -623,7 +822,7 @@ ACMD(do_hide) send_to_char(ch, "You hide yourself as best you can.\r\n"); gain_skill(ch, "stealth", TRUE); WAIT_STATE(ch, PULSE_VIOLENCE / 2); - GET_MOVE(ch) -= 10; + GET_STAMINA(ch) -= 10; } static void remember_scan_target(struct char_data *ch, struct char_data *tch) @@ -886,7 +1085,11 @@ bool perform_scan_sweep(struct char_data *ch) continue; if (total >= scan_target_dc(tch)) { - send_to_char(ch, "A shadowy figure.\r\n"); + char hidden_ldesc[MAX_STRING_LENGTH]; + if (build_hidden_ldesc(tch, hidden_ldesc, sizeof(hidden_ldesc))) + send_to_char(ch, "%s", hidden_ldesc); + else + send_to_char(ch, "A shadowy figure.\r\n"); remember_scan_target(ch, tch); found_any = TRUE; } else { @@ -929,7 +1132,7 @@ ACMD(do_scan) act("$n studies $s surroundings with a wary gaze.", TRUE, ch, 0, 0, TO_ROOM); WAIT_STATE(ch, PULSE_VIOLENCE / 2); - GET_MOVE(ch) -= 10; + GET_STAMINA(ch) -= 10; } ACMD(do_listen) @@ -959,7 +1162,7 @@ ACMD(do_listen) send_to_char(ch, "You focus entirely on every whisper and distant sound.\r\n"); WAIT_STATE(ch, PULSE_VIOLENCE / 2); - GET_MOVE(ch) -= 10; + GET_STAMINA(ch) -= 10; } ACMD(do_palm) @@ -1307,7 +1510,7 @@ static void print_group(struct char_data *ch) GROUP_LEADER(GROUP(ch)) == k ? CBGRN(ch, C_NRM) : CCGRN(ch, C_NRM), GET_HIT(k), GET_MAX_HIT(k), GET_MANA(k), GET_MAX_MANA(k), - GET_MOVE(k), GET_MAX_MOVE(k), + GET_STAMINA(k), GET_MAX_STAMINA(k), CCNRM(ch, C_NRM)); } @@ -1464,7 +1667,7 @@ ACMD(do_report) GET_NAME(ch), GET_HIT(ch), GET_MAX_HIT(ch), GET_MANA(ch), GET_MAX_MANA(ch), - GET_MOVE(ch), GET_MAX_MOVE(ch)); + GET_STAMINA(ch), GET_MAX_STAMINA(ch)); } ACMD(do_split) @@ -1600,7 +1803,7 @@ ACMD(do_display) skip_spaces(&argument); if (!*argument) { - send_to_char(ch, "Usage: prompt { { H | M | V } | all | auto | none }\r\n"); + send_to_char(ch, "Usage: prompt { { H | M | S } | all | auto | none }\r\n"); return; } @@ -1613,15 +1816,15 @@ ACMD(do_display) if (!str_cmp(argument, "on") || !str_cmp(argument, "all")) { SET_BIT_AR(PRF_FLAGS(ch), PRF_DISPHP); SET_BIT_AR(PRF_FLAGS(ch), PRF_DISPMANA); - SET_BIT_AR(PRF_FLAGS(ch), PRF_DISPMOVE); + SET_BIT_AR(PRF_FLAGS(ch), PRF_DISPSTAMINA); } else if (!str_cmp(argument, "off") || !str_cmp(argument, "none")) { REMOVE_BIT_AR(PRF_FLAGS(ch), PRF_DISPHP); REMOVE_BIT_AR(PRF_FLAGS(ch), PRF_DISPMANA); - REMOVE_BIT_AR(PRF_FLAGS(ch), PRF_DISPMOVE); + REMOVE_BIT_AR(PRF_FLAGS(ch), PRF_DISPSTAMINA); } else { REMOVE_BIT_AR(PRF_FLAGS(ch), PRF_DISPHP); REMOVE_BIT_AR(PRF_FLAGS(ch), PRF_DISPMANA); - REMOVE_BIT_AR(PRF_FLAGS(ch), PRF_DISPMOVE); + REMOVE_BIT_AR(PRF_FLAGS(ch), PRF_DISPSTAMINA); for (i = 0; i < strlen(argument); i++) { switch (LOWER(argument[i])) { @@ -1631,11 +1834,12 @@ ACMD(do_display) case 'm': SET_BIT_AR(PRF_FLAGS(ch), PRF_DISPMANA); break; + case 's': case 'v': - SET_BIT_AR(PRF_FLAGS(ch), PRF_DISPMOVE); + SET_BIT_AR(PRF_FLAGS(ch), PRF_DISPSTAMINA); break; default: - send_to_char(ch, "Usage: prompt { { H | M | V } | all | auto | none }\r\n"); + send_to_char(ch, "Usage: prompt { { H | M | S } | all | auto | none }\r\n"); return; } } diff --git a/src/act.wizard.c b/src/act.wizard.c index 794c3fa..6f8ef80 100644 --- a/src/act.wizard.c +++ b/src/act.wizard.c @@ -26,16 +26,17 @@ #include "act.h" #include "genzon.h" /* for real_zone_by_thing */ #include "class.h" +#include "species.h" #include "genmob.h" #include "genolc.h" #include "genobj.h" +#include "genshp.h" #include "fight.h" #include "house.h" #include "modify.h" #include "quest.h" #include "ban.h" #include "screen.h" -#include "roomsave.h" /* local utility functions with file scope */ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, char *val_arg); @@ -43,6 +44,7 @@ static void perform_immort_invis(struct char_data *ch, int level); static void do_stat_room(struct char_data *ch, struct room_data *rm); static void do_stat_object(struct char_data *ch, struct obj_data *j); static void do_stat_character(struct char_data *ch, struct char_data *k); +static void do_stat_shop(struct char_data *ch, shop_rnum shop_nr); static void stop_snooping(struct char_data *ch); static struct obj_data *find_inventory_coin(struct char_data *ch); static void remove_other_coins_from_list(struct obj_data *list, struct obj_data *keep); @@ -66,7 +68,12 @@ static const char *stat_border_line(void); static void stat_table_border(struct char_data *ch); static void stat_table_row(struct char_data *ch, const char *label, const char *value); static void stat_table_row_fmt(struct char_data *ch, const char *label, const char *fmt, ...) __attribute__((format(printf,3,4))); +static void stat_table_border_buf(char *buf, size_t buf_size, size_t *len); +static void stat_table_row_buf(char *buf, size_t buf_size, size_t *len, const char *label, const char *value); +static void stat_table_row_fmt_buf(char *buf, size_t buf_size, size_t *len, const char *label, const char *fmt, ...) __attribute__((format(printf,5,6))); static void stat_appendf(char *buf, size_t buf_size, size_t *len, const char *fmt, ...) __attribute__((format(printf,4,5))); +static void stat_append_list_item(char *buf, size_t buf_size, size_t *len, size_t *line_len, const char *item); +static void stat_format_notrade_classes(bitvector_t flags, char *out, size_t outsz); static void stat_format_script_triggers(struct script_data *sc, char *buf, size_t buf_size); static void stat_format_script_globals(struct script_data *sc, char *buf, size_t buf_size); static void stat_format_script_memory(struct script_memory *mem, char *buf, size_t buf_size); @@ -208,6 +215,60 @@ static void stat_table_row_fmt(struct char_data *ch, const char *label, const ch stat_table_row(ch, label, buf); } +static void stat_table_border_buf(char *buf, size_t buf_size, size_t *len) +{ + stat_appendf(buf, buf_size, len, "%s", stat_border_line()); +} + +static void stat_table_row_buf(char *buf, size_t buf_size, size_t *len, const char *label, const char *value) +{ + const char *text = (value && *value) ? value : ""; + bool printed = FALSE; + + while (*text) { + while (*text == '\r' || *text == '\n') + text++; + if (!*text) + break; + + char chunk[STAT_VALUE_WIDTH + 1]; + const char *next = stat_next_chunk(text, chunk, STAT_VALUE_WIDTH); + + if (!*chunk) { + text = next; + continue; + } + + stat_appendf(buf, buf_size, len, "| %-*s | %-*s |\r\n", + STAT_LABEL_WIDTH, + printed || !label ? "" : label, + STAT_VALUE_WIDTH, + chunk); + + printed = TRUE; + text = next; + } + + if (!printed) + stat_appendf(buf, buf_size, len, "| %-*s | %-*s |\r\n", + STAT_LABEL_WIDTH, + label ? label : "", + STAT_VALUE_WIDTH, + (value && *value) ? value : ""); +} + +static void stat_table_row_fmt_buf(char *buf, size_t buf_size, size_t *len, const char *label, const char *fmt, ...) +{ + char row[MAX_STRING_LENGTH]; + va_list args; + + va_start(args, fmt); + vsnprintf(row, sizeof(row), fmt, args); + va_end(args); + + stat_table_row_buf(buf, buf_size, len, label, row); +} + static void stat_appendf(char *buf, size_t buf_size, size_t *len, const char *fmt, ...) { if (*len >= buf_size) @@ -227,6 +288,52 @@ static void stat_appendf(char *buf, size_t buf_size, size_t *len, const char *fm *len += wrote; } +static void stat_append_list_item(char *buf, size_t buf_size, size_t *len, size_t *line_len, const char *item) +{ + size_t item_len = strlen(item); + + if (*line_len && *line_len + 2 + item_len > STAT_VALUE_WIDTH) { + stat_appendf(buf, buf_size, len, "\n"); + *line_len = 0; + } + + if (*line_len) { + stat_appendf(buf, buf_size, len, ", "); + *line_len += 2; + } + + stat_appendf(buf, buf_size, len, "%s", item); + *line_len += item_len; +} + +static void stat_format_notrade_classes(bitvector_t flags, char *out, size_t outsz) +{ + size_t len = 0; + int i, found = 0; + + if (!out || outsz == 0) + return; + + out[0] = '\0'; + + for (i = TRADE_CLASS_START; i < NUM_TRADERS; i++) { + if (IS_SET(flags, 1 << i)) { + int n = snprintf(out + len, outsz - len, "%s%s", found ? " " : "", trade_letters[i]); + + if (n < 0 || (size_t)n >= outsz - len) { + out[outsz - 1] = '\0'; + return; + } + + len += (size_t)n; + found = 1; + } + } + + if (!found) + strlcpy(out, "NOBITS", outsz); +} + static void stat_format_script_triggers(struct script_data *sc, char *buf, size_t buf_size) { size_t len = 0; @@ -1792,8 +1899,7 @@ static void do_stat_character(struct char_data *ch, struct char_data *k) zone_table[world[IN_ROOM(k)].zone].number); if (!IS_NPC(k)) { - char created[64], logon[64], olc[64] = ""; - strftime(created, sizeof(created), "%b %d %Y", localtime(&(k->player.time.birth))); + char logon[64], olc[64] = ""; strftime(logon, sizeof(logon), "%b %d %Y", localtime(&(k->player.time.logon))); if (GET_LEVEL(k) >= LVL_BUILDER) { @@ -1809,35 +1915,43 @@ static void do_stat_character(struct char_data *ch, struct char_data *k) snprintf(olc, sizeof(olc), ", OLC %d", GET_OLC_ZONE(k)); } - stat_table_row_fmt(ch, "Account", "Created %s, Last %s%s", - created, logon, olc); - stat_table_row_fmt(ch, "Age/Play", "Age %d, Played %dh %dm", - age(k)->year, - k->player.time.played / 3600, - (k->player.time.played % 3600) / 60); + stat_table_row_fmt(ch, "Account", "Last %s%s", + logon, olc); + { + time_t played_seconds = get_total_played_seconds(k); + int played_minutes = (played_seconds / SECS_PER_REAL_MIN) % 60; + int played_hours = (played_seconds / SECS_PER_REAL_HOUR) % 24; + int played_days = played_seconds / SECS_PER_REAL_DAY; + stat_table_row_fmt(ch, "Age/Playtime", "Age %d, %dd %dh %dm", + GET_ROLEPLAY_AGE(k), played_days, played_hours, played_minutes); + } } stat_table_row_fmt(ch, "Class", "%s", CLASS_NAME(k)); + stat_table_row_fmt(ch, "Species", "%s", get_species_name(GET_SPECIES(k))); stat_table_row_fmt(ch, "Attributes", "Str %d Int %d Wis %d Dex %d Con %d Cha %d", GET_STR(k), GET_INT(k), GET_WIS(k), GET_DEX(k), GET_CON(k), GET_CHA(k)); + stat_table_row_fmt(ch, "Size", "Weight %d, Height %d", + GET_WEIGHT(k), GET_HEIGHT(k)); + stat_table_row_fmt(ch, "Saving Throws", - "Str %+d (%+d) Dex %+d (%+d) Con %+d (%+d) Int %+d (%+d) Wis %+d (%+d) Cha %+d (%+d)", - get_save_mod(k, ABIL_STR), GET_SAVE(k, ABIL_STR), - get_save_mod(k, ABIL_DEX), GET_SAVE(k, ABIL_DEX), - get_save_mod(k, ABIL_CON), GET_SAVE(k, ABIL_CON), - get_save_mod(k, ABIL_INT), GET_SAVE(k, ABIL_INT), - get_save_mod(k, ABIL_WIS), GET_SAVE(k, ABIL_WIS), - get_save_mod(k, ABIL_CHA), GET_SAVE(k, ABIL_CHA)); + "Str %+d Dex %+d Con %+d Int %+d Wis %+d Cha %+d", + get_save_mod(k, ABIL_STR), + get_save_mod(k, ABIL_DEX), + get_save_mod(k, ABIL_CON), + get_save_mod(k, ABIL_INT), + get_save_mod(k, ABIL_WIS), + get_save_mod(k, ABIL_CHA)); stat_table_row_fmt(ch, "Vitals", - "HP %d/%d (+%d) | Mana %d/%d (+%d) | Move %d/%d (+%d)", + "HP %d/%d (+%d) | Mana %d/%d (+%d) | Stamina %d/%d (+%d)", GET_HIT(k), GET_MAX_HIT(k), hit_gain(k), GET_MANA(k), GET_MAX_MANA(k), mana_gain(k), - GET_MOVE(k), GET_MAX_MOVE(k), move_gain(k)); + GET_STAMINA(k), GET_MAX_STAMINA(k), move_gain(k)); stat_table_row_fmt(ch, "Currency", "Coins %d, Bank %d (Total %d)", GET_COINS(k), GET_BANK_COINS(k), GET_COINS(k) + GET_BANK_COINS(k)); @@ -1933,6 +2047,125 @@ static void do_stat_character(struct char_data *ch, struct char_data *k) stat_table_border(ch); } +static void do_stat_shop(struct char_data *ch, shop_rnum shop_nr) +{ + char entry[MAX_STRING_LENGTH]; + char list[MAX_STRING_LENGTH]; + char buf[MAX_STRING_LENGTH]; + char bits[MAX_STRING_LENGTH]; + char *out; + size_t out_size = MAX_STRING_LENGTH * 4; + size_t len = 0; + size_t line_len = 0; + size_t list_len = 0; + int i; + + CREATE(out, char, out_size); + out[0] = '\0'; + + stat_table_border_buf(out, out_size, &len); + stat_table_row_fmt_buf(out, out_size, &len, "Identifiers", "VNum #%d (RNum %d)", + SHOP_NUM(shop_nr), shop_nr); + + if (SHOP_KEEPER(shop_nr) == NOBODY) { + strlcpy(buf, "None", sizeof(buf)); + } else { + snprintf(buf, sizeof(buf), "[%d] %s", + mob_index[SHOP_KEEPER(shop_nr)].vnum, + mob_proto[SHOP_KEEPER(shop_nr)].player.short_descr ? + mob_proto[SHOP_KEEPER(shop_nr)].player.short_descr : ""); + } + stat_table_row_buf(out, out_size, &len, "Keeper", buf); + + stat_table_row_fmt_buf(out, out_size, &len, "Open/Close", + "Open1 %d Close1 %d, Open2 %d Close2 %d", + SHOP_OPEN1(shop_nr), SHOP_CLOSE1(shop_nr), + SHOP_OPEN2(shop_nr), SHOP_CLOSE2(shop_nr)); + + stat_table_row_fmt_buf(out, out_size, &len, "Rates", + "Sell %1.2f, Buy %1.2f", + SHOP_BUYPROFIT(shop_nr), SHOP_SELLPROFIT(shop_nr)); + + list[0] = '\0'; + line_len = 0; + list_len = 0; + for (i = 0; SHOP_ROOM(shop_nr, i) != NOWHERE; i++) { + room_rnum rnum = real_room(SHOP_ROOM(shop_nr, i)); + if (rnum != NOWHERE) + snprintf(entry, sizeof(entry), "#%d %s", + GET_ROOM_VNUM(rnum), world[rnum].name); + else + snprintf(entry, sizeof(entry), " (#%d)", SHOP_ROOM(shop_nr, i)); + stat_append_list_item(list, sizeof(list), &list_len, &line_len, entry); + } + if (!list_len) + strlcpy(list, "None", sizeof(list)); + stat_table_row_buf(out, out_size, &len, "Rooms", list); + + list[0] = '\0'; + list_len = 0; + line_len = 0; + for (i = 0; SHOP_PRODUCT(shop_nr, i) != NOTHING; i++) { + obj_rnum rnum = SHOP_PRODUCT(shop_nr, i); + if (rnum != NOTHING && rnum >= 0 && rnum <= top_of_objt) { + snprintf(entry, sizeof(entry), "%s (#%d)", + obj_proto[rnum].short_description ? obj_proto[rnum].short_description : "", + obj_index[rnum].vnum); + } else + snprintf(entry, sizeof(entry), ""); + stat_append_list_item(list, sizeof(list), &list_len, &line_len, entry); + } + if (!list_len) + strlcpy(list, "None", sizeof(list)); + stat_table_row_buf(out, out_size, &len, "Products", list); + + list[0] = '\0'; + list_len = 0; + line_len = 0; + for (i = 0; SHOP_BUYTYPE(shop_nr, i) != NOTHING; i++) { + const char *keyword = SHOP_BUYWORD(shop_nr, i) ? SHOP_BUYWORD(shop_nr, i) : "all"; + if (SHOP_BUYTYPE(shop_nr, i) >= 0 && SHOP_BUYTYPE(shop_nr, i) < NUM_ITEM_TYPES) { + snprintf(entry, sizeof(entry), "%s (#%d) [%s]", + item_types[SHOP_BUYTYPE(shop_nr, i)], SHOP_BUYTYPE(shop_nr, i), keyword); + } else + snprintf(entry, sizeof(entry), "Unknown (#%d) [%s]", SHOP_BUYTYPE(shop_nr, i), keyword); + stat_append_list_item(list, sizeof(list), &list_len, &line_len, entry); + } + if (!list_len) + strlcpy(list, "None", sizeof(list)); + stat_table_row_buf(out, out_size, &len, "Accept Types", list); + + stat_format_notrade_classes(SHOP_TRADE_WITH(shop_nr), buf, sizeof(buf)); + stat_table_row_buf(out, out_size, &len, "No Trade With", buf); + + sprintbit(SHOP_BITVECTOR(shop_nr), shop_bits, bits, sizeof(bits)); + stat_table_row_buf(out, out_size, &len, "Shop Flags", bits); + + stat_table_row_buf(out, out_size, &len, "Keeper No Item", + shop_index[shop_nr].no_such_item1 ? shop_index[shop_nr].no_such_item1 : "None"); + stat_table_row_buf(out, out_size, &len, "Player No Item", + shop_index[shop_nr].no_such_item2 ? shop_index[shop_nr].no_such_item2 : "None"); + stat_table_row_buf(out, out_size, &len, "Keeper No Cash", + shop_index[shop_nr].missing_cash1 ? shop_index[shop_nr].missing_cash1 : "None"); + stat_table_row_buf(out, out_size, &len, "Player No Cash", + shop_index[shop_nr].missing_cash2 ? shop_index[shop_nr].missing_cash2 : "None"); + stat_table_row_buf(out, out_size, &len, "Keeper No Buy", + shop_index[shop_nr].do_not_buy ? shop_index[shop_nr].do_not_buy : "None"); + stat_table_row_buf(out, out_size, &len, "Buy Success", + shop_index[shop_nr].message_buy ? shop_index[shop_nr].message_buy : "None"); + stat_table_row_buf(out, out_size, &len, "Sell Success", + shop_index[shop_nr].message_sell ? shop_index[shop_nr].message_sell : "None"); + + stat_table_border_buf(out, out_size, &len); + + if (ch->desc) + page_string(ch->desc, out, TRUE); + else + send_to_char(ch, "%s", out); + + free(out); +} + ACMD(do_stat) { char buf1[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH]; @@ -2006,6 +2239,33 @@ ACMD(do_stat) else send_to_char(ch, "No such object around.\r\n"); } + } else if (is_abbrev(buf1, "shop")) { + shop_rnum shop_nr = NOWHERE; + if (!*buf2) { + int found = FALSE; + room_vnum rvnum = GET_ROOM_VNUM(IN_ROOM(ch)); + for (shop_nr = 0; shop_nr <= top_shop; shop_nr++) { + for (int j = 0; SHOP_ROOM(shop_nr, j) != NOWHERE; j++) { + if (SHOP_ROOM(shop_nr, j) == rvnum) { + found = TRUE; + break; + } + } + if (found) + break; + } + if (!found) { + send_to_char(ch, "This isn't a shop.\r\n"); + return; + } + } else { + shop_nr = real_shop(atoi(buf2)); + if (shop_nr == NOWHERE) { + send_to_char(ch, "That is not a valid shop.\r\n"); + return; + } + } + do_stat_shop(ch, shop_nr); } else if (is_abbrev(buf1, "zone")) { if (!*buf2) { print_zone(ch, zone_table[world[IN_ROOM(ch)].zone].number); @@ -2540,7 +2800,7 @@ ACMD(do_restore) GET_HIT(vict) = GET_MAX_HIT(vict); GET_MANA(vict) = GET_MAX_MANA(vict); - GET_MOVE(vict) = GET_MAX_MOVE(vict); + GET_STAMINA(vict) = GET_MAX_STAMINA(vict); update_pos(vict); send_to_char(ch, "%s has been fully healed.\r\n", GET_NAME(vict)); @@ -2556,7 +2816,7 @@ ACMD(do_restore) GET_HIT(vict) = GET_MAX_HIT(vict); GET_MANA(vict) = GET_MAX_MANA(vict); - GET_MOVE(vict) = GET_MAX_MOVE(vict); + GET_STAMINA(vict) = GET_MAX_STAMINA(vict); if (!IS_NPC(vict) && GET_LEVEL(ch) >= LVL_GRGOD) { if (GET_LEVEL(vict) >= LVL_IMMORT) @@ -3302,16 +3562,8 @@ ACMD(do_wizutil) GET_DEX(vict), GET_CON(vict), GET_CHA(vict)); break; case SCMD_PARDON: - if (!PLR_FLAGGED(vict, PLR_THIEF) && !PLR_FLAGGED(vict, PLR_KILLER)) { - send_to_char(ch, "Your victim is not flagged.\r\n"); - return; - } - REMOVE_BIT_AR(PLR_FLAGS(vict), PLR_THIEF); - REMOVE_BIT_AR(PLR_FLAGS(vict), PLR_KILLER); - send_to_char(ch, "Pardoned.\r\n"); - send_to_char(vict, "You have been pardoned by the Gods!\r\n"); - mudlog(BRF, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s pardoned by %s", GET_NAME(vict), GET_NAME(ch)); - break; + send_to_char(ch, "Criminal flags are currently disabled.\r\n"); + return; case SCMD_MUTE: result = PLR_TOG_CHK(vict, PLR_NOSHOUT); mudlog(BRF, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) Mute %s for %s by %s.", @@ -3567,9 +3819,8 @@ ACMD(do_show) send_to_char(ch, "Player: %-12s (%s) [%2d %s]\r\n", GET_NAME(vict), genders[(int) GET_SEX(vict)], GET_LEVEL(vict), CLASS_ABBR(vict)); - send_to_char(ch, "Coins: %-8d Bal: %-8d Exp: %-8d Align: %-5d\r\n", - GET_COINS(vict), GET_BANK_COINS(vict), GET_EXP(vict), - GET_ALIGNMENT(vict)); + send_to_char(ch, "Coins: %-8d Bal: %-8d Exp: %-8d\r\n", + GET_COINS(vict), GET_BANK_COINS(vict), GET_EXP(vict)); send_to_char(ch, "Started: %-25.25s Last: %-25.25s\r\n", buf1, buf2); send_to_char(ch, "Played: %dh %dm\r\n", (int) (vict->player.time.played / 3600), @@ -3764,9 +4015,8 @@ static struct set_struct { { "ac", LVL_BUILDER, BOTH, NUMBER }, /* 0 */ { "afk", LVL_BUILDER, PC, BINARY }, /* 1 */ { "age", LVL_GOD, BOTH, NUMBER }, - { "align", LVL_BUILDER, BOTH, NUMBER }, { "bank", LVL_BUILDER, PC, NUMBER }, - { "brief", LVL_GOD, PC, BINARY }, /* 5 */ + { "brief", LVL_GOD, PC, BINARY }, /* 4 */ { "cha", LVL_BUILDER, BOTH, NUMBER }, { "class", LVL_BUILDER, BOTH, MISC }, { "color", LVL_GOD, PC, BINARY }, @@ -3775,46 +4025,45 @@ static struct set_struct { { "dex", LVL_BUILDER, BOTH, NUMBER }, { "drunk", LVL_BUILDER, BOTH, MISC }, { "exp", LVL_GOD, BOTH, NUMBER }, - { "frozen", LVL_GRGOD, PC, BINARY }, /* 15 */ + { "frozen", LVL_GRGOD, PC, BINARY }, /* 13 */ { "coins", LVL_BUILDER, BOTH, NUMBER }, { "height", LVL_BUILDER, BOTH, NUMBER }, { "hitpoints", LVL_BUILDER, BOTH, NUMBER }, - { "hunger", LVL_BUILDER, BOTH, MISC }, /* 20 */ + { "hunger", LVL_BUILDER, BOTH, MISC }, /* 17 */ { "int", LVL_BUILDER, BOTH, NUMBER }, { "invis", LVL_GOD, PC, NUMBER }, { "invstart", LVL_BUILDER, PC, BINARY }, - { "killer", LVL_GOD, PC, BINARY }, - { "level", LVL_GRGOD, BOTH, NUMBER }, /* 25 */ + { "level", LVL_GRGOD, BOTH, NUMBER }, /* 21 */ { "loadroom", LVL_BUILDER, PC, MISC }, { "mana", LVL_BUILDER, BOTH, NUMBER }, { "maxhit", LVL_BUILDER, BOTH, NUMBER }, { "maxmana", LVL_BUILDER, BOTH, NUMBER }, - { "maxmove", LVL_BUILDER, BOTH, NUMBER }, /* 30 */ - { "move", LVL_BUILDER, BOTH, NUMBER }, + { "maxstam", LVL_BUILDER, BOTH, NUMBER }, /* 26 */ { "name", LVL_IMMORT, PC, MISC }, { "nodelete", LVL_GOD, PC, BINARY }, { "nohassle", LVL_GOD, PC, BINARY }, - { "nosummon", LVL_BUILDER, PC, BINARY }, /* 35 */ + { "nosummon", LVL_BUILDER, PC, BINARY }, { "nowizlist", LVL_GRGOD, PC, BINARY }, { "olc", LVL_GRGOD, PC, MISC }, { "password", LVL_GRGOD, PC, MISC }, { "poofin", LVL_IMMORT, PC, MISC }, - { "poofout", LVL_IMMORT, PC, MISC }, /* 40 */ + { "poofout", LVL_IMMORT, PC, MISC }, { "quest", LVL_GOD, PC, BINARY }, { "room", LVL_BUILDER, BOTH, NUMBER }, - { "screenwidth", LVL_GOD, PC, NUMBER }, + { "screenwidth", LVL_GOD, PC, NUMBER }, /* 38 */ { "sex", LVL_GOD, BOTH, MISC }, - { "showvnums", LVL_BUILDER, PC, BINARY }, /* 45 */ + { "showvnums", LVL_BUILDER, PC, BINARY }, { "siteok", LVL_GOD, PC, BINARY }, { "skill", LVL_GOD, BOTH, NUMBER }, + { "stam", LVL_BUILDER, BOTH, NUMBER }, /* 43 */ { "str", LVL_BUILDER, BOTH, NUMBER }, - { "thief", LVL_GOD, PC, BINARY }, - { "thirst", LVL_BUILDER, BOTH, MISC }, /* 50 */ + { "thirst", LVL_BUILDER, BOTH, MISC }, { "variable", LVL_GRGOD, PC, MISC }, { "weight", LVL_BUILDER, BOTH, NUMBER }, { "wis", LVL_BUILDER, BOTH, NUMBER }, - { "questpoints", LVL_GOD, PC, NUMBER }, - { "questhistory", LVL_GOD, PC, NUMBER }, /* 55 */ + { "questpoints", LVL_GOD, PC, NUMBER }, /* 49 */ + { "questhistory", LVL_GOD, PC, NUMBER }, + { "species", LVL_BUILDER, BOTH, MISC }, { "\n", 0, BOTH, MISC } }; @@ -3871,22 +4120,16 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c send_to_char(ch, "Ages 2 to 200 accepted.\r\n"); return (0); } - /* NOTE: May not display the exact age specified due to the integer - * division used elsewhere in the code. Seems to only happen for - * some values below the starting age (17) anyway. -gg 5/27/98 */ - vict->player.time.birth = time(0) - ((value - 17) * SECS_PER_MUD_YEAR); + GET_ROLEPLAY_AGE(vict) = LIMIT(value, MIN_CHAR_AGE, MAX_CHAR_AGE); + GET_ROLEPLAY_AGE_YEAR(vict) = time_info.year; break; - case 3: /* align */ - GET_ALIGNMENT(vict) = RANGE(-1000, 1000); - affect_total(vict); - break; - case 4: /* bank */ + case 3: /* bank */ GET_BANK_COINS(vict) = RANGE(0, 100000000); break; - case 5: /* brief */ + case 4: /* brief */ SET_OR_REMOVE(PRF_FLAGS(vict), PRF_BRIEF); break; - case 6: /* cha */ + case 5: /* cha */ if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD) RANGE(3, 25); else @@ -3894,18 +4137,18 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c vict->real_abils.cha = value; affect_total(vict); break; - case 7: /* class */ + case 6: /* class */ if ((i = parse_class(*val_arg)) == CLASS_UNDEFINED) { send_to_char(ch, "That is not a class.\r\n"); return (0); } GET_CLASS(vict) = i; break; - case 8: /* color */ + case 7: /* color */ SET_OR_REMOVE(PRF_FLAGS(vict), (PRF_COLOR_1)); SET_OR_REMOVE(PRF_FLAGS(vict), (PRF_COLOR_2)); break; - case 9: /* con */ + case 8: /* con */ if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD) RANGE(3, 25); else @@ -3913,10 +4156,10 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c vict->real_abils.con = value; affect_total(vict); break; - case 10: /* delete */ + case 9: /* delete */ SET_OR_REMOVE(PLR_FLAGS(vict), PLR_DELETED); break; - case 11: /* dex */ + case 10: /* dex */ if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD) RANGE(3, 25); else @@ -3924,7 +4167,7 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c vict->real_abils.dex = value; affect_total(vict); break; - case 12: /* drunk */ + case 11: /* drunk */ if (!str_cmp(val_arg, "off")) { GET_COND(vict, DRUNK) = -1; send_to_char(ch, "%s's drunkenness is now off.\r\n", GET_NAME(vict)); @@ -3938,17 +4181,17 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c return (0); } break; - case 13: /* exp */ + case 12: /* exp */ vict->points.exp = RANGE(0, 50000000); break; - case 14: /* frozen */ + case 13: /* frozen */ if (ch == vict && on) { send_to_char(ch, "Better not -- could be a long winter!\r\n"); return (0); } SET_OR_REMOVE(PLR_FLAGS(vict), PLR_FROZEN); break; - case 15: { /* coins */ + case 14: { /* coins */ struct obj_data *coin_obj; int i; @@ -3984,15 +4227,15 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c send_to_char(ch, "Ok.\r\n"); return (1); } - case 16: /* height */ + case 15: /* height */ GET_HEIGHT(vict) = value; affect_total(vict); break; - case 17: /* hit */ + case 16: /* hit */ vict->points.hit = RANGE(-9, vict->points.max_hit); affect_total(vict); break; - case 18: /* hunger */ + case 17: /* hunger */ if (!str_cmp(val_arg, "off")) { GET_COND(vict, HUNGER) = -1; send_to_char(ch, "%s's hunger is now off.\r\n", GET_NAME(vict)); @@ -4006,7 +4249,7 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c return (0); } break; - case 19: /* int */ + case 18: /* int */ if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD) RANGE(3, 25); else @@ -4014,20 +4257,17 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c vict->real_abils.intel = value; affect_total(vict); break; - case 20: /* invis */ + case 19: /* invis */ if (GET_LEVEL(ch) < LVL_IMPL && ch != vict) { send_to_char(ch, "You aren't godly enough for that!\r\n"); return (0); } GET_INVIS_LEV(vict) = RANGE(0, GET_LEVEL(vict)); break; - case 21: /* invistart */ + case 20: /* invistart */ SET_OR_REMOVE(PLR_FLAGS(vict), PLR_INVSTART); break; - case 22: /* killer */ - SET_OR_REMOVE(PLR_FLAGS(vict), PLR_KILLER); - break; - case 23: /* level */ + case 21: /* level */ if ((!IS_NPC(vict) && value > GET_LEVEL(ch)) || value > LVL_IMPL) { send_to_char(ch, "You can't do that.\r\n"); return (0); @@ -4035,7 +4275,7 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c RANGE(1, LVL_IMPL); vict->player.level = value; break; - case 24: /* loadroom */ + case 22: /* loadroom */ if (!str_cmp(val_arg, "off")) { REMOVE_BIT_AR(PLR_FLAGS(vict), PLR_LOADROOM); } else if (is_number(val_arg)) { @@ -4053,27 +4293,23 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c return (0); } break; - case 25: /* mana */ + case 23: /* mana */ vict->points.mana = RANGE(0, vict->points.max_mana); affect_total(vict); break; - case 26: /* maxhit */ + case 24: /* maxhit */ vict->points.max_hit = RANGE(1, 5000); affect_total(vict); break; - case 27: /* maxmana */ + case 25: /* maxmana */ vict->points.max_mana = RANGE(1, 5000); affect_total(vict); break; - case 28: /* maxmove */ - vict->points.max_move = RANGE(1, 5000); + case 26: /* maxstam */ + vict->points.max_stamina = RANGE(1, 5000); affect_total(vict); break; - case 29: /* move */ - vict->points.move = RANGE(0, vict->points.max_move); - affect_total(vict); - break; - case 30: /* name */ + case 27: /* name */ if (ch != vict && GET_LEVEL(ch) < LVL_IMPL) { send_to_char(ch, "Only Imps can change the name of other players.\r\n"); return (0); @@ -4083,24 +4319,24 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c return (0); } break; - case 31: /* nodelete */ + case 28: /* nodelete */ SET_OR_REMOVE(PLR_FLAGS(vict), PLR_NODELETE); break; - case 32: /* nohassle */ + case 29: /* nohassle */ if (GET_LEVEL(ch) < LVL_GOD && ch != vict) { send_to_char(ch, "You aren't godly enough for that!\r\n"); return (0); } SET_OR_REMOVE(PRF_FLAGS(vict), PRF_NOHASSLE); break; - case 33: /* nosummon */ + case 30: /* nosummon */ SET_OR_REMOVE(PRF_FLAGS(vict), PRF_SUMMONABLE); send_to_char(ch, "Nosummon %s for %s.\r\n", ONOFF(!on), GET_NAME(vict)); break; - case 34: /* nowiz */ + case 31: /* nowiz */ SET_OR_REMOVE(PLR_FLAGS(vict), PLR_NOWIZLIST); break; - case 35: /* olc */ + case 32: /* olc */ if (is_abbrev(val_arg, "socials") || is_abbrev(val_arg, "actions") || is_abbrev(val_arg, "aedit")) GET_OLC_ZONE(vict) = AEDIT_PERMISSION; else if (is_abbrev(val_arg, "hedit") || is_abbrev(val_arg, "help")) @@ -4115,7 +4351,7 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c } else GET_OLC_ZONE(vict) = atoi(val_arg); break; - case 36: /* password */ + case 33: /* password */ if (GET_LEVEL(vict) >= LVL_GRGOD) { send_to_char(ch, "You cannot change that.\r\n"); return (0); @@ -4124,7 +4360,7 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c *(GET_PASSWD(vict) + MAX_PWD_LENGTH) = '\0'; send_to_char(ch, "Password changed to '%s'.\r\n", val_arg); break; - case 37: /* poofin */ + case 34: /* poofin */ if ((vict == ch) || (GET_LEVEL(ch) == LVL_IMPL)) { skip_spaces(&val_arg); parse_at(val_arg); @@ -4138,7 +4374,7 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c POOFIN(vict) = strdup(val_arg); } break; - case 38: /* poofout */ + case 35: /* poofout */ if ((vict == ch) || (GET_LEVEL(ch) == LVL_IMPL)) { skip_spaces(&val_arg); parse_at(val_arg); @@ -4152,10 +4388,10 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c POOFOUT(vict) = strdup(val_arg); } break; - case 39: /* quest */ + case 36: /* quest */ SET_OR_REMOVE(PRF_FLAGS(vict), PRF_QUEST); break; - case 40: /* room */ + case 37: /* room */ if ((rnum = real_room(value)) == NOWHERE) { send_to_char(ch, "No room exists with that number.\r\n"); return (0); @@ -4164,23 +4400,23 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c char_from_room(vict); char_to_room(vict, rnum); break; - case 41: /* screenwidth */ + case 38: /* screenwidth */ GET_SCREEN_WIDTH(vict) = RANGE(40, 200); break; - case 42: /* sex */ + case 39: /* sex */ if ((i = search_block(val_arg, genders, FALSE)) < 0) { send_to_char(ch, "Must be 'male', 'female', or 'neutral'.\r\n"); return (0); } GET_SEX(vict) = i; break; - case 43: /* showvnums */ + case 40: /* showvnums */ SET_OR_REMOVE(PRF_FLAGS(vict), PRF_SHOWVNUMS); break; - case 44: /* siteok */ + case 41: /* siteok */ SET_OR_REMOVE(PLR_FLAGS(vict), PLR_SITEOK); break; - case 45: /* skills/spells */ + case 42: /* skills/spells */ { char local_buf[MAX_INPUT_LENGTH], *value_arg, *name_end; char skill_name[MAX_INPUT_LENGTH]; @@ -4265,7 +4501,12 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c } break; - case 46: /* str */ + case 43: /* stam */ + vict->points.stamina = RANGE(0, vict->points.max_stamina); + affect_total(vict); + break; + + case 44: /* str */ if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD) RANGE(3, 25); else @@ -4273,10 +4514,7 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c vict->real_abils.str = value; affect_total(vict); break; - case 47: /* thief */ - SET_OR_REMOVE(PLR_FLAGS(vict), PLR_THIEF); - break; - case 48: /* thirst */ + case 45: /* thirst */ if (!str_cmp(val_arg, "off")) { GET_COND(vict, THIRST) = -1; send_to_char(ch, "%s's thirst is now off.\r\n", GET_NAME(vict)); @@ -4290,13 +4528,13 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c return (0); } break; - case 49: /* variable */ + case 46: /* variable */ return perform_set_dg_var(ch, vict, val_arg); - case 50: /* weight */ + case 47: /* weight */ GET_WEIGHT(vict) = value; affect_total(vict); break; - case 51: /* wis */ + case 48: /* wis */ if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD) RANGE(3, 25); else @@ -4304,10 +4542,10 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c vict->real_abils.wis = value; affect_total(vict); break; - case 52: /* questpoints */ + case 49: /* questpoints */ GET_QUESTPOINTS(vict) = RANGE(0, 100000000); break; - case 53: /* questhistory */ + case 50: /* questhistory */ qvnum = atoi(val_arg); if (real_quest(qvnum) == NOTHING) { send_to_char(ch, "That quest doesn't exist.\r\n"); @@ -4324,6 +4562,16 @@ static int perform_set(struct char_data *ch, struct char_data *vict, int mode, c } break; } + case 51: /* species */ + if ((i = parse_species(val_arg)) == SPECIES_UNDEFINED) { + send_to_char(ch, "That is not a species.\r\n"); + return (0); + } + update_species(vict, i); + affect_total(vict); + send_to_char(ch, "You set %s's species to %s.\r\n", + get_char_sdesc(vict), get_species_name(GET_SPECIES(vict))); + break; default: send_to_char(ch, "Can't set that!\r\n"); return (0); @@ -4410,7 +4658,21 @@ ACMD(do_set) } else if (!str_cmp(name, "mob")) half_chop(buf, name, buf); - half_chop(buf, field, buf); + if (!is_file && !is_player && !str_cmp(name, "species")) { + char val[MAX_INPUT_LENGTH]; + char target[MAX_INPUT_LENGTH]; + + half_chop(buf, val, target); + if (!*val || !*target) { + send_to_char(ch, "Usage: set species \r\n"); + return; + } + strlcpy(field, "species", sizeof(field)); + strlcpy(name, target, sizeof(name)); + strlcpy(buf, val, sizeof(buf)); + } else { + half_chop(buf, field, buf); + } if (!*name || !*field) { send_to_char(ch, "Usage: set \r\n"); @@ -4596,7 +4858,7 @@ static struct zcheck_affs { {APPLY_CHAR_HEIGHT,-50, 50, "character height"}, {APPLY_MANA, -50, 50, "mana"}, {APPLY_HIT, -50, 50, "hit points"}, - {APPLY_MOVE, -50, 50, "movement"}, + {APPLY_STAMINA, -50, 50, "stamina"}, {APPLY_COINS, 0, 0, "coins"}, {APPLY_EXP, 0, 0, "experience"}, {APPLY_AC, -10, 10, "magical AC"}, @@ -4705,10 +4967,6 @@ ACMD (do_zcheck) "- No unarmed combat proficiency set (add skill or weapon)\r\n"); } - if (MOB_FLAGGED(mob, MOB_AGGRESSIVE) && (MOB_FLAGGED(mob, MOB_AGGR_GOOD) || MOB_FLAGGED(mob, MOB_AGGR_EVIL) || MOB_FLAGGED(mob, MOB_AGGR_NEUTRAL)) && (found=1)) - len += snprintf(buf + len, sizeof(buf) - len, - "- Both aggresive and agressive to align.\r\n"); - if (GET_EXP(mob)>MAX_EXP_ALLOWED && (found=1)) len += snprintf(buf + len, sizeof(buf) - len, "- Has %d experience (limit: %d)\r\n", @@ -6091,53 +6349,6 @@ ACMD(do_recent) } -ACMD(do_oset) -{ - char arg[MAX_INPUT_LENGTH]; - char arg2[MAX_INPUT_LENGTH]; - const char usage[] = "Usage: \r\n" - "Options: alias, apply, longdesc, shortdesc\r\n" - "> oset