@prop $pinfo_field.brief_name "" r @prop $pinfo_field.property "" r @prop $pinfo_field.types {} r @prop $pinfo_field.player_can_modify 1 r @prop $pinfo.ooc_fields {} r @prop $pinfo.ic_fields {} r @prop $pinfo.fields_help_list {"This is a list of fields you can set. To set a single-line field, use @pinfo- is . To set a multi-line field, use @pinfo- to start an editor. In all cases, is displayed in brackets."} r @prop $pinfo.fields_help_singleline ", Single-Line" r @prop $pinfo.fields_help_multiline ", Multi-Line" r @chmod $pinfo_editor +r @prop $pinfo_editor.state_fields {} r @stateprop state_fields for $pinfo_editor @prop $pinfo_field.help_msg {"Props you need to set:", ".brief_name - the 'brief name' players and programmers can use to refer to this field by.", ".property - the propety on the player to read the data from. Not needed if you're overriding get_data.", ".types - Valid data types for this field.", ".player_can_modify - Is this a field that players can change through @pinfo, or is it read only?", "$pinfo.ic_fields or .ooc_fields - add it to one of these. Fields are displayed in the order they appear in the lists.","","For program license details, see $pinfo_field.license. If $pinfo_field.license is not +r, this MOO is in violation of the license."} r @prop $pinfo_field.license {"dynpinfo - dynamic flexible pinfo system for MOOs.","Copyright (C) 2005 Nicholas Pilon","This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.","","This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.","","For the terms of the GNU General Public License, see .","","Complying with the GPL for a MOO is simple - you MUST keep $pinfo, $pinfo_field, all children of $pinfo_field, and all verbs on all of the above objects +r at all times. Verbs on other objects that these verbs call do not HAVE to be +r but should be if they are central to the functionality of the verbs."} @verb $pinfo_field:is_valid this none this rdx @program $pinfo_field:is_valid "is_valid(player, value) => 1 if this value is valid for this field for player, error otherwise."; "[bold]INTERNAL VERB ONLY.[normal]"; "Default is simply valid if type is valid."; {target, value} = args; if (typeof(value) in this.types) return 1; else return E_TYPE; endif . @verb $pinfo_field:can_view this none this rdx @program $pinfo_field:can_view "can_view(player, target) => 1 if player can view this field on target, 0 otherwise."; "[bold]INTERNAL VERB ONLY.[normal]"; "Base version always returns true."; return 1; . @verb $pinfo_field:get_data this none this rdx @program $pinfo_field:get_data "get_data(player) => Data for this field for player."; "Simply reads, does not do any error checking."; "[bold]INTERNAL VERB ONLY.[normal]"; {target} = args; if (caller != this) raise(E_PERM); endif return target.(this.property); . @verb $pinfo_field:get_field this none this rdx @program $pinfo_field:get_field "get_field(player) => Value of this field on player or E_PERM if caller cannot read that field."; "[bold]INTERNAL VERB ONLY.[normal]"; "To get fields, please use player:get_pinfo(field)!"; {target} = args; if (this:can_view(caller_perms(), target)) set_task_perms(caller_perms()); data = this:get_data(target); retval = this:is_valid(target, data); if (retval) return data; else return retval; endif else return E_PERM; endif . @verb $ic_pinfo_field:get_field this none this rdx @program $ic_pinfo_field:get_field "get_field(player) => Value of this field on player or E_PERM if caller cannot read that field. Returns \"Unset\" for unset fields."; "[bold]INTERNAL VERB ONLY.[normal]"; "To get fields, please use player:get_pinfo(field)!"; set_task_perms(caller_perms()); retval = pass(@args); if (typeof(retval) != ERR) if (retval == "") return "Unset."; elseif (retval == {} || retval == {""}) return {"Unset"}; endif endif return retval; . @verb $pinfo_field:set_field this none this rdx @program $pinfo_field:set_field "set_field(player, value) => 1 on success, E_PERM if permission denied, E_TYPE if type of value is wrong, E_INVARG if the value is invalid."; "[bold]INTERNAL VERB ONLY.[normal]"; "To set fields, please use player:set_pinfo(field, value)"; {target, value} = args; if (!this:can_modify(caller_perms(), target)) return E_PERM; endif retval = this:is_valid(target, value); if (retval) target.(this.property) = value; return 1; else return retval; endif . @verb $pinfo_field:can_modify this none this rdx @program $pinfo_field:can_modify "can_modify(modifier, target) => 1 if player can modify this field on target, 0 otherwise."; "Default simply returns .player_can_set for anyone who controls the player and 0 for everyone else."; {modifier, target} = args; if ($npc_db:isa_npc(target) && target:authorized_to_mod(modifier, modifier)) return this.player_can_modify; elseif (modifier == target || $perm_utils:controls(modifier, target)) return this.player_can_modify; else return 0; endif . @verb $pinfo_field:can_edit this none this rdx @program $pinfo_field:can_edit "can_edit(target) => 1 if this field is editable on player, 0 otherwise."; "Default simply returns true if LIST is a valid type for this field."; return LIST in this.types; . @verb $pinfo:match_field this none this rdx @program $pinfo:match_field "match_field(field) => Obj#"; "[bold]INTERNAL VERB ONLY.[normal]"; "Used by player:set_pinfo and player:get_pinfo. IC fields are matched BEFORE OOC fields!"; {field_name} = args; return $string_utils:match(field_name, this.ic_fields, "brief_name", this.ooc_fields, "brief_name"); . @verb $pinfo:ic_fields this none this rdx @program $pinfo:ic_fields "ic_fields() => A list of the IC fields."; return this.ic_fields; . @verb $pinfo:ooc_fields this none this rdx @program $pinfo:ooc_fields "ooc_fields() => A list of the OOC fields."; return this.ooc_fields; . @verb #6:set_pinfo this none this rdxo @program #6:set_pinfo "set_pinfo(field, value) => 1, E_PERM, E_INVARG, E_TYPE"; "Attempts to set the specified object's pinfo field to the given value. Returns 1 if the operation is successful, E_PERM if the caller cannot set pinfo fields on this object, and E_TYPE if the pinfo value isn't the right type, and E_INVARG if the field isn't valid."; set_task_perms(caller_perms()); {field_name, value} = args; if (typeof(field_name) == STR) field = $pinfo:match_field(field_name); elseif (typeof(field_name) == OBJ) field = field_name; endif if (valid(field)) return field:set_field(this, value); else return E_INVARG; endif . @verb #6:get_pinfo this none this rdx @program #6:get_pinfo "get_pinfo(field) => value, E_TYPE, E_PERM, E_INVARG"; "Attempts to retrieve the specified object's pinfo field. Returns the contents of the field if the operation is successful, E_PERM if the caller cannot read that field on that object, E_TYPE if the field's data is somehow the wrong type, and E_INVARG if the field doesn't exist. Field can either be a brief name (full or partial) or a field object."; set_task_perms(caller_perms()); {field_name} = args; if (typeof(field_name) == STR) field = $pinfo:match_field(field_name); elseif (typeof(field_name) == OBJ) field = field_name; else raise(E_TYPE, "Invalid field specifier."); endif if (valid(field)) return field:get_field(this); else return E_INVARG; endif . @verb $pinfo:@pinfo-* any any any rdx @program $pinfo:@pinfo-* target = dobj; if (!valid(target)) if (dobjstr == "") target = player; else target = $string_utils:match_actor(dobjstr); if (target == $ambiguous_match) player:tell("I couldn't tell which ", dobjstr, " you meant!"); return 0; elseif (target == $failed_match) player:tell("I couldn't find any ", dobjstr); return 0; endif endif endif field_name = verb[index(verb,"-") + 1..$]; if (prepstr == "is") set_task_perms(caller_perms()); retval = target:set_pinfo(field_name, iobjstr); if (retval) player:tell(target:title() + "'s " + $pinfo:match_field(field_name).name + " has been set to: " + target:get_pinfo(field_name)); elseif (retval == E_PERM) player:tell("You do not appear to be able to set " + target:title() + "'s " + $pinfo:match_field(field_name).name); elseif (retval == E_TYPE) field = $pinfo:match_field(field_name); player:tell("\"" + iobjstr + "\" does not appear to be a valid value for " + target:title() + "'s " + field.name); if (LIST in field.types) player:tell("Try using '@pinfo-" + field_name + " " + target.name + "' instead to invoke the pinfo editor."); endif elseif (retval == E_INVARG) player:tell("I can't find a pinfo field named " + field_name); else raise(E_TYPE, "Unexpected return value from set_pinfo."); endif elseif (prepstr == "" && iobjstr == "") set_task_perms(caller_perms()); $pinfo_editor:invoke(target, field_name); else raise (E_VERBNF); endif . @verb $pinfo:get_fields_help this none this rdx @program $pinfo:get_fields_help "get_fields_help(type) => list of strings representing the help for type fields."; "Type should be 'ic' or 'ooc'."; "[bold]INTERNAL USE ONLY[normal]"; if (caller != this) raise(E_PERM); endif fields_text = {}; for field in ($pinfo:(args[1] + "_fields")()) if (field:can_modify(player, player)) singlevalue = 1; listvalue = 0; if (LIST in field.types) listvalue = 1; if (length(field.types) == 1) singlevalue = 0; endif endif field_text = ">>"; if (singlevalue) field_text = field_text + this.fields_help_singleline; endif if (listvalue) field_text = field_text + this.fields_help_multiline; endif field_text = field_text + " [bold]" + field.name + "[normal] (" + field.brief_name + "): "; desc = field:description(); if (typeof(desc) == STR) desc = {desc}; endif desc[1] = field_text + desc[1]; fields_text = {@fields_text, @desc}; endif endfor return fields_text; . @verb $pinfo:format_field_name tnt rdx @program $pinfo:format_field_name "format_field_name(field) => Formatted field name ready for printing by pinfo."; "Not intended for external use. Provided in capsule form for oral intake only."; {field} = args; return ">> [bold]" + field.name + "[normal]:"; . @verb $pinfo:print_fields this none this rdx @program $pinfo:print_fields "print_fields(player, type) => list of strings of pinfo output for type for player."; "Type should be 'ic' or 'ooc'."; "[bold]INTERNAL USE ONLY[normal]"; if (caller != this) raise(E_PERM); endif {target, type} = args; set_task_perms(caller_perms()); output = {}; for field in ($pinfo:(type + "_fields")()) value = target:get_pinfo(field); if (value == E_PERM) continue; endif if (typeof(value) == LIST) if (value != {}) output = listappend(output, this:format_field_name(field) + " " + tostr(value[1])); if (length(value) > 1) output = {@output, @value[2..$]}; endif output = listappend(output, ""); endif else if (value != "" && typeof(value) != ERR) output = listappend(output, this:format_field_name(field) + " " + tostr(value)); /* output = listappend(output, "");*/ endif endif endfor return output; . @verb $pinfo:@pinfo any none none @program $pinfo:@pinfo if (dobjstr == "") "List pinfo fields."; ic_fields_text = this:get_fields_help("ic"); ooc_fields_text = this:get_fields_help("ooc"); $console:dialog_box(player, "pinfo Fields", {}, $pinfo.fields_help_list, "IC Fields", ic_fields_text, "OOC Fields", ooc_fields_text); else "Display pinfo for the given person."; target = $string_utils:match_actor(dobjstr); if (target == $ambiguous_match) player:tell("I don't know which " + dobjstr + " you mean!"); return; elseif (target == $failed_match) player:tell("I don't know of any players or NPCs named " + dobjstr); return; endif set_task_perms(player); ic_output = this:print_fields(target, "ic"); ooc_output = this:print_fields(target, "ooc"); $console:dialog_box(player, "IC pinfo for " + target:title(), {}, ic_output, "OOC pinfo for " + target:title(), ooc_output); endif . @verb $pinfo:info_fields tnt rdx @program $pinfo:info_fields "info_fields() => A list of fields used by @cinfo/@info."; return this.info_fields; . @verb $pinfo:"@cinfo @info" any none none rdx @program $pinfo:@cinfo if (dobjstr == "") "List pinfo fields."; target = player; else target = $string_utils:match_actor(dobjstr); if (target == $ambiguous_match) player:tell("I couldn't tell which ", dobjstr, " you meant."); return; elseif (target == $failed_match) player:tell("I couldn't find any player named ", dobjstr); return; endif endif set_task_perms(player); output = this:print_fields(target, "info"); $console:dialog_box(player, "IC info for " + target:title(), {}, output); . @verb $pinfo_editor:parse_invoke this none this rdx @program $pinfo_editor:parse_invoke "parse_invoke(field) => {field dbref}"; {target, field_name} = args; if (!valid(target)) player:tell(target, " doesn't appear to be a valid thing. This shouldn't happen. Please @mail *feedback with exactly what you typed."); return 0; endif field = $pinfo:match_field(field_name); if (valid(field)) if (!field:can_modify(player, target)) player:tell("You do not appear to be able to modify ", target:title(), "'s ", field.name); return 0; elseif (!field:can_edit(player)) player:tell("You do not appear to be able to edit ", target:title(), "'s ", field.name); return 0; endif text = this:fetch_pinfo_field(target, field); if (text == E_TYPE) player:tell(target:title(), "'s ", field.name, " does not appear to be the right type. Reverting to default."); player:tell("Old value:"); player:tell_lines(target:get_pinfo(field)); text = {}; elseif (text == E_PERM) player:tell("You cannot read ", target:title() + "'s " + field.name + ". Please contact a wizard."); return 0; elseif (text == E_INVARG) player:tell("Something's very wrong - that field appears to both exist and not exist! Please contact a wizard."); return 0; endif return {target, field, text}; elseif (field == $failed_match) player:tell("I could not find a pinfo field named " + field_name + "."); return 0; elseif (field == $ambiguous_match) player:tell("I could not tell which field named " + field_name + " you meant."); return 0; endif . @verb $pinfo_editor:init_session this none this rdx @program $pinfo_editor:init_session {who, target, field, text} = args; if (this:ok(who)) this.state_fields[who] = field; this.state_targets[who] = target; value = this:load(who, text); if (value == E_TYPE) player:tell(target:title(), "'s ", field.name, " does not appear to be editable. reverting to default."); player:tell("Old value:"); player:tell_lines(target:get_pinfo(field)); text = {}; this:load(who, text); endif player:tell(this:working_on(who)); endif . @verb $pinfo_editor:fetch_pinfo_field this none this rdx @program $pinfo_editor:fetch_pinfo_field if (caller != $pinfo_editor || caller_perms() != $pinfo_editor.owner) return E_PERM; endif set_task_perms(player); {person, field} = args; return person:get_pinfo(field); . @verb $pinfo_editor:working_on this none this rdx @program $pinfo_editor:working_on {who} = args; return "You are working on " + this.state_targets[who]:title() + "'s " + this.state_fields[who].name; . @verb $pinfo_editor:save none none none rd @program $pinfo_editor:save if (!(who = this:loaded(player))) player:tell(this:nothing_loaded_msg()); return; endif field = this.state_fields[who]; target = this.state_targets[who]; value = target:set_pinfo(field, this:text()); if (value == E_PERM) player:tell("You can no longer write to ", target:title(), "'s ", field.name, ". I suggest 'abort'-ing and contacting a wizard."); elseif (value == E_TYPE) player:tell("For some reason, ", target:title(), "'s ", field.name, " can no longer be edited. I suggest 'abort'-ing and contacting a wizard."); elseif (value == E_INVARG) player:tell("That isn't a valid value for ", target:title(), "'s ", field.name, ". I suggest reading the documentation in @pinfo. If this doesn't help, please contact a wizard."); elseif (typeof(value) != ERR) this:set_changed(who, 0); player:tell(target:title(), "'s ", field.name, " has been set."); endif .