/*******************************************************************************
Save this file to your ./src directory, and if necessary, add zoom.o to your
Makefile. Now, follow the rest of these instructions...
-------------------------------------------------------------------------merc.h-
Add this with your other maxes:
#define MAX_ZOOM 21
Now, add this to struct pc_data:
bool can_zoom[MAX_ZOOM];
Add this with your other GSNs:
extern sh_int gsn_zoom;
------------------------------------------------------------------------magic.h-
Add this to the bottom of the file.
DECLARE_SPELL_FUN( spell_zoom );
------------------------------------------------------------------------const.c-
Add this to your skill table.
{
"zoom", {25, 30, 40, 50}, {2, 3, 4, 4},
spell_zoom, TAR_IGNORE, POS_STANDING,
&gsn_zoom, SLOT (0), 10, 12,
"", "!Zoom!", ""},
---------------------------------------------------------------------act_move.c-
At the top, add this:
extern int zoom_vnum[MAX_ZOOM];
extern char * const zoom_name[MAX_ZOOM];
In the function move_char(), after the char_to_room() call:
if (!IS_NPC(ch))
{
char buf[MSL];
int i;
for (i = 0; i < MAX_ZOOM; i++)
{
if (zoom_vnum[i] == ch->in_room->vnum
&& !ch->pcdata->can_zoom[i]
&& get_skill (ch, gsn_zoom) > 0)
{
ch->pcdata->can_zoom[i] = TRUE;
sprintf (buf, "You have discovered a new Zoom"
" location to: %s!\n\r", zoom_name[i]);
send_to_char (buf, ch);
break;
}
}
}
-------------------------------------------------------------------------save.c-
Tind this bit of code in fwrite_char():
if (IS_NPC (ch))
{
fprintf (fp, "Vnum %d\n", ch->pIndexData->vnum);
}
else
{
Anywhere within that else statement, add this block of code:
fprintf (fp, "Zoom");
for (i = 0; i < MAX_ZOOM; i++)
fprintf (fp, " %d", ch->pcdata->can_zoom[i]);
fprintf (fp, "\n");
Now, in fread_char(), create a 'Z' case:
case 'Z':
if (!str_cmp (word, "Zoom"))
{
int zoom;
for (zoom = 0; zoom < MAX_ZOOM; zoom++)
ch->pcdata->can_zoom[zoom] = fread_number (fp);
fMatch = TRUE;
break;
}
break;
---------------------------------------------------------------------------db.c-
Add this to your other GSNs:
sh_int gsn_zoom;
--------------------------------------------------------------------------------
If you followed those instructions, everything should be working. Go ahead and
cut off these instructions, you're done. Here is a default helpfile, if you
don't wish to write your own:
-1 'ZOOM'~
Syntax: cast 'zoom' <place>
The Zoom spell will instantly take you to a number of predefined places, if
you've visited them in the past. When you find a new Zoom target, you will
be notified. But be warned; no matter how hard your head, you can't fly
through the ceiling.
~
*******************************************************************************/
/***************************************************************************
* You may use this code as you see fit within any non-commercial MUD. *
* My only conditions are that my comments remain in tact, that you do not *
* hesitate to give me feedback on the code, and that you don't claim my *
* work as your own. Enjoy. . -- Midboss *
* *********************************************************************** *
* "Zoom" spell for instant transportation to predefined locations. *
***************************************************************************/
#include <stdio.h>
#include <string.h>
#include "merc.h"
#include "interp.h"
/*
* Comment this out if you want the spell to only transport the user.
*/
#define GROUP
/*
* From magic.c.
*/
extern char *target_name;
/*
* The zoom location stuff. It's set up for the stock ROM areas, so adjust
* the values to fit your MUD's world.
*/
char * const zoom_name[MAX_ZOOM] = {
"Midgaard", "New Thalos", "",
"", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", ""
};
int zoom_vnum[MAX_ZOOM] = {
3001, 9506, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0
};
int zoom_cost[MAX_ZOOM] = {
5, 5, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0
};
/*
* The 'zoom' spell. It will take a player (or his group) to an area of his
* or her choosing, but only to a predefined vnum within that area, and only
* to specific areas. Additionally, the player must have been to the area at
* least once before to zoom to it.
*/
void spell_zoom (int sn, int level, CHAR_DATA * ch, void *vo, int target)
{
#ifdef GROUP
CHAR_DATA * gch, * gch_next;
#endif
int i, where = -1;
int members = 1;
ROOM_INDEX_DATA * to_room, * was_in;
if (IS_NPC (ch))
{
send_to_char ("Your spell fizzled.\n\r", ch);
return;
}
/*
* Let's see if we can find a location.
*/
for (i = 0; i < MAX_ZOOM; i++)
{
if ((ch->pcdata->can_zoom[i] || IS_IMMORTAL (ch))
&& !str_prefix (target_name, zoom_name[i]))
{
where = i;
break;
}
}
to_room = get_room_index (zoom_vnum[where]);
was_in = ch->in_room;
/*
* Make sure there was a proper argument, a location was found, the
* destination room isn't NULL, and we aren't zooming in a circle.
*/
if (target_name[0] == '\0' || where == -1
|| to_room == NULL || to_room == was_in)
{
/*
* Hit Z or R twice!
*/
act ("You fly into the air and do a barrel roll.",
ch, NULL, NULL, TO_CHAR);
act ("$n flies into the air and does a barrel roll.",
ch, NULL, NULL, TO_ROOM);
return;
}
/*
* Make sure the character has enough MP. Checks for other members,
* if needed.
*/
#ifdef GROUP
for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room)
if (is_same_group (gch, ch) && gch != ch)
++members;
#endif
if (ch->mana < members * zoom_cost[where])
{
ch->mana = 0;
act ("You fly about aimlessly for a moment,"
" and forget where you were going.", ch, NULL, NULL, TO_CHAR);
act ("You flies about aimlessly for a moment.",
ch, NULL, NULL, TO_CHAR);
return;
}
/*
* Deduct the mana cost.
*/
ch->mana = UMAX (0, ch->mana - members * zoom_cost[where]);
/*
* We can't fly through the ceiling, can we?
*/
if (!IS_SET(ch->in_room->room_flags, ROOM_INDOORS))
{
act ("You zoom head-first into the ceiling!",
ch, NULL, NULL, TO_CHAR);
act ("$n zooms head-first into the ceiling!",
ch, NULL, NULL, TO_ROOM);
ch->hit = UMAX (1, ch->hit - (ch->max_hit * 5 / 100));
return;
}
/*
* Now transport the character, and if necessary, his or her party.
*/
act ("You hover in the air for a second, then zoom into the sky.",
ch, NULL, NULL, TO_CHAR);
act ("$n hovers in the air for a second, then zooms into the sky.",
ch, NULL, NULL, TO_ROOM);
char_from_room (ch);
char_to_room (ch, to_room);
act ("$n suddenly descends from the sky and lands.",
ch, NULL, NULL, TO_ROOM);
do_function (ch, &do_look, "auto");
#ifdef GROUP
for (gch = was_in->people; gch != NULL; gch = gch_next)
{
gch_next = gch->next_in_room;
if (is_same_group (gch, ch) && gch != ch)
{
act ("You zoom into the sky after $N.",
gch, NULL, ch, TO_CHAR);
act ("$n zooms into the sky after $N.",
gch, NULL, ch, TO_ROOM);
char_from_room (gch);
char_to_room (gch, to_room);
act ("$n suddenly descends from the sky and lands.",
gch, NULL, NULL, TO_ROOM);
do_function (gch, &do_look, "auto");
}
}
#endif
return;
}
/*
* Simple command to list all known zoom locations. If you want your
* MUD's users to have access to it, remember to add the command entry
* and declaration to interp.c and interp.h respectively.
*/
void do_zoomlist (CHAR_DATA * ch, char * argument)
{
char buf[MSL];
int i, show = 0;
if (IS_NPC (ch))
return;
if (get_skill (ch, gsn_zoom) < 1)
{
send_to_char ("Huh?\n\r", ch);
return;
}
buf[0] = '\0';
for (i = 0; i < MAX_ZOOM; i++)
{
if ((IS_IMMORTAL (ch) || ch->pcdata->can_zoom[i])
&& zoom_name[i][0] != '\0')
{
++show;
sprintf (buf + strlen (buf), "%-25s %3dmp%s",
zoom_name[i], zoom_cost[i],
show % 2 == 0 ? "\n\r" : " ");
}
}
if (show < 1)
{
send_to_char ("You know of no Zoom locations.\n\r", ch);
return;
}
send_to_char ("You know of the following Zoom locations:\n\r", ch);
send_to_char (buf, ch);
}