Author Topic: Dynamic prompts based on ds2.1a18 code  (Read 2727 times)

Offline Anfauglir

  • Acquaintance
  • *
  • Posts: 1
    • View Profile
Dynamic prompts based on ds2.1a18 code
« on: December 21, 2006, 08:29:55 AM »
Heya all. I started a new mud based on ds2.1a18 and the first thing i noticed is the lack of dynamic prompts. the FAQ says that it will be done in the future. I personally cant stand not having them, so i implemented them :)

And here is what you have to do to make them yourself.

First of all lets add something to /lib/body.c :

Code: [Select]
/* Anfauglir's prompt changes */
private string user_prompt;
/* Anfauglir end */

Place this bit at the beginning of the file, under other variables

On my mud it looks like this now:

Code: [Select]
...

#define COLLAPSE_AT            10.0

private int HealthPoints, MagicPoints, ExperiencePoints, QuestPoints;
private int melee;
private int Alcohol, Caffeine, Food, Drink, Poison, Sleeping, DeathEvents;
private float StaminaPoints;
private string Torso, Biter;
private mapping Fingers, Limbs, MissingLimbs;
private static int Dying, LastHeal, Encumbrance;
private static function Protect;
private static mapping WornItems;
private static class MagicProtection *Protection;
static private int HeartModifier = 0;
private static string PoliticalParty, BodyComposition;
private static int Pacifist, rifleshot_wounds, gunshot_wounds, globalint1;
private static int Size, Respiration, BodyType;
string *ExtraChannels;
mixed Agent;

/* Anfauglir's prompt changes */
private string user_prompt;
/* Anfauglir end */

string GetRace();

static void create() {
    PoliticalParty = "UNDECIDED";
    rifleshot_wounds = 0;
    gunshot_wounds = 0;

...


After we have the place holder for the prompt, we need to be able to set it and to read it.
So i added two new functions to body.c (you can just paste them to the end of the file. thats what i did)

Code: [Select]
/* Anfauglir's prompt changes */

string QueryPrompt(){
    return user_prompt;
}

int SetPrompt(string prompt){
    user_prompt = prompt;
    return 1;
}


And since we are good programmers, we will add their prototypes to body.h:
(that is /lib/include/body.h)

Code: [Select]
/* Anfauglir's prompt changes */
string QueryPrompt();
int SetPrompt(string prompt);

Ok. So we have the easy part done. Now comes the hard part - /lib/nmsh.c

First find the function reset_prompt (close to the end of the file) and replace it with this:

Code: [Select]
void reset_prompt() {
    Prompt =(string)this_object()->QueryPrompt();
    if(!stringp(Prompt)) Prompt = "Prompt screwey> ";
}


Second step is the write_prompt function. From what i managed to see and understand, the driver itself calls that function each time we need to see the prompt. And this is how it looks on my mud:

Code: [Select]
nomask string write_prompt() {
    string tmp, ret;
    int x, y;

    if( (y = query_ed_mode()) != -1 ) {
        if( !y ) {
            if( creatorp() ) ret = ":";
            else
                ret = "\tQ)uit without saving, save and ex)it, h)elp\nCommand: ";
        }
        else if( y == -2 ) ret = "Help: ";
        else ret = "*\b";
        message("prompt", ret, this_object());
        return ret;
    }
    if (Prompt == ">") Prompt = " >"; //stupid hack. for some reason the driver dislikes ">" as a single char and eats it.
    if((ret = Prompt) == DEFAULT_PROMPT) {
        message("prompt", ret, this_object());
        return ret;
    }
    if(ret){
        while((x = strsrch(ret, "$")) != -1) {
            if(x == strlen(ret) -1) break;
            switch(ret[x+1]) {
            case 'D':
                if(!creatorp(this_object())) break;
                if(sscanf(query_cwd(), user_path(GetKeyName())+"%s",
                    tmp)) tmp = "~"+tmp;
                else tmp = query_cwd();
                ret = replace_string(ret, "$D", tmp);
                break;
            case 'V': case 'v':
                if(!creatorp(this_object())) break;
                if(GetInvis()) {
                    ret = replace_string(ret, "$V", "INVIS");
                    ret = replace_string(ret, "$v", "invis");
                }
                else if(hiddenp(this_object())) {
                    ret = replace_string(ret, "$V", "HID");
                    ret = replace_string(ret, "$v", "hid");
                }
                else {
                    ret = replace_string(ret, "$V", "");
                    ret = replace_string(ret, "$v", "");
                }
                break;
            case 'H':
                ret = replace_string(ret, "$H", sprintf("%d", this_player()->GetMaxHealthPoints()));
                break;
            case 'h':
                ret = replace_string(ret, "$h", sprintf("%d", this_player()->GetHealthPoints()));
                break;
            case 'M':
                ret = replace_string(ret, "$M", sprintf("%d", this_player()->GetMaxMagicPoints()));
                break;
            case 'm':
                ret = replace_string(ret, "$m", sprintf("%d", this_player()->GetMagicPoints()));
                break;
            case 'S':
                ret = replace_string(ret, "$S", sprintf("%d", to_int((float)this_player()->GetMaxStaminaPoints())));
                break;
            case 's':
                ret = replace_string(ret, "$s", sprintf("%d", this_player()->GetStaminaPoints()));
                break;
            case 'C':
                ret = replace_string(ret, "$C", sprintf("%d", this_player()->GetMaxCarry()));
                break;
            case 'c':
                ret = replace_string(ret, "$c", sprintf("%d", this_player()->GetCarriedMass()));
                break;
            default:
                ret = replace_string(ret, ret[x..x+1], "");
                break;
            }
        }   
    }       
    message("prompt", ret, this_object());
    return ret;
}       


It is actually pretty similar to the existing function in the file, and you can change it to display anything you want your player to see. I made it rather generic to display values from existing player file.
(notice the comment i made about driver eating > if its a single char in the prompt. If anyone makes a workaround i will be more than happy)

Last part is the prompt command that everyone can use to set their prompt:
Just make a file in /cmds/players and paste the code inside, reboot the mud and pray that it works :)

