To install MOBprograms.
Please start by making a copy of all your source files to a backup place
just in case somthing weird happens. (I dont want you to hate me forever)
0. Edit Makefile
----------------
Add in mob_commands.o and mob_prog.o to the list of O_FILES
(any order is fine here)
Also, you may need to add the CFLAG -DDUNNO_STRSTR.
If your system complains about not knowing this, then put it in.
1. Deal with merc.h
-------------------
There are six changes to make here.
a. Add the following lines to the end of the Structure types section
typedef struct mob_prog_data MPROG_DATA;
typedef struct mob_prog_act_list MPROG_ACT_LIST;
b. Add the following lines in the mob_index_data structure:
MPROG_DATA * mobprogs;
int progtypes;
c. Add the following lines in the char_data structure:
MPROG_ACT_LIST * mpact;
int mpactnum;
d. Add the following code block wherever you desire:
struct mob_prog_act_list
{
MPROG_ACT_LIST * next;
char * buf;
CHAR_DATA * ch;
OBJ_DATA * obj;
void * vo;
};
struct mob_prog_data
{
MPROG_DATA *next;
int type;
char * arglist;
char * comlist;
};
bool MOBtrigger;
#define ERROR_PROG -1
#define IN_FILE_PROG 0
#define ACT_PROG 1
#define SPEECH_PROG 2
#define RAND_PROG 4
#define FIGHT_PROG 8
#define DEATH_PROG 16
#define HITPRCNT_PROG 32
#define ENTRY_PROG 64
#define GREET_PROG 128
#define ALL_GREET_PROG 256
#define GIVE_PROG 512
#define BRIBE_PROG 1024
e. Add this to the PLAYER_DIR, NULL_FILE #defines
#define MOB_DIR "MOBProgs/" /* MOBProg files */
or if you are using MSDOS or Macintosh, add this
#define MOB_DIR "" /* MOBProg files */
f. Add in the global prototypes for the mob_progs
/* act_wiz.c */
ROOM_INDEX_DATA * find_location args( ( CHAR_DATA *ch, char *arg ) );
/* fight.c */
void death_cry args( ( CHAR_DATA *ch ) );
/* mob_prog.c */
#ifdef DUNNO_STRSTR
char * strstr args ( (const char *s1, const char *s2 ) );
#endif
void mprog_wordlist_check args ( ( char * arg, CHAR_DATA *mob,
CHAR_DATA* actor, OBJ_DATA* object,
void* vo, int type ) );
void mprog_percent_check args ( ( CHAR_DATA *mob, CHAR_DATA* actor,
OBJ_DATA* object, void* vo,
int type ) );
void mprog_act_trigger args ( ( char* buf, CHAR_DATA* mob,
CHAR_DATA* ch, OBJ_DATA* obj,
void* vo ) );
void mprog_bribe_trigger args ( ( CHAR_DATA* mob, CHAR_DATA* ch,
int amount ) );
void mprog_entry_trigger args ( ( CHAR_DATA* mob ) );
void mprog_give_trigger args ( ( CHAR_DATA* mob, CHAR_DATA* ch,
OBJ_DATA* obj ) );
void mprog_greet_trigger args ( ( CHAR_DATA* mob ) );
void mprog_fight_trigger args ( ( CHAR_DATA* mob, CHAR_DATA* ch ) );
void mprog_hitprcnt_trigger args ( ( CHAR_DATA* mob, CHAR_DATA* ch ) );
void mprog_death_trigger args ( ( CHAR_DATA* mob ) );
void mprog_random_trigger args ( ( CHAR_DATA* mob ) );
void mprog_speech_trigger args ( ( char* txt, CHAR_DATA* mob ) );
2. Make adjustments to db.c
---------------------------
There are 4 changes in here.
a. import the file: mprog_add_to_db.c
(the prototypes will need to be moved to the beginning
of the db.c file, otherwise this can go wherever)
b. in boot_db, add the following line between the MOBILES and the
OBJECTS lines which look mighty similar:
else if ( !str_cmp( word, "MOBPROGS" ) ) load_mobprogs( fpArea );
c. in load_mobiles, add the following lines between the
letter != 'S' and iHash = vnum... sections. (note that the line
goes after the closing brace for the if statement:
letter = fread_letter( fp );
if ( letter == '>' )
{
ungetc( letter, fp );
mprog_read_programs( fp, pMobIndex );
}
else ungetc( letter,fp );
d. In "Fix up exits" section right after the load_notes( )
in boot_db(..)
Initialize MOBtrigger by adding MOBtrigger = TRUE;
3. Adjust your files a little
-----------------------------
a. Do this to your comm.c in void act( ... )
replace
write_to_buffer ( to->desc, buf, point - buf );
at the end of the routine with
if (to->desc)
write_to_buffer( to->desc, buf, point - buf );
if (MOBtrigger)
mprog_act_trigger( buf, to, ch, obj1, vch );
and right before the return add,
MOBtrigger = TRUE;
b. Where you want the player to NOT trigger MOBprograms add a
MOBtrigger = FALSE;
before the appropriate act(..) call in various *.c files.
4. Stick in the triggers
------------------------
In update.c in mobile_update just before the Scavenge section
(after the busy/sleeping check) add the following line:
if ( ch->in_room->area->nplayer > 0 ) mprog_random_trigger( ch );
Also, in update.c in aggr_update just after: wch_next = wch->next;
add the following code chunk to process the act triggers. These are
performed here to allow everyone in the room to see what just
happenened before the mobile reacts - call them mob-reflexes:
if ( IS_NPC( wch ) && wch->mpactnum > 0
&& wch->in_room->area->nplayer > 0 )
{
MPROG_ACT_LIST * tmp_act, *tmp2_act;
for ( tmp_act = wch->mpact; tmp_act != NULL;
tmp_act = tmp_act->next )
{
mprog_wordlist_check( tmp_act->buf,wch, tmp_act->ch,
tmp_act->obj, tmp_act->vo, ACT_PROG );
free_string( tmp_act->buf );
}
for ( tmp_act = wch->mpact; tmp_act != NULL; tmp_act = tmp2_act )
{
tmp2_act = tmp_act->next;
free_mem( tmp_act, sizeof( MPROG_ACT_LIST ) );
}
wch->mpactnum = 0;
wch->mpact = NULL;
}
In act_comm.c in do_say just before the final return add:
mprog_speech_trigger( argument, ch );
In act_move.c in move_char just before the final return add:
mprog_entry_trigger( ch );
mprog_greet_trigger( ch );
In act_obj.c in do_give just before the final return add:
mprog_give_trigger( victim, ch, obj );
and earlier in do_give just after: send_to_char( "OK.\n\r", ch );
mprog_bribe_trigger( victim, ch, amount );
In fight.c in violence_update just before the Fun for the whole
family, add
mprog_hitprcnt_trigger( ch, victim );
mprog_fight_trigger( ch, victim );
and in raw_kill replace death_cry(); with
mprog_death_trigger( victim );
5. MobCommands
--------------
If you so desire, use the normal methods described in the merc docs
to add the commands. place the following into interp.c in cmd_table:
/*
* MOBprogram commands.
*/
{ "mpstat", do_mpstat, POS_DEAD, 38, LOG_NORMAL },
{ "mpasound", do_mpasound, POS_DEAD, 0, LOG_NORMAL },
{ "mpjunk", do_mpjunk, POS_DEAD, 0, LOG_NORMAL },
{ "mpecho", do_mpecho, POS_DEAD, 0, LOG_NORMAL },
{ "mpechoat", do_mpechoat, POS_DEAD, 0, LOG_NORMAL },
{ "mpechoaround", do_mpechoaround,POS_DEAD, 0, LOG_NORMAL },
{ "mpkill", do_mpkill ,POS_DEAD, 0, LOG_NORMAL },
{ "mpmload", do_mpmload ,POS_DEAD, 0, LOG_NORMAL },
{ "mpoload", do_mpoload ,POS_DEAD, 0, LOG_NORMAL },
{ "mppurge", do_mppurge ,POS_DEAD, 0, LOG_NORMAL },
{ "mpgoto", do_mpgoto ,POS_DEAD, 0, LOG_NORMAL },
{ "mpat", do_mpat ,POS_DEAD, 0, LOG_NORMAL },
{ "mptransfer", do_mptransfer ,POS_DEAD, 0, LOG_NORMAL },
{ "mpforce", do_mpforce ,POS_DEAD, 0, LOG_NORMAL },
Place the following into merc.h with all the other DO_FUN's:
DECLARE_DO_FUN( do_mpasound );
DECLARE_DO_FUN( do_mpat );
DECLARE_DO_FUN( do_mpecho );
DECLARE_DO_FUN( do_mpechoaround );
DECLARE_DO_FUN( do_mpechoat );
DECLARE_DO_FUN( do_mpforce );
DECLARE_DO_FUN( do_mpgoto );
DECLARE_DO_FUN( do_mpjunk );
DECLARE_DO_FUN( do_mpkill );
DECLARE_DO_FUN( do_mpmload );
DECLARE_DO_FUN( do_mpoload );
DECLARE_DO_FUN( do_mppurge );
DECLARE_DO_FUN( do_mpstat );
DECLARE_DO_FUN( do_mptransfer );
Sorry there are no accompanying help files here, but they are fairly
basic and obvious commands. Most of the code is stripped from the
act_wiz stuff itself.
6. A few bug fixes.
--------------------
In update.c in mobile_update(...), along with the MOBprogram
random trigger:
if ( ch->in_room->area->nplayer > 0 )
mprog_random_trigger( ch );
should be:
/* MOBprogram random trigger */
if ( ch->in_room->area->nplayer > 0 )
{
mprog_random_trigger( ch );
/* If ch dies or changes
position due to it's random
trigger, continue - Kahn */
if ( ch->position < POS_STANDING )
continue;
}
Also in mobile_update after move_char(...) in the /* Wander */
block right before the /* Flee */ block it should be:
..
..
&& !IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB)
&& ( !IS_SET(ch->act, ACT_STAY_AREA)
|| pexit->to_room->area == ch->in_room->area ) )
{
move_char( ch, door );
/* If ch changes position due
to it's or someother mob's
movement via MOBProgs,
continue - Kahn */
if ( ch->position < POS_STANDING )
continue;
}
This is to prevent the server from referencing a bad pointer
to ch. This bug became apparent when a MOBProgram caused a mob to die
and then continued with mobile_update by fleeing with a bad ch pointer.
7. Give it a whirl
------------------
" Try making it and hope it all works for the best. You may get some
warnings from the mob_prog.c file and these are ok to ignore.
I also got a bizzare prototype error on one platform I tested with.
It was in mprog_translate, and I had to comment out the prototype
before it would compile. Haven't any idea why that happened.
" - N'Atas-Ha
Also, you may want to do the following little extras...
change the calls to act in do_say, do_yell, do_shout, do_emote and
also the ones in do_give to not trigger (using MOBtrigger = FALSE;).
This means that these acts cannot trigger a mobile. The do_emote is
particularly critical, since otherwise a player can emote any trigger
they wish. You may find other act calls which you desire to make
"safe".
You may also consider giving MOBProgged mobs the ability to utilize
all the commands available. To do this just make the necessary
changes to interpret(...) in interp.c. MERC 2.2 will have this
feature with most of the necessary security loopholes closed.
Below here is the mobinfo help screen which we would sorta like you to include.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-1 MOBINFO~
. Our Mobiles have been infused with the breath of a
shy faeyrie to give them a slightly warmer nature.
Perhaps you have noticed this already. If not, do
take a moment to ask a mobile to tea. The code is
written by J Murphy, N'Atas-Ha of ThePrincedom and
based on a concept created on Worlds of Carnage by
Aaron Buhr. questions/comments to murph@cs.cmu.edu
A little rewriting of the code/DOC/INSTALL done by
Kahn of MERC Industries and tested extensively on
Marble Mud (marble.bu.edu 4000).
~
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++