Author Topic: new mud, new coder, state of the mud address  (Read 2298 times)

Offline genova

  • Acquaintance
  • *
  • Posts: 7
    • View Profile
new mud, new coder, state of the mud address
« on: May 09, 2013, 06:57:57 pm »
  I've been working with the DS3.6 mudlib for a couple weeks now, I am very happy I switched from a DIKU-based set up, a lot of my favorite muds are on LP and DS has a very developed system. I went through all the tutorial docs I could find, reading them over and over until I finally was able to read the actual files, now I read the files and follow the inherit chains and for the most part I understand what I read.

  I first made a basic town area, and realized I was rushing it, it wasn't coming out very good, and everything was super spaced out.
  So I used domaincreate and started over. Now I've changed some basic things, like the currency, and the languages things speak, and I've even written really basic functions, or adapted ones I found in examples, like beggars who look innocent and pull out a knife they didnt have, or rooms that only allow explorers in. Things are getting kind of fun, stuff does what I tell it to for the most part, after some trial and error. Now I come to the purpose of the writing: establishing things I want to develop/change, keeping in mind I will have to rely heavily on examples at first.

Regeneration: I found the part that deals with the healing mod associated with sleeping and eating etc. I need to find the parts that deal with movement and magic as well, and figure out how they work. I want to have better control over how and why my characters regen mp hp and mv, and I keep reading but I'm just stabbing in the dark on this one.

Leveling up, spending XP specifically: I assume I need another variable set on the player that says "AvailableXP" in addition to the normal variable that holds the normal XP value. Then I would need to find some way to make that xp spendable, like on stats for example. Just a thought.

Races: I've created a few extra races from existing ones, and made some new playable races. I would like to learn more about the formatting of traits I can put into the individual race files (human, orc, etc). What kinds of other things could I specify in a race file, I wonder.

Techniques:
This is my most ambitious plan, and I have changed it along the way to better suit the DS system as is.
Classes will have teachers and trainers in their guildhouse, that only that class can get into
Teachers teach new skills,
Trainers train existing skills,
both cost training points per training session.
Skills will train by the standard pro vs con method in abilities.c (?)

Now each skill will have associated 'Techniques' which are basically just verbs that do things that use a skill check and possibly result in a skill gain. so for eg kick requires melee attack level 1, and helps develop that skill sometimes.
Then it gets more complicated, I don't really understand the spellcasting system, nor the prayer system, but I assume they are not very different. Actually, looking at the spells might be the way to figure this thing out.

I'm also toying with the idea of each technique should have a level from 0-1000 that can develop with the character, so you end up with fireball specific mages and orc fighters who are particularly good at kicking dirt or something like that. My current thinking is that I would want to have that be its own sub-skill or something.

Languages: I'm more or less leaving languages how they are, but I want to make the learning process involve "trainer says x you say x" for a few rounds. Shouldn't be too difficult.

Quests: I really like quests, and I like that there are associated titles you get with completion, very snazzy. I need something that players can spend the quest points on.

Areas: Obviously I need to keep slowly expanding outward

Items: I am currently creating a spreadsheet of all the equipment and stuff players may encounter

Armor: Another extremely ambitious plan for me: I want to have different kinds of armor, not just different protection on them, but literally armor types, so there are heavy armors for people with the heavy armor skill, and light armors for people with the light armor skill. I think I would need to make header files and do other things I don't really understand, as well as change something in the combat.c to actually make use of these traits.

This is intended to be a work in progress, I'll write more later as it comes up, I assume most any new mud admin has to think about this stuff, so if you have any tips of course they are appreciated.



G

Offline quixadhal

  • BFF
  • ***
  • Posts: 642
    • View Profile
    • WileyMUD
Re: new mud, new coder, state of the mud address
« Reply #1 on: May 10, 2013, 12:42:41 am »
The way I planned out "classes" is using a tiered system.  I call them "guilds", because a "class" is AD&D-speak for "the one thing you were born to do".

So, everyone starts the game as a generic "adventurer".  As they explore, they gain a handful of generic adventurer-type skills (punch, kick, attack with a weapon, loot corpses, bash in doors, search for traps, etc).  When they find a guild, they have the option of joining it IF they meet the pre-requisites.

For the first tier, those pre-reqs are pretty easy.  Maybe get to physical level X, and certain guilds may have race/gender/nationality/alignment requirements.  Let's say you join the Mage guild of Shylar.

The mages in Shylar teach most of the usual low-level general magic you'd expect, and they also have a few specialty spells that only they know.  Shlyar was a crossroads town, so perhaps their mage guild has a few extra spells related to travel.

As you adventure further, you find other guilds.  Most first-tier guilds also won't exclude you from joining if you're already in another first-tier guild... so you can also join a fighter guild if you like.

At some point, you find a second-tier mage guild, perhaps the Frost Mages of Lovitar.  They specialize in mage related to ice and pain.  Lovitar was a goddess, and so you'd have no problem joining as a mage, cleric, or fighter.  However, their goddess punished thieves harshly, so if you're in a first-tier (or higher) thieves guild, you can't join unless you abandon it.  Lovitar also hated men, so only females can join in any case.

