Costume Closet

Tutorial by Chris Hunt – nospam@cwhunt.com

in collaboration with Ron Broglio – ron.broglio@lcc.gatech.edu

 

1. Purpose

This patch gives players the ability play with his identity by wearing ‘costumes’—new user icons, names, descriptions, etc. defined by the costume maker.

For example, a player can become Frankenstein’s monster for a few minutes, interact with other players, then ‘drop’ his costume and reacquire his original identity. It installs two new generic objects, Costume Closet and Costume. Additional Costume Closets can be created by using the first one as a parent.

 

2. Background

This upgrade is a bit more demanding than the other ones we have presented. It requires two new object classes, each with their own methods and properties. As such, we will drop the line-by-line tutorial in favor of a more wholesale guide to implementation. This guide has a slightly quicker pace than our other documentation.

            We used the @dump command to export these objects to a text format that enCore can understand. First we will create our empty objects, tailor our text to these objects, and then we will install the object methods and properties.

            This specific implementation assumes wizard privileges. Any programmer may implement a costume closet, but a few changes need to be made. We will flag these after installation.

 

3. Implementation

Open the object editor. Press ‘Create New Object’ and create a generic thing. Call it ‘Costume’. Repeat the same process to create a second generic thing called ‘Costume Closet’.

            Close the object editor and open the program editor. Find your two new objects and select your Costume; check ‘Read’ and ‘Fertile’, then press ‘Save Object’. Repeat the same process for the Costume Closet. (Skipping this step will prevent the creation of other closets.)

 

Figure 3.1

 

