#include <kernel/kernel.h> #include <phantasmal/exit.h> #include <phantasmal/log.h> #include <phantasmal/phrase.h> #include <phantasmal/map.h> #include <phantasmal/obj_flags.h> #include <phantasmal/lpc_names.h> #include <type.h> inherit OBJECT; /* exit.c Inherited by any exit type. An object which is an exit might contain or inherit from one, though that design isn't set in stone yet... */ int direction; /* 8 compass directions */ int type; /* one-way, two-way, etc. */ int link_to; /* exit # that a two-way links to */ object from_location; object destination; /* Object flags uses flag values in obj_flags.h */ private int objflags; static void create(varargs int clone) { ::create(clone); if(clone) { } } void upgraded(varargs int clone) { ::upgraded(clone); } void destructed(int clone) { ::destructed(clone); } void set_direction(int new_dir) { if(previous_program() == EXITD) { direction = new_dir; } else error("Only EXITD can set exit directions!"); } void set_from_location(object new_loc) { if(previous_program() == EXITD) { from_location = new_loc; } else error("Only EXITD can set exit from locations!"); } void set_destination(object new_dest) { if(previous_program() == EXITD) { destination = new_dest; } else error("Only EXITD can set exit destinations!"); } void set_exit_type(int new_type) { if(previous_program() == EXITD) { switch (new_type) { case ET_ONEWAY: case ET_TWOWAY: type = new_type; break; default: /* unknown type */ type = ET_TWOWAY; break; } } else error("Only EXITD can set exit types!"); } void set_link(int new_link) { if(previous_program() == EXITD) { link_to = new_link; } else error("Only EXITD can set links!"); } int get_direction() { return direction; } int get_exit_type() { return type; } int get_link() { return link_to; } object get_from_location() { return from_location; } object get_destination() { return destination; } /* * string to_unq_flags(void) * * creates a string out of the object flags. */ static string to_unq_flags(void) { object dest, shortphr, other_exit; string ret, tmp_n, tmp_a; int locale, opp_dir; string** nouns, **adjectives; ret = ""; dest = get_destination(); shortphr = EXITD->get_short_for_dir(get_direction()); ret += " ~rnumber{" + get_number() + "}\n" + " ~direction{" + get_direction() + "}\n" + " ~destination{" + dest->get_number() + "}\n" + " ~return{"; if(get_link() > 0 && dest) { opp_dir = EXITD->opposite_direction(get_direction()); other_exit = dest->get_exit(opp_dir); if(!other_exit) { LOGD->write_syslog("Problem finding return exit!", LOG_WARN); } else { ret += other_exit->get_number() + "}\n"; } } else { ret += "-1}\n"; } ret += " ~type{" + get_exit_type() + "}\n"; if(bdesc) { ret += " ~rbdesc{" + bdesc->to_unq_text() + "}\n"; } if(ldesc) { ret += " ~rldesc{" + ldesc->to_unq_text() + "}\n"; } if(edesc) { ret += " ~redesc{" + edesc->to_unq_text() + "}\n"; } /* Skip debug locale */ tmp_n = tmp_a = ""; nouns = get_immediate_nouns(); adjectives = get_immediate_adjectives(); for(locale = 1; locale < sizeof(nouns); locale++) { if(sizeof(nouns[locale])) { tmp_n += "~" + PHRASED->locale_name_for_language(locale) + "{" + implode(nouns[locale], ",") + "}"; } if(sizeof(adjectives[locale])) { tmp_a += "~" + PHRASED->locale_name_for_language(locale) + "{" + implode(adjectives[locale], ",") + "}"; } } /* The double-braces are intentional -- this uses the efficient method of specifying nouns and adjectives rather than the human- friendly one. */ if(tmp_n && tmp_n!="") { ret += " ~rnouns{{" + tmp_n + "}}\n"; } if(tmp_a && tmp_a!="") { ret += " ~radjectives{{" + tmp_a + "}}\n"; } ret += " ~rflags{" + objflags + "}"; return ret; } /* * void from_dtd_flags(mixed *unq) * * loads data from the unq parsed with a room-derived dtd. */ static void from_dtd_tag(string tag, mixed value) { int ctr; if (tag=="rnumber") { tr_num = value; } else if (tag=="direction") { direction = value; } else if (tag=="destination") { destination = value; } else if (tag=="return") { link_to = value; } else if (tag=="type") { type = value; } else if (tag=="rbdesc") { bdesc = value; } else if (tag=="rldesc") { ldesc = value; } else if (tag=="redesc") { edesc = value; } else if (tag=="rflags") { objflags = value; } else if(tag=="rnouns") { for(ctr = 0; ctr < sizeof(value); ctr++) { add_noun(value[ctr]); } } else if(tag=="radjectives") { for(ctr = 0; ctr < sizeof(value); ctr++) { add_adjective(value[ctr]); } } } /* * flag overrides */ int is_container() { return objflags & OF_CONTAINER; } int is_open() { return objflags & OF_OPEN; } int is_openable() { return objflags & OF_OPENABLE; } int is_locked() { return objflags & OF_LOCKED; } int is_lockable() { return objflags & OF_LOCKABLE; } private void set_flags(int flags, int value) { if(value) { objflags |= flags; } else { objflags &= ~flags; } } void set_all_flags(int flags) { if(previous_program() != EXITD) error("Only EXITD may set_all_flags!"); objflags = flags; } /* These may seem a little weird. The problem is, we need to access * a different objects private function. The recursion takes care * of this for us. I use get_link()>0 because == -1 for one-way and * ==0 for non-existent link. */ void set_container(int value) { object link_exit; if(!SYSTEM() && !COMMON()) error("Only SYSTEM code can currently set an object as a container!"); if (get_link()>0 && previous_program() != EXIT) { link_exit = EXITD->get_exit_by_num(get_link()); link_exit->set_container(value); } set_flags(OF_CONTAINER, value); } void set_open(int value) { object link_exit; string err; if(!SYSTEM() && !COMMON()) error("Only SYSTEM code can currently set an object as open!"); if (get_link()>0 && previous_program() != EXIT) { link_exit = EXITD->get_exit_by_num(get_link()); link_exit->set_open(value); } set_flags(OF_OPEN, value); } void set_openable(int value) { object link_exit; if(!SYSTEM() && !COMMON()) error("Only SYSTEM code can currently set an object as openable!"); if (get_link()>0 && previous_program() != EXIT) { link_exit = EXITD->get_exit_by_num(get_link()); link_exit->set_openable(value); } set_flags(OF_OPENABLE, value); } void set_locked(int value) { object link_exit; if(!SYSTEM() && !COMMON()) error("Only SYSTEM code can currently set an object as a container!"); if (get_link()>0 && previous_program() != EXIT) { link_exit = EXITD->get_exit_by_num(get_link()); link_exit->set_locked(value); } set_flags(OF_LOCKED, value); } void set_lockable(int value) { object link_exit; if(!SYSTEM() && !COMMON()) error("Only SYSTEM code can currently set an object as open!"); if (get_link()>0 && previous_program() != EXIT) { link_exit = EXITD->get_exit_by_num(get_link()); link_exit->set_lockable(value); } set_flags(OF_LOCKABLE, value); } /* Return nil if a user can pass through a door, the reason if they cannot */ string can_pass(object user, object pass_object) { if (!is_open()) return "The door is closed."; } /* Called when a user passes through the exit */ void pass(object pass_object) { }