If you choose to abandon your conflicting guild, they may be unhappy with you.  In some cases, they won't care.  In others, they might never let you rejoin.  In some, they might send out assassins to kill you, thus preventing the guild secrets from falling into "enemy" hands.  The higher tier a guild belongs to, the more specialized it is, and the more jealously they might guard their lore.

Finally, if you are ambitious enough, you can create rival guilds.  You might join Bob's fire guild and learn one set of spells.  Joe's fire guild is similar, but has different spells.  You can't join both.

I find that system much more flexible than having to pick a "class" at creation time, and trying to shoehorn other skills into it later.  YMMV. :)

Offline genova

  • Acquaintance
  • *
  • Posts: 7
    • View Profile
Re: new mud, new coder, state of the mud address
« Reply #2 on: May 10, 2013, 04:28:23 am »
I'm definitely having players start off as an explorer, with options to join a guild/class (in my game the guild is just the people who the class its skills, sets a home, and has advancement for that class) as they meet prerequisites, and probably after a quest or two. And I'm also planning to have a sort of tiered approach, with "Explorer>basic fighter, mage or thief> specialist" kind of deal, it should feel like the player went into the class as the character not the player, so I prefer this method over class select at creation.

Offline genova

  • Acquaintance
  • *
  • Posts: 7
    • View Profile
Re: new mud, new coder, state of the mud address
« Reply #3 on: May 12, 2013, 02:37:43 pm »
Hi guys,
I'm currently trying to do 2 things
  • move the regen code into its own regen.c file, that body.c inherits,
  • look at eventCompleteHeal below, I want MP and SP to work like HP does (in that function), I'm planning to basically cut and paste HP's functions and make equivalents for the other two.
The proposed benefits of doing this are:
  • being able to 'get at' the code when I want to play with it more easily
  • being able to create equivalents to the verb 'sleep' specifically for mana and stam regen
  • being able to eventually share the code as a simple to implement module
  • learning is good
The code below is called 'regen.c' has only the functions I saw in body.c that related, what else do I need in there to make it properly work? should I copy over the declarations from the top of body.c? does it matter which file the declarations are in if you're inheriting a file which just contains a bunch of functions?

in my body.c I have a line at the top that reads:
inherit "regen/regen"
(regen is in its own folder within the folder where body.c is)
but otherwise I have not changed nor 'cut' from body.c, and I'm a little shaky on how to proceed.

any tips?

Code: [Select]
void eventCompleteHeal(int x){
    eventHealDamage(x, 1, GetLimbs()); //hp
    AddMagicPoints(x + 1); //mp
    AddStaminaPoints(x); //sp
}

/* varargs static int AddHealthPoints(int x, string limb, object agent)
 * int x - number of points being added, may be negative (required)
 * string limb - the limb to which health is being added (optional)
 * object agent - the living responsible for this damage
 *
 * defaults
 * limb defaults to 0
 *
 * description
 * if the value of limb is not zero, then "x" number of health points will
 * be added to limb "limb"
 * if he value is 0, then the overall health points will be modified
 *
 * returns the remaining number of health points for the limb in question
 * or for the overall health points
 */

varargs static int AddHealthPoints(int x, string limb, mixed agent){
    int y = 0;
    string agentname;

    if(agent){
        if(stringp(agent)){
            agentname = agent;
            agent = 0;
        }
        else if(objectp(agent)){
            if(agent != this_object()) agentname = agent->GetName();
        }
    }

    if(godmode && x < 1) return 0;

    if( limb ){
        if( !Limbs[limb] ) return -1;
        y = GetMaxHealthPoints(limb);
        if(y < 1) return y;
        if((Limbs[limb]["health"] += x) < 1) Limbs[limb]["health"] = 0;
        else if(Limbs[limb]["health"] > y)
            Limbs[limb]["health"] = y;
        return Limbs[limb]["health"];
    }
    else {
        if((HealthPoints += x) < 1) HealthPoints = 0;
        else if(HealthPoints > (y = GetMaxHealthPoints())) HealthPoints = y;
        if( HealthPoints < 1 ){
            if( !this_object()->GetDying()){
                mixed smith;
                this_object()->SetDying(1);
                Agent = agent;
                smith = (Agent||agentname);
                call_out("eventDie", 0, smith);
            }
        }
        else {
            float h = percent(GetHealthPoints(), GetMaxHealthPoints());

            if( h < COLLAPSE_AT ){
                eventCollapse();
            }
        }
        return HealthPoints;
    }
}

varargs int GetHealthPoints(string limb){
    if(limb){
        if(!Limbs[limb]) return -1;
        else return Limbs[limb]["health"];
    }
    else return HealthPoints;
}

int SetHealthPoints(int x){
    if(interactive(this_object())) return GetHealthPoints();
    if( x > GetMaxHealthPoints() ){
        this_object()->SetStat("durability", (x-50)/10,
                this_object()->GetStatClass("durability"));
        AddHealthPoints( x - GetHealthPoints() );
    }
    HealthPoints = x;
    return GetHealthPoints();
}

