*water appearing/moving onto cells should turn empty flasks into potions if they have F_FILLPOT

This commit is contained in:
Rob Pearce 2016-06-06 12:15:42 +10:00
parent d381e8444c
commit bd0f37f461
5 changed files with 209 additions and 128 deletions

17
data.c
View File

@ -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);

5
defs.h
View File

@ -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.

310
objects.c
View File

@ -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)
}
}
}

View File

@ -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);

View File

@ -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);