From bd0f37f461d99964112b403434596fda8d972556 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Mon, 6 Jun 2016 12:15:42 +1000 Subject: [PATCH] *water appearing/moving onto cells should turn empty flasks into potions if they have F_FILLPOT --- data.c | 17 +-- defs.h | 5 +- objects.c | 310 +++++++++++++++++++++++++++++++++--------------------- objects.h | 3 + spell.c | 2 + 5 files changed, 209 insertions(+), 128 deletions(-) diff --git a/data.c b/data.c index 7e839c1..adb90f3 100644 --- a/data.c +++ b/data.c @@ -2259,7 +2259,7 @@ void initobjects(void) { addflag(lastot->flags, F_DTCREATEOB, DT_FIRE, 0, DT_COMPASS, "cloud of steam"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, B_DONTKILL, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL); - addflag(lastot->flags, F_FILLPOT, OT_POT_WATER, NA, NA, NULL); + addflag(lastot->flags, F_FILLPOT, OT_POT_WATER, NA, NA, NULL); // special case addflag(lastot->flags, F_GROWSTO, OT_WATERDEEP, VT_OB, NA, NULL); addflag(lastot->flags, F_SHRINKSTO, OT_PUDDLEWATERL, VT_OB, NA, NULL); @@ -2763,6 +2763,7 @@ void initobjects(void) { addflag(lastot->flags, F_ONEPERCELL, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_SHRINKSTO, NA, VT_OB, NA, "water fountain"); addflag(lastot->flags, F_IMPORTANT, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_FILLPOT, OT_POT_WATER, NA, NA, NULL); // traps - cell only addot(OT_TRAPARROW, "arrow trap", "A pressure plate which causes arrows to shoot at you.", MT_NOTHING, 0, OC_TRAP, SZ_SMALL); @@ -7221,7 +7222,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_ACID, FALLTHRU, "1d4"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_FILLPOT, OT_POT_ACID, NA, NA, NULL); + addflag(lastot->flags, F_FILLPOT, OT_POT_ACID, 1, NA, NULL); addflag(lastot->flags, F_PURIFIESTO, OT_PUDDLEWATER, NA, NA, NULL); addot(OT_ACIDSPLASH, "splash of acid", "A splash corrosive acid.", MT_ACID, 0, OC_MISC, SZ_SMALL); @@ -7236,7 +7237,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_ACID, FALLTHRU, "1d2"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_FILLPOT, OT_POT_ACID, NA, NA, NULL); + addflag(lastot->flags, F_FILLPOT, OT_POT_ACID, 5, NA, NULL); addflag(lastot->flags, F_PURIFIESTO, OT_SPLASHWATER, NA, NA, NULL); addot(OT_SLIMEPOOL, "pool of slime", "A deep pool of foul-smelling slime.", MT_SLIME, 300, OC_TERRAIN, SZ_HUGE); @@ -7265,7 +7266,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_FLAMMABLE, 5, NA, NA, "medium fire"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_FILLPOT, OT_POT_OIL, NA, NA, NULL); + addflag(lastot->flags, F_FILLPOT, OT_POT_OIL, 1, NA, NULL); addflag(lastot->flags, F_SLIPPERY, 110, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL); @@ -7333,7 +7334,7 @@ void initobjects(void) { addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_FILLPOT, OT_POT_WATER, NA, NA, NULL); + addflag(lastot->flags, F_FILLPOT, OT_POT_WATER, 2, NA, NULL); //addflag(lastot->flags, F_WALKDAM, DT_WATER, NA, NA, "0d1+1"); addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "0d1+1"); addflag(lastot->flags, F_SLIPPERY, 5, NA, NA, NULL); @@ -7357,7 +7358,7 @@ void initobjects(void) { addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_FILLPOT, OT_POT_WATER, NA, NA, NULL); + addflag(lastot->flags, F_FILLPOT, OT_POT_WATER, 1, NA, NULL); addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "0d1+2"); addflag(lastot->flags, F_DRYABLE, W_SOAKED, NA, NA, NULL); @@ -7393,7 +7394,7 @@ void initobjects(void) { addflag(lastot->flags, F_COSMETIC, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PURIFIESTO, OT_SPLASHWATER, NA, NA, NULL); - addflag(lastot->flags, F_FILLPOT, OT_POT_BLOOD, 5, NA, NULL); + addflag(lastot->flags, F_FILLPOT, OT_POT_BLOOD, BLOODFORPOT, NA, NULL); addflag(lastot->flags, F_DRYABLE, W_DAMP, NA, NA, NULL); addot(OT_BLOODPOOL, "pool of blood", "A large pool of blood.", MT_BLOOD, 0, OC_MISC, SZ_SMALL); @@ -7414,7 +7415,7 @@ void initobjects(void) { addflag(lastot->flags, F_LINKOB, OT_POT_BLOOD, NA, NA, NULL); addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PURIFIESTO, OT_PUDDLEWATERL, NA, NA, NULL); - addflag(lastot->flags, F_FILLPOT, OT_POT_BLOOD, NA, NA, NULL); + addflag(lastot->flags, F_FILLPOT, OT_POT_BLOOD, 1, NA, NULL); addflag(lastot->flags, F_DRYABLE, W_SOAKED, NA, NA, NULL); addot(OT_WOODPLANK, "plank of wood", "A large plank of heavy wood.", MT_WOOD, 25, OC_MISC, SZ_MEDIUM); diff --git a/defs.h b/defs.h index 2c748e7..169b1b2 100644 --- a/defs.h +++ b/defs.h @@ -2902,7 +2902,10 @@ enum FLAG { F_FILLPOT, // can fill empty flasks with this object to create // a potion of obtype v0. // v1 = how many objects need to exist before oyu - // can fill a flask from it. + // can fill a flask from it. this many will be + // removed by doing the fill. + // NA = the object is so large the effects of taking + // some to fill a flask are negligible. // v2 = need lore of this creature's race to // fill . F_GEM, // this object is a gem. diff --git a/objects.c b/objects.c index ec64123..8d73fe7 100644 --- a/objects.c +++ b/objects.c @@ -2445,6 +2445,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum } } + if (o->pile->where) { vault_t *v; v = getcellvault(o->pile->where); @@ -2456,21 +2457,10 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum } } */ - // blood will stain things on the ground - if (o->material->id == MT_BLOOD) { - object_t *poss[MAXPILEOBS],*oo; - int nposs = 0; - // bloodstain one piece of armour - for (oo = o->pile->first ; oo ; oo = oo->next) { - if ((oo != o) && isarmour(oo)) { - poss[nposs++] = oo; - } - } - if (nposs) { - oo = poss[rnd(0,nposs-1)]; - applyobmod(oo, findobmod(OM_BLOODSTAINED)); - } - } + + // affect other objects here. + o = obaffectsothers(o); + } // wantflags @@ -5124,6 +5114,86 @@ object_t *getrandomammo(lifeform_t *lf) { return findammoinobpile(gun, lf->pack); } +object_t *fillpotfrom(object_t *flask, object_t *fillfrom, int reduceliquid) { + char liquidname[BUFLEN]; + int autoid = B_FALSE; + object_t *newob = NULL; + char newobname[BUFLEN]; + flag_t *bfob,*fillflag; + + fillflag = hasflag(fillfrom->flags, F_FILLPOT); + if (!fillflag) return NULL; + + getobname(fillfrom, liquidname, 1); + + // get a random fillpot flag. + bfob = getrandomflag(fillfrom->flags, F_FILLPOT); + if (bfob) { + objecttype_t *ot; + ot = findot(bfob->val[0]); + if (ot) { + strcpy(newobname, ot->name); + } else { + strcpy(newobname, "potion of blood"); + } + } else if (fillfrom->type->id == OT_FOUNTAIN) { + objecttype_t *ot; + flag_t *f; + // same type as fountain + f = hasflag(fillfrom->flags, F_LINKOB); + ot = findot(f->val[0]); + strcpy(newobname, ot->name); + // if you knew what the fountain was, you'll + // know what the potion object is. + if (f->val[2] == B_TRUE) autoid = B_TRUE; + } else { + switch (fillfrom->material->id) { + case MT_BLOOD: + strcpy(newobname, "potion of blood"); + break; + case MT_WATER: + strcpy(newobname, "potion of water"); + break; + default: + strcpy(newobname, ""); + break; + } + } + if (strlen(newobname)) { + obpile_t *op; + op = flask->pile; + + // kill the empty flask + removeob(flask, 1); + // give the new potion + newob = addob(op, newobname); + if (newob) { + if (autoid) makeknown(newob->type->id); + // overwrite newobname + getobname(newob, newobname, newob->amt); + if (op->owner == player) { + msgnocap("%c - %s.",newob->letter, newobname); + } + } + if (reduceliquid) { + if (fillfrom->type->id == OT_FOUNTAIN) { + if (fountain_will_dryup(fillfrom)) { + removeob(fillfrom, fillfrom->amt); + } + } else { + if (fillflag->val[1] == NA) { + // no effect on original ob + } else { + removeob(fillfrom, fillflag->val[1]); + } + } + } + } else { + return NULL; + } + return newob; +} + object_t *findammoinobpile(object_t *gun, obpile_t *op) { flag_t *retflag[MAXCANDIDATES]; int nretflags = 0, i; @@ -8119,6 +8189,13 @@ int isequippedon(object_t *o, enum BODYPART bp) { return B_FALSE; } +int isfillable(object_t *o) { + if ((o->type->id == OT_EMPTYFLASK) || (o->type->id == OT_EMPTYVIAL)) { + return B_TRUE; + } + return B_FALSE; +} + int isfirearm(object_t *o) { if (!o) return B_FALSE; if (hasflag(o->flags, F_FIREARM)) { @@ -9424,7 +9501,6 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) { int redrawaftermove = B_FALSE; int pleasethiefgod = 0; lifeform_t *robbedlf = NULL; - flag_t *f; reason = E_OK; @@ -9667,51 +9743,11 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) { statdirty = B_TRUE; } } else if (dst->where) { - object_t *oo,*nextoo; // object hit the ground? - // triggered a trap? - for (oo = dst->where->obpile->first ; oo ; oo = nextoo ) { - nextoo = oo->next; - if (oo != o) { - f = hasflag(oo->flags, F_TRAP); - if (f && (f->val[1] != curtime)) { - triggertrap(NULL, o, oo, dst->where); - } - // bless objects which land on a holy circle. - if ((oo->type->id == OT_HOLYCIRCLE) && !blessob(o)) { - // holy circle vanishes. - if (onein(3)) { - if (haslos(player, dst->where)) { - char ooname[BUFLEN]; - getobname(oo, ooname, 1); - msg("%s fades and vanishes.", ooname); - } - removeob(oo, oo->amt); - } - } - // curse objects which land on a pentagram. - if ((oo->type->id == OT_PENTAGRAM) && !curseob(o)) { - // pentagrams don't vanish as often as holy circles - if (onein(6)) { - if (haslos(player, dst->where)) { - char ooname[BUFLEN]; - getobname(oo, ooname, 1); - msg("%s fades and vanishes.", ooname); - } - removeob(oo, oo->amt); - } - } - - if ((oo->type->id == OT_WATERDEEP) && (getmaterialstate(o->material->id) == MS_SOLID)) { - noise(dst->where, NULL, NC_OTHER, SV_TALK, "a splash.", "Splash!"); - } - } - } + o = obaffectsothers(o); } - //o = newobeffects(o); - return o; } @@ -9752,6 +9788,99 @@ void obaction(object_t *o, char *text) { } } +// affect other objects on the ground +// +// returns the source objects, or NULL if it was destroyed + +// TODO: optimise to not go through every object heaps of times. +object_t *obaffectsothers(object_t *o) { + object_t *poss[MAXPILEOBS],*oo,*nextoo; + cell_t *loc; + int nposs = 0; + loc = o->pile->where; + if (!loc) return o; + + // blood will stain things on the ground + if (o->material->id == MT_BLOOD) { + nposs = 0; + // bloodstain one piece of armour + for (oo = o->pile->first ; oo ; oo = oo->next) { + if ((oo != o) && isarmour(oo)) { + poss[nposs++] = oo; + } + } + if (nposs) { + oo = poss[rnd(0,nposs-1)]; + applyobmod(oo, findobmod(OM_BLOODSTAINED)); + } + } + + // liquids will fill flasks on the ground + if (hasflag(o->flags, F_FILLPOT)) { + nposs = 0; + for (oo = o->pile->first ; oo ; oo = oo->next) { + if ((oo != o) && isfillable(oo)) { + poss[nposs++] = oo; + } + } + if (nposs) { + oo = poss[rnd(0,nposs-1)]; + fillpotfrom(oo, o, B_FALSE); + } + } + + for (oo = loc->obpile->first ; o && oo ; oo = nextoo ) { + nextoo = oo->next; + if (oo != o) { + flag_t *f; + + if ((oo->type->id == OT_WATERDEEP) && (getmaterialstate(o->material->id) == MS_SOLID)) { + noise(loc, NULL, NC_OTHER, SV_TALK, "a splash.", "Splash!"); + } + + // triggered a trap? + f = hasflag(oo->flags, F_TRAP); + if (f && (f->val[1] != curtime)) { + long origid; + // an explosion trap or similar might kill the source object. + origid = o->id; + triggertrap(NULL, o, oo, loc); + o = hasobid(loc->obpile, origid); + if (!o) return NULL; + } + + // bless objects which land on a holy circle. + if ((oo->type->id == OT_HOLYCIRCLE) && !blessob(o)) { + // holy circle vanishes. + if (onein(3)) { + if (haslos(player, loc)) { + char ooname[BUFLEN]; + getobname(oo, ooname, 1); + msg("%s fades and vanishes.", ooname); + } + removeob(oo, oo->amt); + } + } + // curse objects which land on a pentagram. + if ((oo->type->id == OT_PENTAGRAM) && !curseob(o)) { + // pentagrams don't vanish as often as holy circles + if (onein(6)) { + if (haslos(player, loc)) { + char ooname[BUFLEN]; + getobname(oo, ooname, 1); + msg("%s fades and vanishes.", ooname); + } + removeob(oo, oo->amt); + } + } + + } + } + + return o; +} + + object_t *obexists(enum OBTYPE obid) { map_t *m; int x,y; @@ -11688,7 +11817,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { if (!seen) { noise(where, NULL, NC_OTHER, SV_WHISPER, "something spraying.", NULL); } - } else if ((o->type->id == OT_EMPTYFLASK) || (o->type->id == OT_EMPTYVIAL)) { + } else if (isfillable(o)) { object_t *oo,*nextoo; object_t *notenough = NULL; if (isplayer(lf)) { @@ -11731,73 +11860,16 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { char ch; char ques[BUFLEN]; char liquidname[BUFLEN]; - int autoid = B_FALSE; - object_t *newob; getobname(oo, liquidname, 1); snprintf(ques, BUFLEN, "Fill your %s from %s?", noprefix(obname), liquidname); ch = askchar(ques, "yn", "y", B_TRUE, B_FALSE); if (ch == 'y') { - char newobname[BUFLEN]; - flag_t *bfob; - // get a random fillpot flag. - bfob = getrandomflag(oo->flags, F_FILLPOT); - if (bfob) { - objecttype_t *ot; - ot = findot(bfob->val[0]); - if (ot) { - strcpy(newobname, ot->name); - } else { - strcpy(newobname, "potion of blood"); - } - } else if (oo->type->id == OT_FOUNTAIN) { - objecttype_t *ot; - // same type as fountain - f = hasflag(oo->flags, F_LINKOB); - ot = findot(f->val[0]); - strcpy(newobname, ot->name); - // if you knew what the fountain was, you'll - // know what the potion object is. - if (f->val[2] == B_TRUE) autoid = B_TRUE; - } else { - switch (oo->material->id) { - case MT_BLOOD: - strcpy(newobname, "potion of blood"); - break; - case MT_WATER: - strcpy(newobname, "potion of water"); - break; - default: - strcpy(newobname, ""); - break; - } - } - if (strlen(newobname)) { - // kill the empty flask - removeob(o, 1); - // give the new potion - newob = addob(lf->pack, newobname); - if (newob) { - if (autoid) makeknown(newob->type->id); - // overwrite newobname - getobname(newob, newobname, newob->amt); - msgnocap("%c - %s.",newob->letter, newobname); - } - if (oo->type->id == OT_FOUNTAIN) { - if (fountain_will_dryup(oo)) { - removeob(oo, oo->amt); - } - } else { - if (fillflag->val[1] != NA) { - removeob(oo, fillflag->val[1]); - } else { - removeob(oo, 1); - } - } - } else { + if (fillpotfrom(o, oo, B_TRUE)) { msg("That doesn't seem like a very good idea."); + } else { + donedip = B_TRUE; } - donedip = B_TRUE; - } // if (ch == y) + } } } diff --git a/objects.h b/objects.h index eb26986..0960344 100644 --- a/objects.h +++ b/objects.h @@ -62,6 +62,7 @@ void dumpobs(int ntogen); void dumpobrarity(void); void explodeob(object_t *o, flag_t *f, int bigness, lifeform_t *causedby); void extinguish(object_t *o); +object_t *fillpotfrom(object_t *flask, object_t *fillfrom, int reduceliquid); object_t *findammoinobpile(object_t *gun, obpile_t *op); material_t *findmaterial(int id); objectclass_t *findoc(int id); @@ -209,6 +210,7 @@ int isdrinkable(object_t *o); int isedible(object_t *o); flag_t *isequipped(object_t *o); int isequippedon(object_t *o, enum BODYPART bp); +int isfillable(object_t *o); int isfirearm(object_t *o); int isflammable(object_t *o); int isfullycharged(object_t *o); @@ -277,6 +279,7 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok); void modbonus(object_t *o, int amt); //object_t *newobeffects(object_t *o); void obaction(object_t *o, char *text); +object_t *obaffectsothers(object_t *o); object_t *obexists(enum OBTYPE obid); void obdie(object_t *o); int obfits(object_t *o, obpile_t *op); diff --git a/spell.c b/spell.c index 8d591f4..3160529 100644 --- a/spell.c +++ b/spell.c @@ -14440,6 +14440,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ msg("%s appear%s on the ground!", obname, OBS1(o)); } ncreated++; + // + o = obaffectsothers(o); } else { // ob exists but couldn't make it appear msg("The air in front of %s seems to ripple for a moment.", lfname);