diff --git a/changelog b/changelog index 43ad59d..7460a66 100644 --- a/changelog +++ b/changelog @@ -37,6 +37,11 @@ Xlist (mlist, olist, rlist, zlist, slist, tlist, qlist) tbaMUD 3.59 [Mar 13 2009] - Jamdog Bug-Fix: Character deletion (remove_player, players.c), where the wrong player was potentially being deleted. + Added Zone Flags, including zedit sub-menu + Added Zone level restrictions, including zedit sub-menu + Added zlock and zunlock commands + Added areas command + Set GRID flag on zones 0, 12 and 30 [Mar 08 2009] - Jamdog Fixed a possible crash bug in delete_object (genobj.c) (Thanks Slicer) CAP function now recognises both preceeding color codes and ANSI codes (Thanks Slicer) diff --git a/lib/world/zon/0.zon b/lib/world/zon/0.zon index 080ea53..c882f3e 100644 --- a/lib/world/zon/0.zon +++ b/lib/world/zon/0.zon @@ -1,14 +1,14 @@ #0 Rumble~ The Builder Academy Zone~ -0 99 10 2 +0 99 10 2 d 0 0 0 -1 -1 +M 0 1 1 1 (Puff) D 0 89 4 2 (The Prison Cell Corridor) M 0 31 1 89 (the Commissar) G 1 68 99 -1 (the Commissar's key) M 0 18 1 2 (Friedrich Nietzsche) R 0 88 1228 -1 (a advertising bulletin board) O 0 1228 99 88 (a advertising bulletin board) -M 0 1 1 1 (Puff) R 0 90 86 -1 (a pair of shackles) R 0 90 84 -1 (the shower drain) O 0 84 1 90 (the shower drain) diff --git a/lib/world/zon/30.zon b/lib/world/zon/30.zon index 6e2ba87..d9b6496 100644 --- a/lib/world/zon/30.zon +++ b/lib/world/zon/30.zon @@ -1,173 +1,173 @@ -#30 -DikuMUD~ -Northern Midgaard~ -3000 3099 15 2 -R 0 3000 3099 -1 (a bulletin board) -O 0 3099 99 3000 (a bulletin board) -M 0 3045 1 3022 (the waiter) -G 1 3002 100 -1 (a bottle) -G 1 3003 100 -1 (a bottle) -G 1 3004 100 -1 (a bottle) -E 1 3022 100 16 (a long sword) -R 0 3022 3096 -1 (a social bulletin board) -O 0 3096 99 3022 (a social bulletin board) -M 0 3044 1 3028 (the waiter) -G 1 3003 100 -1 (a bottle) -G 1 3004 100 -1 (a bottle) -E 1 3021 100 16 (a small sword) -R 0 3028 3096 -1 (a social bulletin board) -O 0 3096 99 3028 (a social bulletin board) -M 0 3043 1 3003 (the waiter) -G 1 3002 100 -1 (a bottle) -G 1 3004 100 -1 (a bottle) -E 1 3024 100 16 (a warhammer) -R 0 3003 3096 -1 (a social bulletin board) -O 0 3096 99 3003 (a social bulletin board) -M 0 3042 1 3018 (the waiter) -G 1 3002 100 -1 (a bottle) -G 1 3003 100 -1 (a bottle) -E 1 3020 100 16 (a dagger) -R 0 3018 3096 -1 (a social bulletin board) -O 0 3096 99 3018 (a social bulletin board) -M 0 3009 1 3058 (Wally the Watermaster) -G 1 3102 100 -1 (a cup) -G 1 3103 100 -1 (a bottle) -G 1 3104 100 -1 (a canteen) -M 0 3026 1 3027 (the assassin) -E 1 3022 100 16 (a long sword) -M 0 3059 5 3027 (the Peacekeeper) -M 0 3060 10 3027 (the cityguard) -E 1 3022 100 16 (a long sword) -R 0 3027 3034 -1 (an automatic teller machine) -O 0 3034 99 3027 (an automatic teller machine) -M 0 3027 1 3021 (the knight) -E 1 3022 100 16 (a long sword) -M 0 3059 5 3021 (the Peacekeeper) -M 0 3060 10 3021 (the cityguard) -E 1 3022 100 16 (a long sword) -R 0 3021 3034 -1 (an automatic teller machine) -O 0 3034 99 3021 (an automatic teller machine) -M 0 3024 1 3017 (the sorcerer) -E 1 3022 100 16 (a long sword) -M 0 3059 5 3017 (the Peacekeeper) -M 0 3060 10 3017 (the cityguard) -E 1 3022 100 16 (a long sword) -R 0 3017 3034 -1 (an automatic teller machine) -O 0 3034 99 3017 (an automatic teller machine) -M 0 3025 1 3004 (the knight templar) -E 1 3022 100 16 (a long sword) -M 0 3059 5 3004 (the Peacekeeper) -M 0 3060 10 3004 (the cityguard) -E 1 3022 100 16 (a long sword) -R 0 3004 3034 -1 (an automatic teller machine) -O 0 3034 99 3004 (an automatic teller machine) -M 0 3005 1 3008 (the receptionist) -E 1 3022 100 16 (a long sword) -M 0 3068 4 3008 (the green gelatinous blob) -R 0 3008 3034 -1 (an automatic teller machine) -O 0 3034 99 3008 (an automatic teller machine) -R 0 3001 3034 -1 (an automatic teller machine) -O 0 3034 99 3001 (an automatic teller machine) -M 0 98 1 3001 (the travelling saleswoman) -G 1 82 99 -1 (the teleporter) -M 0 13 2 3063 (a kind soul) -M 0 3000 1 3033 (the wizard) -G 1 3050 500 -1 (a scroll of identify) -G 1 3051 500 -1 (a yellow potion of see invisible) -G 1 3052 500 -1 (a scroll of recall) -G 1 3053 500 -1 (a grey wand of invisibility) -G 1 3054 500 -1 (a gnarled staff) -M 0 3001 1 3009 (the baker) -G 1 3009 100 -1 (a waybread) -G 1 3010 100 -1 (a bread) -G 1 3011 100 -1 (a danish pastry) -E 1 3022 100 16 (a long sword) -M 0 3002 1 3010 (the grocer) -G 1 3030 100 -1 (a torch) -G 1 3031 100 -1 (a lantern) -G 1 3032 100 -1 (a bag) -G 1 3033 100 -1 (a box) -G 1 3036 100 -1 (a cashcard) -E 1 3022 100 16 (a long sword) -M 0 3003 1 3011 (the weaponsmith) -G 1 3020 100 -1 (a dagger) -G 1 3021 100 -1 (a small sword) -G 1 3022 100 -1 (a long sword) -G 1 3023 100 -1 (a wooden club) -G 1 3024 100 -1 (a warhammer) -G 1 3025 100 -1 (a flail) -E 1 3022 100 16 (a long sword) -M 0 3004 1 3020 (the armourer) -G 1 3040 100 -1 (a breast plate) -G 1 3041 100 -1 (a chain mail shirt) -G 1 3042 100 -1 (a shield) -G 1 3043 100 -1 (a leather jacket) -G 1 3044 100 -1 (a studded leather jacket) -G 1 3045 100 -1 (a scale mail jacket) -G 1 3046 100 -1 (a bronze breast plate) -G 1 3070 100 -1 (a pair of bronze gauntlets) -G 1 3071 100 -1 (a pair of leather gloves) -G 1 3075 100 -1 (a bronze helmet) -G 1 3076 100 -1 (a leather cap) -G 1 3080 100 -1 (a pair of bronze leggings) -G 1 3081 100 -1 (a pair of leather pants) -G 1 3085 100 -1 (a pair of bronze sleeves) -G 1 3086 100 -1 (a pair of leather sleeves) -E 1 3022 100 16 (a long sword) -M 0 3006 1 3049 (Captain Stolar) -G 1 3060 20 -1 (a raft) -G 1 3061 10 -1 (a canoe) -M 0 3007 1 3050 (the sailor) -M 0 3010 1 3062 (the postmaster) -M 0 3020 1 3019 (the mages' guildmaster) -M 0 3021 1 3002 (the priests' guildmaster) -M 0 3022 1 3029 (the thieves' guildmaster) -M 0 3023 1 3023 (the fighters' guildmaster) -M 0 3040 1 3007 (the bartender) -G 1 3000 100 -1 (a barrel) -G 1 3001 100 -1 (a bottle) -G 1 3002 100 -1 (a bottle) -G 1 3003 100 -1 (a bottle) -G 1 3004 100 -1 (a bottle) -E 1 3022 100 16 (a long sword) -M 0 3046 1 3048 (Filthy) -G 1 3003 100 -1 (a bottle) -G 1 3004 100 -1 (a bottle) -E 1 3022 100 16 (a long sword) -M 0 3059 5 3014 (the Peacekeeper) -M 0 3060 10 3014 (the cityguard) -E 1 3022 100 16 (a long sword) -M 0 3061 5 3006 (the janitor) -M 0 3062 15 3024 (the beastly fido) -G 1 3015 30 -1 (a piece of meat) -M 0 3062 15 3025 (the beastly fido) -G 1 3015 30 -1 (a piece of meat) -M 0 3062 15 3016 (the beastly fido) -G 1 3015 30 -1 (a piece of meat) -M 0 3062 15 3012 (the beastly fido) -G 1 3015 30 -1 (a piece of meat) -M 0 3063 5 3026 (the mercenary) -E 1 3021 100 16 (a small sword) -M 0 3064 3 3007 (the drunk) -M 0 3065 2 3044 (the beggar) -G 1 3005 1 -1 (a key of dull metal) -M 0 3065 2 3048 (the beggar) -M 0 3066 1 3026 (the odif yltsaeb) -G 1 3015 30 -1 (a piece of meat) -M 0 3067 10 3041 (the cityguard) -E 1 3022 100 16 (a long sword) -M 0 3067 10 3040 (the cityguard) -E 1 3022 100 16 (a long sword) -M 0 3068 4 3014 (the green gelatinous blob) -M 0 3089 1 3031 (the Pet Shop Boy) -M 0 3090 1 3032 (the kitten) -M 0 3091 1 3032 (the puppy) -M 0 3092 1 3032 (the beagle) -M 0 3093 1 3032 (the rottweiler) -M 0 3094 1 3032 (the wolf) -M 0 3095 1 3064 (the cryogenicist) -E 1 3022 100 16 (a long sword) -R 0 3005 3035 -1 (the large fountain) -O 0 3035 1 3005 (the large fountain) -S -$ +#30 +DikuMUD~ +Northern Midgaard~ +3000 3099 15 2 d 0 0 0 -1 -1 +R 0 3000 3099 -1 (a bulletin board) +O 0 3099 99 3000 (a bulletin board) +M 0 3045 1 3022 (the waiter) +G 1 3002 100 -1 (a bottle) +G 1 3003 100 -1 (a bottle) +G 1 3004 100 -1 (a bottle) +E 1 3022 100 16 (a long sword) +R 0 3022 3096 -1 (a social bulletin board) +O 0 3096 99 3022 (a social bulletin board) +M 0 3044 1 3028 (the waiter) +G 1 3003 100 -1 (a bottle) +G 1 3004 100 -1 (a bottle) +E 1 3021 100 16 (a small sword) +R 0 3028 3096 -1 (a social bulletin board) +O 0 3096 99 3028 (a social bulletin board) +M 0 3043 1 3003 (the waiter) +G 1 3002 100 -1 (a bottle) +G 1 3004 100 -1 (a bottle) +E 1 3024 100 16 (a warhammer) +R 0 3003 3096 -1 (a social bulletin board) +O 0 3096 99 3003 (a social bulletin board) +M 0 3042 1 3018 (the waiter) +G 1 3002 100 -1 (a bottle) +G 1 3003 100 -1 (a bottle) +E 1 3020 100 16 (a dagger) +R 0 3018 3096 -1 (a social bulletin board) +O 0 3096 99 3018 (a social bulletin board) +M 0 3009 1 3058 (Wally the Watermaster) +G 1 3102 100 -1 (a cup) +G 1 3103 100 -1 (a bottle) +G 1 3104 100 -1 (a canteen) +M 0 3026 1 3027 (the assassin) +E 1 3022 100 16 (a long sword) +M 0 3059 5 3027 (the Peacekeeper) +M 0 3060 10 3027 (the cityguard) +E 1 3022 100 16 (a long sword) +R 0 3027 3034 -1 (an automatic teller machine) +O 0 3034 99 3027 (an automatic teller machine) +M 0 3027 1 3021 (the knight) +E 1 3022 100 16 (a long sword) +M 0 3059 5 3021 (the Peacekeeper) +M 0 3060 10 3021 (the cityguard) +E 1 3022 100 16 (a long sword) +R 0 3021 3034 -1 (an automatic teller machine) +O 0 3034 99 3021 (an automatic teller machine) +M 0 3024 1 3017 (the sorcerer) +E 1 3022 100 16 (a long sword) +M 0 3059 5 3017 (the Peacekeeper) +M 0 3060 10 3017 (the cityguard) +E 1 3022 100 16 (a long sword) +R 0 3017 3034 -1 (an automatic teller machine) +O 0 3034 99 3017 (an automatic teller machine) +M 0 3025 1 3004 (the knight templar) +E 1 3022 100 16 (a long sword) +M 0 3059 5 3004 (the Peacekeeper) +M 0 3060 10 3004 (the cityguard) +E 1 3022 100 16 (a long sword) +R 0 3004 3034 -1 (an automatic teller machine) +O 0 3034 99 3004 (an automatic teller machine) +M 0 3005 1 3008 (the receptionist) +E 1 3022 100 16 (a long sword) +M 0 3068 4 3008 (the green gelatinous blob) +R 0 3008 3034 -1 (an automatic teller machine) +O 0 3034 99 3008 (an automatic teller machine) +R 0 3001 3034 -1 (an automatic teller machine) +O 0 3034 99 3001 (an automatic teller machine) +M 0 98 1 3001 (the travelling saleswoman) +G 1 82 99 -1 (the teleporter) +M 0 13 2 3063 (a kind soul) +M 0 3000 1 3033 (the wizard) +G 1 3050 500 -1 (a scroll of identify) +G 1 3051 500 -1 (a yellow potion of see invisible) +G 1 3052 500 -1 (a scroll of recall) +G 1 3053 500 -1 (a grey wand of invisibility) +G 1 3054 500 -1 (a gnarled staff) +M 0 3001 1 3009 (the baker) +G 1 3009 100 -1 (a waybread) +G 1 3010 100 -1 (a bread) +G 1 3011 100 -1 (a danish pastry) +E 1 3022 100 16 (a long sword) +M 0 3002 1 3010 (the grocer) +G 1 3030 100 -1 (a torch) +G 1 3031 100 -1 (a lantern) +G 1 3032 100 -1 (a bag) +G 1 3033 100 -1 (a box) +G 1 3036 100 -1 (a cashcard) +E 1 3022 100 16 (a long sword) +M 0 3003 1 3011 (the weaponsmith) +G 1 3020 100 -1 (a dagger) +G 1 3021 100 -1 (a small sword) +G 1 3022 100 -1 (a long sword) +G 1 3023 100 -1 (a wooden club) +G 1 3024 100 -1 (a warhammer) +G 1 3025 100 -1 (a flail) +E 1 3022 100 16 (a long sword) +M 0 3004 1 3020 (the armourer) +G 1 3040 100 -1 (a breast plate) +G 1 3041 100 -1 (a chain mail shirt) +G 1 3042 100 -1 (a shield) +G 1 3043 100 -1 (a leather jacket) +G 1 3044 100 -1 (a studded leather jacket) +G 1 3045 100 -1 (a scale mail jacket) +G 1 3046 100 -1 (a bronze breast plate) +G 1 3070 100 -1 (a pair of bronze gauntlets) +G 1 3071 100 -1 (a pair of leather gloves) +G 1 3075 100 -1 (a bronze helmet) +G 1 3076 100 -1 (a leather cap) +G 1 3080 100 -1 (a pair of bronze leggings) +G 1 3081 100 -1 (a pair of leather pants) +G 1 3085 100 -1 (a pair of bronze sleeves) +G 1 3086 100 -1 (a pair of leather sleeves) +E 1 3022 100 16 (a long sword) +M 0 3006 1 3049 (Captain Stolar) +G 1 3060 20 -1 (a raft) +G 1 3061 10 -1 (a canoe) +M 0 3007 1 3050 (the sailor) +M 0 3010 1 3062 (the postmaster) +M 0 3020 1 3019 (the mages' guildmaster) +M 0 3021 1 3002 (the priests' guildmaster) +M 0 3022 1 3029 (the thieves' guildmaster) +M 0 3023 1 3023 (the fighters' guildmaster) +M 0 3040 1 3007 (the bartender) +G 1 3000 100 -1 (a barrel) +G 1 3001 100 -1 (a bottle) +G 1 3002 100 -1 (a bottle) +G 1 3003 100 -1 (a bottle) +G 1 3004 100 -1 (a bottle) +E 1 3022 100 16 (a long sword) +M 0 3046 1 3048 (Filthy) +G 1 3003 100 -1 (a bottle) +G 1 3004 100 -1 (a bottle) +E 1 3022 100 16 (a long sword) +M 0 3059 5 3014 (the Peacekeeper) +M 0 3060 10 3014 (the cityguard) +E 1 3022 100 16 (a long sword) +M 0 3061 5 3006 (the janitor) +M 0 3062 15 3024 (the beastly fido) +G 1 3015 30 -1 (a piece of meat) +M 0 3062 15 3025 (the beastly fido) +G 1 3015 30 -1 (a piece of meat) +M 0 3062 15 3016 (the beastly fido) +G 1 3015 30 -1 (a piece of meat) +M 0 3062 15 3012 (the beastly fido) +G 1 3015 30 -1 (a piece of meat) +M 0 3063 5 3026 (the mercenary) +E 1 3021 100 16 (a small sword) +M 0 3064 3 3007 (the drunk) +M 0 3065 2 3044 (the beggar) +G 1 3005 1 -1 (a key of dull metal) +M 0 3065 2 3048 (the beggar) +M 0 3066 1 3026 (the odif yltsaeb) +G 1 3015 30 -1 (a piece of meat) +M 0 3067 10 3041 (the cityguard) +E 1 3022 100 16 (a long sword) +M 0 3067 10 3040 (the cityguard) +E 1 3022 100 16 (a long sword) +M 0 3068 4 3014 (the green gelatinous blob) +M 0 3089 1 3031 (the Pet Shop Boy) +M 0 3090 1 3032 (the kitten) +M 0 3091 1 3032 (the puppy) +M 0 3092 1 3032 (the beagle) +M 0 3093 1 3032 (the rottweiler) +M 0 3094 1 3032 (the wolf) +M 0 3095 1 3064 (the cryogenicist) +E 1 3022 100 16 (a long sword) +R 0 3005 3035 -1 (the large fountain) +O 0 3035 1 3005 (the large fountain) +S +$ diff --git a/lib/world/zon/31.zon b/lib/world/zon/31.zon index 06e938f..8fab45e 100644 --- a/lib/world/zon/31.zon +++ b/lib/world/zon/31.zon @@ -1,58 +1,58 @@ -#31 -DikuMUD~ -Southern Midgaard~ -3100 3199 30 2 -M 0 3060 20 3111 (the cityguard) -E 1 3022 100 16 (a long sword) -G 1 3105 2 -1 (an iron key) -M 0 3060 20 3111 (the cityguard) -E 1 3022 100 16 (a long sword) -M 0 3060 20 3111 (the cityguard) -E 1 3022 100 16 (a long sword) -M 0 3060 20 3111 (the cityguard) -E 1 3022 100 16 (a long sword) -M 0 3068 4 3106 (the green gelatinous blob) -M 0 3100 1 3106 (the Maid) -G 1 3100 500 -1 (a cup) -G 1 3101 500 -1 (a cup) -G 1 3102 500 -1 (a cup) -M 0 3101 1 3106 (the Sexton) -G 1 3106 2 -1 (a rusty key) -M 0 3102 1 3110 (the Chief Guard) -G 1 3107 2 -1 (a wooden key) -M 0 3103 4 3110 (the upset cityguard) -M 1 3103 4 3110 (the upset cityguard) -M 1 3103 4 3110 (the upset cityguard) -M 1 3103 4 3110 (the upset cityguard) -M 0 3104 1 3137 (the Secretary) -M 0 3105 1 3138 (the Mayor) -E 1 3112 1 17 (the City Key) -M 0 3106 1 3120 (the Town Crier) -M 0 3120 1 3114 (the swan) -M 0 3121 1 3114 (the duckling) -M 0 3122 1 3109 (the sparrow) -M 0 3123 2 3113 (the duck) -M 0 3123 2 3115 (the duck) -O 0 3109 1 3110 (the desk) -P 1 3108 1 3109 (a brass key) -O 0 3110 1 3110 (the safe) -P 1 3115 1 3110 (the gold) -R 0 3101 3111 -1 (the Bench) -O 0 3111 3 3101 (the Bench) -R 0 3102 3111 -1 (the Bench) -O 0 3111 3 3102 (the Bench) -R 0 3103 3111 -1 (the Bench) -O 0 3111 3 3103 (the Bench) -R 0 3141 3113 -1 (a fountain) -O 0 3113 1 3141 (a fountain) -O 0 3114 1 3141 (a small pile of gold coins) -O 0 3116 1 3155 (a candlestick) -O 0 3117 1 3124 (an elm tree) -D 0 3111 3 2 (Park Road) -D 0 3110 1 2 (Cityguard HeadQuarters) -D 0 3129 2 2 (On The Concourse) -D 0 3150 0 2 (A Gravel Road In The Graveyard) -D 0 3154 2 1 (In Front Of The Chapel) -D 0 3155 0 1 (Inside The Chapel) -S -$ +#31 +DikuMUD~ +Southern Midgaard~ +3100 3199 30 2 d 0 0 0 -1 -1 +M 0 3060 20 3111 (the cityguard) +E 1 3022 100 16 (a long sword) +G 1 3105 2 -1 (an iron key) +M 0 3060 20 3111 (the cityguard) +E 1 3022 100 16 (a long sword) +M 0 3060 20 3111 (the cityguard) +E 1 3022 100 16 (a long sword) +M 0 3060 20 3111 (the cityguard) +E 1 3022 100 16 (a long sword) +M 0 3068 4 3106 (the green gelatinous blob) +M 0 3100 1 3106 (the Maid) +G 1 3100 500 -1 (a cup) +G 1 3101 500 -1 (a cup) +G 1 3102 500 -1 (a cup) +M 0 3101 1 3106 (the Sexton) +G 1 3106 2 -1 (a rusty key) +M 0 3102 1 3110 (the Chief Guard) +G 1 3107 2 -1 (a wooden key) +M 0 3103 4 3110 (the upset cityguard) +M 1 3103 4 3110 (the upset cityguard) +M 1 3103 4 3110 (the upset cityguard) +M 1 3103 4 3110 (the upset cityguard) +M 0 3104 1 3137 (the Secretary) +M 0 3105 1 3138 (the Mayor) +E 1 3112 1 17 (the City Key) +M 0 3106 1 3120 (the Town Crier) +M 0 3120 1 3114 (the swan) +M 0 3121 1 3114 (the duckling) +M 0 3122 1 3109 (the sparrow) +M 0 3123 2 3113 (the duck) +M 0 3123 2 3115 (the duck) +O 0 3109 1 3110 (the desk) +P 1 3108 1 3109 (a brass key) +O 0 3110 1 3110 (the safe) +P 1 3115 1 3110 (the gold) +R 0 3101 3111 -1 (the Bench) +O 0 3111 3 3101 (the Bench) +R 0 3102 3111 -1 (the Bench) +O 0 3111 3 3102 (the Bench) +R 0 3103 3111 -1 (the Bench) +O 0 3111 3 3103 (the Bench) +R 0 3141 3113 -1 (a fountain) +O 0 3113 1 3141 (a fountain) +O 0 3114 1 3141 (a small pile of gold coins) +O 0 3116 1 3155 (a candlestick) +O 0 3117 1 3124 (an elm tree) +D 0 3111 3 2 (Park Road) +D 0 3110 1 2 (Cityguard HeadQuarters) +D 0 3129 2 2 (On The Concourse) +D 0 3150 0 2 (A Gravel Road In The Graveyard) +D 0 3154 2 1 (In Front Of The Chapel) +D 0 3155 0 1 (Inside The Chapel) +S +$ diff --git a/src/act.h b/src/act.h index f594d11..8d556ac 100644 --- a/src/act.h +++ b/src/act.h @@ -82,6 +82,7 @@ ACMD(do_look); #define SCMD_LOOK 0 #define SCMD_READ 1 /* functions without subcommands */ +ACMD(do_areas); ACMD(do_consider); ACMD(do_diagnose); ACMD(do_equipment); @@ -339,7 +340,9 @@ ACMD(do_wizlock); ACMD(do_wiznet); ACMD(do_wizupdate); ACMD(do_zcheck); +ACMD(do_zlock); ACMD(do_zpurge); ACMD(do_zreset); +ACMD(do_zunlock); #endif /* _ACT_H_ */ diff --git a/src/act.informative.c b/src/act.informative.c index 50a8713..aaa03d7 100644 --- a/src/act.informative.c +++ b/src/act.informative.c @@ -2400,3 +2400,110 @@ ACMD(do_whois) if (got_from_file) free_char (victim); } + +bool get_zone_levels(zone_rnum znum, char *buf) +{ + /* Create a string for the level restrictions for this zone. */ + if ((zone_table[znum].min_level == -1) && (zone_table[znum].max_level == -1)) { + sprintf(buf, ""); + return FALSE; + } + + if (zone_table[znum].min_level == -1) { + sprintf(buf, "Up to level %d", zone_table[znum].max_level); + return TRUE; + } + + if (zone_table[znum].max_level == -1) { + sprintf(buf, "Above level %d", zone_table[znum].min_level); + return TRUE; + } + + sprintf(buf, "Levels %d to %d", zone_table[znum].min_level, zone_table[znum].max_level); + return TRUE; +} + +ACMD(do_areas) +{ + int i, hilev=-1, lolev=-1, zcount=0, lev_set; + char arg[MAX_INPUT_LENGTH], *second, lev_str[MAX_INPUT_LENGTH]; + bool show_zone = FALSE, overlap = FALSE, overlap_shown = FALSE; + + one_argument(argument, arg); + + if (*arg) { + /* There was an arg typed - check for level range */ + second = strchr(arg, '-'); + if (second) { + /* Check for 1st value */ + if (second == arg) + lolev = 0; + else + lolev = atoi(arg); + + /* Check for 2nd value */ + if (*(second+1) == '\0' || !isdigit(*(second+1)) ) + hilev = 100; + else + hilev = atoi(second+1); + + } else { + /* No range - single number */ + lolev = atoi(arg); + hilev = -1; /* No high level - indicates single level */ + } + } + if (hilev != -1 && lolev > hilev) { + /* Swap hi and lo lev if needed */ + i = lolev; + lolev = hilev; + hilev = i; + } + if (hilev != -1) + send_to_char(ch, "Checking range: %s%d to %d%s\r\n", QYEL, lolev, hilev, QNRM); + else if (lolev != -1) + send_to_char(ch, "Checking level: %s%d%s\r\n", QYEL, lolev, QNRM); + else + send_to_char(ch, "Checking all areas.\r\n"); + + for (i = 0; i <= top_of_zone_table; i++) { /* Go through the whole zone table */ + show_zone = FALSE; + overlap = FALSE; + + if (ZONE_FLAGGED(i, ZONE_GRID)) { /* Is this zone 'on the grid' ? */ + if (lolev == -1) { + /* No range supplied, show all zones */ + show_zone = TRUE; + } else if ((hilev == -1) && (lolev >= ZONE_MINLVL(i)) && (lolev <= ZONE_MAXLVL(i))) { + /* Single number supplied, it's in this zone's range */ + show_zone = TRUE; + } else if ((hilev != -1) && (lolev >= ZONE_MINLVL(i)) && (hilev <= ZONE_MAXLVL(i))) { + /* Range supplied, it's completely within this zone's range (no overlap) */ + show_zone = TRUE; + } else if ((hilev != -1) && ((lolev >= ZONE_MINLVL(i) && lolev <= ZONE_MAXLVL(i)) || (hilev <= ZONE_MAXLVL(i) && hilev >= ZONE_MINLVL(i)))) { + /* Range supplied, it overlaps this zone's range */ + show_zone = TRUE; + overlap = TRUE; + } else if (ZONE_MAXLVL(i) < 0 && (lolev >= ZONE_MINLVL(i))) { + /* Max level not set for this zone, but specified min in range */ + show_zone = TRUE; + } else if (ZONE_MAXLVL(i) < 0 && (hilev >= ZONE_MINLVL(i))) { + /* Max level not set for this zone, so just display it as red */ + show_zone = TRUE; + overlap = TRUE; + } + } + + if (show_zone) { + if (overlap) overlap_shown = TRUE; + lev_set = get_zone_levels(i, lev_str); + send_to_char(ch, "@n(%3d) %s%-*s@n %s%s@n\r\n", ++zcount, overlap ? QRED : QCYN, + count_color_chars(zone_table[i].name)+30, zone_table[i].name, + lev_set ? "@c" : "@n", lev_set ? lev_str : "All Levels"); + } + } + send_to_char(ch, "%s%d%s area%s found.\r\n", QYEL, zcount, QNRM, zcount == 1 ? "" : "s"); + + if (overlap_shown) + send_to_char(ch, "Areas shown in @rred@n may have some creatures outside the specified range.\r\n"); +} diff --git a/src/act.movement.c b/src/act.movement.c index 34c96c5..17a4434 100644 --- a/src/act.movement.c +++ b/src/act.movement.c @@ -85,7 +85,7 @@ int has_flight(struct char_data *ch) return (0); } -/* Simple function to determine if char can scuba. */ +/* Simple function to determine if char can scuba. */ int has_scuba(struct char_data *ch) { struct obj_data *obj; @@ -115,7 +115,7 @@ int has_scuba(struct char_data *ch) * movement by characters should be sent through. This function also defines * the move cost of normal locomotion as: * ( (move cost for source room) + (move cost for destination) ) / 2 - * + * * @pre Function assumes that ch has no master controlling character, that * ch has no followers (in other words followers won't be moved by this * function) and that the direction traveled in is one of the valid, enumerated @@ -123,8 +123,8 @@ int has_scuba(struct char_data *ch) * @param ch The character structure to attempt to move. * @param dir The defined direction (NORTH, SOUTH, etc...) to attempt to * move into. - * @param need_specials_check If TRUE will cause - * @retval int 1 for a successful move (ch is now in a new location) + * @param need_specials_check If TRUE will cause + * @retval int 1 for a successful move (ch is now in a new location) * or 0 for a failed move (ch is still in the original location). */ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) { @@ -136,23 +136,23 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) /* The room the character is currently in and will move from... */ room_rnum was_in = IN_ROOM(ch); /* ... and the room the character will move into. */ - room_rnum going_to = EXIT(ch, dir)->to_room; + room_rnum going_to = EXIT(ch, dir)->to_room; /* How many movement points are required to travel from was_in to going_to. - * We redefine this later when we need it. */ + * We redefine this later when we need it. */ int need_movement = 0; /* Contains the "leave" message to display to the was_in room. */ char leave_message[SMALL_BUFSIZE]; /*---------------------------------------------------------------------*/ /* End Local variable definitions */ - - + + /* Begin checks that can prevent a character from leaving the was_in room. */ /* Future checks should be implemented within this section and return 0. */ /*---------------------------------------------------------------------*/ /* Check for special routines that might activate because of the move and * also might prevent the movement. Special requires commands, so we pass - * in the "command" equivalent of the direction (ie. North is '1' in the - * command list, but NORTH is defined as '0'). + * in the "command" equivalent of the direction (ie. North is '1' in the + * command list, but NORTH is defined as '0'). * Note -- only check if following; this avoids 'double spec-proc' bug */ if (need_specials_check && special(ch, dir + 1, spec_proc_args)) return 0; @@ -164,9 +164,9 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) return 0; if (!leave_otrigger(&world[IN_ROOM(ch)], ch, dir) || IN_ROOM(ch) != was_in) /* prevent teleport crashes */ return 0; - + /* Charm effect: Does it override the movement? */ - if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && was_in == IN_ROOM(ch->master)) + if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && was_in == IN_ROOM(ch->master)) { send_to_char(ch, "The thought of leaving your master makes you weep.\r\n"); act("$n bursts into tears.", FALSE, ch, 0, 0, TO_ROOM); @@ -175,9 +175,9 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) /* Water, No Swimming Rooms: Does the deep water prevent movement? */ if ((SECT(was_in) == SECT_WATER_NOSWIM) || - (SECT(going_to) == SECT_WATER_NOSWIM)) + (SECT(going_to) == SECT_WATER_NOSWIM)) { - if (!has_boat(ch)) + if (!has_boat(ch)) { send_to_char(ch, "You need a boat to go there.\r\n"); return (0); @@ -185,9 +185,9 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) } /* Flying Required: Does lack of flying prevent movement? */ - if ((SECT(was_in) == SECT_FLYING) || (SECT(going_to) == SECT_FLYING)) + if ((SECT(was_in) == SECT_FLYING) || (SECT(going_to) == SECT_FLYING)) { - if (!has_flight(ch)) + if (!has_flight(ch)) { send_to_char(ch, "You need to be flying to go there!\r\n"); return (0); @@ -195,7 +195,7 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) } /* Underwater Room: Does lack of underwater breathing prevent movement? */ - if ((SECT(was_in) == SECT_UNDERWATER) || (SECT(going_to) == SECT_UNDERWATER)) + if ((SECT(was_in) == SECT_UNDERWATER) || (SECT(going_to) == SECT_UNDERWATER)) { if (!has_scuba(ch)) { send_to_char(ch, "You need to be able to breathe water to go there!\r\n"); @@ -204,18 +204,38 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) } /* Houses: Can the player walk into the house? */ - if (ROOM_FLAGGED(was_in, ROOM_ATRIUM)) + if (ROOM_FLAGGED(was_in, ROOM_ATRIUM)) { - if (!House_can_enter(ch, GET_ROOM_VNUM(going_to))) + if (!House_can_enter(ch, GET_ROOM_VNUM(going_to))) { send_to_char(ch, "That's private property -- no trespassing!\r\n"); return (0); } } + /* Check zone level restrictions */ + if ((ZONE_MINLVL(GET_ROOM_ZONE(going_to)) != -1) && ZONE_MINLVL(GET_ROOM_ZONE(going_to)) > GET_LEVEL(ch)) { + send_to_char(ch, "You are not ready to enter that area.\r\n"); + return (0); + } + if ((ZONE_MAXLVL(GET_ROOM_ZONE(going_to)) != -1) && ZONE_MAXLVL(GET_ROOM_ZONE(going_to)) < GET_LEVEL(ch)) { + send_to_char(ch, "You are too powerful for that area.\r\n"); + return (0); + } + + /* Check zone flag restrictions */ + if (ZONE_FLAGGED(GET_ROOM_ZONE(going_to), ZONE_CLOSED)) { + send_to_char(ch, "A mysterious barrier forces you back! That area is off-limits.\r\n"); + return (0); + } + if (ZONE_FLAGGED(GET_ROOM_ZONE(going_to), ZONE_NOIMMORT) && (GET_LEVEL(ch) >= LVL_IMMORT) && (GET_LEVEL(ch) < LVL_GRGOD)) { + send_to_char(ch, "A mysterious barrier forces you back! That area is off-limits.\r\n"); + return (0); + } + /* Room Size Capacity: Is the room full of people already? */ if (ROOM_FLAGGED(going_to, ROOM_TUNNEL) && - num_pc_in_room(&(world[going_to])) >= CONFIG_TUNNEL_SIZE) + num_pc_in_room(&(world[going_to])) >= CONFIG_TUNNEL_SIZE) { if (CONFIG_TUNNEL_SIZE > 1) send_to_char(ch, "There isn't enough room for you to go there!\r\n"); @@ -225,12 +245,12 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) } /* Room Level Requirements: Is ch privileged enough to enter the room? */ - if (ROOM_FLAGGED(going_to, ROOM_GODROOM) && GET_LEVEL(ch) < LVL_GOD) + if (ROOM_FLAGGED(going_to, ROOM_GODROOM) && GET_LEVEL(ch) < LVL_GOD) { send_to_char(ch, "You aren't godly enough to use that room!\r\n"); return (0); } - + /* All checks passed, nothing will prevent movement now other than lack of * move points. */ /* move points needed is avg. move loss for src and destination sect type */ @@ -238,7 +258,7 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) movement_loss[SECT(going_to)]) / 2; /* Move Point Requirement Check */ - if (GET_MOVE(ch) < need_movement && !IS_NPC(ch)) + if (GET_MOVE(ch) < need_movement && !IS_NPC(ch)) { if (need_specials_check && ch->master) send_to_char(ch, "You are too exhausted to follow.\r\n"); @@ -251,7 +271,7 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) /*---------------------------------------------------------------------*/ /* End checks that can prevent a character from leaving the was_in room. */ - + /* Begin: the leave operation. */ /*---------------------------------------------------------------------*/ /* If applicable, subtract movement cost. */ @@ -259,18 +279,18 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) GET_MOVE(ch) -= need_movement; /* Generate the leave message and display to others in the was_in room. */ - if (!AFF_FLAGGED(ch, AFF_SNEAK)) + if (!AFF_FLAGGED(ch, AFF_SNEAK)) { snprintf(leave_message, sizeof(leave_message), "$n leaves %s.", dirs[dir]); act(leave_message, TRUE, ch, 0, 0, TO_ROOM); } - + char_from_room(ch); char_to_room(ch, going_to); /*---------------------------------------------------------------------*/ /* End: the leave operation. The character is now in the new room. */ - + /* Begin: Post-move operations. */ /*---------------------------------------------------------------------*/ /* Post Move Trigger Checks: Check the new room for triggers. @@ -292,7 +312,7 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) look_at_room(ch, 0); /* ... and Kill the player if the room is a death trap. */ - if (ROOM_FLAGGED(going_to, ROOM_DEATH) && GET_LEVEL(ch) < LVL_IMMORT) + if (ROOM_FLAGGED(going_to, ROOM_DEATH) && GET_LEVEL(ch) < LVL_IMMORT) { mudlog(BRF, LVL_IMMORT, TRUE, "%s hit death trap #%d (%s)", GET_NAME(ch), GET_ROOM_VNUM(going_to), world[going_to].name); death_cry(ch); @@ -304,19 +324,19 @@ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) /* Fire memory and greet triggers, check and see if the greet trigger * prevents movement, and if so, move the player back to the previous room. */ entry_memory_mtrigger(ch); - if (!greet_mtrigger(ch, dir)) + if (!greet_mtrigger(ch, dir)) { char_from_room(ch); char_to_room(ch, was_in); look_at_room(ch, 0); /* Failed move, return a failure */ return (0); - } - else + } + else greet_memory_mtrigger(ch); /*---------------------------------------------------------------------*/ /* End: Post-move operations. */ - + /* Only here is the move successful *and* complete. Return success for * calling functions to handle post move operations. */ return (1); @@ -359,7 +379,7 @@ int perform_move(struct char_data *ch, int dir, int need_specials_check) ACMD(do_move) { - /* These subcmd defines are mapped precisely to the direction defines. */ + /* These subcmd defines are mapped precisely to the direction defines. */ perform_move(ch, subcmd, 0); } @@ -601,7 +621,7 @@ ACMD(do_gen_door) IS_SET(flags_door[subcmd], NEED_LOCKED)) send_to_char(ch, "Oh.. it wasn't locked, after all..\r\n"); else if (!(DOOR_IS_UNLOCKED(ch, obj, door)) && - IS_SET(flags_door[subcmd], NEED_UNLOCKED) && + IS_SET(flags_door[subcmd], NEED_UNLOCKED) && (GET_LEVEL(ch) < LVL_IMMORT || !PRF_FLAGGED(ch, PRF_NOHASSLE))) send_to_char(ch, "It seems to be locked.\r\n"); else if (!has_key(ch, keynum) && (GET_LEVEL(ch) < LVL_GOD) && @@ -709,21 +729,21 @@ ACMD(do_sit) int found; one_argument(argument, arg); - + if (!*arg) found = 0; if (!(furniture = get_obj_in_list_vis(ch, arg, NULL, world[ch->in_room].contents))) found = 0; else found = 1; - + switch (GET_POS(ch)) { case POS_STANDING: if (found == 0) { send_to_char(ch, "You sit down.\r\n"); act("$n sits down.", FALSE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; - } else { + } else { if (GET_OBJ_TYPE(furniture) != ITEM_FURNITURE) { send_to_char(ch, "You can't sit on that!\r\n"); return; @@ -735,7 +755,7 @@ ACMD(do_sit) } else if (GET_OBJ_VAL(furniture, 1) == GET_OBJ_VAL(furniture, 0)) { act("There is no where left to sit upon $p.", TRUE, ch, furniture, 0, TO_CHAR); return; - } else { + } else { if (OBJ_SAT_IN_BY(furniture) == NULL) OBJ_SAT_IN_BY(furniture) = ch; for (tempch = OBJ_SAT_IN_BY(furniture); tempch != ch ; tempch = NEXT_SITTING(tempch)) { diff --git a/src/act.wizard.c b/src/act.wizard.c index 2da2382..0b5eae7 100644 --- a/src/act.wizard.c +++ b/src/act.wizard.c @@ -236,6 +236,11 @@ ACMD(do_goto) if ((location = find_target_room(ch, argument)) == NOWHERE) return; + if (ZONE_FLAGGED(GET_ROOM_ZONE(location), ZONE_NOIMMORT) && (GET_LEVEL(ch) >= LVL_IMMORT) && (GET_LEVEL(ch) < LVL_GRGOD)) { + send_to_char(ch, "Sorry, that zone is off-limits for immortals!"); + return; + } + snprintf(buf, sizeof(buf), "$n %s", POOFOUT(ch) ? POOFOUT(ch) : "disappears in a puff of smoke."); act(buf, TRUE, ch, 0, 0, TO_ROOM); @@ -4533,3 +4538,206 @@ bool change_player_name(struct char_data *ch, struct char_data *vict, char *new_ return TRUE; } + +ACMD(do_zlock) +{ + zone_vnum znvnum; + zone_rnum zn; + char arg[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH]; + int counter = 0; + bool fail = FALSE; + + two_arguments(argument, arg, arg2); + + if (!*arg) { + send_to_char(ch, "Usage: %szlock %s\r\n", QYEL, QNRM); + send_to_char(ch, "%s zlock list%s\r\n\r\n", QYEL, QNRM); + send_to_char(ch, "Locks a zone so that building or editing is not possible.\r\n"); + send_to_char(ch, "The 'list' shows all currently locked zones.\r\n"); + send_to_char(ch, "'zlock all' will lock every zone with the GRID flag set.\r\n"); + send_to_char(ch, "'zlock all all' will lock every zone in the MUD.\r\n"); + return; + } + if (is_abbrev(arg, "all")) { + if (GET_LEVEL(ch) < LVL_GRGOD) { + send_to_char(ch, "You do not have sufficient access to lock all zones.\r\n"); + return; + } + if (!*arg2) { + for (zn = 0; zn <= top_of_zone_table; zn++) { + if (!ZONE_FLAGGED(zn, ZONE_NOBUILD) && ZONE_FLAGGED(zn, ZONE_GRID)) { + counter++; + SET_BIT_AR(ZONE_FLAGS(zn), ZONE_NOBUILD); + if (save_zone(zn)) { + log("(GC) %s has locked zone %d", GET_NAME(ch), zone_table[zn].number); + } else { + fail = TRUE; + } + } + } + } else if (is_abbrev(arg2, "all")) { + for (zn = 0; zn <= top_of_zone_table; zn++) { + if (!ZONE_FLAGGED(zn, ZONE_NOBUILD)) { + counter++; + SET_BIT_AR(ZONE_FLAGS(zn), ZONE_NOBUILD); + if (save_zone(zn)) { + log("(GC) %s has locked zone %d", GET_NAME(ch), zone_table[zn].number); + } else { + fail = TRUE; + } + } + } + } + if (counter == 0) { + send_to_char(ch, "There are no unlocked zones to lock!\r\n"); + return; + } + if (fail) { + send_to_char(ch, "Unable to save zone changes. Check syslog!\r\n"); + return; + } + send_to_char(ch, "%d zones have now been locked.\r\n", counter); + mudlog(BRF, LVL_GOD, TRUE, "(GC) %s has locked ALL zones!", GET_NAME(ch)); + return; + } + if (is_abbrev(arg, "list")) { + /* Show all locked zones */ + for (zn = 0; zn <= top_of_zone_table; zn++) { + if (ZONE_FLAGGED(zn, ZONE_NOBUILD)) { + if (!counter) send_to_char(ch, "Locked Zones\r\n"); + + send_to_char(ch, "[%s%3d%s] %s%-*s %s%-1s%s\r\n", + QGRN, zone_table[zn].number, QNRM, QCYN, count_color_chars(zone_table[zn].name)+30, zone_table[zn].name, + QYEL, zone_table[zn].builders ? zone_table[zn].builders : "None.", QNRM); + counter++; + } + } + if (counter == 0) { + send_to_char(ch, "There are currently no locked zones!\r\n"); + } + return; + } + else if ((znvnum = atoi(arg)) == 0) { + send_to_char(ch, "Usage: %szlock %s\r\n", QYEL, QNRM); + return; + } + + if ((zn = real_zone(znvnum)) == NOWHERE) { + send_to_char(ch, "That zone does not exist!\r\n"); + return; + } + + /* Check the builder list */ + if (GET_LEVEL(ch) < LVL_GRGOD && !is_name(GET_NAME(ch), zone_table[zn].builders) && GET_OLC_ZONE(ch) != znvnum) { + send_to_char(ch, "You do not have sufficient access to lock that zone!\r\n"); + return; + } + + /* If we get here, player has typed 'zlock ' */ + if (ZONE_FLAGGED(zn, ZONE_NOBUILD)) { + send_to_char(ch, "Zone %d is already locked!\r\n", znvnum); + return; + } + SET_BIT_AR(ZONE_FLAGS(zn), ZONE_NOBUILD); + if (save_zone(zn)) { + mudlog(NRM, LVL_GRGOD, TRUE, "(GC) %s has locked zone %d", GET_NAME(ch), znvnum); + } + else + { + send_to_char(ch, "Unable to save zone changes. Check syslog!\r\n"); + } +} + +ACMD(do_zunlock) +{ + zone_vnum znvnum; + zone_rnum zn; + char arg[MAX_INPUT_LENGTH]; + int counter = 0; + bool fail = FALSE; + + one_argument(argument, arg); + + if (!*arg) { + send_to_char(ch, "Usage: %szunlock %s\r\n", QYEL, QNRM); + send_to_char(ch, "%s zunlock list%s\r\n\r\n", QYEL, QNRM); + send_to_char(ch, "Unlocks a 'locked' zone to allow building or editing.\r\n"); + send_to_char(ch, "The 'list' shows all currently unlocked zones.\r\n"); + send_to_char(ch, "'zunlock all' will unlock every zone in the MUD.\r\n"); + return; + } + if (is_abbrev(arg, "all")) { + if (GET_LEVEL(ch) < LVL_GRGOD) { + send_to_char(ch, "You do not have sufficient access to lock zones.\r\n"); + return; + } + for (zn = 0; zn <= top_of_zone_table; zn++) { + if (ZONE_FLAGGED(zn, ZONE_NOBUILD)) { + counter++; + REMOVE_BIT_AR(ZONE_FLAGS(zn), ZONE_NOBUILD); + if (save_zone(zn)) { + log("(GC) %s has unlocked zone %d", GET_NAME(ch), zone_table[zn].number); + } else { + fail = TRUE; + } + } + } + if (counter == 0) { + send_to_char(ch, "There are no locked zones to unlock!\r\n"); + return; + } + if (fail) { + send_to_char(ch, "Unable to save zone changes. Check syslog!\r\n"); + return; + } + send_to_char(ch, "%d zones have now been unlocked.\r\n", counter); + mudlog(BRF, LVL_GOD, TRUE, "(GC) %s has unlocked ALL zones!", GET_NAME(ch)); + return; + } + if (is_abbrev(arg, "list")) { + /* Show all unlocked zones */ + for (zn = 0; zn <= top_of_zone_table; zn++) { + if (!ZONE_FLAGGED(zn, ZONE_NOBUILD)) { + if (!counter) send_to_char(ch, "Unlocked Zones\r\n"); + + send_to_char(ch, "[%s%3d%s] %s%-*s %s%-1s%s\r\n", + QGRN, zone_table[zn].number, QNRM, QCYN, count_color_chars(zone_table[zn].name)+30, zone_table[zn].name, + QYEL, zone_table[zn].builders ? zone_table[zn].builders : "None.", QNRM); + counter++; + } + } + if (counter == 0) { + send_to_char(ch, "There are currently no unlocked zones!\r\n"); + } + return; + } + else if ((znvnum = atoi(arg)) == 0) { + send_to_char(ch, "Usage: %szunlock %s\r\n", QYEL, QNRM); + return; + } + + if ((zn = real_zone(znvnum)) == NOWHERE) { + send_to_char(ch, "That zone does not exist!\r\n"); + return; + } + + /* Check the builder list */ + if (GET_LEVEL(ch) < LVL_GRGOD && !is_name(GET_NAME(ch), zone_table[zn].builders) && GET_OLC_ZONE(ch) != znvnum) { + send_to_char(ch, "You do not have sufficient access to unlock that zone!\r\n"); + return; + } + + /* If we get here, player has typed 'zunlock ' */ + if (!ZONE_FLAGGED(zn, ZONE_NOBUILD)) { + send_to_char(ch, "Zone %d is already unlocked!\r\n", znvnum); + return; + } + REMOVE_BIT_AR(ZONE_FLAGS(zn), ZONE_NOBUILD); + if (save_zone(zn)) { + mudlog(NRM, LVL_GRGOD, TRUE, "(GC) %s has unlocked zone %d", GET_NAME(ch), znvnum); + } + else + { + send_to_char(ch, "Unable to save zone changes. Check syslog!\r\n"); + } +} diff --git a/src/constants.c b/src/constants.c index a346db0..08b7367 100644 --- a/src/constants.c +++ b/src/constants.c @@ -67,6 +67,19 @@ const char *room_bits[] = { "\n" }; +/** Room flag descriptions. (ZONE_x) + * @pre Must be in the same order as the defines in structs.h. + * Must end array with a single newline. */ +const char *zone_bits[] = { + "CLOSED", + "NO_IMMORT", + "QUEST", + "GRID", + "NOBUILD", + "!ASTRAL", + "\n" +}; + /** Exit bits for doors. * @pre Must be in the same order as the defines. * Must end array with a single newline. */ diff --git a/src/constants.h b/src/constants.h index 56c4b55..3fd70fc 100644 --- a/src/constants.h +++ b/src/constants.h @@ -1,13 +1,13 @@ /** * @file constants.h * Declares the global constants defined in constants.c. -* +* * Part of the core tbaMUD source code distribution, which is a derivative * of, and continuation of, CircleMUD. -* -* All rights reserved. See license for complete information. -* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University -* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. +* +* All rights reserved. See license for complete information. +* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University +* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. */ #ifndef _CONSTANTS_H_ #define _CONSTANTS_H_ @@ -15,6 +15,7 @@ extern const char *tbamud_version; extern const char *dirs[]; extern const char *room_bits[]; +extern const char *zone_bits[]; extern const char *exit_bits[]; extern const char *sector_types[]; extern const char *genders[]; diff --git a/src/db.c b/src/db.c index 3af0824..4dd6ea3 100644 --- a/src/db.c +++ b/src/db.c @@ -1980,10 +1980,12 @@ char *parse_object(FILE *obj_f, int nr) static void load_zones(FILE *fl, char *zonename) { static zone_rnum zone = 0; - int cmd_no, num_of_cmds = 0, line_num = 0, tmp, error; + int i, cmd_no, num_of_cmds = 0, line_num = 0, tmp, error; char *ptr, buf[READ_SIZE], zname[READ_SIZE], buf2[MAX_STRING_LENGTH]; int zone_fix = FALSE; char t1[80], t2[80]; + char zbuf1[MAX_STRING_LENGTH], zbuf2[MAX_STRING_LENGTH]; + char zbuf3[MAX_STRING_LENGTH], zbuf4[MAX_STRING_LENGTH]; strlcpy(zname, zonename, sizeof(zname)); @@ -2024,22 +2026,42 @@ static void load_zones(FILE *fl, char *zonename) *ptr = '\0'; Z.name = strdup(buf); + /* Clear all the zone flags */ + for (i=0; i Z.top) { log("SYSERR: Zone %d bottom (%d) > top (%d).", Z.number, Z.bot, Z.top); diff --git a/src/db.h b/src/db.h index 41d3bb0..d4b4a24 100644 --- a/src/db.h +++ b/src/db.h @@ -1,13 +1,13 @@ /** * @file db.h * Header file for database handling. -* +* * Part of the core tbaMUD source code distribution, which is a derivative * of, and continuation of, CircleMUD. -* -* All rights reserved. See license for complete information. -* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University -* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. +* +* All rights reserved. See license for complete information. +* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University +* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. * */ #ifndef _DB_H_ @@ -159,9 +159,9 @@ struct reset_com { char *sarg1; /* string argument */ char *sarg2; /* string argument */ - /* Commands: - * 'M': Read a mobile - * 'O': Read an object + /* Commands: + * 'M': Read a mobile + * 'O': Read an object * 'G': Give obj to mob * 'P': Put obj in obj * 'G': Obj to char @@ -181,6 +181,10 @@ struct zone_data { room_vnum bot; /* starting room number for this zone */ room_vnum top; /* upper limit for rooms in this zone */ + int zone_flags[ZN_ARRAY_MAX]; /* Zone Flags bitvector */ + int min_level; /* Minimum level a player must be to enter this zone */ + int max_level; /* Maximum level a player must be to enter this zone */ + int reset_mode; /* conditions for reset (see below) */ zone_vnum number; /* virtual number of this zone */ struct reset_com *cmd; /* command table for reset */ @@ -336,11 +340,11 @@ extern int top_of_helpt; extern struct help_index_element *help_table; /* Mud configurable variables */ -extern int no_mail; -extern int mini_mud; -extern int no_rent_check; -extern time_t boot_time; -extern int circle_restrict; +extern int no_mail; +extern int mini_mud; +extern int no_rent_check; +extern time_t boot_time; +extern int circle_restrict; extern room_rnum r_mortal_start_room; extern room_rnum r_immort_start_room; extern room_rnum r_frozen_start_room; @@ -348,9 +352,9 @@ extern room_rnum r_frozen_start_room; extern struct config_data config_info; extern struct time_info_data time_info; -extern struct weather_data weather_info; +extern struct weather_data weather_info; extern struct player_special_data dummy_mob; -extern struct reset_q_type reset_q; +extern struct reset_q_type reset_q; extern struct room_data *world; extern room_rnum top_of_world; diff --git a/src/genzon.c b/src/genzon.c index b070642..6d361dc 100644 --- a/src/genzon.c +++ b/src/genzon.c @@ -28,7 +28,7 @@ zone_rnum real_zone_by_thing(room_vnum vznum) if (genolc_zone_bottom(bot) > vznum || zone_table[top].top < vznum) return (NOWHERE); - + /* perform binary search on zone-table */ while (bot <= top) { mid = (bot + top) / 2; @@ -54,7 +54,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top, int i, max_zone; zone_rnum rznum; char buf[MAX_STRING_LENGTH]; - + #if CIRCLE_UNSIGNED_INDEX max_zone = 655; if (vzone_num == NOWHERE) { @@ -64,13 +64,13 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top, #endif *error = "You can't make negative zones.\r\n"; return NOWHERE; - } else if (vzone_num > max_zone) { -#if CIRCLE_UNSIGNED_INDEX - *error = "New zone cannot be higher than 655.\r\n"; -#else - *error = "New zone cannot be higher than 327.\r\n"; -#endif - return NOWHERE; + } else if (vzone_num > max_zone) { +#if CIRCLE_UNSIGNED_INDEX + *error = "New zone cannot be higher than 655.\r\n"; +#else + *error = "New zone cannot be higher than 327.\r\n"; +#endif + return NOWHERE; } else if (bottom > top) { *error = "Bottom room cannot be greater than top room.\r\n"; return NOWHERE; @@ -141,7 +141,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top, } fprintf(fp, "$~\n"); fclose(fp); - + /* Create the trigger file. */ snprintf(buf, sizeof(buf), "%s/%d.trg", TRG_PREFIX, vzone_num); if (!(fp = fopen(buf, "w"))) { @@ -161,8 +161,8 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top, create_world_index(vzone_num, "shp"); create_world_index(vzone_num, "trg"); - /* Make a new zone in memory. This was the source of all the zedit new - * crashes. It was happily overwriting the stack. This new loop by Andrew + /* Make a new zone in memory. This was the source of all the zedit new + * crashes. It was happily overwriting the stack. This new loop by Andrew * Helm fixes that problem and is more understandable at the same time. * * The variable is 'top_of_zone_table_table + 2' because we need record 0 @@ -194,6 +194,11 @@ rznum = i; zone->lifespan = 30; zone->age = 0; zone->reset_mode = 2; + zone->min_level = -1; + zone->max_level = -1; + + for (i=0; izone_flags[i] = 0; + /* No zone commands, just terminate it with an 'S' */ CREATE(zone->cmd, struct reset_com, 1); zone->cmd[0].command = 'S'; @@ -286,7 +291,7 @@ void remove_room_zone_commands(zone_rnum zone, room_rnum room_num) { int subcmd = 0, cmd_room = -2; - /* Delete all entries in zone_table that relate to this room so we can add + /* Delete all entries in zone_table that relate to this room so we can add * all the ones we have in their place. */ while (zone_table[zone].cmd[subcmd].command != 'S') { switch (zone_table[zone].cmd[subcmd].command) { @@ -310,15 +315,17 @@ void remove_room_zone_commands(zone_rnum zone, room_rnum room_num) } } -/* Save all the zone_table for this zone to disk. This function now writes - * simple comments in the form of () to each record. A header for each +/* Save all the zone_table for this zone to disk. This function now writes + * simple comments in the form of () to each record. A header for each * field is also there. */ int save_zone(zone_rnum zone_num) { - int subcmd, arg1 = -1, arg2 = -1, arg3 = -1; + int subcmd, arg1 = -1, arg2 = -1, arg3 = -1, flag_tot=0, i; char fname[128], oldname[128]; const char *comment = NULL; FILE *zfile; + char zbuf1[MAX_STRING_LENGTH], zbuf2[MAX_STRING_LENGTH]; + char zbuf3[MAX_STRING_LENGTH], zbuf4[MAX_STRING_LENGTH]; #if CIRCLE_UNSIGNED_INDEX if (zone_num == NOWHERE || zone_num > top_of_zone_table) { @@ -335,21 +342,52 @@ int save_zone(zone_rnum zone_num) return FALSE; } - /* Print zone header to file. */ - fprintf(zfile, "#%d\n" - "%s~\n" - "%s~\n" - "%d %d %d %d\n", - zone_table[zone_num].number, - (zone_table[zone_num].builders && *zone_table[zone_num].builders) - ? zone_table[zone_num].builders : "None.", - (zone_table[zone_num].name && *zone_table[zone_num].name) - ? zone_table[zone_num].name : "undefined", + for (i=0; icmd, &new_com, pos); + new_com.command = 'N'; + add_cmd_to_list(&zone->cmd, &new_com, pos); return 1; } diff --git a/src/interpreter.c b/src/interpreter.c index 786eb72..6f36114 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -75,6 +75,7 @@ cpp_extern const struct command_info cmd_info[] = { { "aedit" , "aed" , POS_DEAD , do_oasis_aedit, LVL_GOD, 0 }, { "alias" , "ali" , POS_DEAD , do_alias , 0, 0 }, { "afk" , "afk" , POS_DEAD , do_gen_tog , 0, SCMD_AFK }, + { "areas" , "are" , POS_DEAD , do_areas , 0, 0 }, { "assist" , "as" , POS_FIGHTING, do_assist , 1, 0 }, { "ask" , "ask" , POS_RESTING , do_spec_comm, 0, SCMD_ASK }, { "astat" , "ast" , POS_DEAD , do_astat , 0, 0 }, @@ -330,6 +331,8 @@ cpp_extern const struct command_info cmd_info[] = { { "zreset" , "zreset" , POS_DEAD , do_zreset , LVL_BUILDER, 0 }, { "zedit" , "zedit" , POS_DEAD , do_oasis_zedit, LVL_BUILDER, 0 }, { "zlist" , "zlist" , POS_DEAD , do_oasis_list, LVL_BUILDER, SCMD_OASIS_ZLIST }, + { "zlock" , "zlock" , POS_DEAD , do_zlock , LVL_BUILDER, 0 }, + { "zunlock" , "zunlock" , POS_DEAD , do_zunlock , LVL_BUILDER, 0 }, { "zcheck" , "zcheck" , POS_DEAD , do_zcheck , LVL_GOD, 0 }, { "zpurge" , "zpurge" , POS_DEAD , do_zpurge , LVL_BUILDER, 0 }, diff --git a/src/oasis.c b/src/oasis.c index 77eb439..52d11e8 100644 --- a/src/oasis.c +++ b/src/oasis.c @@ -61,8 +61,8 @@ void clear_screen(struct descriptor_data *d) } /* Exported utilities */ -/* Set the color string pointers for that which this char will see at color - * level NRM. Changing the entries here will change the colour scheme +/* Set the color string pointers for that which this char will see at color + * level NRM. Changing the entries here will change the colour scheme * throughout the OLC. */ void get_char_colors(struct char_data *ch) { @@ -72,7 +72,7 @@ void get_char_colors(struct char_data *ch) yel = CCYEL(ch, C_NRM); } -/* This procedure frees up the strings and/or the structures attatched to a +/* This procedure frees up the strings and/or the structures attatched to a * descriptor, sets all flags back to how they should be. */ void cleanup_olc(struct descriptor_data *d, byte cleanup_type) { @@ -80,7 +80,7 @@ void cleanup_olc(struct descriptor_data *d, byte cleanup_type) if (d->olc == NULL) return; - /* Check for a room. free_room doesn't perform sanity checks, we must be + /* Check for a room. free_room doesn't perform sanity checks, we must be * careful here. */ if (OLC_ROOM(d)) { switch (cleanup_type) { @@ -101,31 +101,31 @@ void cleanup_olc(struct descriptor_data *d, byte cleanup_type) } } - /* Check for an existing object in the OLC. The strings aren't part of the + /* Check for an existing object in the OLC. The strings aren't part of the * prototype any longer. They get added with strdup(). */ if (OLC_OBJ(d)) { free_object_strings(OLC_OBJ(d)); free(OLC_OBJ(d)); } - /* Check for a mob. free_mobile() makes sure strings are not in the + /* Check for a mob. free_mobile() makes sure strings are not in the * prototype. */ if (OLC_MOB(d)) free_mobile(OLC_MOB(d)); /* Check for a zone. cleanup_type is irrelevant here, free() everything. */ if (OLC_ZONE(d)) { - if (OLC_ZONE(d)->builders) - free(OLC_ZONE(d)->builders); - if (OLC_ZONE(d)->name) + if (OLC_ZONE(d)->builders) + free(OLC_ZONE(d)->builders); + if (OLC_ZONE(d)->name) free(OLC_ZONE(d)->name); if (OLC_ZONE(d)->cmd) free(OLC_ZONE(d)->cmd); free(OLC_ZONE(d)); } - /* Check for a shop. free_shop doesn't perform sanity checks, we must be - * careful here. OLC_SHOP(d) is a _copy_ - no pointers to the original. Just + /* Check for a shop. free_shop doesn't perform sanity checks, we must be + * careful here. OLC_SHOP(d) is a _copy_ - no pointers to the original. Just * go ahead and free it all. */ if (OLC_SHOP(d)) free_shop(OLC_SHOP(d)); @@ -143,7 +143,7 @@ void cleanup_olc(struct descriptor_data *d, byte cleanup_type) break; } } - + /*. Check for aedit stuff -- M. Scott */ if (OLC_ACTION(d)) { switch(cleanup_type) { @@ -179,14 +179,14 @@ void cleanup_olc(struct descriptor_data *d, byte cleanup_type) free(OLC_STORAGE(d)); OLC_STORAGE(d) = NULL; } - /* Free this one regardless. If we've left olc, we've either made a fresh - * copy of it in the trig index, or we lost connection. Either way, we need + /* Free this one regardless. If we've left olc, we've either made a fresh + * copy of it in the trig index, or we lost connection. Either way, we need * to get rid of this. */ if (OLC_TRIG(d)) { free_trigger(OLC_TRIG(d)); OLC_TRIG(d) = NULL; } - /* OLC_SCRIPT is always set as trig_proto of OLC_OBJ/MOB/ROOM. Therefore it + /* OLC_SCRIPT is always set as trig_proto of OLC_OBJ/MOB/ROOM. Therefore it * should not be free'd here. */ /* Restore descriptor playing status. */ @@ -242,8 +242,8 @@ static void free_config(struct config_data *data) free(data); } -/* Checks to see if a builder can modify the specified zone. Ch is the imm - * requesting access to modify this zone. Rnum is the real number of the zone +/* Checks to see if a builder can modify the specified zone. Ch is the imm + * requesting access to modify this zone. Rnum is the real number of the zone * attempted to be modified. Returns TRUE if the builder has access, otherwisei * FALSE. */ int can_edit_zone(struct char_data *ch, zone_rnum rnum) @@ -252,13 +252,17 @@ int can_edit_zone(struct char_data *ch, zone_rnum rnum) if (!ch->desc || IS_NPC(ch) || rnum == NOWHERE) return FALSE; - if (GET_OLC_ZONE(ch) == ALL_PERMISSION) - return TRUE; + /* If zone is flagged NOBUILD, then No-one can edit it (use zunlock to open it) */ + if (rnum != HEDIT_PERMISSION && rnum != AEDIT_PERMISSION && ZONE_FLAGGED(rnum, ZONE_NOBUILD) ) + return FALSE; - if (GET_OLC_ZONE(ch) == HEDIT_PERMISSION && rnum == HEDIT_PERMISSION) - return TRUE; + if (GET_OLC_ZONE(ch) == ALL_PERMISSION) + return TRUE; - if (GET_OLC_ZONE(ch) == AEDIT_PERMISSION && rnum == AEDIT_PERMISSION) + if (GET_OLC_ZONE(ch) == HEDIT_PERMISSION && rnum == HEDIT_PERMISSION) + return TRUE; + + if (GET_OLC_ZONE(ch) == AEDIT_PERMISSION && rnum == AEDIT_PERMISSION) return TRUE; /* always access if ch is high enough level */ @@ -289,7 +293,7 @@ int can_edit_zone(struct char_data *ch, zone_rnum rnum) void send_cannot_edit(struct char_data *ch, zone_vnum zone) { char buf[MAX_STRING_LENGTH]; - + if (GET_OLC_ZONE(ch) != NOWHERE) { send_to_char(ch, "You do not have permission to edit zone %d. Try zone %d.\r\n", zone, GET_OLC_ZONE(ch)); sprintf(buf, "OLC: %s tried to edit zone %d (allowed zone %d).", GET_NAME(ch), zone, GET_OLC_ZONE(ch)); diff --git a/src/oasis.h b/src/oasis.h index 655ad64..42c4a14 100644 --- a/src/oasis.h +++ b/src/oasis.h @@ -226,8 +226,13 @@ extern const char *nrm, *grn, *cyn, *yel; #define ZEDIT_ZONE_RESET 13 #define ZEDIT_CONFIRM_SAVESTRING 14 #define ZEDIT_ZONE_BUILDERS 15 -#define ZEDIT_SARG1 20 -#define ZEDIT_SARG2 21 +#define ZEDIT_SARG1 20 +#define ZEDIT_SARG2 21 +#define ZEDIT_ZONE_FLAGS 22 +#define ZEDIT_LEVELS 23 +#define ZEDIT_LEV_MIN 24 +#define ZEDIT_LEV_MAX 25 +#define ZEDIT_ZONE_CLAIM 26 /* Submodes of MEDIT connectedness. */ #define MEDIT_MAIN_MENU 0 diff --git a/src/spells.c b/src/spells.c index 39231dc..87e6c82 100644 --- a/src/spells.c +++ b/src/spells.c @@ -59,6 +59,11 @@ ASPELL(spell_recall) if (victim == NULL || IS_NPC(victim)) return; + if (ZONE_FLAGGED(GET_ROOM_ZONE(IN_ROOM(victim)), ZONE_NOASTRAL)) { + send_to_char(ch, "A bright flash prevents your spell from working!"); + return; + } + act("$n disappears.", TRUE, victim, 0, 0, TO_ROOM); char_from_room(victim); char_to_room(victim, r_mortal_start_room); @@ -76,9 +81,16 @@ ASPELL(spell_teleport) if (victim == NULL || IS_NPC(victim)) return; + if (ZONE_FLAGGED(GET_ROOM_ZONE(IN_ROOM(victim)), ZONE_NOASTRAL)) { + send_to_char(ch, "A bright flash prevents your spell from working!"); + return; + } + do { to_room = rand_number(0, top_of_world); - } while (ROOM_FLAGGED(to_room, ROOM_PRIVATE) || ROOM_FLAGGED(to_room, ROOM_DEATH) || ROOM_FLAGGED(to_room, ROOM_GODROOM)); + } while (ROOM_FLAGGED(to_room, ROOM_PRIVATE) || ROOM_FLAGGED(to_room, ROOM_DEATH) || + ROOM_FLAGGED(to_room, ROOM_GODROOM) || ZONE_FLAGGED(GET_ROOM_ZONE(to_room), ZONE_CLOSED) || + ZONE_FLAGGED(GET_ROOM_ZONE(to_room), ZONE_NOASTRAL)); act("$n slowly fades out of existence and is gone.", FALSE, victim, 0, 0, TO_ROOM); @@ -102,6 +114,12 @@ ASPELL(spell_summon) return; } + if (ZONE_FLAGGED(GET_ROOM_ZONE(IN_ROOM(victim)), ZONE_NOASTRAL) || + ZONE_FLAGGED(GET_ROOM_ZONE(IN_ROOM(ch)), ZONE_NOASTRAL)) { + send_to_char(ch, "A bright flash prevents your spell from working!"); + return; + } + if (!CONFIG_PK_ALLOWED) { if (MOB_FLAGGED(victim, MOB_AGGRESSIVE)) { act("As the words escape your lips and $N travels\r\n" @@ -169,8 +187,8 @@ int isname_obj(char *search, char *list) return 0; } - /* Found the name in the list, now see if it's a valid hit. The following - * avoids substrings (like ring in shimmering) is it at beginning of + /* Found the name in the list, now see if it's a valid hit. The following + * avoids substrings (like ring in shimmering) is it at beginning of * namelist? */ for (i = 0; searchname[i]; i++) if (searchname[i] != namelist[i]) @@ -202,7 +220,7 @@ ASPELL(spell_locate_object) } /* added a global var to catch 2nd arg. */ - sprintf(name, "%s", cast_arg2); + sprintf(name, "%s", cast_arg2); j = GET_LEVEL(ch) / 2; /* # items to show = twice char's level */ @@ -210,7 +228,7 @@ ASPELL(spell_locate_object) if (!isname_obj(name, i->name)) continue; - send_to_char(ch, "%c%s", UPPER(*i->short_description), i->short_description + 1); + send_to_char(ch, "%c%s", UPPER(*i->short_description), i->short_description + 1); if (i->carried_by) send_to_char(ch, " is being carried by %s.\r\n", PERS(i->carried_by, ch)); @@ -364,7 +382,7 @@ ASPELL(spell_identify) } } -/* Cannot use this spell on an equipped object or it will mess up the wielding +/* Cannot use this spell on an equipped object or it will mess up the wielding * character's hit/dam totals. */ ASPELL(spell_enchant_weapon) { diff --git a/src/structs.h b/src/structs.h index eb872e3..425801c 100644 --- a/src/structs.h +++ b/src/structs.h @@ -91,6 +91,16 @@ /** The total number of Room Flags */ #define NUM_ROOM_FLAGS 17 +/* Zone info: Used in zone_data.zone_flags */ +#define ZONE_CLOSED 0 /**< Zone is closed - players cannot enter */ +#define ZONE_NOIMMORT 1 /**< Immortals (below LVL_GRGOD) cannot enter this zone */ +#define ZONE_QUEST 2 /**< This zone is a quest zone (not implemented) */ +#define ZONE_GRID 3 /**< Zone is 'on the grid', connected, show on 'areas' */ +#define ZONE_NOBUILD 4 /**< Building is not allowed in the zone */ +#define ZONE_NOASTRAL 5 /**< No teleportation magic will work to or from this zone */ +/** The total number of Zone Flags */ +#define NUM_ZONE_FLAGS 6 + /* Exit info: used in room_data.dir_option.exit_info */ #define EX_ISDOOR (1 << 0) /**< Exit is a door */ #define EX_CLOSED (1 << 1) /**< The door is closed */ @@ -489,6 +499,7 @@ #define AF_ARRAY_MAX 4 /**< # Bytes in Bit vector - Affect flags */ #define TW_ARRAY_MAX 4 /**< # Bytes in Bit vector - Obj Wear Locations */ #define EF_ARRAY_MAX 4 /**< # Bytes in Bit vector - Obj Extra Flags */ +#define ZN_ARRAY_MAX 4 /**< # Bytes in Bit vector - Zone Flags */ /* other #defined constants */ /* **DO**NOT** blindly change the number of levels in your MUD merely by diff --git a/src/utils.h b/src/utils.h index 84ef3ce..031e854 100644 --- a/src/utils.h +++ b/src/utils.h @@ -295,6 +295,15 @@ void char_from_furniture(struct char_data *ch); /** Room flags. * @param loc The real room number. */ #define ROOM_FLAGS(loc) (world[(loc)].room_flags) +/** Zone flags. + * @param rnum The real zone number. */ +#define ZONE_FLAGS(rnum) (zone_table[(rnum)].zone_flags) +/** Zone minimum level restriction. + * @param rnum The real zone number. */ +#define ZONE_MINLVL(rnum) (zone_table[(rnum)].min_level) +/** Zone maximum level restriction. + * @param rnum The real zone number. */ +#define ZONE_MAXLVL(rnum) (zone_table[(rnum)].max_level) /** References the routine element for a spell. Currently unused. */ #define SPELL_ROUTINES(spl) (spell_info[spl].routines) @@ -319,6 +328,8 @@ void char_from_furniture(struct char_data *ch); #define PRF_FLAGGED(ch, flag) (IS_SET_AR(PRF_FLAGS(ch), (flag))) /** 1 if flag is set in the room of loc, 0 if not. */ #define ROOM_FLAGGED(loc, flag) (IS_SET_AR(ROOM_FLAGS(loc), (flag))) +/** 1 if flag is set in the zone of rnum, 0 if not. */ +#define ZONE_FLAGGED(rnum, flag) (IS_SET_AR(zone_table[(rnum)].zone_flags, (flag))) /** 1 if flag is set in the exit, 0 if not. */ #define EXIT_FLAGGED(exit, flag) (IS_SET((exit)->exit_info, (flag))) /** 1 if flag is set in the affects bitarray of obj, 0 if not. */ @@ -351,6 +362,9 @@ void char_from_furniture(struct char_data *ch); #define SECT(room) (VALID_ROOM_RNUM(room) ? \ world[(room)].sector_type : SECT_INSIDE) +/** Return the zone number for this room */ +#define GET_ROOM_ZONE(room) (VALID_ROOM_RNUM(room) ? world[(room)].zone : NOWHERE) + /** TRUE if the room has no light, FALSE if not. */ #define IS_DARK(room) room_is_dark((room)) /** TRUE if the room has light, FALSE if not. */ diff --git a/src/zedit.c b/src/zedit.c index 919bb45..dbc0236 100644 --- a/src/zedit.c +++ b/src/zedit.c @@ -81,7 +81,7 @@ ACMD(do_oasis_zedit) if (atoi(stop) < 0 || atoi(sbot) < 0) { send_to_char(ch, "Zones cannot contain negative vnums.\r\n"); return; - } + } room_vnum bottom, top; number = atoidx(buf2); @@ -191,7 +191,7 @@ ACMD(do_oasis_zedit) static void zedit_setup(struct descriptor_data *d, int room_num) { struct zone_data *zone; - int subcmd = 0, count = 0, cmd_room = NOWHERE; + int subcmd = 0, count = 0, cmd_room = NOWHERE, i; /* Allocate one scratch zone structure. */ CREATE(zone, struct zone_data, 1); @@ -208,6 +208,12 @@ static void zedit_setup(struct descriptor_data *d, int room_num) zone->number = 0; /* Header information has changed. */ zone->age = 0; /* The commands have changed. */ + for (i=0; izone_flags[(i)] = zone_table[OLC_ZNUM(d)].zone_flags[(i)]; + + zone->min_level = zone_table[OLC_ZNUM(d)].min_level; + zone->max_level = zone_table[OLC_ZNUM(d)].max_level; + /* Start the reset command list with a terminator. */ CREATE(zone->cmd, struct reset_com, 1); zone->cmd[0].command = 'S'; @@ -284,7 +290,7 @@ static void zedit_save_internally(struct descriptor_data *d) { int mobloaded = FALSE, objloaded = FALSE, - subcmd; + subcmd, i; room_rnum room_num = real_room(OLC_NUM(d)); if (room_num == NOWHERE) { @@ -341,6 +347,10 @@ static void zedit_save_internally(struct descriptor_data *d) zone_table[OLC_ZNUM(d)].top = OLC_ZONE(d)->top; zone_table[OLC_ZNUM(d)].reset_mode = OLC_ZONE(d)->reset_mode; zone_table[OLC_ZNUM(d)].lifespan = OLC_ZONE(d)->lifespan; + zone_table[OLC_ZNUM(d)].min_level = OLC_ZONE(d)->min_level; + zone_table[OLC_ZNUM(d)].max_level = OLC_ZONE(d)->max_level; + for (i=0; izone_flags[(i)]; } add_to_save_list(zone_table[OLC_ZNUM(d)].number, SL_ZON); } @@ -361,16 +371,63 @@ static int start_change_command(struct descriptor_data *d, int pos) return 1; } +/*------------------------------------------------------------------*/ +void zedit_disp_flag_menu(struct descriptor_data *d) +{ + int counter, columns = 0; + char bits[MAX_STRING_LENGTH]; + + clear_screen(d); + for (counter = 0; counter < NUM_ZONE_FLAGS; counter++) { + write_to_output(d, "@g%2d@n) %-20.20s %s", counter + 1, + zone_bits[counter], !(++columns % 2) ? "\r\n" : ""); + } + + sprintbitarray(OLC_ZONE(d)->zone_flags, zone_bits, ZN_ARRAY_MAX, bits); + write_to_output(d, "\r\nZone flags: @c%s@n\r\n" + "Enter Zone flags, 0 to quit : ", bits); + OLC_MODE(d) = ZEDIT_ZONE_FLAGS; +} + +/*------------------------------------------------------------------*/ +bool zedit_get_levels(struct descriptor_data *d, char *buf) +{ + /* Create a string for the recommended levels for this zone. */ + if ((OLC_ZONE(d)->min_level == -1) && (OLC_ZONE(d)->max_level == -1)) { + sprintf(buf, ""); + return FALSE; + } + + if (OLC_ZONE(d)->min_level == -1) { + sprintf(buf, "Up to level %d", OLC_ZONE(d)->max_level); + return TRUE; + } + + if (OLC_ZONE(d)->max_level == -1) { + sprintf(buf, "Above level %d", OLC_ZONE(d)->min_level); + return TRUE; + } + + sprintf(buf, "Levels %d to %d", OLC_ZONE(d)->min_level, OLC_ZONE(d)->max_level); + return TRUE; +} + +/*------------------------------------------------------------------*/ /* Menu functions */ /* the main menu */ static void zedit_disp_menu(struct descriptor_data *d) { int subcmd = 0, room, counter = 0; + char buf1[MAX_STRING_LENGTH], lev_string[50]; + bool levels_set = FALSE; get_char_colors(d->character); clear_screen(d); room = real_room(OLC_NUM(d)); + sprintbitarray(OLC_ZONE(d)->zone_flags, zone_bits, ZN_ARRAY_MAX, buf1); + levels_set = zedit_get_levels(d, lev_string); + /* Menu header */ send_to_char(d->character, "Room number: %s%d%s Room zone: %s%d\r\n" @@ -379,7 +436,9 @@ static void zedit_disp_menu(struct descriptor_data *d) "%sL%s) Lifespan : %s%d minutes\r\n" "%sB%s) Bottom of zone : %s%d\r\n" "%sT%s) Top of zone : %s%d\r\n" - "%sR%s) Reset Mode : %s%s%s\r\n" + "%sR%s) Reset Mode : %s%s\r\n" + "%sF%s) Zone Flags : %s%s\r\n" + "%sM%s) Level Range : %s%s%s\r\n" "[Command list]\r\n", cyn, OLC_NUM(d), nrm, @@ -389,10 +448,11 @@ static void zedit_disp_menu(struct descriptor_data *d) grn, nrm, yel, OLC_ZONE(d)->lifespan, grn, nrm, yel, OLC_ZONE(d)->bot, grn, nrm, yel, OLC_ZONE(d)->top, - grn, nrm, - yel, - OLC_ZONE(d)->reset_mode ? ((OLC_ZONE(d)->reset_mode == 1) ? "Reset when no players are in zone." : "Normal reset.") : "Never reset", - nrm + grn, nrm, yel, + OLC_ZONE(d)->reset_mode ? ((OLC_ZONE(d)->reset_mode == 1) ? "Reset when no players are in zone." : "Normal reset.") : "Never reset", + grn, nrm, cyn, buf1, + grn, nrm, levels_set ? cyn : yel, lev_string, + nrm ); /* Print the commands for this room into display buffer. */ @@ -604,13 +664,13 @@ static void zedit_disp_arg3(struct descriptor_data *d) switch (OLC_CMD(d).command) { case 'E': while (*equipment_types[i] != '\n') { - write_to_output(d, "%2d) %26.26s", i, equipment_types[i]); - - if (*equipment_types[i + 1] != '\n') - write_to_output(d, " %2d) %26.26s", i + 1, - equipment_types[i + 1]); - - write_to_output(d, "\r\n"); + write_to_output(d, "%2d) %26.26s", i, equipment_types[i]); + + if (*equipment_types[i + 1] != '\n') + write_to_output(d, " %2d) %26.26s", i + 1, + equipment_types[i + 1]); + + write_to_output(d, "\r\n"); if (*equipment_types[i + 1] != '\n') i += 2; else @@ -643,10 +703,35 @@ static void zedit_disp_arg3(struct descriptor_data *d) OLC_MODE(d) = ZEDIT_ARG3; } +/*-------------------------------------------------------------------*/ +/* + * Print the recommended levels menu and setup response catch. + */ +void zedit_disp_levels(struct descriptor_data *d) +{ + char lev_string[50]; + bool levels_set = FALSE; + + levels_set = zedit_get_levels(d, lev_string); + + clear_screen(d); + write_to_output(d, + "\r\n" + "@y1@n) Set minimum level\r\n" + "@y2@n) Set maximum level\r\n" + "@y3@n) Clear level restrictions\r\n\r\n" + "@y0@n) Quit to main menu\r\n" + "@gCurrent Setting: %s%s\r\n" + "\r\n" + "Enter choice (0 to quit): ", levels_set ? "@c" : "@y", lev_string + ); + OLC_MODE(d) = ZEDIT_LEVELS; +} + /* The event handler */ void zedit_parse(struct descriptor_data *d, char *arg) { - int pos, i = 0; + int pos, i = 0, number; switch (OLC_MODE(d)) { case ZEDIT_CONFIRM_SAVESTRING: @@ -760,6 +845,15 @@ void zedit_parse(struct descriptor_data *d, char *arg) "Enter new zone reset type : "); OLC_MODE(d) = ZEDIT_ZONE_RESET; break; + case 'f': + case 'F': + zedit_disp_flag_menu(d); + break; + case 'm': + case 'M': + /*** Edit zone level restrictions (sub-menu) ***/ + zedit_disp_levels(d); + break; default: zedit_disp_menu(d); break; @@ -767,6 +861,49 @@ void zedit_parse(struct descriptor_data *d, char *arg) break; /* End of ZEDIT_MAIN_MENU */ +/*-------------------------------------------------------------------*/ + case ZEDIT_LEVELS: + switch (*arg) { + case '1': write_to_output(d, "Enter the min level for this zone (0-%d, -1 = none): ", (LVL_IMMORT-1)); + OLC_MODE(d) = ZEDIT_LEV_MIN; + break; + + case '2': write_to_output(d, "Enter the max level for this zone (0-%d, -1 = none): ", (LVL_IMMORT-1)); + OLC_MODE(d) = ZEDIT_LEV_MAX; + break; + + case '3': OLC_ZONE(d)->min_level = -1; + OLC_ZONE(d)->max_level = -1; + OLC_ZONE(d)->age = 1; + zedit_disp_levels(d); + break; + + case '0': + zedit_disp_menu(d); + break; + + default: write_to_output(d, "Invalid choice!\r\n"); + break; + } + break; + +/*-------------------------------------------------------------------*/ + case ZEDIT_LEV_MIN: + pos = atoi(arg); + OLC_ZONE(d)->min_level = MIN(MAX(pos,-1), 100); + OLC_ZONE(d)->age = 1; + zedit_disp_levels(d); + break; + +/*-------------------------------------------------------------------*/ + case ZEDIT_LEV_MAX: + pos = atoi(arg); + OLC_ZONE(d)->max_level = MIN(MAX(pos,-1), 100); + OLC_ZONE(d)->age = 1; + zedit_disp_levels(d); + break; + +/*-------------------------------------------------------------------*/ case ZEDIT_NEW_ENTRY: /* Get the line number and insert the new line. */ pos = atoi(arg); @@ -779,6 +916,7 @@ void zedit_parse(struct descriptor_data *d, char *arg) zedit_disp_menu(d); break; +/*-------------------------------------------------------------------*/ case ZEDIT_DELETE_ENTRY: /* Get the line number and delete the line. */ pos = atoi(arg); @@ -789,8 +927,9 @@ void zedit_parse(struct descriptor_data *d, char *arg) zedit_disp_menu(d); break; +/*-------------------------------------------------------------------*/ case ZEDIT_CHANGE_ENTRY: - /* Parse the input for which line to edit, and goto next quiz. Abort edit, + /* Parse the input for which line to edit, and goto next quiz. Abort edit, and return to main menu idea from Mark Garringer zizazat@hotmail.com */ if (toupper(*arg) == 'A') { if (OLC_CMD(d).command == 'N') { @@ -808,6 +947,7 @@ void zedit_parse(struct descriptor_data *d, char *arg) zedit_disp_menu(d); break; +/*-------------------------------------------------------------------*/ case ZEDIT_COMMAND_TYPE: /* Parse the input for which type of command this is, and goto next quiz. */ OLC_CMD(d).command = toupper(*arg); @@ -829,6 +969,7 @@ void zedit_parse(struct descriptor_data *d, char *arg) } break; +/*-------------------------------------------------------------------*/ case ZEDIT_IF_FLAG: /* Parse the input for the if flag, and goto next quiz. */ switch (*arg) { @@ -847,6 +988,7 @@ void zedit_parse(struct descriptor_data *d, char *arg) zedit_disp_arg1(d); break; +/*-------------------------------------------------------------------*/ case ZEDIT_ARG1: /* Parse the input for arg1, and goto next quiz. */ if (!isdigit(*arg)) { @@ -891,6 +1033,7 @@ void zedit_parse(struct descriptor_data *d, char *arg) } break; +/*-------------------------------------------------------------------*/ case ZEDIT_ARG2: /* Parse the input for arg2, and goto next quiz. */ if (!isdigit(*arg)) { @@ -953,6 +1096,7 @@ void zedit_parse(struct descriptor_data *d, char *arg) } break; +/*-------------------------------------------------------------------*/ case ZEDIT_ARG3: /* Parse the input for arg3, and go back to main menu. */ if (!isdigit(*arg)) { @@ -1004,6 +1148,7 @@ void zedit_parse(struct descriptor_data *d, char *arg) } break; +/*-------------------------------------------------------------------*/ case ZEDIT_SARG1: if (strlen(arg)) { OLC_CMD(d).sarg1 = strdup(arg); @@ -1013,6 +1158,7 @@ void zedit_parse(struct descriptor_data *d, char *arg) write_to_output(d, "Must have some name to assign : "); break; +/*-------------------------------------------------------------------*/ case ZEDIT_SARG2: if (strlen(arg)) { OLC_CMD(d).sarg2 = strdup(arg); @@ -1021,6 +1167,7 @@ void zedit_parse(struct descriptor_data *d, char *arg) write_to_output(d, "Must have some value to set it to :"); break; +/*-------------------------------------------------------------------*/ case ZEDIT_ZONE_NAME: /* Add new name and return to main menu. */ if (genolc_checkstring(d, arg)) { @@ -1034,6 +1181,7 @@ void zedit_parse(struct descriptor_data *d, char *arg) zedit_disp_menu(d); break; +/*-------------------------------------------------------------------*/ case ZEDIT_ZONE_BUILDERS: /* Add new builders list and return to main menu. */ if (genolc_checkstring(d, arg)) { @@ -1047,6 +1195,7 @@ void zedit_parse(struct descriptor_data *d, char *arg) zedit_disp_menu(d); break; +/*-------------------------------------------------------------------*/ case ZEDIT_ZONE_RESET: /* Parse and add new reset_mode and return to main menu. */ pos = atoi(arg); @@ -1059,6 +1208,7 @@ void zedit_parse(struct descriptor_data *d, char *arg) } break; +/*-------------------------------------------------------------------*/ case ZEDIT_ZONE_LIFE: /* Parse and add new lifespan and return to main menu. */ pos = atoi(arg); @@ -1071,6 +1221,27 @@ void zedit_parse(struct descriptor_data *d, char *arg) } break; +/*-------------------------------------------------------------------*/ + case ZEDIT_ZONE_FLAGS: + number = atoi(arg); + if (number < 0 || number > NUM_ZONE_FLAGS) { + write_to_output(d, "That is not a valid choice!\r\n"); + zedit_disp_flag_menu(d); + } else if (number == 0) { + zedit_disp_menu(d); + break; + } + else { + /* + * Toggle the bit. + */ + TOGGLE_BIT_AR(OLC_ZONE(d)->zone_flags, number - 1); + OLC_ZONE(d)->number = 1; + zedit_disp_flag_menu(d); + } + return; + +/*-------------------------------------------------------------------*/ case ZEDIT_ZONE_BOT: /* Parse and add new bottom room in zone and return to main menu. */ if (OLC_ZNUM(d) == 0) @@ -1081,6 +1252,7 @@ void zedit_parse(struct descriptor_data *d, char *arg) zedit_disp_menu(d); break; +/*-------------------------------------------------------------------*/ case ZEDIT_ZONE_TOP: /* Parse and add new top room in zone and return to main menu. */ if (OLC_ZNUM(d) == top_of_zone_table)