blob: 33935f457e882616967e9b8d98fda18881c27f04 [file] [log] [blame]
/****************************************/
/* BOTTLE.C -- a standard bottle object */
/* or better a container for*/
/* liquides */
/* -- */
/* (c) by Hate 1993 */
/****************************************/
inherit "/std/thing";
/*****************************************************************************/
#include <properties.h>
#include <language.h>
#define PL this_player()
#define GULP 20 /* millilitre is one gulp ;) */
#define NO ({"hundert", "neunzig", "achtzig", "siebzig",\
"sechzig", "fuenfzig", "vierzig", "dreissig",\
"zwanzig", "zehn"})
#define FULL(what, amount) (what*_MaxCapacity/amount)
#define PART(what, amount) (what*amount/_MaxCapacity)
#define AVER(x,y, amount) ((FULL(x, amount)+y)/2)
private string _Fname, _Fdescr;
private int _Fprice, _Fheal, _Fstrength, _Fsoak;
private int _MaxCapacity, _Capacity, _NoDrinking;
private int _open, _NoClose;
/**** ALL THE PUBLIC FUNCTIONS ***********************************************/
public void LiquidContDescr(string Cname, string *Cids, string Cshort, string Clong,
int Cweight, int Capa, int NoClose, string Clabel)
/* give a decription for the liquid container */
/* Cname -- P_NAME of the container */
/* Cid -- identity of the container */
/* Cshort -- P_SHORT of the container */
/* Clong -- P_LONG of the container */
/* Cweight -- weight of the container */
/* Ccapa -- capacity of the container */
/* -- OPTIONAL -- */
/* NoClose -- means if 1 the container can't be closed */
/* Clabel -- optional readable label (for bottles) */
{
SetProp(P_NAME, Cname);
SetProp(P_SHORT, Cshort);
SetProp(P_LONG, Clong);
SetProp(P_READ_MSG, Clabel);
SetProp(P_WEIGHT, Cweight);
SetProp(P_IDS, Cids);
_MaxCapacity = Capa;
_Capacity = Capa;
if(_NoClose = NoClose) _open = 1;
}
public int AddLiquid(int Famount, string Fname, string Fdescr, int Fprice,
int Fheal, int Fstrength, int Fsoak)
/* add something in the container */
/* Famount -- amount of liquid to be added to container, if more ignored */
/* or better the container will run over */
/* Fname -- name of the liquid, if there is still something inside the */
/* container, it it will be mixed */
/* Fdescr -- if somebody wants to look at the liquid he sees it if the */
/* container is open */
/* Fprice -- the price of the liquid for the given amount */
/* Fheal -- the healing per for the given amount */
/* Fstrength -- the strength of the liquid for the given amount */
/* Fsoak -- the soak value for the given amount */
{
if(_Capacity && Famount)
{
if(Famount<=_Capacity) _Capacity -= Famount;
else { Famount = _Capacity; _Capacity = 0; }
if(!_Fname || _Fname == Fname) { _Fname = Fname; _Fdescr = Fdescr; }
else { _Fdescr = "Eine Mixtur aus "+_Fname+" und "+Fname;
_Fname = _Fname+":"+Fname; }
if(_Fprice) _Fprice = AVER(Fprice, _Fprice, Famount);
else _Fprice = FULL(Fprice, Famount);
if(_Fheal) _Fheal = AVER(Fheal, _Fheal, Famount);
else _Fheal = FULL(Fheal, Famount);
if(_Fstrength) _Fstrength = AVER(Fstrength, Fstrength, Famount);
else _Fstrength = FULL(Fstrength, Famount);
if(_Fsoak) _Fsoak = AVER(Fsoak, _Fsoak, Famount);
else _Fsoak = FULL(Fsoak, Famount);
SetProp(P_VALUE, PART(_Fprice, (_MaxCapacity-_Capacity)));
}
return Famount;
}
/* to pour something out of the container */
/* Famount -- amount of liquid to be poured */
/* -- OPTIONAL -- */
/* where -- if set the amount will be added to the container 'where' */
public int PourLiquid(int Famount, object where)
{
int pour, rest, oldc;
oldc = _Capacity;
if(objectp(where) && where->QueryContainer())
{
pour = Famount;
while(pour &&
(rest=where->AddLiquid(GULP, _Fname, _Fdescr,
PART(_Fprice, Famount),
PART(_Fheal, Famount),
PART(_Fstrength, Famount),
PART(_Fsoak, Famount)))==GULP)
pour -= GULP;
Famount -= rest;
}
else
if(objectp(where) && living(where))
{
if(Famount>_MaxCapacity-_Capacity) Famount = _MaxCapacity-_Capacity;
if(PART(_Fsoak, Famount) && !where->drink_soft(PART(_Fsoak, Famount)))
return 0;
if(!where->drink_alcohol(PART(_Fstrength, Famount)))
return 0;
where->heal_self(PART(_Fheal, Famount));
}
_Capacity += Famount;
SetProp(P_VALUE, PART(_Fprice, (_MaxCapacity-_Capacity)));
return oldc != _Capacity;
}
/* sometimes there is something poinsonous inside the container */
/* no -- must be 1 if it is not allowed to drink (standard yes) */
/* that means the liquid can be poured and filled, but nothing else */
public int AllowDrinking(int no) { return _NoDrinking = no; }
/* returns the amount and name of the contents as an array 0-contents 1-name */
public <int|string>* QueryContents() { return ({ _MaxCapacity-_Capacity, _Fname }); }
/* returns 1 if this is an liquid container */
public int QueryContainer() { return 1; }
/*****************************************************************************/
protected void create()
{
if (!clonep(this_object())) return;
::create();
SetProp(P_NAME, "Flasche");
AddId("flasche");
SetProp(P_SHORT, "Eine Flasche");
SetProp(P_LONG, "Du siehst nichts besonderes an oder in der Flasche.\n");
SetProp(P_GENDER, FEMALE);
SetProp(P_WEIGHT,100);
}
void init()
{
::init();
add_action("DoDrink", "trinke");
add_action("DoDrink", "trink");
add_action("DoPour", "schuette");
add_action("DoPour", "schuett");
add_action("DoPour", "fuelle");
add_action("DoPour", "fuell");
add_action("DoOpen", "oeffne");
add_action("DoClose", "schliesse");
add_action("DoLookInside", "schaue");
add_action("DoLookInside", "schau");
}
int DoDrink(string arg)
{
string howmuch, trash, str;
int all, cnt;
if(!_NoDrinking && arg && sscanf(arg, "%saus %s", str, trash)==2 && id(trash))
{
if(!_open) return write(capitalize(name(0,1))+" ist aber noch zu.\n") || 1;
if(_Capacity==_MaxCapacity)
{
write("Du setzt "+name(WEN, 1)+" an und merkst, dass nichts mehr darin "
+"ist.\n");
say(PL->name()+" setzt "+name(WEN)+" an und merkt, dass nichts mehr darin"
+" ist.\n");
return 1;
}
if(sscanf(str, "alles%s", trash) == 1)
{
all = _Capacity;
while(PourLiquid(GULP, PL));
if(_Capacity==all) return write("Du schaffst es nicht zu trinken.\n"),0;
if(_MaxCapacity>_Capacity)
write("Du hast nur einen Teil zu trinken geschafft.\n");
else
{
write("Du trinkst alles bis zum letzten Rest aus "+name(WEM, 1)+".\n");
say(PL->name()+" trinkt alles bis zum letzten Rest aus "
+name(WEM)+".\n");
}
return 1;
}
if(str==" " || (str=="schluck" || sscanf(str, "schluck%s", trash)) == 1)
if(PourLiquid(GULP, PL))
{
write("Du trinkst einen Schluck aus "+name(WEM, 1)+".\n");
say(PL->name()+" trinkt einen Schluck aus "+name(WEM)+".\n");
return 1;
}
else return write("Du schaffst es nicht zu trinken.\n") || 1;
else
{
if(sscanf(str, "%s schluck%s", howmuch, trash)>=1)
switch(howmuch)
{
case "1":
case "ein":
case "einen": { cnt = 1; howmuch = "einen"; break; }
case "2":
case "zwei" : { cnt = 2; break; }
case "3":
case "drei" : { cnt = 3; break; }
case "4":
case "vier" : { cnt = 4; break; }
case "5":
case "fuenf": { cnt = 5; break; }
case "6":
case "sechs": { cnt = 6; break; }
case "7":
case "sieben":{ cnt = 7; break; }
case "8":
case "acht" : { cnt = 8; break; }
case "9":
case "neun" : { cnt = 9; break; }
case "10":
case "zehn" : { cnt = 10; break; }
default: cnt = 0;
}
if(!cnt) { cnt = 1; howmuch = "einen"; }
while(cnt-- && all=PourLiquid(GULP, PL));
if(cnt>0 && all==_MaxCapacity)
write("Sooo viele Schluecke waren gar nicht in "+name(WEM, 1)+".\n");
else write("Du trinkst ein paar Schluck aus "+name(WEM, 1)+".\n");
say(PL->name()+" trinkt aus "+name(WEM)+".\n");
return 1;
}
}
return 0;
}
int DoPour(string arg)
{
object dest;
string where, str;
if(arg && sscanf(arg, "%saus %s", str, where)==2 && id(where))
{
if(!_open) return write(capitalize(name(0,1))+" ist aber noch zu.\n") || 1;
if(_Capacity==_MaxCapacity)
return write("Es ist nichts in "+name(WEM, 1)+".\n") || 1;
if(sscanf(str, "alles%s", where)==1)
{
PourLiquid(_MaxCapacity, environment(this_player()));
write("Du schuettest alles aus "+name(WEM, 1)+".\n");
say(PL->name()+" schuettet alles aus "+name(WEM)+".\n");
return _Capacity;
}
if(sscanf(str, "in %s", where)==1)
{
if(!dest = present(where)) dest = present(where, environment(PL));
if(dest && !query_once_interactive(dest) &&
PourLiquid(_MaxCapacity-_Capacity, dest))
{
write("Du fuellst "+dest->name(WEN, 1)+" mit "+_Fname+" ab.\n");
say(PL->name()+" fuellt "+dest->name(WEN)+" mit "+_Fname+" ab.\n");
return _Capacity;
}
}
}
return 0;
}
int DoOpen(string str)
{
if(id(str) && !_NoClose)
{
if(_open) return write(capitalize(name(0,1))+" ist schon offen.\n") || 1;
write("Du oeffnest "+name(WEN, 1)+".\n");
say(PL->name()+" oeffnet "+name(WEN)+".\n");
_open = 1;
return 1;
}
return 0;
}
int DoClose(string str)
{
if(id(str) && !_NoClose)
{
if(!_open) return write(capitalize(name(0,1))+" ist schon zu.\n") || 1;
write("Du machst "+name(WEN, 1)+" zu.\n");
say(PL->name()+" schliesst "+name(WEN)+".\n");
_open = 0;
return 1;
}
return 0;
}
int DoLookInside(string str)
{
string trash;
if(str && sscanf(str, "in %s", trash)==1 && id(trash))
{
if(!_open) return write(capitalize(name(0,1))+" ist aber noch zu.\n") || 1;
if(_Capacity==_MaxCapacity)
return write("Es ist nichts in "+name(WEM, 1)+".\n") || 1;
write(capitalize(name(0,1))
+" ist zu "+NO[_Capacity*10/_MaxCapacity]+" Prozent voll mit "
+_Fdescr+".\n");
return 1;
}
return 0;
}