/* int AddMagicPoints(int x)
 * int x - the number of magic points being added, may be negative
 *
 * description
 * adds magic points to the body
 *
 * returns the remaining magic points
 */

int AddMagicPoints(int x){
    int y;

    if((MagicPoints += x) < 1) MagicPoints = 0;
    else if(MagicPoints > (y = GetMaxMagicPoints())) MagicPoints = y;
    return MagicPoints;
}

int GetMagicPoints(){ return MagicPoints; }

int GetMaxMagicPoints(){ return 0; }

/* int AddStaminaPoints(int x)
 * int x - number of stamina points being added
 *
 * description
 * adds "x" stamina points, can be negative
 *
 * returns the remaining number of stamina points
 */

int AddLead(string ammo,int number){
    if( !intp(number) ) error("Bad argument 2 to AddLead().\n");
    if( !stringp(ammo) ) error("Bad argument 1 to AddLead().\n");
    firearms_wounds += number;
    if( firearms_wounds < 0 ){
        firearms_wounds = 0;
    }
    return 1;
}

varargs int GetLead(string ammo){
    return firearms_wounds;
}

float AddStaminaPoints(mixed x){
    float y;

    if( !intp(x) && !floatp(x) )
        error("Bad argument 1 to AddStaminaPoints().\n");
    if( intp(x) ) x = to_float(x);
    if((StaminaPoints += x) < 0.1) StaminaPoints = 0.0;
    else if(StaminaPoints > (y = GetMaxStaminaPoints())) StaminaPoints = y;
    return StaminaPoints;
}

int GetStaminaPoints(){ return to_int(StaminaPoints); }

float GetMaxStaminaPoints(){  return 0; }

Offline genova

  • Acquaintance
  • *
  • Posts: 7
    • View Profile
Re: new mud, new coder, state of the mud address
« Reply #4 on: May 12, 2013, 02:51:14 pm »
I moved this over too, I think I need it:
Code: [Select]
void eventCheckHealing(){
    int x, y, lead;
    object dude;
    dude = this_object();
    lead = dude->GetLead();

    if(lead && !present("firearms_wound", dude)){
        object wound = new(LIB_WOUND);
        if(wound) wound->eventMove(dude);
    }

    if(interactive() && !environment()){
        this_object()->eventMove(ROOM_START);
    }

    //This resets the parser counter.
    this_object()->DoneTrying();

    if(HealthPoints < 1 && !this_object()->GetDying()){
        this_object()->SetDying(1);
        this_object()->eventDie("misfortune");
        return;
    }

    if(AUTO_ADVANCE && interactive() && !this_object()->GetDying()){
        PLAYERS_D->CheckAdvance(this_object());
    }

    x = GetHeartRate() * 10;

    if(dude->GetSleeping() > 0 && dude->GetPosition() != POSITION_LYING
            && dude->GetPosition() != POSITION_SITTING){
        dude->eventCollapse();
    }

    if(dude->GetInCombat()){
        if(dude->GetInvis()) dude->SetInvis(0);
        if(!interactive(dude) && !RACES_D->GetLimblessRace(dude->GetRace())){
            dude->SetAutoStand(1);
        }
    }

    if(!inherits(LIB_VEHICLE,this_object())){
        if( (y = time() - LastHeal)  >= x ){
            LastHeal = time();
            do {
                eventCompleteHeal(GetHealRate());
            } while( (y = y - x) >= x );
            if( Alcohol > 0 ){
                Alcohol--;
                if( !Alcohol ){
                    message("my_action", "You are left with a pounding headache.",
                            this_object());
                    AddHealthPoints(-(random(3) + 1));
                }
                else if( !GetSleeping() && random(100) < 8 ){
                    string verb, adv;

                    switch(random(5)){
                        case 0: verb = "burp"; adv = "rudely"; break;
                        case 1: verb = "look"; adv = "ill"; break;
                        case 2: verb = "hiccup"; adv = "loudly"; break;
                        case 3: verb = "stumble"; adv = "clumsily"; break;
                        case 4: verb = "appear"; adv = "drunk"; break;
                    }
                    message("my_action", "You " + verb + " " + adv + ".",
                            this_object());
                    message("other_action", GetName() + " " + pluralize(verb) + " " +
                            adv + ".", environment(), ({ this_object() }));
                }
            }
            if( Sleeping > 0 ){
                Sleeping--;
                if( !Sleeping || dude->GetInCombat() ){
                    Sleeping = 0;
                    message("my_action", "You wake up!", this_object());
                    message("other_action", GetName() + " wakes up from " +
                            possessive(this_object()) + " deep sleep.",
                            environment(this_object()), ({ this_object() }));
                }
                else if( random(100) < 8 ){
                    message("my_action", "You snore.", this_object());
                    message("other_action", this_player()->GetName() +
                            " snores loudly.", environment(this_object()),
                            ({ this_object() }));
                }
            }
            if( Caffeine > 0 ) Caffeine--;
            if( Food > 0 ) Food--;
            if( Drink > 0 ) Drink--;
        }
    }
}