blob: 65332ce2d5237bbdd81339dbc85322bc70c13786 [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";
#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;
}
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;
// if there are any items we have produced ourselfes check them
mixed itema = QueryProp(P_ITEMS);
if(pointerp(itema))
{
mixed names;
int i;
i = sizeof(names = all_inventory(this_object()));
while(i--)
{
if (query_once_interactive(names[i]))
{
Set(" clean counter ",2);
return 1;
}
if(objectp(names[i])) names[i] = explode(object_name(names[i]),"#")[0];
}
for(i = sizeof(itema)-1; i >= 0; i--)
{
// Semantik:
// 1. Wenn RITEM_OBJECT ein array ist, kann evtl ge'clean'ed werden.
// 2. Wenn es 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)
// 3. Wenn es ein REFRESH_DESTRUCT ist und noch existiert, aber nicht
// hier ist, KEIN clean_up.
if (!pointerp(itema[i][RITEM_OBJECT])
&& ((itema[i][RITEM_REFRESH] == REFRESH_NONE
&& (!itema[i][RITEM_OBJECT]
|| environment(itema[i][RITEM_OBJECT])!=this_object()))
|| (itema[i][RITEM_REFRESH] == REFRESH_DESTRUCT
&& itema[i][RITEM_OBJECT]
&& environment(itema[i][RITEM_OBJECT]) != this_object())))
return 1;
names -= (pointerp(itema[i][RITEM_FILE]) ?
itema[i][RITEM_FILE] : ({ itema[i][RITEM_FILE] }));
}
// if there are objects left in the room do not clean up but try again later
if(sizeof(names) && !check_clean_count()) return 1;
}
else
// is there any object lying around?
if(first_inventory(this_object()) && !check_clean_count()) return 2;
// 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);}