As you can see in the command itself, i prohibit regular players from setting $D $V and $v in their prompt. If
they manage to get it in there. they will cause runtimes.

Code: [Select]
/* Anfauglir's prompt implementation for ds */

#include <config.h>
#include <daemons.h>
#include <lib.h>


int cmd(string str) {
    string p, *p1, tmp ;
    int x,y;

    p = str;
    x=0;
    y=1;

    if (!p){
        message("info","Your current prompt is: "+this_player()->QueryPrompt(),this_player());
        return 1;
    }

    if(p){
        if (x=strsrch(p,"$V") != -1 || x=strsrch(p,"$D") != -1 || x=strsrch(p,"$v") != -1 )
            if (!creatorp(this_player())){
                message("info","Some of the options used are for creators only.",this_player());
                y = 0;
            }

    }
    if (y > 0){
        this_player()->SetPrompt(str);
        this_player()->reset_prompt();
    }
    return 1;
}

void help(){
    string tmp_str;

    tmp_str = "Syntax: prompt <prompt options>\n\n";
    tmp_str +="Valid prompt options are:\n";
    tmp_str +="$H - Maximum health points\n";
    tmp_str +="$h - current health points\n";
    tmp_str +="$M - Maximum magic points\n";
    tmp_str +="$m - Current magic points\n";
    tmp_str +="$S - Maximum stamina points\n";
    tmp_str +="$s - current stamina points\n";
    tmp_str +="$C - Maximum weight to carry\n";
    tmp_str +="$c - Current carried weight\n\n";
if (creatorp(this_player())){
    tmp_str +="For creators and above:\n";
    tmp_str +="$V - shows your vis/invis status\n";
    tmp_str +="$D - current directory\n";
}
    message("help",tmp_str, this_player());
}



Have fun with the prompts :)
Beyond mud -
beyondmud.mine.nu 6666
(under heavy development)

Offline cratylus

  • Your favorite and best
  • Administrator
  • ***
  • Posts: 1020
  • Cratylus@Dead Souls <ds> np
    • View Profile
    • About Cratylus
Re: Dynamic prompts based on ds2.1a18 code
« Reply #1 on: December 21, 2006, 01:42:48 PM »
Thanks for the contribution!

-Crat

Offline daelaskai

  • BFF
  • ***
  • Posts: 174
    • View Profile
Re: Dynamic prompts based on ds2.1a18 code
« Reply #2 on: December 25, 2006, 04:29:56 PM »
Yeah, thanks for the contribution.  I had a suggestion to make for this though.

It would be nice to have a multi-line prompt.  For instance, if I put in:

prompt HP: $h/$H - MP: $m/$M\n$D >

It could set my prompt to:

HP: 490/490 - MP: 650/650
/realms/daelas >

Just a suggestion.

Daelas

Offline daelaskai

  • BFF
  • ***
  • Posts: 174
    • View Profile
Re: Dynamic prompts based on ds2.1a18 code
« Reply #3 on: January 01, 2007, 10:26:05 PM »
As a follow up to my suggestion, I thought I'd add the case that I added to the switch statement for the prompt to allow multiple line prompts.  It is as follows:

Code: [Select]
            case 'R':
              ret = replace_string(ret, "$R", "\n");
              break;

I hope this helps people.

Daelas