Note the object number in the title bar (the number after Costume, followed by the pound sign, ‘#’). Write down the object numbers of your Costume and your Costume Closet; make sure you label them carefully. Now we will configure our install text to fit your new objects.

            Open Notepad, Word, or some other application that can search/replace text. Paste the following code into a new window.

 

@prop #COSTUME."home_closet" #-1 rc

;;#COSTUME.("icon") = "thing.gif"

;;#COSTUME.("banner") = ""

;;#COSTUME.("footer") = ""

;;#COSTUME.("external_stylesheet") = "encore_web_object.css"

;;#COSTUME.("hits") = 3

;;#COSTUME.("aliases") = {"Costume"}

;;#COSTUME.("description") = "a costume"

;;#COSTUME.("object_size") = {2049, 1130805543}

 

@verb #COSTUME:"d*rop th*row" this none none rxd

@program #COSTUME:drop

this.home_closet:return_costume(this.home_closet);

"Don't allow the parent class to be recycled";

if (this != #COSTUME)

  recycle(this);

endif

"Code and tutorial by Chris Hunt -- nospam@cwhunt.com";

"Maintained and published by Dr. Ron Broglio, Georgia Tech";

" ron.broglio@lcc.gatech.edu";

 

.

 

@verb #COSTUME:"initialize" none none none rxd

@program #COSTUME:initialize

"Code and tutorial by Chris Hunt -- nospam@cwhunt.com";

"Maintained and published by Dr. Ron Broglio, Georgia Tech";

" ron.broglio@lcc.gatech.edu";

 

 

Run a search for ‘#COSTUME’, and replace it with the object number for your Costume. For instance, if my new Costume object had number #20221, I would search for ‘#COSTUME’ and replace it with ‘#20221’ (without the quotes, of course).

            Take this updated text and paste it into the MOO command box.

 

Figure 3.2

 

If you created the object properly (and used the right number) you should see something like the following:

 

Figure 3.3

 

Now we will repeat the same process for the Costume Closet. This is a more complex object. Replace #COSTUME_CLOSET with the object number of your Costume Closet in the following code and then paste the updated text into the MOO to register the verbs and properties.

 

@prop #COSTUME_CLOSET."costumes" {} rc

@prop #COSTUME_CLOSET."backup" {} rc

@prop #COSTUME_CLOSET."costume_desc_header" "<br><br><table><tr><td><font size=+3>?</font></td><td valign=\"top\"><i>Panicking over your lost identity? Just type \"drop costume\" to return to your normal state!</i></td></tr></table>" rc

@prop #COSTUME_CLOSET."costume_class" #-1 rc

;;#COSTUME_CLOSET.("icon") = "thing.gif"

;;#COSTUME_CLOSET.("banner") = ""

;;#COSTUME_CLOSET.("footer") = ""

;;#COSTUME_CLOSET.("external_stylesheet") = "encore_web_object.css"

;;#COSTUME_CLOSET.("aliases") = {"closet"}

;;#COSTUME_CLOSET.("description") = "You can become any character by borrowing a costume. <br><br>Type 'borrow costume-name from closet' and it will change<br>you to the given costume name. So, for example, you can<br>type <i>'borrow Monster from closet'</i> and you will become a Monster.<br>Type <i>'return_costume to closet'</i> to return to your old self.<br>Type <i>'add_costume to closet'</i> to add new costumes<br><br>Costumes avaliable:<br>"

;;#COSTUME_CLOSET.("object_size") = {9750, 1130807808}

 

@verb #COSTUME_CLOSET:"borrow" any from this rxd

@program #COSTUME_CLOSET:borrow

if (this.costumes == {})

  player:tell("There are no costumes for you to borrow.");

  player:tell(("You need to run \"add_costume to " + self.name) + "\".");

endif

ok = 0;

for costume in (this.costumes)

  if (costume[1] == args[1])

    user_already_has_costume = 0;

    for item in (player.contents)

      if (parent(item) == this.costume_class)

        user_already_has_costume = 1;

      endif

    endfor

    if (user_already_has_costume == 0)

      player_costume = create(this.costume_class, #-1);

      player_costume.name = "Costume";

      player_costume.home_closet = this;

      player_costume:moveto(player);

    endif

    this:savePlayer();

    playerName = player.name;

    player.name = costume[1];

    player.description = costume[2] + this.costume_desc_header;

    player.url_address = costume[3];

    if ($string_utils:is_numeric(costume[4]))

      player.web_width = tonum(costume[4]);

    endif

    if ($string_utils:is_numeric(costume[5]))

      player.web_height = tonum(costume[5]);

    endif

    player.audio_url = costume[6];

    if (length(costume[7]) > 0)

      player.icon = costume[7];

    endif

    if (length(costume[8]) > 0)

      player.gender = costume[8];

    endif

    player.location:look_self();

    player.location:announce((playerName + " becomes ") + costume[1]);

    player:tell("You become " + costume[1]);

    ok = 1;

    break;

  endif

endfor

if (ok == 0)

  player:tell("No such costume.");

  player:tell(("You need to run \"add_costume to " + this.name) + "\" to add that costume.");

endif

"Tutorial by Chris Hunt -- nospam@cwhunt.com";

"Maintained and published by Dr. Ron Broglio, Georgia Tech";

" ron.broglio@lcc.gatech.edu";

 

.

 

@verb #COSTUME_CLOSET:"savePlayer" none none this rxd

@program #COSTUME_CLOSET:savePlayer

for backupPerson in (this.backup)

  if (backupPerson[1] == player)

    return;

  endif

endfor

this.backup = listappend(this.backup, {player, player.name, player.description, player.url_address, player.web_width, player.web_height, player.audio_url, player.icon, player.gender});

"Tutorial by Chris Hunt -- nospam@cwhunt.com";

"Maintained and published by Dr. Ron Broglio, Georgia Tech";

" ron.broglio@lcc.gatech.edu";

 

.

 

@verb #COSTUME_CLOSET:"return_costume" none to this rxd

@program #COSTUME_CLOSET:return_costume

this:update_desc();

i = 0;

for personBackup in (this.backup)

  i = i + 1;

  if (personBackup[1] == player)

    playerName = player.name;

    player.name = personBackup[2];

    player.description = personBackup[3];

    player.url_address = personBackup[4];

    player.web_width = personBackup[5];

    player.web_height = personBackup[6];

    player.audio_url = personBackup[7];

    player.icon = personBackup[8];

    player.gender = personBackup[9];

    this.backup = listdelete(this.backup, i);

    player.location:look_self();

    player:tell("You morph back to " + player.name);

    player.location:announce((playerName + " morphes back to ") + player.name);

    return;

  endif

endfor

player:tell("You haven't borrowed any costumes to restore.");

"Tutorial by Chris Hunt -- nospam@cwhunt.com";

"Maintained and published by Dr. Ron Broglio, Georgia Tech";

" ron.broglio@lcc.gatech.edu";

 

.

 

@verb #COSTUME_CLOSET:"update_desc" none none this rxd

@program #COSTUME_CLOSET:update_desc

this.description = "You can become any character by borrowing a costume. <br><br>";

this.description = this.description + "Type 'borrow costume-name from closet' and it will change<br>";

this.description = this.description + "you to the given costume name. So, for example, you can<br>";

this.description = this.description + "type <i>'borrow Monster from closet'</i> and you will become a Monster.<br>";

this.description = this.description + "Type <i>'return_costume to closet'</i> to return to your old self.<br>";

this.description = this.description + "Type <i>'add_costume to closet'</i> to add new costumes<br><br>";

if (length(this.costumes) > 0)

  this.description = this.description + "Costumes avaliable:";

  for costume in (this.costumes)

    this.description = this.description + "<br><b><i>";

    this.description = this.description + costume[1];

    this.description = this.description + "</i></b>";

  endfor

else

  this.description = this.description + "Currently no costumes available.";

endif

"Tutorial by Chris Hunt -- nospam@cwhunt.com";

"Maintained and published by Dr. Ron Broglio, Georgia Tech";

" ron.broglio@lcc.gatech.edu";

 

.

 

@verb #COSTUME_CLOSET:"list_costumes" none in this rxd

@program #COSTUME_CLOSET:list_costumes

this:update_desc();

if (length(this.costumes) == 0)

  player:tell("No costumes avaliable. Add new constumes");

else

  player:tell("Costumes avaliable:");

  for costume in (this.costumes)

    player:tell(costume[1]);

  endfor

endif

"Tutorial by Chris Hunt -- nospam@cwhunt.com";

"Maintained and published by Dr. Ron Broglio, Georgia Tech";

" ron.broglio@lcc.gatech.edu";

 

.

 

@verb #COSTUME_CLOSET:"add_costume" none to this rxd

@program #COSTUME_CLOSET:add_costume

player:tell("Give the name of the new costume:");

new_name = read();

player:tell("Give the description of the new costume:");

new_description = read();

player:tell("Give the visual-url of the new costume:");

new_url = read();

player:tell("Give the visual-width of the new costume:");

new_width = read();

player:tell("Give the visual-height of the new costume:");

new_height = read();

player:tell("Give the audio-url of the new costume:");

new_audio = read();

player:tell("Give the icon of the new costume:");

new_icon = read();

player:tell("Give the gender of the new costume:");

new_gender = read();

newCostume = {new_name, new_description, new_url, new_width, new_height, new_audio, new_icon, new_gender};

answer = "yes";

i = 0;

for costume in (this.costumes)

  i = i + 1;

  if (costume[1] == new_name)

    player:tell("This costume already exists, overwrite [yes/no]?");

    answer = read();

    if (answer == "yes")

      this.costumes = listdelete(this.costumes, i);

      this.costumes = listinsert(this.costumes, newCostume, i);

      this:update_desc();

      player:tell(new_name + " updated.");

    else

      player:tell(new_name + " not added.");

    endif

    return;

  endif

endfor

this.costumes = listappend(this.costumes, newCostume);

this:update_desc();

player:tell(new_name + " added to costumes.");

"Tutorial by Chris Hunt -- nospam@cwhunt.com";

"Maintained and published by Dr. Ron Broglio, Georgia Tech";

" ron.broglio@lcc.gatech.edu";

 

.

 

@verb #COSTUME_CLOSET:"remove_costume" any from this rxd

@program #COSTUME_CLOSET:remove_costume

i = 0;

for costume in (this.costumes)

  i = i + 1;

  if (costume[1] == args[1])

    this.costumes = listdelete(this.costumes, i);

    player:tell((args[1] + " removed from the ") + this.name);

    this:update_desc();

    return;

  endif

endfor

player:tell((args[1] + " not found in the ") + this.name);

"Tutorial by Chris Hunt -- nospam@cwhunt.com";

"Maintained and published by Dr. Ron Broglio, Georgia Tech";

" ron.broglio@lcc.gatech.edu";

 

.

 

Your screen should look something like this:

 

Figure 3.4

 

Now we need to tell your Costume Closet where to find the costume objects it gives out.

Open the program editor. Press ‘My Objects’ and choose your Costume Closet. Scroll to the bottom of the properties list and select ‘costume_class’. You should see ‘#-1’ in the text box. Replace it with the object number of your Costume. Press ‘Save Property’ and make sure that the Data Type remains ‘Object’. If it changes to ‘List’ or ‘String’ delete the number and try again; make sure you do not insert a line-break in the text box. Now your screen should look like this (with your object number instead, of course):

 

Figure 3.5

 

We mentioned earlier that this implementation requires wizard privileges. These privileges are only need to create the first closet; afterwards, other programmers can create new closets using the wizard-installed one as a parent.

You should now have a working Costume Closet! We recommend using the Closet you just created only as a parent object--any costumes you put in this Closet will be in any other Closets that you make.

Replace ‘#MY_CLOSET’ with your object’s number and create your first child closet by typing:

 

@create #MY_CLOSET named “My Costume Closet”

 

I recommend hiding your parent Closet so that no one can move it or add any costumes to the root. You can do this by replacing ‘#MY_CLOSET’ again and typing:

 

@move #MY_CLOSET to #-1

 

Naturally, we recommend you lock whatever Closets you create to their rooms. See the Closet’s description for information on creating costumes and configuring your Closet.

 

Note:

We strongly recommend that wizards install the base copy of the closet. However, base implementation is possible as a programmer. See our tutorials on creating clones. In this version of the closet, the wizard-only method is used to create clones of the Costume class. Modify the code contained in the borrow_costume verb in the Costume Closet to fit one of the other methods—pay particular attention to line 15.