MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame^] | 1 | /****************************************/ |
| 2 | /* BOTTLE.C -- a standard bottle object */ |
| 3 | /* or better a container for*/ |
| 4 | /* liquides */ |
| 5 | /* -- */ |
| 6 | /* (c) by Hate 1993 */ |
| 7 | /****************************************/ |
| 8 | |
| 9 | inherit "/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 | |
| 27 | private string _Fname, _Fdescr; |
| 28 | private int _Fprice, _Fheal, _Fstrength, _Fsoak; |
| 29 | private int _MaxCapacity, _Capacity, _NoDrinking; |
| 30 | private int _open, _NoClose; |
| 31 | |
| 32 | /**** ALL THE PUBLIC FUNCTIONS ***********************************************/ |
| 33 | public 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 | |
| 57 | public 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' */ |
| 95 | public 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 */ |
| 130 | public int AllowDrinking(int no) { return _NoDrinking = no; } |
| 131 | |
| 132 | /* returns the amount and name of the contents as an array 0-contents 1-name */ |
| 133 | public <int|string>* QueryContents() { return ({ _MaxCapacity-_Capacity, _Fname }); } |
| 134 | |
| 135 | /* returns 1 if this is an liquid container */ |
| 136 | public int QueryContainer() { return 1; } |
| 137 | |
| 138 | /*****************************************************************************/ |
| 139 | protected 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 | |
| 152 | void 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 | |
| 168 | int 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 | |
| 247 | int 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 | |
| 279 | int 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 | |
| 292 | int 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 | |
| 305 | int 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 | |