mirror of
https://github.com/tbamud/tbamud.git
synced 2026-03-19 10:46:33 +01:00
commit
18c92e2357
77 changed files with 8375 additions and 3273 deletions
220
AGENTS.md
Normal file
220
AGENTS.md
Normal file
|
|
@ -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.
|
||||
77
README.md
77
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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
|||
~
|
||||
<detailed description>
|
||||
~
|
||||
<mob flags> <affect flags> <alignment> <type flag>
|
||||
<mob flags> <affect flags> <reserved> <type flag>
|
||||
{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:
|
||||
|
||||
<mob flags> <affect flags> <alignment> S
|
||||
<mob flags> <affect flags> <reserved> S
|
||||
<level> <thaco> <armor class> <hitpoints> <damage>
|
||||
<coins> <experience points>
|
||||
<load position> <default position> <sex>
|
||||
|
|
@ -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:
|
||||
|
||||
<mob flags> <affect flags> <alignment> E
|
||||
<mob flags> <affect flags> <reserved> E
|
||||
<level> <hitroll> <armor class> <hitpoints> <damage>
|
||||
<coins> <experience points>
|
||||
<load position> <default position> <sex>
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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!
|
||||
|
||||
=========================================
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
$
|
||||
|
|
|
|||
|
|
@ -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
|
||||
$~
|
||||
|
|
|
|||
|
|
@ -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
|
||||
.
|
||||
|
|
|
|||
|
|
@ -1 +1,7 @@
|
|||
#1
|
||||
Test~
|
||||
0 q 1
|
||||
~
|
||||
* No Script
|
||||
~
|
||||
$~
|
||||
|
|
|
|||
|
|
@ -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=--,
|
||||
~
|
||||
$~
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
0.trg
|
||||
1.trg
|
||||
2.trg
|
||||
30.trg
|
||||
|
||||
$
|
||||
|
|
|
|||
|
|
@ -1,2 +1 @@
|
|||
30.trg
|
||||
$
|
||||
|
|
|
|||
|
|
@ -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
|
||||
~
|
||||
~
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
| $@
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
| $@
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
11
src/act.h
11
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);
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
236
src/act.other.c
236
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 <string>\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 <string>\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 <string>\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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
935
src/act.wizard.c
935
src/act.wizard.c
File diff suppressed because it is too large
Load diff
11
src/cedit.c
11
src/cedit.c
|
|
@ -79,7 +79,6 @@ static void cedit_setup(struct descriptor_data *d)
|
|||
|
||||
/* Copy the current configuration from the config_info to this one and copy
|
||||
* the game play options from the configuration info struct. */
|
||||
OLC_CONFIG(d)->play.pk_allowed = CONFIG_PK_ALLOWED;
|
||||
OLC_CONFIG(d)->play.pt_allowed = CONFIG_PT_ALLOWED;
|
||||
OLC_CONFIG(d)->play.level_can_shout = CONFIG_LEVEL_CAN_SHOUT;
|
||||
OLC_CONFIG(d)->play.tunnel_size = CONFIG_TUNNEL_SIZE;
|
||||
|
|
@ -177,7 +176,6 @@ static void cedit_save_internally(struct descriptor_data *d)
|
|||
/* see if we need to reassign spec procs on rooms */
|
||||
int reassign = (CONFIG_DTS_ARE_DUMPS != OLC_CONFIG(d)->play.dts_are_dumps);
|
||||
/* Copy the data back from the descriptor to the config_info structure. */
|
||||
CONFIG_PK_ALLOWED = OLC_CONFIG(d)->play.pk_allowed;
|
||||
CONFIG_PT_ALLOWED = OLC_CONFIG(d)->play.pt_allowed;
|
||||
CONFIG_LEVEL_CAN_SHOUT = OLC_CONFIG(d)->play.level_can_shout;
|
||||
CONFIG_TUNNEL_SIZE = OLC_CONFIG(d)->play.tunnel_size;
|
||||
|
|
@ -326,8 +324,6 @@ int save_config( IDXTYPE nowhere )
|
|||
"* [ Game Play Options ]\n"
|
||||
);
|
||||
|
||||
fprintf(fl, "* Is player killing allowed on the mud?\n"
|
||||
"pk_allowed = %d\n\n", CONFIG_PK_ALLOWED);
|
||||
fprintf(fl, "* Is player thieving allowed on the mud?\n"
|
||||
"pt_allowed = %d\n\n", CONFIG_PT_ALLOWED);
|
||||
fprintf(fl, "* What is the minimum level a player can shout/gossip/etc?\n"
|
||||
|
|
@ -591,7 +587,6 @@ static void cedit_disp_game_play_options(struct descriptor_data *d)
|
|||
|
||||
|
||||
write_to_output(d, "\r\n\r\n"
|
||||
"%sA%s) Player Killing Allowed : %s%s\r\n"
|
||||
"%sB%s) Player Thieving Allowed : %s%s\r\n"
|
||||
"%sC%s) Minimum Level To Shout : %s%d\r\n"
|
||||
"%sE%s) Tunnel Size : %s%d\r\n"
|
||||
|
|
@ -617,7 +612,6 @@ static void cedit_disp_game_play_options(struct descriptor_data *d)
|
|||
"%s8%s) Scripts on PC's : %s%s\r\n"
|
||||
"%sQ%s) Exit To The Main Menu\r\n"
|
||||
"Enter your choice : ",
|
||||
grn, nrm, cyn, CHECK_VAR(OLC_CONFIG(d)->play.pk_allowed),
|
||||
grn, nrm, cyn, CHECK_VAR(OLC_CONFIG(d)->play.pt_allowed),
|
||||
grn, nrm, cyn, OLC_CONFIG(d)->play.level_can_shout,
|
||||
grn, nrm, cyn, OLC_CONFIG(d)->play.tunnel_size,
|
||||
|
|
@ -844,11 +838,6 @@ void cedit_parse(struct descriptor_data *d, char *arg)
|
|||
|
||||
case CEDIT_GAME_OPTIONS_MENU:
|
||||
switch (*arg) {
|
||||
case 'a':
|
||||
case 'A':
|
||||
TOGGLE_VAR(OLC_CONFIG(d)->play.pk_allowed);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
case 'B':
|
||||
TOGGLE_VAR(OLC_CONFIG(d)->play.pt_allowed);
|
||||
|
|
|
|||
619
src/class.c
619
src/class.c
|
|
@ -23,6 +23,7 @@
|
|||
#include "constants.h"
|
||||
#include "act.h"
|
||||
#include "class.h"
|
||||
#include "species.h"
|
||||
|
||||
/* Names first */
|
||||
const char *class_abbrevs[] = {
|
||||
|
|
@ -95,52 +96,18 @@ bitvector_t find_class_bitvector(const char *arg)
|
|||
return (ret);
|
||||
}
|
||||
|
||||
/* These are definitions which control the guildmasters for each class.
|
||||
* The first field (top line) controls the highest percentage skill level a
|
||||
* character of the class is allowed to attain in any skill. (After this
|
||||
* level, attempts to practice will say "You are already learned in this area."
|
||||
*
|
||||
* The second line controls the maximum percent gain in learnedness a character
|
||||
* is allowed per practice -- in other words, if the random die throw comes out
|
||||
* higher than this number, the gain will only be this number instead.
|
||||
*
|
||||
* The third line controls the minimu percent gain in learnedness a character
|
||||
* is allowed per practice -- in other words, if the random die throw comes
|
||||
* out below this number, the gain will be set up to this number.
|
||||
*
|
||||
* The fourth line simply sets whether the character knows 'spells' or 'skills'.
|
||||
* This does not affect anything except the message given to the character when
|
||||
* trying to practice (i.e. "You know of the following spells" vs. "You know of
|
||||
* the following skills" */
|
||||
|
||||
#define SPELL 0
|
||||
#define SKILL 1
|
||||
|
||||
/* #define LEARNED_LEVEL 0 % known which is considered "learned" */
|
||||
/* #define MAX_PER_PRAC 1 max percent gain in skill per practice */
|
||||
/* #define MIN_PER_PRAC 2 min percent gain in skill per practice */
|
||||
/* #define PRAC_TYPE 3 should it say 'spell' or 'skill'? */
|
||||
|
||||
int prac_params[4][NUM_CLASSES] = {
|
||||
/* SOR CLE THE FIG BAR RAN BARD DRU */
|
||||
{ 95, 95, 85, 80, 75, 85, 85, 95 }, /* learned level */
|
||||
{ 100, 100, 12, 12, 11, 12, 13, 90 }, /* max per practice */
|
||||
{ 25, 25, 0, 0, 0, 0, 25, 25 }, /* min per practice */
|
||||
{ SPELL, SPELL, SKILL, SKILL, SKILL, SKILL, SKILL, SKILL }, /* prac name */
|
||||
};
|
||||
|
||||
/* The appropriate rooms for each guildmaster/guildguard; controls which types
|
||||
* of people the various guildguards let through. i.e., the first line shows
|
||||
/* The appropriate rooms for each class gatekeeper; controls which types
|
||||
* of people the various guards let through. i.e., the first line shows
|
||||
* that from room 3017, only SORCERORS are allowed to go south. Don't forget
|
||||
* to visit spec_assign.c if you create any new mobiles that should be a guild
|
||||
* to visit spec_assign.c if you create any new mobiles that should be a
|
||||
* master or guard so they can act appropriately. If you "recycle" the
|
||||
* existing mobs that are used in other guilds for your new guild, then you
|
||||
* don't have to change that file, only here. Guildguards are now implemented
|
||||
* existing mobs that are used in other areas for your new one, then you
|
||||
* don't have to change that file, only here. Guards are now implemented
|
||||
* via triggers. This code remains as an example. */
|
||||
/* TO-DO: Is this necessary anymore now that there are no official guild rooms? */
|
||||
struct guild_info_type guild_info[] = {
|
||||
|
||||
/* Midgaard */
|
||||
/* Main City */
|
||||
{ CLASS_SORCEROR, 3017, SOUTH },
|
||||
{ CLASS_CLERIC, 3004, NORTH },
|
||||
{ CLASS_ROGUE, 3027, EAST },
|
||||
|
|
@ -172,10 +139,103 @@ bool has_save_proficiency(int class_num, int ability) {
|
|||
}
|
||||
}
|
||||
|
||||
static void set_real_ability(struct char_data *ch, int ability, int value)
|
||||
{
|
||||
switch (ability) {
|
||||
case ABIL_STR: ch->real_abils.str = value; break;
|
||||
case ABIL_DEX: ch->real_abils.dex = value; break;
|
||||
case ABIL_CON: ch->real_abils.con = value; break;
|
||||
case ABIL_INT: ch->real_abils.intel = value; break;
|
||||
case ABIL_WIS: ch->real_abils.wis = value; break;
|
||||
case ABIL_CHA: ch->real_abils.cha = value; break;
|
||||
}
|
||||
}
|
||||
|
||||
static void roll_real_abils_preference(struct char_data *ch)
|
||||
{
|
||||
int i, j, temp;
|
||||
int rolls[NUM_ABILITIES];
|
||||
int sorted[NUM_ABILITIES];
|
||||
bool used[NUM_ABILITIES] = { FALSE };
|
||||
bool assigned[NUM_ABILITIES] = { FALSE };
|
||||
static const int default_order[NUM_ABILITIES] = {
|
||||
ABIL_STR, ABIL_DEX, ABIL_CON, ABIL_INT, ABIL_WIS, ABIL_CHA
|
||||
};
|
||||
|
||||
for (i = 0; i < NUM_ABILITIES; i++) {
|
||||
int die[4];
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
die[j] = rand_number(1, 6);
|
||||
|
||||
temp = die[0] + die[1] + die[2] + die[3] -
|
||||
MIN(die[0], MIN(die[1], MIN(die[2], die[3])));
|
||||
|
||||
rolls[i] = temp;
|
||||
sorted[i] = temp;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_ABILITIES - 1; i++) {
|
||||
for (j = i + 1; j < NUM_ABILITIES; j++) {
|
||||
if (sorted[j] > sorted[i]) {
|
||||
temp = sorted[i];
|
||||
sorted[i] = sorted[j];
|
||||
sorted[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int pref_count = ch->stat_pref_count;
|
||||
if (pref_count > NUM_ABILITIES)
|
||||
pref_count = NUM_ABILITIES;
|
||||
|
||||
for (i = 0; i < pref_count; i++) {
|
||||
int ability = ch->stat_pref_order[i];
|
||||
|
||||
if (ability < 0 || ability >= NUM_ABILITIES)
|
||||
continue;
|
||||
|
||||
set_real_ability(ch, ability, sorted[i]);
|
||||
assigned[ability] = TRUE;
|
||||
|
||||
for (j = 0; j < NUM_ABILITIES; j++) {
|
||||
if (!used[j] && rolls[j] == sorted[i]) {
|
||||
used[j] = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int fifo_idx = 0;
|
||||
for (i = 0; i < NUM_ABILITIES; i++) {
|
||||
int ability = default_order[i];
|
||||
|
||||
if (assigned[ability])
|
||||
continue;
|
||||
|
||||
while (fifo_idx < NUM_ABILITIES && used[fifo_idx])
|
||||
fifo_idx++;
|
||||
if (fifo_idx >= NUM_ABILITIES)
|
||||
break;
|
||||
|
||||
set_real_ability(ch, ability, rolls[fifo_idx]);
|
||||
used[fifo_idx] = TRUE;
|
||||
assigned[ability] = TRUE;
|
||||
fifo_idx++;
|
||||
}
|
||||
|
||||
if (HAS_VALID_SPECIES(ch))
|
||||
apply_species_bonuses(ch);
|
||||
else
|
||||
ch->aff_abils = ch->real_abils;
|
||||
|
||||
ch->stat_pref_use = FALSE;
|
||||
}
|
||||
|
||||
/* Roll the 6 stats for a character... each stat is made of the sum of the best
|
||||
* 3 out of 4 rolls of a 6-sided die. Each class then decides which priority
|
||||
* will be given for the best to worst stats. */
|
||||
void roll_real_abils(struct char_data *ch)
|
||||
static void roll_real_abils_classic(struct char_data *ch)
|
||||
{
|
||||
int i, j, k, temp;
|
||||
ubyte table[6];
|
||||
|
|
@ -265,7 +325,240 @@ void roll_real_abils(struct char_data *ch)
|
|||
ch->real_abils.cha = table[5];
|
||||
break;
|
||||
}
|
||||
ch->aff_abils = ch->real_abils;
|
||||
if (HAS_VALID_SPECIES(ch))
|
||||
apply_species_bonuses(ch);
|
||||
else
|
||||
ch->aff_abils = ch->real_abils;
|
||||
}
|
||||
|
||||
void roll_real_abils(struct char_data *ch)
|
||||
{
|
||||
if (ch && ch->stat_pref_use)
|
||||
roll_real_abils_preference(ch);
|
||||
else
|
||||
roll_real_abils_classic(ch);
|
||||
}
|
||||
|
||||
/* Per-class skill caps */
|
||||
#define DEFAULT_CLASS_SKILL_MAX 90
|
||||
|
||||
static int class_skill_maxes[NUM_CLASSES][MAX_SKILLS + 1];
|
||||
static bool class_skill_caps_ready = FALSE;
|
||||
|
||||
static int clamp_skill_max(int max)
|
||||
{
|
||||
if (max < 0)
|
||||
return 0;
|
||||
if (max > 100)
|
||||
return 100;
|
||||
return max;
|
||||
}
|
||||
|
||||
static void apply_class_skill(int chclass, struct char_data *ch, int skill, int start, int max)
|
||||
{
|
||||
if (ch)
|
||||
SET_SKILL(ch, skill, start);
|
||||
if (chclass >= 0 && chclass < NUM_CLASSES && skill >= 0 && skill <= MAX_SKILLS)
|
||||
class_skill_maxes[chclass][skill] = clamp_skill_max(max);
|
||||
}
|
||||
|
||||
static void apply_class_skills(int chclass, struct char_data *ch)
|
||||
{
|
||||
switch (chclass) {
|
||||
|
||||
case CLASS_SORCEROR:
|
||||
apply_class_skill(chclass, ch, SPELL_MAGIC_MISSILE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_DETECT_INVIS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_DETECT_MAGIC, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_CHILL_TOUCH, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_INFRAVISION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_INVISIBLE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_ARMOR, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_BURNING_HANDS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_LOCATE_OBJECT, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_STRENGTH, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_SHOCKING_GRASP, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_SLEEP, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_LIGHTNING_BOLT, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_BLINDNESS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_DETECT_POISON, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_COLOR_SPRAY, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_ENERGY_DRAIN, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_CURSE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_POISON, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_FIREBALL, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_CHARM, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_IDENTIFY, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_FLY, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_ENCHANT_WEAPON, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_CLONE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_UNARMED, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_ARCANA, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_HISTORY, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_INSIGHT, 5, 90);
|
||||
break;
|
||||
|
||||
case CLASS_CLERIC:
|
||||
apply_class_skill(chclass, ch, SPELL_CURE_LIGHT, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_ARMOR, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_CREATE_FOOD, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_CREATE_WATER, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_DETECT_POISON, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_CURE_BLIND, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_BLESS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_DETECT_INVIS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_BLINDNESS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_INFRAVISION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_PROT_FROM_EVIL, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_POISON, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_GROUP_ARMOR, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_CURE_CRITIC, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_SUMMON, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_REMOVE_POISON, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_IDENTIFY, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_WORD_OF_RECALL, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_DARKNESS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_EARTHQUAKE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_SANCTUARY, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_CALL_LIGHTNING, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_HEAL, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_CONTROL_WEATHER, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_SENSE_LIFE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_HARM, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_GROUP_HEAL, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_REMOVE_CURSE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SHIELD_USE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_ACROBATICS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_ARCANA, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_RELIGION, 5, 90);
|
||||
break;
|
||||
|
||||
case CLASS_ROGUE:
|
||||
apply_class_skill(chclass, ch, SKILL_STEALTH, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_TRACK, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_BACKSTAB, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PICK_LOCK, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SLEIGHT_OF_HAND, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_UNARMED, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SHIELD_USE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PIERCING_WEAPONS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PERCEPTION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_ACROBATICS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_DECEPTION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_INVESTIGATION, 5, 90);
|
||||
break;
|
||||
|
||||
case CLASS_FIGHTER:
|
||||
apply_class_skill(chclass, ch, SKILL_KICK, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_RESCUE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_BANDAGE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_BASH, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_UNARMED, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SLASHING_WEAPONS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PIERCING_WEAPONS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_BLUDGEONING_WEAPONS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SHIELD_USE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PERCEPTION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_ATHLETICS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_INTIMIDATION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SURVIVAL, 5, 90);
|
||||
break;
|
||||
|
||||
case CLASS_BARBARIAN:
|
||||
apply_class_skill(chclass, ch, SKILL_KICK, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_RESCUE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_BANDAGE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_WHIRLWIND, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_UNARMED, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PIERCING_WEAPONS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_BLUDGEONING_WEAPONS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PERCEPTION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_ATHLETICS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_INTIMIDATION, 5, 90);
|
||||
break;
|
||||
|
||||
case CLASS_RANGER:
|
||||
apply_class_skill(chclass, ch, SKILL_BANDAGE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_TRACK, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_BASH, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SLEIGHT_OF_HAND, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_UNARMED, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SLASHING_WEAPONS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PIERCING_WEAPONS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SHIELD_USE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PERCEPTION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_NATURE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_ANIMAL_HANDLING, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SURVIVAL, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_ATHLETICS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PERSUASION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_STEALTH, 5, 90);
|
||||
break;
|
||||
|
||||
case CLASS_BARD:
|
||||
apply_class_skill(chclass, ch, SPELL_ARMOR, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_IDENTIFY, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_BANDAGE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_TRACK, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PICK_LOCK, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SLEIGHT_OF_HAND, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_UNARMED, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PIERCING_WEAPONS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SHIELD_USE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PERCEPTION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_ACROBATICS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_HISTORY, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_INVESTIGATION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SURVIVAL, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_STEALTH, 5, 90);
|
||||
break;
|
||||
|
||||
case CLASS_DRUID:
|
||||
apply_class_skill(chclass, ch, SPELL_DETECT_INVIS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_DETECT_MAGIC, 5, 90);
|
||||
apply_class_skill(chclass, ch, SPELL_LOCATE_OBJECT, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_BANDAGE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_TRACK, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_UNARMED, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PIERCING_WEAPONS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SHIELD_USE, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PERCEPTION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_ACROBATICS, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_ARCANA, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_HISTORY, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_INSIGHT, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_INVESTIGATION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_PERSUASION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_RELIGION, 5, 90);
|
||||
apply_class_skill(chclass, ch, SKILL_SURVIVAL, 5, 90);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void init_class_skill_caps(void)
|
||||
{
|
||||
int chclass, skill;
|
||||
|
||||
for (chclass = 0; chclass < NUM_CLASSES; chclass++) {
|
||||
for (skill = 0; skill <= MAX_SKILLS; skill++)
|
||||
class_skill_maxes[chclass][skill] = DEFAULT_CLASS_SKILL_MAX;
|
||||
}
|
||||
|
||||
for (chclass = 0; chclass < NUM_CLASSES; chclass++)
|
||||
apply_class_skills(chclass, NULL);
|
||||
|
||||
class_skill_caps_ready = TRUE;
|
||||
}
|
||||
|
||||
int class_skill_max(int chclass, int skillnum)
|
||||
{
|
||||
if (!class_skill_caps_ready)
|
||||
return DEFAULT_CLASS_SKILL_MAX;
|
||||
if (chclass < 0 || chclass >= NUM_CLASSES)
|
||||
return DEFAULT_CLASS_SKILL_MAX;
|
||||
if (skillnum < 0 || skillnum > MAX_SKILLS)
|
||||
return DEFAULT_CLASS_SKILL_MAX;
|
||||
return class_skill_maxes[chclass][skillnum];
|
||||
}
|
||||
|
||||
void grant_class_skills(struct char_data *ch, bool reset)
|
||||
|
|
@ -282,200 +575,39 @@ void grant_class_skills(struct char_data *ch, bool reset)
|
|||
if (GET_CLASS(ch) < CLASS_SORCEROR || GET_CLASS(ch) >= NUM_CLASSES)
|
||||
return;
|
||||
|
||||
switch (GET_CLASS(ch)) {
|
||||
|
||||
case CLASS_SORCEROR:
|
||||
SET_SKILL(ch, SPELL_MAGIC_MISSILE, 5);
|
||||
SET_SKILL(ch, SPELL_DETECT_INVIS, 5);
|
||||
SET_SKILL(ch, SPELL_DETECT_MAGIC, 5);
|
||||
SET_SKILL(ch, SPELL_CHILL_TOUCH, 5);
|
||||
SET_SKILL(ch, SPELL_INFRAVISION, 5);
|
||||
SET_SKILL(ch, SPELL_INVISIBLE, 5);
|
||||
SET_SKILL(ch, SPELL_ARMOR, 5);
|
||||
SET_SKILL(ch, SPELL_BURNING_HANDS, 5);
|
||||
SET_SKILL(ch, SPELL_LOCATE_OBJECT, 5);
|
||||
SET_SKILL(ch, SPELL_STRENGTH, 5);
|
||||
SET_SKILL(ch, SPELL_SHOCKING_GRASP, 5);
|
||||
SET_SKILL(ch, SPELL_SLEEP, 5);
|
||||
SET_SKILL(ch, SPELL_LIGHTNING_BOLT, 5);
|
||||
SET_SKILL(ch, SPELL_BLINDNESS, 5);
|
||||
SET_SKILL(ch, SPELL_DETECT_POISON, 5);
|
||||
SET_SKILL(ch, SPELL_COLOR_SPRAY, 5);
|
||||
SET_SKILL(ch, SPELL_ENERGY_DRAIN, 5);
|
||||
SET_SKILL(ch, SPELL_CURSE, 5);
|
||||
SET_SKILL(ch, SPELL_POISON, 5);
|
||||
SET_SKILL(ch, SPELL_FIREBALL, 5);
|
||||
SET_SKILL(ch, SPELL_CHARM, 5);
|
||||
SET_SKILL(ch, SPELL_IDENTIFY, 5);
|
||||
SET_SKILL(ch, SPELL_FLY, 5);
|
||||
SET_SKILL(ch, SPELL_ENCHANT_WEAPON, 5);
|
||||
SET_SKILL(ch, SPELL_CLONE, 5);
|
||||
SET_SKILL(ch, SKILL_UNARMED, 5);
|
||||
SET_SKILL(ch, SKILL_ARCANA, 5);
|
||||
SET_SKILL(ch, SKILL_HISTORY, 5);
|
||||
SET_SKILL(ch, SKILL_INSIGHT, 5);
|
||||
break;
|
||||
|
||||
case CLASS_CLERIC:
|
||||
SET_SKILL(ch, SPELL_CURE_LIGHT, 5);
|
||||
SET_SKILL(ch, SPELL_ARMOR, 5);
|
||||
SET_SKILL(ch, SPELL_CREATE_FOOD, 5);
|
||||
SET_SKILL(ch, SPELL_CREATE_WATER, 5);
|
||||
SET_SKILL(ch, SPELL_DETECT_POISON, 5);
|
||||
SET_SKILL(ch, SPELL_DETECT_ALIGN, 5);
|
||||
SET_SKILL(ch, SPELL_CURE_BLIND, 5);
|
||||
SET_SKILL(ch, SPELL_BLESS, 5);
|
||||
SET_SKILL(ch, SPELL_DETECT_INVIS, 5);
|
||||
SET_SKILL(ch, SPELL_BLINDNESS, 5);
|
||||
SET_SKILL(ch, SPELL_INFRAVISION, 5);
|
||||
SET_SKILL(ch, SPELL_PROT_FROM_EVIL, 5);
|
||||
SET_SKILL(ch, SPELL_POISON, 5);
|
||||
SET_SKILL(ch, SPELL_GROUP_ARMOR, 5);
|
||||
SET_SKILL(ch, SPELL_CURE_CRITIC, 5);
|
||||
SET_SKILL(ch, SPELL_SUMMON, 5);
|
||||
SET_SKILL(ch, SPELL_REMOVE_POISON, 5);
|
||||
SET_SKILL(ch, SPELL_IDENTIFY, 5);
|
||||
SET_SKILL(ch, SPELL_WORD_OF_RECALL, 5);
|
||||
SET_SKILL(ch, SPELL_DARKNESS, 5);
|
||||
SET_SKILL(ch, SPELL_EARTHQUAKE, 5);
|
||||
SET_SKILL(ch, SPELL_DISPEL_EVIL, 5);
|
||||
SET_SKILL(ch, SPELL_DISPEL_GOOD, 5);
|
||||
SET_SKILL(ch, SPELL_SANCTUARY, 5);
|
||||
SET_SKILL(ch, SPELL_CALL_LIGHTNING, 5);
|
||||
SET_SKILL(ch, SPELL_HEAL, 5);
|
||||
SET_SKILL(ch, SPELL_CONTROL_WEATHER, 5);
|
||||
SET_SKILL(ch, SPELL_SENSE_LIFE, 5);
|
||||
SET_SKILL(ch, SPELL_HARM, 5);
|
||||
SET_SKILL(ch, SPELL_GROUP_HEAL, 5);
|
||||
SET_SKILL(ch, SPELL_REMOVE_CURSE, 5);
|
||||
SET_SKILL(ch, SKILL_SHIELD_USE, 5);
|
||||
SET_SKILL(ch, SKILL_ACROBATICS, 5);
|
||||
SET_SKILL(ch, SKILL_ARCANA, 5);
|
||||
SET_SKILL(ch, SKILL_RELIGION, 5);
|
||||
break;
|
||||
|
||||
case CLASS_ROGUE:
|
||||
SET_SKILL(ch, SKILL_STEALTH, 5);
|
||||
SET_SKILL(ch, SKILL_TRACK, 5);
|
||||
SET_SKILL(ch, SKILL_BACKSTAB, 5);
|
||||
SET_SKILL(ch, SKILL_PICK_LOCK, 5);
|
||||
SET_SKILL(ch, SKILL_SLEIGHT_OF_HAND, 5);
|
||||
SET_SKILL(ch, SKILL_UNARMED, 5);
|
||||
SET_SKILL(ch, SKILL_SHIELD_USE, 5);
|
||||
SET_SKILL(ch, SKILL_PIERCING_WEAPONS, 5);
|
||||
SET_SKILL(ch, SKILL_PERCEPTION, 5);
|
||||
SET_SKILL(ch, SKILL_ACROBATICS, 5);
|
||||
SET_SKILL(ch, SKILL_DECEPTION, 5);
|
||||
SET_SKILL(ch, SKILL_INVESTIGATION, 5);
|
||||
break;
|
||||
|
||||
case CLASS_FIGHTER:
|
||||
SET_SKILL(ch, SKILL_KICK, 5);
|
||||
SET_SKILL(ch, SKILL_RESCUE, 5);
|
||||
SET_SKILL(ch, SKILL_BANDAGE, 5);
|
||||
SET_SKILL(ch, SKILL_BASH, 5);
|
||||
SET_SKILL(ch, SKILL_UNARMED, 5);
|
||||
SET_SKILL(ch, SKILL_SLASHING_WEAPONS, 5);
|
||||
SET_SKILL(ch, SKILL_PIERCING_WEAPONS, 5);
|
||||
SET_SKILL(ch, SKILL_BLUDGEONING_WEAPONS, 5);
|
||||
SET_SKILL(ch, SKILL_SHIELD_USE, 5);
|
||||
SET_SKILL(ch, SKILL_PERCEPTION, 5);
|
||||
SET_SKILL(ch, SKILL_ATHLETICS, 5);
|
||||
SET_SKILL(ch, SKILL_INTIMIDATION, 5);
|
||||
SET_SKILL(ch, SKILL_SURVIVAL, 5);
|
||||
break;
|
||||
|
||||
case CLASS_BARBARIAN:
|
||||
SET_SKILL(ch, SKILL_KICK, 5);
|
||||
SET_SKILL(ch, SKILL_RESCUE, 5);
|
||||
SET_SKILL(ch, SKILL_BANDAGE, 5);
|
||||
SET_SKILL(ch, SKILL_WHIRLWIND, 5);
|
||||
SET_SKILL(ch, SKILL_UNARMED, 5);
|
||||
SET_SKILL(ch, SKILL_PIERCING_WEAPONS, 5);
|
||||
SET_SKILL(ch, SKILL_BLUDGEONING_WEAPONS, 5);
|
||||
SET_SKILL(ch, SKILL_PERCEPTION, 5);
|
||||
SET_SKILL(ch, SKILL_ATHLETICS, 5);
|
||||
SET_SKILL(ch, SKILL_INTIMIDATION, 5);
|
||||
break;
|
||||
|
||||
case CLASS_RANGER:
|
||||
SET_SKILL(ch, SKILL_BANDAGE, 5);
|
||||
SET_SKILL(ch, SKILL_TRACK, 5);
|
||||
SET_SKILL(ch, SKILL_BASH, 5);
|
||||
SET_SKILL(ch, SKILL_SLEIGHT_OF_HAND, 5);
|
||||
SET_SKILL(ch, SKILL_UNARMED, 5);
|
||||
SET_SKILL(ch, SKILL_SLASHING_WEAPONS, 5);
|
||||
SET_SKILL(ch, SKILL_PIERCING_WEAPONS, 5);
|
||||
SET_SKILL(ch, SKILL_SHIELD_USE, 5);
|
||||
SET_SKILL(ch, SKILL_PERCEPTION, 5);
|
||||
SET_SKILL(ch, SKILL_NATURE, 5);
|
||||
SET_SKILL(ch, SKILL_ANIMAL_HANDLING, 5);
|
||||
SET_SKILL(ch, SKILL_SURVIVAL, 5);
|
||||
SET_SKILL(ch, SKILL_ATHLETICS, 5);
|
||||
SET_SKILL(ch, SKILL_PERSUASION, 5);
|
||||
SET_SKILL(ch, SKILL_STEALTH, 5);
|
||||
break;
|
||||
|
||||
case CLASS_BARD:
|
||||
SET_SKILL(ch, SPELL_ARMOR, 5);
|
||||
SET_SKILL(ch, SPELL_IDENTIFY, 5);
|
||||
SET_SKILL(ch, SKILL_BANDAGE, 5);
|
||||
SET_SKILL(ch, SKILL_TRACK, 5);
|
||||
SET_SKILL(ch, SKILL_PICK_LOCK, 5);
|
||||
SET_SKILL(ch, SKILL_SLEIGHT_OF_HAND, 5);
|
||||
SET_SKILL(ch, SKILL_UNARMED, 5);
|
||||
SET_SKILL(ch, SKILL_PIERCING_WEAPONS, 5);
|
||||
SET_SKILL(ch, SKILL_SHIELD_USE, 5);
|
||||
SET_SKILL(ch, SKILL_PERCEPTION, 5);
|
||||
SET_SKILL(ch, SKILL_ACROBATICS, 5);
|
||||
SET_SKILL(ch, SKILL_HISTORY, 5);
|
||||
SET_SKILL(ch, SKILL_INVESTIGATION, 5);
|
||||
SET_SKILL(ch, SKILL_SURVIVAL, 5);
|
||||
SET_SKILL(ch, SKILL_STEALTH, 5);
|
||||
break;
|
||||
|
||||
case CLASS_DRUID:
|
||||
SET_SKILL(ch, SPELL_DETECT_INVIS, 5);
|
||||
SET_SKILL(ch, SPELL_DETECT_MAGIC, 5);
|
||||
SET_SKILL(ch, SPELL_LOCATE_OBJECT, 5);
|
||||
SET_SKILL(ch, SKILL_BANDAGE, 5);
|
||||
SET_SKILL(ch, SKILL_TRACK, 5);
|
||||
SET_SKILL(ch, SKILL_UNARMED, 5);
|
||||
SET_SKILL(ch, SKILL_PIERCING_WEAPONS, 5);
|
||||
SET_SKILL(ch, SKILL_SHIELD_USE, 5);
|
||||
SET_SKILL(ch, SKILL_PERCEPTION, 5);
|
||||
SET_SKILL(ch, SKILL_ACROBATICS, 5);
|
||||
SET_SKILL(ch, SKILL_ARCANA, 5);
|
||||
SET_SKILL(ch, SKILL_HISTORY, 5);
|
||||
SET_SKILL(ch, SKILL_INSIGHT, 5);
|
||||
SET_SKILL(ch, SKILL_INVESTIGATION, 5);
|
||||
SET_SKILL(ch, SKILL_PERSUASION, 5);
|
||||
SET_SKILL(ch, SKILL_RELIGION, 5);
|
||||
SET_SKILL(ch, SKILL_SURVIVAL, 5);
|
||||
break;
|
||||
}
|
||||
|
||||
apply_class_skills(GET_CLASS(ch), ch);
|
||||
}
|
||||
|
||||
/* Some initializations for characters, including initial skills */
|
||||
void do_start(struct char_data *ch)
|
||||
{
|
||||
int base_hit = 90;
|
||||
int base_mana = 100;
|
||||
int base_stamina = 90;
|
||||
|
||||
GET_LEVEL(ch) = 1;
|
||||
GET_EXP(ch) = 1;
|
||||
|
||||
roll_real_abils(ch);
|
||||
|
||||
GET_MAX_HIT(ch) = 90;
|
||||
GET_MAX_MANA(ch) = 100;
|
||||
GET_MAX_MOVE(ch) = 90;
|
||||
if (!get_species_base_points(GET_SPECIES(ch), &base_hit, &base_mana, &base_stamina)) {
|
||||
base_hit = 90;
|
||||
base_mana = 100;
|
||||
base_stamina = 90;
|
||||
}
|
||||
|
||||
GET_MAX_HIT(ch) = base_hit;
|
||||
GET_MAX_MANA(ch) = base_mana;
|
||||
GET_MAX_STAMINA(ch) = base_stamina;
|
||||
|
||||
grant_class_skills(ch, TRUE);
|
||||
grant_species_skills(ch);
|
||||
|
||||
advance_level(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);
|
||||
|
||||
GET_COND(ch, THIRST) = 24;
|
||||
GET_COND(ch, HUNGER) = 24;
|
||||
|
|
@ -485,12 +617,26 @@ void do_start(struct char_data *ch)
|
|||
SET_BIT_AR(PLR_FLAGS(ch), PLR_SITEOK);
|
||||
}
|
||||
|
||||
/* This function controls the change to maxmove, maxmana, and maxhp for each
|
||||
/* This function controls the change to maxstamina, maxmana, and maxhp for each
|
||||
* class every time they gain a level. */
|
||||
void advance_level(struct char_data *ch)
|
||||
{
|
||||
int add_hp, add_mana = 0, add_move = 0, i;
|
||||
|
||||
if (GET_LEVEL(ch) >= LVL_IMMORT) {
|
||||
GET_MAX_HIT(ch) = 999;
|
||||
GET_MAX_MANA(ch) = 999;
|
||||
GET_MAX_STAMINA(ch) = 999;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
GET_COND(ch, i) = (char) -1;
|
||||
SET_BIT_AR(PRF_FLAGS(ch), PRF_HOLYLIGHT);
|
||||
|
||||
snoop_check(ch);
|
||||
save_char(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
add_hp = GET_ABILITY_MOD(GET_CON(ch));
|
||||
|
||||
switch (GET_CLASS(ch)) {
|
||||
|
|
@ -549,7 +695,7 @@ void advance_level(struct char_data *ch)
|
|||
}
|
||||
|
||||
ch->points.max_hit += MAX(1, add_hp);
|
||||
ch->points.max_move += MAX(1, add_move);
|
||||
ch->points.max_stamina += MAX(1, add_move);
|
||||
|
||||
if (GET_LEVEL(ch) > 1)
|
||||
ch->points.max_mana += add_mana;
|
||||
|
|
@ -577,32 +723,12 @@ int backstab_mult(int level)
|
|||
}
|
||||
|
||||
/* invalid_class is used by handler.c to determine if a piece of equipment is
|
||||
* usable by a particular class, based on the ITEM_ANTI_{class} bitvectors. */
|
||||
* usable by a particular class. Class-based anti item flags are no longer
|
||||
* enforced. */
|
||||
int invalid_class(struct char_data *ch, struct obj_data *obj)
|
||||
{
|
||||
if (OBJ_FLAGGED(obj, ITEM_ANTI_SORCEROR) && IS_SORCEROR(ch))
|
||||
return TRUE;
|
||||
|
||||
if (OBJ_FLAGGED(obj, ITEM_ANTI_CLERIC) && IS_CLERIC(ch))
|
||||
return TRUE;
|
||||
|
||||
if (OBJ_FLAGGED(obj, ITEM_ANTI_FIGHTER) && IS_FIGHTER(ch))
|
||||
return TRUE;
|
||||
|
||||
if (OBJ_FLAGGED(obj, ITEM_ANTI_ROGUE) && IS_ROGUE(ch))
|
||||
return TRUE;
|
||||
|
||||
if (OBJ_FLAGGED(obj, ITEM_ANTI_BARBARIAN) && IS_BARBARIAN(ch))
|
||||
return TRUE;
|
||||
|
||||
if (OBJ_FLAGGED(obj, ITEM_ANTI_RANGER) && IS_RANGER(ch))
|
||||
return TRUE;
|
||||
|
||||
if (OBJ_FLAGGED(obj, ITEM_ANTI_BARD) && IS_BARD(ch))
|
||||
return TRUE;
|
||||
|
||||
if (OBJ_FLAGGED(obj, ITEM_ANTI_DRUID) && IS_DRUID(ch))
|
||||
return TRUE;
|
||||
(void) ch;
|
||||
(void) obj;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -649,7 +775,6 @@ void init_spell_levels(void)
|
|||
spell_level(SPELL_CREATE_FOOD, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_CREATE_WATER, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_DETECT_POISON, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_DETECT_ALIGN, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_CURE_BLIND, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_BLESS, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_DETECT_INVIS, CLASS_CLERIC, 1);
|
||||
|
|
@ -665,8 +790,6 @@ void init_spell_levels(void)
|
|||
spell_level(SPELL_WORD_OF_RECALL, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_DARKNESS, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_EARTHQUAKE, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_DISPEL_EVIL, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_DISPEL_GOOD, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_SANCTUARY, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_CALL_LIGHTNING, CLASS_CLERIC, 1);
|
||||
spell_level(SPELL_HEAL, CLASS_CLERIC, 1);
|
||||
|
|
|
|||
|
|
@ -23,13 +23,14 @@ int parse_class(char arg);
|
|||
void roll_real_abils(struct char_data *ch);
|
||||
bool has_save_proficiency(int class_num, int ability);
|
||||
void grant_class_skills(struct char_data *ch, bool reset);
|
||||
void init_class_skill_caps(void);
|
||||
int class_skill_max(int chclass, int skillnum);
|
||||
|
||||
/* Global variables */
|
||||
|
||||
extern const char *class_abbrevs[];
|
||||
extern const char *pc_class_types[];
|
||||
extern const char *class_menu;
|
||||
extern int prac_params[][NUM_CLASSES];
|
||||
extern struct guild_info_type guild_info[];
|
||||
|
||||
#endif /* _CLASS_H_*/
|
||||
|
|
|
|||
12
src/comm.c
12
src/comm.c
|
|
@ -1145,8 +1145,8 @@ static char *make_prompt(struct descriptor_data *d)
|
|||
if (count >= 0)
|
||||
len += count;
|
||||
}
|
||||
if (GET_MOVE(ch) << 2 < GET_MAX_MOVE(ch) && len < sizeof(prompt)) {
|
||||
count = snprintf(prompt + len, sizeof(prompt) - len, "%dV ", GET_MOVE(ch));
|
||||
if (GET_STAMINA(ch) << 2 < GET_MAX_STAMINA(ch) && len < sizeof(prompt)) {
|
||||
count = snprintf(prompt + len, sizeof(prompt) - len, "%dS ", GET_STAMINA(ch));
|
||||
if (count >= 0)
|
||||
len += count;
|
||||
}
|
||||
|
|
@ -1163,8 +1163,8 @@ static char *make_prompt(struct descriptor_data *d)
|
|||
len += count;
|
||||
}
|
||||
|
||||
if (PRF_FLAGGED(d->character, PRF_DISPMOVE) && len < sizeof(prompt)) {
|
||||
count = snprintf(prompt + len, sizeof(prompt) - len, "%dV ", GET_MOVE(d->character));
|
||||
if (PRF_FLAGGED(d->character, PRF_DISPSTAMINA) && len < sizeof(prompt)) {
|
||||
count = snprintf(prompt + len, sizeof(prompt) - len, "%dS ", GET_STAMINA(d->character));
|
||||
if (count >= 0)
|
||||
len += count;
|
||||
}
|
||||
|
|
@ -2795,8 +2795,8 @@ static void msdp_update( void )
|
|||
MSDPSetNumber( d, eMSDP_MANA_MAX, GET_MAX_MANA(ch) );
|
||||
MSDPSetNumber( d, eMSDP_WIMPY, GET_WIMP_LEV(ch) );
|
||||
MSDPSetNumber( d, eMSDP_MONEY, GET_COINS(ch) );
|
||||
MSDPSetNumber( d, eMSDP_MOVEMENT, GET_MOVE(ch) );
|
||||
MSDPSetNumber( d, eMSDP_MOVEMENT_MAX, GET_MAX_MOVE(ch) );
|
||||
MSDPSetNumber( d, eMSDP_MOVEMENT, GET_STAMINA(ch) );
|
||||
MSDPSetNumber( d, eMSDP_MOVEMENT_MAX, GET_MAX_STAMINA(ch) );
|
||||
MSDPSetNumber( d, eMSDP_AC, compute_armor_class(ch) );
|
||||
|
||||
/* This would be better moved elsewhere */
|
||||
|
|
|
|||
|
|
@ -39,13 +39,6 @@
|
|||
/* Can Scripts be attached to players? */
|
||||
int script_players = NO;
|
||||
|
||||
/* pk_allowed sets the tone of the entire game. If pk_allowed is set to NO,
|
||||
* then players will not be allowed to kill, summon, charm, or sleep other
|
||||
* players, as well as a variety of other "asshole player" protections. However,
|
||||
* if you decide you want to have an all-out knock-down drag-out PK Mud, just
|
||||
* set pk_allowed to YES - and anything goes. */
|
||||
int pk_allowed = NO;
|
||||
|
||||
/* Is playerthieving allowed? */
|
||||
int pt_allowed = NO;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
#define _CONFIG_H_
|
||||
|
||||
/* Global variable declarations, all settable by cedit */
|
||||
extern int pk_allowed;
|
||||
extern int script_players;
|
||||
extern int pt_allowed;
|
||||
extern int level_can_shout;
|
||||
|
|
|
|||
|
|
@ -189,8 +189,8 @@ const char *position_types[] = {
|
|||
* @pre Must be in the same order as the defines.
|
||||
* Must end array with a single newline. */
|
||||
const char *player_bits[] = {
|
||||
"KILLER",
|
||||
"THIEF",
|
||||
"UNUSED0",
|
||||
"UNUSED1",
|
||||
"FROZEN",
|
||||
"DONTSET",
|
||||
"WRITING",
|
||||
|
|
@ -228,9 +228,9 @@ const char *action_bits[] = {
|
|||
"AGGR",
|
||||
"STAY-ZONE",
|
||||
"WIMPY",
|
||||
"AGGR_EVIL",
|
||||
"AGGR_GOOD",
|
||||
"AGGR_NEUTRAL",
|
||||
"RESERVED",
|
||||
"RESERVED",
|
||||
"RESERVED",
|
||||
"MEMORY",
|
||||
"HELPER",
|
||||
"NO_CHARM",
|
||||
|
|
@ -240,6 +240,7 @@ const char *action_bits[] = {
|
|||
"NO_BLIND",
|
||||
"NO_KILL",
|
||||
"DEAD", /* You should never see this. */
|
||||
"MOUNT",
|
||||
"\n"
|
||||
};
|
||||
|
||||
|
|
@ -253,7 +254,7 @@ const char *preference_bits[] = {
|
|||
"NO_TELL",
|
||||
"D_HP",
|
||||
"D_MANA",
|
||||
"D_MOVE",
|
||||
"D_STAMINA",
|
||||
"AUTOEX",
|
||||
"NO_HASS",
|
||||
"QUEST",
|
||||
|
|
@ -289,7 +290,6 @@ const char *affected_bits[] =
|
|||
"\0", /* DO NOT REMOVE!! */
|
||||
"BLIND",
|
||||
"INVIS",
|
||||
"DET-ALIGN",
|
||||
"DET-INVIS",
|
||||
"DET-MAGIC",
|
||||
"SENSE-LIFE",
|
||||
|
|
@ -299,8 +299,8 @@ const char *affected_bits[] =
|
|||
"CURSE",
|
||||
"INFRA",
|
||||
"POISON",
|
||||
"PROT-EVIL",
|
||||
"PROT-GOOD",
|
||||
"RESERVED",
|
||||
"RESERVED",
|
||||
"SLEEP",
|
||||
"NO_TRACK",
|
||||
"FLY",
|
||||
|
|
@ -311,6 +311,7 @@ const char *affected_bits[] =
|
|||
"CHARM",
|
||||
"BANDAGED",
|
||||
"LISTEN",
|
||||
"MOUNTED",
|
||||
"\n"
|
||||
};
|
||||
|
||||
|
|
@ -326,7 +327,9 @@ const char *connected_types[] = {
|
|||
"Get new PW",
|
||||
"Confirm new PW",
|
||||
"Select sex",
|
||||
"Select species",
|
||||
"Select class",
|
||||
"Short description",
|
||||
"Reading MOTD",
|
||||
"Main Menu",
|
||||
"Get descript.",
|
||||
|
|
@ -350,7 +353,18 @@ const char *connected_types[] = {
|
|||
"Preference edit",
|
||||
"IBT edit",
|
||||
"Message edit",
|
||||
"Protocol Detection",
|
||||
"Background/Protocol",
|
||||
"Connect menu",
|
||||
"Get account",
|
||||
"Confirm account",
|
||||
"Account password",
|
||||
"New account PW",
|
||||
"Confirm account PW",
|
||||
"Account email",
|
||||
"Account menu",
|
||||
"Account list",
|
||||
"Stat preference",
|
||||
"Select age",
|
||||
"\n"
|
||||
};
|
||||
|
||||
|
|
@ -472,17 +486,6 @@ const char *extra_bits[] = {
|
|||
"MAGIC",
|
||||
"NO_DROP",
|
||||
"BLESS",
|
||||
"ANTI_GOOD",
|
||||
"ANTI_EVIL",
|
||||
"ANTI_NEUTRAL",
|
||||
"ANTI_SORCEROR",
|
||||
"ANTI_CLERIC",
|
||||
"ANTI_ROGUE",
|
||||
"ANTI_FIGHTER",
|
||||
"ANTI_BARBARIAN",
|
||||
"ANTI_RANGER",
|
||||
"ANTI_BARD",
|
||||
"ANTI_DRUID",
|
||||
"NO_SELL",
|
||||
"QUEST_ITEM",
|
||||
"HOOD_UP",
|
||||
|
|
@ -511,7 +514,7 @@ const char *apply_types[] = {
|
|||
"CHAR_HEIGHT",
|
||||
"MAXMANA",
|
||||
"MAXHIT",
|
||||
"MAXMOVE",
|
||||
"MAXSTAMINA",
|
||||
"COINS",
|
||||
"EXP",
|
||||
"ARMOR",
|
||||
|
|
|
|||
178
src/db.c
178
src/db.c
|
|
@ -21,6 +21,7 @@
|
|||
#include "house.h"
|
||||
#include "constants.h"
|
||||
#include "oasis.h"
|
||||
#include "species.h"
|
||||
#include "dg_scripts.h"
|
||||
#include "dg_event.h"
|
||||
#include "act.h"
|
||||
|
|
@ -30,6 +31,7 @@
|
|||
#include "genolc.h"
|
||||
#include "genobj.h" /* for free_object_strings */
|
||||
#include "config.h" /* for the default config values. */
|
||||
#include "class.h"
|
||||
#include "fight.h"
|
||||
#include "modify.h"
|
||||
#include "shop.h"
|
||||
|
|
@ -38,7 +40,6 @@
|
|||
#include "mud_event.h"
|
||||
#include "msgedit.h"
|
||||
#include "screen.h"
|
||||
#include "roomsave.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* declarations of most of the 'global' variables */
|
||||
|
|
@ -748,6 +749,7 @@ void boot_db(void)
|
|||
|
||||
log("Assigning spell and skill levels.");
|
||||
init_spell_levels();
|
||||
init_class_skill_caps();
|
||||
|
||||
log("Sorting command list and spells.");
|
||||
sort_commands();
|
||||
|
|
@ -1600,10 +1602,10 @@ static void parse_simple_mob(FILE *mob_f, int i, int nr)
|
|||
GET_MAX_HIT(mob_proto + i) = 0;
|
||||
GET_HIT(mob_proto + i) = t[1];
|
||||
GET_MANA(mob_proto + i) = t[2];
|
||||
GET_MOVE(mob_proto + i) = t[3];
|
||||
GET_STAMINA(mob_proto + i) = t[3];
|
||||
|
||||
GET_MAX_MANA(mob_proto + i) = 10;
|
||||
GET_MAX_MOVE(mob_proto + i) = 50;
|
||||
GET_MAX_STAMINA(mob_proto + i) = 50;
|
||||
|
||||
if (!get_line(mob_f, line)) {
|
||||
log("SYSERR: Format error in last line of mob #%d\n"
|
||||
|
|
@ -1622,6 +1624,7 @@ static void parse_simple_mob(FILE *mob_f, int i, int nr)
|
|||
GET_SEX(mob_proto + i) = t[2];
|
||||
|
||||
GET_CLASS(mob_proto + i) = CLASS_UNDEFINED;
|
||||
GET_SPECIES(mob_proto + i) = SPECIES_UNDEFINED;
|
||||
GET_WEIGHT(mob_proto + i) = 200;
|
||||
GET_HEIGHT(mob_proto + i) = 198;
|
||||
|
||||
|
|
@ -1705,6 +1708,14 @@ static void interpret_espec(const char *keyword, const char *value, int i, int n
|
|||
RANGE(CLASS_UNDEFINED, NUM_CLASSES - 1);
|
||||
mob_proto[i].player.chclass = num_arg;
|
||||
}
|
||||
CASE("Species") {
|
||||
RANGE(SPECIES_UNDEFINED, NUM_SPECIES - 1);
|
||||
mob_proto[i].player.species = num_arg;
|
||||
}
|
||||
CASE("Age") {
|
||||
RANGE(MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
mob_proto[i].player.roleplay_age = num_arg;
|
||||
}
|
||||
|
||||
/* --- 5e-style Saving Throws --- */
|
||||
CASE("SaveStr") {
|
||||
|
|
@ -1890,13 +1901,6 @@ void parse_mobile(FILE *mob_f, int nr)
|
|||
REMOVE_BIT_AR(AFF_FLAGS(mob_proto + i), AFF_CHARM);
|
||||
REMOVE_BIT_AR(AFF_FLAGS(mob_proto + i), AFF_POISON);
|
||||
REMOVE_BIT_AR(AFF_FLAGS(mob_proto + i), AFF_SLEEP);
|
||||
if (MOB_FLAGGED(mob_proto + i, MOB_AGGRESSIVE) && MOB_FLAGGED(mob_proto + i, MOB_AGGR_GOOD))
|
||||
REMOVE_BIT_AR(MOB_FLAGS(mob_proto + i), MOB_AGGR_GOOD);
|
||||
if (MOB_FLAGGED(mob_proto + i, MOB_AGGRESSIVE) && MOB_FLAGGED(mob_proto + i, MOB_AGGR_NEUTRAL))
|
||||
REMOVE_BIT_AR(MOB_FLAGS(mob_proto + i), MOB_AGGR_NEUTRAL);
|
||||
if (MOB_FLAGGED(mob_proto + i, MOB_AGGRESSIVE) && MOB_FLAGGED(mob_proto + i, MOB_AGGR_EVIL))
|
||||
REMOVE_BIT_AR(MOB_FLAGS(mob_proto + i), MOB_AGGR_EVIL);
|
||||
|
||||
check_bitvector_names(AFF_FLAGS(mob_proto + i)[0], affected_bits_count, buf2, "mobile affect");
|
||||
|
||||
/* This is necessary, since if we have conventional world files, &letter is
|
||||
|
|
@ -1955,6 +1959,13 @@ void parse_mobile(FILE *mob_f, int nr)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (mob_proto[i].player.time.birth == 0)
|
||||
mob_proto[i].player.time.birth = time(0);
|
||||
if (mob_proto[i].player.roleplay_age == 0)
|
||||
mob_proto[i].player.roleplay_age = MIN_CHAR_AGE;
|
||||
if (mob_proto[i].player.roleplay_age_year == 0)
|
||||
mob_proto[i].player.roleplay_age_year = time_info.year;
|
||||
|
||||
letter = fread_letter(mob_f);
|
||||
while (letter == 'L') {
|
||||
int wpos = -1, vnum = -1, qty = 1;
|
||||
|
|
@ -1969,7 +1980,7 @@ void parse_mobile(FILE *mob_f, int nr)
|
|||
log("SYSERR: Bad 'L' line in mob #%d: '%s' (need <wear_pos> <obj_vnum> [qty]).", nr, line);
|
||||
} else {
|
||||
if (qty < 1) qty = 1;
|
||||
loadout_add_entry(&mob_proto[i].proto_loadout, vnum, (int)wpos, qty);
|
||||
loadout_append_entry(&mob_proto[i].proto_loadout, vnum, (int)wpos, qty);
|
||||
}
|
||||
/* look ahead to see if there is another 'L' */
|
||||
letter = fread_letter(mob_f);
|
||||
|
|
@ -2062,7 +2073,7 @@ void parse_mobile(FILE *mob_f, int nr)
|
|||
log("SYSERR: Bad post-trigger 'L' line in mob #%d: '%s' (need <wear_pos> <obj_vnum> [qty]).", nr, line);
|
||||
} else {
|
||||
if (qty < 1) qty = 1;
|
||||
loadout_add_entry(&mob_proto[i].proto_loadout, vnum, (int)wpos, qty);
|
||||
loadout_append_entry(&mob_proto[i].proto_loadout, vnum, (int)wpos, qty);
|
||||
}
|
||||
letter = fread_letter(mob_f);
|
||||
}
|
||||
|
|
@ -2634,6 +2645,11 @@ void equip_mob_from_loadout(struct char_data *mob)
|
|||
const struct mob_loadout *e = mob_proto[rnum].proto_loadout;
|
||||
if (!e) return;
|
||||
|
||||
struct obj_data *stack[16];
|
||||
int i;
|
||||
for (i = 0; i < (int)(sizeof(stack) / sizeof(stack[0])); i++)
|
||||
stack[i] = NULL;
|
||||
|
||||
for (; e; e = e->next) {
|
||||
int qty = (e->quantity > 0) ? e->quantity : 1;
|
||||
|
||||
|
|
@ -2645,46 +2661,73 @@ void equip_mob_from_loadout(struct char_data *mob)
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Inventory-only request */
|
||||
if (e->wear_pos < 0) {
|
||||
obj_to_char(obj, mob);
|
||||
continue;
|
||||
}
|
||||
if (e->wear_pos >= 0) {
|
||||
for (i = 0; i < (int)(sizeof(stack) / sizeof(stack[0])); i++)
|
||||
stack[i] = NULL;
|
||||
|
||||
/* If the intended slot is free, place it there. We trust the saved slot. */
|
||||
if (e->wear_pos >= 0 && e->wear_pos < NUM_WEARS && GET_EQ(mob, e->wear_pos) == NULL) {
|
||||
/* If the intended slot is free, place it there. We trust the saved slot. */
|
||||
if (e->wear_pos < NUM_WEARS && GET_EQ(mob, e->wear_pos) == NULL) {
|
||||
|
||||
#ifdef STRICT_WEAR_CHECK
|
||||
/* Optional strict flag check (may be mismatched in customized codebases). */
|
||||
if (!invalid_align(mob, obj) /* example gate, add yours as needed */) {
|
||||
equip_char(mob, obj, e->wear_pos);
|
||||
continue;
|
||||
}
|
||||
/* If strict check fails, try alt or inventory below. */
|
||||
#else
|
||||
equip_char(mob, obj, e->wear_pos);
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Try the mirrored slot for finger/neck/wrist pairs if intended is occupied. */
|
||||
{
|
||||
int alt = find_alt_slot_same_family(mob, e->wear_pos);
|
||||
if (alt >= 0 && GET_EQ(mob, alt) == NULL) {
|
||||
#ifdef STRICT_WEAR_CHECK
|
||||
if (!invalid_align(mob, obj)) {
|
||||
equip_char(mob, obj, alt);
|
||||
continue;
|
||||
/* Optional strict flag check (may be mismatched in customized codebases). */
|
||||
if (!invalid_align(mob, obj) /* example gate, add yours as needed */) {
|
||||
equip_char(mob, obj, e->wear_pos);
|
||||
} else {
|
||||
obj_to_char(obj, mob);
|
||||
}
|
||||
#else
|
||||
equip_char(mob, obj, alt);
|
||||
continue;
|
||||
equip_char(mob, obj, e->wear_pos);
|
||||
#endif
|
||||
} else {
|
||||
/* Try the mirrored slot for finger/neck/wrist pairs if intended is occupied. */
|
||||
int alt = find_alt_slot_same_family(mob, e->wear_pos);
|
||||
if (alt >= 0 && GET_EQ(mob, alt) == NULL) {
|
||||
#ifdef STRICT_WEAR_CHECK
|
||||
if (!invalid_align(mob, obj)) {
|
||||
equip_char(mob, obj, alt);
|
||||
} else {
|
||||
obj_to_char(obj, mob);
|
||||
}
|
||||
#else
|
||||
equip_char(mob, obj, alt);
|
||||
#endif
|
||||
} else {
|
||||
/* Couldn’t place it — keep in inventory. */
|
||||
obj_to_char(obj, mob);
|
||||
}
|
||||
}
|
||||
|
||||
if (obj_is_storage(obj) || GET_OBJ_TYPE(obj) == ITEM_FURNITURE)
|
||||
stack[0] = obj;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Couldn’t place it — keep in inventory. */
|
||||
obj_to_char(obj, mob);
|
||||
/* Inventory-only request */
|
||||
if (e->wear_pos == -1) {
|
||||
for (i = 0; i < (int)(sizeof(stack) / sizeof(stack[0])); i++)
|
||||
stack[i] = NULL;
|
||||
obj_to_char(obj, mob);
|
||||
if (obj_is_storage(obj) || GET_OBJ_TYPE(obj) == ITEM_FURNITURE)
|
||||
stack[0] = obj;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Nested inventory: wear_pos = -2 (depth 1), -3 (depth 2), etc. */
|
||||
{
|
||||
int depth = -(e->wear_pos) - 1;
|
||||
if (depth <= 0 ||
|
||||
depth >= (int)(sizeof(stack) / sizeof(stack[0])) ||
|
||||
!stack[depth - 1]) {
|
||||
obj_to_char(obj, mob);
|
||||
continue;
|
||||
}
|
||||
obj_to_obj(obj, stack[depth - 1]);
|
||||
if (obj_is_storage(obj) || GET_OBJ_TYPE(obj) == ITEM_FURNITURE) {
|
||||
stack[depth] = obj;
|
||||
for (i = depth + 1; i < (int)(sizeof(stack) / sizeof(stack[0])); i++)
|
||||
stack[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2729,15 +2772,28 @@ struct char_data *read_mobile(mob_vnum nr, int type) /* and mob_rnum */
|
|||
|
||||
if (!mob->points.max_hit) {
|
||||
mob->points.max_hit = dice(mob->points.hit, mob->points.mana) +
|
||||
mob->points.move;
|
||||
mob->points.stamina;
|
||||
} else
|
||||
mob->points.max_hit = rand_number(mob->points.hit, mob->points.mana);
|
||||
|
||||
{
|
||||
int base_hit = 0;
|
||||
int base_mana = 0;
|
||||
int base_stamina = 0;
|
||||
|
||||
if (get_species_base_points(GET_SPECIES(mob), &base_hit, &base_mana, &base_stamina)) {
|
||||
mob->points.max_hit += base_hit;
|
||||
mob->points.max_mana += base_mana;
|
||||
mob->points.max_stamina += base_stamina;
|
||||
}
|
||||
}
|
||||
|
||||
mob->points.hit = mob->points.max_hit;
|
||||
mob->points.mana = mob->points.max_mana;
|
||||
mob->points.move = mob->points.max_move;
|
||||
mob->points.stamina = mob->points.max_stamina;
|
||||
|
||||
mob->player.time.birth = time(0);
|
||||
if (mob->player.time.birth == 0)
|
||||
mob->player.time.birth = time(0);
|
||||
mob->player.time.played = 0;
|
||||
mob->player.time.logon = time(0);
|
||||
|
||||
|
|
@ -2794,6 +2850,9 @@ struct obj_data *read_object(obj_vnum nr, int type) /* and obj_rnum */
|
|||
copy_proto_script(&obj_proto[i], obj, OBJ_TRIGGER);
|
||||
assign_triggers(obj, OBJ_TRIGGER);
|
||||
|
||||
if (GET_OBJ_TYPE(obj) == ITEM_MONEY)
|
||||
update_money_obj(obj);
|
||||
|
||||
return (obj);
|
||||
}
|
||||
|
||||
|
|
@ -3747,8 +3806,8 @@ void reset_char(struct char_data *ch)
|
|||
|
||||
if (GET_HIT(ch) <= 0)
|
||||
GET_HIT(ch) = 1;
|
||||
if (GET_MOVE(ch) <= 0)
|
||||
GET_MOVE(ch) = 1;
|
||||
if (GET_STAMINA(ch) <= 0)
|
||||
GET_STAMINA(ch) = 1;
|
||||
if (GET_MANA(ch) <= 0)
|
||||
GET_MANA(ch) = 1;
|
||||
|
||||
|
|
@ -3764,6 +3823,7 @@ void clear_char(struct char_data *ch)
|
|||
GET_PFILEPOS(ch) = -1;
|
||||
GET_MOB_RNUM(ch) = NOBODY;
|
||||
GET_CLASS(ch) = CLASS_UNDEFINED;
|
||||
GET_SPECIES(ch) = SPECIES_UNDEFINED;
|
||||
GET_WAS_IN(ch) = NOWHERE;
|
||||
GET_POS(ch) = POS_STANDING;
|
||||
ch->mob_specials.default_pos = POS_STANDING;
|
||||
|
|
@ -3802,12 +3862,12 @@ void init_char(struct char_data *ch)
|
|||
GET_EXP(ch) = 7000000;
|
||||
|
||||
/* The implementor never goes through do_start(). */
|
||||
GET_MAX_HIT(ch) = 500;
|
||||
GET_MAX_MANA(ch) = 100;
|
||||
GET_MAX_MOVE(ch) = 82;
|
||||
GET_MAX_HIT(ch) = 999;
|
||||
GET_MAX_MANA(ch) = 999;
|
||||
GET_MAX_STAMINA(ch) = 999;
|
||||
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);
|
||||
}
|
||||
|
||||
ch->player.short_descr = NULL;
|
||||
|
|
@ -3819,7 +3879,12 @@ void init_char(struct char_data *ch)
|
|||
ch->player_specials->saved.completed_quests = NULL;
|
||||
GET_QUEST(ch) = NOTHING;
|
||||
|
||||
ch->player.time.birth = time(0);
|
||||
if (ch->player.time.birth == 0)
|
||||
ch->player.time.birth = time(0);
|
||||
if (GET_ROLEPLAY_AGE(ch) == 0)
|
||||
GET_ROLEPLAY_AGE(ch) = MIN_CHAR_AGE;
|
||||
if (GET_ROLEPLAY_AGE_YEAR(ch) == 0)
|
||||
GET_ROLEPLAY_AGE_YEAR(ch) = time_info.year;
|
||||
ch->player.time.logon = time(0);
|
||||
ch->player.time.played = 0;
|
||||
|
||||
|
|
@ -3880,7 +3945,7 @@ void init_char(struct char_data *ch)
|
|||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/* returns the real number of the room with given virtual number */
|
||||
|
|
@ -4128,7 +4193,6 @@ static void load_default_config( void )
|
|||
/* This function is called only once, at boot-time. We assume config_info is
|
||||
* empty. -Welcor */
|
||||
/* Game play options. */
|
||||
CONFIG_PK_ALLOWED = pk_allowed;
|
||||
CONFIG_PT_ALLOWED = pt_allowed;
|
||||
CONFIG_LEVEL_CAN_SHOUT = level_can_shout;
|
||||
CONFIG_TUNNEL_SIZE = tunnel_size;
|
||||
|
|
@ -4388,9 +4452,7 @@ void load_config( void )
|
|||
break;
|
||||
|
||||
case 'p':
|
||||
if (!str_cmp(tag, "pk_allowed"))
|
||||
CONFIG_PK_ALLOWED = num;
|
||||
else if (!str_cmp(tag, "protocol_negotiation"))
|
||||
if (!str_cmp(tag, "protocol_negotiation"))
|
||||
CONFIG_PROTOCOL_NEGOTIATION = num;
|
||||
else if (!str_cmp(tag, "pt_allowed"))
|
||||
CONFIG_PT_ALLOWED = num;
|
||||
|
|
|
|||
|
|
@ -801,30 +801,6 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (!str_cmp(field, "is_killer")) {
|
||||
if (subfield && *subfield) {
|
||||
if (!str_cmp("on", subfield))
|
||||
SET_BIT_AR(PLR_FLAGS(c), PLR_KILLER);
|
||||
else if (!str_cmp("off", subfield))
|
||||
REMOVE_BIT_AR(PLR_FLAGS(c), PLR_KILLER);
|
||||
}
|
||||
if (PLR_FLAGGED(c, PLR_KILLER))
|
||||
strcpy(str, "1");
|
||||
else
|
||||
strcpy(str, "0");
|
||||
}
|
||||
else if (!str_cmp(field, "is_thief")) {
|
||||
if (subfield && *subfield) {
|
||||
if (!str_cmp("on", subfield))
|
||||
SET_BIT_AR(PLR_FLAGS(c), PLR_THIEF);
|
||||
else if (!str_cmp("off", subfield))
|
||||
REMOVE_BIT_AR(PLR_FLAGS(c), PLR_THIEF);
|
||||
}
|
||||
if (PLR_FLAGGED(c, PLR_THIEF))
|
||||
strcpy(str, "1");
|
||||
else
|
||||
strcpy(str, "0");
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if (!str_cmp(field, "level")) {
|
||||
|
|
@ -867,19 +843,19 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
|
|||
}
|
||||
snprintf(str, slen, "%d", GET_MAX_MANA(c));
|
||||
}
|
||||
else if (!str_cmp(field, "maxmove")) {
|
||||
else if (!str_cmp(field, "maxmove") || !str_cmp(field, "maxstamina")) {
|
||||
if (subfield && *subfield) {
|
||||
int addition = atoi(subfield);
|
||||
GET_MAX_MOVE(c) = MAX(GET_MAX_MOVE(c) + addition, 1);
|
||||
GET_MAX_STAMINA(c) = MAX(GET_MAX_STAMINA(c) + addition, 1);
|
||||
}
|
||||
snprintf(str, slen, "%d", GET_MAX_MOVE(c));
|
||||
snprintf(str, slen, "%d", GET_MAX_STAMINA(c));
|
||||
}
|
||||
else if (!str_cmp(field, "move")) {
|
||||
else if (!str_cmp(field, "move") || !str_cmp(field, "stamina")) {
|
||||
if (subfield && *subfield) {
|
||||
int addition = atoi(subfield);
|
||||
GET_MOVE(c) += addition;
|
||||
GET_STAMINA(c) += addition;
|
||||
}
|
||||
snprintf(str, slen, "%d", GET_MOVE(c));
|
||||
snprintf(str, slen, "%d", GET_STAMINA(c));
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
|
|
|
|||
131
src/fight.c
131
src/fight.c
|
|
@ -57,7 +57,6 @@ static struct char_data *next_combat_list = NULL;
|
|||
static void perform_group_gain(struct char_data *ch, int base, struct char_data *victim);
|
||||
static void dam_message(int dam, struct char_data *ch, struct char_data *victim, int w_type);
|
||||
static void make_corpse(struct char_data *ch);
|
||||
static void change_alignment(struct char_data *ch, struct char_data *victim);
|
||||
static void group_gain(struct char_data *ch, struct char_data *victim);
|
||||
static void solo_gain(struct char_data *ch, struct char_data *victim);
|
||||
/** @todo refactor this function name */
|
||||
|
|
@ -72,8 +71,8 @@ static int roll_damage(struct char_data *ch, struct char_data *victim,
|
|||
int dam = 0;
|
||||
|
||||
if (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON) {
|
||||
int ndice = GET_OBJ_VAL(wielded, 1); /* #dice */
|
||||
int sdice = GET_OBJ_VAL(wielded, 2); /* sides */
|
||||
int ndice = GET_OBJ_VAL(wielded, 0); /* #dice */
|
||||
int sdice = GET_OBJ_VAL(wielded, 1); /* sides */
|
||||
dam = dice(ndice, sdice);
|
||||
dam += GET_ABILITY_MOD(GET_STR(ch)); /* STR adds to weapon damage */
|
||||
} else {
|
||||
|
|
@ -92,7 +91,7 @@ static int weapon_family_skill_num(struct char_data *ch, struct obj_data *wielde
|
|||
if (!wielded || GET_OBJ_TYPE(wielded) != ITEM_WEAPON)
|
||||
return SKILL_UNARMED;
|
||||
|
||||
/* NOTE: w_type here is TYPE_HIT + GET_OBJ_VAL(wielded, 3) or mob attack type + TYPE_HIT.
|
||||
/* NOTE: w_type here is TYPE_HIT + GET_OBJ_VAL(wielded, 2) or mob attack type + TYPE_HIT.
|
||||
Adjust the cases below to match your game's TYPE_* values. */
|
||||
switch (w_type) {
|
||||
/* --- Piercing family --- */
|
||||
|
|
@ -176,20 +175,6 @@ void update_pos(struct char_data *victim)
|
|||
GET_POS(victim) = POS_STUNNED;
|
||||
}
|
||||
|
||||
void check_killer(struct char_data *ch, struct char_data *vict)
|
||||
{
|
||||
if (PLR_FLAGGED(vict, PLR_KILLER) || PLR_FLAGGED(vict, PLR_THIEF))
|
||||
return;
|
||||
if (PLR_FLAGGED(ch, PLR_KILLER) || IS_NPC(ch) || IS_NPC(vict) || ch == vict)
|
||||
return;
|
||||
|
||||
SET_BIT_AR(PLR_FLAGS(ch), PLR_KILLER);
|
||||
send_to_char(ch, "If you want to be a PLAYER KILLER, so be it...\r\n");
|
||||
mudlog(BRF, MAX(LVL_IMMORT, MAX(GET_INVIS_LEV(ch), GET_INVIS_LEV(vict))),
|
||||
TRUE, "PC Killer bit set on %s for initiating attack on %s at %s.",
|
||||
GET_NAME(ch), GET_NAME(vict), world[IN_ROOM(vict)].name);
|
||||
}
|
||||
|
||||
/* start one char fighting another (yes, it is horrible, I know... ) */
|
||||
void set_fighting(struct char_data *ch, struct char_data *vict)
|
||||
{
|
||||
|
|
@ -210,8 +195,6 @@ void set_fighting(struct char_data *ch, struct char_data *vict)
|
|||
FIGHTING(ch) = vict;
|
||||
GET_POS(ch) = POS_FIGHTING;
|
||||
|
||||
if (!CONFIG_PK_ALLOWED)
|
||||
check_killer(ch, vict);
|
||||
}
|
||||
|
||||
/* remove a char from the list of fighting chars */
|
||||
|
|
@ -297,14 +280,6 @@ static void make_corpse(struct char_data *ch)
|
|||
obj_to_room(corpse, IN_ROOM(ch));
|
||||
}
|
||||
|
||||
/* When ch kills victim */
|
||||
static void change_alignment(struct char_data *ch, struct char_data *victim)
|
||||
{
|
||||
/* new alignment change algorithm: if you kill a monster with alignment A,
|
||||
* you move 1/16th of the way to having alignment -A. Simple and fast. */
|
||||
GET_ALIGNMENT(ch) += (-GET_ALIGNMENT(victim) - GET_ALIGNMENT(ch)) / 16;
|
||||
}
|
||||
|
||||
void death_cry(struct char_data *ch)
|
||||
{
|
||||
int door;
|
||||
|
|
@ -363,8 +338,6 @@ struct char_data *i;
|
|||
void die(struct char_data * ch, struct char_data * killer)
|
||||
{
|
||||
if (!IS_NPC(ch)) {
|
||||
REMOVE_BIT_AR(PLR_FLAGS(ch), PLR_KILLER);
|
||||
REMOVE_BIT_AR(PLR_FLAGS(ch), PLR_THIEF);
|
||||
}
|
||||
raw_kill(ch, killer);
|
||||
}
|
||||
|
|
@ -372,11 +345,9 @@ void die(struct char_data * ch, struct char_data * killer)
|
|||
static void perform_group_gain(struct char_data *ch, int base,
|
||||
struct char_data *victim)
|
||||
{
|
||||
int share;
|
||||
|
||||
share = MIN(CONFIG_MAX_EXP_GAIN, MAX(1, base));
|
||||
|
||||
change_alignment(ch, victim);
|
||||
(void)ch;
|
||||
(void)base;
|
||||
(void)victim;
|
||||
}
|
||||
|
||||
static void group_gain(struct char_data *ch, struct char_data *victim)
|
||||
|
|
@ -418,8 +389,6 @@ static void solo_gain(struct char_data *ch, struct char_data *victim)
|
|||
exp += MAX(0, (exp * MIN(8, (GET_LEVEL(victim) - GET_LEVEL(ch)))) / 8);
|
||||
|
||||
exp = MAX(exp, 1);
|
||||
|
||||
change_alignment(ch, victim);
|
||||
}
|
||||
|
||||
static char *replace_string(const char *str, const char *weapon_singular, const char *weapon_plural)
|
||||
|
|
@ -634,6 +603,7 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, int attackty
|
|||
char local_buf[256];
|
||||
struct char_data *tmp_char;
|
||||
struct obj_data *corpse_obj;
|
||||
int prev_hit = 0;
|
||||
|
||||
if (GET_POS(victim) <= POS_DEAD) {
|
||||
/* This is "normal"-ish now with delayed extraction. -gg 3/15/2001 */
|
||||
|
|
@ -659,8 +629,8 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, int attackty
|
|||
return (0);
|
||||
}
|
||||
|
||||
/* You can't damage an immortal! */
|
||||
if (!IS_NPC(victim) && ((GET_LEVEL(victim) >= LVL_IMMORT) && PRF_FLAGGED(victim, PRF_NOHASSLE)))
|
||||
/* Immortals cannot be damaged. */
|
||||
if (!IS_NPC(victim) && GET_REAL_LEVEL(victim) >= LVL_IMMORT)
|
||||
dam = 0;
|
||||
|
||||
dam = damage_mtrigger(ch, victim, dam, attacktype);
|
||||
|
|
@ -694,14 +664,9 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, int attackty
|
|||
dam /= 2;
|
||||
|
||||
/* Check for PK if this is not a PK MUD */
|
||||
if (!CONFIG_PK_ALLOWED) {
|
||||
check_killer(ch, victim);
|
||||
if (PLR_FLAGGED(ch, PLR_KILLER) && (ch != victim))
|
||||
dam = 0;
|
||||
}
|
||||
|
||||
/* Set the maximum damage per round and subtract the hit points */
|
||||
dam = MAX(MIN(dam, 100), 0);
|
||||
prev_hit = GET_HIT(victim);
|
||||
GET_HIT(victim) -= dam;
|
||||
|
||||
update_pos(victim);
|
||||
|
|
@ -826,16 +791,30 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, int attackty
|
|||
void hit(struct char_data *ch, struct char_data *victim, int type)
|
||||
{
|
||||
struct obj_data *wielded = GET_EQ(ch, WEAR_WIELD);
|
||||
bool wielded_weapon = (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON);
|
||||
struct obj_data *shield = GET_EQ(victim, WEAR_SHIELD);
|
||||
int w_type, d20, attack_mod = 0, target_ac, dam = 0;
|
||||
bool hit_success = FALSE;
|
||||
bool attacker_immortal, victim_immortal;
|
||||
bool attacker_is_player, victim_is_player;
|
||||
int unarmed_die_size = 0;
|
||||
int unarmed_prof_bonus = 0;
|
||||
int unarmed_str_mod = 0;
|
||||
|
||||
/* Basic sanity */
|
||||
if (!ch || !victim) return;
|
||||
|
||||
attacker_is_player = (ch->desc != NULL);
|
||||
victim_is_player = (victim->desc != NULL);
|
||||
|
||||
attacker_immortal = (attacker_is_player &&
|
||||
(GET_REAL_LEVEL(ch) >= LVL_IMMORT || PRF_FLAGGED(ch, PRF_NOHASSLE)));
|
||||
victim_immortal = (victim_is_player &&
|
||||
(GET_REAL_LEVEL(victim) >= LVL_IMMORT || PRF_FLAGGED(victim, PRF_NOHASSLE)));
|
||||
|
||||
/* Determine attack message type exactly like stock code */
|
||||
if (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON)
|
||||
w_type = GET_OBJ_VAL(wielded, 3) + TYPE_HIT;
|
||||
if (wielded_weapon)
|
||||
w_type = GET_OBJ_VAL(wielded, 2) + TYPE_HIT;
|
||||
else {
|
||||
if (IS_NPC(ch) && ch->mob_specials.attack_type != 0)
|
||||
w_type = ch->mob_specials.attack_type + TYPE_HIT;
|
||||
|
|
@ -843,6 +822,39 @@ void hit(struct char_data *ch, struct char_data *victim, int type)
|
|||
w_type = TYPE_HIT;
|
||||
} /* matches stock message mapping */
|
||||
|
||||
if (victim_immortal) {
|
||||
damage(ch, victim, 0, w_type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (attacker_immortal) {
|
||||
if (wielded_weapon) {
|
||||
int ndice = GET_OBJ_VAL(wielded, 0);
|
||||
int sdice = GET_OBJ_VAL(wielded, 1);
|
||||
dam = (ndice * sdice) + GET_ABILITY_MOD(GET_STR(ch));
|
||||
} else {
|
||||
int prof_bonus = (!IS_NPC(ch)) ? GET_PROFICIENCY(GET_SKILL(ch, SKILL_UNARMED)) : 0;
|
||||
int str_mod = GET_ABILITY_MOD(GET_STR(ch));
|
||||
int die_size;
|
||||
|
||||
switch (prof_bonus) {
|
||||
case 0: die_size = 4; break; /* untrained */
|
||||
case 1: die_size = 6; break; /* trained */
|
||||
case 2: die_size = 8; break; /* expert */
|
||||
default: die_size = 10; break; /* master or above */
|
||||
}
|
||||
|
||||
if (IS_NPC(ch) && prof_bonus <= 0) {
|
||||
prof_bonus = MIN(6, (GET_LEVEL(ch) / 4));
|
||||
}
|
||||
|
||||
dam = die_size + str_mod + prof_bonus;
|
||||
}
|
||||
|
||||
damage(ch, victim, dam, w_type);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Roll d20 */
|
||||
d20 = rand_number(1, 20);
|
||||
|
||||
|
|
@ -859,7 +871,7 @@ void hit(struct char_data *ch, struct char_data *victim, int type)
|
|||
attack_mod += GET_PROFICIENCY(GET_SKILL(ch, skillnum));
|
||||
|
||||
/* --- UNARMED ATTACK HANDLING --- */
|
||||
if (!wielded) {
|
||||
if (!wielded_weapon) {
|
||||
int prof_bonus = (!IS_NPC(ch)) ? GET_PROFICIENCY(GET_SKILL(ch, SKILL_UNARMED)) : 0;
|
||||
int str_mod = GET_ABILITY_MOD(GET_STR(ch));
|
||||
int die_size;
|
||||
|
|
@ -871,6 +883,7 @@ void hit(struct char_data *ch, struct char_data *victim, int type)
|
|||
case 2: die_size = 8; break; /* expert */
|
||||
default: die_size = 10; break; /* master or above */
|
||||
}
|
||||
unarmed_die_size = die_size;
|
||||
|
||||
/* NPC fallback scaling */
|
||||
if (IS_NPC(ch) && prof_bonus <= 0) {
|
||||
|
|
@ -879,9 +892,11 @@ void hit(struct char_data *ch, struct char_data *victim, int type)
|
|||
|
||||
/* base damage roll for unarmed attacks */
|
||||
dam = dice(1, die_size) + str_mod + prof_bonus;
|
||||
unarmed_prof_bonus = prof_bonus;
|
||||
unarmed_str_mod = str_mod;
|
||||
|
||||
/* mark attack type for damage() messaging */
|
||||
w_type = SKILL_UNARMED + TYPE_HIT;
|
||||
w_type = TYPE_HIT;
|
||||
}
|
||||
|
||||
/* Weapon magic (cap +3) */
|
||||
|
|
@ -901,8 +916,9 @@ void hit(struct char_data *ch, struct char_data *victim, int type)
|
|||
/* Ascending AC target */
|
||||
target_ac = compute_armor_class_asc(victim);
|
||||
|
||||
/* Nat 1/20, then normal resolution */
|
||||
if (d20 == 1) hit_success = FALSE;
|
||||
/* Nat 1/20, then normal resolution (immortals always hit). */
|
||||
if (attacker_immortal) hit_success = TRUE;
|
||||
else if (d20 == 1) hit_success = FALSE;
|
||||
else if (d20 == 20) hit_success = TRUE;
|
||||
else hit_success = ((d20 + attack_mod) >= target_ac);
|
||||
|
||||
|
|
@ -912,13 +928,22 @@ void hit(struct char_data *ch, struct char_data *victim, int type)
|
|||
* If we are unarmed, dam was already rolled above.
|
||||
* If wielding a weapon, roll normally.
|
||||
*/
|
||||
if (wielded)
|
||||
if (wielded_weapon)
|
||||
dam = roll_damage(ch, victim, wielded, w_type);
|
||||
if (attacker_immortal) {
|
||||
if (wielded_weapon) {
|
||||
int ndice = GET_OBJ_VAL(wielded, 0);
|
||||
int sdice = GET_OBJ_VAL(wielded, 1);
|
||||
dam = (ndice * sdice) + GET_ABILITY_MOD(GET_STR(ch));
|
||||
} else if (unarmed_die_size > 0) {
|
||||
dam = unarmed_die_size + unarmed_str_mod + unarmed_prof_bonus;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- SHIELD BLOCK CHECK ---
|
||||
* Only happens if an attack actually lands.
|
||||
*/
|
||||
if (shield) {
|
||||
if (shield && !attacker_immortal) {
|
||||
int def_prof = (!IS_NPC(victim)) ? GET_PROFICIENCY(GET_SKILL(victim, SKILL_SHIELD_USE)) : 0;
|
||||
int block_chance = def_prof * 10; /* 0–60% total chance to block an attack */
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ struct attack_hit_type {
|
|||
|
||||
/* Functions available in fight.c */
|
||||
void appear(struct char_data *ch);
|
||||
void check_killer(struct char_data *ch, struct char_data *vict);
|
||||
int compute_armor_class(struct char_data *ch);
|
||||
int damage(struct char_data *ch, struct char_data *victim, int dam, int attacktype);
|
||||
void death_cry(struct char_data *ch);
|
||||
|
|
|
|||
77
src/genmob.c
77
src/genmob.c
|
|
@ -359,6 +359,18 @@ int write_mobile_espec(mob_vnum mvnum, struct char_data *mob, FILE *fd)
|
|||
fprintf(fd, "Class: %d\n", (int)GET_CLASS(mob));
|
||||
count++;
|
||||
}
|
||||
if (HAS_VALID_SPECIES(mob)) {
|
||||
fprintf(fd, "Species: %d\n", (int)GET_SPECIES(mob));
|
||||
count++;
|
||||
}
|
||||
{
|
||||
int age_years = GET_ROLEPLAY_AGE(mob);
|
||||
if (age_years >= MIN_CHAR_AGE && age_years <= MAX_CHAR_AGE &&
|
||||
age_years != MIN_CHAR_AGE) {
|
||||
fprintf(fd, "Age: %d\n", age_years);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- 5e-style saving throws --- */
|
||||
if (GET_SAVE(mob, ABIL_STR) != 0) {
|
||||
|
|
@ -396,33 +408,60 @@ int write_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd)
|
|||
char ddesc[MAX_STRING_LENGTH];
|
||||
char bdesc[MAX_STRING_LENGTH];
|
||||
char buf[MAX_STRING_LENGTH];
|
||||
int has_bdesc = 0;
|
||||
|
||||
ldesc[MAX_STRING_LENGTH - 1] = '\0';
|
||||
ddesc[MAX_STRING_LENGTH - 1] = '\0';
|
||||
bdesc[MAX_STRING_LENGTH - 1] = '\0';
|
||||
strip_cr(strncpy(ldesc, GET_LDESC(mob), MAX_STRING_LENGTH - 1));
|
||||
strip_cr(strncpy(ddesc, GET_DDESC(mob), MAX_STRING_LENGTH - 1));
|
||||
if (GET_BDESC(mob))
|
||||
if (GET_BDESC(mob)) {
|
||||
strip_cr(strncpy(bdesc, GET_BDESC(mob), MAX_STRING_LENGTH - 1));
|
||||
else
|
||||
{
|
||||
const char *p;
|
||||
for (p = bdesc; *p; p++) {
|
||||
if (*p != ' ' && *p != '\t' && *p != '\r' && *p != '\n') {
|
||||
has_bdesc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
bdesc[0] = '\0';
|
||||
|
||||
int n = snprintf(buf, MAX_STRING_LENGTH,
|
||||
"#%d\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"B\n"
|
||||
"%s%c\n",
|
||||
mvnum,
|
||||
GET_NAME(mob), STRING_TERMINATOR,
|
||||
GET_KEYWORDS(mob), STRING_TERMINATOR,
|
||||
GET_SDESC(mob), STRING_TERMINATOR,
|
||||
ldesc, STRING_TERMINATOR,
|
||||
ddesc, STRING_TERMINATOR,
|
||||
bdesc, STRING_TERMINATOR);
|
||||
int n;
|
||||
if (has_bdesc) {
|
||||
n = snprintf(buf, MAX_STRING_LENGTH,
|
||||
"#%d\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"B\n"
|
||||
"%s%c\n",
|
||||
mvnum,
|
||||
GET_NAME(mob), STRING_TERMINATOR,
|
||||
GET_KEYWORDS(mob), STRING_TERMINATOR,
|
||||
GET_SDESC(mob), STRING_TERMINATOR,
|
||||
ldesc, STRING_TERMINATOR,
|
||||
ddesc, STRING_TERMINATOR,
|
||||
bdesc, STRING_TERMINATOR);
|
||||
} else {
|
||||
n = snprintf(buf, MAX_STRING_LENGTH,
|
||||
"#%d\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n",
|
||||
mvnum,
|
||||
GET_NAME(mob), STRING_TERMINATOR,
|
||||
GET_KEYWORDS(mob), STRING_TERMINATOR,
|
||||
GET_SDESC(mob), STRING_TERMINATOR,
|
||||
ldesc, STRING_TERMINATOR,
|
||||
ddesc, STRING_TERMINATOR);
|
||||
}
|
||||
|
||||
if (n >= MAX_STRING_LENGTH) {
|
||||
mudlog(BRF, LVL_BUILDER, TRUE,
|
||||
|
|
@ -447,7 +486,7 @@ int write_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd)
|
|||
GET_LEVEL(mob),
|
||||
GET_HIT(mob),
|
||||
GET_MANA(mob),
|
||||
GET_MOVE(mob));
|
||||
GET_STAMINA(mob));
|
||||
|
||||
/* --- Position / default position / sex --- */
|
||||
fprintf(fd, "%d %d %d\n",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
int delete_mobile(mob_rnum);
|
||||
int copy_mobile(struct char_data *to, struct char_data *from);
|
||||
int add_mobile(struct char_data *, mob_vnum);
|
||||
void init_mobile(struct char_data *mob);
|
||||
int copy_mob_strings(struct char_data *to, struct char_data *from);
|
||||
int free_mob_strings(struct char_data *);
|
||||
int free_mobile(struct char_data *mob);
|
||||
|
|
|
|||
|
|
@ -629,7 +629,7 @@ static int export_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd)
|
|||
AFF_FLAGS(mob)[2], AFF_FLAGS(mob)[3],
|
||||
GET_ALIGNMENT(mob),
|
||||
GET_LEVEL(mob), GET_HIT(mob),
|
||||
GET_MANA(mob), GET_MOVE(mob));
|
||||
GET_MANA(mob), GET_STAMINA(mob));
|
||||
|
||||
fprintf(fd, "%d %d %d\n",
|
||||
GET_POS(mob), GET_DEFAULT_POS(mob), GET_SEX(mob)
|
||||
|
|
|
|||
|
|
@ -463,6 +463,7 @@ int free_room_strings(struct room_data *room)
|
|||
free(room->description);
|
||||
if (room->ex_description)
|
||||
free_ex_descriptions(room->ex_description);
|
||||
room->ex_description = NULL;
|
||||
if (room->forage)
|
||||
free_forage_list(room->forage);
|
||||
room->forage = NULL;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
#include "fight.h"
|
||||
#include "quest.h"
|
||||
#include "mud_event.h"
|
||||
#include "roomsave.h"
|
||||
|
||||
/* local file scope variables */
|
||||
static int extractions_pending = 0;
|
||||
|
|
@ -148,7 +147,7 @@ static void aff_apply_modify(struct char_data *ch, byte loc, sbyte mod, char *ms
|
|||
case APPLY_CHAR_HEIGHT: GET_HEIGHT(ch) += mod; break;
|
||||
case APPLY_MANA: GET_MAX_MANA(ch) += mod; break;
|
||||
case APPLY_HIT: GET_MAX_HIT(ch) += mod; break;
|
||||
case APPLY_MOVE: GET_MAX_MOVE(ch) += mod; break;
|
||||
case APPLY_STAMINA: GET_MAX_STAMINA(ch) += mod; break;
|
||||
case APPLY_COINS: break;
|
||||
case APPLY_EXP: break;
|
||||
|
||||
|
|
@ -446,6 +445,8 @@ void obj_to_char(struct obj_data *object, struct char_data *ch)
|
|||
RoomSave_mark_dirty_room(__rs_room);
|
||||
IS_CARRYING_W(ch) += GET_OBJ_WEIGHT(object);
|
||||
IS_CARRYING_N(ch)++;
|
||||
if (AFF_FLAGGED(ch, AFF_MOUNTED) && MOUNT(ch) && RIDDEN_BY(MOUNT(ch)) == ch)
|
||||
IS_CARRYING_W(MOUNT(ch)) += GET_OBJ_WEIGHT(object);
|
||||
|
||||
autoquest_trigger_check(ch, NULL, object, AQ_OBJ_FIND);
|
||||
|
||||
|
|
@ -487,6 +488,11 @@ void obj_from_char(struct obj_data *object)
|
|||
|
||||
IS_CARRYING_W(object->carried_by) -= GET_OBJ_WEIGHT(object);
|
||||
IS_CARRYING_N(object->carried_by)--;
|
||||
if (AFF_FLAGGED(object->carried_by, AFF_MOUNTED) &&
|
||||
MOUNT(object->carried_by) &&
|
||||
RIDDEN_BY(MOUNT(object->carried_by)) == object->carried_by)
|
||||
IS_CARRYING_W(MOUNT(object->carried_by)) =
|
||||
MAX(0, IS_CARRYING_W(MOUNT(object->carried_by)) - GET_OBJ_WEIGHT(object));
|
||||
object->carried_by = NULL;
|
||||
object->next_content = NULL;
|
||||
if (__rs_room != NOWHERE)
|
||||
|
|
@ -525,17 +531,6 @@ static int apply_ac(struct char_data *ch, int eq_pos)
|
|||
return (factor * GET_OBJ_VAL(GET_EQ(ch, eq_pos), 0));
|
||||
}
|
||||
|
||||
int invalid_align(struct char_data *ch, struct obj_data *obj)
|
||||
{
|
||||
if (OBJ_FLAGGED(obj, ITEM_ANTI_EVIL) && IS_EVIL(ch))
|
||||
return TRUE;
|
||||
if (OBJ_FLAGGED(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch))
|
||||
return TRUE;
|
||||
if (OBJ_FLAGGED(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void equip_char(struct char_data *ch, struct obj_data *obj, int pos)
|
||||
{
|
||||
int j;
|
||||
|
|
@ -558,7 +553,7 @@ void equip_char(struct char_data *ch, struct obj_data *obj, int pos)
|
|||
log("SYSERR: EQUIP: Obj is in_room when equip.");
|
||||
return;
|
||||
}
|
||||
if (invalid_align(ch, obj) || invalid_class(ch, obj)) {
|
||||
if (invalid_class(ch, obj)) {
|
||||
act("You are zapped by $p and instantly let go of it.", FALSE, ch, obj, 0, TO_CHAR);
|
||||
act("$n is zapped by $p and instantly lets go of it.", FALSE, ch, obj, 0, TO_ROOM);
|
||||
/* Changed to drop in inventory instead of the ground. */
|
||||
|
|
@ -569,6 +564,9 @@ void equip_char(struct char_data *ch, struct obj_data *obj, int pos)
|
|||
GET_EQ(ch, pos) = obj;
|
||||
obj->worn_by = ch;
|
||||
obj->worn_on = pos;
|
||||
IS_CARRYING_W(ch) += GET_OBJ_WEIGHT(obj);
|
||||
if (AFF_FLAGGED(ch, AFF_MOUNTED) && MOUNT(ch) && RIDDEN_BY(MOUNT(ch)) == ch)
|
||||
IS_CARRYING_W(MOUNT(ch)) += GET_OBJ_WEIGHT(obj);
|
||||
|
||||
if (GET_OBJ_TYPE(obj) == ITEM_ARMOR)
|
||||
GET_AC(ch) -= apply_ac(ch, pos);
|
||||
|
|
@ -601,6 +599,10 @@ struct obj_data *unequip_char(struct char_data *ch, int pos)
|
|||
obj = GET_EQ(ch, pos);
|
||||
obj->worn_by = NULL;
|
||||
obj->worn_on = -1;
|
||||
IS_CARRYING_W(ch) -= GET_OBJ_WEIGHT(obj);
|
||||
if (AFF_FLAGGED(ch, AFF_MOUNTED) && MOUNT(ch) && RIDDEN_BY(MOUNT(ch)) == ch)
|
||||
IS_CARRYING_W(MOUNT(ch)) =
|
||||
MAX(0, IS_CARRYING_W(MOUNT(ch)) - GET_OBJ_WEIGHT(obj));
|
||||
|
||||
if (GET_OBJ_TYPE(obj) == ITEM_ARMOR)
|
||||
GET_AC(ch) += apply_ac(ch, pos);
|
||||
|
|
@ -798,6 +800,8 @@ void obj_to_obj(struct obj_data *obj, struct obj_data *obj_to)
|
|||
GET_OBJ_WEIGHT(tmp_obj) += GET_OBJ_WEIGHT(obj);
|
||||
if (tmp_obj->carried_by)
|
||||
IS_CARRYING_W(tmp_obj->carried_by) += GET_OBJ_WEIGHT(obj);
|
||||
else if (tmp_obj->worn_by)
|
||||
IS_CARRYING_W(tmp_obj->worn_by) += GET_OBJ_WEIGHT(obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -831,6 +835,8 @@ void obj_from_obj(struct obj_data *obj)
|
|||
GET_OBJ_WEIGHT(temp) -= GET_OBJ_WEIGHT(obj);
|
||||
if (temp->carried_by)
|
||||
IS_CARRYING_W(temp->carried_by) -= GET_OBJ_WEIGHT(obj);
|
||||
else if (temp->worn_by)
|
||||
IS_CARRYING_W(temp->worn_by) -= GET_OBJ_WEIGHT(obj);
|
||||
}
|
||||
obj->in_obj = NULL;
|
||||
obj->next_content = NULL;
|
||||
|
|
@ -990,6 +996,13 @@ void extract_char_final(struct char_data *ch)
|
|||
STATE(d) = CON_CLOSE;
|
||||
}
|
||||
if (GET_POS(ch) == POS_DEAD) {
|
||||
int pfilepos = GET_PFILEPOS(ch);
|
||||
|
||||
if (pfilepos < 0)
|
||||
pfilepos = get_ptable_by_name(GET_NAME(ch));
|
||||
if (pfilepos >= 0)
|
||||
SET_BIT(player_table[pfilepos].flags, PINDEX_DELETED);
|
||||
|
||||
STATE(ch->desc) = CON_ACCOUNT_MENU;
|
||||
send_account_menu(ch->desc);
|
||||
ch->desc->character = NULL;
|
||||
|
|
@ -1001,6 +1014,25 @@ void extract_char_final(struct char_data *ch)
|
|||
}
|
||||
}
|
||||
|
||||
if (AFF_FLAGGED(ch, AFF_MOUNTED) || MOUNT(ch)) {
|
||||
struct char_data *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);
|
||||
}
|
||||
if (RIDDEN_BY(ch)) {
|
||||
struct char_data *rider = RIDDEN_BY(ch);
|
||||
if (rider && MOUNT(rider) == ch) {
|
||||
MOUNT(rider) = NULL;
|
||||
REMOVE_BIT_AR(AFF_FLAGS(rider), AFF_MOUNTED);
|
||||
}
|
||||
RIDDEN_BY(ch) = NULL;
|
||||
}
|
||||
|
||||
/* On with the character's assets... */
|
||||
if (ch->followers || ch->master)
|
||||
die_follower(ch);
|
||||
|
|
@ -1456,7 +1488,7 @@ int get_obj_pos_in_equip_vis(struct char_data *ch, char *arg, int *number, struc
|
|||
|
||||
static int money_weight(int amount)
|
||||
{
|
||||
const int coins_per_weight = 10;
|
||||
const int coins_per_weight = 30;
|
||||
|
||||
if (amount <= 0)
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ void obj_from_char(struct obj_data *object);
|
|||
|
||||
void equip_char(struct char_data *ch, struct obj_data *obj, int pos);
|
||||
struct obj_data *unequip_char(struct char_data *ch, int pos);
|
||||
int invalid_align(struct char_data *ch, struct obj_data *obj);
|
||||
|
||||
void obj_to_room(struct obj_data *object, room_rnum room);
|
||||
void obj_from_room(struct obj_data *object);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "act.h" /* ACMDs located within the act*.c files */
|
||||
#include "ban.h"
|
||||
#include "class.h"
|
||||
#include "species.h"
|
||||
#include "graph.h"
|
||||
#include "hedit.h"
|
||||
#include "house.h"
|
||||
|
|
@ -47,6 +48,11 @@ static int _parse_name(char *arg, char *name);
|
|||
static bool perform_new_char_dupe_check(struct descriptor_data *d);
|
||||
/* sort_commands utility */
|
||||
static int sort_commands_helper(const void *a, const void *b);
|
||||
static void show_species_menu(struct descriptor_data *d);
|
||||
static bool is_creation_state(int state);
|
||||
static void show_stat_pref_prompt(struct descriptor_data *d);
|
||||
static int ability_from_pref_arg(const char *arg);
|
||||
static bool parse_stat_preference(char *input, ubyte *order, ubyte *count);
|
||||
|
||||
/* globals defined here, used here and elsewhere */
|
||||
int *cmd_sort_info = NULL;
|
||||
|
|
@ -81,7 +87,7 @@ cpp_extern const struct command_info cmd_info[] = {
|
|||
{ "sw" , "sw" , POS_STANDING, do_move , 0, SCMD_SW },
|
||||
|
||||
/* now, the main list */
|
||||
{ "acaudit" , "acaudi" , POS_DEAD , do_acaudit , LVL_IMMORT, 0 },
|
||||
{ "audit" , "aud" , POS_DEAD , do_audit , LVL_IMMORT, 0 },
|
||||
{ "at" , "at" , POS_DEAD , do_at , LVL_IMMORT, 0 },
|
||||
{ "advance" , "adv" , POS_DEAD , do_advance , LVL_GRGOD, 0 },
|
||||
{ "aedit" , "aed" , POS_DEAD , do_oasis_aedit, LVL_GOD, 0 },
|
||||
|
|
@ -112,6 +118,7 @@ cpp_extern const struct command_info cmd_info[] = {
|
|||
|
||||
{ "cast" , "c" , POS_SITTING , do_cast , 1, 0 },
|
||||
{ "cedit" , "cedit" , POS_DEAD , do_oasis_cedit, LVL_IMPL, 0 },
|
||||
{ "change" , "chang" , POS_SLEEPING , do_change , 0, 0 },
|
||||
{ "changelog", "cha" , POS_DEAD , do_changelog, LVL_IMPL, 0 },
|
||||
{ "check" , "ch" , POS_STANDING, do_not_here , 1, 0 },
|
||||
{ "checkload", "checkl" , POS_DEAD , do_checkloadstatus, LVL_GOD, 0 },
|
||||
|
|
@ -130,6 +137,7 @@ cpp_extern const struct command_info cmd_info[] = {
|
|||
{ "detach" , "detach" , POS_DEAD , do_detach , LVL_BUILDER, 0 },
|
||||
{ "diagnose" , "diag" , POS_RESTING , do_diagnose , 0, 0 },
|
||||
{ "dig" , "dig" , POS_DEAD , do_dig , LVL_BUILDER, 0 },
|
||||
{ "dismount" , "dism" , POS_STANDING, do_dismount , 0, 0 },
|
||||
{ "display" , "disp" , POS_DEAD , do_display , 0, 0 },
|
||||
{ "drink" , "dri" , POS_RESTING , do_drink , 0, SCMD_DRINK },
|
||||
{ "drop" , "dro" , POS_RESTING , do_drop , 0, SCMD_DROP },
|
||||
|
|
@ -173,6 +181,7 @@ cpp_extern const struct command_info cmd_info[] = {
|
|||
{ "hold" , "hold" , POS_RESTING , do_grab , 1, 0 },
|
||||
{ "holylight", "holy" , POS_DEAD , do_gen_tog , LVL_IMMORT, SCMD_HOLYLIGHT },
|
||||
{ "house" , "house" , POS_RESTING , do_house , 0, 0 },
|
||||
{ "hitch" , "hitc" , POS_STANDING, do_hitch , 0, 0 },
|
||||
|
||||
{ "inventory", "i" , POS_DEAD , do_inventory, 0, 0 },
|
||||
{ "idea" , "ide" , POS_DEAD , do_ibt , 0, SCMD_IDEA },
|
||||
|
|
@ -191,6 +200,7 @@ cpp_extern const struct command_info cmd_info[] = {
|
|||
{ "last" , "last" , POS_DEAD , do_last , LVL_GOD, 0 },
|
||||
{ "leave" , "lea" , POS_STANDING, do_leave , 0, 0 },
|
||||
{ "list" , "lis" , POS_STANDING, do_not_here , 0, 0 },
|
||||
{ "mount" , "mou" , POS_STANDING, do_mount , 0, 0 },
|
||||
{ "listen" , "lisn" , POS_RESTING , do_listen , 0, 0 },
|
||||
{ "links" , "lin" , POS_STANDING, do_links , LVL_GOD, 0 },
|
||||
{ "lock" , "loc" , POS_SITTING , do_gen_door , 0, SCMD_LOCK },
|
||||
|
|
@ -202,6 +212,7 @@ cpp_extern const struct command_info cmd_info[] = {
|
|||
{ "medit" , "med" , POS_DEAD , do_oasis_medit, LVL_BUILDER, 0 },
|
||||
{ "mlist" , "mlist" , POS_DEAD , do_oasis_list, LVL_BUILDER, SCMD_OASIS_MLIST },
|
||||
{ "mcopy" , "mcopy" , POS_DEAD , do_oasis_copy, LVL_GOD, CON_MEDIT },
|
||||
{ "mcreate" , "mcreate" , POS_DEAD , do_mcreate , LVL_BUILDER, 0 },
|
||||
{ "msave" , "msav" , POS_DEAD , do_msave, LVL_BUILDER, 0 },
|
||||
{ "msgedit" , "msgedit" , POS_DEAD , do_msgedit, LVL_GOD, 0 },
|
||||
{ "mute" , "mute" , POS_DEAD , do_wizutil , LVL_GOD, SCMD_MUTE },
|
||||
|
|
@ -219,11 +230,14 @@ cpp_extern const struct command_info cmd_info[] = {
|
|||
{ "olc" , "olc" , POS_DEAD , do_show_save_list, LVL_BUILDER, 0 },
|
||||
{ "olist" , "olist" , POS_DEAD , do_oasis_list, LVL_BUILDER, SCMD_OASIS_OLIST },
|
||||
{ "oedit" , "oedit" , POS_DEAD , do_oasis_oedit, LVL_BUILDER, 0 },
|
||||
{ "ocreate" , "ocreate" , POS_DEAD , do_ocreate , LVL_BUILDER, 0 },
|
||||
{ "ooc" , "oo" , POS_RESTING , do_ooc , 0, 0 },
|
||||
{ "osave" , "osave" , POS_DEAD , do_osave , LVL_BUILDER, 0 },
|
||||
{ "oset" , "oset" , POS_DEAD , do_oset, LVL_BUILDER, 0 },
|
||||
{ "ocopy" , "ocopy" , POS_DEAD , do_oasis_copy, LVL_GOD, CON_OEDIT },
|
||||
|
||||
{ "put" , "p" , POS_RESTING , do_put , 0, 0 },
|
||||
{ "pack" , "pac" , POS_RESTING , do_pack , 0, 0 },
|
||||
{ "peace" , "pe" , POS_DEAD , do_peace , LVL_BUILDER, 0 },
|
||||
{ "pemote" , "pem" , POS_SLEEPING, do_pemote , 0, SCMD_PEMOTE },
|
||||
{ "phemote" , "phem" , POS_SLEEPING, do_phemote , 0, SCMD_PHEMOTE },
|
||||
|
|
@ -257,11 +271,13 @@ cpp_extern const struct command_info cmd_info[] = {
|
|||
{ "recent" , "recent" , POS_DEAD , do_recent , LVL_IMMORT, 0 },
|
||||
{ "remove" , "rem" , POS_RESTING , do_remove , 0, 0 },
|
||||
{ "report" , "repo" , POS_RESTING , do_report , 0, 0 },
|
||||
{ "reroll" , "rero" , POS_DEAD , do_wizutil , LVL_GRGOD, SCMD_REROLL },
|
||||
{ "reroll" , "rero" , POS_DEAD , do_reroll , 0, 0 },
|
||||
{ "rescue" , "resc" , POS_FIGHTING, do_rescue , 1, 0 },
|
||||
{ "restore" , "resto" , POS_DEAD , do_restore , LVL_GOD, 0 },
|
||||
{ "return" , "retu" , POS_DEAD , do_return , 0, 0 },
|
||||
{ "redit" , "redit" , POS_DEAD , do_oasis_redit, LVL_BUILDER, 0 },
|
||||
{ "rcreate" , "rcreate" , POS_DEAD , do_rcreate , LVL_BUILDER, 0 },
|
||||
{ "rset" , "rset" , POS_DEAD , do_rset , LVL_BUILDER, 0 },
|
||||
{ "rlist" , "rlist" , POS_DEAD , do_oasis_list, LVL_BUILDER, SCMD_OASIS_RLIST },
|
||||
{ "rcopy" , "rcopy" , POS_DEAD , do_oasis_copy, LVL_GOD, CON_REDIT },
|
||||
{ "roomflags", "roomflags", POS_DEAD , do_gen_tog , LVL_IMMORT, SCMD_SHOWVNUMS },
|
||||
|
|
@ -320,7 +336,9 @@ cpp_extern const struct command_info cmd_info[] = {
|
|||
{ "unlock" , "unlock" , POS_SITTING , do_gen_door , 0, SCMD_UNLOCK },
|
||||
{ "unban" , "unban" , POS_DEAD , do_unban , LVL_GRGOD, 0 },
|
||||
{ "unaffect" , "unaffect", POS_DEAD , do_wizutil , LVL_GOD, SCMD_UNAFFECT },
|
||||
{ "unhitch" , "unh" , POS_STANDING, do_unhitch , 0, 0 },
|
||||
{ "unfollow" , "unf" , POS_RESTING , do_unfollow , 0, 0 },
|
||||
{ "unpack" , "unpa" , POS_RESTING , do_unpack , 0, 0 },
|
||||
{ "uptime" , "uptime" , POS_DEAD , do_date , LVL_GOD, SCMD_UPTIME },
|
||||
{ "use" , "use" , POS_SITTING , do_use , 1, SCMD_USE },
|
||||
{ "users" , "users" , POS_DEAD , do_users , LVL_GOD, 0 },
|
||||
|
|
@ -477,8 +495,6 @@ void command_interpreter(struct char_data *ch, char *argument)
|
|||
char *line;
|
||||
char arg[MAX_INPUT_LENGTH];
|
||||
|
||||
REMOVE_BIT_AR(AFF_FLAGS(ch), AFF_HIDE);
|
||||
|
||||
/* just drop to next line for hitting CR */
|
||||
skip_spaces(&argument);
|
||||
if (!*argument)
|
||||
|
|
@ -494,6 +510,9 @@ void command_interpreter(struct char_data *ch, char *argument)
|
|||
} else
|
||||
line = any_one_arg(argument, arg);
|
||||
|
||||
if (!is_abbrev(arg, "change"))
|
||||
REMOVE_BIT_AR(AFF_FLAGS(ch), AFF_HIDE);
|
||||
|
||||
/* Since all command triggers check for valid_dg_target before acting, the levelcheck
|
||||
* here has been removed. Otherwise, find the command. */
|
||||
{
|
||||
|
|
@ -1268,7 +1287,7 @@ static bool perform_new_char_dupe_check(struct descriptor_data *d)
|
|||
/* Do the player names match? */
|
||||
if (!strcmp(GET_NAME(k->character), GET_NAME(d->character))) {
|
||||
/* Check the other character is still in creation? */
|
||||
if ((STATE(k) > CON_PLAYING) && (STATE(k) < CON_QCLASS)) {
|
||||
if (is_creation_state(STATE(k))) {
|
||||
/* Boot the older one */
|
||||
k->character->desc = NULL;
|
||||
k->character = NULL;
|
||||
|
|
@ -1303,6 +1322,125 @@ static bool perform_new_char_dupe_check(struct descriptor_data *d)
|
|||
return (found);
|
||||
}
|
||||
|
||||
static void show_species_menu(struct descriptor_data *d)
|
||||
{
|
||||
int count = pc_species_count();
|
||||
|
||||
write_to_output(d, "Select a species:\r\n");
|
||||
for (int i = 0; i < count; i++) {
|
||||
int species = pc_species_list[i];
|
||||
write_to_output(d, " %2d) %s\r\n", i + 1, species_types[species]);
|
||||
}
|
||||
write_to_output(d, "Species: ");
|
||||
}
|
||||
|
||||
static void show_age_prompt(struct descriptor_data *d)
|
||||
{
|
||||
write_to_output(d, "Age (%d-%d): ", MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
}
|
||||
|
||||
static bool is_creation_state(int state)
|
||||
{
|
||||
switch (state) {
|
||||
case CON_GET_NAME:
|
||||
case CON_NAME_CNFRM:
|
||||
case CON_PASSWORD:
|
||||
case CON_NEWPASSWD:
|
||||
case CON_CNFPASSWD:
|
||||
case CON_QSEX:
|
||||
case CON_QSPECIES:
|
||||
case CON_QCLASS:
|
||||
case CON_QAGE:
|
||||
case CON_QSTAT_PREF:
|
||||
case CON_QSHORTDESC:
|
||||
case CON_PLR_DESC:
|
||||
case CON_PLR_BACKGROUND:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void show_stat_pref_prompt(struct descriptor_data *d)
|
||||
{
|
||||
write_to_output(d,
|
||||
"\r\nEnter your stat preference, with the first stat being your preferred highest,\r\n"
|
||||
"followed by the others in descending order.\r\n"
|
||||
"If you list fewer than six, those listed get the highest rolls; the rest are FIFO.\r\n"
|
||||
"Example: strength dexterity constitution intelligence wisdom charisma\r\n"
|
||||
" or: str dex con int wis cha\r\n"
|
||||
"Press Enter to skip (first-in, first-out).\r\n"
|
||||
"Stat preference: ");
|
||||
}
|
||||
|
||||
static int ability_from_pref_arg(const char *arg)
|
||||
{
|
||||
if (!arg || !*arg)
|
||||
return -1;
|
||||
if (!str_cmp(arg, "str") || is_abbrev(arg, "strength"))
|
||||
return ABIL_STR;
|
||||
if (!str_cmp(arg, "dex") || is_abbrev(arg, "dexterity"))
|
||||
return ABIL_DEX;
|
||||
if (!str_cmp(arg, "con") || is_abbrev(arg, "constitution"))
|
||||
return ABIL_CON;
|
||||
if (!str_cmp(arg, "int") || is_abbrev(arg, "intelligence"))
|
||||
return ABIL_INT;
|
||||
if (!str_cmp(arg, "wis") || is_abbrev(arg, "wisdom"))
|
||||
return ABIL_WIS;
|
||||
if (!str_cmp(arg, "cha") || is_abbrev(arg, "charisma"))
|
||||
return ABIL_CHA;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool parse_stat_preference(char *input, ubyte *order, ubyte *count)
|
||||
{
|
||||
char arg[MAX_INPUT_LENGTH];
|
||||
bool seen[NUM_ABILITIES] = { FALSE };
|
||||
|
||||
if (!order || !count)
|
||||
return FALSE;
|
||||
|
||||
*count = 0;
|
||||
skip_spaces(&input);
|
||||
if (!*input)
|
||||
return TRUE;
|
||||
|
||||
if (!str_cmp(input, "none") || !str_cmp(input, "no") || !str_cmp(input, "skip"))
|
||||
return TRUE;
|
||||
|
||||
while (*input) {
|
||||
size_t len;
|
||||
int ability;
|
||||
|
||||
input = one_argument(input, arg);
|
||||
if (!*arg)
|
||||
break;
|
||||
|
||||
len = strlen(arg);
|
||||
while (len > 0 && (arg[len - 1] == ',' || arg[len - 1] == '.')) {
|
||||
arg[len - 1] = '\0';
|
||||
len--;
|
||||
}
|
||||
|
||||
if (!*arg)
|
||||
continue;
|
||||
|
||||
ability = ability_from_pref_arg(arg);
|
||||
if (ability < 0 || ability >= NUM_ABILITIES)
|
||||
return FALSE;
|
||||
if (seen[ability])
|
||||
return FALSE;
|
||||
if (*count >= NUM_ABILITIES)
|
||||
return FALSE;
|
||||
|
||||
order[*count] = (ubyte)ability;
|
||||
(*count)++;
|
||||
seen[ability] = TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* load the player, put them in the right room - used by copyover_recover too */
|
||||
int enter_player_game (struct descriptor_data *d)
|
||||
{
|
||||
|
|
@ -1869,10 +2007,26 @@ void nanny(struct descriptor_data *d, char *arg)
|
|||
return;
|
||||
}
|
||||
|
||||
write_to_output(d, "%s\r\nClass: ", class_menu);
|
||||
STATE(d) = CON_QCLASS;
|
||||
show_species_menu(d);
|
||||
STATE(d) = CON_QSPECIES;
|
||||
break;
|
||||
|
||||
case CON_QSPECIES: {
|
||||
int choice = atoi(arg);
|
||||
int species = species_from_pc_choice(choice);
|
||||
|
||||
if (species == SPECIES_UNDEFINED) {
|
||||
write_to_output(d, "\r\nThat's not a species.\r\n");
|
||||
show_species_menu(d);
|
||||
return;
|
||||
}
|
||||
|
||||
GET_SPECIES(d->character) = species;
|
||||
write_to_output(d, "%s\r\nClass: ", class_menu);
|
||||
STATE(d) = CON_QCLASS;
|
||||
break;
|
||||
}
|
||||
|
||||
case CON_QCLASS:
|
||||
load_result = parse_class(*arg);
|
||||
if (load_result == CLASS_UNDEFINED) {
|
||||
|
|
@ -1882,6 +2036,51 @@ case CON_QCLASS:
|
|||
GET_CLASS(d->character) = load_result;
|
||||
}
|
||||
|
||||
show_age_prompt(d);
|
||||
STATE(d) = CON_QAGE;
|
||||
return;
|
||||
|
||||
case CON_QAGE: {
|
||||
if (!is_number(arg)) {
|
||||
write_to_output(d, "\r\nPlease enter a number between %d and %d.\r\n",
|
||||
MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
show_age_prompt(d);
|
||||
return;
|
||||
}
|
||||
|
||||
int age_years = atoi(arg);
|
||||
if (age_years < MIN_CHAR_AGE || age_years > MAX_CHAR_AGE) {
|
||||
write_to_output(d, "\r\nAge must be between %d and %d.\r\n",
|
||||
MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
show_age_prompt(d);
|
||||
return;
|
||||
}
|
||||
|
||||
GET_ROLEPLAY_AGE(d->character) = age_years;
|
||||
GET_ROLEPLAY_AGE_YEAR(d->character) = time_info.year;
|
||||
|
||||
show_stat_pref_prompt(d);
|
||||
STATE(d) = CON_QSTAT_PREF;
|
||||
return;
|
||||
}
|
||||
|
||||
case CON_QSTAT_PREF: {
|
||||
ubyte order[NUM_ABILITIES];
|
||||
ubyte count = 0;
|
||||
|
||||
if (!parse_stat_preference(arg, order, &count)) {
|
||||
write_to_output(d,
|
||||
"\r\nInvalid stat list. Please enter a valid order, or press Enter to skip.\r\n");
|
||||
show_stat_pref_prompt(d);
|
||||
return;
|
||||
}
|
||||
|
||||
d->character->stat_pref_use = TRUE;
|
||||
d->character->stat_pref_count = count;
|
||||
for (int i = 0; i < NUM_ABILITIES; i++) {
|
||||
d->character->stat_pref_order[i] = (i < count) ? order[i] : 0;
|
||||
}
|
||||
|
||||
/* Create player entry and initialize character now so file exists */
|
||||
if (d->olc) {
|
||||
free(d->olc);
|
||||
|
|
@ -1928,6 +2127,7 @@ case CON_QCLASS:
|
|||
|
||||
STATE(d) = CON_QSHORTDESC;
|
||||
return;
|
||||
}
|
||||
|
||||
case CON_QSHORTDESC: {
|
||||
skip_spaces(&arg);
|
||||
|
|
|
|||
22
src/limits.c
22
src/limits.c
|
|
@ -23,7 +23,7 @@
|
|||
#include "fight.h"
|
||||
#include "screen.h"
|
||||
#include "mud_event.h"
|
||||
#include "roomsave.h"
|
||||
#include "set.h"
|
||||
#include <time.h>
|
||||
|
||||
/* local file scope function prototypes */
|
||||
|
|
@ -142,7 +142,7 @@ int hit_gain(struct char_data *ch)
|
|||
return (gain);
|
||||
}
|
||||
|
||||
/* move gain pr. game hour */
|
||||
/* stamina gain pr. game hour */
|
||||
int move_gain(struct char_data *ch)
|
||||
{
|
||||
int gain;
|
||||
|
|
@ -209,12 +209,13 @@ void run_autowiz(void)
|
|||
/* Requires: find_skill_num(), GET_WIS(), wis_app[], GET_SKILL(), SET_SKILL(), rand_number()
|
||||
* Cooldown: 1 hour - 5 * WIS bonus minutes (floored at 0)
|
||||
* Rolls: failure -> 1..20, success -> 1..100
|
||||
* Cap: 90% (change MIN(90, ...) if you want a different cap)
|
||||
* Cap: per-class max (see class.c)
|
||||
*/
|
||||
void gain_skill(struct char_data *ch, char *skill, bool success)
|
||||
{
|
||||
int skill_num, base, roll, increase;
|
||||
int wisb, cd_seconds;
|
||||
int cap;
|
||||
time_t now;
|
||||
|
||||
if (IS_NPC(ch))
|
||||
|
|
@ -233,8 +234,11 @@ void gain_skill(struct char_data *ch, char *skill, bool success)
|
|||
}
|
||||
|
||||
base = GET_SKILL(ch, skill_num);
|
||||
cap = class_skill_max(GET_CLASS(ch), skill_num);
|
||||
if (cap <= 0)
|
||||
return;
|
||||
/* If already capped, bail early (and don’t start cooldown) */
|
||||
if (base >= 90)
|
||||
if (base >= cap)
|
||||
return;
|
||||
|
||||
/* Wisdom bonus from wis_app[] (constants.c). Higher = better learning & shorter cooldown. */
|
||||
|
|
@ -246,7 +250,7 @@ void gain_skill(struct char_data *ch, char *skill, bool success)
|
|||
/* Old 1..400 with (400 - wisb*4) ⇒ scaled: (100 - wisb) */
|
||||
if (roll >= (100 - wisb)) {
|
||||
increase = base + 1;
|
||||
SET_SKILL(ch, skill_num, MIN(90, increase));
|
||||
SET_SKILL(ch, skill_num, MIN(cap, increase));
|
||||
|
||||
/* Cooldown only when an increase actually happens */
|
||||
cd_seconds = 3600 - (wisb * 5 * 60); /* 1 hour - 5 * WIS minutes */
|
||||
|
|
@ -259,7 +263,7 @@ void gain_skill(struct char_data *ch, char *skill, bool success)
|
|||
/* Old 1..100 with (100 - wisb) ⇒ scaled: (20 - wisb) */
|
||||
if (roll >= (20 - wisb)) {
|
||||
increase = base + 1;
|
||||
SET_SKILL(ch, skill_num, MIN(90, increase));
|
||||
SET_SKILL(ch, skill_num, MIN(cap, increase));
|
||||
|
||||
/* Cooldown only when an increase actually happens */
|
||||
cd_seconds = 3600 - (wisb * 5 * 60); /* 1 hour - 5 * WIS minutes */
|
||||
|
|
@ -413,7 +417,7 @@ void point_update(void)
|
|||
if (GET_POS(i) >= POS_STUNNED) {
|
||||
GET_HIT(i) = MIN(GET_HIT(i) + hit_gain(i), GET_MAX_HIT(i));
|
||||
GET_MANA(i) = MIN(GET_MANA(i) + mana_gain(i), GET_MAX_MANA(i));
|
||||
GET_MOVE(i) = MIN(GET_MOVE(i) + move_gain(i), GET_MAX_MOVE(i));
|
||||
GET_STAMINA(i) = MIN(GET_STAMINA(i) + move_gain(i), GET_MAX_STAMINA(i));
|
||||
if (AFF_FLAGGED(i, AFF_POISON))
|
||||
if (damage(i, i, 2, SPELL_POISON) == -1)
|
||||
continue; /* Oops, they died. -gg 6/24/98 */
|
||||
|
|
@ -480,8 +484,8 @@ void point_update(void)
|
|||
}
|
||||
|
||||
/* ---- Room SAVE autosave (every 10 minutes; adjust the 600 as desired) ----
|
||||
* Requires: #include "roomsave.h" at the top of this file.
|
||||
* Saves all rooms flagged ROOM_SAVE via roomsave.c.
|
||||
* Requires: #include "set.h" at the top of this file.
|
||||
* Saves all rooms flagged ROOM_SAVE via set.c.
|
||||
*/
|
||||
if (++roomsave_pulse >= (PASSES_PER_SEC * 600)) {
|
||||
roomsave_pulse = 0;
|
||||
|
|
|
|||
51
src/magic.c
51
src/magic.c
|
|
@ -189,6 +189,7 @@ int mag_damage(int level, struct char_data *ch, struct char_data *victim,
|
|||
int spellnum, int savetype)
|
||||
{
|
||||
int dam = 0;
|
||||
int save_dc;
|
||||
|
||||
if (victim == NULL || ch == NULL)
|
||||
return (0);
|
||||
|
|
@ -234,28 +235,6 @@ int mag_damage(int level, struct char_data *ch, struct char_data *victim,
|
|||
break;
|
||||
|
||||
/* Mostly clerics */
|
||||
case SPELL_DISPEL_EVIL:
|
||||
dam = dice(6, 8) + 6;
|
||||
if (IS_EVIL(ch)) {
|
||||
victim = ch;
|
||||
dam = GET_HIT(ch) - 1;
|
||||
} else if (IS_GOOD(victim)) {
|
||||
act("The gods protect $N.", FALSE, ch, 0, victim, TO_CHAR);
|
||||
return (0);
|
||||
}
|
||||
break;
|
||||
case SPELL_DISPEL_GOOD:
|
||||
dam = dice(6, 8) + 6;
|
||||
if (IS_GOOD(ch)) {
|
||||
victim = ch;
|
||||
dam = GET_HIT(ch) - 1;
|
||||
} else if (IS_EVIL(victim)) {
|
||||
act("The gods protect $N.", FALSE, ch, 0, victim, TO_CHAR);
|
||||
return (0);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case SPELL_CALL_LIGHTNING:
|
||||
dam = dice(7, 8) + 7;
|
||||
break;
|
||||
|
|
@ -279,8 +258,12 @@ int mag_damage(int level, struct char_data *ch, struct char_data *victim,
|
|||
} /* switch(spellnum) */
|
||||
|
||||
|
||||
save_dc = compute_save_dc(ch, level, spellnum);
|
||||
if (!IS_NPC(ch) && GET_REAL_LEVEL(ch) >= LVL_IMMORT)
|
||||
save_dc = 1000;
|
||||
|
||||
/* divide damage by two if victim makes his saving throw */
|
||||
if (mag_savingthrow(victim, savetype, compute_save_dc(ch, level, spellnum)))
|
||||
if (mag_savingthrow(victim, savetype, save_dc))
|
||||
dam /= 2;
|
||||
|
||||
/* and finally, inflict the damage */
|
||||
|
|
@ -307,6 +290,8 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim,
|
|||
return;
|
||||
|
||||
save_dc = compute_save_dc(ch, level, spellnum);
|
||||
if (!IS_NPC(ch) && GET_REAL_LEVEL(ch) >= LVL_IMMORT)
|
||||
save_dc = 1000;
|
||||
|
||||
for (i = 0; i < MAX_SPELL_AFFECTS; i++) {
|
||||
new_affect(&(af[i]));
|
||||
|
|
@ -391,13 +376,6 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim,
|
|||
to_vict = "You feel very uncomfortable.";
|
||||
break;
|
||||
|
||||
case SPELL_DETECT_ALIGN:
|
||||
af[0].duration = 12 + level;
|
||||
SET_BIT_AR(af[0].bitvector, AFF_DETECT_ALIGN);
|
||||
accum_duration = TRUE;
|
||||
to_vict = "Your eyes tingle.";
|
||||
break;
|
||||
|
||||
case SPELL_DETECT_INVIS:
|
||||
af[0].duration = 12 + level;
|
||||
SET_BIT_AR(af[0].bitvector, AFF_DETECT_INVIS);
|
||||
|
|
@ -454,13 +432,6 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim,
|
|||
to_room = "$n gets violently ill!";
|
||||
break;
|
||||
|
||||
case SPELL_PROT_FROM_EVIL:
|
||||
af[0].duration = 24;
|
||||
SET_BIT_AR(af[0].bitvector, AFF_PROTECT_EVIL);
|
||||
accum_duration = TRUE;
|
||||
to_vict = "You feel invulnerable!";
|
||||
break;
|
||||
|
||||
case SPELL_SANCTUARY:
|
||||
af[0].duration = 4;
|
||||
SET_BIT_AR(af[0].bitvector, AFF_SANCTUARY);
|
||||
|
|
@ -470,8 +441,6 @@ void mag_affects(int level, struct char_data *ch, struct char_data *victim,
|
|||
break;
|
||||
|
||||
case SPELL_SLEEP:
|
||||
if (!CONFIG_PK_ALLOWED && !IS_NPC(ch) && !IS_NPC(victim))
|
||||
return;
|
||||
if (MOB_FLAGGED(victim, MOB_NOSLEEP))
|
||||
return;
|
||||
if (mag_savingthrow(victim, ABIL_WIS, save_dc))
|
||||
|
|
@ -645,8 +614,6 @@ void mag_areas(int level, struct char_data *ch, int spellnum, int savetype)
|
|||
continue;
|
||||
if (!IS_NPC(tch) && GET_LEVEL(tch) >= LVL_IMMORT)
|
||||
continue;
|
||||
if (!CONFIG_PK_ALLOWED && !IS_NPC(ch) && !IS_NPC(tch))
|
||||
continue;
|
||||
if (!IS_NPC(ch) && IS_NPC(tch) && AFF_FLAGGED(tch, AFF_CHARM))
|
||||
continue;
|
||||
if (!IS_NPC(tch) && spell_info[spellnum].violent && GROUP(tch) && GROUP(ch) && GROUP(ch) == GROUP(tch))
|
||||
|
|
@ -816,7 +783,7 @@ void mag_points(int level, struct char_data *ch, struct char_data *victim,
|
|||
break;
|
||||
}
|
||||
GET_HIT(victim) = MIN(GET_MAX_HIT(victim), GET_HIT(victim) + healing);
|
||||
GET_MOVE(victim) = MIN(GET_MAX_MOVE(victim), GET_MOVE(victim) + move);
|
||||
GET_STAMINA(victim) = MIN(GET_MAX_STAMINA(victim), GET_STAMINA(victim) + move);
|
||||
update_pos(victim);
|
||||
}
|
||||
|
||||
|
|
|
|||
227
src/medit.c
227
src/medit.c
|
|
@ -13,6 +13,7 @@
|
|||
#include "comm.h"
|
||||
#include "spells.h"
|
||||
#include "class.h"
|
||||
#include "species.h"
|
||||
#include "db.h"
|
||||
#include "shop.h"
|
||||
#include "genolc.h"
|
||||
|
|
@ -30,7 +31,7 @@
|
|||
|
||||
/* local functions */
|
||||
static void medit_setup_new(struct descriptor_data *d);
|
||||
static void init_mobile(struct char_data *mob);
|
||||
void init_mobile(struct char_data *mob);
|
||||
static void medit_save_to_disk(zone_vnum zone_num);
|
||||
static void medit_disp_positions(struct descriptor_data *d);
|
||||
static void medit_disp_sex(struct descriptor_data *d);
|
||||
|
|
@ -41,6 +42,9 @@ static void medit_disp_mob_flags(struct descriptor_data *d);
|
|||
static void medit_disp_aff_flags(struct descriptor_data *d);
|
||||
static void medit_disp_menu(struct descriptor_data *d);
|
||||
static void medit_disp_class_menu(struct descriptor_data *d);
|
||||
static void medit_disp_species_menu(struct descriptor_data *d);
|
||||
static int roll_stat_for_cap(int cap);
|
||||
static int autoroll_species_stat(struct char_data *mob, int ability);
|
||||
|
||||
/* utility functions */
|
||||
ACMD(do_oasis_medit)
|
||||
|
|
@ -228,15 +232,18 @@ void medit_setup_existing(struct descriptor_data *d, int rmob_num)
|
|||
}
|
||||
|
||||
/* Ideally, this function should be in db.c, but I'll put it here for portability. */
|
||||
static void init_mobile(struct char_data *mob)
|
||||
void init_mobile(struct char_data *mob)
|
||||
{
|
||||
int i;
|
||||
clear_char(mob);
|
||||
|
||||
GET_HIT(mob) = GET_MANA(mob) = 1;
|
||||
GET_MAX_MANA(mob) = GET_MAX_MOVE(mob) = 100;
|
||||
GET_MAX_MANA(mob) = GET_MAX_STAMINA(mob) = 100;
|
||||
GET_WEIGHT(mob) = 200;
|
||||
GET_HEIGHT(mob) = 198;
|
||||
mob->player.time.birth = time(0);
|
||||
mob->player.roleplay_age = MIN_CHAR_AGE;
|
||||
mob->player.roleplay_age_year = time_info.year;
|
||||
|
||||
/* Only assign defaults if the individual stat is unset (zero) */
|
||||
if (!mob->real_abils.str) mob->real_abils.str = 11;
|
||||
|
|
@ -419,19 +426,20 @@ static void medit_disp_menu(struct descriptor_data *d)
|
|||
{
|
||||
struct char_data *mob;
|
||||
char flags[MAX_STRING_LENGTH], flag2[MAX_STRING_LENGTH];
|
||||
const char *background, *classname;
|
||||
const char *classname, *speciesname;
|
||||
|
||||
mob = OLC_MOB(d);
|
||||
get_char_colors(d->character);
|
||||
clear_screen(d);
|
||||
background = GET_BACKGROUND(mob) ? GET_BACKGROUND(mob) : "<None>\r\n";
|
||||
classname = HAS_VALID_CLASS(mob) ? pc_class_types[GET_CLASS(mob)] : "Unassigned";
|
||||
speciesname = HAS_VALID_SPECIES(mob) ? species_types[GET_SPECIES(mob)] : "Unassigned";
|
||||
|
||||
write_to_output(d,
|
||||
"-- Mob Number: [%s%d%s]\r\n"
|
||||
"%s1%s) Name: %s%s\r\n"
|
||||
"%s2%s) Keywords: %s%s\r\n"
|
||||
"%s3%s) Sex: %s%-7.7s%s\r\n"
|
||||
"%sG%s) Age: %s%d%s\r\n"
|
||||
"%s4%s) S-Desc: %s%s\r\n"
|
||||
"%s5%s) L-Desc:-\r\n%s%s\r\n"
|
||||
"%s6%s) D-Desc:-\r\n%s%s\r\n",
|
||||
|
|
@ -440,6 +448,7 @@ static void medit_disp_menu(struct descriptor_data *d)
|
|||
grn, nrm, yel, GET_NAME(mob),
|
||||
grn, nrm, yel, GET_KEYWORDS(mob),
|
||||
grn, nrm, yel, genders[(int)GET_SEX(mob)], nrm,
|
||||
grn, nrm, yel, GET_ROLEPLAY_AGE(mob), nrm,
|
||||
grn, nrm, yel, GET_SDESC(mob),
|
||||
grn, nrm, yel, GET_LDESC(mob),
|
||||
grn, nrm, yel, GET_DDESC(mob)
|
||||
|
|
@ -452,12 +461,13 @@ static void medit_disp_menu(struct descriptor_data *d)
|
|||
"%s8%s) Default : %s%s\r\n"
|
||||
"%s9%s) Attack : %s%s\r\n"
|
||||
"%sD%s) Class : %s%s\r\n"
|
||||
"%sE%s) Species : %s%s\r\n"
|
||||
"%sK%s) Skinning Menu...\r\n"
|
||||
"%s0%s) Stats Menu...\r\n"
|
||||
"%s-%s) Skills Menu...\r\n"
|
||||
"%sA%s) NPC Flags : %s%s\r\n"
|
||||
"%sB%s) AFF Flags : %s%s\r\n"
|
||||
"%sC%s) Background:-\r\n%s%s\r\n"
|
||||
"%sC%s) Background...\r\n"
|
||||
"%sS%s) Script : %s%s\r\n"
|
||||
"%sW%s) Copy mob\r\n"
|
||||
"%sX%s) Delete mob\r\n"
|
||||
|
|
@ -468,12 +478,13 @@ static void medit_disp_menu(struct descriptor_data *d)
|
|||
grn, nrm, yel, position_types[(int)GET_DEFAULT_POS(mob)],
|
||||
grn, nrm, yel, attack_hit_text[(int)GET_ATTACK(mob)].singular,
|
||||
grn, nrm, yel, classname,
|
||||
grn, nrm, yel, speciesname,
|
||||
grn, nrm,
|
||||
grn, nrm,
|
||||
grn, nrm,
|
||||
grn, nrm, cyn, flags,
|
||||
grn, nrm, cyn, flag2,
|
||||
grn, nrm, yel, background,
|
||||
grn, nrm,
|
||||
grn, nrm, cyn, OLC_SCRIPT(d) ?"Set.":"Not Set.",
|
||||
grn, nrm,
|
||||
grn, nrm,
|
||||
|
|
@ -523,6 +534,46 @@ static void medit_disp_class_menu(struct descriptor_data *d)
|
|||
OLC_MODE(d) = MEDIT_CLASS_MENU;
|
||||
}
|
||||
|
||||
static void medit_disp_species_menu(struct descriptor_data *d)
|
||||
{
|
||||
struct char_data *mob = OLC_MOB(d);
|
||||
const char *current = HAS_VALID_SPECIES(mob) ? species_types[GET_SPECIES(mob)] : "Unassigned";
|
||||
|
||||
get_char_colors(d->character);
|
||||
clear_screen(d);
|
||||
|
||||
write_to_output(d,
|
||||
"-- Mob Number: %s[%s%d%s]%s\r\n"
|
||||
"Species selection for %s%s%s\r\n\r\n",
|
||||
cyn, yel, OLC_NUM(d), cyn, nrm,
|
||||
yel, GET_SDESC(mob), nrm);
|
||||
|
||||
for (int i = 0; i < NUM_SPECIES; i++) {
|
||||
bool selected = HAS_VALID_SPECIES(mob) && (GET_SPECIES(mob) == i);
|
||||
write_to_output(d, "%s%2d%s) %s%-12s%s%s\r\n",
|
||||
cyn, i + 1, nrm,
|
||||
selected ? grn : yel,
|
||||
species_types[i],
|
||||
nrm,
|
||||
selected ? " (current)" : "");
|
||||
}
|
||||
|
||||
write_to_output(d, "%s%2d%s) %sUnassigned%s%s\r\n",
|
||||
cyn, NUM_SPECIES + 1, nrm,
|
||||
!HAS_VALID_SPECIES(mob) ? grn : yel,
|
||||
nrm,
|
||||
!HAS_VALID_SPECIES(mob) ? " (current)" : "");
|
||||
|
||||
write_to_output(d,
|
||||
"\r\nCurrent choice: %s%s%s\r\n"
|
||||
"%s0%s) Return to main menu\r\n"
|
||||
"Enter choice : ",
|
||||
cyn, current, nrm,
|
||||
cyn, nrm);
|
||||
|
||||
OLC_MODE(d) = MEDIT_SPECIES_MENU;
|
||||
}
|
||||
|
||||
/* Display main menu. */
|
||||
static void medit_disp_stats_menu(struct descriptor_data *d)
|
||||
{
|
||||
|
|
@ -534,32 +585,28 @@ static void medit_disp_stats_menu(struct descriptor_data *d)
|
|||
clear_screen(d);
|
||||
|
||||
/* Color codes have to be used here, for count_color_codes to work */
|
||||
sprintf(buf, "(range \ty%d\tn to \ty%d\tn)", GET_HIT(mob) + GET_MOVE(mob),
|
||||
(GET_HIT(mob) * GET_MANA(mob)) + GET_MOVE(mob));
|
||||
sprintf(buf, "(range \ty%d\tn to \ty%d\tn)", GET_HIT(mob) + GET_STAMINA(mob),
|
||||
(GET_HIT(mob) * GET_MANA(mob)) + GET_STAMINA(mob));
|
||||
|
||||
/* Top section - standard stats */
|
||||
write_to_output(d,
|
||||
"-- Mob Number: %s[%s%d%s]%s\r\n"
|
||||
"(%s1%s) Level: %s[%s%4d%s]%s\r\n"
|
||||
"(%s2%s) %sAuto Set Stats (based on level)%s\r\n\r\n"
|
||||
"(%s1%s) %sAuto Set Stats (species range)%s\r\n\r\n"
|
||||
"Hit Points (xdy+z):\r\n"
|
||||
"(%s3%s) HP NumDice: %s[%s%5d%s]%s\r\n"
|
||||
"(%s4%s) HP SizeDice: %s[%s%5d%s]%s\r\n"
|
||||
"(%s5%s) HP Addition: %s[%s%5d%s]%s\r\n"
|
||||
"(%s8%s) Alignment: %s[%s%5d%s]%s\r\n\r\n",
|
||||
"(%s2%s) HP NumDice: %s[%s%5d%s]%s\r\n"
|
||||
"(%s3%s) HP SizeDice: %s[%s%5d%s]%s\r\n"
|
||||
"(%s4%s) HP Addition: %s[%s%5d%s]%s\r\n\r\n",
|
||||
cyn, yel, OLC_NUM(d), cyn, nrm,
|
||||
cyn, nrm, cyn, yel, GET_LEVEL(mob), cyn, nrm,
|
||||
cyn, nrm, cyn, nrm,
|
||||
cyn, nrm, cyn, yel, GET_HIT(mob), cyn, nrm,
|
||||
cyn, nrm, cyn, yel, GET_MANA(mob), cyn, nrm,
|
||||
cyn, nrm, cyn, yel, GET_MOVE(mob), cyn, nrm,
|
||||
cyn, nrm, cyn, yel, GET_ALIGNMENT(mob), cyn, nrm
|
||||
cyn, nrm, cyn, yel, GET_STAMINA(mob), cyn, nrm
|
||||
);
|
||||
|
||||
if (CONFIG_MEDIT_ADVANCED) {
|
||||
/* Bottom section - non-standard stats, togglable in cedit */
|
||||
write_to_output(d,
|
||||
"%sAttributes Saving Throws\r\n"
|
||||
"%sAttributes Saving Throw bonus\r\n"
|
||||
"(%sF%s) Str: %s[%s%3d%s]%s (%sR%s) Save STR %s[%s%3d%s]%s\r\n"
|
||||
"(%sG%s) Dex: %s[%s%3d%s]%s (%sS%s) Save DEX %s[%s%3d%s]%s\r\n"
|
||||
"(%sH%s) Con: %s[%s%3d%s]%s (%sT%s) Save CON %s[%s%3d%s]%s\r\n"
|
||||
|
|
@ -722,6 +769,11 @@ void medit_parse(struct descriptor_data *d, char *arg)
|
|||
OLC_MODE(d) = MEDIT_SEX;
|
||||
medit_disp_sex(d);
|
||||
return;
|
||||
case 'g':
|
||||
case 'G':
|
||||
OLC_MODE(d) = MEDIT_AGE;
|
||||
write_to_output(d, "Enter age (%d-%d): ", MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
return;
|
||||
case '4':
|
||||
OLC_MODE(d) = MEDIT_S_DESC;
|
||||
i--;
|
||||
|
|
@ -757,6 +809,10 @@ void medit_parse(struct descriptor_data *d, char *arg)
|
|||
case 'D':
|
||||
medit_disp_class_menu(d);
|
||||
return;
|
||||
case 'e':
|
||||
case 'E':
|
||||
medit_disp_species_menu(d);
|
||||
return;
|
||||
case '0':
|
||||
OLC_MODE(d) = MEDIT_STATS_MENU;
|
||||
medit_disp_stats_menu(d);
|
||||
|
|
@ -914,31 +970,23 @@ void medit_parse(struct descriptor_data *d, char *arg)
|
|||
case 'Q':
|
||||
medit_disp_menu(d);
|
||||
return;
|
||||
case '1': /* Edit level */
|
||||
OLC_MODE(d) = MEDIT_LEVEL;
|
||||
i++;
|
||||
break;
|
||||
case '2': /* Autoroll stats */
|
||||
case '1': /* Autoroll stats */
|
||||
medit_autoroll_stats(d);
|
||||
medit_disp_stats_menu(d);
|
||||
OLC_VAL(d) = TRUE;
|
||||
return;
|
||||
case '3':
|
||||
case '2':
|
||||
OLC_MODE(d) = MEDIT_NUM_HP_DICE;
|
||||
i++;
|
||||
break;
|
||||
case '4':
|
||||
case '3':
|
||||
OLC_MODE(d) = MEDIT_SIZE_HP_DICE;
|
||||
i++;
|
||||
break;
|
||||
case '5':
|
||||
case '4':
|
||||
OLC_MODE(d) = MEDIT_ADD_HP;
|
||||
i++;
|
||||
break;
|
||||
case '8':
|
||||
OLC_MODE(d) = MEDIT_ALIGNMENT;
|
||||
i++;
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
if (!CONFIG_MEDIT_ADVANCED) {
|
||||
|
|
@ -1165,6 +1213,30 @@ void medit_parse(struct descriptor_data *d, char *arg)
|
|||
medit_disp_menu(d);
|
||||
return;
|
||||
|
||||
case MEDIT_SPECIES_MENU:
|
||||
i = atoi(arg);
|
||||
if (i == 0) {
|
||||
medit_disp_menu(d);
|
||||
return;
|
||||
}
|
||||
if (i == NUM_SPECIES + 1) {
|
||||
GET_SPECIES(OLC_MOB(d)) = SPECIES_UNDEFINED;
|
||||
OLC_VAL(d) = TRUE;
|
||||
write_to_output(d, "Species cleared.\r\n");
|
||||
medit_disp_menu(d);
|
||||
return;
|
||||
}
|
||||
if (i < 1 || i > NUM_SPECIES + 1) {
|
||||
write_to_output(d, "Invalid choice!\r\n");
|
||||
medit_disp_species_menu(d);
|
||||
return;
|
||||
}
|
||||
GET_SPECIES(OLC_MOB(d)) = i - 1;
|
||||
OLC_VAL(d) = TRUE;
|
||||
write_to_output(d, "Species set to %s.\r\n", species_types[GET_SPECIES(OLC_MOB(d))]);
|
||||
medit_disp_menu(d);
|
||||
return;
|
||||
|
||||
case OLC_SCRIPT_EDIT:
|
||||
if (dg_script_edit_parse(d, arg)) return;
|
||||
break;
|
||||
|
|
@ -1246,6 +1318,19 @@ void medit_parse(struct descriptor_data *d, char *arg)
|
|||
GET_SEX(OLC_MOB(d)) = LIMIT(i - 1, 0, NUM_GENDERS - 1);
|
||||
break;
|
||||
|
||||
case MEDIT_AGE:
|
||||
if (i < MIN_CHAR_AGE || i > MAX_CHAR_AGE) {
|
||||
write_to_output(d, "Age must be between %d and %d.\r\n",
|
||||
MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
write_to_output(d, "Enter age (%d-%d): ", MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
return;
|
||||
}
|
||||
GET_ROLEPLAY_AGE(OLC_MOB(d)) = i;
|
||||
GET_ROLEPLAY_AGE_YEAR(OLC_MOB(d)) = time_info.year;
|
||||
OLC_VAL(d) = TRUE;
|
||||
medit_disp_menu(d);
|
||||
return;
|
||||
|
||||
case MEDIT_NUM_HP_DICE:
|
||||
GET_HIT(OLC_MOB(d)) = LIMIT(i, 0, 30);
|
||||
OLC_VAL(d) = TRUE;
|
||||
|
|
@ -1259,7 +1344,7 @@ void medit_parse(struct descriptor_data *d, char *arg)
|
|||
return;
|
||||
|
||||
case MEDIT_ADD_HP:
|
||||
GET_MOVE(OLC_MOB(d)) = LIMIT(i, 0, 30000);
|
||||
GET_STAMINA(OLC_MOB(d)) = LIMIT(i, 0, 30000);
|
||||
OLC_VAL(d) = TRUE;
|
||||
medit_disp_stats_menu(d);
|
||||
return;
|
||||
|
|
@ -1413,25 +1498,83 @@ void medit_string_cleanup(struct descriptor_data *d, int terminator)
|
|||
}
|
||||
}
|
||||
|
||||
static int roll_stat_for_cap(int cap)
|
||||
{
|
||||
int total = 0;
|
||||
int dice_d4 = 0;
|
||||
int remainder = 0;
|
||||
|
||||
if (cap <= 0)
|
||||
return 0;
|
||||
|
||||
dice_d4 = cap / 4;
|
||||
remainder = cap % 4;
|
||||
|
||||
if (dice_d4 > 0)
|
||||
total += dice(dice_d4, 4);
|
||||
if (remainder > 0)
|
||||
total += dice(1, remainder);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static int autoroll_species_stat(struct char_data *mob, int ability)
|
||||
{
|
||||
int min = 0;
|
||||
int cap = 0;
|
||||
int mod = 0;
|
||||
int roll_cap;
|
||||
int total;
|
||||
|
||||
if (HAS_VALID_SPECIES(mob)) {
|
||||
int species = GET_SPECIES(mob);
|
||||
int species_min = species_ability_min(species, ability);
|
||||
int species_cap = species_ability_cap(species, ability);
|
||||
|
||||
if (species_min > 0)
|
||||
min = species_min;
|
||||
if (species_cap > 0)
|
||||
cap = species_cap;
|
||||
|
||||
mod = species_ability_mod(species, ability);
|
||||
}
|
||||
|
||||
if (cap > 0 && min > cap)
|
||||
min = cap;
|
||||
|
||||
roll_cap = (cap > 0) ? (cap - mod) : (18 - mod);
|
||||
if (roll_cap < 1)
|
||||
roll_cap = 1;
|
||||
|
||||
total = roll_stat_for_cap(roll_cap) + mod;
|
||||
|
||||
if (cap > 0 && total > cap)
|
||||
total = cap;
|
||||
if (min > 0 && total < min)
|
||||
total = min;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
void medit_autoroll_stats(struct descriptor_data *d)
|
||||
{
|
||||
int mob_lev;
|
||||
int mob_lev = GET_LEVEL(OLC_MOB(d));
|
||||
|
||||
mob_lev = 1;
|
||||
GET_LEVEL(OLC_MOB(d)) = 1;
|
||||
if (mob_lev < 1)
|
||||
mob_lev = 1;
|
||||
|
||||
GET_MOVE(OLC_MOB(d)) = mob_lev * 10; /* hit point bonus (mobs don't use movement points) */
|
||||
GET_STAMINA(OLC_MOB(d)) = mob_lev * 10; /* hit point bonus (mobs don't use stamina points) */
|
||||
GET_HIT(OLC_MOB(d)) = mob_lev / 5; /* number of hitpoint dice */
|
||||
GET_MANA(OLC_MOB(d)) = mob_lev / 5; /* size of hitpoint dice */
|
||||
|
||||
/* 'Advanced' stats are only rolled if advanced options are enabled */
|
||||
if (CONFIG_MEDIT_ADVANCED) {
|
||||
GET_STR(OLC_MOB(d)) = LIMIT((mob_lev * 2) / 3, 11, 18); /* 2/3 level in range 11 to 18 */
|
||||
GET_INT(OLC_MOB(d)) = LIMIT((mob_lev * 2) / 3, 11, 18);
|
||||
GET_WIS(OLC_MOB(d)) = LIMIT((mob_lev * 2) / 3, 11, 18);
|
||||
GET_DEX(OLC_MOB(d)) = LIMIT((mob_lev * 2) / 3, 11, 18);
|
||||
GET_CON(OLC_MOB(d)) = LIMIT((mob_lev * 2) / 3, 11, 18);
|
||||
GET_CHA(OLC_MOB(d)) = LIMIT((mob_lev * 2) / 3, 11, 18);
|
||||
GET_STR(OLC_MOB(d)) = autoroll_species_stat(OLC_MOB(d), ABIL_STR);
|
||||
GET_INT(OLC_MOB(d)) = autoroll_species_stat(OLC_MOB(d), ABIL_INT);
|
||||
GET_WIS(OLC_MOB(d)) = autoroll_species_stat(OLC_MOB(d), ABIL_WIS);
|
||||
GET_DEX(OLC_MOB(d)) = autoroll_species_stat(OLC_MOB(d), ABIL_DEX);
|
||||
GET_CON(OLC_MOB(d)) = autoroll_species_stat(OLC_MOB(d), ABIL_CON);
|
||||
GET_CHA(OLC_MOB(d)) = autoroll_species_stat(OLC_MOB(d), ABIL_CHA);
|
||||
|
||||
/* New ability-based saving throws: all default to 1/4 of mob level */
|
||||
GET_SAVE(OLC_MOB(d), ABIL_STR) = mob_lev / 4;
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ void mobile_activity(void)
|
|||
((door = rand_number(0, 18)) < DIR_COUNT) && CAN_GO(ch, door) &&
|
||||
!ROOM_FLAGGED(EXIT(ch, door)->to_room, ROOM_NOMOB) &&
|
||||
!ROOM_FLAGGED(EXIT(ch, door)->to_room, ROOM_DEATH) &&
|
||||
!RIDDEN_BY(ch) &&
|
||||
(!MOB_FLAGGED(ch, MOB_STAY_ZONE) ||
|
||||
(world[EXIT(ch, door)->to_room].zone == world[IN_ROOM(ch)].zone)))
|
||||
{
|
||||
|
|
@ -99,10 +100,7 @@ void mobile_activity(void)
|
|||
if (MOB_FLAGGED(ch, MOB_WIMPY) && AWAKE(vict))
|
||||
continue;
|
||||
|
||||
if (MOB_FLAGGED(ch, MOB_AGGRESSIVE ) ||
|
||||
(MOB_FLAGGED(ch, MOB_AGGR_EVIL ) && IS_EVIL(vict)) ||
|
||||
(MOB_FLAGGED(ch, MOB_AGGR_NEUTRAL) && IS_NEUTRAL(vict)) ||
|
||||
(MOB_FLAGGED(ch, MOB_AGGR_GOOD ) && IS_GOOD(vict))) {
|
||||
if (MOB_FLAGGED(ch, MOB_AGGRESSIVE)) {
|
||||
|
||||
/* Can a master successfully control the charmed monster? */
|
||||
if (aggressive_mob_on_a_leash(ch, ch->master, vict))
|
||||
|
|
@ -267,4 +265,3 @@ static bool aggressive_mob_on_a_leash(struct char_data *slave, struct char_data
|
|||
/* So sorry, now you're a player killer... Tsk tsk. */
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
|
|
|||
60
src/oasis.h
60
src/oasis.h
|
|
@ -269,39 +269,41 @@ extern const char *nrm, *grn, *cyn, *yel;
|
|||
#define MEDIT_SKILL_MENU 11
|
||||
#define MEDIT_SKILL_EDIT 12
|
||||
#define MEDIT_CLASS_MENU 13
|
||||
#define MEDIT_SPECIES_MENU 14
|
||||
|
||||
/* Numerical responses. */
|
||||
#define MEDIT_NUMERICAL_RESPONSE 14
|
||||
#define MEDIT_SEX 15
|
||||
#define MEDIT_NUM_HP_DICE 16
|
||||
#define MEDIT_SIZE_HP_DICE 17
|
||||
#define MEDIT_ADD_HP 18
|
||||
#define MEDIT_POS 19
|
||||
#define MEDIT_DEFAULT_POS 20
|
||||
#define MEDIT_ATTACK 21
|
||||
#define MEDIT_LEVEL 22
|
||||
#define MEDIT_ALIGNMENT 23
|
||||
#define MEDIT_DELETE 24
|
||||
#define MEDIT_COPY 25
|
||||
#define MEDIT_STR 26
|
||||
#define MEDIT_INT 27
|
||||
#define MEDIT_WIS 28
|
||||
#define MEDIT_DEX 29
|
||||
#define MEDIT_CON 30
|
||||
#define MEDIT_CHA 31
|
||||
#define MEDIT_SAVE_STR 32
|
||||
#define MEDIT_SAVE_DEX 33
|
||||
#define MEDIT_SAVE_CON 34
|
||||
#define MEDIT_SAVE_INT 35
|
||||
#define MEDIT_SAVE_WIS 36
|
||||
#define MEDIT_SAVE_CHA 37
|
||||
#define MEDIT_SKILL_VALUE 38
|
||||
#define MEDIT_NUMERICAL_RESPONSE 15
|
||||
#define MEDIT_SEX 16
|
||||
#define MEDIT_AGE 44
|
||||
#define MEDIT_NUM_HP_DICE 17
|
||||
#define MEDIT_SIZE_HP_DICE 18
|
||||
#define MEDIT_ADD_HP 19
|
||||
#define MEDIT_POS 20
|
||||
#define MEDIT_DEFAULT_POS 21
|
||||
#define MEDIT_ATTACK 22
|
||||
#define MEDIT_LEVEL 23
|
||||
#define MEDIT_ALIGNMENT 24
|
||||
#define MEDIT_DELETE 25
|
||||
#define MEDIT_COPY 26
|
||||
#define MEDIT_STR 27
|
||||
#define MEDIT_INT 28
|
||||
#define MEDIT_WIS 29
|
||||
#define MEDIT_DEX 30
|
||||
#define MEDIT_CON 31
|
||||
#define MEDIT_CHA 32
|
||||
#define MEDIT_SAVE_STR 33
|
||||
#define MEDIT_SAVE_DEX 34
|
||||
#define MEDIT_SAVE_CON 35
|
||||
#define MEDIT_SAVE_INT 36
|
||||
#define MEDIT_SAVE_WIS 37
|
||||
#define MEDIT_SAVE_CHA 38
|
||||
#define MEDIT_SKILL_VALUE 39
|
||||
|
||||
/* Skinning yield editor */
|
||||
#define MEDIT_SKIN_MENU 39
|
||||
#define MEDIT_SKIN_ADD_VNUM 40
|
||||
#define MEDIT_SKIN_ADD_DC 41
|
||||
#define MEDIT_SKIN_DELETE 42
|
||||
#define MEDIT_SKIN_MENU 40
|
||||
#define MEDIT_SKIN_ADD_VNUM 41
|
||||
#define MEDIT_SKIN_ADD_DC 42
|
||||
#define MEDIT_SKIN_DELETE 43
|
||||
|
||||
/* Submodes of SEDIT connectedness. */
|
||||
#define SEDIT_MAIN_MENU 0
|
||||
|
|
|
|||
|
|
@ -226,9 +226,7 @@ static void auto_equip(struct char_data *ch, struct obj_data *obj, int location)
|
|||
|
||||
if (location > 0) { /* Wearable. */
|
||||
if (!GET_EQ(ch,j)) {
|
||||
/* Check the characters's alignment to prevent them from being zapped
|
||||
* through the auto-equipping. */
|
||||
if (invalid_align(ch, obj) || invalid_class(ch, obj))
|
||||
if (invalid_class(ch, obj))
|
||||
location = LOC_INVENTORY;
|
||||
else
|
||||
equip_char(ch, obj, j);
|
||||
|
|
@ -573,6 +571,9 @@ obj_save_data *objsave_parse_objects(FILE *fl)
|
|||
void commit_current(void) {
|
||||
if (!temp) return;
|
||||
|
||||
if (GET_OBJ_TYPE(temp) == ITEM_MONEY)
|
||||
update_money_obj(temp);
|
||||
|
||||
/* sanitize top-level locate range only; children will be negative later */
|
||||
int loc = pending_locate;
|
||||
if (pending_nest <= 0) {
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@
|
|||
|
||||
#define PFDEF_SEX 0
|
||||
#define PFDEF_CLASS 0
|
||||
#define PFDEF_SPECIES SPECIES_UNDEFINED
|
||||
#define PFDEF_LEVEL 0
|
||||
#define PFDEF_HEIGHT 0
|
||||
#define PFDEF_WEIGHT 0
|
||||
#define PFDEF_ALIGNMENT 0
|
||||
#define PFDEF_PLRFLAGS 0
|
||||
#define PFDEF_AFFFLAGS 0
|
||||
#define PFDEF_SAVETHROW 0
|
||||
|
|
@ -29,7 +29,6 @@
|
|||
#define PFDEF_CONDITION 0
|
||||
#define PFDEF_BADPWS 0
|
||||
#define PFDEF_PREFFLAGS 0
|
||||
#define PFDEF_PRACTICES 0
|
||||
#define PFDEF_COINS 0
|
||||
#define PFDEF_BANK_COINS 0
|
||||
#define PFDEF_EXP 0
|
||||
|
|
@ -44,8 +43,8 @@
|
|||
#define PFDEF_MAXHIT 0
|
||||
#define PFDEF_MANA 0
|
||||
#define PFDEF_MAXMANA 0
|
||||
#define PFDEF_MOVE 0
|
||||
#define PFDEF_MAXMOVE 0
|
||||
#define PFDEF_STAMINA 0
|
||||
#define PFDEF_MAXSTAMINA 0
|
||||
#define PFDEF_HUNGER 0
|
||||
#define PFDEF_THIRST 0
|
||||
#define PFDEF_DRUNK 0
|
||||
|
|
@ -58,5 +57,7 @@
|
|||
#define PFDEF_CURRQUEST NOTHING
|
||||
#define PFDEF_LASTMOTD 0
|
||||
#define PFDEF_LASTNEWS 0
|
||||
#define PFDEF_REROLL_USED 0
|
||||
#define PFDEF_REROLL_EXPIRES 0
|
||||
|
||||
#endif /* _PFDEFAULTS_H_ */
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#define LOAD_HIT 0
|
||||
#define LOAD_MANA 1
|
||||
#define LOAD_MOVE 2
|
||||
#define LOAD_STAMINA 2
|
||||
#define LOAD_STRENGTH 3
|
||||
|
||||
#define PT_PNAME(i) (player_table[(i)].name)
|
||||
|
|
@ -222,6 +222,20 @@ char *get_name_by_id(long id)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
static void update_roleplay_age(struct char_data *ch)
|
||||
{
|
||||
if (GET_ROLEPLAY_AGE(ch) == 0)
|
||||
GET_ROLEPLAY_AGE(ch) = MIN_CHAR_AGE;
|
||||
|
||||
if (GET_ROLEPLAY_AGE_YEAR(ch) == 0)
|
||||
GET_ROLEPLAY_AGE_YEAR(ch) = time_info.year;
|
||||
|
||||
if (time_info.year > GET_ROLEPLAY_AGE_YEAR(ch)) {
|
||||
GET_ROLEPLAY_AGE(ch) += (time_info.year - GET_ROLEPLAY_AGE_YEAR(ch));
|
||||
GET_ROLEPLAY_AGE_YEAR(ch) = time_info.year;
|
||||
}
|
||||
}
|
||||
|
||||
/* Stuff related to the save/load player system. */
|
||||
/* New load_char reads ASCII Player Files. Load a char, TRUE if loaded, FALSE
|
||||
* if not. */
|
||||
|
|
@ -232,6 +246,7 @@ int load_char(const char *name, struct char_data *ch)
|
|||
char filename[40];
|
||||
char buf[128], buf2[128], line[MAX_INPUT_LENGTH + 1], tag[6];
|
||||
char f1[128], f2[128], f3[128], f4[128];
|
||||
bool loaded_stamina = FALSE;
|
||||
trig_data *t = NULL;
|
||||
trig_rnum t_rnum = NOTHING;
|
||||
|
||||
|
|
@ -255,10 +270,12 @@ int load_char(const char *name, struct char_data *ch)
|
|||
ch->player_specials->saved.skills[i] = 0;
|
||||
GET_SEX(ch) = PFDEF_SEX;
|
||||
GET_CLASS(ch) = PFDEF_CLASS;
|
||||
GET_SPECIES(ch) = PFDEF_SPECIES;
|
||||
GET_LEVEL(ch) = PFDEF_LEVEL;
|
||||
GET_HEIGHT(ch) = PFDEF_HEIGHT;
|
||||
GET_WEIGHT(ch) = PFDEF_WEIGHT;
|
||||
GET_ALIGNMENT(ch) = PFDEF_ALIGNMENT;
|
||||
GET_ROLEPLAY_AGE(ch) = 0;
|
||||
GET_ROLEPLAY_AGE_YEAR(ch) = 0;
|
||||
for (i = 0; i < NUM_OF_SAVING_THROWS; i++)
|
||||
GET_SAVE(ch, i) = PFDEF_SAVETHROW;
|
||||
GET_LOADROOM(ch) = PFDEF_LOADROOM;
|
||||
|
|
@ -283,8 +300,8 @@ int load_char(const char *name, struct char_data *ch)
|
|||
GET_MAX_HIT(ch) = PFDEF_MAXHIT;
|
||||
GET_MANA(ch) = PFDEF_MANA;
|
||||
GET_MAX_MANA(ch) = PFDEF_MAXMANA;
|
||||
GET_MOVE(ch) = PFDEF_MOVE;
|
||||
GET_MAX_MOVE(ch) = PFDEF_MAXMOVE;
|
||||
GET_STAMINA(ch) = PFDEF_STAMINA;
|
||||
GET_MAX_STAMINA(ch) = PFDEF_MAXSTAMINA;
|
||||
GET_OLC_ZONE(ch) = PFDEF_OLC;
|
||||
GET_PAGE_LENGTH(ch) = PFDEF_PAGELENGTH;
|
||||
GET_SCREEN_WIDTH(ch) = PFDEF_SCREENWIDTH;
|
||||
|
|
@ -297,6 +314,9 @@ int load_char(const char *name, struct char_data *ch)
|
|||
GET_NUM_QUESTS(ch) = PFDEF_COMPQUESTS;
|
||||
GET_LAST_MOTD(ch) = PFDEF_LASTMOTD;
|
||||
GET_LAST_NEWS(ch) = PFDEF_LASTNEWS;
|
||||
GET_REROLL_USED(ch) = PFDEF_REROLL_USED;
|
||||
GET_REROLL_EXPIRES(ch) = PFDEF_REROLL_EXPIRES;
|
||||
memset(&GET_REROLL_OLD_ABILS(ch), 0, sizeof(struct char_ability_data));
|
||||
if (GET_ACCOUNT(ch)) {
|
||||
free(GET_ACCOUNT(ch));
|
||||
GET_ACCOUNT(ch) = NULL;
|
||||
|
|
@ -315,6 +335,8 @@ int load_char(const char *name, struct char_data *ch)
|
|||
switch (*tag) {
|
||||
case 'A':
|
||||
if (!strcmp(tag, "Ac ")) GET_AC(ch) = atoi(line);
|
||||
else if (!strcmp(tag, "AgYr")) GET_ROLEPLAY_AGE_YEAR(ch) = atoi(line);
|
||||
else if (!strcmp(tag, "Age ")) GET_ROLEPLAY_AGE(ch) = LIMIT(atoi(line), MIN_CHAR_AGE, MAX_CHAR_AGE);
|
||||
else if (!strcmp(tag, "Acct")) {
|
||||
if (GET_ACCOUNT(ch))
|
||||
free(GET_ACCOUNT(ch));
|
||||
|
|
@ -338,7 +360,6 @@ int load_char(const char *name, struct char_data *ch)
|
|||
AFF_FLAGS(ch)[0] = asciiflag_conv(line);
|
||||
}
|
||||
if (!strcmp(tag, "Affs")) load_affects(fl, ch);
|
||||
else if (!strcmp(tag, "Alin")) GET_ALIGNMENT(ch) = atoi(line);
|
||||
else if (!strcmp(tag, "Alis")) read_aliases_ascii(fl, ch, atoi(line));
|
||||
break;
|
||||
|
||||
|
|
@ -396,7 +417,7 @@ int load_char(const char *name, struct char_data *ch)
|
|||
|
||||
case 'M':
|
||||
if (!strcmp(tag, "Mana")) load_HMVS(ch, line, LOAD_MANA);
|
||||
else if (!strcmp(tag, "Move")) load_HMVS(ch, line, LOAD_MOVE);
|
||||
else if (!strcmp(tag, "Move") && !loaded_stamina) load_HMVS(ch, line, LOAD_STAMINA);
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
|
|
@ -434,10 +455,34 @@ int load_char(const char *name, struct char_data *ch)
|
|||
|
||||
case 'R':
|
||||
if (!strcmp(tag, "Room")) GET_LOADROOM(ch) = atoi(line);
|
||||
else if (!strcmp(tag, "RrUs")) GET_REROLL_USED(ch) = atoi(line);
|
||||
else if (!strcmp(tag, "RrTm")) GET_REROLL_EXPIRES(ch) = (time_t)atol(line);
|
||||
else if (!strcmp(tag, "RrAb")) {
|
||||
int rstr, rint, rwis, rdex, rcon, rcha;
|
||||
|
||||
if (sscanf(line, "%d %d %d %d %d %d", &rstr, &rint, &rwis, &rdex, &rcon, &rcha) == 6) {
|
||||
GET_REROLL_OLD_ABILS(ch).str = rstr;
|
||||
GET_REROLL_OLD_ABILS(ch).intel = rint;
|
||||
GET_REROLL_OLD_ABILS(ch).wis = rwis;
|
||||
GET_REROLL_OLD_ABILS(ch).dex = rdex;
|
||||
GET_REROLL_OLD_ABILS(ch).con = rcon;
|
||||
GET_REROLL_OLD_ABILS(ch).cha = rcha;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
if (!strcmp(tag, "Sex ")) GET_SEX(ch) = atoi(line);
|
||||
if (!strcmp(tag, "Spec")) {
|
||||
int val = atoi(line);
|
||||
if (val < SPECIES_UNDEFINED || val >= NUM_SPECIES)
|
||||
val = SPECIES_UNDEFINED;
|
||||
GET_SPECIES(ch) = val;
|
||||
}
|
||||
else if (!strcmp(tag, "Stam")) {
|
||||
load_HMVS(ch, line, LOAD_STAMINA);
|
||||
loaded_stamina = TRUE;
|
||||
}
|
||||
else if (!strcmp(tag, "Sex ")) GET_SEX(ch) = atoi(line);
|
||||
else if (!strcmp(tag, "Sdsc")) {
|
||||
/* Clear any existing sdesc to avoid leaks */
|
||||
if (GET_SHORT_DESC(ch))
|
||||
|
|
@ -503,7 +548,13 @@ int load_char(const char *name, struct char_data *ch)
|
|||
}
|
||||
}
|
||||
|
||||
update_roleplay_age(ch);
|
||||
ch->player.time.birth = time(0) - get_total_played_seconds(ch);
|
||||
affect_total(ch);
|
||||
MOUNT(ch) = NULL;
|
||||
RIDDEN_BY(ch) = NULL;
|
||||
HITCHED_TO(ch) = NULL;
|
||||
REMOVE_BIT_AR(AFF_FLAGS(ch), AFF_MOUNTED);
|
||||
|
||||
/* initialization for imms */
|
||||
if (GET_LEVEL(ch) >= LVL_IMMORT) {
|
||||
|
|
@ -552,6 +603,9 @@ void save_char(struct char_data * ch)
|
|||
}
|
||||
}
|
||||
|
||||
update_roleplay_age(ch);
|
||||
ch->player.time.birth = time(0) - get_total_played_seconds(ch);
|
||||
|
||||
if (!get_filename(filename, sizeof(filename), PLR_FILE, GET_NAME(ch)))
|
||||
return;
|
||||
if (!(fl = fopen(filename, "w"))) {
|
||||
|
|
@ -614,10 +668,13 @@ void save_char(struct char_data * ch)
|
|||
if (POOFOUT(ch)) fprintf(fl, "PfOt: %s\n", POOFOUT(ch));
|
||||
if (GET_SEX(ch) != PFDEF_SEX) fprintf(fl, "Sex : %d\n", GET_SEX(ch));
|
||||
if (GET_CLASS(ch) != PFDEF_CLASS) fprintf(fl, "Clas: %d\n", GET_CLASS(ch));
|
||||
if (GET_SPECIES(ch) != PFDEF_SPECIES) fprintf(fl, "Spec: %d\n", GET_SPECIES(ch));
|
||||
if (GET_LEVEL(ch) != PFDEF_LEVEL) fprintf(fl, "Levl: %d\n", GET_LEVEL(ch));
|
||||
|
||||
fprintf(fl, "Id : %ld\n", GET_IDNUM(ch));
|
||||
fprintf(fl, "Brth: %ld\n", (long)ch->player.time.birth);
|
||||
fprintf(fl, "Age : %d\n", GET_ROLEPLAY_AGE(ch));
|
||||
fprintf(fl, "AgYr: %d\n", GET_ROLEPLAY_AGE_YEAR(ch));
|
||||
fprintf(fl, "Plyd: %d\n", ch->player.time.played);
|
||||
fprintf(fl, "Last: %ld\n", (long)ch->player.time.logon);
|
||||
|
||||
|
|
@ -625,11 +682,22 @@ void save_char(struct char_data * ch)
|
|||
fprintf(fl, "Lmot: %d\n", (int)GET_LAST_MOTD(ch));
|
||||
if (GET_LAST_NEWS(ch) != PFDEF_LASTNEWS)
|
||||
fprintf(fl, "Lnew: %d\n", (int)GET_LAST_NEWS(ch));
|
||||
if (GET_REROLL_USED(ch) != PFDEF_REROLL_USED)
|
||||
fprintf(fl, "RrUs: %d\n", (int)GET_REROLL_USED(ch));
|
||||
if (GET_REROLL_EXPIRES(ch) != PFDEF_REROLL_EXPIRES) {
|
||||
fprintf(fl, "RrTm: %ld\n", (long)GET_REROLL_EXPIRES(ch));
|
||||
fprintf(fl, "RrAb: %d %d %d %d %d %d\n",
|
||||
GET_REROLL_OLD_ABILS(ch).str,
|
||||
GET_REROLL_OLD_ABILS(ch).intel,
|
||||
GET_REROLL_OLD_ABILS(ch).wis,
|
||||
GET_REROLL_OLD_ABILS(ch).dex,
|
||||
GET_REROLL_OLD_ABILS(ch).con,
|
||||
GET_REROLL_OLD_ABILS(ch).cha);
|
||||
}
|
||||
|
||||
if (GET_HOST(ch)) fprintf(fl, "Host: %s\n", GET_HOST(ch));
|
||||
if (GET_HEIGHT(ch) != PFDEF_HEIGHT) fprintf(fl, "Hite: %d\n", GET_HEIGHT(ch));
|
||||
if (GET_WEIGHT(ch) != PFDEF_WEIGHT) fprintf(fl, "Wate: %d\n", GET_WEIGHT(ch));
|
||||
if (GET_ALIGNMENT(ch) != PFDEF_ALIGNMENT) fprintf(fl, "Alin: %d\n", GET_ALIGNMENT(ch));
|
||||
|
||||
|
||||
sprintascii(bits, PLR_FLAGS(ch)[0]);
|
||||
|
|
@ -669,7 +737,7 @@ void save_char(struct char_data * ch)
|
|||
|
||||
if (GET_HIT(ch) != PFDEF_HIT || GET_MAX_HIT(ch) != PFDEF_MAXHIT) fprintf(fl, "Hit : %d/%d\n", GET_HIT(ch), GET_MAX_HIT(ch));
|
||||
if (GET_MANA(ch) != PFDEF_MANA || GET_MAX_MANA(ch) != PFDEF_MAXMANA) fprintf(fl, "Mana: %d/%d\n", GET_MANA(ch), GET_MAX_MANA(ch));
|
||||
if (GET_MOVE(ch) != PFDEF_MOVE || GET_MAX_MOVE(ch) != PFDEF_MAXMOVE) fprintf(fl, "Move: %d/%d\n", GET_MOVE(ch), GET_MAX_MOVE(ch));
|
||||
if (GET_STAMINA(ch) != PFDEF_STAMINA || GET_MAX_STAMINA(ch) != PFDEF_MAXSTAMINA) fprintf(fl, "Stam: %d/%d\n", GET_STAMINA(ch), GET_MAX_STAMINA(ch));
|
||||
|
||||
if (GET_STR(ch) != PFDEF_STR) fprintf(fl, "Str : %d\n", GET_STR(ch));
|
||||
if (GET_INT(ch) != PFDEF_INT) fprintf(fl, "Int : %d\n", GET_INT(ch));
|
||||
|
|
@ -946,9 +1014,9 @@ static void load_HMVS(struct char_data *ch, const char *line, int mode)
|
|||
GET_MAX_MANA(ch) = num2;
|
||||
break;
|
||||
|
||||
case LOAD_MOVE:
|
||||
GET_MOVE(ch) = num;
|
||||
GET_MAX_MOVE(ch) = num2;
|
||||
case LOAD_STAMINA:
|
||||
GET_STAMINA(ch) = num;
|
||||
GET_MAX_STAMINA(ch) = num2;
|
||||
break;
|
||||
|
||||
case LOAD_STRENGTH:
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ static void prefedit_disp_main_menu(struct descriptor_data *d)
|
|||
vict = PREFEDIT_GET_CHAR;
|
||||
|
||||
sprintf(prompt_string, "%s%s%s", PREFEDIT_FLAGGED(PRF_DISPHP) ? "H" : "", PREFEDIT_FLAGGED(PRF_DISPMANA) ? "M" : "",
|
||||
PREFEDIT_FLAGGED(PRF_DISPMOVE) ? "V" : "" );
|
||||
PREFEDIT_FLAGGED(PRF_DISPSTAMINA) ? "S" : "" );
|
||||
|
||||
sprintf(color_string, "%s", multi_types[(PREFEDIT_FLAGGED(PRF_COLOR_1) ? 1 : 0) + (PREFEDIT_FLAGGED(PRF_COLOR_2) ? 2 : 0)]);
|
||||
|
||||
|
|
@ -292,12 +292,12 @@ static void prefedit_disp_prompt_menu(struct descriptor_data *d)
|
|||
sprintf(prompt_string, "<Auto>");
|
||||
else
|
||||
sprintf(prompt_string, "%s%s%s", PREFEDIT_FLAGGED(PRF_DISPHP) ? "H" : "", PREFEDIT_FLAGGED(PRF_DISPMANA) ? "M" : "",
|
||||
PREFEDIT_FLAGGED(PRF_DISPMOVE) ? "V" : "");
|
||||
PREFEDIT_FLAGGED(PRF_DISPSTAMINA) ? "S" : "");
|
||||
|
||||
send_to_char(d->character, "%sPrompt Settings\r\n"
|
||||
"%s1%s) Toggle HP\r\n"
|
||||
"%s2%s) Toggle Mana\r\n"
|
||||
"%s3%s) Toggle Moves\r\n"
|
||||
"%s3%s) Toggle Stamina\r\n"
|
||||
"%s4%s) Toggle auto flag\r\n\r\n"
|
||||
"%sCurrent Prompt: %s%s%s\r\n\r\n"
|
||||
"%s0%s) Quit (to main menu)\r\n",
|
||||
|
|
@ -730,10 +730,10 @@ void prefedit_parse(struct descriptor_data * d, char *arg)
|
|||
}
|
||||
else if (number == 3)
|
||||
{
|
||||
if (PREFEDIT_FLAGGED(PRF_DISPMOVE))
|
||||
REMOVE_BIT_AR(PREFEDIT_GET_FLAGS, PRF_DISPMOVE);
|
||||
if (PREFEDIT_FLAGGED(PRF_DISPSTAMINA))
|
||||
REMOVE_BIT_AR(PREFEDIT_GET_FLAGS, PRF_DISPSTAMINA);
|
||||
else
|
||||
SET_BIT_AR(PREFEDIT_GET_FLAGS, PRF_DISPMOVE);
|
||||
SET_BIT_AR(PREFEDIT_GET_FLAGS, PRF_DISPSTAMINA);
|
||||
}
|
||||
else if (number == 4)
|
||||
{
|
||||
|
|
@ -784,9 +784,9 @@ void prefedit_Restore_Defaults(struct descriptor_data *d)
|
|||
if (!PREFEDIT_FLAGGED(PRF_DISPMANA))
|
||||
SET_BIT_AR(PREFEDIT_GET_FLAGS, PRF_DISPMANA);
|
||||
|
||||
/* PRF_DISPMOVE - On */
|
||||
if (!PREFEDIT_FLAGGED(PRF_DISPMOVE))
|
||||
SET_BIT_AR(PREFEDIT_GET_FLAGS, PRF_DISPMOVE);
|
||||
/* PRF_DISPSTAMINA - On */
|
||||
if (!PREFEDIT_FLAGGED(PRF_DISPSTAMINA))
|
||||
SET_BIT_AR(PREFEDIT_GET_FLAGS, PRF_DISPSTAMINA);
|
||||
|
||||
/* PRF_AUTOEXIT - On */
|
||||
if (!PREFEDIT_FLAGGED(PRF_AUTOEXIT))
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ static const char s_Button5[] = "\005\002Inventory\002inventory\006";
|
|||
|
||||
static const char s_Gauge1[] = "\005\002Health\002red\002HEALTH\002HEALTH_MAX\006";
|
||||
static const char s_Gauge2[] = "\005\002Mana\002blue\002MANA\002MANA_MAX\006";
|
||||
static const char s_Gauge3[] = "\005\002Movement\002green\002MOVEMENT\002MOVEMENT_MAX\006";
|
||||
static const char s_Gauge3[] = "\005\002Stamina\002green\002MOVEMENT\002MOVEMENT_MAX\006";
|
||||
static const char s_Gauge4[] = "\005\002Exp TNL\002yellow\002EXPERIENCE\002EXPERIENCE_MAX\006";
|
||||
static const char s_Gauge5[] = "\005\002Opponent\002darkred\002OPPONENT_HEALTH\002OPPONENT_HEALTH_MAX\006";
|
||||
|
||||
|
|
@ -142,11 +142,10 @@ static variable_name_t VariableNameTable[eMSDP_MAX+1] =
|
|||
{ eMSDP_LEVEL, "LEVEL", NUMBER_READ_ONLY },
|
||||
{ eMSDP_RACE, "RACE", STRING_READ_ONLY },
|
||||
{ eMSDP_CLASS, "CLASS", STRING_READ_ONLY },
|
||||
{ eMSDP_MANA, "MANA", NUMBER_READ_ONLY },
|
||||
{ eMSDP_MANA_MAX, "MANA_MAX", NUMBER_READ_ONLY },
|
||||
{ eMSDP_WIMPY, "WIMPY", NUMBER_READ_ONLY },
|
||||
{ eMSDP_PRACTICE, "PRACTICE", NUMBER_READ_ONLY },
|
||||
{ eMSDP_MONEY, "MONEY", NUMBER_READ_ONLY },
|
||||
{ eMSDP_MANA, "MANA", NUMBER_READ_ONLY },
|
||||
{ eMSDP_MANA_MAX, "MANA_MAX", NUMBER_READ_ONLY },
|
||||
{ eMSDP_WIMPY, "WIMPY", NUMBER_READ_ONLY },
|
||||
{ eMSDP_MONEY, "MONEY", NUMBER_READ_ONLY },
|
||||
{ eMSDP_MOVEMENT, "MOVEMENT", NUMBER_READ_ONLY },
|
||||
{ eMSDP_MOVEMENT_MAX, "MOVEMENT_MAX", NUMBER_READ_ONLY },
|
||||
{ eMSDP_AC, "AC", NUMBER_READ_ONLY },
|
||||
|
|
|
|||
|
|
@ -106,11 +106,10 @@ typedef enum
|
|||
eMSDP_LEVEL,
|
||||
eMSDP_RACE,
|
||||
eMSDP_CLASS,
|
||||
eMSDP_MANA,
|
||||
eMSDP_MANA_MAX,
|
||||
eMSDP_WIMPY,
|
||||
eMSDP_PRACTICE,
|
||||
eMSDP_MONEY,
|
||||
eMSDP_MANA,
|
||||
eMSDP_MANA_MAX,
|
||||
eMSDP_WIMPY,
|
||||
eMSDP_MONEY,
|
||||
eMSDP_MOVEMENT,
|
||||
eMSDP_MOVEMENT_MAX,
|
||||
eMSDP_AC,
|
||||
|
|
|
|||
710
src/roomsave.c
710
src/roomsave.c
|
|
@ -1,710 +0,0 @@
|
|||
/**
|
||||
* @file roomsave.c
|
||||
* Numeric and string contants used by the MUD.
|
||||
*
|
||||
* An addition to the core tbaMUD source code distribution, which is a derivative
|
||||
* of, and continuation of, CircleMUD.
|
||||
*
|
||||
* All rights reserved. See license for complete information.
|
||||
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University
|
||||
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.
|
||||
*
|
||||
*/
|
||||
#include "conf.h"
|
||||
#include "sysdep.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
#include "structs.h"
|
||||
#include "utils.h"
|
||||
#include "db.h"
|
||||
#include "handler.h"
|
||||
#include "comm.h"
|
||||
#include "constants.h"
|
||||
#include "roomsave.h"
|
||||
|
||||
/* Write saved rooms under lib/world/rsv/<vnum>.rsv (like wld/ zon/ obj/). */
|
||||
#ifndef ROOMSAVE_PREFIX
|
||||
#define ROOMSAVE_PREFIX LIB_WORLD "rsv/"
|
||||
#endif
|
||||
#ifndef ROOMSAVE_EXT
|
||||
#define ROOMSAVE_EXT ".rsv"
|
||||
#endif
|
||||
|
||||
static unsigned char *roomsave_dirty = NULL;
|
||||
|
||||
void RoomSave_init_dirty(void) {
|
||||
free(roomsave_dirty);
|
||||
roomsave_dirty = calloc((size_t)top_of_world + 1, 1);
|
||||
}
|
||||
|
||||
void RoomSave_mark_dirty_room(room_rnum rnum) {
|
||||
if (!roomsave_dirty) return;
|
||||
if (rnum != NOWHERE && rnum >= 0 && rnum <= top_of_world)
|
||||
roomsave_dirty[rnum] = 1;
|
||||
}
|
||||
|
||||
/* Where does an object “live” (topmost location -> room)? */
|
||||
room_rnum RoomSave_room_of_obj(struct obj_data *o) {
|
||||
if (!o) return NOWHERE;
|
||||
while (o->in_obj) o = o->in_obj;
|
||||
if (o->carried_by) return IN_ROOM(o->carried_by);
|
||||
if (o->worn_by) return IN_ROOM(o->worn_by);
|
||||
return o->in_room;
|
||||
}
|
||||
|
||||
/* --- helper: read a list of objects until '.' or 'E' and return the head --- */
|
||||
/* Context-aware implementation: stop_on_E = 1 for nested B..E, 0 for top-level. */
|
||||
static struct obj_data *roomsave_read_list_ctx(FILE *fl, int stop_on_E)
|
||||
{
|
||||
char line[256];
|
||||
struct obj_data *head = NULL, *tail = NULL;
|
||||
|
||||
while (fgets(line, sizeof(line), fl)) {
|
||||
if (line[0] == '.') {
|
||||
/* End of this list scope */
|
||||
break;
|
||||
}
|
||||
|
||||
if (stop_on_E && line[0] == 'E') {
|
||||
/* End of nested (B..E) scope */
|
||||
break;
|
||||
}
|
||||
|
||||
/* For top-level reads (stop_on_E==0), or any non-'O', push back
|
||||
so the outer #R reader can handle M/E/G/P or '.' */
|
||||
if (line[0] != 'O') {
|
||||
long back = -((long)strlen(line));
|
||||
fseek(fl, back, SEEK_CUR);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Parse object header: O vnum timer weight cost unused */
|
||||
int vnum, timer, weight, cost, unused_cost;
|
||||
if (sscanf(line, "O %d %d %d %d %d", &vnum, &timer, &weight, &cost, &unused_cost) != 5)
|
||||
continue;
|
||||
|
||||
/* IMPORTANT: read by VNUM (VIRTUAL), not real index */
|
||||
struct obj_data *obj = read_object((obj_vnum)vnum, VIRTUAL);
|
||||
if (!obj) {
|
||||
mudlog(NRM, LVL_IMMORT, TRUE, "RoomSave: read_object(vnum=%d) failed.", vnum);
|
||||
/* Skip to next object/header or end-of-scope */
|
||||
long backpos;
|
||||
while (fgets(line, sizeof(line), fl)) {
|
||||
if (line[0] == 'O' || line[0] == '.' || (stop_on_E && line[0] == 'E')) {
|
||||
backpos = -((long)strlen(line));
|
||||
fseek(fl, backpos, SEEK_CUR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Apply core scalars */
|
||||
GET_OBJ_TIMER(obj) = timer;
|
||||
GET_OBJ_WEIGHT(obj) = weight;
|
||||
GET_OBJ_COST(obj) = cost;
|
||||
GET_OBJ_COST_PER_DAY(obj) = 0;
|
||||
|
||||
/* Clear array flags so missing slots don't keep proto bits */
|
||||
#ifdef EF_ARRAY_MAX
|
||||
# ifdef GET_OBJ_EXTRA_AR
|
||||
for (int i = 0; i < EF_ARRAY_MAX; i++) GET_OBJ_EXTRA_AR(obj, i) = 0;
|
||||
# else
|
||||
for (int i = 0; i < EF_ARRAY_MAX; i++) GET_OBJ_EXTRA(obj)[i] = 0;
|
||||
# endif
|
||||
#endif
|
||||
#ifdef TW_ARRAY_MAX
|
||||
for (int i = 0; i < TW_ARRAY_MAX; i++) GET_OBJ_WEAR(obj)[i] = 0;
|
||||
#endif
|
||||
|
||||
/* Read per-object lines until next 'O' or '.' or 'E'(when nested) */
|
||||
long backpos;
|
||||
while (fgets(line, sizeof(line), fl)) {
|
||||
if (line[0] == 'V') {
|
||||
int idx, val;
|
||||
if (sscanf(line, "V %d %d", &idx, &val) == 2) {
|
||||
#ifdef NUM_OBJ_VAL_POSITIONS
|
||||
if (idx >= 0 && idx < NUM_OBJ_VAL_POSITIONS) GET_OBJ_VAL(obj, idx) = val;
|
||||
#else
|
||||
if (idx >= 0 && idx < 6) GET_OBJ_VAL(obj, idx) = val;
|
||||
#endif
|
||||
}
|
||||
continue;
|
||||
} else if (line[0] == 'X') { /* extra flags */
|
||||
int idx, val;
|
||||
if (sscanf(line, "X %d %d", &idx, &val) == 2) {
|
||||
#if defined(EF_ARRAY_MAX) && defined(GET_OBJ_EXTRA_AR)
|
||||
if (idx >= 0 && idx < EF_ARRAY_MAX) GET_OBJ_EXTRA_AR(obj, idx) = val;
|
||||
#elif defined(EF_ARRAY_MAX)
|
||||
if (idx >= 0 && idx < EF_ARRAY_MAX) GET_OBJ_EXTRA(obj)[idx] = val;
|
||||
#else
|
||||
if (idx == 0) GET_OBJ_EXTRA(obj) = val;
|
||||
#endif
|
||||
}
|
||||
continue;
|
||||
} else if (line[0] == 'W') { /* wear flags */
|
||||
int idx, val;
|
||||
if (sscanf(line, "W %d %d", &idx, &val) == 2) {
|
||||
#ifdef TW_ARRAY_MAX
|
||||
if (idx >= 0 && idx < TW_ARRAY_MAX) GET_OBJ_WEAR(obj)[idx] = val;
|
||||
#else
|
||||
if (idx == 0) GET_OBJ_WEAR(obj) = val;
|
||||
#endif
|
||||
}
|
||||
continue;
|
||||
} else if (line[0] == 'B') {
|
||||
/* Nested contents until matching 'E' */
|
||||
struct obj_data *child_head = roomsave_read_list_ctx(fl, 1 /* stop_on_E */);
|
||||
|
||||
/* Detach each node before obj_to_obj(), otherwise we lose siblings */
|
||||
for (struct obj_data *it = child_head, *next; it; it = next) {
|
||||
next = it->next_content; /* remember original sibling */
|
||||
it->next_content = NULL; /* detach from temp list */
|
||||
obj_to_obj(it, obj); /* push into container (LIFO) */
|
||||
}
|
||||
continue;
|
||||
} else if (line[0] == 'O' || line[0] == '.' || (stop_on_E && line[0] == 'E')) {
|
||||
/* Next object / end-of-scope: rewind one line for outer loop to see it */
|
||||
backpos = -((long)strlen(line));
|
||||
fseek(fl, backpos, SEEK_CUR);
|
||||
break;
|
||||
} else {
|
||||
/* ignore unknown lines */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Append to this scope's list */
|
||||
obj->next_content = NULL;
|
||||
if (!head) head = tail = obj;
|
||||
else { tail->next_content = obj; tail = obj; }
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
/* Keep your existing one-arg API for callers: top-level semantics (stop_on_E = 0). */
|
||||
static struct obj_data *roomsave_read_list(FILE *fl)
|
||||
{
|
||||
return roomsave_read_list_ctx(fl, 0);
|
||||
}
|
||||
|
||||
/* ---------- Minimal line format ----------
|
||||
#R <vnum> <unix_time>
|
||||
O <vnum> <timer> <extra_flags> <wear_flags> <weight> <cost> <unused>
|
||||
V <i> <val[i]> ; repeated for all value slots present on this obj
|
||||
B ; begin contents of this object (container)
|
||||
E ; end contents of this object
|
||||
. ; end of room
|
||||
------------------------------------------ */
|
||||
|
||||
static void ensure_dir_exists(const char *path) {
|
||||
if (mkdir(path, 0775) == -1 && errno != EEXIST) {
|
||||
mudlog(CMP, LVL_IMMORT, TRUE, "SYSERR: roomsave mkdir(%s): %s", path, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/* zone vnum for a given room rnum (e.g., 134 -> zone 1) */
|
||||
static int roomsave_zone_for_rnum(room_rnum rnum) {
|
||||
if (rnum == NOWHERE || rnum < 0 || rnum > top_of_world) return 0;
|
||||
zone_rnum znum = world[rnum].zone;
|
||||
if (znum < 0 || znum > top_of_zone_table) return 0;
|
||||
return zone_table[znum].number; /* e.g., 1 for rooms 100–199, 2 for 200–299, etc. */
|
||||
}
|
||||
|
||||
/* lib/world/rsv/<zone>.rsv */
|
||||
static void roomsave_zone_filename(int zone_vnum, char *out, size_t outsz) {
|
||||
snprintf(out, outsz, "%s%d%s", ROOMSAVE_PREFIX, zone_vnum, ROOMSAVE_EXT);
|
||||
}
|
||||
|
||||
/* Write one object (and its recursive contents) */
|
||||
static void write_one_object(FILE *fl, struct obj_data *obj) {
|
||||
int i;
|
||||
|
||||
/* Core scalars (flags printed separately per-slot) */
|
||||
fprintf(fl, "O %d %d %d %d %d\n",
|
||||
GET_OBJ_VNUM(obj),
|
||||
GET_OBJ_TIMER(obj),
|
||||
GET_OBJ_WEIGHT(obj),
|
||||
GET_OBJ_COST(obj),
|
||||
GET_OBJ_COST_PER_DAY(obj));
|
||||
|
||||
/* Extra flags array */
|
||||
#if defined(EF_ARRAY_MAX) && defined(GET_OBJ_EXTRA_AR)
|
||||
for (i = 0; i < EF_ARRAY_MAX; i++)
|
||||
fprintf(fl, "X %d %d\n", i, GET_OBJ_EXTRA_AR(obj, i));
|
||||
#elif defined(EF_ARRAY_MAX)
|
||||
for (i = 0; i < EF_ARRAY_MAX; i++)
|
||||
fprintf(fl, "X %d %d\n", i, GET_OBJ_EXTRA(obj)[i]);
|
||||
#else
|
||||
fprintf(fl, "X %d %d\n", 0, GET_OBJ_EXTRA(obj));
|
||||
#endif
|
||||
|
||||
/* Wear flags array */
|
||||
#ifdef TW_ARRAY_MAX
|
||||
for (i = 0; i < TW_ARRAY_MAX; i++)
|
||||
fprintf(fl, "W %d %d\n", i, GET_OBJ_WEAR(obj)[i]);
|
||||
#else
|
||||
fprintf(fl, "W %d %d\n", 0, GET_OBJ_WEAR(obj));
|
||||
#endif
|
||||
|
||||
/* Values[] (durability, liquids, charges, etc.) */
|
||||
#ifdef NUM_OBJ_VAL_POSITIONS
|
||||
for (i = 0; i < NUM_OBJ_VAL_POSITIONS; i++)
|
||||
fprintf(fl, "V %d %d\n", i, GET_OBJ_VAL(obj, i));
|
||||
#else
|
||||
for (i = 0; i < 6; i++)
|
||||
fprintf(fl, "V %d %d\n", i, GET_OBJ_VAL(obj, i));
|
||||
#endif
|
||||
|
||||
/* Contents (recursive) */
|
||||
if (obj->contains) {
|
||||
struct obj_data *cont;
|
||||
fprintf(fl, "B\n");
|
||||
for (cont = obj->contains; cont; cont = cont->next_content)
|
||||
write_one_object(fl, cont);
|
||||
fprintf(fl, "E\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Forward declaration for RoomSave_now*/
|
||||
static void RS_write_room_mobs(FILE *out, room_rnum rnum);
|
||||
|
||||
/* Public: write the entire room’s contents */
|
||||
int RoomSave_now(room_rnum rnum) {
|
||||
char path[PATH_MAX], tmp[PATH_MAX], line[512];
|
||||
FILE *in = NULL, *out = NULL;
|
||||
room_vnum rvnum;
|
||||
int zvnum;
|
||||
|
||||
if (rnum == NOWHERE)
|
||||
return 0;
|
||||
|
||||
rvnum = world[rnum].number;
|
||||
zvnum = roomsave_zone_for_rnum(rnum);
|
||||
if (zvnum < 0)
|
||||
return 0;
|
||||
|
||||
ensure_dir_exists(ROOMSAVE_PREFIX);
|
||||
roomsave_zone_filename(zvnum, path, sizeof(path));
|
||||
|
||||
{
|
||||
int n = snprintf(tmp, sizeof(tmp), "%s.tmp", path);
|
||||
if (n < 0 || n >= (int)sizeof(tmp)) {
|
||||
mudlog(NRM, LVL_IMMORT, TRUE,
|
||||
"SYSERR: RoomSave: temp path too long for %s", path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(out = fopen(tmp, "w"))) {
|
||||
mudlog(NRM, LVL_IMMORT, TRUE,
|
||||
"SYSERR: RoomSave: fopen(%s) failed: %s",
|
||||
tmp, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((in = fopen(path, "r")) != NULL) {
|
||||
while (fgets(line, sizeof(line), in)) {
|
||||
if (strncmp(line, "#R ", 3) == 0) {
|
||||
int file_rvnum;
|
||||
long ts;
|
||||
if (sscanf(line, "#R %d %ld", &file_rvnum, &ts) == 2) {
|
||||
if (file_rvnum == (int)rvnum) {
|
||||
/* Skip old block completely until and including '.' line */
|
||||
while (fgets(line, sizeof(line), in)) {
|
||||
if (line[0] == '.') {
|
||||
/* consume it and break */
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue; /* do NOT write skipped lines */
|
||||
}
|
||||
}
|
||||
}
|
||||
fputs(line, out); /* keep unrelated lines */
|
||||
}
|
||||
fclose(in);
|
||||
}
|
||||
|
||||
/* Append new block */
|
||||
fprintf(out, "#R %d %ld\n", rvnum, (long)time(0));
|
||||
|
||||
RS_write_room_mobs(out, rnum);
|
||||
|
||||
for (struct obj_data *obj = world[rnum].contents; obj; obj = obj->next_content)
|
||||
write_one_object(out, obj);
|
||||
|
||||
/* Always terminate block */
|
||||
fprintf(out, ".\n");
|
||||
|
||||
if (fclose(out) != 0) {
|
||||
mudlog(NRM, LVL_IMMORT, TRUE,
|
||||
"SYSERR: RoomSave: fclose(%s) failed: %s",
|
||||
tmp, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (rename(tmp, path) != 0) {
|
||||
mudlog(NRM, LVL_IMMORT, TRUE,
|
||||
"SYSERR: RoomSave: rename(%s -> %s) failed: %s",
|
||||
tmp, path, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* --- M/E/G/P load helpers (mob restore) -------------------------------- */
|
||||
|
||||
struct rs_load_ctx {
|
||||
room_rnum rnum;
|
||||
struct char_data *cur_mob; /* last mob spawned by 'M' */
|
||||
struct obj_data *stack[16]; /* container stack by depth for 'P' */
|
||||
};
|
||||
|
||||
static struct obj_data *RS_create_obj_by_vnum(obj_vnum ov) {
|
||||
obj_rnum ornum;
|
||||
if (ov <= 0) return NULL;
|
||||
ornum = real_object(ov);
|
||||
if (ornum == NOTHING) return NULL;
|
||||
return read_object(ornum, REAL);
|
||||
}
|
||||
|
||||
static struct char_data *RS_create_mob_by_vnum(mob_vnum mv) {
|
||||
mob_rnum mrnum;
|
||||
if (mv <= 0) return NULL;
|
||||
mrnum = real_mobile(mv);
|
||||
if (mrnum == NOBODY) return NULL;
|
||||
return read_mobile(mrnum, REAL);
|
||||
}
|
||||
|
||||
|
||||
/* Reset the loader context before reading a new #R block */
|
||||
static void RS_ctx_clear(struct rs_load_ctx *ctx) {
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
/* DO NOT reset ctx->rnum — each #R block sets this explicitly
|
||||
* before parsing mobs or objects. Resetting it causes cross-room
|
||||
* bleed (e.g., mobs from one room spawning in another).
|
||||
*/
|
||||
|
||||
ctx->cur_mob = NULL;
|
||||
|
||||
/* Clear all container stack pointers */
|
||||
for (int i = 0; i < 16; i++)
|
||||
ctx->stack[i] = NULL;
|
||||
}
|
||||
|
||||
/* Optional autosave hook (invoked by limits.c:point_update). */
|
||||
void RoomSave_autosave_tick(void) {
|
||||
/* Iterate all rooms; only save flagged ones. */
|
||||
for (room_rnum rnum = 0; rnum <= top_of_world; ++rnum) {
|
||||
if (ROOM_FLAGGED(rnum, ROOM_SAVE))
|
||||
RoomSave_now(rnum);
|
||||
}
|
||||
}
|
||||
|
||||
/* Forward decl so RS_parse_mob_line can use it without implicit declaration */
|
||||
static void RS_stack_clear(struct rs_load_ctx *ctx);
|
||||
|
||||
/* Handle one line inside a #R block. Returns 1 if handled here. */
|
||||
static int RS_parse_mob_line(struct rs_load_ctx *ctx, char *line)
|
||||
{
|
||||
if (!line) return 0;
|
||||
while (*line == ' ' || *line == '\t') ++line;
|
||||
if (!*line) return 0;
|
||||
|
||||
switch (line[0]) {
|
||||
case 'M': {
|
||||
mob_vnum mv;
|
||||
if (sscanf(line+1, " %d", (int *)&mv) != 1) return 0;
|
||||
|
||||
ctx->cur_mob = RS_create_mob_by_vnum(mv);
|
||||
if (!ctx->cur_mob) return 1;
|
||||
|
||||
/* Place in the block's room */
|
||||
char_to_room(ctx->cur_mob, ctx->rnum);
|
||||
|
||||
/* Safety: if anything put it elsewhere, force it back */
|
||||
if (IN_ROOM(ctx->cur_mob) != ctx->rnum)
|
||||
char_to_room(ctx->cur_mob, ctx->rnum);
|
||||
|
||||
RS_stack_clear(ctx); /* clear only container stack */
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 'E': { /* E <wear_pos> <obj_vnum> */
|
||||
int pos; obj_vnum ov; struct obj_data *obj;
|
||||
if (!ctx->cur_mob) return 1; /* orphan -> ignore */
|
||||
if (sscanf(line+1, " %d %d", &pos, (int *)&ov) != 2) return 0;
|
||||
obj = RS_create_obj_by_vnum(ov);
|
||||
if (!obj) return 1;
|
||||
|
||||
if (pos < 0 || pos >= NUM_WEARS) pos = WEAR_HOLD; /* clamp */
|
||||
equip_char(ctx->cur_mob, obj, pos);
|
||||
|
||||
/* Reset ONLY container stack for following P-lines; keep cur_mob */
|
||||
RS_stack_clear(ctx);
|
||||
ctx->stack[0] = obj;
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 'G': { /* G <obj_vnum> */
|
||||
obj_vnum ov; struct obj_data *obj;
|
||||
if (!ctx->cur_mob) return 1; /* orphan -> ignore */
|
||||
if (sscanf(line+1, " %d", (int *)&ov) != 1) return 0;
|
||||
obj = RS_create_obj_by_vnum(ov);
|
||||
if (!obj) return 1;
|
||||
|
||||
obj_to_char(obj, ctx->cur_mob);
|
||||
|
||||
RS_stack_clear(ctx);
|
||||
ctx->stack[0] = obj;
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 'P': { /* P <depth> <obj_vnum> : put into last obj at (depth-1) */
|
||||
int depth; obj_vnum ov; struct obj_data *parent, *obj;
|
||||
if (sscanf(line+1, " %d %d", &depth, (int *)&ov) != 2) return 0;
|
||||
if (depth <= 0 || depth >= (int)(sizeof(ctx->stack)/sizeof(ctx->stack[0])))
|
||||
return 1;
|
||||
parent = ctx->stack[depth-1];
|
||||
if (!parent) return 1;
|
||||
|
||||
obj = RS_create_obj_by_vnum(ov);
|
||||
if (!obj) return 1;
|
||||
obj_to_obj(obj, parent);
|
||||
|
||||
ctx->stack[depth] = obj;
|
||||
{ int d; for (d = depth+1; d < (int)(sizeof(ctx->stack)/sizeof(ctx->stack[0])); ++d) ctx->stack[d] = NULL; }
|
||||
return 1;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Forward decls for mob restore helpers */
|
||||
static void RS_stack_clear(struct rs_load_ctx *ctx);
|
||||
|
||||
void RoomSave_boot(void)
|
||||
{
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
|
||||
ensure_dir_exists(ROOMSAVE_PREFIX);
|
||||
|
||||
dirp = opendir(ROOMSAVE_PREFIX);
|
||||
if (!dirp) {
|
||||
mudlog(NRM, LVL_IMMORT, TRUE,
|
||||
"SYSERR: RoomSave_boot: cannot open %s", ROOMSAVE_PREFIX);
|
||||
return;
|
||||
}
|
||||
|
||||
log("RoomSave: scanning %s for *.rsv", ROOMSAVE_PREFIX);
|
||||
|
||||
while ((dp = readdir(dirp))) {
|
||||
size_t n = strlen(dp->d_name);
|
||||
if (n < 5) continue; /* skip . and .. */
|
||||
if (strcmp(dp->d_name + n - 4, ROOMSAVE_EXT) != 0) continue;
|
||||
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
int wn = snprintf(path, sizeof(path), "%s%s", ROOMSAVE_PREFIX, dp->d_name);
|
||||
if (wn < 0 || wn >= (int)sizeof(path)) {
|
||||
mudlog(NRM, LVL_IMMORT, TRUE,
|
||||
"SYSERR: RoomSave_boot: path too long: %s%s",
|
||||
ROOMSAVE_PREFIX, dp->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
FILE *fl = fopen(path, "r");
|
||||
if (!fl) {
|
||||
mudlog(NRM, LVL_IMMORT, TRUE,
|
||||
"SYSERR: RoomSave_boot: fopen(%s) failed: %s",
|
||||
path, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
log("RoomSave: reading %s", path);
|
||||
|
||||
int blocks = 0;
|
||||
int restored_objs_total = 0;
|
||||
int restored_mobs_total = 0;
|
||||
|
||||
/* Outer loop: read every #R block in this .rsv file */
|
||||
char line[512];
|
||||
while (fgets(line, sizeof(line), fl)) {
|
||||
|
||||
/* Skip until a valid #R header */
|
||||
if (strncmp(line, "#R ", 3) != 0)
|
||||
continue;
|
||||
|
||||
/* Parse header line */
|
||||
int rvnum; long ts;
|
||||
if (sscanf(line, "#R %d %ld", &rvnum, &ts) != 2) {
|
||||
mudlog(NRM, LVL_IMMORT, TRUE,
|
||||
"RoomSave: malformed #R header in %s: %s", path, line);
|
||||
/* Skip malformed block */
|
||||
while (fgets(line, sizeof(line), fl))
|
||||
if (line[0] == '.') break;
|
||||
continue;
|
||||
}
|
||||
|
||||
blocks++;
|
||||
|
||||
/* Resolve the room for this block */
|
||||
room_rnum rnum = real_room((room_vnum)rvnum);
|
||||
if (rnum == NOWHERE) {
|
||||
mudlog(NRM, LVL_IMMORT, FALSE,
|
||||
"RoomSave: unknown room vnum %d in %s (skipping)",
|
||||
rvnum, path);
|
||||
/* Skip to next block */
|
||||
while (fgets(line, sizeof(line), fl))
|
||||
if (line[0] == '.') break;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Clear this room's ground contents before restoring */
|
||||
while (world[rnum].contents)
|
||||
extract_obj(world[rnum].contents);
|
||||
|
||||
/* Clear and set mob context for this block */
|
||||
struct rs_load_ctx mctx;
|
||||
RS_ctx_clear(&mctx);
|
||||
mctx.rnum = rnum;
|
||||
|
||||
/* Per-block counts */
|
||||
int count_objs = 0, count_mobs = 0;
|
||||
char inner[512];
|
||||
|
||||
/* Inner loop: read this #R block until '.' */
|
||||
while (fgets(inner, sizeof(inner), fl)) {
|
||||
|
||||
/* Trim spaces */
|
||||
while (inner[0] == ' ' || inner[0] == '\t')
|
||||
memmove(inner, inner + 1, strlen(inner));
|
||||
|
||||
/* Stop at end of block */
|
||||
if (inner[0] == '.')
|
||||
break;
|
||||
|
||||
/* Defensive: stop if another #R starts (malformed file) */
|
||||
if (!strncmp(inner, "#R ", 3)) {
|
||||
fseek(fl, -((long)strlen(inner)), SEEK_CUR);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Handle object blocks */
|
||||
if (inner[0] == 'O') {
|
||||
long pos = ftell(fl);
|
||||
fseek(fl, pos - strlen(inner), SEEK_SET);
|
||||
struct obj_data *list = roomsave_read_list(fl);
|
||||
for (struct obj_data *it = list, *next; it; it = next) {
|
||||
next = it->next_content;
|
||||
it->next_content = NULL;
|
||||
obj_to_room(it, rnum);
|
||||
count_objs++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Handle mob & equipment/inventory */
|
||||
if (RS_parse_mob_line(&mctx, inner)) {
|
||||
if (inner[0] == 'M')
|
||||
count_mobs++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Unknown token: ignore gracefully */
|
||||
}
|
||||
|
||||
restored_objs_total += count_objs;
|
||||
restored_mobs_total += count_mobs;
|
||||
|
||||
if (count_mobs > 0)
|
||||
log("RoomSave: room %d <- %d object(s) and %d mob(s)",
|
||||
rvnum, count_objs, count_mobs);
|
||||
else
|
||||
log("RoomSave: room %d <- %d object(s)", rvnum, count_objs);
|
||||
}
|
||||
|
||||
log("RoomSave: finished %s (blocks=%d, objects=%d, mobs=%d)",
|
||||
path, blocks, restored_objs_total, restored_mobs_total);
|
||||
|
||||
fclose(fl);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
}
|
||||
|
||||
/* ======== MOB SAVE: write NPCs and their equipment/inventory ========== */
|
||||
|
||||
/* Depth-aware writer for container contents under a parent object.
|
||||
* Writes: P <depth> <obj_vnum>
|
||||
* depth starts at 1 for direct children. */
|
||||
static void RS_write_P_chain(FILE *fp, struct obj_data *parent, int depth) {
|
||||
struct obj_data *c;
|
||||
for (c = parent->contains; c; c = c->next_content) {
|
||||
obj_vnum cv = GET_OBJ_VNUM(c);
|
||||
if (cv <= 0) continue; /* skip non-proto / invalid */
|
||||
fprintf(fp, "P %d %d\n", depth, (int)cv);
|
||||
if (c->contains)
|
||||
RS_write_P_chain(fp, c, depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Writes: E <wear_pos> <obj_vnum> (then P-chain) */
|
||||
static void RS_write_mob_equipment(FILE *fp, struct char_data *mob) {
|
||||
int w;
|
||||
for (w = 0; w < NUM_WEARS; ++w) {
|
||||
struct obj_data *eq = GET_EQ(mob, w);
|
||||
if (!eq) continue;
|
||||
if (GET_OBJ_VNUM(eq) <= 0) continue;
|
||||
fprintf(fp, "E %d %d\n", w, (int)GET_OBJ_VNUM(eq));
|
||||
if (eq->contains) RS_write_P_chain(fp, eq, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Writes: G <obj_vnum> for inventory items (then P-chain) */
|
||||
static void RS_write_mob_inventory(FILE *fp, struct char_data *mob) {
|
||||
struct obj_data *o;
|
||||
for (o = mob->carrying; o; o = o->next_content) {
|
||||
if (GET_OBJ_VNUM(o) <= 0) continue;
|
||||
fprintf(fp, "G %d\n", (int)GET_OBJ_VNUM(o));
|
||||
if (o->contains) RS_write_P_chain(fp, o, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Top-level writer: for each NPC in room, emit:
|
||||
* M <mob_vnum>
|
||||
* [E ...]*
|
||||
* [G ...]*
|
||||
* (Players are ignored.) */
|
||||
static void RS_write_room_mobs(FILE *out, room_rnum rnum) {
|
||||
struct char_data *mob;
|
||||
for (mob = world[rnum].people; mob; mob = mob->next_in_room) {
|
||||
if (!IS_NPC(mob)) continue;
|
||||
if (GET_MOB_VNUM(mob) <= 0) continue;
|
||||
fprintf(out, "M %d\n", (int)GET_MOB_VNUM(mob));
|
||||
RS_write_mob_equipment(out, mob);
|
||||
RS_write_mob_inventory(out, mob);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear only the container stack, NOT cur_mob */
|
||||
static void RS_stack_clear(struct rs_load_ctx *ctx) {
|
||||
int i;
|
||||
for (i = 0; i < (int)(sizeof(ctx->stack)/sizeof(ctx->stack[0])); ++i)
|
||||
ctx->stack[i] = NULL;
|
||||
}
|
||||
42
src/sedit.c
42
src/sedit.c
|
|
@ -31,6 +31,7 @@ static void sedit_shop_flags_menu(struct descriptor_data *d);
|
|||
static void sedit_no_trade_menu(struct descriptor_data *d);
|
||||
static void sedit_types_menu(struct descriptor_data *d);
|
||||
static void sedit_disp_menu(struct descriptor_data *d);
|
||||
static void format_notrade_classes(bitvector_t flags, char *out, size_t outsz);
|
||||
|
||||
|
||||
void sedit_save_internally(struct descriptor_data *d)
|
||||
|
|
@ -44,6 +45,34 @@ static void sedit_save_to_disk(int num)
|
|||
save_shops(num);
|
||||
}
|
||||
|
||||
static void 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);
|
||||
}
|
||||
|
||||
/* utility functions */
|
||||
ACMD(do_oasis_sedit)
|
||||
{
|
||||
|
|
@ -346,11 +375,12 @@ static void sedit_no_trade_menu(struct descriptor_data *d)
|
|||
|
||||
get_char_colors(d->character);
|
||||
clear_screen(d);
|
||||
for (i = 0; i < NUM_TRADERS; i++) {
|
||||
write_to_output(d, "%s%2d%s) %-20.20s %s", grn, i + 1, nrm, trade_letters[i],
|
||||
for (i = 0; i < NUM_TRADE_CLASSES; i++) {
|
||||
write_to_output(d, "%s%2d%s) %-20.20s %s", grn, i + 1, nrm,
|
||||
trade_letters[TRADE_CLASS_START + i],
|
||||
!(++count % 2) ? "\r\n" : "");
|
||||
}
|
||||
sprintbit(S_NOTRADE(OLC_SHOP(d)), trade_letters, bits, sizeof(bits));
|
||||
format_notrade_classes(S_NOTRADE(OLC_SHOP(d)), bits, sizeof(bits));
|
||||
write_to_output(d, "\r\nCurrently won't trade with: %s%s%s\r\n"
|
||||
"Enter choice : ", cyn, bits, nrm);
|
||||
OLC_MODE(d) = SEDIT_NOTRADE;
|
||||
|
|
@ -382,7 +412,7 @@ static void sedit_disp_menu(struct descriptor_data *d)
|
|||
get_char_colors(d->character);
|
||||
|
||||
clear_screen(d);
|
||||
sprintbit(S_NOTRADE(shop), trade_letters, buf1, sizeof(buf1));
|
||||
format_notrade_classes(S_NOTRADE(shop), buf1, sizeof(buf1));
|
||||
sprintbit(S_BITVECTOR(shop), shop_bits, buf2, sizeof(buf2));
|
||||
write_to_output(d,
|
||||
"-- Shop Number : [%s%d%s]\r\n"
|
||||
|
|
@ -756,8 +786,8 @@ void sedit_parse(struct descriptor_data *d, char *arg)
|
|||
}
|
||||
break;
|
||||
case SEDIT_NOTRADE:
|
||||
if ((i = LIMIT(atoi(arg), 0, NUM_TRADERS)) > 0) {
|
||||
TOGGLE_BIT(S_NOTRADE(OLC_SHOP(d)), 1 << (i - 1));
|
||||
if ((i = LIMIT(atoi(arg), 0, NUM_TRADE_CLASSES)) > 0) {
|
||||
TOGGLE_BIT(S_NOTRADE(OLC_SHOP(d)), 1 << (TRADE_CLASS_START + i - 1));
|
||||
sedit_no_trade_menu(d);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,24 @@
|
|||
/**
|
||||
* @file roomsave.h
|
||||
* Core structures used within the core mud code.
|
||||
*
|
||||
* An addition to the core tbaMUD source code distribution, which is a derivative
|
||||
* of, and continuation of, CircleMUD.
|
||||
*
|
||||
* All rights reserved. See license for complete information.
|
||||
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University
|
||||
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.
|
||||
* @file set.h
|
||||
* Builder room/object creation and utility headers.
|
||||
*
|
||||
* This set of code was not originally part of the circlemud distribution.
|
||||
*/
|
||||
#ifndef ROOMSAVE_H_
|
||||
#define ROOMSAVE_H_
|
||||
|
||||
#include "conf.h"
|
||||
#include "sysdep.h"
|
||||
#ifndef SET_H
|
||||
#define SET_H
|
||||
|
||||
#include "structs.h"
|
||||
|
||||
ACMD(do_rset);
|
||||
ACMD(do_rcreate);
|
||||
ACMD(do_ocreate);
|
||||
ACMD(do_mcreate);
|
||||
ACMD(do_oset);
|
||||
ACMD(do_osave);
|
||||
ACMD(do_msave);
|
||||
ACMD(do_rsave);
|
||||
|
||||
/* Boot-time loader: scans ROOMSAVE_DIR and restores contents into rooms. */
|
||||
void RoomSave_boot(void);
|
||||
|
||||
|
|
@ -32,4 +35,4 @@ void RoomSave_mark_dirty_room(room_rnum rnum);
|
|||
/* For container edits: find the room an object ultimately lives in */
|
||||
room_rnum RoomSave_room_of_obj(struct obj_data *obj);
|
||||
|
||||
#endif /* ROOMSAVE_H_ */
|
||||
#endif
|
||||
19
src/shop.c
19
src/shop.c
|
|
@ -29,9 +29,9 @@
|
|||
/* Global variables definitions used externally */
|
||||
/* Constant list for printing out who we sell to */
|
||||
const char *trade_letters[] = {
|
||||
"Good", /* First, the alignment based ones */
|
||||
"Evil",
|
||||
"Neutral",
|
||||
"RESERVED1",
|
||||
"RESERVED2",
|
||||
"RESERVED3",
|
||||
"Sorceror", /* Then the class based ones */
|
||||
"Cleric",
|
||||
"Rogue",
|
||||
|
|
@ -119,13 +119,6 @@ static int is_ok_char(struct char_data *keeper, struct char_data *ch, int shop_n
|
|||
if (IS_GOD(ch))
|
||||
return (TRUE);
|
||||
|
||||
if ((IS_GOOD(ch) && NOTRADE_GOOD(shop_nr)) ||
|
||||
(IS_EVIL(ch) && NOTRADE_EVIL(shop_nr)) ||
|
||||
(IS_NEUTRAL(ch) && NOTRADE_NEUTRAL(shop_nr))) {
|
||||
snprintf(buf, sizeof(buf), "%s %s", GET_NAME(ch), MSG_NO_SELL_ALIGN);
|
||||
do_tell(keeper, buf, cmd_tell, 0);
|
||||
return (FALSE);
|
||||
}
|
||||
if (IS_NPC(ch))
|
||||
return (TRUE);
|
||||
|
||||
|
|
@ -1361,7 +1354,7 @@ void assign_the_shopkeepers(void)
|
|||
|
||||
static char *customer_string(int shop_nr, int detailed)
|
||||
{
|
||||
int sindex = 0, flag = 1, nlen;
|
||||
int sindex = TRADE_CLASS_START, flag = (1 << TRADE_CLASS_START), nlen;
|
||||
size_t len = 0;
|
||||
static char buf[256];
|
||||
|
||||
|
|
@ -1433,7 +1426,7 @@ static void list_all_shops(struct char_data *ch)
|
|||
static void list_detailed_shop(struct char_data *ch, int shop_nr)
|
||||
{
|
||||
struct char_data *k;
|
||||
int sindex, column, flag = 1, found = 0;
|
||||
int sindex, column, flag = (1 << TRADE_CLASS_START), found = 0;
|
||||
/* char *ptrsave; */
|
||||
|
||||
send_to_char(ch, "Vnum: [%5d], Rnum: [%5d]\r\n", SHOP_NUM(shop_nr), shop_nr + 1);
|
||||
|
|
@ -1484,7 +1477,7 @@ static void list_detailed_shop(struct char_data *ch, int shop_nr)
|
|||
/* send_to_char(ch, "Customers: %s\r\n", (ptrsave = customer_string(shop_nr, TRUE)) ? ptrsave : "None"); */
|
||||
send_to_char(ch, "Customers: ");
|
||||
column = 12; /* ^^^ strlen ^^^ */
|
||||
for (sindex = 0; *trade_letters[sindex] != '\n'; sindex++) {
|
||||
for (sindex = TRADE_CLASS_START; *trade_letters[sindex] != '\n'; sindex++) {
|
||||
char buf1[128];
|
||||
int linelen;
|
||||
|
||||
|
|
|
|||
13
src/shop.h
13
src/shop.h
|
|
@ -74,9 +74,9 @@ struct shop_data {
|
|||
#define LIST_ROOM 2
|
||||
|
||||
/* Whom will we not trade with (bitvector for SHOP_TRADE_WITH()) */
|
||||
#define TRADE_NOGOOD (1 << 0)
|
||||
#define TRADE_NOEVIL (1 << 1)
|
||||
#define TRADE_NONEUTRAL (1 << 2)
|
||||
#define TRADE_RESERVED1 (1 << 0)
|
||||
#define TRADE_RESERVED2 (1 << 1)
|
||||
#define TRADE_RESERVED3 (1 << 2)
|
||||
#define TRADE_NOSORCEROR (1 << 3)
|
||||
#define TRADE_NOCLERIC (1 << 4)
|
||||
#define TRADE_NOROGUE (1 << 5)
|
||||
|
|
@ -87,6 +87,9 @@ struct shop_data {
|
|||
#define TRADE_NODRUID (1 << 10)
|
||||
/** Total number of trade types */
|
||||
#define NUM_TRADERS 11
|
||||
#define TRADE_RESERVED_COUNT 3
|
||||
#define TRADE_CLASS_START TRADE_RESERVED_COUNT
|
||||
#define NUM_TRADE_CLASSES (NUM_TRADERS - TRADE_RESERVED_COUNT)
|
||||
|
||||
struct stack_data {
|
||||
int data[100];
|
||||
|
|
@ -123,9 +126,6 @@ struct stack_data {
|
|||
#define SHOP_SELLPROFIT(i) (shop_index[(i)].profit_sell)
|
||||
#define SHOP_FUNC(i) (shop_index[(i)].func)
|
||||
|
||||
#define NOTRADE_GOOD(i) (IS_SET(SHOP_TRADE_WITH((i)), TRADE_NOGOOD))
|
||||
#define NOTRADE_EVIL(i) (IS_SET(SHOP_TRADE_WITH((i)), TRADE_NOEVIL))
|
||||
#define NOTRADE_NEUTRAL(i) (IS_SET(SHOP_TRADE_WITH((i)), TRADE_NONEUTRAL))
|
||||
#define NOTRADE_SORCEROR(i) (IS_SET(SHOP_TRADE_WITH((i)), TRADE_NOSORCEROR))
|
||||
#define NOTRADE_CLERIC(i) (IS_SET(SHOP_TRADE_WITH((i)), TRADE_NOCLERIC))
|
||||
#define NOTRADE_ROGUE(i) (IS_SET(SHOP_TRADE_WITH((i)), TRADE_NOROGUE))
|
||||
|
|
@ -153,7 +153,6 @@ struct stack_data {
|
|||
#define MSG_CLOSED_FOR_DAY "Sorry, come back tomorrow."
|
||||
#define MSG_NO_STEAL_HERE "$n is a bloody thief!"
|
||||
#define MSG_NO_SEE_CHAR "I don't trade with someone I can't see!"
|
||||
#define MSG_NO_SELL_ALIGN "Get out of here before I call the guards!"
|
||||
#define MSG_NO_SELL_CLASS "We don't serve your kind here!"
|
||||
#define MSG_NO_USED_WANDSTAFF "I don't buy used up wands or staves!"
|
||||
#define MSG_CANT_KILL_KEEPER "Get out of here before I call the guards!"
|
||||
|
|
|
|||
|
|
@ -81,22 +81,6 @@ static const char *how_good(int percent)
|
|||
return " (superb)";
|
||||
}
|
||||
|
||||
static const char *prac_types[] = {
|
||||
"spell",
|
||||
"skill"
|
||||
};
|
||||
|
||||
/* TO-DO: Dig deeper and figure out if the min/max practice defines can be removed */
|
||||
#define LEARNED_LEVEL 0 /* % known which is considered "learned" */
|
||||
#define MAX_PER_PRAC 1 /* max percent gain in skill per practice */
|
||||
#define MIN_PER_PRAC 2 /* min percent gain in skill per practice */
|
||||
#define PRAC_TYPE 3 /* should it say 'spell' or 'skill'? */
|
||||
|
||||
#define LEARNED(ch) (prac_params[LEARNED_LEVEL][(int)GET_CLASS(ch)])
|
||||
#define MINGAIN(ch) (prac_params[MIN_PER_PRAC][(int)GET_CLASS(ch)])
|
||||
#define MAXGAIN(ch) (prac_params[MAX_PER_PRAC][(int)GET_CLASS(ch)])
|
||||
#define SPLSKL(ch) (prac_types[prac_params[PRAC_TYPE][(int)GET_CLASS(ch)]])
|
||||
|
||||
void list_skills(struct char_data *ch)
|
||||
{
|
||||
const char *overflow = "\r\n**OVERFLOW**\r\n";
|
||||
|
|
@ -104,7 +88,7 @@ void list_skills(struct char_data *ch)
|
|||
size_t len = 0;
|
||||
char buf2[MAX_STRING_LENGTH];
|
||||
|
||||
len = snprintf(buf2, sizeof(buf2), "You know of the following %ss:\r\n", SPLSKL(ch));
|
||||
len = snprintf(buf2, sizeof(buf2), "You know of the following skills:\r\n");
|
||||
|
||||
if (IS_NPC(ch)) {
|
||||
/* NPCs: show only the skills actually assigned to them */
|
||||
|
|
@ -229,7 +213,7 @@ SPECIAL(mayor)
|
|||
break;
|
||||
|
||||
case 'E':
|
||||
act("$n says 'I hereby declare Midgaard closed!'", FALSE, ch, 0, 0, TO_ROOM);
|
||||
act("$n says 'I hereby declare the city closed!'", FALSE, ch, 0, 0, TO_ROOM);
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
|
|
@ -335,13 +319,6 @@ SPECIAL(sorceror)
|
|||
if (GET_LEVEL(ch) > 7 && rand_number(0, 8) == 0)
|
||||
cast_spell(ch, vict, NULL, SPELL_BLINDNESS);
|
||||
|
||||
if (GET_LEVEL(ch) > 12 && rand_number(0, 12) == 0) {
|
||||
if (IS_EVIL(ch))
|
||||
cast_spell(ch, vict, NULL, SPELL_ENERGY_DRAIN);
|
||||
else if (IS_GOOD(ch))
|
||||
cast_spell(ch, vict, NULL, SPELL_DISPEL_EVIL);
|
||||
}
|
||||
|
||||
if (rand_number(0, 4))
|
||||
return (TRUE);
|
||||
|
||||
|
|
@ -504,18 +481,6 @@ SPECIAL(cityguard)
|
|||
for (tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) {
|
||||
if (!CAN_SEE(ch, tch))
|
||||
continue;
|
||||
if (!IS_NPC(tch) && PLR_FLAGGED(tch, PLR_KILLER)) {
|
||||
act("$n screams 'HEY!!! You're one of those PLAYER KILLERS!!!!!!'", FALSE, ch, 0, 0, TO_ROOM);
|
||||
hit(ch, tch, TYPE_UNDEFINED);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
if (!IS_NPC(tch) && PLR_FLAGGED(tch, PLR_THIEF)) {
|
||||
act("$n screams 'HEY!!! You're one of those PLAYER THIEVES!!!!!!'", FALSE, ch, 0, 0, TO_ROOM);
|
||||
hit(ch, tch, TYPE_UNDEFINED);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
if (FIGHTING(tch) && GET_ALIGNMENT(tch) < max_evil && (IS_NPC(tch) || IS_NPC(FIGHTING(tch)))) {
|
||||
max_evil = GET_ALIGNMENT(tch);
|
||||
evil = tch;
|
||||
|
|
|
|||
510
src/species.c
Normal file
510
src/species.c
Normal file
|
|
@ -0,0 +1,510 @@
|
|||
/**
|
||||
* @file species.c
|
||||
* Race/species related configuration, skill bonuses, modifiers, and stat limitations.
|
||||
*
|
||||
* This set of code was not originally part of the circlemud distribution.
|
||||
*/
|
||||
|
||||
#include "conf.h"
|
||||
#include "sysdep.h"
|
||||
|
||||
#include "structs.h"
|
||||
#include "utils.h"
|
||||
#include "db.h"
|
||||
#include "spells.h"
|
||||
#include "species.h"
|
||||
|
||||
struct species_skill_bonus {
|
||||
int skill;
|
||||
int start;
|
||||
};
|
||||
|
||||
/* Keep species ordering in sync with the SPECIES_* defines. */
|
||||
const char *species_types[NUM_SPECIES] = {
|
||||
"Human",
|
||||
"City Elf",
|
||||
"Desert Elf",
|
||||
"Half-Elf",
|
||||
"Dwarf",
|
||||
"Mul",
|
||||
"Half-Giant",
|
||||
"Mantis",
|
||||
"Gith",
|
||||
"Aarakocra",
|
||||
"Dray",
|
||||
"Kenku",
|
||||
"Jozhal",
|
||||
"Pterran",
|
||||
"Tarek",
|
||||
"Aprig",
|
||||
"Carru",
|
||||
"Crodlu",
|
||||
"Erdlu",
|
||||
"Inix",
|
||||
"Jhakar",
|
||||
"Kank",
|
||||
"Mekillot",
|
||||
"Worm",
|
||||
"Renk",
|
||||
"Rat",
|
||||
"Undead",
|
||||
"Dragon"
|
||||
};
|
||||
|
||||
/* PC creation options (1-based ordering in menus). */
|
||||
const int pc_species_list[] = {
|
||||
SPECIES_HUMAN,
|
||||
SPECIES_CITY_ELF,
|
||||
SPECIES_DESERT_ELF,
|
||||
SPECIES_HALF_ELF,
|
||||
SPECIES_DWARF,
|
||||
SPECIES_MUL,
|
||||
SPECIES_HALF_GIANT,
|
||||
SPECIES_MANTIS,
|
||||
SPECIES_GITH,
|
||||
-1
|
||||
};
|
||||
|
||||
struct species_base_points {
|
||||
int hit;
|
||||
int mana;
|
||||
int stamina;
|
||||
};
|
||||
|
||||
static const struct species_base_points species_base_points[NUM_SPECIES] = {
|
||||
{ 100, 90, 100 }, /* Human */
|
||||
{ 90, 110, 90 }, /* City Elf */
|
||||
{ 100, 80, 140 }, /* Desert Elf */
|
||||
{ 95, 90, 95 }, /* Half-Elf */
|
||||
{ 110, 75, 110 }, /* Dwarf */
|
||||
{ 110, 80, 110 }, /* Mul */
|
||||
{ 180, 50, 180 }, /* Half-Giant */
|
||||
{ 90, 90, 90 }, /* Mantis */
|
||||
{ 90, 100, 90 }, /* Gith */
|
||||
{ 90, 90, 90 }, /* Aarakocra */
|
||||
{ 100, 100, 100 }, /* Dray */
|
||||
{ 70, 120, 80 }, /* Kenku */
|
||||
{ 60, 10, 80 }, /* Jozhal */
|
||||
{ 120, 10, 120 }, /* Pterran */
|
||||
{ 100, 60, 100 }, /* Tarek */
|
||||
{ 60, 10, 80 }, /* Aprig */
|
||||
{ 100, 10, 100 }, /* Carru */
|
||||
{ 100, 10, 80 }, /* Crodlu */
|
||||
{ 80, 10, 200 }, /* Erdlu */
|
||||
{ 120, 10, 400 }, /* Inix */
|
||||
{ 75, 10, 75 }, /* Jhakar */
|
||||
{ 100, 10, 300 }, /* Kank */
|
||||
{ 200, 10, 150 }, /* Mekillot */
|
||||
{ 100, 10, 150 }, /* Worm */
|
||||
{ 10, 10, 20 }, /* Renk */
|
||||
{ 10, 10, 20 }, /* Rat */
|
||||
{ 110, 110, 110 }, /* Undead */
|
||||
{ 250, 250, 250 } /* Dragon */
|
||||
};
|
||||
|
||||
static const struct species_skill_bonus species_skill_none[] = {
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
/* Skill percent values map to proficiency tiers via GET_PROFICIENCY(). */
|
||||
static const struct species_skill_bonus species_skill_crodlu[] = {
|
||||
{ SKILL_PERCEPTION, 45 }, /* +3 proficiency */
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
static const struct species_skill_bonus species_skill_jhakar[] = {
|
||||
{ SKILL_PERCEPTION, 45 }, /* +3 proficiency */
|
||||
{ SKILL_STEALTH, 60 }, /* +4 proficiency */
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
/* Per-species skill bonuses.
|
||||
* Usage:
|
||||
* 1) Define a bonus list for a species (see commented example below).
|
||||
* 2) In species_skill_bonuses[], point that species at the new list.
|
||||
* 3) Keep the { -1, 0 } terminator as the final entry.
|
||||
*
|
||||
* Example (commented out):
|
||||
*
|
||||
* static const struct species_skill_bonus species_skill_human[] = {
|
||||
* { SKILL_PERCEPTION, 5 },
|
||||
* { -1, 0 }
|
||||
* };
|
||||
*/
|
||||
static const struct species_skill_bonus *species_skill_bonuses[NUM_SPECIES] = {
|
||||
/* species_skill_human, */ /* Human (example if you enable the list above) */
|
||||
species_skill_none, /* Human */
|
||||
species_skill_none, /* City Elf */
|
||||
species_skill_none, /* Desert Elf */
|
||||
species_skill_none, /* Half-Elf */
|
||||
species_skill_none, /* Dwarf */
|
||||
species_skill_none, /* Mul */
|
||||
species_skill_none, /* Half-Giant */
|
||||
species_skill_none, /* Mantis */
|
||||
species_skill_none, /* Gith */
|
||||
species_skill_none, /* Aarakocra */
|
||||
species_skill_none, /* Dray */
|
||||
species_skill_none, /* Kenku */
|
||||
species_skill_none, /* Jozhal */
|
||||
species_skill_none, /* Pterran */
|
||||
species_skill_none, /* Tarek */
|
||||
species_skill_none, /* Aprig */
|
||||
species_skill_none, /* Carru */
|
||||
species_skill_crodlu, /* Crodlu */
|
||||
species_skill_none, /* Erdlu */
|
||||
species_skill_none, /* Inix */
|
||||
species_skill_jhakar, /* Jhakar */
|
||||
species_skill_none, /* Kank */
|
||||
species_skill_none, /* Mekillot */
|
||||
species_skill_none, /* Worm */
|
||||
species_skill_none, /* Renk */
|
||||
species_skill_none, /* Rat */
|
||||
species_skill_none, /* Undead */
|
||||
species_skill_none /* Dragon */
|
||||
};
|
||||
|
||||
/* Ability minimums by species (STR, DEX, CON, INT, WIS, CHA). Zero = no min. */
|
||||
static const int species_ability_mins[NUM_SPECIES][NUM_ABILITIES] = {
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Human */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* City Elf */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Desert Elf */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Half-Elf */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Dwarf */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Mul */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Half-Giant */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Mantis */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Gith */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Aarakocra */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Dray */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Kenku */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Jozhal */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Pterran */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Tarek */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Aprig */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Carru */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Crodlu */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Erdlu */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Inix */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Jhakar */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Kank */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Mekillot */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Worm */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Renk */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Rat */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Undead */
|
||||
{ 0, 0, 0, 0, 0, 0 } /* Dragon */
|
||||
};
|
||||
|
||||
/* Ability modifiers by species (STR, DEX, CON, INT, WIS, CHA). */
|
||||
static const int species_ability_mods[NUM_SPECIES][NUM_ABILITIES] = {
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Human */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* City Elf */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Desert Elf */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Half-Elf */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Dwarf */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Mul */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Half-Giant */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Mantis */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Gith */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Aarakocra */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Dray */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Kenku */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Jozhal */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Pterran */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Tarek */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Aprig */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Carru */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Crodlu */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Erdlu */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Inix */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Jhakar */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Kank */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Mekillot */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Worm */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Renk */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Rat */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* Undead */
|
||||
{ 0, 0, 0, 0, 0, 0 } /* Dragon */
|
||||
};
|
||||
|
||||
/* Ability caps by species (STR, DEX, CON, INT, WIS, CHA). Zero = no cap. */
|
||||
static const int species_ability_caps[NUM_SPECIES][NUM_ABILITIES] = {
|
||||
{ 14, 14, 14, 14, 14, 14 }, /* Human */
|
||||
{ 10, 18, 10, 14, 16, 14 }, /* City Elf */
|
||||
{ 12, 18, 12, 12, 14, 12 }, /* Desert Elf */
|
||||
{ 13, 16, 13, 13, 15, 10 }, /* Half-Elf */
|
||||
{ 18, 10, 18, 10, 10, 10 }, /* Dwarf */
|
||||
{ 20, 14, 18, 10, 10, 8 }, /* Mul */
|
||||
{ 24, 8, 20, 6, 6, 6 }, /* Half-Giant */
|
||||
{ 14, 14, 16, 10, 12, 6 }, /* Mantis */
|
||||
{ 12, 16, 14, 10, 8, 6 }, /* Gith */
|
||||
{ 13, 16, 14, 13, 13, 13 }, /* Aarakocra */
|
||||
{ 15, 13, 15, 12, 12, 14 }, /* Dray */
|
||||
{ 12, 16, 12, 15, 15, 13 }, /* Kenku */
|
||||
{ 8, 10, 8, 8, 8, 6 }, /* Jozhal */
|
||||
{ 15, 12, 15, 15, 12, 10 }, /* Pterran */
|
||||
{ 17, 13, 18, 10, 10, 6 }, /* Tarek */
|
||||
{ 8, 10, 12, 2, 10, 5 }, /* Aprig */
|
||||
{ 21, 8, 15, 2, 12, 6 }, /* Carru */
|
||||
{ 16, 15, 14, 4, 12, 6 }, /* Crodlu */
|
||||
{ 16, 10, 12, 2, 11, 7 }, /* Erdlu */
|
||||
{ 22, 12, 18, 2, 10, 7 }, /* Inix */
|
||||
{ 17, 15, 16, 3, 12, 7 }, /* Jhakar */
|
||||
{ 18, 10, 14, 2, 10, 4 }, /* Kank */
|
||||
{ 24, 9, 21, 3, 11, 6 }, /* Mekillot */
|
||||
{ 22, 8, 19, 2, 2, 6 }, /* Worm */
|
||||
{ 2, 4, 10, 4, 10, 4 }, /* Renk */
|
||||
{ 2, 11, 9, 2, 10, 4 }, /* Rat */
|
||||
{ 18, 16, 18, 16, 16, 16 }, /* Undead */
|
||||
{ 25, 25, 25, 25, 25, 25 } /* Dragon */
|
||||
};
|
||||
|
||||
const char *get_species_name(int species)
|
||||
{
|
||||
if (species >= 0 && species < NUM_SPECIES)
|
||||
return species_types[species];
|
||||
return "Unassigned";
|
||||
}
|
||||
|
||||
int pc_species_count(void)
|
||||
{
|
||||
int count = 0;
|
||||
while (pc_species_list[count] != -1)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
bool species_is_pc_selectable(int species)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (pc_species_list[i] != -1) {
|
||||
if (pc_species_list[i] == species)
|
||||
return TRUE;
|
||||
i++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int species_from_pc_choice(int choice)
|
||||
{
|
||||
int count = pc_species_count();
|
||||
|
||||
if (choice < 1 || choice > count)
|
||||
return SPECIES_UNDEFINED;
|
||||
return pc_species_list[choice - 1];
|
||||
}
|
||||
|
||||
int species_ability_mod(int species, int ability)
|
||||
{
|
||||
if (species < 0 || species >= NUM_SPECIES)
|
||||
return 0;
|
||||
if (ability < 0 || ability >= NUM_ABILITIES)
|
||||
return 0;
|
||||
return species_ability_mods[species][ability];
|
||||
}
|
||||
|
||||
int species_ability_min(int species, int ability)
|
||||
{
|
||||
if (species < 0 || species >= NUM_SPECIES)
|
||||
return 0;
|
||||
if (ability < 0 || ability >= NUM_ABILITIES)
|
||||
return 0;
|
||||
return species_ability_mins[species][ability];
|
||||
}
|
||||
|
||||
int species_ability_cap(int species, int ability)
|
||||
{
|
||||
if (species < 0 || species >= NUM_SPECIES)
|
||||
return 0;
|
||||
if (ability < 0 || ability >= NUM_ABILITIES)
|
||||
return 0;
|
||||
return species_ability_caps[species][ability];
|
||||
}
|
||||
|
||||
bool get_species_base_points(int species, int *hit, int *mana, int *stamina)
|
||||
{
|
||||
if (species < 0 || species >= NUM_SPECIES)
|
||||
return FALSE;
|
||||
|
||||
if (hit)
|
||||
*hit = species_base_points[species].hit;
|
||||
if (mana)
|
||||
*mana = species_base_points[species].mana;
|
||||
if (stamina)
|
||||
*stamina = species_base_points[species].stamina;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void apply_species_ranges(struct char_data *ch)
|
||||
{
|
||||
int species;
|
||||
int cap, min;
|
||||
|
||||
if (!ch)
|
||||
return;
|
||||
|
||||
species = GET_SPECIES(ch);
|
||||
if (species < 0 || species >= NUM_SPECIES)
|
||||
return;
|
||||
|
||||
min = species_ability_min(species, ABIL_STR);
|
||||
if (min > 0 && ch->real_abils.str < min)
|
||||
ch->real_abils.str = min;
|
||||
cap = species_ability_cap(species, ABIL_STR);
|
||||
if (cap > 0 && ch->real_abils.str > cap)
|
||||
ch->real_abils.str = cap;
|
||||
|
||||
min = species_ability_min(species, ABIL_DEX);
|
||||
if (min > 0 && ch->real_abils.dex < min)
|
||||
ch->real_abils.dex = min;
|
||||
cap = species_ability_cap(species, ABIL_DEX);
|
||||
if (cap > 0 && ch->real_abils.dex > cap)
|
||||
ch->real_abils.dex = cap;
|
||||
|
||||
min = species_ability_min(species, ABIL_CON);
|
||||
if (min > 0 && ch->real_abils.con < min)
|
||||
ch->real_abils.con = min;
|
||||
cap = species_ability_cap(species, ABIL_CON);
|
||||
if (cap > 0 && ch->real_abils.con > cap)
|
||||
ch->real_abils.con = cap;
|
||||
|
||||
min = species_ability_min(species, ABIL_INT);
|
||||
if (min > 0 && ch->real_abils.intel < min)
|
||||
ch->real_abils.intel = min;
|
||||
cap = species_ability_cap(species, ABIL_INT);
|
||||
if (cap > 0 && ch->real_abils.intel > cap)
|
||||
ch->real_abils.intel = cap;
|
||||
|
||||
min = species_ability_min(species, ABIL_WIS);
|
||||
if (min > 0 && ch->real_abils.wis < min)
|
||||
ch->real_abils.wis = min;
|
||||
cap = species_ability_cap(species, ABIL_WIS);
|
||||
if (cap > 0 && ch->real_abils.wis > cap)
|
||||
ch->real_abils.wis = cap;
|
||||
|
||||
min = species_ability_min(species, ABIL_CHA);
|
||||
if (min > 0 && ch->real_abils.cha < min)
|
||||
ch->real_abils.cha = min;
|
||||
cap = species_ability_cap(species, ABIL_CHA);
|
||||
if (cap > 0 && ch->real_abils.cha > cap)
|
||||
ch->real_abils.cha = cap;
|
||||
}
|
||||
|
||||
void apply_species_bonuses(struct char_data *ch)
|
||||
{
|
||||
int species;
|
||||
|
||||
if (!ch)
|
||||
return;
|
||||
|
||||
species = GET_SPECIES(ch);
|
||||
if (species < 0 || species >= NUM_SPECIES)
|
||||
return;
|
||||
|
||||
apply_species_ranges(ch);
|
||||
|
||||
ch->real_abils.str += species_ability_mod(species, ABIL_STR);
|
||||
ch->real_abils.dex += species_ability_mod(species, ABIL_DEX);
|
||||
ch->real_abils.con += species_ability_mod(species, ABIL_CON);
|
||||
ch->real_abils.intel += species_ability_mod(species, ABIL_INT);
|
||||
ch->real_abils.wis += species_ability_mod(species, ABIL_WIS);
|
||||
ch->real_abils.cha += species_ability_mod(species, ABIL_CHA);
|
||||
|
||||
apply_species_ranges(ch);
|
||||
ch->aff_abils = ch->real_abils;
|
||||
}
|
||||
|
||||
void grant_species_skills(struct char_data *ch)
|
||||
{
|
||||
int species;
|
||||
const struct species_skill_bonus *bonus;
|
||||
|
||||
if (!ch)
|
||||
return;
|
||||
|
||||
species = GET_SPECIES(ch);
|
||||
if (species < 0 || species >= NUM_SPECIES)
|
||||
return;
|
||||
|
||||
for (bonus = species_skill_bonuses[species]; bonus->skill != -1; bonus++) {
|
||||
if (bonus->skill >= 0 && bonus->skill <= MAX_SKILLS) {
|
||||
if (GET_SKILL(ch, bonus->skill) < bonus->start)
|
||||
SET_SKILL(ch, bonus->skill, bonus->start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_species_skills(struct char_data *ch, int species)
|
||||
{
|
||||
const struct species_skill_bonus *bonus;
|
||||
|
||||
if (!ch)
|
||||
return;
|
||||
if (species < 0 || species >= NUM_SPECIES)
|
||||
return;
|
||||
|
||||
for (bonus = species_skill_bonuses[species]; bonus->skill != -1; bonus++) {
|
||||
if (bonus->skill >= 0 && bonus->skill <= MAX_SKILLS) {
|
||||
if (GET_SKILL(ch, bonus->skill) <= bonus->start)
|
||||
SET_SKILL(ch, bonus->skill, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_species_bonuses(struct char_data *ch, int species)
|
||||
{
|
||||
if (!ch)
|
||||
return;
|
||||
if (species < 0 || species >= NUM_SPECIES)
|
||||
return;
|
||||
|
||||
ch->real_abils.str -= species_ability_mod(species, ABIL_STR);
|
||||
ch->real_abils.dex -= species_ability_mod(species, ABIL_DEX);
|
||||
ch->real_abils.con -= species_ability_mod(species, ABIL_CON);
|
||||
ch->real_abils.intel -= species_ability_mod(species, ABIL_INT);
|
||||
ch->real_abils.wis -= species_ability_mod(species, ABIL_WIS);
|
||||
ch->real_abils.cha -= species_ability_mod(species, ABIL_CHA);
|
||||
}
|
||||
|
||||
int parse_species(const char *arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!arg || !*arg)
|
||||
return SPECIES_UNDEFINED;
|
||||
|
||||
for (i = 0; i < NUM_SPECIES; i++) {
|
||||
if (!str_cmp(arg, species_types[i]))
|
||||
return i;
|
||||
}
|
||||
|
||||
return SPECIES_UNDEFINED;
|
||||
}
|
||||
|
||||
void update_species(struct char_data *ch, int new_species)
|
||||
{
|
||||
int old_species;
|
||||
|
||||
if (!ch)
|
||||
return;
|
||||
|
||||
old_species = GET_SPECIES(ch);
|
||||
if (old_species == new_species)
|
||||
return;
|
||||
|
||||
if (old_species >= 0 && old_species < NUM_SPECIES) {
|
||||
remove_species_skills(ch, old_species);
|
||||
remove_species_bonuses(ch, old_species);
|
||||
}
|
||||
|
||||
GET_SPECIES(ch) = new_species;
|
||||
|
||||
if (new_species >= 0 && new_species < NUM_SPECIES) {
|
||||
apply_species_bonuses(ch);
|
||||
grant_species_skills(ch);
|
||||
} else {
|
||||
ch->aff_abils = ch->real_abils;
|
||||
}
|
||||
}
|
||||
30
src/species.h
Normal file
30
src/species.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* @file species.h
|
||||
* Race/species related header.
|
||||
*
|
||||
* This set of code was not originally part of the circlemud distribution.
|
||||
*/
|
||||
|
||||
#ifndef _SPECIES_H_
|
||||
#define _SPECIES_H_
|
||||
|
||||
struct char_data;
|
||||
|
||||
const char *get_species_name(int species);
|
||||
int species_from_pc_choice(int choice);
|
||||
int pc_species_count(void);
|
||||
bool species_is_pc_selectable(int species);
|
||||
int species_ability_mod(int species, int ability);
|
||||
int species_ability_min(int species, int ability);
|
||||
int species_ability_cap(int species, int ability);
|
||||
bool get_species_base_points(int species, int *hit, int *mana, int *stamina);
|
||||
|
||||
void apply_species_bonuses(struct char_data *ch);
|
||||
void grant_species_skills(struct char_data *ch);
|
||||
int parse_species(const char *arg);
|
||||
void update_species(struct char_data *ch, int new_species);
|
||||
|
||||
extern const char *species_types[];
|
||||
extern const int pc_species_list[];
|
||||
|
||||
#endif /* _SPECIES_H_ */
|
||||
|
|
@ -795,9 +795,6 @@ void mag_assign_spells(void) {
|
|||
spello(SPELL_DARKNESS, "darkness", 30, 5, 4, POS_STANDING,
|
||||
TAR_IGNORE, FALSE, MAG_ROOMS, NULL);
|
||||
|
||||
spello(SPELL_DETECT_ALIGN, "detect alignment", 20, 10, 2, POS_STANDING,
|
||||
TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS, "You feel less aware.");
|
||||
|
||||
spello(SPELL_DETECT_INVIS, "detect invisibility", 20, 10, 2, POS_STANDING,
|
||||
TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS,
|
||||
"Your eyes stop tingling.");
|
||||
|
|
@ -810,12 +807,6 @@ void mag_assign_spells(void) {
|
|||
TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_MANUAL,
|
||||
"The detect poison wears off.");
|
||||
|
||||
spello(SPELL_DISPEL_EVIL, "dispel evil", 40, 25, 3, POS_FIGHTING,
|
||||
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE, NULL);
|
||||
|
||||
spello(SPELL_DISPEL_GOOD, "dispel good", 40, 25, 3, POS_FIGHTING,
|
||||
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE, NULL);
|
||||
|
||||
spello(SPELL_EARTHQUAKE, "earthquake", 40, 25, 3, POS_FIGHTING,
|
||||
TAR_IGNORE, TRUE, MAG_AREAS, NULL);
|
||||
|
||||
|
|
|
|||
33
src/spells.c
33
src/spells.c
|
|
@ -124,28 +124,6 @@ ASPELL(spell_summon)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!CONFIG_PK_ALLOWED) {
|
||||
if (MOB_FLAGGED(victim, MOB_AGGRESSIVE)) {
|
||||
act("As the words escape your lips and $N travels\r\n"
|
||||
"through time and space towards you, you realize that $E is\r\n"
|
||||
"aggressive and might harm you, so you wisely send $M back.",
|
||||
FALSE, ch, 0, victim, TO_CHAR);
|
||||
return;
|
||||
}
|
||||
if (!IS_NPC(victim) && !PRF_FLAGGED(victim, PRF_SUMMONABLE) &&
|
||||
!PLR_FLAGGED(victim, PLR_KILLER)) {
|
||||
send_to_char(victim, "%s just tried to summon you to: %s.\r\n"
|
||||
"This failed because you have summon protection on.\r\n"
|
||||
"Type NOSUMMON to allow other players to summon you.\r\n",
|
||||
GET_NAME(ch), world[IN_ROOM(ch)].name);
|
||||
|
||||
send_to_char(ch, "You failed because %s has summon protection on.\r\n", GET_NAME(victim));
|
||||
mudlog(BRF, MAX(LVL_IMMORT, MAX(GET_INVIS_LEV(ch), GET_INVIS_LEV(victim))), TRUE,
|
||||
"%s failed summoning %s to %s.", GET_NAME(ch), GET_NAME(victim), world[IN_ROOM(ch)].name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (MOB_FLAGGED(victim, MOB_NOSUMMON) ||
|
||||
(IS_NPC(victim) && mag_savingthrow(victim, SAVING_CHA, save_dc))) {
|
||||
send_to_char(ch, "%s", SUMMON_FAIL);
|
||||
|
|
@ -272,8 +250,6 @@ ASPELL(spell_charm)
|
|||
else if (AFF_FLAGGED(victim, AFF_CHARM) || level < GET_LEVEL(victim))
|
||||
send_to_char(ch, "You fail.\r\n");
|
||||
/* player charming another player - no legal reason for this */
|
||||
else if (!CONFIG_PK_ALLOWED && !IS_NPC(victim))
|
||||
send_to_char(ch, "You fail - shouldn't be doing it anyway.\r\n");
|
||||
else if (circle_follow(victim, ch))
|
||||
send_to_char(ch, "Sorry, following in circles is not allowed.\r\n");
|
||||
else if (mag_savingthrow(victim, SAVING_WIS, save_dc))
|
||||
|
|
@ -412,14 +388,7 @@ ASPELL(spell_enchant_weapon)
|
|||
obj->affected[1].location = APPLY_PROFICIENCY;
|
||||
obj->affected[1].modifier = 1 + (level >= 20);
|
||||
|
||||
if (IS_GOOD(ch)) {
|
||||
SET_BIT_AR(GET_OBJ_EXTRA(obj), ITEM_ANTI_EVIL);
|
||||
act("$p glows blue.", FALSE, ch, obj, 0, TO_CHAR);
|
||||
} else if (IS_EVIL(ch)) {
|
||||
SET_BIT_AR(GET_OBJ_EXTRA(obj), ITEM_ANTI_GOOD);
|
||||
act("$p glows red.", FALSE, ch, obj, 0, TO_CHAR);
|
||||
} else
|
||||
act("$p glows yellow.", FALSE, ch, obj, 0, TO_CHAR);
|
||||
act("$p glows yellow.", FALSE, ch, obj, 0, TO_CHAR);
|
||||
}
|
||||
|
||||
ASPELL(spell_detect_poison)
|
||||
|
|
|
|||
75
src/spells.h
75
src/spells.h
|
|
@ -56,45 +56,42 @@
|
|||
#define SPELL_CURE_CRITIC 15 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_CURE_LIGHT 16 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_CURSE 17 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_DETECT_ALIGN 18 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_DETECT_INVIS 19 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_DETECT_MAGIC 20 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_DETECT_POISON 21 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_DISPEL_EVIL 22 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_EARTHQUAKE 23 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_ENCHANT_WEAPON 24 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_ENERGY_DRAIN 25 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_FIREBALL 26 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_HARM 27 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_HEAL 28 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_INVISIBLE 29 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_LIGHTNING_BOLT 30 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_LOCATE_OBJECT 31 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_MAGIC_MISSILE 32 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_POISON 33 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_PROT_FROM_EVIL 34 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_REMOVE_CURSE 35 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_SANCTUARY 36 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_SHOCKING_GRASP 37 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_SLEEP 38 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_STRENGTH 39 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_SUMMON 40 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_VENTRILOQUATE 41 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_WORD_OF_RECALL 42 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_REMOVE_POISON 43 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_SENSE_LIFE 44 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_ANIMATE_DEAD 45 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_DISPEL_GOOD 46 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_GROUP_ARMOR 47 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_GROUP_HEAL 48 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_GROUP_RECALL 49 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_INFRAVISION 50 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_WATERWALK 51 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_IDENTIFY 52 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_FLY 53 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_DARKNESS 54
|
||||
#define SPELL_DETECT_INVIS 18 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_DETECT_MAGIC 19 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_DETECT_POISON 20 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_EARTHQUAKE 21 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_ENCHANT_WEAPON 22 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_ENERGY_DRAIN 23 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_FIREBALL 24 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_HARM 25 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_HEAL 26 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_INVISIBLE 27 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_LIGHTNING_BOLT 28 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_LOCATE_OBJECT 29 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_MAGIC_MISSILE 30 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_POISON 31 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_PROT_FROM_EVIL 32 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_REMOVE_CURSE 33 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_SANCTUARY 34 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_SHOCKING_GRASP 35 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_SLEEP 36 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_STRENGTH 37 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_SUMMON 38 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_VENTRILOQUATE 39 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_WORD_OF_RECALL 40 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_REMOVE_POISON 41 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_SENSE_LIFE 42 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_ANIMATE_DEAD 43 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_GROUP_ARMOR 44 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_GROUP_HEAL 45 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_GROUP_RECALL 46 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_INFRAVISION 47 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_WATERWALK 48 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_IDENTIFY 49 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_FLY 50 /* Reserved Skill[] DO NOT CHANGE */
|
||||
#define SPELL_DARKNESS 51
|
||||
/** Total Number of defined spells */
|
||||
#define NUM_SPELLS 54
|
||||
#define NUM_SPELLS 51
|
||||
|
||||
/* Insert new spells here, up to MAX_SPELLS */
|
||||
#define MAX_SPELLS 130
|
||||
|
|
@ -136,7 +133,7 @@
|
|||
|
||||
/* New skills may be added here up to MAX_SKILLS (200) */
|
||||
|
||||
/* NON-PLAYER AND OBJECT SPELLS AND SKILLS: The practice levels for the spells
|
||||
/* NON-PLAYER AND OBJECT SPELLS AND SKILLS: The skill levels for the spells
|
||||
* and skills below are _not_ recorded in the players file; therefore, the
|
||||
* intended use is for spells and skills associated with objects (such as
|
||||
* SPELL_IDENTIFY used with scrolls of identify) or non-players (such as NPC
|
||||
|
|
|
|||
213
src/structs.h
213
src/structs.h
|
|
@ -164,6 +164,38 @@
|
|||
/** Total number of available PC Classes */
|
||||
#define NUM_CLASSES 8
|
||||
|
||||
/* Species */
|
||||
#define SPECIES_UNDEFINED (-1) /**< Species undefined */
|
||||
#define SPECIES_HUMAN 0
|
||||
#define SPECIES_CITY_ELF 1
|
||||
#define SPECIES_DESERT_ELF 2
|
||||
#define SPECIES_HALF_ELF 3
|
||||
#define SPECIES_DWARF 4
|
||||
#define SPECIES_MUL 5
|
||||
#define SPECIES_HALF_GIANT 6
|
||||
#define SPECIES_MANTIS 7
|
||||
#define SPECIES_GITH 8
|
||||
#define SPECIES_AARAKOCRA 9
|
||||
#define SPECIES_DRAY 10
|
||||
#define SPECIES_KENKU 11
|
||||
#define SPECIES_JOZHAL 12
|
||||
#define SPECIES_PTERRAN 13
|
||||
#define SPECIES_TAREK 14
|
||||
#define SPECIES_APRIG 15
|
||||
#define SPECIES_CARRU 16
|
||||
#define SPECIES_CRODLU 17
|
||||
#define SPECIES_ERDLU 18
|
||||
#define SPECIES_INIX 19
|
||||
#define SPECIES_JHAKAR 20
|
||||
#define SPECIES_KANK 21
|
||||
#define SPECIES_MEKILLOT 22
|
||||
#define SPECIES_WORM 23
|
||||
#define SPECIES_RENK 24
|
||||
#define SPECIES_RAT 25
|
||||
#define SPECIES_UNDEAD 26
|
||||
#define SPECIES_DRAGON 27
|
||||
#define NUM_SPECIES 28
|
||||
|
||||
/* NPC classes (currently unused - feel free to implement!) */
|
||||
#define CLASS_OTHER 0 /**< NPC Class Other (or undefined) */
|
||||
#define CLASS_UNDEAD 1 /**< NPC Class Undead */
|
||||
|
|
@ -193,8 +225,8 @@
|
|||
#define NUM_POSITIONS 9
|
||||
|
||||
/* Player flags: used by char_data.char_specials.act */
|
||||
#define PLR_KILLER 0 /**< Player is a player-killer */
|
||||
#define PLR_THIEF 1 /**< Player is a player-thief */
|
||||
#define PLR_UNUSED0 0 /**< Reserved (unused) */
|
||||
#define PLR_UNUSED1 1 /**< Reserved (unused) */
|
||||
#define PLR_FROZEN 2 /**< Player is frozen */
|
||||
#define PLR_DONTSET 3 /**< Don't EVER set (ISNPC bit, set by mud) */
|
||||
#define PLR_WRITING 4 /**< Player writing (board/mail/olc) */
|
||||
|
|
@ -223,9 +255,9 @@
|
|||
#define MOB_AGGRESSIVE 5 /**< Mob auto-attacks everybody nearby */
|
||||
#define MOB_STAY_ZONE 6 /**< Mob shouldn't wander out of zone */
|
||||
#define MOB_WIMPY 7 /**< Mob flees if severely injured */
|
||||
#define MOB_AGGR_EVIL 8 /**< Auto-attack any evil PC's */
|
||||
#define MOB_AGGR_GOOD 9 /**< Auto-attack any good PC's */
|
||||
#define MOB_AGGR_NEUTRAL 10 /**< Auto-attack any neutral PC's */
|
||||
#define MOB_AGGR_RESERVED1 8 /**< Reserved (unused) */
|
||||
#define MOB_AGGR_RESERVED2 9 /**< Reserved (unused) */
|
||||
#define MOB_AGGR_RESERVED3 10 /**< Reserved (unused) */
|
||||
#define MOB_MEMORY 11 /**< remember attackers if attacked */
|
||||
#define MOB_HELPER 12 /**< attack PCs fighting other NPCs */
|
||||
#define MOB_NOCHARM 13 /**< Mob can't be charmed */
|
||||
|
|
@ -235,8 +267,9 @@
|
|||
#define MOB_NOBLIND 17 /**< Mob can't be blinded */
|
||||
#define MOB_NOKILL 18 /**< Mob can't be attacked */
|
||||
#define MOB_NOTDEADYET 19 /**< (R) Mob being extracted */
|
||||
#define MOB_MOUNT 20 /**< Mob can be mounted */
|
||||
|
||||
#define NUM_MOB_FLAGS 19
|
||||
#define NUM_MOB_FLAGS 21
|
||||
|
||||
/* Preference flags: used by char_data.player_specials.pref */
|
||||
#define PRF_BRIEF 0 /**< Room descs won't normally be shown */
|
||||
|
|
@ -245,7 +278,7 @@
|
|||
#define PRF_NOTELL 3 /**< Can't receive tells */
|
||||
#define PRF_DISPHP 4 /**< Display hit points in prompt */
|
||||
#define PRF_DISPMANA 5 /**< Display mana points in prompt */
|
||||
#define PRF_DISPMOVE 6 /**< Display move points in prompt */
|
||||
#define PRF_DISPSTAMINA 6 /**< Display stamina points in prompt */
|
||||
#define PRF_AUTOEXIT 7 /**< Display exits in a room */
|
||||
#define PRF_NOHASSLE 8 /**< Aggr mobs won't attack */
|
||||
#define PRF_QUEST 9 /**< On quest */
|
||||
|
|
@ -279,28 +312,28 @@
|
|||
#define AFF_DONTUSE 0 /**< DON'T USE! This allows 0 to mean "no bits set" in the database */
|
||||
#define AFF_BLIND 1 /**< (R) Char is blind */
|
||||
#define AFF_INVISIBLE 2 /**< Char is invisible */
|
||||
#define AFF_DETECT_ALIGN 3 /**< Char is sensitive to align */
|
||||
#define AFF_DETECT_INVIS 4 /**< Char can see invis chars */
|
||||
#define AFF_DETECT_MAGIC 5 /**< Char is sensitive to magic */
|
||||
#define AFF_SENSE_LIFE 6 /**< Char can sense hidden life */
|
||||
#define AFF_WATERWALK 7 /**< Char can walk on water */
|
||||
#define AFF_SANCTUARY 8 /**< Char protected by sanct */
|
||||
#define AFF_UNUSED 9 /**< (R) Char is grouped */
|
||||
#define AFF_CURSE 10 /**< Char is cursed */
|
||||
#define AFF_INFRAVISION 11 /**< Char can see in dark */
|
||||
#define AFF_POISON 12 /**< (R) Char is poisoned */
|
||||
#define AFF_PROTECT_EVIL 13 /**< Char protected from evil */
|
||||
#define AFF_PROTECT_GOOD 14 /**< Char protected from good */
|
||||
#define AFF_SLEEP 15 /**< (R) Char magically asleep */
|
||||
#define AFF_NOTRACK 16 /**< Char can't be tracked */
|
||||
#define AFF_FLYING 17 /**< Char is flying */
|
||||
#define AFF_SCUBA 18 /**< Room for future expansion */
|
||||
#define AFF_SNEAK 19 /**< Char can move quietly */
|
||||
#define AFF_HIDE 20 /**< Char is hidden */
|
||||
#define AFF_SCAN 21 /**< Actively scanning for hidden threats */
|
||||
#define AFF_CHARM 22 /**< Char is charmed */
|
||||
#define AFF_BANDAGED 23 /**< Character was bandaged recently */
|
||||
#define AFF_LISTEN 24 /**< Actively eavesdropping */
|
||||
#define AFF_DETECT_INVIS 3 /**< Char can see invis chars */
|
||||
#define AFF_DETECT_MAGIC 4 /**< Char is sensitive to magic */
|
||||
#define AFF_SENSE_LIFE 5 /**< Char can sense hidden life */
|
||||
#define AFF_WATERWALK 6 /**< Char can walk on water */
|
||||
#define AFF_SANCTUARY 7 /**< Char protected by sanct */
|
||||
#define AFF_UNUSED 8 /**< (R) Char is grouped */
|
||||
#define AFF_CURSE 9 /**< Char is cursed */
|
||||
#define AFF_INFRAVISION 10 /**< Char can see in dark */
|
||||
#define AFF_POISON 11 /**< (R) Char is poisoned */
|
||||
#define AFF_RESERVED13 12 /**< Reserved (unused) */
|
||||
#define AFF_RESERVED14 13 /**< Reserved (unused) */
|
||||
#define AFF_SLEEP 14 /**< (R) Char magically asleep */
|
||||
#define AFF_NOTRACK 15 /**< Char can't be tracked */
|
||||
#define AFF_FLYING 16 /**< Char is flying */
|
||||
#define AFF_SCUBA 17 /**< Room for future expansion */
|
||||
#define AFF_SNEAK 18 /**< Char can move quietly */
|
||||
#define AFF_HIDE 19 /**< Char is hidden */
|
||||
#define AFF_SCAN 20 /**< Actively scanning for hidden threats */
|
||||
#define AFF_CHARM 21 /**< Char is charmed */
|
||||
#define AFF_BANDAGED 22 /**< Character was bandaged recently */
|
||||
#define AFF_LISTEN 23 /**< Actively eavesdropping */
|
||||
#define AFF_MOUNTED 24 /**< Riding a mount */
|
||||
/** Total number of affect flags */
|
||||
#define NUM_AFF_FLAGS 25
|
||||
|
||||
|
|
@ -313,42 +346,45 @@
|
|||
#define CON_NEWPASSWD 5 /**< New character, create password */
|
||||
#define CON_CNFPASSWD 6 /**< New character, confirm password */
|
||||
#define CON_QSEX 7 /**< Choose character sex */
|
||||
#define CON_QCLASS 8 /**< Choose character class */
|
||||
#define CON_QSHORTDESC 9 /**< Enter a new character short description prompt */
|
||||
#define CON_RMOTD 10 /**< Reading the message of the day */
|
||||
#define CON_MENU 11 /**< At the main menu */
|
||||
#define CON_PLR_DESC 12 /**< Enter a new character description prompt */
|
||||
#define CON_CHPWD_GETOLD 13 /**< Changing passwd: Get old */
|
||||
#define CON_CHPWD_GETNEW 14 /**< Changing passwd: Get new */
|
||||
#define CON_CHPWD_VRFY 15 /**< Changing passwd: Verify new password */
|
||||
#define CON_DELCNF1 16 /**< Character Delete: Confirmation 1 */
|
||||
#define CON_DELCNF2 17 /**< Character Delete: Confirmation 2 */
|
||||
#define CON_DISCONNECT 18 /**< In-game link loss (leave character) */
|
||||
#define CON_OEDIT 19 /**< OLC mode - object editor */
|
||||
#define CON_REDIT 20 /**< OLC mode - room editor */
|
||||
#define CON_ZEDIT 21 /**< OLC mode - zone info editor */
|
||||
#define CON_MEDIT 22 /**< OLC mode - mobile editor */
|
||||
#define CON_SEDIT 23 /**< OLC mode - shop editor */
|
||||
#define CON_TEDIT 24 /**< OLC mode - text editor */
|
||||
#define CON_CEDIT 25 /**< OLC mode - conf editor */
|
||||
#define CON_AEDIT 26 /**< OLC mode - social (action) edit */
|
||||
#define CON_TRIGEDIT 27 /**< OLC mode - trigger edit */
|
||||
#define CON_HEDIT 28 /**< OLC mode - help edit */
|
||||
#define CON_QEDIT 29 /**< OLC mode - quest edit */
|
||||
#define CON_PREFEDIT 30 /**< OLC mode - preference edit */
|
||||
#define CON_IBTEDIT 31 /**< OLC mode - idea/bug/typo edit */
|
||||
#define CON_MSGEDIT 32 /**< OLC mode - message editor */
|
||||
#define CON_PLR_BACKGROUND 33 /**< Entering a new character background */
|
||||
#define CON_GET_PROTOCOL 33 /**< Used at log-in while attempting to get protocols > */
|
||||
#define CON_GET_CONNECT 34 /**< Login connect/disconnect menu */
|
||||
#define CON_GET_ACCOUNT 35 /**< Login with account name */
|
||||
#define CON_ACCOUNT_CNFRM 36 /**< New account, confirm name */
|
||||
#define CON_ACCOUNT_PASSWORD 37 /**< Login with account password */
|
||||
#define CON_ACCOUNT_NEWPASSWD 38 /**< New account, create password */
|
||||
#define CON_ACCOUNT_CNFPASSWD 39 /**< New account, confirm password */
|
||||
#define CON_ACCOUNT_EMAIL 40 /**< New account, optional email */
|
||||
#define CON_ACCOUNT_MENU 41 /**< Account main menu */
|
||||
#define CON_ACCOUNT_LIST 42 /**< Viewing account character list */
|
||||
#define CON_QSPECIES 8 /**< Choose character species */
|
||||
#define CON_QCLASS 9 /**< Choose character class */
|
||||
#define CON_QSTAT_PREF 44 /**< Choose character stat preference order */
|
||||
#define CON_QAGE 45 /**< Choose character age */
|
||||
#define CON_QSHORTDESC 10 /**< Enter a new character short description prompt */
|
||||
#define CON_RMOTD 11 /**< Reading the message of the day */
|
||||
#define CON_MENU 12 /**< At the main menu */
|
||||
#define CON_PLR_DESC 13 /**< Enter a new character description prompt */
|
||||
#define CON_CHPWD_GETOLD 14 /**< Changing passwd: Get old */
|
||||
#define CON_CHPWD_GETNEW 15 /**< Changing passwd: Get new */
|
||||
#define CON_CHPWD_VRFY 16 /**< Changing passwd: Verify new password */
|
||||
#define CON_DELCNF1 17 /**< Character Delete: Confirmation 1 */
|
||||
#define CON_DELCNF2 18 /**< Character Delete: Confirmation 2 */
|
||||
#define CON_DISCONNECT 19 /**< In-game link loss (leave character) */
|
||||
#define CON_OEDIT 20 /**< OLC mode - object editor */
|
||||
#define CON_REDIT 21 /**< OLC mode - room editor */
|
||||
#define CON_ZEDIT 22 /**< OLC mode - zone info editor */
|
||||
#define CON_MEDIT 23 /**< OLC mode - mobile editor */
|
||||
#define CON_SEDIT 24 /**< OLC mode - shop editor */
|
||||
#define CON_TEDIT 25 /**< OLC mode - text editor */
|
||||
#define CON_CEDIT 26 /**< OLC mode - conf editor */
|
||||
#define CON_AEDIT 27 /**< OLC mode - social (action) edit */
|
||||
#define CON_TRIGEDIT 28 /**< OLC mode - trigger edit */
|
||||
#define CON_HEDIT 29 /**< OLC mode - help edit */
|
||||
#define CON_QEDIT 30 /**< OLC mode - quest edit */
|
||||
#define CON_PREFEDIT 31 /**< OLC mode - preference edit */
|
||||
#define CON_IBTEDIT 32 /**< OLC mode - idea/bug/typo edit */
|
||||
#define CON_MSGEDIT 33 /**< OLC mode - message editor */
|
||||
#define CON_PLR_BACKGROUND 34 /**< Entering a new character background */
|
||||
#define CON_GET_PROTOCOL 34 /**< Used at log-in while attempting to get protocols > */
|
||||
#define CON_GET_CONNECT 35 /**< Login connect/disconnect menu */
|
||||
#define CON_GET_ACCOUNT 36 /**< Login with account name */
|
||||
#define CON_ACCOUNT_CNFRM 37 /**< New account, confirm name */
|
||||
#define CON_ACCOUNT_PASSWORD 38 /**< Login with account password */
|
||||
#define CON_ACCOUNT_NEWPASSWD 39 /**< New account, create password */
|
||||
#define CON_ACCOUNT_CNFPASSWD 40 /**< New account, confirm password */
|
||||
#define CON_ACCOUNT_EMAIL 41 /**< New account, optional email */
|
||||
#define CON_ACCOUNT_MENU 42 /**< Account main menu */
|
||||
#define CON_ACCOUNT_LIST 43 /**< Viewing account character list */
|
||||
|
||||
/* OLC States range - used by IS_IN_OLC and IS_PLAYING */
|
||||
#define FIRST_OLC_STATE CON_OEDIT /**< The first CON_ state that is an OLC */
|
||||
|
|
@ -439,23 +475,12 @@
|
|||
#define ITEM_MAGIC 6 /**< Item is magical */
|
||||
#define ITEM_NODROP 7 /**< Item is cursed: can't drop */
|
||||
#define ITEM_BLESS 8 /**< Item is blessed */
|
||||
#define ITEM_ANTI_GOOD 9 /**< Not usable by good people */
|
||||
#define ITEM_ANTI_EVIL 10 /**< Not usable by evil people */
|
||||
#define ITEM_ANTI_NEUTRAL 11 /**< Not usable by neutral people */
|
||||
#define ITEM_ANTI_SORCEROR 12 /**< Not usable by sorcerors */
|
||||
#define ITEM_ANTI_CLERIC 13 /**< Not usable by clerics */
|
||||
#define ITEM_ANTI_ROGUE 14 /**< Not usable by rogues */
|
||||
#define ITEM_ANTI_FIGHTER 15 /**< Not usable by fighters */
|
||||
#define ITEM_ANTI_BARBARIAN 16 /**< Not usable by barbarians */
|
||||
#define ITEM_ANTI_RANGER 17 /**< Not usable by rangers */
|
||||
#define ITEM_ANTI_BARD 18 /**< Not usable by bards */
|
||||
#define ITEM_ANTI_DRUID 19 /**< Not usable by druids */
|
||||
#define ITEM_NOSELL 20 /**< Shopkeepers won't touch it */
|
||||
#define ITEM_QUEST 21 /**< Item is a quest item */
|
||||
#define ITEM_HOOD_UP 22 /**< WORN item hood is currently up */
|
||||
#define ITEM_SKINNED 23 /* Item/corpse can be skinned */
|
||||
#define ITEM_NOSELL 9 /**< Shopkeepers won't touch it */
|
||||
#define ITEM_QUEST 10 /**< Item is a quest item */
|
||||
#define ITEM_HOOD_UP 11 /**< WORN item hood is currently up */
|
||||
#define ITEM_SKINNED 12 /* Item/corpse can be skinned */
|
||||
/** Total number of item flags */
|
||||
#define NUM_ITEM_FLAGS 24
|
||||
#define NUM_ITEM_FLAGS 13
|
||||
|
||||
/* Modifier constants used with obj affects ('A' fields) */
|
||||
#define APPLY_NONE 0 /**< No effect */
|
||||
|
|
@ -472,7 +497,7 @@
|
|||
#define APPLY_CHAR_HEIGHT 11 /**< Apply to height */
|
||||
#define APPLY_MANA 12 /**< Apply to max mana */
|
||||
#define APPLY_HIT 13 /**< Apply to max hit points */
|
||||
#define APPLY_MOVE 14 /**< Apply to max move points */
|
||||
#define APPLY_STAMINA 14 /**< Apply to max stamina points */
|
||||
#define APPLY_COINS 15 /**< Reserved */
|
||||
#define APPLY_EXP 16 /**< Reserved */
|
||||
#define APPLY_AC 17 /**< Apply to Armor Class */
|
||||
|
|
@ -872,7 +897,7 @@ struct time_info_data
|
|||
/** Player specific time information. */
|
||||
struct time_data
|
||||
{
|
||||
time_t birth; /**< Represents the PCs birthday, used to calculate age. */
|
||||
time_t birth; /**< Anchor for calculating mechanical age from played time. */
|
||||
time_t logon; /**< Time of the last logon, used to calculate time played */
|
||||
int played; /**< This is the total accumulated time played in secs */
|
||||
};
|
||||
|
|
@ -907,8 +932,11 @@ struct char_player_data
|
|||
char *background; /**< PC / NPC background / history text */
|
||||
byte sex; /**< PC / NPC sex */
|
||||
byte chclass; /**< PC / NPC class */
|
||||
byte species; /**< PC / NPC species */
|
||||
byte level; /**< PC / NPC level */
|
||||
struct time_data time; /**< PC AGE in days */
|
||||
struct time_data time; /**< Playtime tracking */
|
||||
int roleplay_age; /**< Roleplay age in years */
|
||||
int roleplay_age_year; /**< Last mud year roleplay age was updated */
|
||||
ubyte weight; /**< PC / NPC weight */
|
||||
ubyte height; /**< PC / NPC height */
|
||||
};
|
||||
|
|
@ -945,8 +973,8 @@ struct char_point_data
|
|||
sh_int max_mana; /**< Max mana level */
|
||||
sh_int hit; /**< Curent hit point, or health, level */
|
||||
sh_int max_hit; /**< Max hit point, or health, level */
|
||||
sh_int move; /**< Current move point, or stamina, level */
|
||||
sh_int max_move; /**< Max move point, or stamina, level */
|
||||
sh_int stamina; /**< Current stamina level */
|
||||
sh_int max_stamina; /**< Max stamina level */
|
||||
|
||||
/** Current armor class. Internal use goes from -100 (totally armored) to
|
||||
* 100 (totally naked). Externally expressed as -10 (totally armored) to
|
||||
|
|
@ -978,6 +1006,9 @@ struct char_special_data
|
|||
struct char_data *fighting; /**< Target of fight; else NULL */
|
||||
struct char_data *hunting; /**< Target of NPC hunt; else NULL */
|
||||
struct obj_data *furniture; /**< Object being sat on/in; else NULL */
|
||||
struct char_data *mount; /**< Mount being ridden; else NULL */
|
||||
struct char_data *rider; /**< Rider, if being mounted; else NULL */
|
||||
struct char_data *hitched_to; /**< Person this mount is hitched to; else NULL */
|
||||
struct char_data *next_in_furniture; /**< Next person sitting, else NULL */
|
||||
|
||||
byte position; /**< Standing, fighting, sleeping, etc. */
|
||||
|
|
@ -986,6 +1017,7 @@ struct char_special_data
|
|||
byte carry_items; /**< Number of items carried */
|
||||
int timer; /**< Timer for update */
|
||||
int stealth_check; /* last rolled Stealth value for Hide; 0 = not hiding/opposed */
|
||||
bool custom_ldesc; /* temporary ldesc override from change command */
|
||||
|
||||
struct char_special_data_saved saved; /**< Constants saved for PCs. */
|
||||
};
|
||||
|
|
@ -1013,6 +1045,9 @@ struct player_special_data_saved
|
|||
int quest_counter; /**< Count of targets left to get */
|
||||
time_t lastmotd; /**< Last time player read motd */
|
||||
time_t lastnews; /**< Last time player read news */
|
||||
bool reroll_used; /**< Has the PC used their one-time reroll */
|
||||
time_t reroll_expires; /**< When the reroll review period ends */
|
||||
struct char_ability_data reroll_old_abils; /**< Original stats before reroll */
|
||||
time_t next_skill_gain[MAX_SKILLS+1]; /* indexed by skill/spell number */
|
||||
};
|
||||
|
||||
|
|
@ -1128,6 +1163,10 @@ struct char_data
|
|||
struct group_data *group; /**< Character's Group */
|
||||
|
||||
long pref; /**< unique session id */
|
||||
|
||||
bool stat_pref_use; /**< Use stat preference ordering when rolling abilities */
|
||||
ubyte stat_pref_count; /**< Number of preferred stats entered */
|
||||
ubyte stat_pref_order[NUM_ABILITIES]; /**< Ability order preferences */
|
||||
|
||||
struct list_data * events;
|
||||
};
|
||||
|
|
@ -1347,6 +1386,7 @@ struct recent_player
|
|||
/* NPC loadout helpers */
|
||||
void loadout_free_list(struct mob_loadout **head);
|
||||
void loadout_add_entry(struct mob_loadout **head, obj_vnum vnum, sh_int wear_pos, int qty);
|
||||
void loadout_append_entry(struct mob_loadout **head, obj_vnum vnum, sh_int wear_pos, int qty);
|
||||
struct mob_loadout *loadout_deep_copy(const struct mob_loadout *src);
|
||||
|
||||
/* Furniture defines for object values */
|
||||
|
|
@ -1387,7 +1427,6 @@ struct forage_entry {
|
|||
* variables. */
|
||||
struct game_data
|
||||
{
|
||||
int pk_allowed; /**< Is player killing allowed? */
|
||||
int pt_allowed; /**< Is player thieving allowed? */
|
||||
int level_can_shout; /**< Level player must be to shout. */
|
||||
int tunnel_size; /**< Number of people allowed in a tunnel.*/
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ struct char_point_data_plrtoascii {
|
|||
sh_int max_mana; /* Max mana for PC/NPC */
|
||||
sh_int hit;
|
||||
sh_int max_hit; /* Max hit for PC/NPC */
|
||||
sh_int move;
|
||||
sh_int max_move; /* Max move for PC/NPC */
|
||||
sh_int stamina;
|
||||
sh_int max_stamina; /* Max stamina for PC/NPC */
|
||||
|
||||
sh_int armor; /* Internal -100..100, external -10..10 AC */
|
||||
int coins; /* Money carried */
|
||||
|
|
@ -59,7 +59,7 @@ struct char_point_data_plrtoascii {
|
|||
* in player_special_data.
|
||||
*/
|
||||
struct char_special_data_saved_plrtoascii {
|
||||
int alignment; /* +-1000 for alignments */
|
||||
int alignment;
|
||||
long idnum; /* player's idnum; -1 for mobiles */
|
||||
long /*bitvector_t*/ act; /* act flag for NPC's; player flag for PC's */
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ struct char_special_data_saved_plrtoascii {
|
|||
|
||||
struct player_special_data_saved_plrtoascii {
|
||||
byte skills[MAX_SKILLS+1]; /* array of skills plus skill 0 */
|
||||
byte PADDING0; /* used to be spells_to_learn */
|
||||
byte legacy0; /* legacy unused byte */
|
||||
bool talks[MAX_TONGUE]; /* PC s Tongues 0 for NPC */
|
||||
int wimp_level; /* Below this # of hit points, flee! */
|
||||
byte freeze_level; /* Level of god who froze char, if any */
|
||||
|
|
@ -89,7 +89,7 @@ struct player_special_data_saved_plrtoascii {
|
|||
ubyte spare3;
|
||||
ubyte spare4;
|
||||
ubyte page_length;
|
||||
int spells_to_learn; /* How many can you learn yet this level*/
|
||||
int spare5;
|
||||
int olc_zone;
|
||||
int spare8;
|
||||
int spare9;
|
||||
|
|
@ -212,8 +212,6 @@ void convert(char *filename)
|
|||
|
||||
/* char_special_data_saved */
|
||||
csds = &(player.char_specials_saved);
|
||||
if (csds->alignment != PFDEF_ALIGNMENT)
|
||||
fprintf(outfile, "Alin: %d\n", csds->alignment);
|
||||
fprintf(outfile, "Id : %d\n", (int)csds->idnum);
|
||||
if (csds->act != PFDEF_PLRFLAGS)
|
||||
fprintf(outfile, "Act : %d\n", (int)csds->act);
|
||||
|
|
@ -263,8 +261,6 @@ void convert(char *filename)
|
|||
if (psds->conditions[2] && player.level < LVL_IMMORT &&
|
||||
psds->conditions[DRUNK] != PFDEF_DRUNK)
|
||||
fprintf(outfile, "Drnk: %d\n", (int)psds->conditions[2]);
|
||||
if (psds->spells_to_learn != PFDEF_PRACTICES)
|
||||
fprintf(outfile, "Lern: %d\n", (int)psds->spells_to_learn);
|
||||
|
||||
/* char_ability_data */
|
||||
cad = &(player.abilities);
|
||||
|
|
@ -287,8 +283,8 @@ void convert(char *filename)
|
|||
fprintf(outfile, "Hit : %d/%d\n", cpd->hit, cpd->max_hit);
|
||||
if (cpd->mana != PFDEF_MANA || cpd->max_mana != PFDEF_MAXMANA)
|
||||
fprintf(outfile, "Mana: %d/%d\n", cpd->mana, cpd->max_mana);
|
||||
if (cpd->move != PFDEF_MOVE || cpd->max_move != PFDEF_MAXMOVE)
|
||||
fprintf(outfile, "Move: %d/%d\n", cpd->move, cpd->max_move);
|
||||
if (cpd->stamina != PFDEF_STAMINA || cpd->max_stamina != PFDEF_MAXSTAMINA)
|
||||
fprintf(outfile, "Stam: %d/%d\n", cpd->stamina, cpd->max_stamina);
|
||||
if (cpd->armor != PFDEF_AC)
|
||||
fprintf(outfile, "Ac : %d\n", cpd->armor);
|
||||
if (cpd->coins != PFDEF_COINS)
|
||||
|
|
|
|||
107
src/utils.c
107
src/utils.c
|
|
@ -570,17 +570,24 @@ time_t mud_time_to_secs(struct time_info_data *now)
|
|||
return (time(NULL) - when);
|
||||
}
|
||||
|
||||
/** Calculate a player's MUD age.
|
||||
* @todo The minimum starting age of 17 is hardcoded in this function. Recommend
|
||||
* changing the minimum age to a property (variable) external to this function.
|
||||
time_t get_total_played_seconds(const struct char_data *ch)
|
||||
{
|
||||
time_t played = ch->player.time.played;
|
||||
|
||||
if (ch->desc && STATE(ch->desc) == CON_PLAYING)
|
||||
played += time(0) - ch->player.time.logon;
|
||||
|
||||
return played;
|
||||
}
|
||||
|
||||
/** Calculate a player's mechanical age based on total played time.
|
||||
* @param ch A valid player character. */
|
||||
struct time_info_data *age(struct char_data *ch)
|
||||
{
|
||||
static struct time_info_data player_age;
|
||||
|
||||
player_age = *mud_time_passed(time(0), ch->player.time.birth);
|
||||
|
||||
player_age.year += 17; /* All players start at 17 */
|
||||
time_t played = get_total_played_seconds(ch);
|
||||
player_age = *mud_time_passed(time(0), time(0) - played);
|
||||
|
||||
return (&player_age);
|
||||
}
|
||||
|
|
@ -647,6 +654,8 @@ void stop_follower(struct char_data *ch)
|
|||
}
|
||||
|
||||
ch->master = NULL;
|
||||
if (HITCHED_TO(ch))
|
||||
HITCHED_TO(ch) = NULL;
|
||||
REMOVE_BIT_AR(AFF_FLAGS(ch), AFF_CHARM);
|
||||
}
|
||||
|
||||
|
|
@ -1700,6 +1709,74 @@ const char *get_char_sdesc(const struct char_data *ch)
|
|||
return "someone";
|
||||
}
|
||||
|
||||
void clear_custom_ldesc(struct char_data *ch)
|
||||
{
|
||||
char base_buf[MAX_INPUT_LENGTH];
|
||||
char ldesc[MAX_STRING_LENGTH];
|
||||
const char *base;
|
||||
|
||||
if (!ch || !ch->char_specials.custom_ldesc)
|
||||
return;
|
||||
|
||||
ch->char_specials.custom_ldesc = FALSE;
|
||||
|
||||
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 = NULL;
|
||||
}
|
||||
|
||||
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 is standing here.\r\n", base_buf);
|
||||
ch->player.long_descr = strdup(ldesc);
|
||||
}
|
||||
|
||||
bool build_hidden_ldesc(const struct char_data *ch, char *out, size_t outsz)
|
||||
{
|
||||
char base_buf[MAX_INPUT_LENGTH];
|
||||
const char *base;
|
||||
size_t base_len;
|
||||
const char *suffix;
|
||||
|
||||
if (!out || outsz == 0) return FALSE;
|
||||
*out = '\0';
|
||||
|
||||
if (!ch || !ch->char_specials.custom_ldesc || !ch->player.long_descr)
|
||||
return FALSE;
|
||||
if (GET_POS(ch) != GET_DEFAULT_POS(ch))
|
||||
return FALSE;
|
||||
|
||||
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);
|
||||
|
||||
base_len = strlen(base_buf);
|
||||
if (strncmp(ch->player.long_descr, base_buf, base_len) != 0)
|
||||
return FALSE;
|
||||
|
||||
suffix = ch->player.long_descr + base_len;
|
||||
if (*suffix == ' ')
|
||||
suffix++;
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
snprintf(out, outsz, "A shadowy figure %s", suffix);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* 5e system helpers */
|
||||
|
||||
extern const struct armor_slot armor_slots[]; /* in constants.c */
|
||||
|
|
@ -2074,6 +2151,24 @@ void loadout_add_entry(struct mob_loadout **head, obj_vnum vnum, sh_int wear_pos
|
|||
*head = e;
|
||||
}
|
||||
|
||||
void loadout_append_entry(struct mob_loadout **head, obj_vnum vnum, sh_int wear_pos, int qty) {
|
||||
struct mob_loadout *e = NULL;
|
||||
struct mob_loadout *tail;
|
||||
if (qty < 1) qty = 1;
|
||||
CREATE(e, struct mob_loadout, 1);
|
||||
e->vnum = vnum;
|
||||
e->wear_pos = wear_pos;
|
||||
e->quantity = qty;
|
||||
e->next = NULL;
|
||||
if (!*head) {
|
||||
*head = e;
|
||||
return;
|
||||
}
|
||||
for (tail = *head; tail->next; tail = tail->next)
|
||||
;
|
||||
tail->next = e;
|
||||
}
|
||||
|
||||
struct mob_loadout *loadout_deep_copy(const struct mob_loadout *src) {
|
||||
struct mob_loadout *head = NULL, *tail = NULL;
|
||||
for (const struct mob_loadout *p = src; p; p = p->next) {
|
||||
|
|
|
|||
36
src/utils.h
36
src/utils.h
|
|
@ -54,6 +54,7 @@ void sprintbitarray(int bitvector[], const char *names[], int maxar, char *resul
|
|||
int get_line(FILE *fl, char *buf);
|
||||
int get_filename(char *filename, size_t fbufsize, int mode, const char *orig_name);
|
||||
time_t mud_time_to_secs(struct time_info_data *now);
|
||||
time_t get_total_played_seconds(const struct char_data *ch);
|
||||
struct time_info_data *age(struct char_data *ch);
|
||||
int num_pc_in_room(struct room_data *room);
|
||||
void core_dump_real(const char *who, int line);
|
||||
|
|
@ -80,6 +81,8 @@ char *right_trim_whitespace(const char *string);
|
|||
void remove_from_string(char *string, const char *to_remove);
|
||||
const char *const *obj_value_labels(int item_type);
|
||||
const char *get_char_sdesc(const struct char_data *ch);
|
||||
void clear_custom_ldesc(struct char_data *ch);
|
||||
bool build_hidden_ldesc(const struct char_data *ch, char *out, size_t outsz);
|
||||
int obj_is_storage(const struct obj_data *obj);
|
||||
int obj_storage_is_closed(const struct obj_data *obj);
|
||||
int roll_skill_check(struct char_data *ch, int skillnum, int mode, int *out_d20);
|
||||
|
|
@ -193,6 +196,12 @@ void advance_level(struct char_data *ch);
|
|||
void char_from_furniture(struct char_data *ch);
|
||||
/** What ch is currently sitting on. */
|
||||
#define SITTING(ch) ((ch)->char_specials.furniture)
|
||||
/** Mount ch is currently riding. */
|
||||
#define MOUNT(ch) ((ch)->char_specials.mount)
|
||||
/** Rider currently mounted on ch. */
|
||||
#define RIDDEN_BY(ch) ((ch)->char_specials.rider)
|
||||
/** Person ch is hitched to. */
|
||||
#define HITCHED_TO(ch) ((ch)->char_specials.hitched_to)
|
||||
/** Who is sitting next to ch, if anyone. */
|
||||
#define NEXT_SITTING(ch) ((ch)->char_specials.next_in_furniture)
|
||||
/** Who is sitting on this obj */
|
||||
|
|
@ -234,6 +243,9 @@ void char_from_furniture(struct char_data *ch);
|
|||
* Current calculation ~= 12.4 real life days */
|
||||
#define SECS_PER_MUD_YEAR (17*SECS_PER_MUD_MONTH)
|
||||
|
||||
#define MIN_CHAR_AGE 18
|
||||
#define MAX_CHAR_AGE 65
|
||||
|
||||
/** The number of seconds in a real minute. */
|
||||
#define SECS_PER_REAL_MIN 60
|
||||
/** The number of seconds in a real hour. */
|
||||
|
|
@ -514,6 +526,8 @@ do \
|
|||
#define GET_WAS_IN(ch) ((ch)->was_in_room)
|
||||
/** How old is PC/NPC, at last recorded time? */
|
||||
#define GET_AGE(ch) (age(ch)->year)
|
||||
#define GET_ROLEPLAY_AGE(ch) ((ch)->player.roleplay_age)
|
||||
#define GET_ROLEPLAY_AGE_YEAR(ch) ((ch)->player.roleplay_age_year)
|
||||
|
||||
/** Proper name for PCs and NPCs. */
|
||||
#define GET_NAME(ch) ((ch)->player.name)
|
||||
|
|
@ -556,6 +570,8 @@ do \
|
|||
|
||||
/** Class of ch. */
|
||||
#define GET_CLASS(ch) ((ch)->player.chclass)
|
||||
/** Species of ch. */
|
||||
#define GET_SPECIES(ch) ((ch)->player.species)
|
||||
/** Height of ch. */
|
||||
#define GET_HEIGHT(ch) ((ch)->player.height)
|
||||
/** Weight of ch. */
|
||||
|
|
@ -596,10 +612,10 @@ do \
|
|||
#define GET_HIT(ch) ((ch)->points.hit)
|
||||
/** Maximum hit points of ch. */
|
||||
#define GET_MAX_HIT(ch) ((ch)->points.max_hit)
|
||||
/** Current move points (stamina) of ch. */
|
||||
#define GET_MOVE(ch) ((ch)->points.move)
|
||||
/** Maximum move points (stamina) of ch. */
|
||||
#define GET_MAX_MOVE(ch) ((ch)->points.max_move)
|
||||
/** Current stamina points of ch. */
|
||||
#define GET_STAMINA(ch) ((ch)->points.stamina)
|
||||
/** Maximum stamina points of ch. */
|
||||
#define GET_MAX_STAMINA(ch) ((ch)->points.max_stamina)
|
||||
/** Current mana points (magic) of ch. */
|
||||
#define GET_MANA(ch) ((ch)->points.mana)
|
||||
/** Maximum mana points (magic) of ch. */
|
||||
|
|
@ -668,6 +684,9 @@ do \
|
|||
#define GET_SCAN_RESULTS(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->scan_results))
|
||||
#define GET_LAST_MOTD(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.lastmotd))
|
||||
#define GET_LAST_NEWS(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.lastnews))
|
||||
#define GET_REROLL_USED(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.reroll_used))
|
||||
#define GET_REROLL_EXPIRES(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.reroll_expires))
|
||||
#define GET_REROLL_OLD_ABILS(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.reroll_old_abils))
|
||||
/** Get channel history i for ch. */
|
||||
#define GET_HISTORY(ch, i) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.comm_hist[i]))
|
||||
/** Return the page length (height) for ch. */
|
||||
|
|
@ -736,13 +755,6 @@ do \
|
|||
#define CAN_SEE_IN_DARK(ch) \
|
||||
(AFF_FLAGGED(ch, AFF_INFRAVISION) || (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_HOLYLIGHT)))
|
||||
|
||||
/** Defines if ch is good. */
|
||||
#define IS_GOOD(ch) (GET_ALIGNMENT(ch) >= 350)
|
||||
/** Defines if ch is evil. */
|
||||
#define IS_EVIL(ch) (GET_ALIGNMENT(ch) <= -350)
|
||||
/** Defines if ch is neither good nor evil. */
|
||||
#define IS_NEUTRAL(ch) (!IS_GOOD(ch) && !IS_EVIL(ch))
|
||||
|
||||
/** Old wait state function.
|
||||
* @deprecated Use GET_WAIT_STATE */
|
||||
#define WAIT_STATE(ch, cycle) do { GET_WAIT_STATE(ch) = (cycle); } while(0)
|
||||
|
|
@ -936,6 +948,7 @@ do \
|
|||
|
||||
/** True if ch has a valid player class assigned. */
|
||||
#define HAS_VALID_CLASS(ch) ((GET_CLASS(ch) >= CLASS_SORCEROR) && (GET_CLASS(ch) < NUM_CLASSES))
|
||||
#define HAS_VALID_SPECIES(ch) ((GET_SPECIES(ch) >= 0) && (GET_SPECIES(ch) < NUM_SPECIES))
|
||||
|
||||
/** Return the class abbreviation for ch. */
|
||||
#define CLASS_ABBR(ch) (HAS_VALID_CLASS(ch) ? class_abbrevs[(int)GET_CLASS(ch)] : "--")
|
||||
|
|
@ -1021,7 +1034,6 @@ do \
|
|||
#define CONFIG_CONFFILE config_info.CONFFILE
|
||||
|
||||
/** Player killing allowed or not? */
|
||||
#define CONFIG_PK_ALLOWED config_info.play.pk_allowed
|
||||
/** Player thieving allowed or not? */
|
||||
#define CONFIG_PT_ALLOWED config_info.play.pt_allowed
|
||||
/** What level to use the shout command? */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue