blob: 7c9255f00146437d164d1db443ed54a344262836 [file] [log] [blame]
// MorgenGrauen MUDlib
//
// room.c -- room base object
//
// $Id: room.c 9475 2016-02-19 21:16:17Z Zesstra $
#pragma strong_types
#pragma save_types
#pragma range_check
#pragma no_clone
inherit "/std/thing/properties";
inherit "/std/thing/language";
inherit "/std/hook_provider";
inherit "/std/room/light";
inherit "/std/container/inventory";
inherit "/std/room/moving";
inherit "/std/room/restrictions";
inherit "/std/room/description";
inherit "/std/room/exits";
inherit "/std/room/commands";
inherit "/std/room/items";
inherit "/std/container/vitems";
inherit "/std/room/doors";
inherit "/std/room/comm";
#include <thing/properties.h>
#include <config.h>
#include <properties.h>
#include <rooms.h>
#include <language.h>
#include <wizlevels.h>
#include <moving.h>
#include <defines.h>
#include <doorroom.h>
#include <functionlist.h>
#include <hook.h>
void reset()
{
items::reset();
vitems::reset();
exits::reset();
doors::reset();
}
static int
_query_noget()
{
return 1;
}
void maybe_replace_program()
{
string *list, first;
object first_ob;
if (object_name(this_object())=="/std/room" ||
!(first_ob=find_object(first=(list=inherit_list(this_object()))[1])) ||
(sizeof(list)!=1+sizeof(inherit_list(first_ob))) ||
(1!=sizeof(list=functionlist(this_object(),
RETURN_FUNCTION_NAME|NAME_INHERITED))) ||
list[0]!="create")
return;
replace_program(first);
}
protected void create()
{
maybe_replace_program();
/* Set effective userid to userid */
/* so that we may clone other things */
seteuid(getuid(this_object()));
properties::create();
restrictions::create();
commands::create();
light::create();
description::create();
exits::create();
items::create();
doors::create();
offerHook(H_HOOK_INIT, 1);
SetProp(P_NAME,0);
SetProp(P_NAME_ADJ,({}));
Set(P_SHORT,0);
Set(P_LONG,0);
Set(P_TRANSPARENT,0);
Set(P_ADJECTIVES,({}));
Set(P_IDS,({}));
Set(P_WEIGHT,PROTECTED,F_MODE);
Set(P_TOTAL_WEIGHT,PROTECTED,F_MODE);
Set(" clean counter ",2);
}
protected void create_super() {
set_next_reset(-1);
}
private int
check_clean_count()
{
int cc;
cc=Query(" clean counter ");
if (--cc<=0)
return 1;
Set(" clean counter ",cc);
return 0;
}
public int clean_up(int arg)
{
// Never try again when P_NEVER_CLEAN is set.
if (Query(P_NEVER_CLEAN)) return 0;
// do not cleanup, if this room is used as blueprint for clones or inherited
// (arg>1) or if there are valid hook consumers waiting for something to
// happen here. This is temporary and could change, so return 1;
if (arg>1 || HHasConsumers())
return 1;
// Pruefen ob Spieler (auch netztote) anwesend sind.
// Es fuehrt leider kein Weg dran vorbei einmal über das inventar und einmal
// ueber P_ITEMS zu iterieren.
object* inv = all_inventory();
foreach(object ob : inv)
{
if(query_once_interactive(ob))
{
Set(" clean counter ",2);
return 1;
}
}
// Auf Objekte aus P_ITEMS pruefen
foreach(<object|<string|string*>|int|mapping>* item : QueryProp(P_ITEMS))
{
// Semantik:
// 1. Wenn RITEM_OBJECT ein REFRESH_NONE Item ist und es entweder nicht mehr
// existiert oder nicht in diesem Raum ist, kein clean_up (es wuerde
// beim neuladen des Raumes ja wieder erzeugt;
// falls es aber hier ist, wird es mitvernichtet, dann ists ok)
// 2. Wenn es ein REFRESH_DESTRUCT ist und noch existiert, aber nicht
// hier ist, KEIN clean_up.
// Hier heisst fuer beide Faelle direkt in diesem Raum, befindet es sich in
// einem Container koennte es beim Zerstoeren woanders hin bewegt werden und
// damit nach dem neuladen doppelt existieren.
if( (item[RITEM_REFRESH] == REFRESH_NONE &&
(!item[RITEM_OBJECT] ||
environment(item[RITEM_OBJECT]) != ME))) ||
(item[RITEM_REFRESH] == REFRESH_DESTRUCT &&
item[RITEM_OBJECT] &&
environment(item[RITEM_OBJECT]) != ME)))
{
return 1;
}
inv -= ({item[RITEM_OBJECT]});
}
// if there are objects left in the room do not clean up but try again later
if(sizeof(inv) && !check_clean_count())
return 1;
// do clean_up
//log_file("clean_up_log",sprintf(
// "%s:%s: %O\n",ctime(time())[11..18],__HOST_NAME__,this_object()));
remove();
// wenn der Raum sich im remove() nicht zerstoert, hat er dafuer vermutlich
// nen Grund. Evtl. klappts ja naechstes Mal.
return(1);
}
/* Instead of printing the exits with the long description, we implement */
/* the command "exits" to show them. */
int
show_exits() {
mixed ex;
if( this_player()->CannotSee() ) return 1;
if ((ex=QueryProp(P_HIDE_EXITS)) && intp(ex)) return 1;
if (ex = GetExits(this_player())) write(ex);
return 1;
}
int
toggle_exits(string str)
{
int ex;
/* Nur das aktuelle Environment des Spielers ist zustaendig fuer die
Auflistung der Ausgaenge. Anderenfalls wird das Kommando von Raeumen
im Raum (z.B. Transportern) abgefangen und es werden dessen Ausgaenge
aufgelistet.
Sprich: keine Auflistung von Aussen. */
if (environment(this_player()) != this_object()) return 0;
if (!str) return show_exits();
if (str!="auto") return 0;
ex = this_player()->QueryProp(P_SHOW_EXITS);
this_player()->SetProp(P_SHOW_EXITS, !ex);
if (ex) write("Ausgaenge werden nicht mehr automatisch angezeigt.\n");
else write("Ausgaenge werden automatisch angezeigt.\n");
return 1;
}
public varargs void init(object origin)
{
if (HookFlow(H_HOOK_INIT, 0)[H_RETCODE] == H_CANCELLED)
return;
Set(" clean counter ",2);
exits::init(origin);
commands::init(origin);
description::init(origin);
doors::init(origin);
add_action("toggle_exits", "exits");
add_action("toggle_exits", "ausgang");
add_action("toggle_exits", "ausgaenge");
add_action("toggle_exits", "aus");
}
int _query_para(){
int re;
if(re=Query(P_PARA))return re;
if(sizeof(regexp(({object_name(this_object())}),".*\\^0$")))
return -1;
return to_int(
regreplace(object_name(this_object()),".*\\^\([1-9][0-9]*\)$","\\1",1));
}
//dies ist ein Raum, war gewuenscht von mehreren Leuten.
status IsRoom() {return(1);}