blob: 33935f457e882616967e9b8d98fda18881c27f04 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001/****************************************/
2/* BOTTLE.C -- a standard bottle object */
3/* or better a container for*/
4/* liquides */
5/* -- */
6/* (c) by Hate 1993 */
7/****************************************/
8
9inherit "/std/thing";
10
11/*****************************************************************************/
12#include <properties.h>
13#include <language.h>
14
15#define PL this_player()
16
17#define GULP 20 /* millilitre is one gulp ;) */
18
19#define NO ({"hundert", "neunzig", "achtzig", "siebzig",\
20 "sechzig", "fuenfzig", "vierzig", "dreissig",\
21 "zwanzig", "zehn"})
22
23#define FULL(what, amount) (what*_MaxCapacity/amount)
24#define PART(what, amount) (what*amount/_MaxCapacity)
25#define AVER(x,y, amount) ((FULL(x, amount)+y)/2)
26
27private string _Fname, _Fdescr;
28private int _Fprice, _Fheal, _Fstrength, _Fsoak;
29private int _MaxCapacity, _Capacity, _NoDrinking;
30private int _open, _NoClose;
31
32/**** ALL THE PUBLIC FUNCTIONS ***********************************************/
33public void LiquidContDescr(string Cname, string *Cids, string Cshort, string Clong,
34 int Cweight, int Capa, int NoClose, string Clabel)
35/* give a decription for the liquid container */
36/* Cname -- P_NAME of the container */
37/* Cid -- identity of the container */
38/* Cshort -- P_SHORT of the container */
39/* Clong -- P_LONG of the container */
40/* Cweight -- weight of the container */
41/* Ccapa -- capacity of the container */
42/* -- OPTIONAL -- */
43/* NoClose -- means if 1 the container can't be closed */
44/* Clabel -- optional readable label (for bottles) */
45{
46 SetProp(P_NAME, Cname);
47 SetProp(P_SHORT, Cshort);
48 SetProp(P_LONG, Clong);
49 SetProp(P_READ_MSG, Clabel);
50 SetProp(P_WEIGHT, Cweight);
51 SetProp(P_IDS, Cids);
52 _MaxCapacity = Capa;
53 _Capacity = Capa;
54 if(_NoClose = NoClose) _open = 1;
55}
56
57public int AddLiquid(int Famount, string Fname, string Fdescr, int Fprice,
58 int Fheal, int Fstrength, int Fsoak)
59/* add something in the container */
60/* Famount -- amount of liquid to be added to container, if more ignored */
61/* or better the container will run over */
62/* Fname -- name of the liquid, if there is still something inside the */
63/* container, it it will be mixed */
64/* Fdescr -- if somebody wants to look at the liquid he sees it if the */
65/* container is open */
66/* Fprice -- the price of the liquid for the given amount */
67/* Fheal -- the healing per for the given amount */
68/* Fstrength -- the strength of the liquid for the given amount */
69/* Fsoak -- the soak value for the given amount */
70{
71 if(_Capacity && Famount)
72 {
73 if(Famount<=_Capacity) _Capacity -= Famount;
74 else { Famount = _Capacity; _Capacity = 0; }
75 if(!_Fname || _Fname == Fname) { _Fname = Fname; _Fdescr = Fdescr; }
76 else { _Fdescr = "Eine Mixtur aus "+_Fname+" und "+Fname;
77 _Fname = _Fname+":"+Fname; }
78 if(_Fprice) _Fprice = AVER(Fprice, _Fprice, Famount);
79 else _Fprice = FULL(Fprice, Famount);
80 if(_Fheal) _Fheal = AVER(Fheal, _Fheal, Famount);
81 else _Fheal = FULL(Fheal, Famount);
82 if(_Fstrength) _Fstrength = AVER(Fstrength, Fstrength, Famount);
83 else _Fstrength = FULL(Fstrength, Famount);
84 if(_Fsoak) _Fsoak = AVER(Fsoak, _Fsoak, Famount);
85 else _Fsoak = FULL(Fsoak, Famount);
86 SetProp(P_VALUE, PART(_Fprice, (_MaxCapacity-_Capacity)));
87 }
88 return Famount;
89}
90
91/* to pour something out of the container */
92/* Famount -- amount of liquid to be poured */
93/* -- OPTIONAL -- */
94/* where -- if set the amount will be added to the container 'where' */
95public int PourLiquid(int Famount, object where)
96{
97 int pour, rest, oldc;
98
99 oldc = _Capacity;
100 if(objectp(where) && where->QueryContainer())
101 {
102 pour = Famount;
103 while(pour &&
104 (rest=where->AddLiquid(GULP, _Fname, _Fdescr,
105 PART(_Fprice, Famount),
106 PART(_Fheal, Famount),
107 PART(_Fstrength, Famount),
108 PART(_Fsoak, Famount)))==GULP)
109 pour -= GULP;
110 Famount -= rest;
111 }
112 else
113 if(objectp(where) && living(where))
114 {
115 if(Famount>_MaxCapacity-_Capacity) Famount = _MaxCapacity-_Capacity;
116 if(PART(_Fsoak, Famount) && !where->drink_soft(PART(_Fsoak, Famount)))
117 return 0;
118 if(!where->drink_alcohol(PART(_Fstrength, Famount)))
119 return 0;
120 where->heal_self(PART(_Fheal, Famount));
121 }
122 _Capacity += Famount;
123 SetProp(P_VALUE, PART(_Fprice, (_MaxCapacity-_Capacity)));
124 return oldc != _Capacity;
125}
126
127/* sometimes there is something poinsonous inside the container */
128/* no -- must be 1 if it is not allowed to drink (standard yes) */
129/* that means the liquid can be poured and filled, but nothing else */
130public int AllowDrinking(int no) { return _NoDrinking = no; }
131
132/* returns the amount and name of the contents as an array 0-contents 1-name */
133public <int|string>* QueryContents() { return ({ _MaxCapacity-_Capacity, _Fname }); }
134
135/* returns 1 if this is an liquid container */
136public int QueryContainer() { return 1; }
137
138/*****************************************************************************/
139protected void create()
140{
141 if (!clonep(this_object())) return;
142 ::create();
143
144 SetProp(P_NAME, "Flasche");
145 AddId("flasche");
146 SetProp(P_SHORT, "Eine Flasche");
147 SetProp(P_LONG, "Du siehst nichts besonderes an oder in der Flasche.\n");
148 SetProp(P_GENDER, FEMALE);
149 SetProp(P_WEIGHT,100);
150}
151
152void init()
153{
154 ::init();
155
156 add_action("DoDrink", "trinke");
157 add_action("DoDrink", "trink");
158 add_action("DoPour", "schuette");
159 add_action("DoPour", "schuett");
160 add_action("DoPour", "fuelle");
161 add_action("DoPour", "fuell");
162 add_action("DoOpen", "oeffne");
163 add_action("DoClose", "schliesse");
164 add_action("DoLookInside", "schaue");
165 add_action("DoLookInside", "schau");
166}
167
168int DoDrink(string arg)
169{
170 string howmuch, trash, str;
171 int all, cnt;
172
173 if(!_NoDrinking && arg && sscanf(arg, "%saus %s", str, trash)==2 && id(trash))
174 {
175 if(!_open) return write(capitalize(name(0,1))+" ist aber noch zu.\n") || 1;
176 if(_Capacity==_MaxCapacity)
177 {
178 write("Du setzt "+name(WEN, 1)+" an und merkst, dass nichts mehr darin "
179 +"ist.\n");
180 say(PL->name()+" setzt "+name(WEN)+" an und merkt, dass nichts mehr darin"
181 +" ist.\n");
182 return 1;
183 }
184 if(sscanf(str, "alles%s", trash) == 1)
185 {
186 all = _Capacity;
187 while(PourLiquid(GULP, PL));
188 if(_Capacity==all) return write("Du schaffst es nicht zu trinken.\n"),0;
189 if(_MaxCapacity>_Capacity)
190 write("Du hast nur einen Teil zu trinken geschafft.\n");
191 else
192 {
193 write("Du trinkst alles bis zum letzten Rest aus "+name(WEM, 1)+".\n");
194 say(PL->name()+" trinkt alles bis zum letzten Rest aus "
195 +name(WEM)+".\n");
196 }
197 return 1;
198 }
199 if(str==" " || (str=="schluck" || sscanf(str, "schluck%s", trash)) == 1)
200 if(PourLiquid(GULP, PL))
201 {
202 write("Du trinkst einen Schluck aus "+name(WEM, 1)+".\n");
203 say(PL->name()+" trinkt einen Schluck aus "+name(WEM)+".\n");
204 return 1;
205 }
206 else return write("Du schaffst es nicht zu trinken.\n") || 1;
207 else
208 {
209 if(sscanf(str, "%s schluck%s", howmuch, trash)>=1)
210 switch(howmuch)
211 {
212 case "1":
213 case "ein":
214 case "einen": { cnt = 1; howmuch = "einen"; break; }
215 case "2":
216 case "zwei" : { cnt = 2; break; }
217 case "3":
218 case "drei" : { cnt = 3; break; }
219 case "4":
220 case "vier" : { cnt = 4; break; }
221 case "5":
222 case "fuenf": { cnt = 5; break; }
223 case "6":
224 case "sechs": { cnt = 6; break; }
225 case "7":
226 case "sieben":{ cnt = 7; break; }
227 case "8":
228 case "acht" : { cnt = 8; break; }
229 case "9":
230 case "neun" : { cnt = 9; break; }
231 case "10":
232 case "zehn" : { cnt = 10; break; }
233 default: cnt = 0;
234 }
235 if(!cnt) { cnt = 1; howmuch = "einen"; }
236 while(cnt-- && all=PourLiquid(GULP, PL));
237 if(cnt>0 && all==_MaxCapacity)
238 write("Sooo viele Schluecke waren gar nicht in "+name(WEM, 1)+".\n");
239 else write("Du trinkst ein paar Schluck aus "+name(WEM, 1)+".\n");
240 say(PL->name()+" trinkt aus "+name(WEM)+".\n");
241 return 1;
242 }
243 }
244 return 0;
245}
246
247int DoPour(string arg)
248{
249 object dest;
250 string where, str;
251
252 if(arg && sscanf(arg, "%saus %s", str, where)==2 && id(where))
253 {
254 if(!_open) return write(capitalize(name(0,1))+" ist aber noch zu.\n") || 1;
255 if(_Capacity==_MaxCapacity)
256 return write("Es ist nichts in "+name(WEM, 1)+".\n") || 1;
257 if(sscanf(str, "alles%s", where)==1)
258 {
259 PourLiquid(_MaxCapacity, environment(this_player()));
260 write("Du schuettest alles aus "+name(WEM, 1)+".\n");
261 say(PL->name()+" schuettet alles aus "+name(WEM)+".\n");
262 return _Capacity;
263 }
264 if(sscanf(str, "in %s", where)==1)
265 {
266 if(!dest = present(where)) dest = present(where, environment(PL));
267 if(dest && !query_once_interactive(dest) &&
268 PourLiquid(_MaxCapacity-_Capacity, dest))
269 {
270 write("Du fuellst "+dest->name(WEN, 1)+" mit "+_Fname+" ab.\n");
271 say(PL->name()+" fuellt "+dest->name(WEN)+" mit "+_Fname+" ab.\n");
272 return _Capacity;
273 }
274 }
275 }
276 return 0;
277}
278
279int DoOpen(string str)
280{
281 if(id(str) && !_NoClose)
282 {
283 if(_open) return write(capitalize(name(0,1))+" ist schon offen.\n") || 1;
284 write("Du oeffnest "+name(WEN, 1)+".\n");
285 say(PL->name()+" oeffnet "+name(WEN)+".\n");
286 _open = 1;
287 return 1;
288 }
289 return 0;
290}
291
292int DoClose(string str)
293{
294 if(id(str) && !_NoClose)
295 {
296 if(!_open) return write(capitalize(name(0,1))+" ist schon zu.\n") || 1;
297 write("Du machst "+name(WEN, 1)+" zu.\n");
298 say(PL->name()+" schliesst "+name(WEN)+".\n");
299 _open = 0;
300 return 1;
301 }
302 return 0;
303}
304
305int DoLookInside(string str)
306{
307 string trash;
308
309 if(str && sscanf(str, "in %s", trash)==1 && id(trash))
310 {
311 if(!_open) return write(capitalize(name(0,1))+" ist aber noch zu.\n") || 1;
312 if(_Capacity==_MaxCapacity)
313 return write("Es ist nichts in "+name(WEM, 1)+".\n") || 1;
314 write(capitalize(name(0,1))
315 +" ist zu "+NO[_Capacity*10/_MaxCapacity]+" Prozent voll mit "
316 +_Fdescr+".\n");
317 return 1;
318 }
319 return 0;
320}
321