#include %zone function title "" lifespan 20 reset RESET_NOT creators {"bakka"} notes "&lThis Zone is not a zone at all. Like basis.zon it is a intergral part of the mud containing nothing but reuseable dil code. The code comes from various sources and is intended to allow builders to better utilize already created dil functions. After all there is no need to reinvent the wheel. Changes 12/07/95 - project started 12/07/95 - wander_zones 12/07/95 - scramble 12/07/95 - guard_level 12/10/95 - stealdil 12/10/95 - safe_room 01/06/95 - combat_mag 03/20/96 - added General channel functions. channel and recieve 03/20/96 - added new timer on blow away function. 04/09/96 - Added teach_q_block and shop_q_block. 04/29/96 - Added direction 05/08/96 - Added shopkeepers 05/11/96 - Added generic 'give' routine which reacts on special players. 15/10/96 - Added fido dil to take over for special 10/23/96 - fixed bug in clan channel 11/28/96 - Made it so that shopkeepers have their money stored on their home room to assure a daily maxmoney 12/21/96 removed old channel1 and channel2 that are no longer used. 02/05/97 - fixed clan channels to deal with new extra format 06/30/97 - Added storage 07/04/97 - Fixed Shopkeepers so they will only work if they can defend themselves. 07/08/97 - Fixed the wpntype dil. 07/22/97 - Added aggressive. " /* A short description of each function. See comments next to each dil for implementation notes. wander_zones - Allows a mob to wander around more than one zone, but not all zones. You specify what zones they mob can wander. Has optional intelligence which allows the opening and closeing of doors. scramble - Scramble the exits on a room. Simple way to turn a few rooms into a major maze. Use with extreem care, too much causes players to go nuts. guard_level - Guard an exit by a level range. stealdil - Randomly Steal an object from a player channel and recieve alternative channel updates made to be put on players. safe_room - Make a room safe from all sorts of attacks by pcs combat_mag - Replaces the special fun COMBAT_MAGIC and COMBAT_HEAL direction - Returns the direction in one of NORTH - DOWN. aggressive - make mobs aggressive to certain sex, alignment, race, level, etc. */ %dil dilbegin deputy_check(); code { :loop: wait(SFB_CMD, POLICE_ACADEMY in activator.quests); /* Lets not check for OUTLAW, since some weapons set it. Only if crimes > 0 will the player be banished (meaning that someone accused him) */ if (activator.crimes > 0) { addextra(activator.quests, {POLICE_BANNED}, ""); subextra(activator.quests, POLICE_ACADEMY); /* Clear all skills & spells taught by the law */ activator.skills[SKI_CUFF] := 0; exec("say "+activator.name+", I am very disappointed in you, you "+ "can no longer consider yourself a deputy.", self); } goto loop; } dilend /* function: Catchit descr: This function is to keep a mob from attacking a non-pk player while controlled by a player. This dil should be copied onto the mob when it is created and the pk value should be set so that it knows if its owner can pk or not. For an example of this function see the summon devil spell in spells.zon arguments: pk 1 for can pk 0 for can't */ dilbegin aware catchit(pk:integer); var pc:unitptr; code { :there: wait (SFB_PRE,(( command (CMD_AUTO_DAMAGE)) and (self==activator))); if (target.type!=UNIT_ST_PC) goto there; if ((isset (target.pcflags,PC_PK_RELAXED)) and (pk==1)) goto there; else { power:=-1; block; } goto there; } dilend /* function: nokill descr: This function is used to give a player pk protection for 10 minutes while recovering his/her corpse. The dil should be copied onto the player as he or she gets killed and it will remove itself after the player quits or the time expires. */ dilbegin aware recall no_kill (); code { interrupt (SFB_MSG,"remove kill prottection"==argument,dil_end); interrupt (SFB_CMD,(( command (CMD_QUIT)) and ( self==activator)), dil_end); interrupt (SFB_CMD,(( command (CMD_REMOVE)) and ("pk protection" ==argument) and (self==activator)), dil_end); heartbeat:=PULSE_SEC*600; if (isset (self.pcflags, PC_PK_RELAXED)) { unset (self.pcflags,PC_PK_RELAXED); act ("Due to your death you have been rewarded protection against PK for a short time.", A_ALWAYS,self,null,null,TO_CHAR); wait (SFB_TICK, TRUE); :dil_end: set (self.pcflags,PC_PK_RELAXED); act ("Your prottection from Pk has just worn off.", A_ALWAYS,self,null,null,TO_CHAR); quit; } else quit; } dilend /* function carry_n_limit(ch) descr: This function returns the amount of items that a person can carry arguments ch : a unitptr to the pc your checking. return: returns amount of items. */ dilbegin integer carry_n_limit(ch : unitptr); code { return (10 + (ch.abilities[ABIL_DEX]) / 10); } dilend /* Function: carry_w_limit(ch) descr: This function returns the amount of weight a person can carry. argument: ch : unitptr that you are checking. return: amount of weight player can carry. */ dilbegin integer carry_w_limit(ch : unitptr); var i : integer; code { i := ch.baseweight / 2; if (i < 50) i := 50; return (50 + i + ch.abilities[ABIL_STR]*2); } dilend /* function: Provoked_attack (vict, ch) descr: This function returns wether the offensive spell would be one that provokes the victum to attack or not. This is usfull in spells like disarm it is also used in skills like steal. arguments vict: the person you are doing the action on. ch: the person doing the act. */ dilbegin provoked_attack(victim : unitptr, ch : unitptr); code { if (not (victim.type & (UNIT_ST_NPC|UNIT_ST_PC))) return; /* FALSE */ if (not (ch.type & (UNIT_ST_PC|UNIT_ST_NPC))) return; /* FALSE */ if (victim.level >= 200) return; /* FALSE */ if (ch.level >= 200) return; /* FALSE */ if (not isset(ch.charflags, CHAR_SELF_DEFENCE)) { if ((ch.fighting == null) and (not isset(victim.charflags, CHAR_LEGAL_TARGET))) set(victim.charflags, CHAR_SELF_DEFENCE); } /* Test for LEGAL_TARGET bit */ if (isset(victim.charflags, CHAR_PROTECTED)) { if ((not isset(victim.charflags, CHAR_LEGAL_TARGET)) and (not isset(ch.charflags, CHAR_SELF_DEFENCE))) set(ch.charflags, CHAR_LEGAL_TARGET); } if (victim.position <= POSITION_SLEEPING) return; /* FALSE */ if (isset(victim.charflags, CHAR_PEACEFUL)) return; /* FALSE */ if (opponent(victim, ch)) return; /* TRUE */ set_fighting(victim, ch); return; /* TRUE */ } dilend /* function: hit_limit(i) descr: this is used in the heal spells in spells.zon to determin amount healed. *./ dilbegin integer hit_limit(i : integer); code { return (i * 3); } dilend /* You can add any number of hitpoints, even negative. Excess are chopped off to max_hp, negative may kill because of the position_update */ /* function: add_hitpoints descr: this function is used in the heal spells to add hit points. arguments: ch: person your adding to. php: amount your adding. */ dilbegin add_hitpoints(ch : unitptr, php : integer); code { ch.hp := ch.hp + php; if (ch.hp > ch.max_hp) ch.hp := ch.max_hp; position_update(ch); return; } dilend /* function: may_tele_away descr: This little function is to let you know if the unit is allowed to teleport from the current location. argument: u: unit that is teleporting. returns: true if the unit can teleport. false if not. */ dilbegin integer may_tele_away(u : unitptr); code { while (u) { if (u.flags & UNIT_FL_NO_TELEPORT) return(FALSE); u := u.outside; } return(TRUE); } dilend /* function: unit_room(u) descr: This function returns the room the pc is in no matter how many containers the pc, obj, room, or npc is in. arguments: u: pc to find the room from. returns: the unit pointer to the room. */ dilbegin unitptr unit_room(u : unitptr); code { while (u.type != UNIT_ST_ROOM) u := u.outside; return(u); } dilend /* function: unit_char(u) descr: this function finds the char which is a pc or npc that the unit is in. arguments: u: unit to find the pc or npc it is in from. return unit ptr to the unit npc or pc. */ dilbegin unitptr unit_char(u : unitptr); code { while ((u.type & (UNIT_ST_NPC | UNIT_ST_PC)) == 0) u := u.outside; return(u); } dilend /* function skill_resist. */ dilbegin integer skillresist(aa : integer, ad : integer, sa : integer, sd : integer); code { return (openroll(100, 5) + aa + sa - ad - sd - 50); } dilend dilbegin integer skill_duration(hm : integer); code { if (hm < 20) return (2); else if (hm > 150) return (15); else return (hm / 10); } dilend dilbegin string sizestring(cm : integer); var ftn : integer; fts : string; inn : integer; ins : string; code { /* One inch equals 2,54 cm. There are 12 inches (30.48 cm) to a foot */ ftn := cm / 30; inn := (10*(cm % 30))/25; if (ftn == 1) fts := "one foot"; else if (ftn > 1) fts := itoa(ftn)+" feet"; else fts := ""; if (inn == 1) ins := "one inch"; else if (inn > 1) ins := itoa(inn)+" inches"; else ins := ""; if (fts != "") { if (ins != "") fts := fts + " and "; } else { if (inn < 1) ins := "less than an inch"; } return (fts + ins); } dilend dilbegin string weightstring(p : integer); var s : string; code { if (p == 1) s := "one pound"; else if (p > 1) s := itoa(p)+" pounds"; else s := "less than a pound"; return (s); } dilend /* function walk_room purpose: to allow a mob to walk to a room even if he/she has to unlock open and close doors. */ dilbegin integer walk_room (place:string, spd:integer); external string dirstring@function (dr:integer); integer rev_dir@function (i:integer); var rm:unitptr; rdir:integer; dir : integer; dir_string : string; rdir_string : string; dr_name : string; heart : integer; thing : unitptr; code { :init: on_activation(self.position <= POSITION_SLEEPING, skip); log(itoa(spd)); if(( (spd*4) < 5) ) { heartbeat := 5 * 3; } else { heartbeat := spd * 3; } heart := heartbeat; :start: if (self.outside==thing) return (TRUE); wait(SFB_TICK, TRUE); /* Lets stand up if for some reason we are sitting */ if ((self.position == POSITION_RESTING) or (self.position == POSITION_SITTING)) { exec("stand", self); } /* if were not standing now then abort! */ if (self.position != POSITION_STANDING) return (FALSE); heartbeat := heart; thing:=findroom(place); log(thing.name); dir:=pathto (self,thing); if (dir==DIR_IMPOSSIBLE) return (FALSE); dir_string:=dirstring@function (dir); rdir:=rev_dir@function(dir); rdir_string :=dirstring@function (rdir); if (isset (self.outside.exit_info[dir], EX_LOCKED)) goto locked; if (isset (self.outside.exit_info[dir], EX_CLOSED)) { exec ("open "+dir_string+" "+self.outside.exit_names[dir].[0],self); exec (dir_string,self); exec ("close "+rdir_string+" "+self.outside.exit_names[rdir].[0],self); goto start; } :locked: if (isset (self.outside.exit_info[dir], EX_LOCKED)) { rm:=self.outside; unset(rm.exit_info[dir], EX_LOCKED); exec ("open "+dir_string+" "+self.outside.exit_names[dir].[0],self); exec (dir_string,self); exec ("close "+rdir_string+" "+self.outside.exit_names[rdir].[0],self); set(rm.exit_info[dir], EX_LOCKED); goto start; } if (dir== DIR_ENTER) exec (dir_string+" "+self.outside.exit_names[dir].[0],self); else exec(dir_string, self); goto start; } dilend /* function dirstring purpose: use to return the string of a direction when you ahve its number value. for example if you have DIR_NORTH you can use this like yourstring:=dirstring (DIR_NORTH); and it will return "north" in yourstring. */ dilbegin string dirstring (dr:integer); var dirlist:stringlist; code { dirlist := {"north","east","south","west","up","down","northeast", "northwest","southeast","southwest","enter","exit","impossible","here"}; return (dirlist.[dr]); } dilend /* function rev_dir purpose This function returns the oposite direction so if you have DIR_NORTH it will return the number value of south. */ dilbegin integer rev_dir(i : integer); var rev_dir : stringlist; code { rev_dir := {"2", "3", "0", "1", "5", "4", "9", "8", "7", "6"}; return (atoi(rev_dir.[i])); } dilend /* The following are the new restrict functions a doc called restrict.doc is in the valhalla doc directory for you to download and read to better understand how to use them. */ dilbegin guild_restrict (guilds:stringlist,damage:integer,percent:integer,action:string); var amount:integer; expd : extraptr; code { :start: wait (SFB_DONE, (((command (CMD_HOLD)) or (command (CMD_WEAR)) or (command (CMD_WIELD))) and (self==medium))); if (activator.type!=UNIT_ST_PC) goto start; if (activator.guild in guilds) goto start; if (self.outside.level>=IMMORTAL_LEVEL) goto start; expd := "$path" in self.outside.quests; if (expd != null) { if ((expd.names.[1] in guilds) or (expd.names.[2] in guilds) or (expd.names.[3] in guilds)) goto start; } if ((not( command (CMD_WEAR))) and (not(command (CMD_WIELD))) and (not(command (CMD_HOLD)))) goto start; if (action=="") { act ("Your $2n burns you and you drop it to the ground.", A_ALWAYS,self.outside,self,null,TO_CHAR); act ("$1n's $2n burns $1m and $1e drops it to the ground.", A_SOMEONE,self.outside,self,null,TO_REST); act ("Being in the right guild might help.", A_ALWAYS,self.outside,null,null,TO_CHAR); } else action (); if (percent!=0) amount:=(self.outside.hp*percent)/100; if (damage==-1) damage:=openroll (100,5); if (percent!=0) if (damage>amount) damage:=amount; else if (damage==0) damage:=amount; self.outside.hp:=self.outside.hp-damage; position_update (self.outside); unequip (self); link (self,self.outside.outside); goto start; } dilend dilbegin anti_guild (guilds:stringlist,damage:integer,percent:integer,action:string); var amount:integer; code { heartbeat:=PULSE_SEC*3; :start: wait (SFB_DONE, (((command (CMD_HOLD)) or (command (CMD_WEAR)) or (command (CMD_WIELD))) and (self==medium))); if (activator.type!=UNIT_ST_PC) goto start; if (not (activator.guild in guilds)) goto start; if (self.outside.level>=IMMORTAL_LEVEL) goto start; if (action =="") { act ("Your $2n burns you and you drop it to the ground.", A_ALWAYS,self.outside,self,null,TO_CHAR); act ("$1n's $2n burns $1m and $1e drops it to the ground.", A_SOMEONE,self.outside,self,null,TO_REST); act ("Not being in this guild might help.", A_ALWAYS,self.outside,null,null,TO_CHAR); } else action (); if (percent!=0) amount:=(self.outside.hp*percent)/100; if (damage==-1) damage:=openroll (100,5); if (percent!=0) if (damage>amount) damage:=amount; else if (damage==0) damage:=amount; self.outside.hp:=self.outside.hp-damage; position_update (self.outside); unequip (self); link (self,self.outside.outside); goto start; } dilend dilbegin quest_restrict (quest:string,damage:integer,percent:integer,action:string); var amount:integer; code { heartbeat:=PULSE_SEC*3; :start: wait (SFB_DONE, (((command (CMD_HOLD)) or (command (CMD_WEAR)) or (command (CMD_WIELD))) and (self==medium))); if (activator.type!=UNIT_ST_PC) goto start; if (quest in activator.quests) goto start; if (self.outside.level>=IMMORTAL_LEVEL) goto start; if (action=="") { act ("Your $2n burns you and you drop it to the ground.", A_ALWAYS,self.outside,self,null,TO_CHAR); act ("$1n's $2n burns $1m and $1e drops it to the ground.", A_SOMEONE,self.outside,self,null,TO_REST); act ("Doing the right Quest might help.", A_ALWAYS,self.outside,null,null,TO_CHAR); } else action (); if (percent!=0) amount:=(self.outside.hp*percent)/100; if (damage==-1) damage:=openroll (100,5); if (percent!=0) if (damage>amount) damage:=amount; else if (damage==0) damage:=amount; self.outside.hp:=self.outside.hp-damage; position_update (self.outside); unequip (self); link (self,self.outside.outside); goto start; } dilend dilbegin quests_restrict (qts:stringlist,damage:integer,percent:integer,action:string); var amount:integer; i:integer; code { :start: wait (SFB_DONE, (((command (CMD_HOLD)) or (command (CMD_WEAR)) or (command (CMD_WIELD))) and (self==medium))); if (activator.type!=UNIT_ST_PC) goto start; if (self.outside.level>=IMMORTAL_LEVEL) goto start; i:=0; while (qts.[i]!=null) { if (qts.[i]==null) break; if (qts.[i] in activator.quests) goto start; i:=i+1; } if (action=="") { act ("Your $2n burns you and you drop it to the ground.", A_ALWAYS,self.outside,self,null,TO_CHAR); act ("$1n's $2n burns $1m and $1e drops it to the ground.", A_SOMEONE,self.outside,self,null,TO_REST); act ("Doing the right Quest might help.", A_ALWAYS,self.outside,null,null,TO_CHAR); } else action (); if (percent!=0) amount:=(self.outside.hp*percent)/100; if (damage==-1) damage:=openroll (100,5); if (percent!=0) if (damage>amount) damage:=amount; else if (damage==0) damage:=amount; self.outside.hp:=self.outside.hp-damage; position_update (self.outside); unequip (self); link (self,self.outside.outside); goto start; } dilend dilbegin ali_restrict (max_ali:integer,min_ali:integer, damage:integer,percent:integer, action:string); var amount:integer; code { if (max_ali=min_ali)) goto start; if (self.outside.level>=IMMORTAL_LEVEL) goto start; if (action=="") { act ("Your $2n burns you and you drop it to the ground.", A_ALWAYS,self.outside,self,null,TO_CHAR); act ("$1n's $2n burns $1m and $1e drops it to the ground.", A_SOMEONE,self.outside,self,null,TO_REST); if (activator.alignment>max_ali) act ("You are to good to use $2n", A_ALWAYS,self.outside,self,null,TO_CHAR); else act ("You are to evil to use $2n", A_ALWAYS,self.outside,self,null,TO_CHAR); } else action (max_ali,min_ali); if (percent!=0) amount:=(self.outside.hp*percent)/100; if (damage==-1) damage:=openroll (100,5); if (percent!=0) if (damage>amount) damage:=amount; else if (damage==0) damage:=amount; self.outside.hp:=self.outside.hp-damage; position_update (self.outside); unequip (self); link (self,self.outside.outside); goto start; } dilend dilbegin level_restrict (lvl:integer,damage:integer,percent:integer, action:string); var amount:integer; code { :start: wait (SFB_DONE, (((command (CMD_HOLD)) or (command (CMD_WEAR)) or (command (CMD_WIELD))) and (self==medium))); if (activator.type!=UNIT_ST_PC) goto start; if (activator.level>=lvl) goto start; if (self.outside.level>=IMMORTAL_LEVEL) goto start; amount:=lvl-activator.level; if (action=="") { act ("Your $2n burns you and you drop it to the ground.", A_ALWAYS,self.outside,self,null,TO_CHAR); act ("$1n's $2n burns $1m and $1e drops it to the ground.", A_SOMEONE,self.outside,self,null,TO_REST); act ("You are not high enough level to use $3n. $2t levels needed to use it.", A_ALWAYS,self.outside,itoa (amount),self,TO_CHAR); } else action (amount); if (percent!=0) amount:=(self.outside.hp*percent)/100; if (damage==-1) damage:=openroll (100,5); if (percent!=0) if (damage>amount) damage:=amount; else if (damage==0) damage:=amount; self.outside.hp:=self.outside.hp-damage; position_update (self.outside); unequip (self); link (self,self.outside.outside); goto start; } dilend dilbegin race_restrict (rc:integer,damage:integer,percent:integer,action:string); var amount:integer; code { :start: wait (SFB_DONE, (((command (CMD_HOLD)) or (command (CMD_WEAR)) or (command (CMD_WIELD))) and (self==medium))); if (activator.type!=UNIT_ST_PC) goto start; if (activator.race!=rc) goto start; if (self.outside.level>=IMMORTAL_LEVEL) goto start; if (action=="") { act ("Your $2n burns you and you drop it to the ground.", A_ALWAYS,self.outside,self,null,TO_CHAR); act ("$1n's $2n burns $1m and $1e drops it to the ground.", A_SOMEONE,self.outside,self,null,TO_REST); act ("Being the right race might help.", A_ALWAYS,self.outside,null,null,TO_CHAR); } else action (); if (percent!=0) amount:=(self.outside.hp*percent)/100; if (damage==-1) damage:=openroll (100,5); if (percent!=0) if (damage>amount) damage:=amount; else if (damage==0) damage:=amount; self.outside.hp:=self.outside.hp-damage; position_update (self.outside); unequip (self); link (self,self.outside.outside); goto start; } dilend dilbegin string abistr (ability:integer); var ablst:stringlist; code { ablst:={"magic" , "divinity" , "strength" , "dextarity","constitution" , "charisma" ,"brains" , "hit points"}; return (ablst.[ability]); } dilend dilbegin abi_restrict (ab:integer,min_abi:integer, damage:integer,percent:integer, action:string); external string abistr (ability:integer); var amount:integer; abl:string; code { :start: wait (SFB_DONE, (((command (CMD_HOLD)) or (command (CMD_WEAR)) or (command (CMD_WIELD))) and (self==medium))); if (activator.type!=UNIT_ST_PC) goto start; if (activator.abilities[ab]>=min_abi) goto start; if (self.outside.level>=IMMORTAL_LEVEL) goto start; if (action =="") { act ("Your $2n burns you and you drop it to the ground.", A_ALWAYS,self.outside,self,null,TO_CHAR); act ("$1n's $2n burns $1m and $1e drops it to the ground.", A_SOMEONE,self.outside,self,null,TO_REST); amount:=min_abi-activator.abilities[ab]; abl:=abistr (ab); act ("You don't have enough "+abl+" to use $3n.", A_ALWAYS,self.outside,itoa (amount),self,TO_CHAR); act ("$2t more "+abl+" needed to use it.", A_ALWAYS,self.outside,itoa (amount),self,TO_CHAR); } else action (min_abi); if (percent!=0) amount:=(self.outside.hp*percent)/100; if (damage==-1) damage:=openroll (100,5); if (percent!=0) if (damage>amount) damage:=amount; else if (damage==0) damage:=amount; self.outside.hp:=self.outside.hp-damage; position_update (self.outside); unequip (self); link (self,self.outside.outside); goto start; } dilend dilbegin ski_restrict (ab:integer,min_abi:integer, damage:integer,percent:integer, action:string); var amount:integer; abl:string; code { :start: wait (SFB_DONE, (((command (CMD_HOLD)) or (command (CMD_WEAR)) or (command (CMD_WIELD))) and (self==medium))); if (activator.type!=UNIT_ST_PC) goto start; if (activator.skills[ab]>=min_abi) goto start; if (self.outside.level>=IMMORTAL_LEVEL) goto start; if (action =="") { act ("Your $2n burns you and you drop it to the ground.", A_ALWAYS,self.outside,self,null,TO_CHAR); act ("$1n's $2n burns $1m and $1e drops it to the ground.", A_SOMEONE,self.outside,self,null,TO_REST); amount:=min_abi-activator.skills[ab]; act ("You are not skilled enough to use $3n. $2t skill needed to use it.", A_ALWAYS,self.outside,itoa (amount),self,TO_CHAR); } else action (min_abi); if (percent!=0) amount:=(self.outside.hp*percent)/100; if (damage==-1) damage:=openroll (100,5); if (percent!=0) if (damage>amount) damage:=amount; else if (damage==0) damage:=amount; self.outside.hp:=self.outside.hp-damage; position_update (self.outside); unequip (self); link (self,self.outside.outside); goto start; } dilend dilbegin sp_restrict (ab:integer,min_abi:integer, damage:integer,percent:integer, action:string); var amount:integer; abl:string; code { :start: wait (SFB_DONE, (((command (CMD_HOLD)) or (command (CMD_WEAR)) or (command (CMD_WIELD))) and (self==medium))); if (activator.type!=UNIT_ST_PC) goto start; if (activator.spells[ab]>=min_abi) goto start; if (self.outside.level>=IMMORTAL_LEVEL) goto start; if (action =="") { act ("Your $2n burns you and you drop it to the ground.", A_ALWAYS,self.outside,self,null,TO_CHAR); act ("$1n's $2n burns $1m and $1e drops it to the ground.", A_SOMEONE,self.outside,self,null,TO_REST); amount:=min_abi-activator.spells[ab]; act ("You are not skilled enough to use $3n. $2t skill needed to use it.", A_ALWAYS,self.outside,itoa (amount),self,TO_CHAR); } else action (min_abi); if (percent!=0) amount:=(self.outside.hp*percent)/100; if (damage==-1) damage:=openroll (100,5); if (percent!=0) if (damage>amount) damage:=amount; else if (damage==0) damage:=amount; self.outside.hp:=self.outside.hp-damage; position_update (self.outside); unequip (self); link (self,self.outside.outside); goto start; } dilend dilbegin weap_restrict (ab:integer,min_abi:integer, damage:integer,percent:integer, action:string); var amount:integer; abl:string; code { :start: wait (SFB_DONE, (((command (CMD_HOLD)) or (command (CMD_WEAR)) or (command (CMD_WIELD))) and (self==medium))); if (activator.type!=UNIT_ST_PC) goto start; if (activator.weapons[ab]>=min_abi) goto start; if (self.outside.level>=IMMORTAL_LEVEL) goto start; if (action =="") { act ("Your $2n burns you and you drop it to the ground.", A_ALWAYS,self.outside,self,null,TO_CHAR); act ("$1n's $2n burns $1m and $1e drops it to the ground.", A_SOMEONE,self.outside,self,null,TO_REST); amount:=min_abi-activator.weapons[ab]; act ("You are not skilled enough to use $3n. $2t skill needed to use it.", A_ALWAYS,self.outside,itoa (amount),self,TO_CHAR); } else action (min_abi); if (percent!=0) amount:=(self.outside.hp*percent)/100; if (damage==-1) damage:=openroll (100,5); if (percent!=0) if (damage>amount) damage:=amount; else if (damage==0) damage:=amount; self.outside.hp:=self.outside.hp-damage; position_update (self.outside); unequip (self); link (self,self.outside.outside); goto start; } dilend dilbegin sex_restrict (sx:integer,damage:integer,percent:integer, action:string); var amount:integer; code { :start: wait (SFB_DONE, (((command (CMD_HOLD)) or (command (CMD_WEAR)) or (command (CMD_WIELD))) and (self==medium))); if (activator.type!=UNIT_ST_PC) goto start; if (activator.sex==sx) goto start; if (self.outside.level>=IMMORTAL_LEVEL) goto start; if (action=="") { act ("Your $2n burns you and you drop it to the ground.", A_ALWAYS,self.outside,self,null,TO_CHAR); act ("$1n's $2n burns $1m and $1e drops it to the ground.", A_SOMEONE,self.outside,self,null,TO_REST); act ("You are not the right sex to use $3n.", A_ALWAYS,self.outside,null,self,TO_CHAR); } else action (); if (percent!=0) amount:=(self.outside.hp*percent)/100; if (damage==-1) damage:=openroll (100,5); if (percent!=0) if (damage>amount) damage:=amount; else if (damage==0) damage:=amount; self.outside.hp:=self.outside.hp-damage; position_update (self.outside); unequip (self); link (self,self.outside.outside); goto start; } dilend dilbegin ply_restrict (person:string,damage:integer,percent:integer,action:string); var amount:integer; code { heartbeat:=PULSE_SEC*3; :start: wait (SFB_DONE, (((command (CMD_HOLD)) or (command (CMD_WEAR)) or (command (CMD_WIELD))) and (self==medium))); if (activator.type!=UNIT_ST_PC) goto start; if (person == activator.name) goto start; if (self.outside.level>=IMMORTAL_LEVEL) goto start; if (action=="") { act ("Your $2n burns you and you drop it to the ground.", A_ALWAYS,self.outside,self,null,TO_CHAR); act ("$1n's $2n burns $1m and $1e drops it to the ground.", A_SOMEONE,self.outside,self,null,TO_REST); act ("You realy shouldn't try to use someone elses personal item.", A_ALWAYS,self.outside,null,null,TO_CHAR); } else action (); if (percent!=0) amount:=(self.outside.hp*percent)/100; if (damage==-1) damage:=openroll (100,5); if (percent!=0) if (damage>amount) damage:=amount; else if (damage==0) damage:=amount; self.outside.hp:=self.outside.hp-damage; position_update (self.outside); unequip (self); link (self,self.outside.outside); goto start; } dilend /* This is an enhanced version of the Guard way SFUN. It will allow both certain players to enter as well as certain mobs. An optional stopdil can be supplied if you wish to do something special. It takes two arguments, the activator and the direction. Examples: dilcopy guard_dir@function(CMD_EAST, {"rejji"}, null, null); dilcopy guard_dir@function(CMD_SOUTH, {"papi", "whistler"}, {"welmar", "guard", "captain", "bipbop@kingc"); Important: The guard dir is ONLY active in the room in which the monster is initially loaded! Thus, if it is summoned it will not block directions until it is back where it was first created. */ dilbegin guard_dir(direction : integer, excludepc : stringlist, excludenpc : stringlist, stopdil : string); var place : integer; code { place := self.outside.idx; :start: wait(SFB_CMD, command(direction)); if (self.outside.idx != place) goto start; if (activator.type == UNIT_ST_PC) { if (activator.name in excludepc) goto start; goto stopit; } if (activator.name in excludenpc) goto start; :stopit: block; if (stopdil == "") { act ("$3n stops you and says, 'Members only!'", A_ALWAYS,activator,null,self,TO_CHAR); act ("$3n stops $1n, and says, 'Members only!'", A_SOMEONE,activator,null,self,TO_REST); } else { stopdil(activator, direction); } goto start; } dilend /* The okdil & notokdil are optional and both take two arguments of type unitptr - the activator and the key. This DIL can be used for many other things than keys.... Example: dilcopy key_give@function({"hugo", "bent"}, "key2@house", "key", "", ""); This will load the "key2@house" when either Bent or Hugo says "key". */ dilbegin key_give(pcnames : stringlist, keysym : string, word : string, okdil : string, notokdil : string); var key:unitptr; code { heartbeat := PULSE_SEC*5; :start: wait(SFB_DONE, command(CMD_SAY) and (word in argument)); if (activator.name in pcnames) { key := load (keysym); link (key, activator); if (okdil == "") { act ("$3n gives $1n $2n.", A_SOMEONE, activator, key, self, TO_REST); act ("$3n gives you $2n.", A_SOMEONE,activator,key,self,TO_CHAR); } else { okdil(activator, key); } } else { if (notokdil == "") { exec("say I don't know you.",self); } else { notokdil(activator, key); } } goto start; } dilend /* The following dils are the shopkeepers in dil. For more information look at the shopkeeper.doc. */ /*************************************************************************** ***/ #define STATE_OPEN 0 #define STATE_CLOSED 1 dilbegin integer isopen( times : stringlist ); var time1 : integer; time2 : integer; code { if( length( times ) < 2 ) return(STATE_OPEN); time1 := atoi( times.[0] ); time2 := atoi( times.[1] ); if( time1 == time2 ) return(STATE_OPEN); if( time1 < time2 ) if( ( mudhour >= time2 ) or ( mudhour < time1 ) ) return(STATE_CLOSED); if( time1 > time2 ) if( ( mudhour >= time2 ) and ( mudhour < time1 ) ) return(STATE_CLOSED); return(STATE_OPEN); } dilend /*************************************************************************** ***/ dilbegin string wpntype( obj : unitptr ); code{ if( not( obj.type & UNIT_ST_OBJ ) ) return(""); if( obj.objecttype == ITEM_WEAPON ) on obj.value[0] goto root,axe,sword,club_mace,polearm,unarmed,special, battle_axe,hand_axe,war_mattock,war_hammer,great_sword,scimitar,katana, falchion,kopesh,broad_sword,long_sword,rapier,short_sword,dagger, battle_mace,mace,battle_club,club,morning_star,flail,quarterstaff, spear,halberd,bardiche,sickle,scythe,trident, fist,kick,bite,sting,claw,crush,whip,wakizashi,bow,throw,blank0,blank1, blank2,blank3,blank4; return(""); :root: return("[Root]"); :axe: return("[Axe/Hammer]"); :sword: return("[Sword]"); :club_mace: return("[Club/Mace]"); :polearm: return("[Polearm]"); :unarmed: return("[Unarmed]"); :special: return("[Special]"); :battle_axe: return("[Battle Axe]"); :hand_axe: return("[Hand Axe]"); :war_mattock: return("[War Mattock]"); :war_hammer: return("[War Hammer]"); :great_sword: return("[Great Sword]"); :scimitar: return("[Scimitar]"); :katana: return("[Katana]"); :falchion: return("[Falchion]"); :kopesh: return("[Kopesh]"); :broad_sword: return("[Broad Sword]"); :long_sword: return("[Long Sword]"); :rapier: return("[Rapier]"); :short_sword: return("[Short Sword]"); :dagger: return("[Dagger]"); :battle_mace: return("[Battle Mace]"); :mace: return("[Mace]"); :battle_club: return("[Battle Club]"); :club: return("[Club]"); :morning_star: return("[Morning Star]"); :flail: return("[Flail]"); :quarterstaff: return("[Staff]"); :spear: return("[Spear]"); :halberd: return("[Halberd]"); :bardiche: return("[Bardiche]"); :sickle: return("[Sickle]"); :scythe: return("[Scythe]"); :trident: return("[Trident]"); :fist: return("[Fist]"); :kick: return("[Kick]"); :bite: return("[Bite]"); :sting: return("[Sting]"); :claw: return("[Claw]"); :crush: return("[Crush]"); :whip: return("[Whip]"); :wakizashi: return("[Wakizashi]"); :bow: return("[Bow]"); :throw: return("[Throw]"); :blank0: return("[Blank0]"); :blank1: return("[Blank1]"); :blank2: return("[Blank2]"); :blank3: return("[Blank3]"); :blank4: return("[Blank4]"); } dilend /*************************************************************************** ***/ /* Makes sure that the items sold are first in the list. */ dilbegin shop_sort( ); var item : unitptr; dest : unitptr; nxt : unitptr; code{ dest := load( "bag@midgaard" );/* Load something to store in */ item := self.inside; while( item ) /* Store all items that have a price tag */ { nxt := item.next; if( "$price" in item.extra ) link( item, dest ); item := nxt; } item := dest.inside; while( item ) /* Put all items back inside shopkeeper */ { nxt := item.next; link( item, self ); item := nxt; } destroy( dest ); return; } dilend /*************************************************************************** ***/ /* This is added to all shopitems so they wont have a pricetag when stolen or is some gods forces them to drop the items... */ dilbegin shopown( ); var owner : unitptr; code{ owner := self.outside; secure( owner, gone ); heartbeat:= PULSE_SEC*5; :loop: wait( SFB_TICK, TRUE ); if( owner == self.outside ) goto loop; :gone: subextra( self.extra, "$price" ); quit; } dilend /*************************************************************************** ***/ #define LOG(_CMDSTR) log(self.nameidx+"/"+rom.nameidx+"Shop error - "+_CMDSTR) #define BUY_PRICE(u) ((u.cost * buyprofit)/100) #define SELL_PRICE(u) ((u.cost * sellprofit)/100) dilbegin aware shopkeeper(prod : stringlist, custom_acts : stringlist, opentimes : stringlist, itemtype : string, sellprofit : integer, buyprofit : integer, maxcash : integer, closedil : string, dilparams : string ); external integer isopen( opentimes : stringlist ); integer carry_n_limit( ch : unitptr ); integer carry_w_limit( ch : unitptr ); string wpntype( obj : unitptr ); shop_sort( ); var temp_nitem : integer; /* added to fix a bug with act */ sitem : integer; /* Selected item */ citem : integer; /* Current item */ mitem : integer; /* Max item */ iteml : stringlist; /* Item list */ items : string; /* Item symbolic */ itmsl : stringlist; /* Items symbolc list */ itmsn : stringlist; /* Itemlist including names */ nitml : stringlist; /* Current number of items */ mitml : stringlist; /* Max number of items */ produ : stringlist; /* Copy of prod, but only functioning items */ cisl : stringlist; /* Complete item symbolic list */ acts : stringlist; arg : string; /* Argument */ nitem : integer; /* Number of items */ clc : integer; /* Calculations integer */ tmps : string; /* Crap string */ u : unitptr; /* Crap unitptr */ rom : unitptr; pc : unitptr; tu : unitptr; /* Temporary unit */ ts : stringlist; /* Temporary stringlist */ fitstr : string; /* Fit string */ wpnstr : string; /* Weapon string */ ti : integer; /* Temporary integer */ ts1 : string; /* Temporary string */ ts2 : string; /* Temporary string */ ext : extraptr; /* Temporary extraptr */ types : stringlist; /* Extraptr holding item types traded. */ closed : integer; /* Open/Closed flag */ tm : integer; /* For cost calculation */ cc : integer; /* Cost */ openstat : integer; /* Current shop status: Open or Closed */ chgtime : integer; /* Time for next change of shop status */ choice : integer; /* Command choice */ foundany : integer; /* If any items was in list */ homes : string; /* Symbolic of room where we were first loaded */ home : unitptr; /* Home room where we were first loaded */ mys : string; /* Symbolic of the shopkeeper */ account : extraptr; /* Where we store our money */ noaccount : integer; /* Is there a account already? */ code { :init: /* Everything is handled by a price extra and an item list */ /* Any item in inv without a pricetag can't be sold! */ heartbeat := 3; rom := self; while( not( rom.type & UNIT_ST_ROOM ) ) rom := rom.outside; /* Made it so that the shopkeeper stores the amount of money he has */ /* left in an extra on his "home room". This way the shopkeeper does */ /* not have full money every time he is killed, only refreshed once */ /* per day or after a reboot/crash as it should. (Nexus) */ homes := rom.nameidx+"@"+rom.zoneidx; mys := self.nameidx+"@"+self.zoneidx; home := findroom(homes); account := "$Shop Account" in home.extra; if ((account) and (mys in account.names)) noaccount := 0; else if (account) { log(self.nameidx+"/"+rom.nameidx+" Shop Error - Found other "+ "shopkeeper's account"); noaccount := 0; } else /* make account */ { ts := {"$Shop Account"}; addstring(ts,mys); addextra(home.extra,ts,""); noaccount := 1; } if( length( custom_acts.[0] ) > 0 ) addstring( acts, custom_acts.[0] ); else addstring( acts, "$1n says, 'I've got no such item!'" ); if( length( custom_acts.[1] ) > 0 ) addstring( acts, custom_acts.[1] ); else addstring( acts, "$1n says, '$3n, you havn't even got it!'" ); if( length( custom_acts.[2] ) > 0 ) addstring( acts, custom_acts.[2] ); else addstring( acts, "$1n says, 'I don't trade with things such as $2n'" ); if( length( custom_acts.[3] ) > 0 ) addstring( acts, custom_acts.[3] ); else addstring( acts, "$1n says, '$3n, you can't afford $2n'" ); if( length( custom_acts.[4] ) > 0 ) addstring( acts, custom_acts.[4] ); else addstring( acts, "$1n says, 'Here is $2n'" ); if( length( custom_acts.[5] ) > 0 ) addstring( acts, custom_acts.[5] ); else addstring( acts, "$1n says, 'Thank you for $2n'" ); if( length( custom_acts.[6] ) > 0 ) addstring( acts, custom_acts.[6] ); else addstring( acts, "$1n says, 'I don't seem to have that many $2ns in my stock'" ); if( length( custom_acts.[7] ) > 0 ) addstring( acts, custom_acts.[7] ); else addstring( acts, "$1n says, 'The shop is closed, come back later'" ); if( length( custom_acts.[8] ) > 0 ) addstring( acts, custom_acts.[8] ); else addstring( acts, "$1n says, '$3n, I have no use for $2n.'" ); if( length( custom_acts.[9] ) > 0 ) addstring( acts, custom_acts.[9] ); else addstring( acts, "$1n says, 'It looks like i don't have enough cash for it.'" ); /* Brain segment added by Eirinn December 7th to counteract stealing. */ if ((self.level < 10) and (self.abilities[ABIL_BRA] < 50)) self.abilities[ABIL_BRA] := 50; else if ((self.level < 20) and (self.level >= 10) and (self.abilities[ABIL_BRA] < 75)) self.abilities[ABIL_BRA] := 75; else if ((self.level < 30) and (self.level >= 20) and (self.abilities[ABIL_BRA] < 100)) self.abilities[ABIL_BRA] := 100; else if ((self.level < 40) and (self.level >= 30) and (self.abilities[ABIL_BRA] < 125)) self.abilities[ABIL_BRA] := 125; else if ((self.level >=40) and (self.abilities[ABIL_BRA] < 150)) self.abilities[ABIL_BRA] := 150; iteml := prod; /* Init. all needed system lists! */ itmsl := null; produ := null; itmsn := null; mitml := null; nitml := null; citem := 0; tm := 0; while( citem < length( iteml ) ) { tmps := iteml.[citem]; items := getword( tmps ); ts1 := getword( tmps ); ts2 := getword( tmps ); u := load( items ); secure( u, lost_u ); if( u ) { if( ( atoi( ts1 ) > 0 ) and ( atoi( ts2 ) > 0 ) ) { if( not( items in itmsl ) ) { if( not( u.name in itmsn ) ) { addstring( produ, iteml.[citem] ); addstring( itmsl, items ); addstring( nitml, ts2 ); addstring( mitml, ts2 ); addstring( itmsn, u.name ); tmps := moneystring( ( u.cost * sellprofit )/100, 0 ); addextra( u.extra, {"$price"}, tmps ); } else { LOG( "2 or more items with the same first name '" + u.name + "'" ); destroy( u ); } } else { LOG( "Duplicate items in shop, item '" + items + "'" ); destroy( u ); } } else { LOG( "Illegal unit definition '" + iteml.[citem] + "'" ); destroy( u ); } } else LOG( "Error loading item '" + items + "'" ); :lost_u: unsecure( u ); citem := citem + 1; tm := tm + 1; if( tm == 5 ) { pause; tm := 0; } } cisl := itmsl; interrupt( SFB_DEAD, self==activator, destroy_items ); if( length( dilparams ) < 2 ) dilparams := "()"; else if( not ( "(" in dilparams ) ) /* No spaces in parameters.. add some */ dilparams := "(" + dilparams + ")"; types := null; ts1 := itemtype; while( length( ts1 ) > 0 ) { ts2 := getword( ts1 ); if( atoi( ts2 ) > 0 ) addstring( types, ts2 ); } pause; heartbeat := PULSE_SEC * 30; if (noaccount) goto newday; /* credit account */ else goto no_credit; /* don't credit account */ :check_open: sendto( "closing", self ); heartbeat := PULSE_SEC * 30; if( length( closedil ) > 0 ) if( not( "(" in closedil or ")" in closedil ) ) dilcopy( closedil + dilparams, self ); :loop_closed: wait( SFB_CMD|SFB_TICK|SFB_DONE, TRUE ); /* POSITION_RESTING condition added by Eirinn 4th July '97 */ if ( self.position < POSITION_RESTING) goto loop_closed; if( command( CMD_LIST ) or command( CMD_BUY ) or command( CMD_SELL ) or command( CMD_VALUE ) or command( CMD_REQUEST ) ) { block; act( acts.[7], A_SOMEONE, self, u, activator, TO_VICT ); } else if( not( command( CMD_AUTO_TICK ) or command( CMD_GIVE ) ) ) goto loop_closed; closed := isopen( opentimes ); if( closed == STATE_OPEN ) { closed := dildestroy( closedil, self ); closed := STATE_OPEN; goto newday; } if( ( atoi( opentimes.[0] ) - 1 ) == mudhour ) sendto( "opening", self ); if( command( CMD_GIVE ) and medium ) { if( "$price" in medium.extra ) subextra( medium.extra, "$price" ); } shop_sort(); goto loop_closed; :loop: closed := isopen( opentimes ); if( closed ) goto check_open; shop_sort(); wait( SFB_CMD|SFB_TICK|SFB_DONE, TRUE ); closed := isopen( opentimes ); if( closed ) goto check_open; if( command( CMD_AUTO_TICK ) ) goto loop; if( command( CMD_GIVE ) ) { if( not medium ) goto loop; if( "$price" in medium.extra ) subextra( medium.extra, "$price" ); goto loop; } if( ( self.position == POSITION_FIGHTING ) or ( self.position < POSITION_RESTING ) ) goto loop; if( command( CMD_LIST ) ) choice := 0; else if( command( CMD_BUY ) ) choice := 1; else if( command( CMD_SELL ) ) choice := 2; else if( command( CMD_VALUE ) ) choice := 3; else if( command( CMD_REQUEST ) ) choice := 4; else if( command( "stock" ) and ( activator.level >= IMMORTAL_LEVEL ) ) choice := 5; else goto loop; pc := activator; if( not visible( pc, self ) ) goto loop; block; if( not visible( self, pc ) ) { exec( "say I only do business with people i can see.", self ); goto loop; } arg := argument; secure( pc, lost_pc ); on choice goto list,buy,sell,check_value,request,stock; log( "Something is wrong, shop triggered on an unknown command." ); unsecure( pc ); goto loop; :stock: mitem := length( produ ); citem := 0; items := self.nameidx + "@" + self.zoneidx + " current stock:&n"; while( citem < mitem ) { tmps := produ.[citem]; items := items + " " + getword( tmps ) + " P: " + getword( tmps ) + ", M: " + mitml.[citem]; items := items + ", C: " + nitml.[citem] + "&n"; citem := citem + 1; } sendtext( items, pc ); unsecure( pc ); goto loop; :newday: /* New day, increase stock & load stolen/soldout goods */ home := findroom(homes); account := "$Shop Account" in home.extra; if ((account) and (mys in account.names)) account.descr := itoa(maxcash); /* fill daily account */ else if (account) log(self.nameidx+"/"+rom.nameidx+"Shop Error - The account I found is not mine!"); else log(self.nameidx+"/"+rom.nameidx+"Shop Error - Can't find a shop account!"); :no_credit: /* Go here if account should not be credited */ mitem := length( itmsl ); citem := 0; while( citem < mitem ) { items := produ.[citem]; tmps := getword( items ); tmps := itoa( atoi( nitml.[citem] ) + atoi( getword( items ) ) ); ts1 := getword( items ); if( atoi( tmps ) > atoi( ts1 ) ) tmps := ts1; nitml.[citem] := tmps; u := findunit( self, itmsn.[citem], FIND_UNIT_INVEN, null ); if( ( u == null ) and ( atoi( tmps ) > 0 ) ) { u := load( itmsl.[citem] ); tmps := moneystring( ( u.cost * sellprofit ) / 100, 0 ); addextra( u.extra, {"$price"}, tmps ); } else if( not( "$price" in u.extra ) and ( atoi( tmps ) != 0) ) { if( ( u.nameidx + "@" + u.zoneidx ) != itmsl.[citem] ) u := load( itmsl.[citem] ); tmps := moneystring( ( u.cost * sellprofit ) / 100, 0 ); addextra( u.extra, {"$price"}, tmps ); } citem := citem + 1; } goto loop; :request: /* Price request on item in own inv. */ u := findunit( self, arg, FIND_UNIT_INVEN, null ); if( u == null) { act( acts.[0], A_SOMEONE, self, null, pc, TO_VICT ); } else { ext := "$price" in u.extra; if( ext ) { if( ext.descr == "" ) act( "$1n says, 'I'll give $2n away for free'", A_SOMEONE, self, u, pc, TO_VICT); else act( "$1n says, 'I want "+ext.descr+" for $2n'", A_SOMEONE, self, u, pc, TO_VICT); } else act( acts.[0], A_SOMEONE, self, u, pc, TO_VICT ); } unsecure( pc ); goto loop; :sell: /* Sell routine for players to sell to shopkeeper */ u := findunit( pc, arg, FIND_UNIT_INVEN, null ); if( u == null ) { act( acts.[1], A_SOMEONE, self, null, pc, TO_VICT ); } else { if( "$no-sell" in u.extra ) { act( acts.[8], A_SOMEONE, self, u, pc, TO_VICT ); unsecure( pc ); goto loop; } if( not( itoa( u.objecttype ) in types ) ) { act( acts.[2], A_SOMEONE, self, u, pc, TO_VICT ); unsecure( pc ); goto loop; } cc := u.cost; if( cc < 0 ) cc := 0; tm := ( cc * buyprofit ) / 100; home := findroom(homes); account := "$Shop Account" in home.extra; if ((account) and (mys in account.names)) /* do account stuff */ { ti := atoi(account.descr); if (tm > ti) { act( acts.[9], A_SOMEONE, self, u, pc, TO_VICT ); unsecure( pc ); goto loop; } ti := ti - tm; account.descr := itoa(ti); } else /* if no account or other shopkeeper's, say can't afford */ { act( acts.[9], A_SOMEONE, self, u, pc, TO_VICT ); unsecure( pc ); goto loop; log(self.nameidx+"/"+rom.nameidx+ "Shop Error - Can't find my "+ "shop account!"); } log(self.nameidx+"/"+rom.nameidx+ "Shop Error - Can't find my shop account!"); citem := transfermoney( null, pc, tm ); tmps := moneystring( ( cc * sellprofit ) / 100, FALSE ); if( not( "$price" in u.extra ) ) addextra( u.extra, {"$price"}, tmps ); /* act( acts.[5], A_SOMEONE, self, u, pc, TO_VICT ); */ tmps := moneystring( ( cc * buyprofit ) / 100, FALSE ); act( "$1n says, 'I paid you $2t for that $3n'", A_SOMEONE, self, tmps, pc, TO_ALL ); link( u, self ); if( ( u.nameidx + "@" + u.zoneidx ) in itmsl ) { mitem := length( itmsl ); citem := 0; sitem := ( u.nameidx + "@" + u.zoneidx ) in itmsl; nitml.[sitem - 1] := itoa( atoi( nitml.[sitem - 1] ) + 1 ); destroy( u ); } else if( ( u.nameidx + "@" + u.zoneidx ) in cisl )/* If already in store*/ { /* destroy new item. */ destroy( u ); } else /* If not in store already */ { /* add to store list */ if( length( cisl ) >= 24 ) /* Allow only 24 items in list */ destroy( u ); else addstring( cisl, u.nameidx+"@"+u.zoneidx ); } } unsecure( pc ); goto loop; :check_value: /* Check value of item in players inv. on request */ u := findunit( pc, arg, FIND_UNIT_INVEN, null); if( "$no-sell" in u.extra ) { act( acts.[8], A_SOMEONE, self, u, pc, TO_VICT ); unsecure( pc ); goto loop; } if( u != null ) { tmps := moneystring( ( u.cost * buyprofit ) / 100, 0 ); act( "$1n says, 'I'll pay " + tmps + " for the $2N'", A_SOMEONE, self, u, pc, TO_VICT ); } else act( acts.[1], A_SOMEONE, self, null, pc, TO_VICT ); unsecure( pc ); goto loop; :buy: /* Buy routine */ nitem := 0; tm := 0; nitem := atoi( getword( arg ) ); if (nitem < 0) { act("$1n says, 'How are you planning to buy a negative number of items?'", A_SOMEONE, self, null, pc, TO_ALL ); } else if(( nitem > 1 ) and ( arg != "" )) { /* If bigger than 0, then a multiple number was requested */ if( nitem > 100 ) { act( "$1n says, 'I don't sell over 100 items at one time'", A_SOMEONE, self, null, pc, TO_ALL ); unsecure( pc ); goto loop; } u := findunit( self, arg, FIND_UNIT_INVEN, null ); /*Check inventory */ if( "$price" in u.extra ) /* If in inventory */ { clc := can_carry( pc, u, nitem ); if( clc == 1 ) { act("Your hands are full!", A_SOMEONE, self, null, pc, TO_VICT ); unsecure( pc ); goto loop; } else if( clc == 2 ) { act("You can't carry the weight!", A_SOMEONE, self, null, pc, TO_VICT ); unsecure( pc ); goto loop; } cc := u.cost; /* Get item cost */ items := u.nameidx + "@" + u.zoneidx; /* Get symbolic name */ sitem := items in itmsl; if( sitem ) cc := (cc * atoi( mitml.[sitem - 1] )) / atoi( nitml.[sitem - 1] ); if( pc.level > IMMORTAL_LEVEL ) tm := 1; else tm := transfermoney( pc, null, cc * nitem ); if ( tm ) { if ( items in itmsl ) /* Check if standard item */ { if( nitem <= atoi( nitml.[sitem - 1] ) ) { nitml.[sitem - 1] := itoa(atoi( nitml.[sitem - 1] ) - nitem); if( nitml.[sitem - 1] == "0" ) destroy( u ); else { subextra( u.extra, "$price" ); tmps := moneystring( ( u.cost * sellprofit * atoi( mitml.[sitem-1] ) / atoi( nitml.[sitem-1] ) ) / 100, 0 ); addextra( u.extra, {"$price"}, tmps ); } temp_nitem:=nitem; while( temp_nitem > 0 ) /* Load and link all items */ { tu := load( items ); tu.height := pc.height; link( tu, pc ); temp_nitem := temp_nitem- 1; } tmps := moneystring( (cc * nitem), FALSE ); act( "$1n says, 'Those cost you $2t", A_SOMEONE, self, tmps, pc, TO_ALL ); act( "$1n gives you " + getword( argument ) + " $2n.", A_SOMEONE, self, u, pc, TO_VICT ); act( "$1n gives $3n some $2ns.", A_SOMEONE, self, u, pc, TO_NOTVICT ); } else { if (transfermoney( null, pc, cc * nitem ) and FALSE) exec("grin",self); act( acts.[6], A_SOMEONE, self, u, pc, TO_ALL ); } } else /* Not standard item, can't buy multiple.. */ act( acts.[6], A_SOMEONE, self, u, pc, TO_ALL ); } else { act( acts.[3], A_SOMEONE, self, u, pc, TO_ALL ); } } else { act( acts.[0], A_SOMEONE, self, null, pc, TO_ALL ); } } else { if( nitem == 1 ) u := findunit( self, arg, FIND_UNIT_INVEN, null ); else u := findunit( self, argument, FIND_UNIT_INVEN, null ); if( "$price" in u.extra ) { clc := can_carry( pc, u, 1 ); if( clc == 1 ) { act("Your hands are full!", A_SOMEONE, self, null, pc, TO_VICT ); unsecure( pc ); goto loop; } else if( clc == 2 ) { act("You can't carry the weight!", A_SOMEONE, self, null, pc, TO_VICT ); unsecure( pc ); goto loop; } cc := (u.cost * sellprofit) / 100; items := u.nameidx + "@" + u.zoneidx; sitem := items in itmsl; if( sitem ) cc := (cc * atoi( mitml.[sitem - 1] )) / atoi( nitml.[sitem - 1] ); /* If buyer is a god, don't take money */ if( pc.level >= IMMORTAL_LEVEL ) tm := 1 else tm := transfermoney( pc, null, cc ); if( tm != 0) { if( items in itmsl ) { mitem := length(itmsl); citem := 0; if( atoi( nitml.[sitem - 1] ) > 0 ) { nitml.[sitem-1] := itoa( atoi( nitml.[sitem-1] ) - 1 ); ext := "$price" in u.extra; tmps := ext.descr; act( "$1n says, 'That cost you $2t", A_SOMEONE, self, tmps, pc, TO_ALL ); /* act( acts.[4], A_SOMEONE, self, u, pc, TO_ALL ); */ if( nitml.[sitem-1] == "0" ) destroy( u ); else { subextra( u.extra, "$price" ); tmps := moneystring( ( u.cost * sellprofit * atoi( mitml.[sitem-1] ) / atoi( nitml.[sitem-1] ) ) / 100, 0 ); addextra( u.extra, {"$price"}, tmps ); } tu := load( items ); tu.height := pc.height; link( tu, pc ); } else act( acts.[0], A_SOMEONE, self, null, pc, TO_ALL ); } else { tmps := moneystring( cc, FALSE ); act( "$1n says, 'That cost you $2t", A_SOMEONE, self, tmps, pc, TO_ALL ); /* act( acts.[4], A_SOMEONE, self, u, pc, TO_ALL ); */ subextra( u.extra, "$price" ); substring( cisl, u.nameidx+"@"+u.zoneidx ); link( u, pc ); } } else { act( acts.[3], A_SOMEONE, self, u, pc, TO_ALL ); } } else act( acts.[0], A_SOMEONE, self, null, pc, TO_ALL ); } unsecure( pc ); goto loop; :list: act( "Items in store:", A_SOMEONE, self, null, pc, TO_VICT ); u := self.inside; sitem := 0; foundany := 0; while( u ) { ext := "$price" in u.extra; if( ext ) { if( u.minv <= pc.level ) { tmps := ext.descr; if ( u.objecttype == ITEM_WEAPON ) { wpnstr := wpntype( u ); wpnstr := wpnstr + " "; } else wpnstr := ""; fitstr := fits( pc, u, -1 ); foundany := 1; citem := ( u.nameidx + "@" + u.zoneidx ) in itmsl; if ( citem > 0 ) /* ( u.nameidx + "@" + u.zoneidx ) in itmsl )*/ { act(" [" + nitml.[citem - 1] + "] $2N " + wpnstr + "at " + tmps + ".", A_ALWAYS, self, u, pc, TO_VICT ); } else { if (fitstr != "") fitstr := fitstr + " "; act( " [1] $2N " + wpnstr + "&c+c" + fitstr + "&cwat " + tmps + ".", A_ALWAYS, self, u, pc, TO_VICT ); } } } sitem := sitem + 1; if( sitem == 50 ) /* This shouldn't be required, but pause */ { /* to prevent destruction of dil */ sitem := 0; secure( u, lost_unit); heartbeat := 2; wait(SFB_TICK, TRUE); heartbeat := PULSE_SEC * 30; unsecure( u ); } u := u.next; } if( foundany == 0 ) act( "None!", A_SOMEONE, self, null, pc, TO_VICT ); unsecure( pc ); goto loop; :lost_unit: unsecure( u ); goto loop; :lost_pc: unsecure( pc ); goto loop; :destroy_items: /* Wipe all units that shopkeeper used to sell */ u := self.inside; while(u!=null) { pc := u.next; subextra(u.extra,"$price"); if(((u.nameidx+"@"+u.zoneidx) in cisl) and (u.equip==0)) destroy(u); u := pc; } quit; } dilend /* shopkeeper */ dilbegin integer direction(dir : string); code { dir := " " + getword(dir); if (dir in " north") return (CMD_NORTH); else if (dir in " east") return (CMD_EAST); else if (dir in " south") return (CMD_SOUTH); else if (dir in " west") return (CMD_WEST); else if (dir in " up") return (CMD_UP); else if (dir in " down") return (CMD_DOWN); else if (dir in " northeast") return (CMD_NORTHEAST); else if (dir in " northwest") return (CMD_NORTHWEST); else if (dir in " southeast") return (CMD_SOUTHEAST); else if (dir in " southwest") return (CMD_SOUTHWEST); return (-1); } dilend dilbegin busy (s:string); code { :start: wait (SFB_DONE, command(CMD_GIVE) and (self==target)); exec ("say "+s, self); exec ("drop "+medium.name, self); goto start; } dilend dilbegin string accept_dil (pc:unitptr,s:string); var i:integer; code { heartbeat := PULSE_SEC*7; secure(pc,losthim); exec ("say "+s,self); i := 0; while (i < 5) { wait(SFB_CMD, activator == pc); if (command(CMD_NOD)) return ("yes"); else if (command(CMD_SAY) and (argument =="yes")) return ("yes"); else if (command(CMD_SHAKE)) return ("no"); else if (command(CMD_SAY) and (argument =="no")) return ("no"); else { /* This specifies what happens if the pc does something else*/ pause; exec ("say "+s,self); } i := i+1; pause; } :losthim: return ("no"); } dilend /* Blocks the buy & sell commands unless he has completed the quest in the string 'q'. If not, the string 's' is executed by owner (self). For example: dilcopy teach_q_block@function("$Police Academy", "say Deputies only!"); special SFUN_TEACH_INIT ... */ dilbegin shop_q_block(q : string, s : string); code { :loop: wait(SFB_CMD, command(CMD_BUY) or command(CMD_SELL)); if (not (q in activator.quests)) { exec(s, self); block; } goto loop; } dilend /* Blocks the practice command unless he has completed the quest in the string 'q'. If not, the string 's' is executed by owner (self). For example: dilcopy teach_q_block@function("Mary's Pot Complete", "say Buggar ye off"); special SFUN_TEACH_INIT ... */ dilbegin teach_q_block(q : string, s : string); code { :loop: wait(SFB_CMD, command(CMD_PRACTICE)); if (not (q in activator.quests)) { exec(s, self); block; } goto loop; } dilend /* function blowaway used on: items and even mobs shiver example: dilcopy blowaway (1500,"this is the act"); */ dilbegin blowaway(seconds:integer,s : string); code { heartbeat := PULSE_SEC *seconds; :loop: pause; if (self.outside.type == UNIT_ST_ROOM) { if (not isset(self.flags, UNIT_FL_BURIED)) act(s, A_SOMEONE, self, null, null, TO_ROOM); destroy(self); } goto loop; } dilend /* The climb skill as a special routine to be connected to ROOMS Ticks : None Used on: ROOMS Syntax : climb(destination:string, difficulty:integer, damage : integer, direction : integer); Example: dilcopy climb@function("deck@ship", 17, 20, CMD_UP); This special dil is used for the climb skill and should be set on stationary objects (stationary mast, robe, tree, wall, etc). The is the skill-amount required to climb. A skill of 100 would be a 50% chance for the expert thief / climber. The is how much damage is given if you fail to climb the object. When you fail, you "fall" to the , so you can make gravity work correctly. The destination can be the same room in which you started. The is the direction in which a climb is required (most usually it is up, which is macro UP == 5). */ dilbegin climb(destination:string, difficulty:integer, damage:integer, direction:integer); external integer skillresist(aa : integer, ad : integer, sa : integer, sd : integer); var dest : unitptr; skilla : integer; hm : integer; doorname : string; code { if (not self.exit_to[direction]) { log("No such exit in climb dil."); quit; } if (not findroom(destination)) { log("No such room in climb dil."); quit; } doorname := self.exit_names[direction].[0]; /* One could check for an empty name here... */ dilcopy ("climb_cmd@function("+itoa(direction)+")",self); :loop: wait(SFB_CMD,command(direction)); if (activator.type == UNIT_ST_PC) { skilla := activator.skills[SKI_CLIMB]; if (skilla < 1) skilla := -25; } else skilla := activator.abilities[ABIL_DEX]; hm := skillresist(skilla, 0, activator.abilities[ABIL_DEX], 0); if (hm >= difficulty) { act("You easily climb the $2t.", A_ALWAYS, activator, doorname, null, TO_CHAR); act("$1n easily climbs the $2t.", A_ALWAYS, activator, doorname, null, TO_ROOM); goto loop; } dest := findroom(destination); if (dest != activator.outside) { act("You fall and hit yourself!", A_ALWAYS, activator, doorname, null, TO_CHAR); act("$1n failed to climb the $2t and takes a nasty fall...", A_ALWAYS, activator, doorname, null, TO_ROOM); link(activator, dest); act("$1n failed to climb the $2t and lands at your feet...", A_ALWAYS, activator, doorname, null, TO_ROOM); } else { act("You fail to climb the $2t!", A_ALWAYS, activator, doorname, null, TO_CHAR); act("$1n failed to climb the $2t!", A_ALWAYS, activator, doorname, null, TO_ROOM); } if (activator.level < IMMORTAL_LEVEL) { activator.hp := activator.hp - damage; position_update(activator); } block; goto loop; } dilend dilbegin climb_cmd (direction:integer); external string dirstring (dr:integer); var dir:string; code { dir :=dirstring(direction); :start: wait (SFB_CMD, command (CMD_CLIMB)); block; if (not(argument == dir)) { act ("You can't seem to climb in that direction.", A_ALWAYS,activator,null,null,TO_CHAR); goto start; } exec (dir,activator); goto start; } dilend /* Function: combat_mag Descr: Replaces the special function SFUN_COMBAT_MAGIC and SFUN_COMBAT_HEAL that better uses the magic. use on: mobiels arguments: atk_spl : string (Attack spell ie "fireball" or "" for none) def_spl : string (Defense Spell ie "heal" or "" for none) def_pct : integer (At what % of hitpoints defense spell will be cast) spd : integer (speed at which mob will uses its attack magic 1 for all at once (every round) to 5 for every 5 rounds. I suggest 2.) Defense spells take priority when the hitpoints fall below the % specified, after (if) the hits have been restored above that number attack magic will resume. If def_spl is used, function automaticly makes sure that it retains enough mana for at least one healing, ie it will attack 4 times if it don't need a healing. example: dilcopy combat_mag@function ("harm", "heal", 25, 2); */ dilbegin combat_mag(atk_spl : string, def_spl : string, def_pct : integer, spd: integer); var use_atk : integer; use_def : integer; can_cast : integer; hp_trig : integer; i : integer; test : string; code { :init: use_atk := 0; use_def := 0; hp_trig := ((self.max_hp*def_pct)/100); if (atk_spl != "") { /* Use for compatibility */ if ("cast" in atk_spl) { test := getword(atk_spl); } use_atk := 1; } if (def_spl != "") { if ("cast" in def_spl) { test := getword(def_spl); } use_def := 1; } heartbeat := 12; :waitcom: wait(SFB_COM, self.position == POSITION_FIGHTING); :def_spl: heartbeat := 3; if (use_def != 1) goto atk_spl; if (self.hp <= hp_trig) { exec("cast " + def_spl + " self", self); goto waitcom; } :atk_spl: if (use_atk == 1) { if(use_def == 1) { i := self.mana -20; if (i >= 20) { can_cast := 1; } else { can_cast := 0; } } else { if (self.mana >= 16) { can_cast := 1; } else { can_cast := 0; } } if(can_cast == 1) { heartbeat := 12 * spd; pause; exec("cast " + atk_spl + " " + self.fighting.name, self); } } if (self.mana <10) { wait(SFB_TICK, TRUE); } goto waitcom; } dilend /* function: fido descr this replaces the old fido special arguments: txt1 : the text shown when mob finds and eats corpses, default: 'XXX savagely devours a corpse.' will be shown if txt1 is set to "". If txt1 is set to "stop", the mob will NOT devour corpses (convenient if you want your dogs to only eat food leftovers but not corpses). txt2 : the text shown when mob finds and eats ITEM_FOOD, default: 'XXX hungrily devours YYY.' will be shown if txt2 is set to "". If txt2 is set to "stop", the mob will NOT devour ITEM_FOOD (convenient if you want to make a corpse-eating ghoul, who'd choke on normal food, etc). In both cases $1n is the mob itself, $2n is the title of the item devoured. Example: dilcopy fido@function("$1n slowly devours $2n, crunching the bones.", "$1n grabs $2n and hungrily munches it."); */ dilbegin fido(txt1:string,txt2:string); var u : unitptr; code { :start: heartbeat:=PULSE_SEC*rnd(5,15); wait(SFB_TICK,TRUE); wait(SFB_TICK,TRUE); foreach (UNIT_ST_OBJ,u) { if ((u.nameidx=="corpse")and(u.zoneidx=="basis")and (u.flags!=UNIT_FL_BURIED)and(visible(self,u))and (txt1!="stop") and (self.value[2]!=1)) { if (txt1=="") { exec("emote savagely devours a corpse.",self); } else { act(""+txt1,A_SOMEONE,self,u,null,TO_ALL); } while (u.inside) link(u.inside,self.outside); destroy(u); goto start; } if ((u.objecttype == ITEM_FOOD)and(txt2 != "stop")and (u.flags!=UNIT_FL_BURIED)and(visible(self,u))) { if (txt2=="") { exec("emote hungrily devours "+u.title+".",self); } else { act(""+txt2,A_SOMEONE,self,u,null,TO_ALL); } destroy(u); goto start; } goto start; } goto start; } dilend /* Function: safe_room Descr: To make a room that disallows all forms of attacks. Mainly used for safehavens like the temple of udgaard. use on: rooms arguments: NONE example: dilcopy safe_room@function(); */ dilbegin string laststring (s:string ); var i:integer; s_list:stringlist; code { s_list:=getwords(s); i:=length(s_list); if (i==0) return ("0"); else return (s_list.[(i-1)]); } dilend dilbegin safe_room(); external string laststring (s:string);/*returns last word in a string.*/ var tgt_string:string; first_arg:string; arg:string; tgt:unitptr; code { :there: heartbeat := PULSE_SEC*3; wait(SFB_CMD, TRUE and ((activator.type==UNIT_ST_PC) or (activator.type==UNIT_ST_NPC))); if ((activator.type==UNIT_ST_NPC) and (activator.master==null)) goto there; arg:=argument; first_arg:=getword(arg); tgt_string:=laststring (argument); if (tgt_string=="0") goto there; tgt:=findunit (activator,tgt_string,FIND_UNIT_SURRO,null);/*should probably think of a better return*/ if ((tgt==null)and (first_arg!="command")) goto there; if ((POLICE_ACADEMY in activator.quests) and ( tgt.type ==UNIT_ST_PC) and (isset (tgt.charflags,CHAR_OUTLAW))) goto there; if (tgt==activator.master) goto there; if ((command (CMD_STEAL)) or (command (CMD_KILL)) or (command (CMD_FILCH)) or (command (CMD_PICK_POCKET)) or (command (CMD_DISARM)) or (command (CMD_TRIP)) or (command (CMD_DRAG)) or (command (CMD_BACKSTAB)) or (command (CMD_HIT)) or (command (CMD_RESCUE)) or (command (CMD_KICK) ) or (command (CMD_BASH)) or (command (CMD_USE)) or (command (CMD_RECITE)) or (command (CMD_CAST))) { block; act ("Spells and attacks are not allowed in safe rooms.", A_SOMEONE, activator, null, null, TO_CHAR); } goto there; } dilend /* Function: wander_zones Description: Random Wander like the special function, but allows more than one zone, i.e. Can have a mob only wander two or three zones. Arguments: zones : string = A string of zonenames seperated by spaces. spd : integer = The speed (in seconds) at which the mob wanders. Minumum = 5 secs (for process time). doors : integer = Can open/close doors (0 = false, 1 = true) lckd_doors : integer = Can open/closed locked doors (0=false, 1=true) Example: dilcopy wander_zones@function ("halfzon haon_dor", 5, 1); */ dilbegin wander_zones(zones : string, spd : integer, doors : integer, lckd_doors : integer); external string dirstring (dr:integer); integer rev_dir (i:integer); var i:integer; dir : integer; x : integer; rm : unitptr; dir_string : string; op_string : string; dr_name : string; heart : integer; zones_lst : stringlist; code { :init: on_activation(self.position <= POSITION_SLEEPING, skip); zones_lst := getwords(zones); if(( (spd*4) < 5) ) { heartbeat := 5 * 3; } else { heartbeat := spd * 3; } heart := heartbeat; :start: wait(SFB_TICK, TRUE); /* Make Sure we are in a leagl wander zone.*/ if (not(self.outside.zoneidx in zones_lst)) goto start; /* Lets stand up if for some reason we are sitting */ if ((self.position == POSITION_RESTING) or (self.position == POSITION_SITTING)) { exec("stand", self); } /* if were not standing now then abort! */ if (self.position != POSITION_STANDING) goto start; /* Get a rnd dir and make sure it exists, it is one of the zones we are allowed to wander, and it is not a no_mob room */ x := 0; /* initilize loop counter, to prevent dil destroy */ :get_dir: heartbeat := 3; dir := rnd(0,5); if ( (self.exit_to[dir] == null) or ( not ((self.outside.exit_to[dir].zoneidx) in zones_lst )) or ( isset( self.outside.exit_to[dir].flags, UNIT_FL_NO_MOB))) { x := x+1; if (x > 20) { x := 0; pause; } goto get_dir; } heartbeat := heart; dir_string:=dirstring (dir); i:=rev_dir(dir); op_string :=dirstring (i); if (doors == TRUE) { if (isset (self.outside.exit_info[dir], EX_LOCKED)) goto locked; if (isset (self.outside.exit_info[dir], EX_CLOSED)) { exec ("open "+dir_string+" "+self.outside.exit_names[dir].[0],self); exec (dir_string,self); dir :=rev_dir (dir); dir_string:=dirstring (dir); exec ("close "+dir_string+" "+self.outside.exit_names[dir].[0],self); goto start; } } :locked: if (lckd_doors == TRUE) { if (isset (self.outside.exit_info[dir], EX_LOCKED)) { unset(self.outside.exit_info[dir], EX_LOCKED); exec ("open "+dir_string+" "+self.outside.exit_names[dir].[0],self); exec (dir_string,self); dir :=rev_dir (dir); dir_string:=dirstring (dir); exec ("close "+dir_string+" "+self.outside.exit_names[dir].[0],self); set(rm.exit_info[dir], EX_LOCKED); goto start; } } exec(dir_string, self); goto start; } dilend /* Basic Guard Function. Hopefully will take care of all of the necessary function of a law protecting function. There are alot of options that need to be passed: Type Example ------------------------------------------------- zones - string : halfzon halfzon2 cont_proc - string : guard@halfzon * symbolic main guard * prot_prot - integer : 1 * 0 = false, 1= true * captain - string : sherrif@halfzon * symbolic name of captain* */ /* A guard door function by level, this blocks all previous holes, drag, groups, etc. and allows greater flexibility. Groups are allowed to pass with out problem, only holding out those that do not meet the level criteria. dir - WEST, NORTH, EAST, WEST, UP, DOWN g_room - symbolic name of room for guard function to work. l_lvl - lowest level you want to allow through. m_lvl - Max level you want to allow through. disp_actions - A dil function that is called when they fail the criteria */ dilbegin guard_level( dir : integer, g_room : string, l_lvl : integer, m_lvl : integer, disp_actions : string ); external string dirstring (dr:integer); integer rev_dir (i:integer); var pc : unitptr; folwr : unitptr; cmd_dir : integer; dir_string :string; leave_string : string; i:integer; code { /* Ok lets set up the whole mess. This is only run once when the function is copied to the dil. It does not change. We have the dir_string and leave_strings to help show the right messages for following pcs. */ on_activation(self.position <= POSITION_SLEEPING, sleep); heartbeat := 3; cmd_dir := dir; dir_string := dirstring(dir); i:=rev_dir(dir); leave_string :=dirstring (i); /* Now that that is all set up we can wait around for commands */ :start: wait(SFB_CMD, ( (command(cmd_dir) or command(CMD_DRAG)) and (activator.type == UNIT_ST_PC) and (self.outside == findroom(g_room)))); pc := activator; secure (pc, start); block; if((command(CMD_DRAG) and (dir_string in argument)) ) { act("You stumble and fall down.", A_SOMEONE, pc,null, null, TO_CHAR); act("$1n stumbles and falls down.", A_SOMEONE, pc,null, null, TO_REST); pc.position := POSITION_SITTING; goto start; } if( ( (pc.level < l_lvl) or (pc.level > m_lvl) ) ) { disp_actions(self, pc); goto start; } /* Loop through all players and mobs simulating the follow, etc */ foreach( UNIT_ST_PC|UNIT_ST_NPC, folwr ) { if( ( (folwr.master == pc) and (folwr != pc) ) ) { if ( (folwr.level < l_lvl) or (folwr.level > m_lvl) ) { disp_actions(self, folwr); } else { act("You follow $2n " + dir_string + ".", A_SOMEONE, folwr, pc, null, TO_CHAR); if (folwr.minv <= pc.level) { act("$1n leaves " + dir_string + ".", A_SOMEONE, folwr, pc, null, TO_REST); act("$2n arrives from " + leave_string + ".", A_SOMEONE, pc, folwr, null, TO_CHAR); } link(folwr, self.outside.exit_to[dir]); exec("look", folwr); } } else if (folwr == pc) { act("$1n leaves " + dir_string + ".", A_SOMEONE, pc, null, null, TO_REST); } } link(pc, self.outside.exit_to[dir]); exec("look", pc); goto start; :sleep: heartbeat := 240; /* approx 1 min max sleeping time */ pause; self.position := POSITION_STANDING; exec("yawn", self); heartbeat := 3; walkto(findroom(g_room)); /* incase he was dragged away while asleep */ goto start; /* Back to work */ } dilend /* Function: scramble Description: Scramble a rooms exits to make a ever changing maze. Arguments: a_exit = string of exits to scramble valid are: north south west east up down Example: dilcopy scramble@function ("north east south west"); */ dilbegin scramble(a_exit : string); var dir : integer; pc : unitptr; fol_pc : unitptr; dir_string : string; leave_string :string; code { heartbeat := 3; if ("north" in a_exit) interrupt(SFB_CMD,( (command(CMD_NORTH)) and (activator.type == UNIT_ST_PC) and (activator.level < IMMORTAL_LEVEL) ), scramble); if ("south" in a_exit) interrupt(SFB_CMD,( (command(CMD_SOUTH)) and (activator.type == UNIT_ST_PC) and (activator.level < IMMORTAL_LEVEL) ), scramble); if ("east" in a_exit) interrupt(SFB_CMD,( (command(CMD_EAST)) and (activator.type == UNIT_ST_PC) and (activator.level < IMMORTAL_LEVEL) ), scramble); if ("west" in a_exit) interrupt(SFB_CMD,( (command(CMD_WEST)) and (activator.type == UNIT_ST_PC) and (activator.level < IMMORTAL_LEVEL) ), scramble); if ("up" in a_exit) interrupt(SFB_CMD,( (command(CMD_UP)) and (activator.type == UNIT_ST_PC) and (activator.level < IMMORTAL_LEVEL) ), scramble); if ("down" in a_exit) interrupt(SFB_CMD,( (command(CMD_DOWN)) and (activator.type == UNIT_ST_PC) and (activator.level < IMMORTAL_LEVEL) ), scramble); interrupt(SFB_CMD,( (command(CMD_DRAG)) and (activator.type == UNIT_ST_PC) and (activator.level < IMMORTAL_LEVEL) ), sorry); interrupt(SFB_CMD,( (command(CMD_RIDE)) and (activator.type == UNIT_ST_PC) and (activator.level < IMMORTAL_LEVEL) ), sorry); :start: wait(SFB_MSG, "DESTROY" in argument ); quit; goto start; :sorry: act("Sorry you can't do that here!", A_SOMEONE, pc, null, null, TO_CHAR); goto start; :scramble: pc := activator; secure(pc, start); block; :get_dir: dir := rnd(0,5); if (self.exit_to[dir] == null) goto get_dir; if (command(CMD_NORTH)) { dir_string := "north"; leave_string := "south"; } if (command(CMD_SOUTH)) { dir_string := "south"; leave_string := "north"; } if (command(CMD_EAST)) { dir_string := "east"; leave_string := "west"; } if (command(CMD_WEST)) { dir_string := "west"; leave_string := "east"; } if (command(CMD_UP)) { dir_string := "up"; leave_string := "below"; } if (command(CMD_DOWN)) { dir_string := "down"; leave_string := "above"; } foreach( UNIT_ST_PC|UNIT_ST_NPC, fol_pc ) { if( (fol_pc.master == pc) and (fol_pc != pc) and (fol_pc.position==POSITION_STANDING)) { act("You follow $2n " + dir_string + ".", A_SOMEONE, fol_pc, pc, null, TO_CHAR); if (fol_pc.minv < pc.level) { act("$2n arrives from the " + leave_string + ".", A_SOMEONE, pc, fol_pc, null, TO_CHAR); } link(fol_pc, self.exit_to[dir]); exec("look", fol_pc); } else if (fol_pc != pc) { act("$2n leaves " + dir_string + ".", A_SOMEONE, fol_pc, pc, null, TO_CHAR); } } link(pc, self.exit_to[dir]); exec("look", pc); } dilend /* Function: stealdil Description: Randomly steal from a player. Use On: Mobs Arguments: item = string of item to try to steal. ie money platinum sword hammer only one item may be passed Example: dilcopy stealdil@function("platinum"); */ dilbegin stealdil(item : string); var i : integer; pc : unitptr; code { heartbeat := PULSE_SEC*5; :start: wait (SFB_CMD, (activator.type == UNIT_ST_PC)); pc := activator; i := rnd(1,10); if (i>2) goto start; exec ("steal " + item + " from " + pc.name, self); exec ("flee", self); goto start; } dilend /* function Channel and recieve to be used together. used on: Players argume nts: none; example: dilcopy ("channel",pc); no need to copy recieve channel takes care of the recieve part. */ #define MAX_CHAN 25 dilbegin recieve( slActive : stringlist, msg : string , talker : unitptr, jmode : integer, dmode : integer); var nWizinv : integer; sChan : string; sName : string; sKey : string; sFirst : string; slKeys : stringlist; clan_rec:extraptr; clan_send:extraptr; rclanname:string; sclanname:string; garbage:string; code { secure(talker, lost); slKeys := {"@", "#", "1join1", "1left1"}; sKey := ""; sChan := getword(msg); /*Throw away the CHANNEL*/ sChan := getword(msg); if(not(sChan in slActive)) return; if ((sChan=="gchat") and (not (self.guild==talker.guild))) return; if(sChan=="clan"){ if(self.type==UNIT_ST_PC) clan_rec:=CLAN_NAME in self.extra; if(clan_rec==null){ return; } if(talker.type==UNIT_ST_PC) clan_send:= CLAN_NAME in talker.extra; if(clan_send==null){ return; } rclanname:=clan_rec.descr; sclanname:=clan_send.descr; if(rclanname!=sclanname){ return; } } sFirst := getword(msg); if ( sFirst in slKeys ) { sKey := sFirst; } else { if (length(msg) > 0) { msg := sFirst + " " + msg; } else { msg := Sfirst; } } if (sKey == "@") { if (self.level >= talker.minv) { sendtext("&c+w<"+sChan+ ">&cc " +talker.name+ "&c+w " +msg+"&bn&cw&n",self ); } else { sendtext("&c+w<"+sChan+">&cc Someone &c+w"+msg+"&bn&cw&n",self ); } } else if (sKey == "#"){ if (self.minv <= talker.level ) { if(self.type==UNIT_ST_PC){ if ((sChan=="clan") and (clan_send.names.[3]=="Master")) { if (self.level < 200) sendtext(" &c+w "+self.name+" "+self.title+ " (Level "+itoa(self.vlevel) + ") (alignment/"+itoa(self.alignment)+ ") (guild/"+self.guild+ ")&bn&cw&n", talker); else if (self.level < 251) sendtext(" &c+w "+self.name+" "+self.title+ " (Immortal [Level " + itoa(self.level) +"]" + ") (alignment/"+itoa(self.alignment)+ ") (guild/"+self.guild+ ")&bn&cw&n", talker); else sendtext(" &c+w "+self.name+" "+self.title+ " (Admin [Level " + itoa(self.level) +"]" + ") (alignment/"+itoa(self.alignment)+ ") (guild/"+self.guild+ ")&bn&cw&n", talker); } else { if (self.level <200) sendtext(" &c+w "+self.name+" "+self.title+ " (Level "+itoa(self.vlevel) + ")&bn&cw&n", talker); else if (self.level < 251) sendtext(" &c+w "+self.name+" "+self.title+ " (Immortal [Level " + itoa(self.level) +"]" + ")&bn&cw&n", talker); else sendtext(" &c+w "+self.name+" "+self.title+ " (Admin [Level " + itoa(self.level) +"]" + ")&bn&cw&n", talker); } } else sendtext(" &c+w "+self.title+"&bn&cw&n",talker); } } else if (sKey == "1join1" ) { if (jmode ==1) { if (self.level >= talker.minv ) { sendtext("&c+w <"+sChan+">&cc " +talker.name + " has entered the " + "channel.&bn&cw&n",self); } } } else if (sKey == "1left1" ) { if (dmode ==1) { if (self.level >= talker.minv ) { sendtext("&c+w <"+sChan+">&cc " +talker.name + " has left the " + "channel.&bn&cw&n",self); } } } else { if (self.level >= talker.minv) { sendtext("&c+w <"+sChan+">&cc " +talker.name+" says &c+w'" +msg+"'&bn&cw&n",self); } else { sendtext(" &c+w <"+sChan+">&cc Someone says &c+w'" +msg +"'&bn&cw&n",self); } } :lost: return; } dilend #define NOSHOUT_QUEST "$noshout" #define NOTELL_QUEST "$notell" #define NOCOMM_QUEST "$nocomm" dilbegin aware recall channel( ); external recieve@function( slActive : stringlist, msg : string, talker : unitptr, jmode:integer, dmode:integer); var time_string:string; targ:unitptr; slActive : stringlist; func:string; msg : string; words : stringlist; nChan : integer; nEcho : integer; x : integer; dmode : integer; jmode : integer; code { heartbeat := 3; nEcho := 1; dmode := 1; jmode := 1; if (self.level>=200) interrupt (SFB_CMD, (command ("nocomm") and (self==activator)),nochannel); interrupt (SFB_CMD, (command (CMD_NOSHOUT) and (self==activator)),noshout); interrupt (SFB_CMD, (command (CMD_NOTELL) and (self==activator)),notell); interrupt (SFB_DONE,((command (CMD_TELL)) and (self==target)),told); interrupt (SFB_CMD, (command("comm") and (("add" in argument) or ("del" in argument)) and (activator == self)), add_del); interrupt (SFB_CMD, (command("comm") and ("echo" in argument) and (activator == self)), echo_chan); interrupt (SFB_CMD, (command("comm") and ("help" == argument) and (activator == self)), help_chan); interrupt (SFB_CMD, (command("comm") and ("inform" in argument) and (activator == self)), inform); interrupt (SFB_CMD, (command("comm") and ("#" == argument) and (activator == self)), show_chan); interrupt (SFB_MSG, ("CHANNEL" in argument), recieve); :start: wait (SFB_CMD, (cmdstr in slActive) and (activator == self)); block; if (NOCOMM_QUEST in self.quests) { act ("You have lost the privilege to use communication channels.", A_ALWAYS,self,null,null,TO_CHAR); goto start; } /*Channel has been recognized, take argument and send it to rest of dils*/ if( isset(self.pcflags, PC_NOTELLING)) { act("Your telepathic ability has been lost.", A_SOMEONE, self, null, null, TO_CHAR); goto start; } msg := argument; msg := "CHANNEL " + cmdstr + " " + msg; if (argument=="#") sendtext ("&n",self); sendtoalldil(msg, "channel@function"); if (nEcho == 1) { recieve@function(slActive, msg, self,jmode,dmode); } goto start; :told: subextra (self.quests,"$reply"); addextra (self.quests,{"$reply"},activator.name); goto start; :recieve: if (not (NOCOMM_QUEST in self.quests)) recieve@function(slActive, argument, activator,jmode, dmode); goto start; :add_del: func:=argument; words:=getwords(func); if ("add" in words.[0]) goto add_chan; else if ("del" in words.[0]) goto del_chan; else goto start; :add_chan: block; words := getwords(argument); if (("add" in words.[0]) and (words.[1] !=null) ) { if ( words.[1] in slActive ) { act("Channel "+words.[1] + " Already Active!", A_SOMEONE, self, null, null, TO_CHAR); goto start; } addstring(slActive, words.[1]); act("Channel "+words.[1]+" activated.", A_SOMEONE, self, null, null, TO_CHAR); msg := "CHANNEL " + words.[1] + " 1join1"; sendtoalldil(msg, "channel@function"); if (nEcho == 1) { recieve@function(slActive, msg, self,jmode,dmode); } } else { act("Unknown channel command or incorrect options.", A_SOMEONE, self, null, null, TO_CHAR); } goto start; :del_chan: block; words := getwords(argument); if (("del" in words.[0]) and (words.[1] in slActive)) { if (not(words.[1] in slActive) ) { act("Channel "+words.[1] + " is not on!", A_SOMEONE, self, null, null, TO_CHAR); goto start; } act("Channel "+words.[1]+" deactivated.", A_SOMEONE, self, null, null, TO_CHAR); msg := "CHANNEL " + words.[1] + " 1left1"; sendtoalldil(msg, "channel@function"); if (nEcho == 1) { recieve@function(slActive, msg, self,jmode,dmode); } substring(slActive, words.[1]); } else { act("Unknown channel command or incorrect options.", A_SOMEONE, self, null, null, TO_CHAR); } goto start; :show_chan: block; nChan := length(slActive); x := 0; while (x < nChan) { sendtext("&c+wChannel "+slActive.[x]+" is active.&bn&cw&n",self ); x:= x+1; } goto start; :echo_chan: block; if( nEcho == 1) { act("Channel echoing in disabled, you will NOT see your own messages.", A_SOMEONE, self, null, null, TO_CHAR); nEcho := 0; } else { act("Channel echoing in enabled, you will see your own messages.", A_SOMEONE, self, null, null, TO_CHAR); nEcho := 1; } goto start; :help_chan: block; sendtext ("&cc To add a channel type:&n"+ "&c+wcomm add &n&n"+ "&cc To delete a channel type:&n"+ "&c+wcomm delete &n&n"+ "&cc To see all your active channels type:&n"+ "&c+wcomm #&n&n"+ "&cc To see who is on a specific channel type:&n"+ "&c+w #&n&n"+ "&cc To see who joins or departs a channel type:&n"+ "&c+wcomm inform &n&n"+ "&cc To toggle echoing of your message type:&n"+ "&c+wcomm echo&n"+ "&cc To do a channel emote type: &n"+ "&c+w @ &n"+ "&cc The standard guild channel is gchat only members will here you&bn &cw &n&n",self); goto start; :inform: block; words := getwords(argument); if (words.[1] == "") { act("Not enough arguments for inform command try 'chan help'", A_SOMEONE, self, null, null, TO_CHAR); } else if (words.[1] == "on") { act("Channel full inform on.", A_SOMEONE, self, null, null, TO_CHAR); jmode := 1; dmode := 1; } else if (words.[1] == "off") { act("Channel inform turned off.", A_SOMEONE, self, null, null, TO_CHAR); jmode := 0; dmode := 0; } else if (words.[1] == "join" ){ act ("Channel inform Join Only set.", A_SOMEONE, self, null, null, TO_CHAR); jmode := 1; dmode := 0; } else if (words.[1] == "depart" ){ act ("Channel inform Depart Only set.", A_SOMEONE, self, null, null, TO_CHAR); jmode := 1; dmode := 0; } goto start; :noshout: targ:=findunit (self,argument,FIND_UNIT_WORLD,null); if (targ==null) goto start; if (not (NOSHOUT_QUEST in targ.quests)) { time_string:=asctime(realtime); time_string:=time_string+" "+self.name; addextra (targ.quests,{NOSHOUT_QUEST},time_string); } else subextra (targ.quests,NOSHOUT_QUEST); goto start; :notell: targ:=findunit (self,argument,FIND_UNIT_WORLD,null); if (targ==null) goto start; if (not (NOTELL_QUEST in targ.quests)) { time_string:=asctime(realtime); time_string:=time_string+" "+self.name; addextra (targ.quests,{NOTELL_QUEST},time_string); } else subextra (targ.quests,NOTELL_QUEST); goto start; :nochannel: block; targ:=findunit (self,argument,FIND_UNIT_WORLD,null); if (targ==null) { act ("No such person found.", A_ALWAYS,self,null,null,TO_CHAR); goto start; } if (targ.level >=self.level) { act ("$2n would not like that very much.", A_ALWAYS,self,targ,null,TO_CHAR); goto start; } if (not(NOCOMM_QUEST in targ.quests)) { time_string:=asctime(realtime); time_string:=time_string+" "+self.name; addextra (targ.quests,{NOCOMM_QUEST},time_string); act ("You have lost the ability to use communication channels.", A_ALWAYS,targ,null,null,TO_CHAR); act ("$2n has lost the ability to use communication channels.", A_ALWAYS,self,targ,null,TO_CHAR); goto start; } else { subextra (targ.quests,NOCOMM_QUEST); act ("You have regained the privilege to use the communication channels.", A_ALWAYS,targ,null,null,TO_CHAR); act ("$2n can now use the communication channels again.", A_ALWAYS,self,targ,null,TO_CHAR); goto start; } goto start; :leave: quit; } dilend /* STORAGE-------------------------------------------- To use storage, first create a mobile called the clerk or something, make sure its a nasty 199 with a flamestrike or something. This is a prereq because he carries a lot of cash. If not, then make some big nasty bodyguards for him. Next you have to create some sort of storage device, use the same name and unique name as you use in the code below. (You will understand when you get there) It doesn't matter how big it is, the code will monitor what you can put in it, it must thought be bigger than the amount of stuff you plan to allow people to store. You must dilcopy the following programs to the mobile, copy NOTHING to the container. --------- Put The following three dils on your storage clerk ----------- dilcopy order@function(cont_name : string, cont_log_name : string, amt : string, typea : string,caust : integer, day : integer, week : integer, month : integer, year : integer, typeb : string, typec : string, typed : string,typee : string, daycost : integer, weekcost : integer, monthcost : integer, yearcost : integer); dilbegin storage(cont_name : string, cont_log_name: string,capaci : integer); dilbegin renew(cont_name : string, cont_log_name : string, day : integer, week : integer, month : integer, year : integer, typeb : string, typec : string, typed : string,typee : string, daycost : integer, weekcost : integer, monthcost : integer, yearcost : integer); ------------------------------------------------------------------------- EXAMPLES: dilcopy order@function(cont_name : string, cont_log_name : string, amt : string, typea : string,caust : integer, day : integer, week : integer, month : integer, year : integer, typeb : string, typec : string, typed : string,typee : string, daycost : integer, weekcost : integer, monthcost : integer, yearcost : integer); "cont_name" and "cont_log_name" These are the variables that control which container from where is used they should be unique to your zone example: cont_name = "name of container" this should not be a name that makes sense, I suggest something like +container cont_log_name = "container@myzone" this is the +@+ -------------------------------------------------------- amt, typea, and caust, are variables which relate to the first time fee for renting storage -- caust is a mud acutal currency pointer number... see documentation below concerning daycost for a full explanation example: amt = 1 typea = platinum caust = 40960 -------------------------------------------------------- day, week, month, and year are variables which relate to the daily payment rate. They should reflect how much gold it will cost to rent for the given period of time. example: day = 8 week = 32 month = 48 year = 90 -------------------------------------------------------- types b-e are variables which relate to the type of currency used to calculate the daily cost example: typeb = gold typec = gold typed = gold typee = gold -------------------------------------------------------- daycost - yearcost are the actual mud values of the currency -- you can determine these values by using the makemoney command -- for instance -- yearcost = 5120 * 90 if you type makemoney 5120, you will notice that this is equal to one gold, -- in this case 5120 * 90 = 1 gold X 90 = 90 gold for one years storage example: daycost = 5120*8 weekcost = 5120*32 monthcost = 5120*48 yearcost = 5120*90 -------------------------------------------------------- Using the previous examples, you can create a dilcopy that looks like this: dilcopy order@function("udcontainer", "container@udgaard", 1, "platinum",40960, 8 , 32, 48,90,"gold","gold","gold","gold", 5120*8, 5120*32, 5120*48, 5120*90); ***************************************************************************** dilbegin storage(cont_name : string, cont_log_name: string,capaci : integer); cont_name and cont_log_name should be the same as you used for the order dilcopy. capaci is a numerical value which equals the number of pounds that can be stored. Example: dilbegin storage("udcontainer", "container@udgaard",90); ***************************************************************************** For the Renew program, your variables must be the same as those used in the order program. ***************************************************************************** hope this explains it, mail any questions to gersh@logtv.com Note: All code must be checked by Isildur prior to it being place in your zone, and all costs must be submitted to him before going online. Don't do stupid things like selling storage for nothing. Base your costs on how much can be stored. The values used in this example are for a container which holds 90 pounds. Obviously, charge more for more space, and less for less space. If you have a little town, dont make a huge storage weight, if you are writing for a city, then make it big. 90 lbs. is used in Udgaard, Midgaard will probably have 150. ------------------------ */ dilbegin order(cont_name : string, cont_log_name : string, amt : string, typea : string,caust : integer, day : integer, week : integer, month : integer, year : integer, typeb : string, typec : string, typed : string,typee : string, daycost : integer, weekcost : integer, monthcost : integer, yearcost : integer); var claim : string; owner : stringlist; pc : unitptr; have : string; cont : unitptr; item : unitptr; thing : unitptr; i : integer; tf : integer; code { :init: heartbeat := PULSE_SEC*5; on_activation((self.position <= POSITION_SLEEPING), skip); :start: wait(SFB_CMD, (command("order") and ("container" in argument)) and (activator.type == UNIT_ST_PC)); pc := activator; secure(pc, lostpc); { block; cont := findunit(self, cont_name, 0, pc.inside); if(cont != null) { exec("say You already have space rented.", self); goto start; } exec("say Hello There, " +pc.name+ ".", self); exec("say We have a " +amt+" "+typea+" first time fee for storage "+ "space.", self); exec("say You can rent for the day, a week, a month, or the year", self); exec("say The rates are " +itoa(day)+" "+typeb+ " for a day.", self); exec("say " +itoa(week)+" "+typec+" for the week.", self); exec("say " +itoa(month)+" "+typed+" for the month.", self); exec("say " +itoa(year)+" "+typee+" for the year.", self); exec("say These fees are paid in advance.", self); exec("say Would like like to rent space with us?", self); exec("say Please Nod or Shake", self); i := 0; while (i < 5) { wait(SFB_CMD, activator #= pc); if(command(CMD_NOD)) { goto want_container; } else if(command(CMD_SAY)) { pause; exec("say Please Nod or Shake.", self); } else if(command(CMD_SHAKE)) goto no_store; i := i + 1; } :no_store: exec("say I'm sorry to hear that.", self); goto start; :want_container: tf := transfermoney(pc, self, caust); if(tf == FALSE) { exec("say You can't afford our initial fee.", self); goto start; } :choice: exec("say Please say whether you want to rent for a day, "+ " week, month, or year", self); wait(SFB_CMD, (command(CMD_SAY))); block; if("day" in argument) { tf := transfermoney(pc, self, daycost); if(tf == FALSE) { exec("say You can't afford to rent for a day.", self); goto start; } goto day; } if("week" in argument) { tf := transfermoney(pc, self, weekcost); if(tf == FALSE) { exec("say You can't afford to rent for a week.", self); goto start; } goto week; } if("month" in argument) { tf := transfermoney(pc, self, monthcost); if(tf == FALSE) { exec("say You can't afford to rent for a month.", self); goto start; } goto month; } if("year" in argument) { tf := transfermoney(pc, self, yearcost); if(tf == FALSE) { exec("say You can't afford to rent for a year.", self); goto start; } goto year; } goto choice; /* -------------------------------------------------- IF YOU HAVE ARGUMENTED OUT ALL ELSE CORRECTLY, IT IS NOT NECESSARY TO CHANGE ANY OF THE CODE BELOW -------------------------------------------------- */ :day: claim := "$"+pc.name; owner := {""}; addstring(owner, claim); item := load(cont_log_name); item.minv := 200; item.alignment := 0; addextra(item.extra, owner, ""); dilcopy("counter@udgaard", item); dilcopy("timerone@udgaard", item); goto end; :week: claim := "$"+pc.name; owner := {""}; addstring(owner, claim); item := load(cont_log_name); item.minv := 200; item.alignment := 0; addextra(item.extra, owner, ""); dilcopy("counter@udgaard", item); dilcopy("timertwo@udgaard", item); goto end; :month: claim := "$"+pc.name; owner := {""}; addstring(owner, claim); item := load(cont_log_name); item.minv := 200; item.alignment := 0; addextra(item.extra, owner, ""); dilcopy("counter@udgaard", item); dilcopy("timerthree@udgaard", item); goto end; :year: claim := "$"+pc.name; owner := {""}; addstring(owner, claim); item := load(cont_log_name); item.minv := 200; item.alignment := 0; addextra(item.extra, owner, ""); dilcopy("counter@udgaard", item); dilcopy("timerfour@udgaard", item); goto end; :end: link(item, pc); act("The clerk reserves some storage space for you.", A_SOMEONE, pc, null, null, TO_CHAR); act("The clerk reserves some storage space for $1n.", A_SOMEONE, pc, null, null, TO_REST); unsecure(pc); goto start; } :lostpc: goto start; } dilend dilbegin storage(cont_name : string, cont_log_name: string,capaci : integer); var pc : unitptr; cont : unitptr; have : string; stuff : unitptr; item : unitptr; tf : integer; weit : integer; newweit : integer; weait : integer; weaits : stringlist; weaitsmore : integer; exdp : extraptr; strin : string; strilst : stringlist; strint : integer; /*udgaard only*/ items : unitptr; slop : integer; bucket : integer; finder : integer; code { :init: heartbeat := PULSE_SEC*5; on_activation((self.position <= POSITION_SLEEPING), skip); :start: wait(SFB_CMD, (command("withdraw") or command("store")) and (activator.type == UNIT_ST_PC)); pc := activator; secure(pc, lostpc); block; { if(command("store")) { block; pc := activator; secure(pc, lostpc); act("$1n speaks with the clerk.", A_SOMEONE, pc, null, null, TO_REST); have := "$"+activator.name; cont := findunit(self, cont_name, 0, pc.inside); if(not(have in cont.extra)) { goto start; } if(cont == null) { exec("say You haven't rented space with us.", self); goto start; } stuff := findunit(self, argument, 0, pc.inside); if(stuff == null) { exec("say You aren't holding a " +argument+"!", self); goto start; } cont := findunit(self, cont_name, 0, pc.inside); weait := 0; weait := stuff.weight; strint := cont.alignment; weaitsmore := weait + strint; if(weaitsmore >= capaci) { exec("say I'm sorry, but you are out of space.", self); goto start; } cont.alignment := weaitsmore; link(cont, pc.outside); link(stuff, cont); setweight(cont, 0); setweight(cont, (-(cont.weight))); link(cont, pc); act("The clerk puts your $2n into storage.", A_SOMEONE, self, stuff, pc, TO_VICT); act("The clerk stores something for $3n.", A_SOMEONE, self, null, pc, TO_NOTVICT); unsecure(pc); goto start; } if(command("withdraw")) { block; act("$1n speaks with the clerk.", A_SOMEONE, pc, null, null, TO_REST); have := "$"+activator.name; cont := findunit(self, cont_name, 0, pc.inside); if(not(have in cont.extra)) { goto start; } if(cont == null) { exec("say You haven't rented space with us.", self); goto start; } stuff := findunit(self, argument, 0, cont.inside); if(stuff == null) { exec("say You don't have a " +argument+" in storage!", self); goto start; } cont := findunit(self, cont_name, 0, pc.inside); weait := 0; weait := stuff.weight; strint := cont.alignment; weaitsmore := strint - weait; cont.alignment := weaitsmore; link(stuff, pc); setweight(cont, 0); setweight(cont, (-(cont.weight))); act("The clerk gives you your $2n.", A_SOMEONE, self, stuff, pc, TO_VICT); act("The clerk gives something to $3n.", A_SOMEONE, self, null, pc, TO_NOTVICT); unsecure(pc); goto start; } } :lostpc: goto start; } dilend dilbegin store_inventory(cont_name : string, cont_log_name : string); var pc : unitptr; cont : unitptr; have : string; items : unitptr; code { :init: heartbeat := PULSE_SEC*5; on_activation((self.position <= POSITION_SLEEPING), skip); :start: wait(SFB_CMD, (command("storage") and ("list" in argument)) and (activator.type == UNIT_ST_PC)); pc := activator; secure(pc, lostpc); { block; have := "$"+activator.name; cont := findunit(self, cont_name, 0, pc.inside); if(not(have in cont.extra)) { exec("say You haven't rented space with us.", self); goto start; } if(cont == null) { exec("say You haven't rented space with us.", self); goto start; } act("The clerk says that you have: ", A_SOMEONE, pc, null, null, TO_CHAR); items := cont.inside; if (items == null) { act("nothing", A_SOMEONE, pc, null, null, TO_CHAR); goto after_loop; } while (items) { act(items.title, A_SOMEONE, pc, null, null, TO_CHAR); items := (items.next); } :after_loop: act(" in storage.", A_SOMEONE, pc, null, null, TO_CHAR); unsecure(pc); goto start; } :lostpc: goto start; } dilend dilbegin renew(cont_name : string, cont_log_name : string, day : integer, week : integer, month : integer, year : integer, typeb : string, typec : string, typed : string,typee : string, daycost : integer, weekcost : integer, monthcost : integer, yearcost : integer); var claim : string; owner : stringlist; pc : unitptr; have : string; cont : unitptr; item : unitptr; i : integer; tf : integer; code { :init: heartbeat := PULSE_SEC*5; on_activation((self.position <= POSITION_SLEEPING), skip); :start: wait(SFB_CMD, (command("renew") and ("lease" in argument)) and (activator.type == UNIT_ST_PC)); pc := activator; secure(pc, lostpc); { block; have := "$"+activator.name; cont := findunit(self, cont_name, 0, pc.inside); if(not(have in cont.extra)) { goto start; } if(cont == null) { exec("say You can't renew a lease on nothing!", self); goto start; } exec("say Hello again, " +pc.name+ ".", self); pause; exec("say You can renew your lease for the day, a week, a month, "+ "or the year", self); exec("say The rates are " +itoa(day)+" "+typeb+ " for a day.", self); exec("say " +itoa(week)+" "+typec+" for the week.", self); exec("say " +itoa(month)+" "+typed+" for the month.", self); exec("say " +itoa(year)+" "+typee+" for the year.", self); exec("say These fees are paid in advance.", self); exec("say Would like like to renew your space with us?", self); pause; exec("say Please Nod or Shake", self); i := 0; while (i < 5) { wait(SFB_CMD, activator #= pc); if(command(CMD_NOD)) { goto want_container; } else if(command(CMD_SAY)) { pause; exec("say Please Nod or Shake.", self); } else if(command(CMD_SHAKE)) goto no_store; i := i + 1; } :no_store: exec("say I'm sorry to hear that.", self); goto start; :want_container: :choice: exec("say Please say whether you want to renew for a day, "+ " week, month, or year", self); wait(SFB_CMD, (command(CMD_SAY))); block; if("day" in argument) { tf := transfermoney(pc, self, daycost); if(tf == FALSE) { exec("say You can't afford to renew for a day.", self); goto start; } goto day; } if("week" in argument) { tf := transfermoney(pc, self, weekcost); if(tf == FALSE) { exec("say You can't afford to renew for a week.", self); goto start; } goto week; } if("month" in argument) { tf := transfermoney(pc, self, monthcost); if(tf == FALSE) { exec("say You can't afford to renew for a month.", self); goto start; } goto month; } if("year" in argument) { tf := transfermoney(pc, self, yearcost); if(tf == FALSE) { exec("say You can't afford to renew for a year.", self); goto start; } goto year; } goto choice; :day: cont := findunit(self, cont_name, 0, pc.inside); sendto("add day", cont); goto end; :week: cont := findunit(self, cont_name, 0, pc.inside); sendto("add week", cont); goto end; :month: cont := findunit(self, cont_name, 0, pc.inside); sendto("add month", cont); goto end; :year: cont := findunit(self, cont_name, 0, pc.inside); sendto("add year", cont); goto end; :end: act("The clerk renews your storage lease.", A_SOMEONE, pc, null, null, TO_CHAR); act("The clerk renews $1n's storage lease.", A_SOMEONE, pc, null, null, TO_REST); unsecure(pc); goto start; } :lostpc: goto start; } dilend /* dilbegin aware store_time(); var pc : unitptr; cont : unitptr; cont_name : string; cont_log_name : string; have : string; items : unitptr; time : string; time_left : integer; code { :init: heartbeat := PULSE_SEC*5; on_activation((self.position <= POSITION_SLEEPING), skip); :start: cont_name := "udcontainer"; cont_log_name := "ud_cont@udgaard"; block; wait(SFB_CMD, (command("lease")) and (activator.type == UNIT_ST_PC)); block; pc := activator; secure(pc, lostpc); { have := "$"+activator.name; cont := findunit(self, cont_name, 0, pc.inside); if(not(have in cont.extra)) { exec("say You haven't rented space with us.", self); goto start; } if(cont == null) { exec("say You haven't rented space with us.", self); goto start; } link(cont, pc.outside); sendto("time_left", cont); wait(SFB_MSG, TRUE); time := argument; :tm_lft: log("on clerk"); log(time); link(cont, pc.inside); act("The clerk says that you have: "+time+ " mud days left.", A_SOMEONE, pc, null, null, TO_CHAR); unsecure(pc); goto start; } :lostpc: goto start; } dilend */ dilbegin recall counter(); code { :start: heartbeat := PULSE_SEC * SECS_PER_MUD_DAY/24; wait(SFB_TICK, TRUE); heartbeat := PULSE_SEC * 5; sendto("add count", self); goto start; } dilend dilbegin recall aware timerone(); var day : integer; week : integer; month : integer; year : integer; time : integer; pc : unitptr; count : integer; code { if(time > 0) goto init; time := 0; :init: day := interrupt (SFB_MSG, argument == "add day", day); week := interrupt (SFB_MSG, argument == "add week", week); month := interrupt (SFB_MSG, argument == "add month", month); year := interrupt (SFB_MSG, argument == "add year", year); heartbeat := PULSE_SEC * 3; count := interrupt (SFB_MSG, argument == "add count", count); wait(SFB_TICK, TRUE); :top: pc := self.outside; if(time == 12) /* 12 */ goto half_time; if(time == 22) /* 22 */ goto time_close; if(time == 24) /* 24 */ goto time_up; goto init; :hold: day := interrupt (SFB_MSG, argument == "add day", day); week := interrupt (SFB_MSG, argument == "add week", week); month := interrupt (SFB_MSG, argument == "add month", month); year := interrupt (SFB_MSG, argument == "add year", year); heartbeat := PULSE_SEC * 3; count := interrupt (SFB_MSG, argument == "add count", count); wait(SFB_TICK, TRUE); goto hold; :half_time: act("**Warning** Your storage lease expires in 12 mud hours.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :time_close: act("**Warning** Your storage lease expires in 2 mud hours.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :time_up: act("**Warning** Your storage lease has expired.", A_SOMEONE, pc, null, null, TO_CHAR); act("Your belongings have been repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); destroy(self); quit; :day: time := time - 24; goto init; :week: time := time - 168; goto init; :month: time := time - 674; goto init; :year: time := time - 8086; goto init; :count: time := time + 1; goto top; } dilend dilbegin recall aware timertwo(); var day : integer; week : integer; month : integer; year : integer; time : integer; pc : unitptr; count : integer; code { if(time > 0) goto init; time := 0; :init: day := interrupt (SFB_MSG, argument == "add day", day); week := interrupt (SFB_MSG, argument == "add week", week); month := interrupt (SFB_MSG, argument == "add month", month); year := interrupt (SFB_MSG, argument == "add year", year); heartbeat := PULSE_SEC * 3; count := interrupt (SFB_MSG, argument == "add count", count); wait(SFB_TICK, TRUE); :top: pc := self.outside; if(time == 48) goto five_days_left; if(time == 120) goto two_days_left; if(time == 144) goto one_day_left; if(time == 156) goto twelve_hours; if(time == 164) goto four_hours; if(time == 166) goto two_hours; if(time == 168) goto time_up; goto init; :hold: day := interrupt (SFB_MSG, argument == "add day", day); week := interrupt (SFB_MSG, argument == "add week", week); month := interrupt (SFB_MSG, argument == "add month", month); year := interrupt (SFB_MSG, argument == "add year", year); heartbeat := PULSE_SEC * 3; count := interrupt (SFB_MSG, argument == "add count", count); wait(SFB_TICK, TRUE); goto hold; :five_days_left: act("**Warning** Your storage lease expires in 5 mud days.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :two_days_left: act("**Warning** Your storage lease expires in 2 mud days.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :one_day_left: act("**Warning** Your storage lease expires in 1 mud day.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :twelve_hours: act("**Warning** Your storage lease expires in 12 mud hours.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :four_hours: act("**Warning** Your storage lease expires in 4 mud hours.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :two_hours: act("**Warning** Your storage lease expires in 2 mud hours.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :time_up: act("**Warning** Your storage lease has expired.", A_SOMEONE, pc, null, null, TO_CHAR); act("Your belongings have been repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); destroy(self); quit; :day: time := time - 24; goto init; :week: time := time - 168; goto init; :month: time := time - 674; goto init; :year: time := time - 8086; goto init; :count: time := time + 1; goto top; } dilend dilbegin recall aware timerthree(); var day : integer; week : integer; month : integer; year : integer; time : integer; pc : unitptr; count : integer; code { if(time > 0) goto init; time := 0; :init: day := interrupt (SFB_MSG, argument == "add day", day); week := interrupt (SFB_MSG, argument == "add week", week); month := interrupt (SFB_MSG, argument == "add month", month); year := interrupt (SFB_MSG, argument == "add year", year); heartbeat := PULSE_SEC * 3; count := interrupt (SFB_MSG, argument == "add count", count); wait(SFB_TICK, TRUE); :top: pc := self.outside; if(time == 168) goto week_one; if(time == 336) goto week_two; if(time == 504) goto week_three; if(time == 624) goto two_days_left; if(time == 648) goto one_day_left; if(time == 660) goto twelve_hours; if(time == 670) goto four_hours; if(time == 672) goto two_hours; if(time == 674) goto time_up; goto init; :hold: day := interrupt (SFB_MSG, argument == "add day", day); week := interrupt (SFB_MSG, argument == "add week", week); month := interrupt (SFB_MSG, argument == "add month", month); year := interrupt (SFB_MSG, argument == "add year", year); heartbeat := PULSE_SEC * 3; count := interrupt (SFB_MSG, argument == "add count", count); wait(SFB_TICK, TRUE); goto hold; :week_one: act("**Warning** Your storage lease expires in 3 mud weeks.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :week_two: act("**Warning** Your storage lease expires in 2 mud weeks.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :week_three: act("**Warning** Your storage lease expires in 7 mud days", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :two_days_left: act("**Warning** Your storage lease expires in 2 mud days.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :one_day_left: act("**Warning** Your storage lease expires in 1 mud day.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :twelve_hours: act("**Warning** Your storage lease expires in 12 mud hours.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :four_hours: act("**Warning** Your storage lease expires in 4 mud hours.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :two_hours: act("**Warning** Your storage lease expires in 2 mud hours.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :time_up: act("**Warning** Your storage lease has expired.", A_SOMEONE, pc, null, null, TO_CHAR); act("Your belongings have been repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); destroy(self); quit; :day: time := time - 24; goto init; :week: time := time - 168; goto init; :month: time := time - 674; goto init; :year: time := time - 8086; goto init; :count: time := time + 1; goto top; } dilend dilbegin recall aware timerfour(); var day : integer; week : integer; month : integer; year : integer; time : integer; pc : unitptr; count : integer; code { if(time > 0) goto init; time := 0; :init: day := interrupt (SFB_MSG, argument == "add day", day); week := interrupt (SFB_MSG, argument == "add week", week); month := interrupt (SFB_MSG, argument == "add month", month); year := interrupt (SFB_MSG, argument == "add year", year); heartbeat := PULSE_SEC * 3; count := interrupt (SFB_MSG, argument == "add count", count); wait(SFB_TICK, TRUE); :top: pc := self.outside; if(time == 674) goto month_one; if(time == 1348) goto month_two; if(time == 2022) goto month_three; if(time == 2696) goto month_four; if(time == 3370) goto month_five; if(time == 4044) goto month_six; if(time == 4718) goto month_seven; if(time == 5392) goto month_eight; if(time == 6066) goto month_nine; if(time == 6740) goto month_ten; if(time == 7414) goto month_eleven; if(time == 7582) goto week_one; if(time == 7750) goto week_two; if(time == 7918) goto week_three; if(time == 8038) goto two_days_left; if(time == 8062) goto one_day_left; if(time == 8074) goto twelve_hours; if(time == 8082) goto four_hours; if(time == 8084) goto two_hours; if(time == 8086) goto time_up; goto init; :hold: day := interrupt (SFB_MSG, argument == "add day", day); week := interrupt (SFB_MSG, argument == "add week", week); month := interrupt (SFB_MSG, argument == "add month", month); year := interrupt (SFB_MSG, argument == "add year", year); heartbeat := PULSE_SEC * 3; count := interrupt (SFB_MSG, argument == "add count", count); wait(SFB_TICK, TRUE); goto hold; :month_one: act("**Warning** Your storage lease expires in 11 mud months.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :month_two: act("**Warning** Your storage lease expires in 10 mud months.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :month_three: act("**Warning** Your storage lease expires in 9 mud months.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :month_four: act("**Warning** Your storage lease expires in 8 mud months.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :month_five: act("**Warning** Your storage lease expires in 7 mud months.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :month_six: act("**Warning** Your storage lease expires in 6 mud months.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :month_seven: act("**Warning** Your storage lease expires in 5 mud months.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :month_eight: act("**Warning** Your storage lease expires in 4 mud months.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :month_nine: act("**Warning** Your storage lease expires in 3 mud months.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :month_ten: act("**Warning** Your storage lease expires in 2 mud months.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :month_eleven: act("**Warning** Your storage lease expires in 4 mud weeks.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :week_one: act("**Warning** Your storage lease expires in 3 mud weeks.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :week_two: act("**Warning** Your storage lease expires in 2 mud weeks.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :week_three: act("**Warning** Your storage lease expires in 7 mud days", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :two_days_left: act("**Warning** Your storage lease expires in 2 mud days.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :one_day_left: act("**Warning** Your storage lease expires in 1 mud day.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :twelve_hours: act("**Warning** Your storage lease expires in 12 mud hours.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :four_hours: act("**Warning** Your storage lease expires in 4 mud hours.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :two_hours: act("**Warning** Your storage lease expires in 2 mud hours.", A_SOMEONE, pc, null, null, TO_CHAR); act("If you do not renew your lease or remove your belongings they will be repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); goto hold; :time_up: act("**Warning** Your storage lease has expired.", A_SOMEONE, pc, null, null, TO_CHAR); act("Your belongings have been repossessed.", A_SOMEONE, pc, null, null, TO_CHAR); destroy(self); quit; :day: time := time - 24; goto init; :week: time := time - 168; goto init; :month: time := time - 674; goto init; :year: time := time - 8086; goto init; :count: time := time + 1; goto top; } dilend /* Function: aggressive Description: Replacement and enhancement of the SFUN_AGGRESSIVE functions. Makes a Mob hostile to person(s) in the room with it, under certain conditions which are provided as arguments. In short, the all-singing, all-dancing aggression dil. dilbegin aggressive (sx : integer, rce : integer, opp : integer, levl : integer, sanc : integer, tme : integer, tar : integer, align : string, attack : stringlist); Arguments: sx : integer - NOTE: not the sex values in values.h. This decides the sex of your mob's victim. 0 - Sex doesn't matter, 1 - Attack opposite sex to self (if not neutral!), 2 - Attack SEX_MALE, 3 - Attack SEX_FEMALE, 4 - Attack SEX_NEUTRAL. rce : integer - Any of the PC races from 0 to 14. A value of -1 means we don't care about the victim's race. opp : integer - 0 - Non race specific (same as rce := -1) 1 - Attack the specified rce, 2 - Attack any pc race _but_ the specified rce. levl : integer - Allow level specific aggression. A value of 30 would make the mob hostile to all pcs level 30 and above. A value of -30 (note the -) would make the mob hostile to all pcs level 30 or below. A value of 0 means level doesn't matter. sanc : integer - Does this mob obey the sanc/soothe rules? (ie, if someone has cast sanctuary on themselves, will this mob recognise it, and not attack, or attack anyway). 0 - Doesn't obey sanc or soothe 1 - Obeys only sanc 2 - Obeys only soothe 3 - Obeys both sanc and soothe (SOOTHE is a new spell for ranger's guild) tme : integer - Time in ticks to wait before attacking (is automatically put to RANTIME, ie, time variance of time-time/2 to time+time/2). Values accepted are from 0 to 400 (that's 0 - 100 seconds. Can be specified using PULSE_SEC). tar : integer - This is a special value which determines which of the eligible victims we pick. -2 - Last eligible victim to into the room. -1 - Weakest eligible victim in room. 0 - Random eligible victim. +1 - Strongest eligible victim in room. +2 - First eligible victim into the room. align : string - The desired alignment of the victim. "ANY" - We don't care about the alignment. "GOOD" - Attack only good alignment. "EVIL" - Attack only evil alignment. "NEUTRAL " - Attack only neutral alignment. "OPPOSITE" - Attack opposite alignment to self (provided self isn't neutral). "SALIGN" - Attack same alignment as self. "DALIGN" - Attack any alignment different to self. attack : stringlist - This is a 2 string stringlist. These are the messages sent to the people in the room except the victim, and the victim itself, in that order. If the second (victim) string is "", the first string will be shown to the victim, as if they were anyone else in the room. You can leave both blank if you wish. $1n is the mob name (self), $3n is the victim's name. NOTE: the $ values only apply if you supply BOTH string 1 and 2. Example : Let's say our mob is a level 40 Goblin who doesn't like dwarves. He's very particular in that he doesn't like evil female dwarves who are level 20 and above. He does recognise the sanctuary spell, but he does recognise soothe, and he'll wait 10 seconds on average before he attacks. The 2 messages sent are: "$1n savagely attacks $3n with his big axe!" and "$1n attacks you!" Here's what the function call would look like: dilcopy aggressive (3, 2, 1, 20, 2, PULSE_SEC*10, 0, "EVIL", {"$1n savagely attacks $3n with his big axe!", "$1n attacks you!"}); In this example, 3 (attack females), 2 (attack dwarves), 1 (just dwarves), 20 (Level 20+ victims), 2 (obey only soothe), PULSE_SEC*10 (wait around 10 seconds before attacking), EVIL (attack only evil), and the strings in the stringlist are displayed to the victim and the room, in that order. A note on the old SFUN_AGGRESSIVE. If I wanted to translate the following into the new function: SFUN_AGGRESSIVE "Big monster attacks!" time PULSE_SEC*20 SFB_RANTIME it would be: dilcopy aggressive@function (0, -1, 0, 0, 3, PULSE_SEC*20, 0, "ANY", {"Big monster attacks!",""}; I hope that explains the function well enough. If you need further explanation or information on it, contact Eirinn (clarej@tcd.ie) */ #define ALOG(_CMDSTR) \ log(self.nameidx+"@"+self.zoneidx+" AGGRO ERROR - "+_CMDSTR) dilbegin aggressive (sx : integer, rce : integer, opp : integer, levl : integer, sanc : integer, tme : integer, tar : integer, align : string, attack : stringlist); external string find_targ (tar : integer, sx1 : integer, alig : integer, rce : integer, opp : integer, mlev : integer, hlev: integer, sanc : integer); var pc : unitptr; /* The activator and reference point */ sucker : unitptr; /* The eventual victim */ tempstr : string; /* A temporary string */ des_sx : integer; /* The desired sex of the victim */ des_ali : integer; /* What alignment we're looking for (-1, 0, +1) */ des_mlv : integer; /* Minimum level sucker can be */ des_hlv : integer; /* Maximum level sucker can be */ to_wait : integer; /* Time to wait before attacking */ ten_time : integer; /* One tenth of tme - used in "randomisation" */ time_rnd : integer; /* Random part of time */ i : integer; /* For interrupt */ code { /* First of all, we must process the arguments as far as possible so that we know exactly what kind of victim we want. This will save time later when a victim walks into the room (we want it to execute as fast as possible). */ :init: interrupt(SFB_COM,self.position==POSITION_FIGHTING,lost_pc); heartbeat := 1; /* This will be used to wait for all followers (if any), to enter the room before activation */ /* The following part of the routine up to the start label checks the arguments passed to the function for validity (and processes them, if necessary), before allowing the function to procede. */ :sex_check: /* Process the sex argument (also checking if valid) */ if (sx == 0) des_sx := 5; /* Just using 5 to mean not sex specific */ else if (sx == 1) { if (self.sex == SEX_NEUTRAL) { ALOG("You can't have an opposite sex to neutral! *bonk*"); quit; } else if (self.sex == SEX_FEMALE) { des_sx := SEX_MALE; } else if (self.sex == SEX_MALE) { des_sx := SEX_FEMALE; } else { ALOG("Eeek - I'm not a valid sex!"); quit; } } else if (sx == 2) des_sx := SEX_MALE; else if (sx == 3) des_sx := SEX_FEMALE; else if (sx == 4) des_sx := SEX_NEUTRAL; else { ALOG("Eeek - Sex argument not valid!"); quit; } :race_check: /* Check the race/opp arguments' validities */ if (rce == -1) goto align_check; /* Race doesn't matter */ else { if ((rce >= 15) or (rce < 0)) { ALOG("Race argument specifies an invalid pc race!"); quit; } if ((opp != 0) and (opp !=1) and (opp != 2)) { /* Do I attack the race or all but race, or do I care? */ ALOG("Opp argument is not 0, 1, or 2!"); quit; } } :align_check: /* Process the align argument (also checking if valid) */ if (align == "ANY") des_ali := 2; /* Attack anyone */ else if (align == "GOOD") { des_ali := 1; /* Attack only good */ } else if (align == "EVIL") des_ali := -1; /* Attack only evil */ else if (align == "NEUTRAL") des_ali := 0; /* Attack only neutral */ else if (align == "OPPOSITE") /* Attack opposite alignment to self */ { if (self.alignment < -349) des_ali := 1; else if (self.alignment > 349) des_ali := -1; else { ALOG("Neutral align has no opposite!"); quit; } } else if (align == "SALIGN") /* Attack same alignment as self */ { if (self.alignment < -349) des_ali := -1; else if (self.alignment > 349) des_ali := 1; else if ((self.alignment > -350) and (self.alignment < 350)) des_ali := 0; } else if (align == "DALIGN") /* Attack any alignment except own */ /* 2 : evil and neutral, 3 : evil and good 4 : neutral and good */ { if (self.alignment < -349) des_ali := 4; else if (self.alignment > 349) des_ali := 2; else if ((self.alignment > -350) and (self.alignment < 350)) des_ali := 3; } else { ALOG("Align argument specifies an invalid option!"); quit; } :level_check: /* Process the level argument (also checking if valid) */ if ((levl < 0) and (levl > (-1 * MORTAL_MAX_LEVEL))) { des_hlv := (-1 * levl); if (des_hlv > MORTAL_MAX_LEVEL) des_hlv := MORTAL_MAX_LEVEL; des_mlv := 0; } else if ((levl > 0) and (levl <= MORTAL_MAX_LEVEL)) { des_hlv := (MORTAL_MAX_LEVEL); des_mlv := ( levl); } else if (levl == 0) { des_hlv := (MORTAL_MAX_LEVEL); des_mlv := 0; } else { ALOG("Levl argument is invalid!"); quit; } :sanc_check: /* Checking if the sanc argument is valid: 0 - Doesn't obey sanc or soothe 1 - Obeys only sanc 2 - Obeys only soothe 3 - Obeys both sanc and soothe */ if ((sanc != 0) and (sanc != 1) and (sanc != 2) and (sanc != 3)) { ALOG("Sanc argument is invalid!"); quit; } if (sanc > 1) { addextra(self.extra, {"$Soothe"}, ""); } :time_check: /* Checking if the time argument is valid */ if (not((tme >=0) and (tme <=400))) { ALOG("Time argument is out of range!"); quit; } /* Process the time argument - see later for comments */ if (tme == 0) goto get_target; /* Let's not wait then. See if I care :P */ else ten_time := (tme / 10); /* Divide the original time by 10 */ tme := tme / 2; /* This is the new base time value */ :target_check: /* Checking if the tar value is acceptable */ if (not((tar >= -2) and (tar <=2))) { ALOG("Target argument is not a valid target type!"); quit; } :act_check: /* Check the strings for the act are present, if not, provide defaults */ if (length(attack) > 2) { ALOG("Too many strings in attack stringlist!"); quit; } :start: /* Phew, we got to the actual aggression part. Thank Heavens for that. I still want to know why men have nipples though. Oh well. */ wait(SFB_DONE, ( (activator.type == UNIT_ST_PC) and (self.position >= POSITION_RESTING) and (self.position != POSITION_FIGHTING) )); pc := activator; secure(pc, lost_pc); pause; /* Wait for 1/4 of a second in case the pc has a group (we want them all to be present in the room */ /* Now we must wait the appointed time (randomly chosen between the time value which was passed and +/- the time value divided by two and then randomly chosen in intervals of 10ths of this). The reason this is done before target selection is in case a chosen target leaves the room but the original activator of the function doesn't, that way we minimise potential misfires. We could of course do it the other way around, but why use CPU time for nothing? */ :wait_time: time_rnd := (rnd(0,10) * ten_time); /* Now give me a random value from 0 to the original time value */ to_wait := tme + time_rnd; /* Make the tick time a random value from half the original time value to 1.5 times the original time */ heartbeat := to_wait; /* Set the new tick time */ pause; /* Wait the appointed time */ heartbeat := 1; /* Reset the tick time and go get a target */ /* The following function call is for find_targ - this sorts through all of the pcs in the room and returns the one we want according to the tar variable which was passed in the original aggressive function call. */ :get_target: tempstr := find_targ (tar, des_sx, des_ali, rce, opp, des_mlv, des_hlv, sanc); if (tempstr == "No valid targets in the room") goto lost_pc; sucker := findunit(self, tempstr, 0, self.outside.inside); if (self.position == POSITION_FIGHTING) goto lost_pc; if (sucker == null) goto lost_pc; if (sucker.type != UNIT_ST_PC) goto lost_pc; if (attack.[0] == "") goto start_fight; if (attack.[1] != "") { act(attack.[0], A_SOMEONE, self, null, sucker, TO_NOTVICT); act(attack.[1], A_ALWAYS, self, null, sucker, TO_VICT); } else { act(attack.[0], A_SOMEONE, self, null, null, TO_ALL); } :start_fight: if (sucker == self) { quit; } set_fighting(self, sucker); unsecure(pc); goto start; :lost_pc: unsecure(pc); goto start; } dilend /* aggressive */ /* This dil will rate a pc on their abilities, with different weights on the abilities. Gods get a + 10000 headstart. */ dilbegin integer rate_pc (rate_me : unitptr, stre : integer, dext : integer, cons : integer, char : integer, brai : integer, magi : integer, divi : integer, hitp : integer); var rating : integer; /* The Final Rating of the PC */ temp_total : integer; /* A Temporary variable */ code { heartbeat:=PULSE_SEC; :start: rating := 0; if (rate_me.level >= IMMORTAL_LEVEL) rating := rating + 10000; if (stre) rating := rating + (10 * rate_me.abilities[ABIL_STR]); if (dext) rating := rating + (10 * rate_me.abilities[ABIL_DEX]); if (cons) rating := rating + (4 * rate_me.abilities[ABIL_CON]); if (char) rating := rating + (7 * rate_me.abilities[ABIL_CHA]); if (brai) rating := rating + (8 * rate_me.abilities[ABIL_BRA]); if (magi) rating := rating + (6 * rate_me.abilities[ABIL_MAG]); if (divi) rating := rating + (6 * rate_me.abilities[ABIL_DIV]); if (hitp) rating := rating + (8 * rate_me.abilities[ABIL_HP]); return (rating); } dilend /* rate_pc */ /* This function does the slog work for aggressive@function. */ dilbegin string find_targ (tar : integer, sx1 : integer, alig : integer, rce : integer, opp : integer, mlev : integer, hlev: integer, sanc : integer); external integer rate_pc (rate_me : unitptr, stre : integer, dext : integer, cons : integer, char : integer, brai : integer, magi : integer, divi : integer, hitp : integer); var pc : string; /* The victim's name */ loseu : string; /* In case we lose u, which we do (scream) */ u : unitptr; /* The temporary unitptr */ rating : integer; /* The Rating of the PC in terms of abilities */ lowrating : integer; /* The lowest rating encountered so far */ highrating: integer; /* The highest rating encountered so far */ verdict : integer; /* Used as pass value for the unitptr test */ urace : integer; /* The PC's race */ ulevel : integer; /* The PC's level */ sancvar : integer; /* Whether the PC has SANCTUARY cast on self */ soothe : integer; /* Whether the PC has SOOTHE cast on self */ ualign : integer; /* The PC's alignment*/ usex : integer; /* The PC's sex */ count : integer; /* The count of elligible PCs checked so far */ /* All the integers are necessary because the foreach seems to lose track of the u half-way through. */ code { :init: heartbeat:=PULSE_SEC*3; /* In case we need it */ count := 0; /* Initialise the variable (no real reason) */ foreach (UNIT_ST_PC, u) { loseu := u.name; ulevel := 0; urace := 0; sancvar := 0; soothe := 0; verdict := 1; /* Innocent until proven guilty. Ie, it passes the tests unless we prove otherwise. If verdict == 0, this u fails. */ ulevel := u.level; urace := u.race; ualign := u.alignment; usex := u.sex; sancvar := isaff(u, ID_SANCTUARY); if ("$ID_SOOTHE" in u.extra) soothe := 1; if (not(visible(self, u))) verdict := 0; rating := rate_pc (u, 1, 1, 0, 0, 1, 1, 1, 1); /* Go get the pc's rating */ /* SEX */ if (sx1 != 5) { if (usex != sx1) verdict := 0; } /* ALIGNMENT */ if (alig != 2) { if (alig == -1) { if (ualign > -350) verdict := 0; } else if (alig == 0) { if ((ualign < -349) or (ualign > 349)) verdict := 0; } else if (alig == 1) { if (ualign < 350) verdict := 0; } else verdict := 0; } /* RACE */ if ((rce != -1) or (opp != FALSE)) { if (opp == 1) { if (urace!= rce) verdict := 0; } if (opp == 2) { if (urace == rce) verdict := 0; } } /* LEVEL */ if ((ulevel < mlev) or (ulevel > hlev)) verdict := 0; /* SANC */ if (sanc != 0) { if (sanc == 1) { if (sancvar == TRUE) verdict := 0; } if (sanc == 2) { if (soothe == TRUE) verdict := 0; } if (sanc == 3) { if ((sancvar) or (soothe)) verdict := 0; } } if ( verdict ) count := count + 1; /* Increment the count if passed */ if ( ( verdict ) and ( tar == FALSE ) ) /* If passes and looking for random PC. */ { if (rnd(1,count) == 1) pc:=loseu; } else if ( ( verdict ) and ( tar == -2 ) ) /* If passes and looking for last PC to enter. */ { if (count == 1) pc:=loseu; } else if ( ( verdict ) and ( tar == 2 ) ) /* If passes and looking for first PC to enter. */ { pc:=loseu; /* The last person to pass will be firstpc and we then have the value we want. */ } else if ( ( verdict ) and ( tar == -1 ) ) /* If passes and looking for weakest PC to enter. */ { if (count == 1) { lowrating := rating; pc := loseu; } else if (rating < lowrating) { lowrating := rating; pc := loseu; } } else if ( ( verdict ) and ( tar == 1 ) ) /* If passes and looking for strongest PC to enter. */ { if (count == 1) { highrating := rating; pc := loseu; } else if (rating > highrating) { highrating := rating; pc := loseu; } } } /* END FOREACH */ :pass_back: return(pc); } dilend /* find_targ */ /* Function: comb_poison Usage: dilcopy comb_poison@function(toact : string, restact : string); toact is what the victim sees when poisoned. restact is what everyone else sees when the victim is poisoned. Example: dilcopy comb_poison@function("You feel very ill as $1n bites you!", "$1n sinks $1s fangs deep into $3n!"); Notes: It is recommended that builders set magic and brain abilities on mobiles using this function for optimal performance. */ dilbegin aware comb_poison(toact : string, restact : string); var i : integer; code { heartbeat := PULSE_VIOLENCE; :start: wait(SFB_PRE, command(CMD_AUTO_DAMAGE)); if ((activator == self) and (rnd(1,10) > 5)) { if (activator == target) quit; i := cast_spell(SPL_POISON, self, self, target, ""); if (i < 0) i := 0; power := power + (i/5); act(toact, A_ALWAYS, self, null, target, TO_VICT); act(restact, A_SOMEONE, self, null, target, TO_NOTVICT); } goto start; } dilend %rooms dil_chamber names {"dil"} title "Dil Chamber." descr "Magic of great power swirls and dances about you. You stand on something yet nothing. You feel everything yet you touch nothing. Your full yet hungry. This you realize is where the life of the world is held. Stand and fly, feel safe with no fear." flags {UNIT_FL_NO_TELEPORT} end %en